mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 20:49:16 +00:00
refactor of channel view
This commit is contained in:
parent
f0134493db
commit
720537e3d5
@ -146,7 +146,6 @@ export function useCardContext() {
|
|||||||
|
|
||||||
const syncCard = async (token, card) => {
|
const syncCard = async (token, card) => {
|
||||||
const { cardProfile, cardDetail } = card.data;
|
const { cardProfile, cardDetail } = card.data;
|
||||||
|
|
||||||
// sync profile
|
// sync profile
|
||||||
if (card.data.setNotifiedProfile !== card.data.curNotifiedProfile) {
|
if (card.data.setNotifiedProfile !== card.data.curNotifiedProfile) {
|
||||||
if (card.data.profileRevision !== card.data.curNotifiedProfile) {
|
if (card.data.profileRevision !== card.data.curNotifiedProfile) {
|
||||||
@ -174,7 +173,7 @@ export function useCardContext() {
|
|||||||
|
|
||||||
const syncCardChannels = async (card) => {
|
const syncCardChannels = async (card) => {
|
||||||
const { cardProfile, cardDetail } = card.data;
|
const { cardProfile, cardDetail } = card.data;
|
||||||
const { node } = cardProfile.node;
|
const node = cardProfile.node;
|
||||||
const token = `${cardProfile.guid}.${cardDetail.token}`;
|
const token = `${cardProfile.guid}.${cardDetail.token}`;
|
||||||
let delta;
|
let delta;
|
||||||
if (card.data.setNotifiedView !== card.data.curNotifiedView) {
|
if (card.data.setNotifiedView !== card.data.curNotifiedView) {
|
||||||
@ -183,7 +182,7 @@ export function useCardContext() {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const { setNotifiedView, setNotifiedChannel } = card.data;
|
const { setNotifiedView, setNotifiedChannel } = card.data;
|
||||||
delta = await getContactChannels(node, setNotifiedView, setNotifiedChannel);
|
delta = await getContactChannels(node, token, setNotifiedView, setNotifiedChannel);
|
||||||
}
|
}
|
||||||
for (let channel of delta) {
|
for (let channel of delta) {
|
||||||
if (channel.data) {
|
if (channel.data) {
|
||||||
@ -206,7 +205,7 @@ export function useCardContext() {
|
|||||||
cur.data.channelSummary = channel.data.channelSummary;
|
cur.data.channelSummary = channel.data.channelSummary;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
cur.data.channelSummary = getContactChannelSummary(node, token, channel.id);
|
cur.data.channelSummary = await getContactChannelSummary(node, token, channel.id);
|
||||||
}
|
}
|
||||||
cur.data.unsealedSummary = null;
|
cur.data.unsealedSummary = null;
|
||||||
cur.data.topicRevision = channel.data.topicRevision;
|
cur.data.topicRevision = channel.data.topicRevision;
|
||||||
|
@ -47,10 +47,7 @@ export function Channels({ open, active }) {
|
|||||||
</div>
|
</div>
|
||||||
{ state.display === 'small' && (
|
{ state.display === 'small' && (
|
||||||
<div class="inline">
|
<div class="inline">
|
||||||
<div class="add" onClick={actions.setShowAdd}>
|
<Button type="primary" icon={<CommentOutlined />} onClick={actions.setShowAdd}>New</Button>
|
||||||
<CommentOutlined />
|
|
||||||
<div class="label">New</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
@ -68,10 +65,7 @@ export function Channels({ open, active }) {
|
|||||||
</div>
|
</div>
|
||||||
{ state.display !== 'small' && (
|
{ state.display !== 'small' && (
|
||||||
<div class="bar">
|
<div class="bar">
|
||||||
<div class="add" onClick={actions.setShowAdd}>
|
<Button type="primary" icon={<CommentOutlined />} onClick={actions.setShowAdd}>New Topic</Button>
|
||||||
<CommentOutlined />
|
|
||||||
<div class="label">New Topic</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<Modal title="New Topic" centered visible={state.showAdd} footer={addFooter}
|
<Modal title="New Topic" centered visible={state.showAdd} footer={addFooter}
|
||||||
|
@ -6,80 +6,35 @@ import { AppstoreFilled, SolutionOutlined, UnlockOutlined, LockFilled } from '@a
|
|||||||
export function ChannelItem({ item, openChannel, active }) {
|
export function ChannelItem({ item, openChannel, active }) {
|
||||||
|
|
||||||
const itemClass = () => {
|
const itemClass = () => {
|
||||||
if (active.set && active.channel === item.id && active.card === item.cardId) {
|
if (active.set && active.channel === item.channelId && active.card === item.cardId) {
|
||||||
return "active"
|
return "active"
|
||||||
}
|
}
|
||||||
return "idle"
|
return "idle"
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ChannelItemWrapper onClick={() => openChannel(item.id, item.cardId)}>
|
<ChannelItemWrapper onClick={() => openChannel(item.channelId, item.cardId)}>
|
||||||
<div class={itemClass()}>
|
<div class={itemClass()}>
|
||||||
{ item.contacts.length === 0 && (
|
<div class="item">
|
||||||
<div class="item">
|
<div class="avatar">
|
||||||
<div class="logo">
|
<Logo url={item.logo} img={item.img} width={32} height={32} radius={8} />
|
||||||
<SolutionOutlined />
|
|
||||||
</div>
|
|
||||||
<div class="details">
|
|
||||||
<div class="subject">
|
|
||||||
{ item.locked && !item.unlocked && (
|
|
||||||
<LockFilled style={{ paddingRight: 8 }}/>
|
|
||||||
)}
|
|
||||||
{ item.locked && item.unlocked && (
|
|
||||||
<UnlockOutlined style={{ paddingRight: 8 }}/>
|
|
||||||
)}
|
|
||||||
<span>{ item.subject }</span>
|
|
||||||
</div>
|
|
||||||
<div class="message">{ item.message }</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
<div class="details">
|
||||||
{ item.contacts.length === 1 && (
|
<div class="subject">
|
||||||
<div class="item">
|
{ item.locked && !item.unlocked && (
|
||||||
<div class="avatar">
|
<LockFilled style={{ paddingRight: 8 }}/>
|
||||||
<Logo url={item.logo} width={32} height={32} radius={8} />
|
)}
|
||||||
|
{ item.locked && item.unlocked && (
|
||||||
|
<UnlockOutlined style={{ paddingRight: 8 }}/>
|
||||||
|
)}
|
||||||
|
<span>{ item.subject }</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="details">
|
<div class="message">{ item.message }</div>
|
||||||
<div class="subject">
|
|
||||||
{ item.locked && !item.unlocked && (
|
|
||||||
<LockFilled style={{ paddingRight: 8 }}/>
|
|
||||||
)}
|
|
||||||
{ item.locked && item.unlocked && (
|
|
||||||
<UnlockOutlined style={{ paddingRight: 8 }}/>
|
|
||||||
)}
|
|
||||||
<span>{ item.subject }</span>
|
|
||||||
</div>
|
|
||||||
<div class="message">{ item.message }</div>
|
|
||||||
</div>
|
|
||||||
{ item.updated && (
|
|
||||||
<Markup />
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
)}
|
{ item.updatedFlag && (
|
||||||
{ item.contacts.length > 1 && (
|
<Markup />
|
||||||
<div class="item">
|
)}
|
||||||
<div class="logo">
|
</div>
|
||||||
<AppstoreFilled />
|
|
||||||
</div>
|
|
||||||
<div class="details">
|
|
||||||
<div class="subject">
|
|
||||||
{ item.locked && !item.unlocked && (
|
|
||||||
<LockFilled style={{ paddingRight: 8 }}/>
|
|
||||||
)}
|
|
||||||
{ item.locked && item.unlocked && (
|
|
||||||
<UnlockOutlined style={{ paddingRight: 8 }}/>
|
|
||||||
)}
|
|
||||||
<span>{ item.subject }</span>
|
|
||||||
</div>
|
|
||||||
<div class="message">{ item.message }</div>
|
|
||||||
</div>
|
|
||||||
{ item.updated && (
|
|
||||||
<Tooltip placement="right" title="new message">
|
|
||||||
<Markup />
|
|
||||||
</Tooltip>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
</ChannelItemWrapper>
|
</ChannelItemWrapper>
|
||||||
)
|
)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { useContext, useState, useEffect } from 'react';
|
import { useContext, useState, useEffect, useRef } from 'react';
|
||||||
import { StoreContext } from 'context/StoreContext';
|
import { StoreContext } from 'context/StoreContext';
|
||||||
import { ChannelContext } from 'context/ChannelContext';
|
import { ChannelContext } from 'context/ChannelContext';
|
||||||
import { CardContext } from 'context/CardContext';
|
import { CardContext } from 'context/CardContext';
|
||||||
@ -118,162 +118,148 @@ export function useChannels() {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const setUpdated = (chan) => {
|
// TODO optimize (avoid rebuild object when not needed)
|
||||||
|
const getChannel = (cardId, channelId, value) => {
|
||||||
|
const chan = {};
|
||||||
|
chan.cardId = cardId;
|
||||||
|
chan.channelId = channelId;
|
||||||
|
chan.revision = value.revision;
|
||||||
|
chan.updated = value.data?.channelSummary?.lastTopic?.created;
|
||||||
|
|
||||||
|
// set updated flag
|
||||||
|
const key = `${cardId}:${channelId}`
|
||||||
const login = store.state['login:timestamp'];
|
const login = store.state['login:timestamp'];
|
||||||
const update = chan?.data?.channelSummary?.lastTopic?.created;
|
if (!chan.updated || !login || chan.updated < login) {
|
||||||
|
chan.updatedFlag = false;
|
||||||
if (!update || (login && update < login)) {
|
|
||||||
chan.updated = false;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else if (store.state[key] && store.state[key] === value.revision) {
|
||||||
let key = `${chan.id}::${chan.cardId}`
|
chan.updatedFlag = false;
|
||||||
if (store.state[key] && store.state[key] === chan.revision) {
|
|
||||||
chan.updated = false;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
chan.updated = true;
|
chan.updatedFlag = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const setContacts = (chan) => {
|
// extract member info
|
||||||
let contacts = [];
|
let memberCount = 0;
|
||||||
if (chan.guid != null && profile.state.identity.guid !== chan.guid) {
|
let names = [];
|
||||||
const contact = getCardByGuid(card.state.cards, chan.guid);
|
let img = null;
|
||||||
contacts.push(contact);
|
let logo = null;
|
||||||
|
if (cardId) {
|
||||||
|
const contact = card.state.cards.get(cardId);
|
||||||
|
const profile = contact?.data?.cardProfile;
|
||||||
|
if (profile?.name) {
|
||||||
|
names.push(profile.name);
|
||||||
|
}
|
||||||
|
if (profile?.imageSet) {
|
||||||
|
img = null;
|
||||||
|
logo = card.actions.getCardImageUrl(contact.id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
img = 'avatar';
|
||||||
|
logo = null;
|
||||||
|
}
|
||||||
|
memberCount++;
|
||||||
}
|
}
|
||||||
for (let guid of chan.data.channelDetail?.members) {
|
for (let guid of value?.data?.channelDetail?.members) {
|
||||||
if (guid !== profile.state.identity.guid) {
|
if (guid !== profile.state.identity.guid) {
|
||||||
const contact = getCardByGuid(card.state.cards, guid);
|
const contact = getCardByGuid(card.state.cards, guid);
|
||||||
contacts.push(contact);
|
const profile = contact?.data?.cardProfile;
|
||||||
|
if (profile?.name) {
|
||||||
|
names.push(profile.name);
|
||||||
|
}
|
||||||
|
if (profile?.imageSet) {
|
||||||
|
img = null;
|
||||||
|
logo = card.actions.getCardImageUrl(contact.id);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
img = 'avatar';
|
||||||
|
logo = null;
|
||||||
|
}
|
||||||
|
memberCount++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
chan.contacts = contacts;
|
|
||||||
if (contacts.length === 1 && contacts[0]) {
|
|
||||||
chan.logo = card.actions.getCardImageUrl(contacts[0].id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const setSubject = (chan) => {
|
// set logo and label
|
||||||
let subject = "";
|
if (memberCount === 0) {
|
||||||
if (chan.data.channelDetail.dataType === 'sealed') {
|
chan.img = 'solution';
|
||||||
chan.locked = chan.data.channelDetail.dataType === 'sealed'
|
chan.label = 'Notes';
|
||||||
if (state.sealable) {
|
}
|
||||||
try {
|
else if (memberCount === 1) {
|
||||||
if (chan.data.unsealedChannel == null) {
|
chan.logo = logo;
|
||||||
if (chan.cardId) {
|
chan.img = img;
|
||||||
card.actions.unsealChannelSubject(chan.cardId, chan.id, account.state.sealKey);
|
chan.label = names.join(',');
|
||||||
}
|
|
||||||
else {
|
|
||||||
channel.actions.unsealChannelSubject(chan.id, account.state.sealKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (chan.cardId) {
|
|
||||||
chan.unlocked = card.actions.isUnsealed(chan.cardId, chan.id, account.state.sealKey);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
chan.unlocked = channel.actions.isUnsealed(chan.id, account.state.sealKey);
|
|
||||||
}
|
|
||||||
subject = chan.data.unsealedChannel.subject;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (chan.data.channelDetail?.data) {
|
chan.img = 'appstore';
|
||||||
try {
|
chan.label = names.join(',');
|
||||||
subject = JSON.parse(chan.data.channelDetail?.data).subject;
|
|
||||||
}
|
|
||||||
catch (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!subject) {
|
|
||||||
let names = [];
|
|
||||||
for (let contact of chan.contacts) {
|
|
||||||
names.push(contact?.data?.cardProfile?.name);
|
|
||||||
}
|
|
||||||
subject = names.join(", ");
|
|
||||||
}
|
|
||||||
if (!subject && !chan.contacts?.length) {
|
|
||||||
subject = "Notes";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
chan.subject = subject;
|
// set subject
|
||||||
}
|
const detail = value.data?.channelDetail;
|
||||||
|
if (detail?.dataType === 'sealedchannel') {
|
||||||
const setMessage = (chan) => {
|
// handle sealed subject
|
||||||
let message = '';
|
chan.locked = true;
|
||||||
if (chan.data.channelSummary?.lastTopic?.dataType === 'superbasictopic') {
|
chan.unlocked = false;
|
||||||
|
}
|
||||||
|
else if (detail?.dataType === 'superbasic') {
|
||||||
|
chan.locked = false;
|
||||||
|
chan.unlocked = true;
|
||||||
try {
|
try {
|
||||||
message = JSON.parse(chan.data.channelSummary.lastTopic.data).text;
|
const data = JSON.parse(detail.data);
|
||||||
|
chan.subject = data.subject;
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch(err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (chan.data.channelSummary?.lastTopic?.dataType === 'sealedtopic') {
|
if (chan.subject == null) {
|
||||||
|
chan.subject = chan.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set message
|
||||||
|
const topic = value.data?.channelSummary?.lastTopic;
|
||||||
|
if (topic?.dataType === 'sealedtopic') {
|
||||||
|
// handle sealed topic
|
||||||
|
}
|
||||||
|
else if (topic?.dataType === 'superbasictopic') {
|
||||||
try {
|
try {
|
||||||
if (chan.unlocked) {
|
const data = JSON.parse(topic.data);
|
||||||
message = "...";
|
chan.message = data.text;
|
||||||
if (chan.data.unsealedSummary == null) {
|
|
||||||
if (chan.cardId) {
|
|
||||||
card.actions.unsealChannelSummary(chan.cardId, chan.id, account.state.sealKey);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
channel.actions.unsealChannelSummary(chan.id, account.state.sealKey);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (typeof chan.data.unsealedSummary.message.text === 'string') {
|
|
||||||
message = chan.data.unsealedSummary.message.text;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (err) {
|
catch(err) {
|
||||||
console.log(err)
|
console.log(err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof message === 'string') {
|
return chan;
|
||||||
chan.message = message;
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let merged = [];
|
const merged = [];
|
||||||
card.state.cards.forEach((value, key, map) => {
|
card.state.cards.forEach((cardValue, cardKey) => {
|
||||||
merged.push(...Array.from(value.channels.values()));
|
cardValue.channels.forEach((channelValue, channelKey) => {
|
||||||
|
const chan = getChannel(cardKey, channelKey, channelValue);
|
||||||
|
merged.push(chan);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
channel.state.channels.forEach((channelValue, channelKey) => {
|
||||||
|
merged.push(getChannel(null, channelKey, channelValue));
|
||||||
});
|
});
|
||||||
merged.push(...Array.from(channel.state.channels.values()));
|
|
||||||
|
|
||||||
merged.sort((a, b) => {
|
merged.sort((a, b) => {
|
||||||
const aCreated = a?.data?.channelSummary?.lastTopic?.created;
|
const aUpdated = a.updated;
|
||||||
const bCreated = b?.data?.channelSummary?.lastTopic?.created;
|
const bUpdated = b.updated;
|
||||||
if (aCreated === bCreated) {
|
if (aUpdated === bUpdated) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (!aCreated || aCreated < bCreated) {
|
if (!aUpdated || aUpdated < bUpdated) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
});
|
});
|
||||||
|
|
||||||
merged.forEach(chan => {
|
|
||||||
setUpdated(chan);
|
|
||||||
setContacts(chan);
|
|
||||||
setSubject(chan);
|
|
||||||
setMessage(chan);
|
|
||||||
});
|
|
||||||
|
|
||||||
const filtered = merged.filter((chan) => {
|
const filtered = merged.filter((chan) => {
|
||||||
let subject = chan?.subject?.toUpperCase();
|
const subject = chan?.subject?.toUpperCase();
|
||||||
return !filter || subject?.includes(filter);
|
return !filter || subject?.includes(filter);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -29,7 +29,6 @@ export function useSession() {
|
|||||||
const card = useContext(CardContext);
|
const card = useContext(CardContext);
|
||||||
const store = useContext(StoreContext);
|
const store = useContext(StoreContext);
|
||||||
const viewport = useContext(ViewportContext);
|
const viewport = useContext(ViewportContext);
|
||||||
const channel = useContext(ChannelContext);
|
|
||||||
const profile = useContext(ProfileContext);
|
const profile = useContext(ProfileContext);
|
||||||
|
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
@ -48,7 +47,7 @@ export function useSession() {
|
|||||||
else {
|
else {
|
||||||
updateState({ loading: false });
|
updateState({ loading: false });
|
||||||
}
|
}
|
||||||
}, [card, channel, profile]);
|
}, [profile]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!app.state.status) {
|
if (!app.state.status) {
|
||||||
|
Loading…
Reference in New Issue
Block a user