more context refactor

This commit is contained in:
Roland Osborne 2022-04-25 14:29:57 -07:00
parent a10050b118
commit cfb827db3a
12 changed files with 138 additions and 334 deletions

View File

@ -1,7 +1,7 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil'; import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelTopic(token, channelId, topicId) { export async function getContactChannelTopic(server, token, channelId, topicId) {
let topic = await fetchWithTimeout(`/content/channels/${channelId}/topics/${topicId}/detail?contact=${token}`, let topic = await fetchWithTimeout(`https://${server}/content/channels/${channelId}/topics/${topicId}/detail?contact=${token}`,
{ method: 'GET' }); { method: 'GET' });
checkResponse(topic) checkResponse(topic)
return await topic.json() return await topic.json()

View File

@ -1,11 +1,11 @@
import { checkResponse, fetchWithTimeout } from './fetchUtil'; import { checkResponse, fetchWithTimeout } from './fetchUtil';
export async function getContactChannelTopics(token, channelId, revision) { export async function getContactChannelTopics(server, token, channelId, revision) {
let rev = '' let rev = ''
if (revision != null) { if (revision != null) {
rev = `&revision=${revision}` rev = `&revision=${revision}`
} }
let topics = await fetchWithTimeout(`/content/channels/${channelId}/topics?contact=${token}${rev}`, let topics = await fetchWithTimeout(`https://${server}/content/channels/${channelId}/topics?contact=${token}${rev}`,
{ method: 'GET' }); { method: 'GET' });
checkResponse(topics) checkResponse(topics)
return await topics.json() return await topics.json()

View File

@ -1,10 +1,5 @@
import { useEffect, useState, useRef, useContext } from 'react'; import { useEffect, useState, useRef, useContext } from 'react';
import { getContactProfile, setCardProfile, getCards, getCardImageUrl, getCardProfile, getCardDetail, getListingImageUrl, getListing, getAvailable, getUsername, setLogin, createAccount } from './fetchUtil'; import { getAvailable, getUsername, setLogin, createAccount } from './fetchUtil';
import { getChannels } from '../Api/getChannels';
import { getChannel } from '../Api/getChannel';
import { getContactChannels } from '../Api/getContactChannels';
import { getContactChannel } from '../Api/getContactChannel';
import { AccountContext } from './AccountContext'; import { AccountContext } from './AccountContext';
import { ProfileContext } from './ProfileContext'; import { ProfileContext } from './ProfileContext';
import { ArticleContext } from './ArticleContext'; import { ArticleContext } from './ArticleContext';
@ -12,146 +7,6 @@ import { GroupContext } from './GroupContext';
import { CardContext } from './CardContext'; import { CardContext } from './CardContext';
import { ChannelContext } from './ChannelContext'; import { ChannelContext } from './ChannelContext';
async function updateChannels(token, revision, channelMap, mergeChannels) {
let channels = await getChannels(token, revision);
for (let channel of channels) {
if (channel.data) {
let cur = channelMap.get(channel.id);
if (cur == null) {
cur = { id: channel.id, data: { } }
}
if (cur.data.detailRevision != channel.data.detailRevision) {
if (channel.data.channelDetail != null) {
cur.data.channelDetail = channel.data.channelDetail;
cur.data.detailRevision = channel.data.detailRevision;
}
else {
let slot = await getChannel(token, channel.id);
cur.data.channelDetail = slot.data.channelDetail;
cur.data.detailRevision = slot.data.detailRevision;
}
}
cur.data.topicRevision = channel.data.topicRevision;
cur.revision = channel.revision;
channelMap.set(channel.id, cur);
}
else {
channelMap.delete(channel.id);
}
}
mergeChannels();
}
async function updateCards(token, revision, cardMap, updateData, mergeChannels) {
let cards = await getCards(token, revision);
for (let card of cards) {
if (card.data) {
let cur = cardMap.get(card.id);
if (cur == null) {
cur = { id: card.id, data: { articles: new Map() }, channels: new Map() }
}
if (cur.data.detailRevision != card.data.detailRevision) {
if (card.data.cardDetail != null) {
cur.data.cardDetail = card.data.cardDetail;
}
else {
cur.data.cardDetail = await getCardDetail(token, card.id);
}
mergeChannels();
cur.data.detailRevision = card.data.detailRevision;
}
if (cur.data.profileRevision != card.data.profileRevision) {
if (card.data.cardProfile != null) {
cur.data.cardProfile = card.data.cardProfile;
}
else {
cur.data.cardProfile = await getCardProfile(token, card.id);
}
cur.data.profileRevision = card.data.profileRevision;
}
const { cardDetail, cardProfile } = cur.data;
if (cardDetail.status === 'connected') {
if (cur.data.profileRevision != card.data.notifiedProfile) {
let message = await getContactProfile(cardProfile.node, cardProfile.guid, cardDetail.token);
await setCardProfile(token, card.id, message);
// update remote profile
cur.data.notifiedProfile = card.data.notifiedProfile;
}
if (cur.data.notifiedView != card.data.notifiedView) {
// update remote articles and channels
cur.data.articles = new Map();
cur.channels = new Map();
let contactToken = cur.data.cardProfile.guid + "." + cur.data.cardDetail.token
await updateContactChannels(contactToken, cur.data.notifiedView, cur.dataNotifiedChannel, cur.channels);
await updateContactArticles(contactToken, cur.data.notifiedView, cur.dataNotifiedArticle, cur.data.articles);
// update view
cur.data.notifiedArticle = card.data.notifiedArticle;
cur.data.notifiedChannel = card.data.notifiedChannel;
cur.data.notifiedView = card.data.notifiedView;
mergeChannels();
}
if (cur.data.notifiedArticle != card.data.notifiedArticle) {
// update remote articles
let contactToken = cur.data.cardProfile.guid + "." + cur.data.cardDetail.token
await updateContactArticles(contactToken, cur.data.notifiedView, cur.dataNotifiedArticle, cur.data.articles);
cur.data.notifiedArticle = card.data.notifiedArticle;
}
if (cur.data.notifiedChannel != card.data.notifiedChannel) {
// update remote channels
let contactToken = cur.data.cardProfile.guid + "." + cur.data.cardDetail.token
await updateContactChannels(contactToken, cur.data.notifiedView, cur.dataNotifiedChannel, cur.channels);
cur.data.notifiedChannel = card.data.notifiedChannel;
mergeChannels();
}
}
cur.revision = card.revision;
cardMap.set(card.id, cur);
}
else {
cardMap.delete(card.id);
mergeChannels();
}
}
updateData({ cards: Array.from(cardMap.values()) });
}
async function updateContactChannels(token, viewRevision, channelRevision, channelMap) {
let channels = await getContactChannels(token, viewRevision, channelRevision);
for (let channel of channels) {
if (channel.data) {
let cur = channelMap.get(channel.id);
if (cur == null) {
cur = { id: channel.id, data: { } }
}
if (cur.data.detailRevision != channel.data.detailRevision) {
if (channel.data.channelDetail != null) {
cur.data.channelDetail = channel.data.channelDetail;
cur.data.detailRevision = channel.data.detailRevision;
}
else {
let slot = await getContactChannel(token, channel.id);
cur.data.channelDetail = slot.data.channelDetail;
cur.data.detailRevision = slot.data.detailRevision;
}
}
cur.data.topicRevision = channel.data.topicRevision;
cur.revision = channel.revision;
channelMap.set(channel.id, cur);
}
else {
channelMap.delete(channel.id);
}
}
}
async function updateContactArticles(token, viewRevision, articleRevision, articleMap) {
console.log("update contact attributes");
}
async function appCreate(username, password, updateState, setWebsocket) { async function appCreate(username, password, updateState, setWebsocket) {
await createAccount(username, password); await createAccount(username, password);
let access = await setLogin(username, password) let access = await setLogin(username, password)
@ -177,15 +32,10 @@ export function useAppContext() {
const [state, setState] = useState(null); const [state, setState] = useState(null);
const [appRevision, setAppRevision] = useState(); const [appRevision, setAppRevision] = useState();
const cardRevision = useRef(null);
const channelRevision = useRef(null);
const channels = useRef(new Map());
const cards = useRef(new Map());
const delay = useRef(2); const delay = useRef(2);
const ws = useRef(null); const ws = useRef(null);
const revision = useRef(null); const revision = useRef(null);
const updateState = (value) => { const updateState = (value) => {
setState((s) => ({ ...s, ...value })) setState((s) => ({ ...s, ...value }))
} }
@ -203,46 +53,8 @@ export function useAppContext() {
const groupContext = useContext(GroupContext); const groupContext = useContext(GroupContext);
const articleContext = useContext(ArticleContext); const articleContext = useContext(ArticleContext);
const mergeChannels = () => {
let merged = [];
cards.current.forEach((value, key, map) => {
if (value?.data?.cardDetail?.status === 'connected') {
value.channels.forEach((slot, key, map) => {
merged.push({ guid: value?.data?.cardProfile?.guid, cardId: value?.id, channel: slot });
});
}
});
channels.current.forEach((value, key, map) => {
merged.push({ channel: value });
});
updateData({ channels: merged });
}
const getCardByGuid = (guid) => {
let card = null;
cards.current.forEach((value, key, map) => {
if(value?.data?.cardProfile?.guid == guid) {
card = value
}
});
return card;
}
const getConnectedCards = () => {
let connected = []
cards.current.forEach((value, key, map) => {
if(value?.data?.cardDetail?.status === 'connected') {
connected.push(value);
}
});
return connected;
}
const resetData = () => { const resetData = () => {
revision.current = null; revision.current = null;
cardRevision.current = null;
channels.current = new Map();
cards.current = new Map();
setState({}); setState({});
} }
@ -251,13 +63,6 @@ export function useAppContext() {
appLogout(updateState, clearWebsocket); appLogout(updateState, clearWebsocket);
resetData(); resetData();
}, },
getRegistry: async (node) => getListing(node),
getRegistryImageUrl: (server, guid, revision) => getListingImageUrl(server, guid, revision),
getCardImageUrl: (cardId, revision) => getCardImageUrl(state.token, cardId, revision),
getCardByGuid: getCardByGuid,
getCard: (id) => cards.current.get(id),
getChannel: (id) => channels.current.get(id),
getConnectedCards: getConnectedCards,
} }
const adminActions = { const adminActions = {
@ -289,29 +94,6 @@ export function useAppContext() {
} }
}, [appRevision]); }, [appRevision]);
const processRevision = async (token) => {
while(revision.current != null) {
let rev = revision.current;
// update card if revision changed
if (rev.card != cardRevision.current) {
await updateCards(token, cardRevision.current, cards.current, updateData, mergeChannels);
cardRevision.current = rev.card
}
// update channel if revision changed
if (rev.channel != channelRevision.current) {
await updateChannels(token, channelRevision.current, channels.current, mergeChannels);
channelRevision.current = rev.channel
}
// check if new revision was received during processing
if (rev == revision.current) {
revision.current = null
}
}
}
const setWebsocket = (token) => { const setWebsocket = (token) => {
accountContext.actions.setToken(token); accountContext.actions.setToken(token);
@ -324,15 +106,8 @@ export function useAppContext() {
ws.current = new WebSocket("wss://" + window.location.host + "/status"); ws.current = new WebSocket("wss://" + window.location.host + "/status");
ws.current.onmessage = (ev) => { ws.current.onmessage = (ev) => {
try { try {
if (revision.current != null) { let rev = JSON.parse(ev.data);
revision.current = JSON.parse(ev.data); setAppRevision(rev);
}
else {
let rev = JSON.parse(ev.data);
revision.current = rev;
processRevision(token);
setAppRevision(rev);
}
} }
catch (err) { catch (err) {
console.log(err); console.log(err);

View File

@ -13,6 +13,8 @@ import { getCardOpenMessage } from '../Api/getCardOpenMessage';
import { setCardOpenMessage } from '../Api/setCardOpenMessage'; import { setCardOpenMessage } from '../Api/setCardOpenMessage';
import { getCardCloseMessage } from '../Api/getCardCloseMessage'; import { getCardCloseMessage } from '../Api/getCardCloseMessage';
import { setCardCloseMessage } from '../Api/setCardCloseMessage'; import { setCardCloseMessage } from '../Api/setCardCloseMessage';
import { getContactChannelTopics } from '../Api/getContactChannelTopics';
import { getContactChannelTopic } from '../Api/getContactChannelTopic';
import { addCard } from '../Api/addCard'; import { addCard } from '../Api/addCard';
import { removeCard } from '../Api/removeCard'; import { removeCard } from '../Api/removeCard';
@ -69,8 +71,8 @@ export function useCardContext() {
cur.data.articles = new Map(); cur.data.articles = new Map();
cur.channels = new Map(); cur.channels = new Map();
await updateContactChannels(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.dataNotifiedChannel, cur.channels); await updateContactChannels(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.data.notifiedChannel, cur.channels);
await updateContactArticles(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.dataNotifiedArticle, cur.data.articles); await updateContactArticles(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.data.notifiedArticle, cur.data.articles);
// update view // update view
cur.data.notifiedArticle = card.data.notifiedArticle; cur.data.notifiedArticle = card.data.notifiedArticle;
@ -79,16 +81,19 @@ export function useCardContext() {
} }
if (cur.data.notifiedArticle != card.data.notifiedArticle) { if (cur.data.notifiedArticle != card.data.notifiedArticle) {
// update remote articles // update remote articles
await updateContactArticles(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.dataNotifiedArticle, cur.data.articles); await updateContactArticles(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.data.notifiedArticle, cur.data.articles);
cur.data.notifiedArticle = card.data.notifiedArticle; cur.data.notifiedArticle = card.data.notifiedArticle;
} }
if (cur.data.notifiedChannel != card.data.notifiedChannel) { if (cur.data.notifiedChannel != card.data.notifiedChannel) {
// update remote channels // update remote channels
await updateContactChannels(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.dataNotifiedChannel, cur.channels); console.log("UPDATE CHANNEL: ", cur.data.notifiedChannel, card.data.notifiedChannel);
await updateContactChannels(card.id, cur.data.cardProfile.guid, cur.data.cardDetail.token, cur.data.notifiedView, cur.data.notifiedChannel, cur.channels);
cur.data.notifiedChannel = card.data.notifiedChannel; cur.data.notifiedChannel = card.data.notifiedChannel;
} }
} }
cur.revision = card.revision; cur.revision = card.revision;
console.log("SAVE:", cur.data.notifiedChannel);
cards.current.set(card.id, cur); cards.current.set(card.id, cur);
} }
else { else {
@ -98,6 +103,8 @@ export function useCardContext() {
} }
const updateContactChannels = async (cardId, guid, token, viewRevision, channelRevision, channelMap) => { const updateContactChannels = async (cardId, guid, token, viewRevision, channelRevision, channelMap) => {
console.log("UPDATE CONTACT CHANNELS: ", viewRevision, channelRevision);
let delta = await getContactChannels(guid + "." + token, viewRevision, channelRevision); let delta = await getContactChannels(guid + "." + token, viewRevision, channelRevision);
for (let channel of delta) { for (let channel of delta) {
if (channel.data) { if (channel.data) {
@ -132,12 +139,15 @@ export function useCardContext() {
const setCards = async (rev) => { const setCards = async (rev) => {
if (next.current == null) { if (next.current == null) {
await updateCards(); next.current = rev;
updateState({ cards: cards.current }); if (revision.current != rev) {
revision.current = rev; await updateCards();
if (next.current != null) { updateState({ cards: cards.current });
let r = next.current; revision.current = rev;
next.current = null; }
let r = next.current;
next.current = null;
if (revision.current != r) {
setCards(r); setCards(r);
} }
} }
@ -164,13 +174,35 @@ export function useCardContext() {
setCards(rev); setCards(rev);
}, },
getCardByGuid: getCardByGuid, getCardByGuid: getCardByGuid,
getImageUrl: (cardId, rev) => getCardImageUrl(access.current, cardId, rev), getImageUrl: (cardId) => {
let { data } = cards.current.get(cardId);
return getCardImageUrl(access.current, cardId, data.profileRevision)
},
addChannelTopic: async (cardId, channelId, message, assets) => { addChannelTopic: async (cardId, channelId, message, assets) => {
let { cardProfile, cardDetail } = cards.current.get(cardId).data; let { cardProfile, cardDetail } = cards.current.get(cardId).data;
let token = cardProfile.guid + '.' + cardDetail.token; let token = cardProfile.guid + '.' + cardDetail.token;
let node = cardProfile.node; let node = cardProfile.node;
await addContactChannelTopic(node, token, channelId, message, assets); await addContactChannelTopic(node, token, channelId, message, assets);
}, },
getChannelRevision: (cardId, channelId) => {
let card = cards.current.get(cardId);
let channel = card.channels.get(channelId);
return channel.revision;
},
getChannelTopics: async (cardId, channelId, revision) => {
let card = cards.current.get(cardId);
let node = card.data.cardProfile.node;
let channel = card.channels.get(channelId);
let token = card.data.cardProfile.guid + '.' + card.data.cardDetail.token;
return await getContactChannelTopics(node, token, channelId, revision);
},
getChannelTopic: async (cardId, channelId, topicId) => {
let card = cards.current.get(cardId);
let node = card.data.cardProfile.node;
let channel = card.channels.get(channelId);
let token = card.data.cardProfile.guid + '.' + card.data.cardDetail.token;
return await getContactChannelTopic(node, token, channelId, topicId);
},
addCard: async (message) => { addCard: async (message) => {
return await addCard(access.current, message); return await addCard(access.current, message);
}, },

View File

@ -3,6 +3,8 @@ import { getChannels } from '../Api/getChannels';
import { getChannel } from '../Api/getChannel'; import { getChannel } from '../Api/getChannel';
import { addChannel } from '../Api/addChannel'; import { addChannel } from '../Api/addChannel';
import { addChannelTopic } from '../Api/addChannelTopic'; import { addChannelTopic } from '../Api/addChannelTopic';
import { getChannelTopics } from '../Api/getChannelTopics';
import { getChannelTopic } from '../Api/getChannelTopic';
export function useChannelContext() { export function useChannelContext() {
const [state, setState] = useState({ const [state, setState] = useState({
@ -31,7 +33,7 @@ export function useChannelContext() {
cur.data.detailRevision = channel.data.detailRevision; cur.data.detailRevision = channel.data.detailRevision;
} }
else { else {
let slot = await getChannel(state.token, channel.id); let slot = await getChannel(access.current, channel.id);
cur.data.channelDetail = slot.data.channelDetail; cur.data.channelDetail = slot.data.channelDetail;
cur.data.detailRevision = slot.data.detailRevision; cur.data.detailRevision = slot.data.detailRevision;
} }
@ -48,14 +50,15 @@ export function useChannelContext() {
const setChannels = async (rev) => { const setChannels = async (rev) => {
if (next.current == null) { if (next.current == null) {
next.current = rev;
if (revision.current != rev) { if (revision.current != rev) {
await updateChannels(); await updateChannels();
updateState({ channels: channels.current }); updateState({ channels: channels.current });
revision.current = rev; revision.current = rev;
} }
if (next.current != null) { let r = next.current;
let r = next.current; next.current = null;
next.current = null; if (revision.current != r) {
setChannels(r); setChannels(r);
} }
} }
@ -77,6 +80,16 @@ export function useChannelContext() {
addChannelTopic: async (channelId, message, assets) => { addChannelTopic: async (channelId, message, assets) => {
await addChannelTopic(access.current, channelId, message, assets); await addChannelTopic(access.current, channelId, message, assets);
}, },
getChannelRevision: (channelId) => {
let channel = channels.current.get(channelId);
return channel.revision;
},
getChannelTopics: async (channelId, revision) => {
return await getChannelTopics(access.current, channelId, revision);
},
getChannelTopic: async (channelId, topicId) => {
return await getChannelTopic(access.current, channelId, topicId);
},
} }
return { state, actions } return { state, actions }

View File

@ -159,7 +159,7 @@ export function useContact() {
updateState({ location: profile.location }); updateState({ location: profile.location });
updateState({ node: profile.node }); updateState({ node: profile.node });
if (contact.data.cardProfile.imageSet) { if (contact.data.cardProfile.imageSet) {
updateState({ imageUrl: card.actions.getImageUrl(contact.id, contact.revision) }); updateState({ imageUrl: card.actions.getImageUrl(contact.id) });
} }
else { else {
updateState({ imageUrl: '' }); updateState({ imageUrl: '' });

View File

@ -42,8 +42,9 @@ export const AddTopicWrapper = styled.div`
`; `;
export const BusySpin = styled(Spin)` export const BusySpin = styled(Spin)`
display: flex;
position: absolute; position: absolute;
margin-right: 12px; padding-right: 12px;
x-index: 10; x-index: 10;
`; `;

View File

@ -1,12 +1,10 @@
import { useContext, useState, useEffect, useRef } from 'react'; import { useContext, useState, useEffect, useRef } from 'react';
import { AppContext } from '../../../AppContext/AppContext';
import { ConversationContext } from '../../../ConversationContext/ConversationContext'; import { ConversationContext } from '../../../ConversationContext/ConversationContext';
export function useTopicItem() { export function useTopicItem() {
const [state, setState] = useState({}); const [state, setState] = useState({});
const app = useContext(AppContext);
const conversation = useContext(ConversationContext); const conversation = useContext(ConversationContext);
const updateState = (value) => { const updateState = (value) => {

View File

@ -1,11 +1,8 @@
import { useContext, useState, useEffect, useRef } from 'react'; import { useContext, useState, useEffect, useRef } from 'react';
import { AppContext } from '../../AppContext/AppContext';
import { useNavigate, useLocation, useParams } from "react-router-dom"; import { useNavigate, useLocation, useParams } from "react-router-dom";
import { getChannelTopics } from '../../Api/getChannelTopics';
import { getChannelTopic } from '../../Api/getChannelTopic';
import { getContactChannelTopics } from '../../Api/getContactChannelTopics';
import { getContactChannelTopic } from '../../Api/getContactChannelTopic';
import { ConversationContext } from '../../ConversationContext/ConversationContext'; import { ConversationContext } from '../../ConversationContext/ConversationContext';
import { CardContext } from '../../AppContext/CardContext';
import { ChannelContext } from '../../AppContext/ChannelContext';
export function useConversation() { export function useConversation() {
@ -15,11 +12,11 @@ export function useConversation() {
const { cardId, channelId } = useParams(); const { cardId, channelId } = useParams();
const navigate = useNavigate(); const navigate = useNavigate();
const app = useContext(AppContext); const card = useContext(CardContext);
const channel = useContext(ChannelContext);
const conversation = useContext(ConversationContext); const conversation = useContext(ConversationContext);
const topics = useRef(new Map()); const topics = useRef(new Map());
const revision = useRef(null);
console.log("PARAMS: ", cardId, channelId);
const updateState = (value) => { const updateState = (value) => {
setState((s) => ({ ...s, ...value })); setState((s) => ({ ...s, ...value }));
@ -33,86 +30,79 @@ console.log("PARAMS: ", cardId, channelId);
const updateConversation = async () => { const updateConversation = async () => {
if (cardId) { if (cardId) {
if(app?.actions?.getCard) { let rev = card.actions.getChannelRevision(cardId, channelId);
let contact = app.actions.getCard(cardId); if (revision.current != rev) {
let conversation = contact.channels.get(channelId); let delta = await card.actions.getChannelTopics(cardId, channelId, revision.current);
if (conversation?.revision != state.revision) { for (let topic of delta) {
let token = contact.data.cardProfile.guid + "." + contact.data.cardDetail.token; if (topic.data == null) {
let slots = await getContactChannelTopics(token, channelId, state.revision); topics.current.delete(topic.id);
for (let topic of slots) { }
if (topic.data == null) { else {
topics.current.delete(topic.id); let cur = topics.current.get(topic.id);
} if (cur == null) {
else { cur = { id: topic.id, data: {} };
let cur = topics.current.get(topic.id); }
if (cur == null) { if (topic.data.detailRevision != cur.data.detailRevision) {
cur = { id: topic.id, data: {} }; if(topic.data.topicDetail != null) {
} cur.data.topicDetail = topic.data.topicDetail;
if (topic.data.detailRevision != cur.data.detailRevision) { cur.data.detailRevision = topic.data.detailRevision;
if(topic.data.topicDetail != null) { }
cur.data.topicDetail = topic.data.topicDetail; else {
cur.data.detailRevision = topic.data.detailRevision; let slot = await card.actions.getChannelTopic(cardId, channelId, topic.id);
} cur.data.topicDetail = slot.data.topicDetail;
else { cur.data.detailRevision = slot.data.detailRevision;
let slot = await getContactChannelTopic(token, channelId, topic.id); }
cur.data.topicDetail = slot.data.topicDetail; }
cur.data.detailRevision = slot.data.detailRevision; cur.revision = topic.revision;
} topics.current.set(topic.id, cur);
}
cur.revision = topic.revision;
topics.current.set(topic.id, cur);
}
} }
updateState({
topics: Array.from(topics.current.values()),
revision: conversation.revision,
});
} }
updateState({
topics: Array.from(topics.current.values()),
});
revision.current = rev;
} }
} }
else { else {
if(app?.actions?.getChannel) { let rev = channel.actions.getChannelRevision(channelId);
let conversation = app.actions.getChannel(channelId); if (revision.current != rev) {
if (conversation?.revision != state.revision) { let delta = await channel.actions.getChannelTopics(channelId, revision.current);
let slots = await getChannelTopics(app.state.token, channelId, state.revision); for (let topic of delta) {
if (topic.data == null) {
for (let topic of slots) { topics.current.delete(topic.id);
if (topic.data == null) { }
topics.current.delete(topic.id); else {
} let cur = topics.current.get(topic.id);
else { if (cur == null) {
let cur = topics.current.get(topic.id); cur = { id: topic.id, data: {} };
if (cur == null) { }
cur = { id: topic.id, data: {} }; if (topic.data.detailRevision != cur.data.detailRevision) {
} if(topic.data.topicDetail != null) {
if (topic.data.detailRevision != cur.data.detailRevision) { cur.data.topicDetail = topic.data.topicDetail;
if(topic.data.topicDetail != null) { cur.data.detailRevision = topic.data.detailRevision;
cur.data.topicDetail = topic.data.topicDetail; }
cur.data.detailRevision = topic.data.detailRevision; else {
} let slot = await channel.actions.getChannelTopic(channelId, topic.id);
else { cur.data.topicDetail = slot.data.topicDetail;
let slot = await getChannelTopic(app.state.token, channelId, topic.id); cur.data.detailRevision = slot.data.detailRevision;
cur.data.topicDetail = slot.data.topicDetail; }
cur.data.detailRevision = slot.data.detailRevision; }
} cur.revision = topic.revision;
} topics.current.set(topic.id, cur);
cur.revision = topic.revision;
topics.current.set(topic.id, cur);
}
} }
updateState({
topics: Array.from(topics.current.values()),
revision: conversation.revision
});
} }
updateState({
topics: Array.from(topics.current.values()),
revision: conversation.revision
});
revision.current = rev;
} }
} }
} }
useEffect(() => { useEffect(() => {
updateConversation(); updateConversation();
}, [app]); }, [card, channel]);
return { state, actions }; return { state, actions };
} }

View File

@ -25,7 +25,7 @@ export function Cards({ showRegistry }) {
const cardImage = (item) => { const cardImage = (item) => {
if (actions?.getImageUrl) { if (actions?.getImageUrl) {
return actions.getImageUrl(item.id, item.revision); return actions.getImageUrl(item.id);
} }
return null return null
} }

View File

@ -1,5 +1,4 @@
import { useContext, useState, useEffect } from 'react'; import { useContext, useState, useEffect } from 'react';
import { AppContext } from '../../../AppContext/AppContext';
export function useContacts() { export function useContacts() {
@ -7,13 +6,9 @@ export function useContacts() {
const actions = {}; const actions = {};
const app = useContext(AppContext);
const updateState = (value) => { const updateState = (value) => {
setState((s) => ({ ...s, ...value })); setState((s) => ({ ...s, ...value }));
} }
useEffect(() => {}, [app])
return { state, actions }; return { state, actions };
} }

View File

@ -169,7 +169,7 @@ export function VirtualList({ items, itemRenderer }) {
} }
} }
else { else {
let pos = containers.current[0].top + containers.current[0].height; let pos = containers.current[0].top + containers.current[0].height + 2 * GUTTER;
for (let i = 1; i < containers.current.length; i++) { for (let i = 1; i < containers.current.length; i++) {
if (containers.current[i].top != pos) { if (containers.current[i].top != pos) {
containers.current[i].top = pos; containers.current[i].top = pos;