syncing topics from server

This commit is contained in:
balzack 2022-09-29 22:34:31 -07:00
parent 40a29e17c3
commit 0251b648ef
2 changed files with 83 additions and 65 deletions

View File

@ -9,18 +9,18 @@ export function useConversationContext() {
subject: null, subject: null,
logo: null, logo: null,
contacts: [], contacts: [],
topics: [], topics: new Map(),
}); });
const store = useContext(StoreContext); const store = useContext(StoreContext);
const card = useContext(CardContext); const card = useContext(CardContext);
const channel = useContext(ChannelContext); const channel = useContext(ChannelContext);
const profile = useContext(ProfileContext); const profile = useContext(ProfileContext);
const topics = useRef(new Map()); const topics = useRef(null);
const revision = useRef(0); const revision = useRef(0);
const detailRevision = useRef(0); const detailRevision = useRef(0);
const syncRevision = useRef(0);
const syncing = useRef(false); const syncing = useRef(false);
const conversationId = useRef(null); const conversationId = useRef(null);
const reset = useRef(false);
const setView = useRef(0); const setView = useRef(0);
const updateState = (value) => { const updateState = (value) => {
@ -33,17 +33,11 @@ export function useConversationContext() {
} }
return await channel.actions.getTopicItems(channelId); return await channel.actions.getTopicItems(channelId);
} }
const getTopicDeltaItems = async (cardId, channelId, revision) => { const setTopicItem = async (cardId, channelId, topic) => {
if (cardId) { if (cardId) {
return await card.actions.getChannelTopicDeltaItems(cardId, channelId, revision); return await card.actions.setChannelTopicItem(cardId, channelId, topic);
} }
return await channel.actions.getTopicDeltaItems(channelId, revision); return await channel.actions.setTopicItem(channelId, topic);
}
const setTopicItem = async (cardId, channelId, revision, topic) => {
if (cardId) {
return await card.actions.setChannelTopicItem(cardId, channelId, revision, topic);
}
return await channel.actions.setTopicItem(channelId, revision, topic);
} }
const clearTopicItem = async (cardId, channelId, topicId) => { const clearTopicItem = async (cardId, channelId, topicId) => {
if (cardId) { if (cardId) {
@ -93,55 +87,82 @@ export function useConversationContext() {
} }
return await channel.actions.remvoeTopic(channelId, topicId); return await channel.actions.remvoeTopic(channelId, topicId);
} }
const setSyncRevision = async (cardId, channelId, revision) => {
if (cardId) {
return await card.actions.setSyncRevision(cardId, channelId, revision);
}
return await channel.actions.setSyncRevision(channelId, revision);
}
const sync = async () => { const sync = async () => {
const curView = setView.current; const curView = setView.current;
if (!syncing.current && conversationId.current) { if (!syncing.current) {
const { cardId, channelId } = conversationId.current; if (reset.current) {
const item = getChannel(cardId, channelId); revision.current = null;
if (item && (item.revision !== revision.current || item.syncRevision != syncRevision.current)) { detailRevision.current = null;
syncing.current = true; topics.current = null;
reset.current = false;
}
if (conversationId.current) {
const { cardId, channelId } = conversationId.current;
const channelItem = getChannel(cardId, channelId);
if (channelItem && (channelItem.revision !== revision.current)) {
syncing.current = true;
try { try {
// set channel details // set channel details
if (detailRevision.current != item.detailRevision) { if (detailRevision.current != channelItem.detailRevision) {
if (curView === setView.current) { if (curView === setView.current) {
setChannel(item); setChannel(channelItem);
detailRevision.current = item.detailRevision; detailRevision.current = channelItem.detailRevision;
}
} }
}
// set channel topics // initial load from store
if (syncRevision.current != item.syncRevision) { if (!topics.current) {
if (syncRevision.current) { topics.current = new Map();
const topics = await getTopicDeltaItems(cardId, channelId); const items = await getTopicItems(cardId, channelId);
items.forEach(item => {
topics.current.set(item.topicId, item);
});
} }
else {
const topics = await getTopicItems(cardId, channelId); // sync from server
if (channelItem.topicRevision !== channelItem.syncRevision) {
const res = await getTopics(cardId, channelId, channelItem.syncRevision)
for (const topic of res.topics) {
if (!topic.data) {
topics.current.delete(topic.id);
await clearTopicItem(cardId, channelId, topic.id);
}
const cached = topics.current.get(topic.id);
if (!cached || cached.detailRevision != topic.data.detailRevision) {
if (!topic.data.topicDetail) {
const updated = await getTopic(cardId, channelId, topic.id);
topic.data.topicDetail = updated.data.topicDetail;
}
await setTopicItem(cardId, channelId, topic);
const { id, revision, data } = topic;
topics.current.set(id, { topicId: id, revision: revision, detailRevision: topic.data.detailRevision, detail: topic.data.topicDetail });
}
}
await setSyncRevision(cardId, channelId, channelItem.topicRevision);
} }
if (curView === setView.current) {
syncRevision.current = item.syncRevision; // update revision
revision.current = channelItem.revision;
if (curView == setView.current) {
updateState({ topics: topics.current });
} }
}
// sync from server to store syncing.current = false;
if (item.topicRevision !== item.syncRevision) { sync();
const res = await getTopics(cardId, channelId, item.syncRevision)
} }
catch(err) {
// update revision console.log(err);
if (curView === setView.current) { syncing.current = false;
revision.current = item.revision; //TODO set to unsynced state
//TODO set to synced state
} }
syncing.current = false;
sync();
}
catch(err) {
console.log(err);
syncing.current = false;
//TODO set to unsynced state
} }
} }
} }
@ -241,17 +262,14 @@ export function useConversationContext() {
if (channel == null) { if (channel == null) {
setView.current++; setView.current++;
conversationId.current = null; conversationId.current = null;
updateState({ subject: null, logo: null, contacts: [], topics: [] }); reset.current = true;
updateState({ subject: null, logo: null, contacts: [], topics: new Map() });
} }
else if (channel.cardId !== conversationId.current?.cardId || channel.channelId !== conversationId.current?.channelId) { else if (channel.cardId !== conversationId.current?.cardId || channel.channelId !== conversationId.current?.channelId) {
setView.current++; setView.current++;
conversationId.current = channel; conversationId.current = channel;
updateState({ subject: null, logo: null, contacts: [], topics: [] }); reset.current = true;
updateState({ subject: null, logo: null, contacts: [], topics: new Map() });
revision.current = null;
detailRevision.current = null;
syncRevision.current = null;
topics.current = new Map();
sync(); sync();
} }
}, },

View File

@ -214,7 +214,7 @@ export function useStoreContext() {
readRevision: channel.read_revision, readRevision: channel.read_revision,
detailRevision: channel.detail_revision, detailRevision: channel.detail_revision,
topicRevision: channel.topic_revision, topicRevision: channel.topic_revision,
syncRevsion: channel.sync_revision, syncRevision: channel.sync_revision,
detail: decodeObject(channel.detail), detail: decodeObject(channel.detail),
summary: decodeObject(channel.summary), summary: decodeObject(channel.summary),
})); }));
@ -230,9 +230,9 @@ export function useStoreContext() {
detail: decodeObject(topic.detail), detail: decodeObject(topic.detail),
})); }));
}, },
setChannelTopicItem: async (guid, channelId, topicId, topic) => { setChannelTopicItem: async (guid, channelId, topic) => {
const { id, revision, data } = channel; const { id, revision, data } = topic;
await db.current.executeSql(`INSERT OR REPLACE INTO channel_topic_${guid} (channel_id, topic_id, revision, channel_revision, detail_revision, detail) values (?, ?, ?, ?, ?, ?);`, [channelId, id, revision, channelRevision, data.detailRevision, encodeObject(data.topicDetail)]); await db.current.executeSql(`INSERT OR REPLACE INTO channel_topic_${guid} (channel_id, topic_id, revision, detail_revision, detail) values (?, ?, ?, ?, ?);`, [channelId, id, revision, data.detailRevision, encodeObject(data.topicDetail)]);
}, },
clearChannelTopicItem: async (guid, channelId, topicId) => { clearChannelTopicItem: async (guid, channelId, topicId) => {
await db.current.executeSql(`DELETE FROM channel_topic_${guid} WHERE channel_id=? and topic_id=?`, [channelId, topicId]); await db.current.executeSql(`DELETE FROM channel_topic_${guid} WHERE channel_id=? and topic_id=?`, [channelId, topicId]);
@ -302,15 +302,15 @@ export function useStoreContext() {
detail: decodeObject(topic.detail), detail: decodeObject(topic.detail),
})); }));
}, },
setCardChannelTopicItem: async (guid, cardId, channelId, topicId, topic) => { setCardChannelTopicItem: async (guid, cardId, channelId, topic) => {
const { id, revision, data } = channel; const { id, revision, data } = topic;
await db.current.executeSql(`INSERT OR REPLACE INTO channel_topic_${guid} (card_id, channel_id, topic_id, revision, channel_revision, detail_revision, detail) values (?, ?, ?, ?, ?, ?, ?);`, [cardId, channelId, id, revision, channelRevision, data.detailRevision, encodeObject(data.topicDetail)]); await db.current.executeSql(`INSERT OR REPLACE INTO card_channel_topic_${guid} (card_id, channel_id, topic_id, revision, detail_revision, detail) values (?, ?, ?, ?, ?, ?);`, [cardId, channelId, id, revision, data.detailRevision, encodeObject(data.topicDetail)]);
}, },
clearCardChannelTopicItem: async (guid, cardId, channelId, topicId) => { clearCardChannelTopicItem: async (guid, cardId, channelId, topicId) => {
await db.current.executeSql(`DELETE FROM channel_topic_${guid} WHERE card_id=? and channel_id=? and topic_id=?`, [cardId, channelId, topicId]); await db.current.executeSql(`DELETE FROM card_channel_topic_${guid} WHERE card_id=? and channel_id=? and topic_id=?`, [cardId, channelId, topicId]);
}, },
clearCardChannelTopicItems: async (guid, cardId, channelId) => { clearCardChannelTopicItems: async (guid, cardId, channelId) => {
await db.current.executeSql(`DELETE FROM channel_topic_${guid} WHERE card_id=? and channel_id=?`, [cardId, channelId]); await db.current.executeSql(`DELETE FROM card_channel_topic_${guid} WHERE card_id=? and channel_id=?`, [cardId, channelId]);
}, },
} }