From 9b7373de995982875856dea917bd9dfc9bd41e63 Mon Sep 17 00:00:00 2001 From: Bob <160986752+bob2402@users.noreply.github.com> Date: Wed, 10 Jul 2024 17:05:01 +0800 Subject: [PATCH] new conversation list (#496) Co-authored-by: BlowaterNostr --- app/UI/new-nav.test.tsx | 52 +++++---- app/UI/new-nav.tsx | 232 ++++++++++++++++++++++++++++------------ 2 files changed, 195 insertions(+), 89 deletions(-) diff --git a/app/UI/new-nav.test.tsx b/app/UI/new-nav.test.tsx index 22ed2fd..eb47ee5 100644 --- a/app/UI/new-nav.test.tsx +++ b/app/UI/new-nav.test.tsx @@ -2,7 +2,7 @@ import { h, render } from "preact"; import { NewNav } from "./new-nav.tsx"; import { prepareProfileEvent, testEventBus } from "./_setup.test.ts"; -import { ConnectionPool, InMemoryAccountContext } from "@blowater/nostr-sdk"; +import { ConnectionPool, InMemoryAccountContext, PublicKey } from "@blowater/nostr-sdk"; const pool = new ConnectionPool(); await pool.addRelayURLs( @@ -14,22 +14,22 @@ await pool.addRelayURLs( "wss://relay.nostr.wirednet.jp", "wss://relay.nostr.moctane.com", "wss://remnant.cloud", - // "wss://nostr.cahlen.org", - // "wss://fog.dedyn.io", - // "wss://global-relay.cesc.trade", - // "wss://nostr.dakukitsune.ca", - // "wss://africa.nostr.joburg", - // "wss://nostr-relay.ktwo.io", - // "wss://bevo.nostr1.com", - // "wss://relay.corpum.com", - // "wss://relay.nostr.directory", - // "wss://nostr.1f52b.xyz", - // "wss://lnbits.eldamar.icu/nostrrelay/relay", - // "wss://relay.cosmicbolt.net", - // "wss://island.nostr1.com", - // "wss://nostr.codingarena.de", - // "wss://nostr.madco.me", - // "wss://nostr-relay.bitcoin.ninja", + "wss://nostr.cahlen.org", + "wss://fog.dedyn.io", + "wss://global-relay.cesc.trade", + "wss://nostr.dakukitsune.ca", + "wss://africa.nostr.joburg", + "wss://nostr-relay.ktwo.io", + "wss://bevo.nostr1.com", + "wss://relay.corpum.com", + "wss://relay.nostr.directory", + "wss://nostr.1f52b.xyz", + "wss://lnbits.eldamar.icu/nostrrelay/relay", + "wss://relay.cosmicbolt.net", + "wss://island.nostr1.com", + "wss://nostr.codingarena.de", + "wss://nostr.madco.me", + "wss://nostr-relay.bitcoin.ninja", ], ); const ctx = InMemoryAccountContext.Generate(); @@ -42,13 +42,29 @@ const profileEvent = await prepareProfileEvent(ctx, { picture: "https://image.nostr.build/655007ae74f24ea1c611889f48b25cb485b83ab67408daddd98f95782f47e1b5.jpg", }); +let currentConversation: PublicKey | undefined; +const convoList = new Set(); +const pinList = new Set(); +for (let i = 0; i < 50; i++) { + const pubkey = InMemoryAccountContext.Generate().publicKey; + if (i % 4 == 0) pinList.add(pubkey); + if (i == 5) currentConversation = pubkey; + convoList.add(pubkey); +} + render( profileEvent, + getConversationList: () => convoList, + getPinList: () => pinList, + }} />, document.body, ); diff --git a/app/UI/new-nav.tsx b/app/UI/new-nav.tsx index 22b309d..f88a6fd 100644 --- a/app/UI/new-nav.tsx +++ b/app/UI/new-nav.tsx @@ -1,35 +1,38 @@ /** @jsx h */ -import { Component, Fragment, h } from "preact"; -import { emitFunc, EventSubscriber } from "../event-bus.ts"; +import { Component, h } from "preact"; +import { emitFunc } from "../event-bus.ts"; import { NavigationUpdate, NavTabID, SelectSpace, ShowProfileSetting } from "./nav.tsx"; import { ViewSpaceSettings } from "./setting.tsx"; -import { ConnectionPool, getRelayInformation, RelayInformation, robohash } from "@blowater/nostr-sdk"; +import { + ConnectionPool, + getRelayInformation, + PublicKey, + RelayInformation, + robohash, +} from "@blowater/nostr-sdk"; import { setState } from "./_helper.ts"; 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 { ConversationSummary } from "./conversation-list.ts"; -import { ProfileData } from "../features/profile.ts"; -import { PinIcon } from "./icons/pin-icon.tsx"; -import { PrimaryTextColor } from "./style/colors.ts"; -import { - ContactUpdate, - ConversationListRetriever, - ConversationType, - NewMessageChecker, - PinListGetter, -} from "./conversation-list.tsx"; -import { SearchUpdate, SelectConversation } from "./search_model.ts"; +import { ContactUpdate } from "./conversation-list.tsx"; import { TagSelected } from "./contact-tags.tsx"; import { ViewUserDetail } from "./message-panel.tsx"; -import { UI_Interaction_Event, UserBlocker } from "./app_update.tsx"; -import { func_GetProfileByPublicKey, func_GetProfilesByText } from "./search.tsx"; +import { func_GetProfileByPublicKey } from "./search.tsx"; +import { PinIcon } from "./icons/pin-icon.tsx"; +import { SelectConversation } from "./search_model.ts"; type NewNavProps = { pool: ConnectionPool; activeNav: NavTabID; currentSpace: string; + profile: Profile_Nostr_Event | undefined; + currentConversation: PublicKey | undefined; + getters: { + getProfileByPublicKey: func_GetProfileByPublicKey; + getConversationList: func_GetConversationList; + getPinList: func_GetPinList; + }; emit: emitFunc< | SelectSpace | NavigationUpdate @@ -39,22 +42,26 @@ type NewNavProps = { | TagSelected | ViewUserDetail >; - profile: Profile_Nostr_Event | undefined; }; export class NewNav extends Component { render(props: NewNavProps) { return ( -
+
r.url))} emit={props.emit} /> {/* */} - - - + + +
); } @@ -111,13 +118,13 @@ class SpaceDropDownPanel extends Component - {this.TopIconButton()} + {this.CurrentSpaceIndicator()} {this.state.showDropDown ? this.DropDown(spaceList) : undefined}
); } - TopIconButton = () => { + CurrentSpaceIndicator = () => { return (
current space url
}
- + {this.state.showDropDown + ? + : }
); @@ -147,7 +156,7 @@ class SpaceDropDownPanel extends Component { return ( -
+
{this.SettingsButton()} {/* {this.InviteButton()} */}
@@ -296,67 +305,148 @@ function GlobalSearch() { return
Search
; } -function GroupChatList() { - return ( -
- -
Public
-
- ); -} - -type DirectMessageListProps = { - //TODO: The list is based on private messages both received and sent, as well as other sources. - profile: Profile_Nostr_Event | undefined; +type GroupChatListProps = { + activeNav: NavTabID; + emit: emitFunc; }; -// type DirectMessageListState = {}; +class GroupChatList extends Component { + render(props: GroupChatListProps) { + return ( +
{ + props.emit({ + type: "ChangeNavigation", + id: "Public", + }); + }} + > + +
Public
+
+ ); + } +} + +type func_GetConversationList = () => Set; +type func_GetPinList = () => Set; + +type DirectMessageListProps = { + emit: emitFunc; + currentSpace: string; + currentConversation: PublicKey | undefined; + getters: { + getProfileByPublicKey: func_GetProfileByPublicKey; + getConversationList: func_GetConversationList; + getPinList: func_GetPinList; + }; +}; class DirectMessageList extends Component { render(props: DirectMessageListProps) { + const pinList = props.getters.getPinList(); + const pinned = []; + const unpinned = []; + for (const pubkey of props.getters.getConversationList()) { + if (pinList.has(pubkey)) { + pinned.push(pubkey); + } else { + unpinned.push(pubkey); + } + } return ( -
-
-
-
- -
-
- {props.profile?.profile.name || props.profile?.profile.display_name || - props.profile?.pubkey} -
-
-
-
- -
-
- {props.profile?.profile.name || props.profile?.profile.display_name || - props.profile?.pubkey} -
-
-
-
- -
-
- {props.profile?.profile.name || props.profile?.profile.display_name || - props.profile?.pubkey} -
-
+
+
+ {pinned.map((pubkey: PublicKey) => ( + + ))} + {unpinned.map((pubkey: PublicKey) => ( + + ))}
); } } -type ProfileMenuProps = { +type DireactMessageItemProps = { + pubkey: PublicKey; + emit: emitFunc; + isPined: boolean; + currentSpace: string; + currentConversation: PublicKey | undefined; + getters: { + getProfileByPublicKey: func_GetProfileByPublicKey; + }; +}; + +class DireactMessageItem extends Component { + render(props: DireactMessageItemProps) { + const profile = props.getters.getProfileByPublicKey(props.pubkey, new URL(props.currentSpace)) + ?.profile; + const picture = profile?.picture || "./logo.webp"; + const name = profile?.name || profile?.display_name || profile?.pubkey; + return ( +
{ + props.emit({ + type: "SelectConversation", + pubkey: props.pubkey, + }); + }} + > +
+ +
+
+ {name} +
+ {props.isPined + ? ( +
+ +
+ ) + : undefined} +
+ ); + } +} + +type UserIndicatorProps = { profile: Profile_Nostr_Event | undefined; emit: emitFunc; }; -class ProfileMenu extends Component { - render(props: ProfileMenuProps) { +class UserIndicator extends Component { + render(props: UserIndicatorProps) { return (