diff --git a/frontend/app/src/components/SelectChatModal.svelte b/frontend/app/src/components/SelectChatModal.svelte index 1949ae586f..4b8f10932b 100644 --- a/frontend/app/src/components/SelectChatModal.svelte +++ b/frontend/app/src/components/SelectChatModal.svelte @@ -13,7 +13,7 @@ } from "openchat-client"; import Avatar from "./Avatar.svelte"; import CollapsibleCard from "./CollapsibleCard.svelte"; - import { AvatarSize, UserStatus, chatIdentifiersEqual } from "openchat-client"; + import { AvatarSize, chatIdentifiersEqual } from "openchat-client"; import Panel from "./Panel.svelte"; import { iconSize } from "../stores/iconSize"; import HoverIcon from "./HoverIcon.svelte"; @@ -24,6 +24,7 @@ import { now } from "../stores/time"; import MessageOutline from "svelte-material-icons/MessageOutline.svelte"; import ForumOutline from "svelte-material-icons/ForumOutline.svelte"; + import Search from "./Search.svelte"; const client = getContext("client"); const dispatch = createEventDispatcher(); @@ -40,6 +41,7 @@ name: string; avatarUrl: string; description: string; + username: string | undefined; }; type ShareCommunity = { kind: "community"; @@ -50,18 +52,26 @@ channels: ShareChat[]; }; + let searchTerm = ""; + let targets: ShareTo = { + directChats: [], + groupChats: [], + communities: [], + }; + + $: searchTermLower = searchTerm.toLowerCase(); $: userStore = client.userStore; $: selectedChatId = client.selectedChatId; $: globalState = client.globalStateStore; $: { - buildListOfTargets($globalState, $now, $selectedChatId).then((t) => (targets = t)); + buildListOfTargets($globalState, $now, $selectedChatId, searchTermLower).then( + (t) => (targets = t) + ); } - $: targets = undefined as ShareTo | undefined; $: noTargets = getNumberOfTargets(targets) === 0; - function getNumberOfTargets(targets: ShareTo | undefined): number { - if (targets === undefined) return 0; + function getNumberOfTargets(targets: ShareTo): number { return ( targets.directChats.length + targets.groupChats.length + @@ -79,12 +89,39 @@ ); } + function chatMatchesSearch(chats: ShareChat[], searchTerm: string): ShareChat[] { + return chats.filter( + (c) => + searchTerm === "" || + c.name.toLowerCase().includes(searchTerm) || + c.username?.toLowerCase()?.includes(searchTerm) + ); + } + + function communityMatchesSearch(communities: ShareCommunity[], searchTerm: string) { + return communities.reduce((agg, c) => { + const filtered = chatMatchesSearch(c.channels, searchTerm); + if (filtered.length > 0) { + agg.push({ + ...c, + channels: filtered, + }); + } + return agg; + }, [] as ShareCommunity[]); + } + async function buildListOfTargets( global: GlobalState, now: number, - selectedChatId: ChatIdentifier | undefined - ): Promise { - let targets: ShareTo | undefined = undefined; + selectedChatId: ChatIdentifier | undefined, + searchTerm: string + ): Promise { + let targets: ShareTo = { + directChats: [], + groupChats: [], + communities: [], + }; try { const directChats = await targetsFromChatList( now, @@ -100,9 +137,9 @@ global.communities.values().map((c) => normaliseCommunity(now, selectedChatId, c)) ); return { - directChats, - groupChats, - communities, + directChats: chatMatchesSearch(directChats, searchTerm), + groupChats: chatMatchesSearch(groupChats, searchTerm), + communities: communityMatchesSearch(communities, searchTerm), }; } catch (err) {} return targets; @@ -138,6 +175,7 @@ name: client.displayNameAndIcon(them), avatarUrl: client.userAvatarUrl(them), description, + username: "@" + them.username, }; default: @@ -148,6 +186,7 @@ name: chatSummary.name, avatarUrl: client.groupAvatarUrl(chatSummary), description: buildGroupChatDescription(chatSummary), + username: undefined, }; } } @@ -156,9 +195,13 @@ chat: DirectChatSummary, now: number ): Promise { - return (await client.getUserStatus(chat.them.userId, now)) === UserStatus.Online - ? $_("onlineNow") - : $_("offline"); + return client.getLastOnlineDate(chat.them.userId, now).then((lastOnline) => { + if (lastOnline !== undefined && lastOnline !== 0) { + return client.formatLastOnlineDate($_, now, lastOnline); + } else { + return $_("offline"); + } + }); } function buildGroupChatDescription(group: MultiUserChat): string { @@ -188,83 +231,89 @@ - +

{$_("sendTo")}

- dispatch("close")}> + dispatch("close")}>
- {#if targets === undefined} - ... - {:else if noTargets} + + {#if noTargets}
{$_("noChatsAvailable")}
{:else}
- -
-
- -
-
-

- {$_("communities.directChats")} -

-
-
- {#each targets.directChats as target} -
selectChat(target.id)}> + {#if targets.directChats.length > 0} + +
- +
-
{target.name}
-
{target.description}
+

+ {$_("communities.directChats")} +

- {/each} -
- -
-
- -
-
-

- {$_("communities.groupChats")} -

-
-
- {#each targets.groupChats as target} -
selectChat(target.id)}> -
- -
-
-
{target.name}
-
{target.description}
+ {#each targets.directChats as target} +
selectChat(target.id)}> +
+ +
+
+
+ + {target.name} + + {#if target.username !== undefined} + {target.username} + {/if} +
+
{target.description}
+
-
- {/each} - - {#each targets.communities as community} - + {/each} + + {/if} + {#if targets.groupChats.length > 0} +
- +

- {community.name} + {$_("communities.groupChats")}

- {#each community.channels as target} + {#each targets.groupChats as target}
selectChat(target.id)}> @@ -278,6 +327,41 @@
{/each}
+ {/if} + {#each targets.communities as community} + {#if community.channels.length > 0} + +
+
+ +
+
+

+ {community.name} +

+
+
+ {#each community.channels as target} +
selectChat(target.id)}> +
+ +
+
+
{target.name}
+
{target.description}
+
+
+ {/each} +
+ {/if} {/each}
{/if} @@ -366,6 +450,13 @@ overflow: hidden; .name { @include font(book, normal, fs-100); + + display: flex; + gap: $sp2; + + .username { + color: var(--txt-light); + } } .description { @include ellipsis();