From d9bdb2507966b881cf6857737b07feb912e9d19f Mon Sep 17 00:00:00 2001 From: balzack Date: Sat, 12 Oct 2024 09:35:11 -0700 Subject: [PATCH] displaying contact list --- app/client/web/src/card/Card.module.css | 41 ++++++++++++++- app/client/web/src/card/Card.tsx | 24 ++++++--- .../web/src/contacts/Contacts.module.css | 19 +++++-- app/client/web/src/contacts/Contacts.tsx | 17 ++++--- .../web/src/contacts/useContacts.hook.ts | 50 ++++++++++++++++--- .../web/src/identity/Identity.module.css | 1 + app/sdk/src/contact.ts | 4 +- app/sdk/src/types.ts | 1 + 8 files changed, 131 insertions(+), 26 deletions(-) diff --git a/app/client/web/src/card/Card.module.css b/app/client/web/src/card/Card.module.css index 7c3f812f..65b46878 100644 --- a/app/client/web/src/card/Card.module.css +++ b/app/client/web/src/card/Card.module.css @@ -2,6 +2,45 @@ display: flex; flex-direction: row; align-items: center; - width: 100%; + width: auto; height: 100%; + cursor: default; + + .details { + display: flex; + flex-direction: column; + flex-grow: 1; + padding-left: 8px; + padding-right: 8px; + } + + .image { + width: auto; + height: 100%; + } + + .nameSet { + font-size: 16px; + text-wrap: nowrap; + text-overflow: ellipsis; + overflow: hidden; + } + + .nameUnset { + font-size: 16px; + text-wrap: nowrap; + text-overflow: ellipsis; + overflow: hidden; + font-style: italic; + color: var(--mantine-color-text-9); + } + + .handle { + font-size: 12px; + text-wrap: nowrap; + text-overflow: ellipsis; + overflow: hidden; + font-weight: bold; + } + } diff --git a/app/client/web/src/card/Card.tsx b/app/client/web/src/card/Card.tsx index 2759e8f9..3e33d92a 100644 --- a/app/client/web/src/card/Card.tsx +++ b/app/client/web/src/card/Card.tsx @@ -1,14 +1,24 @@ -import React from 'react' -import { Text } from '@mantine/core'; +import React, { ReactNode } from 'react' +import { Image, Text } from '@mantine/core'; import classes from './Card.module.css' -export function Card({imageUrl, name, handle, children} : { imageUrl: string, name: string, handle: string, children: ReactNode }) { -console.log("CHILDREN: ", children); +export function Card({ imageUrl, name, placeholder, handle, node, children, className }: { className: string, imageUrl: string, name: string, placeholder: string, handle: string, node: string, children: ReactNode }) { return ( -
- CARD - { children } +
+
+ +
+ { name && ( + { name } + )} + { !name && ( + { placeholder } + )} + { node ? `${handle}/${node}` : handle } +
+ { children } +
); } diff --git a/app/client/web/src/contacts/Contacts.module.css b/app/client/web/src/contacts/Contacts.module.css index 36159148..11e879d5 100644 --- a/app/client/web/src/contacts/Contacts.module.css +++ b/app/client/web/src/contacts/Contacts.module.css @@ -5,6 +5,7 @@ padding-top: 8px; gap: 2px; width: 100%; + height: 100vh; .header { display: flex; @@ -28,10 +29,20 @@ } } - .card { - height: 48px; - padding: 4px; + .cards { + display: flex; + flex-direction: column; width: 100%; - border: 1px solid white; + overflow: auto; + + .card { + width: 100%; + height: 48px; + padding-top: 8px; + padding-bottom: 8px; + padding-right: 16px; + padding-left: 16px; + border-bottom: 1px solid var(--mantine-color-text-9); + } } } diff --git a/app/client/web/src/contacts/Contacts.tsx b/app/client/web/src/contacts/Contacts.tsx index c53ea11f..b6354ea2 100644 --- a/app/client/web/src/contacts/Contacts.tsx +++ b/app/client/web/src/contacts/Contacts.tsx @@ -8,11 +8,18 @@ import { Card } from '../card/Card'; export function Contacts() { const { state, actions } = useContacts(); + const cards = state.filtered.map((card) => } />) + return (
- + { state.sortAsc && ( + + )} + { !state.sortAsc && ( + + )} } placeholder={state.strings.contacts} + value={state.filter} + onChange={(event) => actions.setFilter(event.currentTarget.value)} />
-
- - - -
+
{ cards }
); } diff --git a/app/client/web/src/contacts/useContacts.hook.ts b/app/client/web/src/contacts/useContacts.hook.ts index 38862312..04caebe0 100644 --- a/app/client/web/src/contacts/useContacts.hook.ts +++ b/app/client/web/src/contacts/useContacts.hook.ts @@ -9,6 +9,10 @@ export function useContacts() { const display = useContext(DisplayContext) as ContextType const [state, setState] = useState({ strings: display.state.strings, + cards: [] as Card[], + filtered: [] as Card[], + sortAsc: false, + filter: '', }) // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -16,24 +20,56 @@ export function useContacts() { setState((s) => ({ ...s, ...value })) } + const compare = (a: Channel, b: Channel) => { + const aval = `${a.handle}/${a.node}`; + const bval = `${b.handle}/${b.node}`; + if (aval < bval) { + return state.sortAsc ? 1 : -1; + } else if (aval > bval) { + return state.sortAsc ? -1 : 1; + } + return 0; + } + + const select = (c: Channel) => { + if (!state.filter) { + return true; + } + const value = state.filter.toLowerCase(); + if (c.name && c.name.toLowerCase().includes(value)) { + return true; + } + const handle = c.node ? `${c.handle}/${c.node}` : c.handle; + if (handle.toLowerCase().includes(value)) { + return true; + } + return false; + } + useEffect(() => { const contact = app.state.session?.getContact(); const setCards = (cards: Card[]) => { - console.log("CARDS", cards); + updateState({ cards }); }; contact.addCardListener(setCards); - const setChannels = ({ cardId, channels }: { cardId: string, channels: Channel[] }) => { - - console.log("CHANNELS :", cardId, channels); - }; - contact.addChannelListener(null, setChannels); return () => { contact.removeCardListener(setCards); - contact.removeChannelListener(setChannels); } }, []) + useEffect(() => { + const filtered = state.cards.sort(compare).filter(select); + updateState({ filtered }); + }, [state.sortAsc, state.filter, state.cards]); + const actions = { + toggleSort: () => { + const sortAsc = !state.sortAsc; + updateState({ sortAsc }); + }, + setFilter: (filter) => { + updateState({ filter }); + }, } return { state, actions } diff --git a/app/client/web/src/identity/Identity.module.css b/app/client/web/src/identity/Identity.module.css index 67275ded..f5e0f39e 100644 --- a/app/client/web/src/identity/Identity.module.css +++ b/app/client/web/src/identity/Identity.module.css @@ -64,6 +64,7 @@ .handle { text-wrap: nowrap; text-overflow: ellipsis; + text-align: center; overflow: hidden; width: 100%; } diff --git a/app/sdk/src/contact.ts b/app/sdk/src/contact.ts index aebd575a..fd63e53b 100644 --- a/app/sdk/src/contact.ts +++ b/app/sdk/src/contact.ts @@ -2,7 +2,7 @@ import { EventEmitter } from 'eventemitter3'; import type { Contact, Logging, Focus } from './api'; import type { FocusModule } from './focus'; import type { Card, Topic, Asset, Tag, Profile, Participant } from './types'; -import type { CardEntity, avatar } from './entities'; +import { type CardEntity, avatar } from './entities'; import type { ArticleRevision, ArticleDetail, @@ -835,6 +835,7 @@ export class ContactModule implements Contact { private setCard(cardId: string, item: CardItem): Card { + const { node, secure, token } = this; const { profile, detail } = item; return { cardId, @@ -847,6 +848,7 @@ export class ContactModule implements Contact { name: profile.name, description: profile.description, location: profile.location, + imageUrl: profile.imageSet ? getCardImageUrl(node, secure, token, cardId, item.profile.revision) : avatar, imageSet: profile.imageSet, node: profile.node }; diff --git a/app/sdk/src/types.ts b/app/sdk/src/types.ts index c0bbcdff..79ba3a89 100644 --- a/app/sdk/src/types.ts +++ b/app/sdk/src/types.ts @@ -9,6 +9,7 @@ export type Card = { name: string; description: string; location: string; + imageUrl: string; imageSet: boolean; version: string; node: string;