mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +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 { cardProfile, cardDetail } = card.data;
|
||||
|
||||
// sync profile
|
||||
if (card.data.setNotifiedProfile !== card.data.curNotifiedProfile) {
|
||||
if (card.data.profileRevision !== card.data.curNotifiedProfile) {
|
||||
@ -174,7 +173,7 @@ export function useCardContext() {
|
||||
|
||||
const syncCardChannels = async (card) => {
|
||||
const { cardProfile, cardDetail } = card.data;
|
||||
const { node } = cardProfile.node;
|
||||
const node = cardProfile.node;
|
||||
const token = `${cardProfile.guid}.${cardDetail.token}`;
|
||||
let delta;
|
||||
if (card.data.setNotifiedView !== card.data.curNotifiedView) {
|
||||
@ -183,7 +182,7 @@ export function useCardContext() {
|
||||
}
|
||||
else {
|
||||
const { setNotifiedView, setNotifiedChannel } = card.data;
|
||||
delta = await getContactChannels(node, setNotifiedView, setNotifiedChannel);
|
||||
delta = await getContactChannels(node, token, setNotifiedView, setNotifiedChannel);
|
||||
}
|
||||
for (let channel of delta) {
|
||||
if (channel.data) {
|
||||
@ -206,7 +205,7 @@ export function useCardContext() {
|
||||
cur.data.channelSummary = channel.data.channelSummary;
|
||||
}
|
||||
else {
|
||||
cur.data.channelSummary = getContactChannelSummary(node, token, channel.id);
|
||||
cur.data.channelSummary = await getContactChannelSummary(node, token, channel.id);
|
||||
}
|
||||
cur.data.unsealedSummary = null;
|
||||
cur.data.topicRevision = channel.data.topicRevision;
|
||||
|
@ -47,10 +47,7 @@ export function Channels({ open, active }) {
|
||||
</div>
|
||||
{ state.display === 'small' && (
|
||||
<div class="inline">
|
||||
<div class="add" onClick={actions.setShowAdd}>
|
||||
<CommentOutlined />
|
||||
<div class="label">New</div>
|
||||
</div>
|
||||
<Button type="primary" icon={<CommentOutlined />} onClick={actions.setShowAdd}>New</Button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
@ -68,10 +65,7 @@ export function Channels({ open, active }) {
|
||||
</div>
|
||||
{ state.display !== 'small' && (
|
||||
<div class="bar">
|
||||
<div class="add" onClick={actions.setShowAdd}>
|
||||
<CommentOutlined />
|
||||
<div class="label">New Topic</div>
|
||||
</div>
|
||||
<Button type="primary" icon={<CommentOutlined />} onClick={actions.setShowAdd}>New Topic</Button>
|
||||
</div>
|
||||
)}
|
||||
<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 }) {
|
||||
|
||||
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 "idle"
|
||||
};
|
||||
|
||||
return (
|
||||
<ChannelItemWrapper onClick={() => openChannel(item.id, item.cardId)}>
|
||||
<ChannelItemWrapper onClick={() => openChannel(item.channelId, item.cardId)}>
|
||||
<div class={itemClass()}>
|
||||
{ item.contacts.length === 0 && (
|
||||
<div class="item">
|
||||
<div class="logo">
|
||||
<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 class="item">
|
||||
<div class="avatar">
|
||||
<Logo url={item.logo} img={item.img} width={32} height={32} radius={8} />
|
||||
</div>
|
||||
)}
|
||||
{ item.contacts.length === 1 && (
|
||||
<div class="item">
|
||||
<div class="avatar">
|
||||
<Logo url={item.logo} width={32} height={32} radius={8} />
|
||||
<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="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 && (
|
||||
<Markup />
|
||||
)}
|
||||
<div class="message">{ item.message }</div>
|
||||
</div>
|
||||
)}
|
||||
{ item.contacts.length > 1 && (
|
||||
<div class="item">
|
||||
<div class="logo">
|
||||
<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>
|
||||
)}
|
||||
{ item.updatedFlag && (
|
||||
<Markup />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</ChannelItemWrapper>
|
||||
)
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { useContext, useState, useEffect } from 'react';
|
||||
import { useContext, useState, useEffect, useRef } from 'react';
|
||||
import { StoreContext } from 'context/StoreContext';
|
||||
import { ChannelContext } from 'context/ChannelContext';
|
||||
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 update = chan?.data?.channelSummary?.lastTopic?.created;
|
||||
|
||||
if (!update || (login && update < login)) {
|
||||
chan.updated = false;
|
||||
return;
|
||||
if (!chan.updated || !login || chan.updated < login) {
|
||||
chan.updatedFlag = false;
|
||||
}
|
||||
|
||||
let key = `${chan.id}::${chan.cardId}`
|
||||
if (store.state[key] && store.state[key] === chan.revision) {
|
||||
chan.updated = false;
|
||||
else if (store.state[key] && store.state[key] === value.revision) {
|
||||
chan.updatedFlag = false;
|
||||
}
|
||||
else {
|
||||
chan.updated = true;
|
||||
chan.updatedFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
const setContacts = (chan) => {
|
||||
let contacts = [];
|
||||
if (chan.guid != null && profile.state.identity.guid !== chan.guid) {
|
||||
const contact = getCardByGuid(card.state.cards, chan.guid);
|
||||
contacts.push(contact);
|
||||
// extract member info
|
||||
let memberCount = 0;
|
||||
let names = [];
|
||||
let img = null;
|
||||
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) {
|
||||
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) => {
|
||||
let subject = "";
|
||||
if (chan.data.channelDetail.dataType === 'sealed') {
|
||||
chan.locked = chan.data.channelDetail.dataType === 'sealed'
|
||||
if (state.sealable) {
|
||||
try {
|
||||
if (chan.data.unsealedChannel == null) {
|
||||
if (chan.cardId) {
|
||||
card.actions.unsealChannelSubject(chan.cardId, chan.id, account.state.sealKey);
|
||||
}
|
||||
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)
|
||||
}
|
||||
}
|
||||
// set logo and label
|
||||
if (memberCount === 0) {
|
||||
chan.img = 'solution';
|
||||
chan.label = 'Notes';
|
||||
}
|
||||
else if (memberCount === 1) {
|
||||
chan.logo = logo;
|
||||
chan.img = img;
|
||||
chan.label = names.join(',');
|
||||
}
|
||||
else {
|
||||
if (chan.data.channelDetail?.data) {
|
||||
try {
|
||||
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.img = 'appstore';
|
||||
chan.label = names.join(',');
|
||||
}
|
||||
|
||||
chan.subject = subject;
|
||||
}
|
||||
|
||||
const setMessage = (chan) => {
|
||||
let message = '';
|
||||
if (chan.data.channelSummary?.lastTopic?.dataType === 'superbasictopic') {
|
||||
// set subject
|
||||
const detail = value.data?.channelDetail;
|
||||
if (detail?.dataType === 'sealedchannel') {
|
||||
// handle sealed subject
|
||||
chan.locked = true;
|
||||
chan.unlocked = false;
|
||||
}
|
||||
else if (detail?.dataType === 'superbasic') {
|
||||
chan.locked = false;
|
||||
chan.unlocked = true;
|
||||
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);
|
||||
}
|
||||
}
|
||||
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 {
|
||||
if (chan.unlocked) {
|
||||
message = "...";
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
const data = JSON.parse(topic.data);
|
||||
chan.message = data.text;
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err)
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof message === 'string') {
|
||||
chan.message = message;
|
||||
}
|
||||
}
|
||||
return chan;
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
let merged = [];
|
||||
card.state.cards.forEach((value, key, map) => {
|
||||
merged.push(...Array.from(value.channels.values()));
|
||||
const merged = [];
|
||||
card.state.cards.forEach((cardValue, cardKey) => {
|
||||
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) => {
|
||||
const aCreated = a?.data?.channelSummary?.lastTopic?.created;
|
||||
const bCreated = b?.data?.channelSummary?.lastTopic?.created;
|
||||
if (aCreated === bCreated) {
|
||||
const aUpdated = a.updated;
|
||||
const bUpdated = b.updated;
|
||||
if (aUpdated === bUpdated) {
|
||||
return 0;
|
||||
}
|
||||
if (!aCreated || aCreated < bCreated) {
|
||||
if (!aUpdated || aUpdated < bUpdated) {
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
});
|
||||
|
||||
merged.forEach(chan => {
|
||||
setUpdated(chan);
|
||||
setContacts(chan);
|
||||
setSubject(chan);
|
||||
setMessage(chan);
|
||||
});
|
||||
|
||||
const filtered = merged.filter((chan) => {
|
||||
let subject = chan?.subject?.toUpperCase();
|
||||
const subject = chan?.subject?.toUpperCase();
|
||||
return !filter || subject?.includes(filter);
|
||||
});
|
||||
|
||||
|
@ -29,7 +29,6 @@ export function useSession() {
|
||||
const card = useContext(CardContext);
|
||||
const store = useContext(StoreContext);
|
||||
const viewport = useContext(ViewportContext);
|
||||
const channel = useContext(ChannelContext);
|
||||
const profile = useContext(ProfileContext);
|
||||
|
||||
const navigate = useNavigate();
|
||||
@ -48,7 +47,7 @@ export function useSession() {
|
||||
else {
|
||||
updateState({ loading: false });
|
||||
}
|
||||
}, [card, channel, profile]);
|
||||
}, [profile]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!app.state.status) {
|
||||
|
Loading…
Reference in New Issue
Block a user