mirror of
https://github.com/balzack/databag.git
synced 2025-04-24 02:25:26 +00:00
displaying contact list
This commit is contained in:
parent
da973b28af
commit
d9bdb25079
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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 (
|
||||
<div className={classes.card}>
|
||||
<Text>CARD</Text>
|
||||
{ children }
|
||||
<div className={className}>
|
||||
<div className={classes.card}>
|
||||
<Image radius="sm" className={classes.image} src={imageUrl} />
|
||||
<div className={classes.details}>
|
||||
{ name && (
|
||||
<Text className={classes.nameSet}>{ name }</Text>
|
||||
)}
|
||||
{ !name && (
|
||||
<Text className={classes.nameUnset}>{ placeholder }</Text>
|
||||
)}
|
||||
<Text className={classes.handle}>{ node ? `${handle}/${node}` : handle }</Text>
|
||||
</div>
|
||||
{ children }
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,11 +8,18 @@ import { Card } from '../card/Card';
|
||||
export function Contacts() {
|
||||
const { state, actions } = useContacts();
|
||||
|
||||
const cards = state.filtered.map((card) => <Card className={classes.card} key={card.cardId} imageUrl={card.imageUrl} name={card.name} handle={card.handle} node={card.node} placeholder={state.strings.name} children={<IconSearch />} />)
|
||||
|
||||
return (
|
||||
<div className={classes.contacts}>
|
||||
<div className={classes.header}>
|
||||
<ActionIcon variant="subtle">
|
||||
<IconSortDescending size={32} />
|
||||
{ state.sortAsc && (
|
||||
<IconSortAscending size={32} onClick={actions.toggleSort} />
|
||||
)}
|
||||
{ !state.sortAsc && (
|
||||
<IconSortDescending size={32} onClick={actions.toggleSort} />
|
||||
)}
|
||||
</ActionIcon>
|
||||
<TextInput
|
||||
className={classes.input}
|
||||
@ -20,17 +27,15 @@ export function Contacts() {
|
||||
leftSectionPointerEvents="none"
|
||||
leftSection={<IconSearch size={20} />}
|
||||
placeholder={state.strings.contacts}
|
||||
value={state.filter}
|
||||
onChange={(event) => actions.setFilter(event.currentTarget.value)}
|
||||
/>
|
||||
<Button className={classes.add} leftSection={<IconUserPlus size={20} />}>
|
||||
{state.strings.add}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className={classes.card}>
|
||||
<Card>
|
||||
<IconSearch />
|
||||
</Card>
|
||||
</div>
|
||||
<div className={classes.cards}>{ cards }</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -64,6 +64,7 @@
|
||||
.handle {
|
||||
text-wrap: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
text-align: center;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
@ -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
|
||||
};
|
||||
|
@ -9,6 +9,7 @@ export type Card = {
|
||||
name: string;
|
||||
description: string;
|
||||
location: string;
|
||||
imageUrl: string;
|
||||
imageSet: boolean;
|
||||
version: string;
|
||||
node: string;
|
||||
|
Loading…
x
Reference in New Issue
Block a user