loading remote cards

This commit is contained in:
balzack 2024-10-01 21:23:16 -07:00
parent 563a0ca46d
commit 84a5eaa727
8 changed files with 130 additions and 53 deletions

View File

@ -0,0 +1,8 @@
import { Text } from '@mantine/core'
import { useContacts } from './useContacts.hook';
export function Contacts() {
const { state, actions } = useContacts();
return <Text>CONTACTS</Text>
}

View File

@ -0,0 +1,31 @@
import { useState, useContext, useEffect } from 'react'
import { AppContext } from '../context/AppContext'
import { ContextType } from '../context/ContextType'
import { Card } from 'databag-client-sdk'
export function useContacts() {
const app = useContext(AppContext) as ContextType
const [state, setState] = useState({
})
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updateState = (value: any) => {
setState((s) => ({ ...s, ...value }))
}
useEffect(() => {
const contact = app.state.session?.getContact();
const setCards = (cards: Card[]) => {
console.log("CARDS", cards);
};
contact.addCardListener(setCards);
return () => {
contact.removeCardListener(setCards);
}
}, [])
const actions = {
}
return { state, actions }
}

View File

@ -10,6 +10,7 @@ import {
} from '@tabler/icons-react'
import { Settings } from '../settings/Settings'
import { Identity } from '../identity/Identity'
import { Contacts } from '../contacts/Contacts'
import { useDisclosure } from '@mantine/hooks'
export function Session() {
@ -17,11 +18,8 @@ export function Session() {
const display = useContext(DisplayContext) as ContextType
const [settings, { open: openSettings, close: closeSettings }] =
useDisclosure(false)
const click = () => {
console.log('SESSION DRAWER', openSettings)
openSettings()
}
const [contacts, { open: openContacts, close: closeContacts }] =
useDisclosure(false)
return (
<div className={classes.session}>
@ -29,6 +27,7 @@ export function Session() {
<>
<div className={classes.screen}>
{tab === 'settings' && <Settings showLogout={true} />}
{tab === 'contacts' && <Contacts />}
</div>
<div className={classes.tabs}>
{tab === 'channels' && (
@ -78,9 +77,18 @@ export function Session() {
{display.state.layout === 'large' && (
<div className={classes.display}>
<div className={classes.left}>
<Identity settings={click} contacts={() => {}} />
<Identity settings={openSettings} contacts={openContacts} />
</div>
<div className={classes.right}></div>
<Drawer
opened={contacts}
onClose={closeContacts}
withCloseButton={false}
size="sm"
position="right"
>
<Contacts />
</Drawer>
<Drawer
opened={settings}
onClose={closeSettings}

View File

@ -3,9 +3,11 @@ import type { Contact, Logging } from './api';
import type { Card, Topic, Asset, Tag, Profile, Participant} from './types';
import type { CardEntity } from './entities';
import type { ArticleRevision, ArticleDetail, ChannelRevision, ChannelSummary, ChannelDetail, CardRevision, CardNotification, CardProfile, CardDetail } from './items';
import { defaultConfigItem } from './items';
import { defaultCardItem } from './items';
import { Store } from './store';
import { getCards } from './net/getCards';
import { getCardProfile } from './net/getCardProfile';
import { getCardDetail } from './net/getCardDetail';
const CLOSE_POLL_MS = 100;
const RETRY_POLL_MS = 2000;
@ -140,13 +142,13 @@ export class ContactModule implements Contact {
await this.sync();
}
private getCardEntry(id: string) { item: CardItem, card: Card } {
private getCardEntry(id: string) {
const entry = this.cardEntries.get(id);
if (entry) {
return entry;
}
const item = JSON.parse(JSON.strifying(defaultCardItem));
const card = this.setCard(item);
const item = JSON.parse(JSON.stringify(defaultCardItem));
const card = this.setCard(id, item);
const cardEntry = { item, card };
this.cardEntries.set(id, cardEntry);
return cardEntry;
@ -166,54 +168,58 @@ export class ContactModule implements Contact {
if (data) {
const entry = this.getCardEntry(id);
if (data.detailRevision !== entry.detail.revison) {
// update detail
entry.detail.revision = data.detailRevision;
// store detail
if (data.detailRevision !== entry.item.detail.revison) {
const detail = data.cardDetail ? data.cardDetail : await getCardDetail(node, secure, token, id);
const { status, statusUpdated, token } = detail;
entry.item.detail = { revision: data.detailRevision, status, statusUpdated, token }
entry.card = this.setCard(id, entry.item);
this.store.setContactCardDetail(guid, id, entry.item.detail);
}
if (data.profileRevision !== entry.profile.revision) {
// update profile
entry.profile.revision = data.profileRevision;
// store profile
if (data.profileRevision !== entry.item.profile.revision) {
const profile = data.cardProfile ? data.cardProfile : await getCardProfile(node, secure, token, id);
const { guid, handle, name, description, location, imageSet, node, seal } = profile;
entry.item.profile = { revision: data.profileRevision, handle, guid, name, description, location, imageSet, node, seal };
entry.card = this.setCard(id, entry.item);
this.store.setContactCardProfile(guid, id, entry.item.profile);
}
if (data.notifiedProfile !== entry.remote.profile) {
entry.remote.profile = data.notifiedProfile;
if (data.notifiedProfile !== entry.item.remote.profile) {
entry.item.remote.profile = data.notifiedProfile;
try {
// sync profile
}
catch (err) {
this.log.warn(err);
entry.offsync = true;
entry.item.offsync = true;
// store offsync
}
// store remote
}
if (data.notifiedArticle !== entry.remote.article) {
entry.remote.article = data.notifiedArticle;
if (data.notifiedArticle !== entry.item.remote.article) {
entry.item.remote.article = data.notifiedArticle;
try {
// sync articles
}
catch (err) {
this.log.warn(err);
entry.offsync = true;
entry.item.offsync = true;
// store offsync
}
this.emitCardArticles(id);
this.emitArticles(id);
// store remote
}
if (data.notifiedChannel !== entry.remote.channel) {
entry.remote.channel = data.notifiedChannel;
if (data.notifiedChannel !== entry.item.remote.channel) {
entry.item.remote.channel = data.notifiedChannel;
try {
//sync channels
}
catch (err) {
this.log.warn(err);
entry.offsync = true;
this.emitCardChannels(id);
entry.item.offsync = true;
this.emitChannels(id);
// store offsync
}
}

View File

@ -1,5 +1,26 @@
import type { Profile } from './types';
export type CardDetailEntity = {
status: string,
statusUpdated: number,
token: string,
notes: string,
groups: [ string ]
}
export type CardProfileEntity = {
guid: string,
handle: string,
name: string,
description: string,
location: string,
imageSet: boolean,
version: string,
node: string,
seal: string,
revision: number,
}
export type CardEntity = {
id: string,
revision: number,
@ -9,25 +30,8 @@ export type CardEntity = {
notifiedProfile: number,
notifiedArticle: number,
notifiedChannel: number,
cardDetail?: {
status: string,
statusUpdated: number,
token: string,
notes: string,
groups: [ string ]
},
cardProfile?: {
guid: string,
handle: string,
name: string,
description: string,
location: string,
imageSet: boolean,
version: string,
node: string,
seal: string,
revision: number,
}
cardDetail?: CardDetailEntity,
cardProfile?: CardProfileEntity,
}
}

View File

@ -0,0 +1,10 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
import { CardDetailEntity } from '../entities';
export async function getCardDetail(node: string, secure: boolean, token: string, cardId: string): Promise<CardDetailEntity> {
const endpoint = `http${secure ? 's' : ''}://${node}/contact/cards/${cardId}/detail?agent=${token}`;
const detail = await fetchWithTimeout(endpoint, { method: 'GET' })
checkResponse(detail.status);
return await detail.json();
}

View File

@ -0,0 +1,10 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil';
import { CardProfileEntity } from '../entities';
export async function getCardProfile(node: string, secure: boolean, token: string, cardId: string): Promise<CardProfileEntity> {
const endpoint = `http${secure ? 's' : ''}://${node}/contact/cards/${cardId}/profile?agent=${token}`;
const profile = await fetchWithTimeout(endpoint, { method: 'GET' })
checkResponse(profile.status);
return await profile.json();
}

View File

@ -1,5 +1,5 @@
import { Login, ProfileEntity, defaultProfileEntity, ConfigEntity, defaultConfigEntity } from './entities';
import type { ArticleRevision, ArticleDetail, ArticleItem, ChannelItem, CardItem, CardRevision, CardNotification, CardProfile, CardDetail, ChannelRevision, ChannelSummary, ChannelDetail } from './items';
import type { ArticleRevision, ArticleDetail, ArticleItem, ChannelItem, CardItem, CardNotification, CardProfile, CardDetail, ChannelRevision, ChannelSummary, ChannelDetail } from './items';
import type { Logging } from './logging';
export interface Store {
@ -25,7 +25,7 @@ export interface Store {
setContactRevision(guid: string, revision: number): Promise<void>;
getContacts(guid: string): Promise<{ cardId: string, item: CardItem }[]>;
setContactCardRevision(guid: string, cardId: string, revision: CardRevision): Promise<void>;
setContactCardRevision(guid: string, cardId: string, revision: number): Promise<void>;
setContactCardProfile(guid: string, cardId: string, profile: CardProfile): Promise<void>;
setContactCardDetail(guid: string, cardId: string, detail: CardDetail): Promise<void>;
setContactCardBlocked(guid: string, cardId: string, blocked: boolean): Promise<void>;
@ -170,7 +170,7 @@ export class OfflineStore implements Store {
return [];
}
public async setContactCardRevision(guid: string, cardId: string, revision: CardRevision): Promise<void> {
public async setContactCardRevision(guid: string, cardId: string, revision: number): Promise<void> {
}
public async setContactCardProfile(guid: string, cardId: string, profile: CardProfile): Promise<void> {
@ -319,7 +319,7 @@ export class OnlineStore implements Store {
return [];
}
public async setContactCardRevision(guid: string, cardId: string, revision: CardRevision): Promise<void> {
public async setContactCardRevision(guid: string, cardId: string, revision: number): Promise<void> {
}
public async setContactCardProfile(guid: string, cardId: string, profile: CardProfile): Promise<void> {
@ -442,7 +442,7 @@ export class NoStore implements Store {
return [];
}
public async setContactCardRevision(guid: string, cardId: string, revision: CardRevision): Promise<void> {
public async setContactCardRevision(guid: string, cardId: string, revision: number): Promise<void> {
}
public async setContactCardProfile(guid: string, cardId: string, profile: CardProfile): Promise<void> {