blowater/app/UI/nav.tsx

565 lines
25 KiB
TypeScript
Raw Normal View History

2023-06-30 14:05:57 +00:00
/** @jsx h */
2024-07-15 14:36:36 +00:00
import { Component, h } from "preact";
import { emitFunc, EventSubscriber } from "../event-bus.ts";
2024-06-21 17:05:39 +00:00
import { ViewSpaceSettings } from "./setting.tsx";
2024-07-15 14:36:36 +00:00
import { getRelayInformation, PublicKey, RelayInformation, robohash } from "@blowater/nostr-sdk";
2024-07-17 10:16:21 +00:00
import { setState, url_identity } from "./_helper.ts";
2024-07-15 14:36:36 +00:00
import { Avatar, RelayAvatar } from "./components/avatar.tsx";
import { CaretDownIcon } from "./icons/caret-down-icon.tsx";
import { PoundIcon } from "./icons/pound-icon.tsx";
import { Profile_Nostr_Event } from "../nostr.ts";
import { ContactUpdate } from "./conversation-list.tsx";
import { TagSelected } from "./contact-tags.tsx";
import { ViewUserDetail } from "./message-panel.tsx";
import { func_GetProfileByPublicKey } from "./search.tsx";
import { PinIcon } from "./icons/pin-icon.tsx";
import { SelectConversation } from "./search_model.ts";
import { ConversationSummary, sortUserInfo } from "./conversation-list.ts";
import { UI_Interaction_Event } from "./app_update.tsx";
2024-07-17 10:16:21 +00:00
import { ValueMap, ValueSet } from "@blowater/collections";
2023-11-27 13:35:01 +00:00
export type InstallPrompt = {
event: Event | undefined;
};
2023-06-30 14:05:57 +00:00
export type ShowProfileSetting = {
type: "ShowProfileSetting";
};
2023-11-02 13:10:16 +00:00
export type NavigationUpdate = {
type: "ChangeNavigation";
id: NavTabID;
};
2023-06-30 14:05:57 +00:00
2024-06-21 17:05:39 +00:00
export type SelectSpace = {
type: "SelectSpace";
2024-07-15 14:36:36 +00:00
spaceURL: URL;
};
2023-06-30 14:05:57 +00:00
export type NavigationModel = {
2023-11-02 13:10:16 +00:00
activeNav: NavTabID;
2023-06-30 14:05:57 +00:00
};
2024-07-15 14:36:36 +00:00
export type NavTabID = "Public" | "DM" | "Search" | "Profile" | "About" | "Setting";
type NewNavProps = {
activeNav: NavTabID;
2024-07-15 14:36:36 +00:00
currentSpaceURL: URL;
2024-07-17 10:16:21 +00:00
spaceList: ValueSet<URL>;
2024-07-15 14:36:36 +00:00
profile: Profile_Nostr_Event | undefined;
currentConversation: PublicKey | undefined;
getters: {
getProfileByPublicKey: func_GetProfileByPublicKey;
getConversationList: func_GetConversationList;
getPinList: func_GetPinList;
};
emit: emitFunc<
| SelectSpace
| NavigationUpdate
| ViewSpaceSettings
| ShowProfileSetting
| ContactUpdate
| TagSelected
| ViewUserDetail
>;
update: EventSubscriber<UI_Interaction_Event>;
2023-06-30 14:05:57 +00:00
};
2024-07-15 14:36:36 +00:00
type NewNavState = {
spaceInformation: RelayInformation & { url: URL };
2024-07-17 10:16:21 +00:00
spaceInformationList: ValueMap<URL, RelayInformation & { url: URL }>;
2023-06-30 14:05:57 +00:00
};
2024-07-15 14:36:36 +00:00
export class NewNav extends Component<NewNavProps, NewNavState> {
state: Readonly<NewNavState> = {
spaceInformation: { url: this.props.currentSpaceURL },
2024-07-17 10:16:21 +00:00
spaceInformationList: new ValueMap(url_identity),
2024-07-15 14:36:36 +00:00
};
async componentDidMount() {
console.log("componentDidMount");
for await (const state of updateInformation(this.props.currentSpaceURL, this.props.spaceList)) {
await setState(this, state);
}
for await (const change of this.props.update.onChange()) {
if (change.type == "SelectSpace") {
2024-07-17 10:16:21 +00:00
const info = this.state.spaceInformationList.get(change.spaceURL);
2024-07-15 14:36:36 +00:00
await setState(this, {
spaceInformation: info,
});
} else if (change.type == "RelayConfigChange") {
console.log("add", change);
if (change.kind == "remove") {
2024-07-17 10:16:21 +00:00
this.state.spaceInformationList.delete(new URL(change.url));
2024-07-15 14:36:36 +00:00
await setState(this, {
spaceInformationList: this.state.spaceInformationList,
});
} else if (change.kind == "add") {
const info = await getRelayInformation(change.url);
if (info instanceof Error) {
console.error(info);
continue;
}
2024-07-17 10:16:21 +00:00
this.state.spaceInformationList.set(change.url, {
2024-07-15 14:36:36 +00:00
...info,
url: new URL(change.url),
});
await setState(this, {
spaceInformationList: this.state.spaceInformationList,
});
console.log("add", this.state.spaceInformationList);
}
}
}
}
render(props: NewNavProps) {
return (
<div
class={`h-screen w-64 flex flex-col gap-y-4 overflow-y-auto bg-neutral-900 p-2 items-center select-none
${props.currentConversation ? "max-sm:hidden" : ""}
`}
>
<SpaceDropDownPanel
currentSpace={this.state.spaceInformation}
spaceList={this.state.spaceInformationList}
emit={props.emit}
/>
{/* <GlobalSearch /> */}
<GroupChatList emit={props.emit} activeNav={props.activeNav} />
<ConversationList
emit={props.emit}
currentSpace={this.props.currentSpaceURL}
currentConversation={props.currentConversation}
getters={props.getters}
/>
<UserIndicator profile={props.profile} emit={props.emit} />
</div>
);
}
}
type SpaceDropDownPanelProps = {
currentSpace: RelayInformation & { url: URL };
2024-07-17 10:16:21 +00:00
spaceList: ValueMap<URL, RelayInformation & { url: URL }>;
2024-07-15 14:36:36 +00:00
emit: emitFunc<SelectSpace | NavigationUpdate | ViewSpaceSettings>;
2023-11-02 13:10:16 +00:00
};
2024-07-15 14:36:36 +00:00
type SpaceDropDownState = {
showDropDown: boolean;
searchSpaceValue: string;
};
2023-11-02 13:10:16 +00:00
2024-07-15 14:36:36 +00:00
class SpaceDropDownPanel extends Component<SpaceDropDownPanelProps, SpaceDropDownState> {
state: Readonly<SpaceDropDownState> = {
showDropDown: false,
searchSpaceValue: "",
2023-11-27 13:35:01 +00:00
};
2024-07-15 14:36:36 +00:00
handleSearchRelayInput = async (e: Event) => {
await setState(this, {
searchSpaceValue: (e.target as HTMLInputElement).value,
});
};
2023-11-02 13:10:16 +00:00
2024-07-15 14:36:36 +00:00
render() {
const spaceList = [];
for (const space of this.props.spaceList.values()) {
if (!space.url.toString().includes(this.state.searchSpaceValue)) {
continue;
}
spaceList.push(
this.SpaceListItem(space, this.props.currentSpace.toString() == space.url.toString()),
);
2023-11-02 13:10:16 +00:00
}
2024-07-15 14:36:36 +00:00
return (
<div class="w-full">
{this.CurrentSpaceIndicator()}
{this.state.showDropDown ? this.DropDown(spaceList) : undefined}
</div>
);
}
CurrentSpaceIndicator = () => {
const currentSpaceInformation = this.props.currentSpace;
const icon = currentSpaceInformation.icon || robohash(this.props.currentSpace.url);
const name = currentSpaceInformation.name || this.props.currentSpace.url.hostname;
return (
<div
class="flex flex-row items-center gap-1 p-1 rounded cursor-pointer hover:bg-neutral-500"
onClick={this.toggleRelayList}
>
<div class="w-10 h-10 rounded-md bg-neutral-700">
<RelayAvatar icon={icon} />
</div>
<div class="flex-1 text-sm font-medium font-sans leading-5 text-neutral-100 truncate">
{name}
</div>
<div class="w-8 h-8 flex justify-center items-center rounded">
{this.state.showDropDown
? <CaretDownIcon class="w-6 h-6 text-neutral-600 transition-transform -rotate-180" />
: <CaretDownIcon class="w-6 h-6 text-neutral-600 transition-transform" />}
</div>
</div>
);
};
DropDown = (spaceList: h.JSX.Element[]) => {
return (
<div class="absolute z-10 min-w-64 rounded-lg bg-neutral-700 text-white p-4 mt-1">
{this.SettingsButton()}
{/* {this.InviteButton()} */}
<div class="border border-neutral-600 my-3"></div>
<div class="w-full flex mb-3">
<input
type="text"
class="flex-grow rounded-lg px-2 py-1 text-white bg-neutral-600 focus:outline-none focus:border-white"
placeholder="filter spaces"
value={this.state.searchSpaceValue}
onInput={this.handleSearchRelayInput}
/>
</div>
<div
class="flex flex-col overflow-y-auto overflow-x-hidden"
style={{ maxHeight: "70vh" }}
>
{spaceList}
</div>
{this.NewSpaceButton()}
</div>
);
};
SpaceListItem(spaceInfo: RelayInformation & { url: URL }, isCurrentRelay: boolean) {
const selected = isCurrentRelay ? " border-[#000] border" : "";
return (
<div
class={"flex flex-row mb-2 hover:bg-neutral-500" +
" hover:cursor-pointer items-center rounded"}
onClick={this.onSpaceSelected(spaceInfo.url)}
>
<div class={`flex justify-center items-center w-12 h-12 rounded-md ${selected}`}>
<div class={`w-10 h-10 bg-neutral-600 rounded-md `}>
<RelayAvatar
icon={spaceInfo.icon ||
robohash(spaceInfo.url)}
/>
</div>
</div>
<div class="px-2">
<div>{spaceInfo.name}</div>
<div class="text-sm font-light">{spaceInfo.url.hostname}</div>
</div>
</div>
);
}
SettingsButton = () => (
<div
class={"flex flex-row items-center p-2 rounded-lg" +
" hover:bg-neutral-500 hover:cursor-pointer"}
onClick={() => {
this.props.emit({
type: "ViewSpaceSettings",
url: this.props.currentSpace.url,
});
setState(this, {
showDropDown: false,
});
}}
>
<svg
class="w-6 h-6 mr-2"
width="14"
height="14"
viewBox="0 0 14 14"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M7.00003 4.00003C6.40668 4.00003 5.82667 4.17598 5.33332 4.50562C4.83997 4.83526 4.45545 5.3038 4.22839 5.85198C4.00133 6.40016 3.94192 7.00336 4.05767 7.5853C4.17343 8.16724 4.45915 8.70179 4.87871 9.12135C5.29827 9.54091 5.83281 9.82663 6.41476 9.94238C6.9967 10.0581 7.5999 9.99873 8.14808 9.77167C8.69626 9.5446 9.16479 9.16009 9.49444 8.66674C9.82408 8.17339 10 7.59337 10 7.00003C9.9992 6.20463 9.68287 5.44205 9.12044 4.87962C8.55801 4.31719 7.79542 4.00086 7.00003 4.00003ZM7.00003 9.00003C6.60447 9.00003 6.21779 8.88273 5.88889 8.66297C5.55999 8.4432 5.30364 8.13085 5.15227 7.7654C5.00089 7.39994 4.96129 6.99781 5.03846 6.60985C5.11563 6.22189 5.30611 5.86552 5.58581 5.58581C5.86552 5.30611 6.22189 5.11563 6.60985 5.03846C6.99781 4.96129 7.39994 5.00089 7.7654 5.15227C8.13085 5.30364 8.4432 5.55999 8.66297 5.88889C8.88273 6.21779 9.00003 6.60447 9.00003 7.00003C9.00003 7.53046 8.78931 8.03917 8.41424 8.41424C8.03917 8.78931 7.53046 9.00003 7.00003 9.00003ZM12.5 7.13503C12.5025 7.04503 12.5025 6.95503 12.5 6.86503L13.4325 5.70003C13.4814 5.63886 13.5153 5.56706 13.5313 5.49042C13.5474 5.41378 13.5452 5.33443 13.525 5.25878C13.3722 4.68415 13.1435 4.13243 12.845 3.61815C12.806 3.55085 12.7517 3.4936 12.6866 3.45096C12.6215 3.40832 12.5473 3.38146 12.47 3.37253L10.9875 3.20753C10.9259 3.14253 10.8634 3.08003 10.8 3.02003L10.625 1.53378C10.616 1.45641 10.5891 1.38222 10.5463 1.31711C10.5036 1.252 10.4462 1.19779 10.3788 1.15878C9.8643 0.86087 9.31263 0.632425 8.73815 0.479404C8.66245 0.459277 8.58308 0.457218 8.50643 0.473394C8.42979 0.489569 8.35802 0.523527 8.2969 0.572529L7.13503 1.50003C7.04503 1.50003 6.95503 1.50003 6.86503 1.50003L5.70003 0.569404C5.63886 0.520509 5.56706 0.486665 5.49042 0.470598C5.41378 0.454531 5.33443 0.456691 5.25878 0.476903C4.68425 0.630045 4.13256 0.858705 3.61815 1.1569C3.55085 1.19598 3.4936 1.25023 3.45096 1.31533C3.40832 1.38044 3.38146 1.45459 3.37253 1.5319L3.20753 3.0169C3.14253 3.07899 3.08003 3.14149 3.02003 3.2044L1.53378 3.37503C1.45641 3.38403 1.38222 3.41098 1.31711 3.45373C1.252 3.49649 1.19779 3.55386 1.15878 3.62128C0.86087 4.13576 0.632425 4.68743 0.479404 5.2619C0.459277 5.33761 0.457218 5.41698 0.473394 5.49362C0.489569 5.57027 0.523527 5.64204 0.572529 5.70315L1.50003 6.86503C1.50003 6.95503 1.50003 7.04503 1.50003 7.13503L0.569404 8.30003C0.520509 8.3612 0.486665 8.43299 0.470598 8.50964C0.454531 8.58628 0.456691 8.66562 0.476903 8.74128C0.629772 9.3159 0.858447 9.86762 1.1569 10.3819C1.19598 10.4492 1.25023 10.5065 1.31533 10.5491C1.38044 10.5917 1.45459 10.6186 1.5319 10.6275L3.0144 10.7925C3.07649 10.8575 3.13899 10.92 3.2019 10.98L3.37503 12.4663C3.38403 12.5436 3.41098 12.6178 3.45373 12.6829C3.49649 12.7481 3.55386 12.8023 3.62128 12.8413C4.13576 13.1392 4.68743 13.3676 5.2619 13.5207C5.33761 13.5408 5.41698 13.5428 5.49362 13.5267C5.57027 13.5105 5.64204 13.4765 5.70315 13.4275L6.86503 12.5C6.95503 12.5025 7.04503 12.5025 7.13503 12.5L8.30003 13.4325C8.3612 13.4814 8.43299 13.5153 8.50964 13.5313C8.58628 13.5474 8.66562 13.5452 8.74128 13.525C9.3159 13.3722 9.86762 13.1435 10.3819 12.845C10.4492 12.806 10.5065 12.7517 10.5491 12.6866C10.5917 12.6215 10.6186 12.5473 10.6275 12.47L10.7925 10.9875C10.8575 10.9259 10.92 10.8634 10.98 10.8L12.4663 10.625C12.5436 10.616 12.6178 10.5891 12.6829 10.5463C12.7481 10.5036 12.8023 10.4462 12.8413 10.3788C13.1392 9.8643 13.3676 9.31263 13.5207 8.73815C13.5408 8.66245 13.5428 8.58308 13.5267 8.50643C13.5105 8.42979 13.4765 8.35802 13.4275 8.2969L12.5 7.13503ZM11.4938 6.72878C11.5044 6.90946 11.5044 7.0906 11.4938 7.27128C11.4863 7.39498 11.5251 7.51703 11.6025 7.61378L12.4894 8.7219C12.3876 9.04532 12.2573 9.35905 12.1 9.6594L10.6875 9.8194C10.5645 9.83306 10.4509 9.89185 10.3688 9.9844C10.2485 10.1197 10.1203 10.2478 9.98503 10.3682C9.89247 10.4503 9.83368 10.5639 9.82003 10.6869L9.66315 12.0982C9.36284 12.2555 9.0491 12.3858 8.72565 12.4875L7.6169 11.6007C7.52818 11.5298 7.41797 11.4912 7.3044 11.4913H7.2744C7.09373 11.5019 6.91258 11.5019 6.7319 11.4913C6.60821 11.4838 6.48615 11.5226 6.3894 11.6L5.
fill="#D4D4D4"
/>
</svg>
<p>Settings</p>
</div>
);
InviteButton = () => (
<div
class={"flex flex-row items-center p-2 rounded-lg" +
" hover:bg-neutral-500 hover:cursor-pointer"}
>
<svg
class="w-6 h-6 mr-2"
width="15"
height="15"
viewBox="0 0 15 15"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.2075 0.792544C14.0818 0.666877 13.9248 0.577003 13.7528 0.532182C13.5807 0.487361 13.3998 0.489212 13.2288 0.537544H13.2194L1.22313 4.17754C1.02838 4.23367 0.855281 4.34765 0.726772 4.50438C0.598262 4.66111 0.520411 4.85319 0.503534 5.05517C0.486658 5.25714 0.531553 5.45948 0.63227 5.63536C0.732988 5.81125 0.884772 5.95237 1.06751 6.04004L6.37501 8.62504L8.95626 13.9294C9.03654 14.1007 9.16419 14.2455 9.32411 14.3466C9.48403 14.4477 9.66955 14.501 9.85876 14.5C9.88751 14.5 9.91626 14.4988 9.94501 14.4963C10.1468 14.48 10.3388 14.4023 10.4952 14.2737C10.6516 14.1451 10.765 13.9718 10.82 13.7769L14.4575 1.78067C14.4575 1.77754 14.4575 1.77442 14.4575 1.77129C14.5065 1.60065 14.5091 1.42004 14.4652 1.24803C14.4212 1.07602 14.3323 0.918809 14.2075 0.792544ZM9.86438 13.4907L9.86126 13.4994V13.495L7.35751 8.35129L10.3575 5.35129C10.4473 5.25676 10.4966 5.13089 10.495 5.00051C10.4933 4.87013 10.4408 4.74556 10.3486 4.65335C10.2564 4.56115 10.1318 4.50862 10.0014 4.50695C9.87104 4.50528 9.74517 4.55461 9.65063 4.64442L6.65064 7.64442L1.50501 5.14067H1.50063H1.50938L13.5 1.50004L9.86438 13.4907Z"
fill="#D4D4D4"
/>
</svg>
<p>Invite</p>
</div>
);
NewSpaceButton = () => {
return (
<div
class={"flex flex-row my-1 py-1" +
" bg-neutral-600" +
" hover:bg-neutral-500" +
" hover:cursor-pointer items-center rounded-lg justify-center" +
" text-white font-semibold"}
onClick={this.onAddRelay}
>
New Space
</div>
);
};
toggleRelayList = async () => {
await setState(this, {
showDropDown: !this.state.showDropDown,
});
};
onSpaceSelected = (spaceURL: URL) => async () => {
await setState(this, {
showDropDown: false,
});
this.props.emit({
type: "SelectSpace",
spaceURL,
});
};
onAddRelay = async () => {
await setState(this, {
showDropDown: false,
});
2023-11-02 13:10:16 +00:00
this.props.emit({
type: "ChangeNavigation",
2024-07-15 14:36:36 +00:00
id: "Setting",
2023-11-02 13:10:16 +00:00
});
};
2024-07-15 14:36:36 +00:00
}
2023-06-30 14:05:57 +00:00
2024-07-15 14:36:36 +00:00
function GlobalSearch() {
return <div>Search</div>;
}
2023-11-27 13:35:01 +00:00
2024-07-15 14:36:36 +00:00
type GroupChatListProps = {
activeNav: NavTabID;
emit: emitFunc<NavigationUpdate>;
};
class GroupChatList extends Component<GroupChatListProps> {
render(props: GroupChatListProps) {
return (
<div
class={`flex items-center justify-start gap-1 w-full p-2 rounded-md px-2 py-1 hover:bg-neutral-950 cursor-pointer ${
props.activeNav == "Public" ? "bg-neutral-800" : ""
}`}
onClick={() => {
props.emit({
type: "ChangeNavigation",
id: "Public",
});
}}
>
<PoundIcon class="w-4 h-4 text-neutral-500" />
<div class="text-white text-sm font-medium font-sans leading-5">Public</div>
</div>
);
}
}
export type func_GetConversationList = (space?: URL) => Array<ConversationSummary>;
type func_GetPinList = () => Set<string>;
type ConversationListProps = {
emit: emitFunc<ContactUpdate>;
currentSpace: URL;
currentConversation: PublicKey | undefined;
getters: {
getProfileByPublicKey: func_GetProfileByPublicKey;
getConversationList: func_GetConversationList;
getPinList: func_GetPinList;
};
};
class ConversationList extends Component<ConversationListProps> {
render(props: ConversationListProps) {
const pinList = props.getters.getPinList();
const pinned = [];
const unpinned = [];
const currentSpaceConversationList = props.getters.getConversationList(props.currentSpace);
const sortedConversationList = currentSpaceConversationList.sort((a, b) => {
return sortUserInfo(a, b);
});
for (const convo of sortedConversationList) {
if (pinList.has(convo.pubkey.hex)) {
pinned.push(
<ConversationItem
emit={props.emit}
pubkey={convo.pubkey}
isPined={true}
currentConversation={props.currentConversation}
2024-07-17 10:16:21 +00:00
currentSpace={props.currentSpace}
2024-07-15 14:36:36 +00:00
getters={props.getters}
/>,
);
} else {
unpinned.push(
<ConversationItem
emit={props.emit}
pubkey={convo.pubkey}
isPined={false}
currentConversation={props.currentConversation}
2024-07-17 10:16:21 +00:00
currentSpace={props.currentSpace}
2024-07-15 14:36:36 +00:00
getters={props.getters}
/>,
);
}
2023-11-27 13:35:01 +00:00
}
2024-07-15 14:36:36 +00:00
return (
<div class="flex-1 w-full overflow-y-auto">
<div class="flex flex-col gap-1 w-full justify-start items-center">
{pinned}
{unpinned}
</div>
</div>
);
}
}
type ConversationItemProps = {
pubkey: PublicKey;
emit: emitFunc<SelectConversation>;
isPined: boolean;
2024-07-17 10:16:21 +00:00
currentSpace: URL;
2024-07-15 14:36:36 +00:00
currentConversation: PublicKey | undefined;
getters: {
getProfileByPublicKey: func_GetProfileByPublicKey;
2023-11-27 13:35:01 +00:00
};
2024-07-15 14:36:36 +00:00
};
2023-11-27 13:35:01 +00:00
2024-07-15 14:36:36 +00:00
class ConversationItem extends Component<ConversationItemProps> {
render(props: ConversationItemProps) {
const profile = props.getters.getProfileByPublicKey(props.pubkey, undefined)
?.profile;
const picture = profile?.picture || robohash(props.pubkey.hex);
const name = profile?.name || profile?.display_name || props.pubkey.bech32();
2023-11-02 13:10:16 +00:00
return (
2024-07-15 14:36:36 +00:00
<div
class={`flex gap-2 rounded-md px-2 py-1 w-full hover:bg-neutral-950 cursor-pointer ${
props.pubkey.hex == props.currentConversation?.hex ? "bg-neutral-800" : ""
}`}
onClick={() => {
props.emit({
type: "SelectConversation",
pubkey: props.pubkey,
});
}}
>
<div class="w-4 flex justify-center items-center">
<Avatar picture={picture} />
</div>
<div class="text-white text-sm font-medium font-sans leading-5 flex-1 truncate">
{name}
</div>
{props.isPined
? (
<div class="flex justify-center items-center">
<PinIcon
class={`w-3 h-3`}
style={{
fill: "rgb(185, 187, 190)",
stroke: "rgb(185, 187, 190)",
strokeWidth: 2,
}}
/>
</div>
)
: undefined}
</div>
);
}
}
type UserIndicatorProps = {
profile: Profile_Nostr_Event | undefined;
emit: emitFunc<ShowProfileSetting>;
};
class UserIndicator extends Component<UserIndicatorProps> {
render(props: UserIndicatorProps) {
return (
<div class="w-full">
<div
class="hover:bg-neutral-800 rounded-md py-1 px-2 flex items-center justify-start gap-2 cursor-pointer"
onClick={() => {
props.emit({
type: "ShowProfileSetting",
});
}}
>
<Avatar
class={`w-8 h-8`}
picture={props.profile?.profile.picture || "./logo.webp"}
2024-05-14 09:52:02 +00:00
/>
2024-07-15 14:36:36 +00:00
<div class="text-neutral-100 flex-1 text-sm font-medium leading-5 truncate">
{props.profile?.profile.name || props.profile?.profile.display_name ||
props.profile?.pubkey}
2023-11-02 13:10:16 +00:00
</div>
2024-07-15 14:36:36 +00:00
</div>
</div>
2023-11-02 13:10:16 +00:00
);
}
2023-06-30 14:05:57 +00:00
}
2024-07-15 14:36:36 +00:00
2024-07-17 10:16:21 +00:00
async function* updateInformation(currentSpaceURL: URL, spaceList: ValueSet<URL>) {
2024-07-15 14:36:36 +00:00
const currentInfo = await getRelayInformation(currentSpaceURL);
if (currentInfo instanceof Error) {
console.error(currentInfo);
return;
}
yield {
spaceInformation: {
url: currentSpaceURL,
...currentInfo,
},
};
2024-07-17 10:16:21 +00:00
const infoList = new ValueMap<URL, RelayInformation & { url: URL }>(url_identity);
2024-07-15 14:36:36 +00:00
for (const space of spaceList) {
if (new URL(space).toString() == currentSpaceURL.toString()) {
2024-07-17 10:16:21 +00:00
infoList.set(currentSpaceURL, {
2024-07-15 14:36:36 +00:00
url: currentSpaceURL,
...currentInfo,
});
continue;
}
const info = await getRelayInformation(space);
if (info instanceof Error) {
console.error(info);
continue;
}
const url = new URL(space);
2024-07-17 10:16:21 +00:00
infoList.set(url, {
2024-07-15 14:36:36 +00:00
url: url,
...info,
});
yield {
spaceInformationList: infoList,
};
}
}