diff --git a/app/mobile/src/context/useConversationContext.hook.js b/app/mobile/src/context/useConversationContext.hook.js index f5e9da23..cdaa2ecf 100644 --- a/app/mobile/src/context/useConversationContext.hook.js +++ b/app/mobile/src/context/useConversationContext.hook.js @@ -9,18 +9,18 @@ export function useConversationContext() { subject: null, logo: null, contacts: [], - topics: [], + topics: new Map(), }); const store = useContext(StoreContext); const card = useContext(CardContext); const channel = useContext(ChannelContext); const profile = useContext(ProfileContext); - const topics = useRef(new Map()); + const topics = useRef(null); const revision = useRef(0); const detailRevision = useRef(0); - const syncRevision = useRef(0); const syncing = useRef(false); const conversationId = useRef(null); + const reset = useRef(false); const setView = useRef(0); const updateState = (value) => { @@ -33,17 +33,11 @@ export function useConversationContext() { } return await channel.actions.getTopicItems(channelId); } - const getTopicDeltaItems = async (cardId, channelId, revision) => { + const setTopicItem = async (cardId, channelId, topic) => { 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); - } - 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); + return await channel.actions.setTopicItem(channelId, topic); } const clearTopicItem = async (cardId, channelId, topicId) => { if (cardId) { @@ -93,55 +87,82 @@ export function useConversationContext() { } 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 curView = setView.current; - if (!syncing.current && conversationId.current) { - const { cardId, channelId } = conversationId.current; - const item = getChannel(cardId, channelId); - if (item && (item.revision !== revision.current || item.syncRevision != syncRevision.current)) { - syncing.current = true; + if (!syncing.current) { + if (reset.current) { + revision.current = null; + detailRevision.current = null; + 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 { - // set channel details - if (detailRevision.current != item.detailRevision) { - if (curView === setView.current) { - setChannel(item); - detailRevision.current = item.detailRevision; + try { + // set channel details + if (detailRevision.current != channelItem.detailRevision) { + if (curView === setView.current) { + setChannel(channelItem); + detailRevision.current = channelItem.detailRevision; + } } - } - // set channel topics - if (syncRevision.current != item.syncRevision) { - if (syncRevision.current) { - const topics = await getTopicDeltaItems(cardId, channelId); + // initial load from store + if (!topics.current) { + topics.current = new Map(); + 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 - if (item.topicRevision !== item.syncRevision) { - const res = await getTopics(cardId, channelId, item.syncRevision) + syncing.current = false; + sync(); } - - // update revision - if (curView === setView.current) { - revision.current = item.revision; - //TODO set to synced state + catch(err) { + console.log(err); + syncing.current = false; + //TODO set to unsynced 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) { setView.current++; 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) { setView.current++; conversationId.current = channel; - updateState({ subject: null, logo: null, contacts: [], topics: [] }); - - revision.current = null; - detailRevision.current = null; - syncRevision.current = null; - topics.current = new Map(); + reset.current = true; + updateState({ subject: null, logo: null, contacts: [], topics: new Map() }); sync(); } }, diff --git a/app/mobile/src/context/useStoreContext.hook.js b/app/mobile/src/context/useStoreContext.hook.js index b494e9ae..d1b8e1fc 100644 --- a/app/mobile/src/context/useStoreContext.hook.js +++ b/app/mobile/src/context/useStoreContext.hook.js @@ -214,7 +214,7 @@ export function useStoreContext() { readRevision: channel.read_revision, detailRevision: channel.detail_revision, topicRevision: channel.topic_revision, - syncRevsion: channel.sync_revision, + syncRevision: channel.sync_revision, detail: decodeObject(channel.detail), summary: decodeObject(channel.summary), })); @@ -230,9 +230,9 @@ export function useStoreContext() { detail: decodeObject(topic.detail), })); }, - setChannelTopicItem: async (guid, channelId, topicId, topic) => { - const { id, revision, data } = channel; - 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)]); + setChannelTopicItem: async (guid, channelId, topic) => { + const { id, revision, data } = topic; + 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) => { 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), })); }, - setCardChannelTopicItem: async (guid, cardId, channelId, topicId, topic) => { - const { id, revision, data } = channel; - 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)]); + setCardChannelTopicItem: async (guid, cardId, channelId, topic) => { + const { id, revision, data } = topic; + 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) => { - 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) => { - 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]); }, }