mirror of
https://github.com/balzack/databag.git
synced 2025-05-05 07:55:15 +00:00
implementing focus module
This commit is contained in:
parent
5ae031f268
commit
2ddf3e0d94
@ -1,7 +1,7 @@
|
|||||||
import { useState, useContext, useEffect, useRef } from 'react'
|
import { useState, useContext, useEffect, useRef } from 'react'
|
||||||
import { AppContext } from '../context/AppContext'
|
import { AppContext } from '../context/AppContext'
|
||||||
import { DisplayContext } from '../context/DisplayContext'
|
import { DisplayContext } from '../context/DisplayContext'
|
||||||
import { Focus, Topic, AssetSource, HostingMode, TransformType } from 'databag-client-sdk'
|
import { Focus, FocusDetail, Topic, AssetSource, HostingMode, TransformType } from 'databag-client-sdk'
|
||||||
import { ContextType } from '../context/ContextType'
|
import { ContextType } from '../context/ContextType'
|
||||||
|
|
||||||
const img =
|
const img =
|
||||||
@ -31,14 +31,14 @@ export function useConversation() {
|
|||||||
const setTopics = (topics: Topic[]) => {
|
const setTopics = (topics: Topic[]) => {
|
||||||
console.log(topics);
|
console.log(topics);
|
||||||
}
|
}
|
||||||
const setStatus = (status: string) => {
|
const setDetail = (focused: { cardId: string | null, channelId: string, detail: FocusDetail | null }) => {
|
||||||
console.log(status);
|
console.log(focused);
|
||||||
}
|
}
|
||||||
focus.addTopicListener(setTopics);
|
focus.addTopicListener(setTopics);
|
||||||
focus.addStatusListener(setStatus);
|
focus.addDetailListener(setDetail);
|
||||||
return () => {
|
return () => {
|
||||||
focus.removeTopicListener(setTopics);
|
focus.removeTopicListener(setTopics);
|
||||||
focus.removeStatusListener(setStatus);
|
focus.removeDetailListener(setDetail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [app.state.focus]);
|
}, [app.state.focus]);
|
||||||
|
13033
app/client/web/yarn.lock
13033
app/client/web/yarn.lock
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
|||||||
import type { Channel, Topic, AssetSource, Asset, Tag, Article, Group, Card, Profile, Call, Config, NodeConfig, NodeAccount, Participant } from './types';
|
import type { Channel, Topic, AssetSource, Asset, Tag, Article, Group, Card, Profile, Call, FocusDetail, Config, NodeConfig, NodeAccount, Participant } from './types';
|
||||||
|
|
||||||
export interface Session {
|
export interface Session {
|
||||||
getSettings(): Settings;
|
getSettings(): Settings;
|
||||||
@ -138,8 +138,8 @@ export interface Focus {
|
|||||||
addTopicListener(ev: (topics: Topic[]) => void): void;
|
addTopicListener(ev: (topics: Topic[]) => void): void;
|
||||||
removeTopicListener(ev: (topics: Topic[]) => void): void;
|
removeTopicListener(ev: (topics: Topic[]) => void): void;
|
||||||
|
|
||||||
addStatusListener(ev: (status: string) => void): void;
|
addDetailListener(ev: (focused: { cardId: string | null, channelId: string, detail: FocusDetail | null }) => void): void;
|
||||||
removeStatusListener(ev: (status: string) => void): void;
|
removeDetailListener(ev: (focused: { cardId: string | null, channelId: string, detail: FocusDetail | null }) => void): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Node {
|
export interface Node {
|
||||||
|
@ -2,7 +2,7 @@ import { EventEmitter } from 'eventemitter3';
|
|||||||
import type { Contact, Focus } from './api';
|
import type { Contact, Focus } from './api';
|
||||||
import { Logging } from './logging';
|
import { Logging } from './logging';
|
||||||
import { FocusModule } from './focus';
|
import { FocusModule } from './focus';
|
||||||
import type { Card, Channel, Article, Topic, Asset, Tag, Profile, Participant } from './types';
|
import type { Card, Channel, Article, Topic, Asset, Tag, FocusDetail, Profile, Participant } from './types';
|
||||||
import { type CardEntity, avatar } from './entities';
|
import { type CardEntity, avatar } from './entities';
|
||||||
import type { ArticleDetail, ChannelSummary, ChannelDetail, CardProfile, CardDetail, CardItem, ChannelItem, ArticleItem } from './items';
|
import type { ArticleDetail, ChannelSummary, ChannelDetail, CardProfile, CardDetail, CardItem, ChannelItem, ArticleItem } from './items';
|
||||||
import { defaultCardItem, defaultChannelItem } from './items';
|
import { defaultCardItem, defaultChannelItem } from './items';
|
||||||
@ -504,6 +504,20 @@ export class ContactModule implements Contact {
|
|||||||
};
|
};
|
||||||
entry.item.unsealedDetail = null;
|
entry.item.unsealedDetail = null;
|
||||||
await this.unsealChannelDetail(cardId, id, entry.item);
|
await this.unsealChannelDetail(cardId, id, entry.item);
|
||||||
|
if (this.focus) {
|
||||||
|
const { dataType, data, enableImage, enableAudio, enableVideo, enableBinary } = detail;
|
||||||
|
const sealed = dataType === 'sealed';
|
||||||
|
const focusDetail = {
|
||||||
|
sealed,
|
||||||
|
dataType,
|
||||||
|
data: sealed ? entry.item.unsealedDetail : data,
|
||||||
|
enableImage,
|
||||||
|
enableAudio,
|
||||||
|
enableVideo,
|
||||||
|
enableBinary,
|
||||||
|
}
|
||||||
|
this.focus.setDetail(cardId, id, focusDetail);
|
||||||
|
}
|
||||||
entry.channel = this.setChannel(cardId, id, entry.item);
|
entry.channel = this.setChannel(cardId, id, entry.item);
|
||||||
await this.store.setContactCardChannelDetail(guid, cardId, id, entry.item.detail, entry.item.unsealedDetail);
|
await this.store.setContactCardChannelDetail(guid, cardId, id, entry.item.detail, entry.item.unsealedDetail);
|
||||||
}
|
}
|
||||||
@ -526,10 +540,10 @@ export class ContactModule implements Contact {
|
|||||||
this.setChannelUnread(cardId, id);
|
this.setChannelUnread(cardId, id);
|
||||||
entry.channel = this.setChannel(cardId, id, entry.item);
|
entry.channel = this.setChannel(cardId, id, entry.item);
|
||||||
await this.store.setContactCardChannelSummary(guid, cardId, id, entry.item.summary, entry.item.unsealedSummary);
|
await this.store.setContactCardChannelSummary(guid, cardId, id, entry.item.summary, entry.item.unsealedSummary);
|
||||||
}
|
|
||||||
if (this.focus) {
|
if (this.focus) {
|
||||||
await this.focus.setRevision(cardId, id, topicRevision);
|
await this.focus.setRevision(cardId, id, topicRevision);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const channels = this.getChannelEntries(cardId);
|
const channels = this.getChannelEntries(cardId);
|
||||||
channels.delete(id);
|
channels.delete(id);
|
||||||
@ -632,6 +646,7 @@ export class ContactModule implements Contact {
|
|||||||
const channelsEntry = this.channelEntries.get(cardId);
|
const channelsEntry = this.channelEntries.get(cardId);
|
||||||
const channelEntry = channelsEntry?.get(channelId);
|
const channelEntry = channelsEntry?.get(channelId);
|
||||||
if (cardEntry && channelEntry) {
|
if (cardEntry && channelEntry) {
|
||||||
|
// allocate focus
|
||||||
const node = cardEntry.item.profile.node;
|
const node = cardEntry.item.profile.node;
|
||||||
const guid = cardEntry.item.profile.guid;
|
const guid = cardEntry.item.profile.guid;
|
||||||
const token = cardEntry.item.detail.token;
|
const token = cardEntry.item.detail.token;
|
||||||
@ -640,6 +655,20 @@ export class ContactModule implements Contact {
|
|||||||
const sealEnabled = Boolean(this.seal);
|
const sealEnabled = Boolean(this.seal);
|
||||||
const insecure = /^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(node);
|
const insecure = /^(?!0)(?!.*\.$)((1?\d?\d|25[0-5]|2[0-4]\d)(\.|:\d+$|$)){4}$/.test(node);
|
||||||
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, cardId, channelId, this.guid, { node, secure: !insecure, token: `${guid}.${token}` }, channelKey, sealEnabled, revision, markRead, flagTopic);
|
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, cardId, channelId, this.guid, { node, secure: !insecure, token: `${guid}.${token}` }, channelKey, sealEnabled, revision, markRead, flagTopic);
|
||||||
|
|
||||||
|
// set current detail
|
||||||
|
const { dataType, data, enableImage, enableAudio, enableVideo, enableBinary } = channelEntry.item.detail;
|
||||||
|
const sealed = dataType === 'sealed';
|
||||||
|
const focusDetail = {
|
||||||
|
sealed,
|
||||||
|
dataType,
|
||||||
|
data: sealed ? channelEntry.item.unsealedDetail : data,
|
||||||
|
enableImage,
|
||||||
|
enableAudio,
|
||||||
|
enableVideo,
|
||||||
|
enableBinary,
|
||||||
|
}
|
||||||
|
this.focus.setDetail(cardId, channelId, focusDetail);
|
||||||
} else {
|
} else {
|
||||||
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, cardId, channelId, this.guid, null, null, false, 0, markRead, flagTopic);
|
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, cardId, channelId, this.guid, null, null, false, 0, markRead, flagTopic);
|
||||||
}
|
}
|
||||||
@ -1022,6 +1051,19 @@ export class ContactModule implements Contact {
|
|||||||
if (item.channelKey) {
|
if (item.channelKey) {
|
||||||
const { data } = await this.crypto.aesDecrypt(subjectEncrypted, subjectIv, item.channelKey);
|
const { data } = await this.crypto.aesDecrypt(subjectEncrypted, subjectIv, item.channelKey);
|
||||||
item.unsealedDetail = data;
|
item.unsealedDetail = data;
|
||||||
|
if (this.focus) {
|
||||||
|
const { dataType, enableImage, enableAudio, enableVideo, enableBinary } = item.detail;
|
||||||
|
const focusDetail = {
|
||||||
|
sealed: true,
|
||||||
|
dataType,
|
||||||
|
data,
|
||||||
|
enableImage,
|
||||||
|
enableAudio,
|
||||||
|
enableVideo,
|
||||||
|
enableBinary,
|
||||||
|
}
|
||||||
|
this.focus.setDetail(cardId, channelId, focusDetail);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -2,7 +2,7 @@ import { EventEmitter } from 'eventemitter3';
|
|||||||
import type { Focus } from './api';
|
import type { Focus } from './api';
|
||||||
import type { TopicItem, AssetItem, TopicDetail } from './items';
|
import type { TopicItem, AssetItem, TopicDetail } from './items';
|
||||||
import type { Topic, Asset, AssetSource, Participant } from './types';
|
import type { Topic, Asset, AssetSource, Participant } from './types';
|
||||||
import { TransformType, HostingMode, AssetType } from './types';
|
import { TransformType, HostingMode, AssetType, FocusDetail } from './types';
|
||||||
import type { Logging } from './logging';
|
import type { Logging } from './logging';
|
||||||
import { Store } from './store';
|
import { Store } from './store';
|
||||||
import { Crypto } from './crypto';
|
import { Crypto } from './crypto';
|
||||||
@ -50,6 +50,7 @@ export class FocusModule implements Focus {
|
|||||||
private unsealAll: boolean;
|
private unsealAll: boolean;
|
||||||
private markRead: ()=>Promise<void>;
|
private markRead: ()=>Promise<void>;
|
||||||
private flagChannelTopic: (id: string)=>Promise<void>;
|
private flagChannelTopic: (id: string)=>Promise<void>;
|
||||||
|
private focusDetail: FocusDetail | null;
|
||||||
|
|
||||||
private markers: Set<string>;
|
private markers: Set<string>;
|
||||||
|
|
||||||
@ -79,6 +80,7 @@ export class FocusModule implements Focus {
|
|||||||
this.closing = false;
|
this.closing = false;
|
||||||
this.closeMedia = [];
|
this.closeMedia = [];
|
||||||
this.nextRevision = null;
|
this.nextRevision = null;
|
||||||
|
this.focusDetail = null;
|
||||||
this.loadMore = false;
|
this.loadMore = false;
|
||||||
this.unsealAll = false;
|
this.unsealAll = false;
|
||||||
this.localComplete = false;
|
this.localComplete = false;
|
||||||
@ -829,20 +831,36 @@ export class FocusModule implements Focus {
|
|||||||
this.emitter.emit('topic', topics);
|
this.emitter.emit('topic', topics);
|
||||||
}
|
}
|
||||||
|
|
||||||
public addStatusListener(ev: (status: string) => void) {
|
public addDetailListener(ev: (focused: { cardId: string | null, channelId: string, detail: FocusDetail | null }) => void) {
|
||||||
this.emitter.on('status', ev);
|
const { cardId, channelId } = this;
|
||||||
const status = this.connection ? 'connected' : 'disconnected'
|
const access = Boolean(this.connection && (!this.focusDetail?.sealed || (this.sealEnabled && this.channelKey)))
|
||||||
ev(status);
|
const detail = access ? this.focusDetail : null;
|
||||||
|
this.emitter.on('detail', ev);
|
||||||
|
ev({ cardId, channelId, detail });
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeStatusListener(ev: (status: string) => void) {
|
public removeDetailListener(ev: (focused: { cardId: string | null, channelId: string, detail: FocusDetail | null }) => void) {
|
||||||
this.emitter.off('status', ev);
|
this.emitter.off('detail', ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
private emitDetail() {
|
||||||
|
const { cardId, channelId } = this;
|
||||||
|
const access = Boolean(this.connection && (!this.focusDetail?.sealed || (this.sealEnabled && this.channelKey)))
|
||||||
|
const detail = access ? this.focusDetail : null;
|
||||||
|
this.emitter.emit('detail', { cardId, channelId, detail });
|
||||||
}
|
}
|
||||||
|
|
||||||
public disconnect(cardId: string | null, channelId: string) {
|
public disconnect(cardId: string | null, channelId: string) {
|
||||||
if (cardId === this.cardId && channelId === this.channelId) {
|
if (cardId === this.cardId && channelId === this.channelId) {
|
||||||
this.connection = null;
|
this.connection = null;
|
||||||
this.emitStatus();
|
this.emitDetail();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public setDetail(cardId: string | null, channelId: string, detail: FocusDetail) {
|
||||||
|
if (cardId === this.cardId && channelId === this.channelId) {
|
||||||
|
this.focusDetail = detail;
|
||||||
|
this.emitDetail();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -856,6 +874,7 @@ export class FocusModule implements Focus {
|
|||||||
public async setSealEnabled(enable: boolean) {
|
public async setSealEnabled(enable: boolean) {
|
||||||
this.sealEnabled = enable;
|
this.sealEnabled = enable;
|
||||||
this.unsealAll = true;
|
this.unsealAll = true;
|
||||||
|
this.emitDetail();
|
||||||
await this.sync();
|
await this.sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,6 +882,7 @@ export class FocusModule implements Focus {
|
|||||||
if (cardId === this.cardId && channelId === this.channelId) {
|
if (cardId === this.cardId && channelId === this.channelId) {
|
||||||
this.channelKey = channelKey;
|
this.channelKey = channelKey;
|
||||||
this.unsealAll = true;
|
this.unsealAll = true;
|
||||||
|
this.emitDetail();
|
||||||
await this.sync();
|
await this.sync();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -877,11 +897,6 @@ export class FocusModule implements Focus {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private emitStatus() {
|
|
||||||
const status = this.connection ? 'connected' : 'disconnected'
|
|
||||||
this.emitter.emit('status', status);
|
|
||||||
}
|
|
||||||
|
|
||||||
private getTopicData(item: TopicItem): { data: any, assets: AssetItem[] } {
|
private getTopicData(item: TopicItem): { data: any, assets: AssetItem[] } {
|
||||||
const topicDetail = item.detail.sealed ? item.unsealedDetail : item.detail.data;
|
const topicDetail = item.detail.sealed ? item.unsealedDetail : item.detail.data;
|
||||||
const { revision } = item.detail;
|
const { revision } = item.detail;
|
||||||
|
@ -141,6 +141,20 @@ export class StreamModule {
|
|||||||
entry.item.unsealedDetail = null;
|
entry.item.unsealedDetail = null;
|
||||||
await this.unsealChannelDetail(id, entry.item);
|
await this.unsealChannelDetail(id, entry.item);
|
||||||
entry.channel = this.setChannel(id, entry.item);
|
entry.channel = this.setChannel(id, entry.item);
|
||||||
|
if (this.focus) {
|
||||||
|
const { dataType, data, enableImage, enableAudio, enableVideo, enableBinary } = detail;
|
||||||
|
const sealed = dataType === 'sealed';
|
||||||
|
const focusDetail = {
|
||||||
|
sealed,
|
||||||
|
dataType,
|
||||||
|
data: sealed ? entry.item.unsealedDetail : data,
|
||||||
|
enableImage,
|
||||||
|
enableAudio,
|
||||||
|
enableVideo,
|
||||||
|
enableBinary,
|
||||||
|
}
|
||||||
|
this.focus.setDetail(null, id, focusDetail);
|
||||||
|
}
|
||||||
await this.store.setContentChannelDetail(guid, id, entry.item.detail, entry.item.unsealedDetail);
|
await this.store.setContentChannelDetail(guid, id, entry.item.detail, entry.item.unsealedDetail);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -375,8 +389,6 @@ export class StreamModule {
|
|||||||
focus.close();
|
focus.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = this.channelEntries.get(channelId);
|
|
||||||
|
|
||||||
const markRead = async () => {
|
const markRead = async () => {
|
||||||
try {
|
try {
|
||||||
await this.setUnreadChannel(channelId, false);
|
await this.setUnreadChannel(channelId, false);
|
||||||
@ -390,14 +402,25 @@ export class StreamModule {
|
|||||||
await addFlag(node, secure, guid, { channelId, topicId });
|
await addFlag(node, secure, guid, { channelId, topicId });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry) {
|
const entry = this.channelEntries.get(channelId);
|
||||||
const channelKey = entry.item.channelKey;
|
const channelKey = entry ? entry.item.channelKey : null;
|
||||||
|
const revision = entry ? entry.item.summary.revision : 0;
|
||||||
const sealEnabled = Boolean(this.seal);
|
const sealEnabled = Boolean(this.seal);
|
||||||
const revision = entry.item.summary.revision;
|
|
||||||
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, null, channelId, this.guid, { node, secure, token }, channelKey, sealEnabled, revision, markRead, flagTopic);
|
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, null, channelId, this.guid, { node, secure, token }, channelKey, sealEnabled, revision, markRead, flagTopic);
|
||||||
|
|
||||||
|
if (entry) {
|
||||||
|
const { dataType, data, enableImage, enableAudio, enableVideo, enableBinary } = entry.item.detail;
|
||||||
|
const sealed = dataType === 'sealed';
|
||||||
|
const focusDetail = {
|
||||||
|
sealed,
|
||||||
|
dataType,
|
||||||
|
data: sealed ? entry.item.unsealedDetail : data,
|
||||||
|
enableImage,
|
||||||
|
enableAudio,
|
||||||
|
enableVideo,
|
||||||
|
enableBinary,
|
||||||
}
|
}
|
||||||
else {
|
this.focus.setDetail(null, channelId, focusDetail);
|
||||||
this.focus = new FocusModule(this.log, this.store, this.crypto, this.media, null, channelId, this.guid, null, null, false, 0, markRead, flagTopic);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.focus;
|
return this.focus;
|
||||||
@ -542,6 +565,19 @@ export class StreamModule {
|
|||||||
if (item.channelKey) {
|
if (item.channelKey) {
|
||||||
const { data } = await this.crypto.aesDecrypt(subjectEncrypted, subjectIv, item.channelKey);
|
const { data } = await this.crypto.aesDecrypt(subjectEncrypted, subjectIv, item.channelKey);
|
||||||
item.unsealedDetail = data;
|
item.unsealedDetail = data;
|
||||||
|
if (this.focus) {
|
||||||
|
const { dataType, enableImage, enableAudio, enableVideo, enableBinary } = item.detail;
|
||||||
|
const focusDetail = {
|
||||||
|
sealed: true,
|
||||||
|
dataType,
|
||||||
|
data,
|
||||||
|
enableImage,
|
||||||
|
enableAudio,
|
||||||
|
enableVideo,
|
||||||
|
enableBinary,
|
||||||
|
}
|
||||||
|
this.focus.setDetail(null, channelId, focusDetail);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -65,6 +65,16 @@ export type Channel = {
|
|||||||
members: Member[];
|
members: Member[];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type FocusDetail = {
|
||||||
|
sealed: boolean;
|
||||||
|
dataType: string;
|
||||||
|
data: any;
|
||||||
|
enableImage: boolean;
|
||||||
|
enableAudio: boolean;
|
||||||
|
enableVideo: boolean;
|
||||||
|
enableBinary: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
export type Member = {
|
export type Member = {
|
||||||
guid: string;
|
guid: string;
|
||||||
//pushEnabled: boolean;
|
//pushEnabled: boolean;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user