From 450e4ff7a0dc3fcd8555234bd555e2a5669a4c55 Mon Sep 17 00:00:00 2001 From: balzack Date: Mon, 19 Sep 2022 22:39:53 -0700 Subject: [PATCH] added cache for channels and cards --- app/mobile/src/context/useCardContext.hook.js | 123 +++++++++++++++++- .../src/context/useChannelContext.hook.js | 33 ++++- .../src/context/useStoreContext.hook.js | 2 +- app/mobile/src/utitls/Logo.jsx | 31 +++++ app/mobile/src/utitls/package.json | 3 + 5 files changed, 184 insertions(+), 8 deletions(-) create mode 100644 app/mobile/src/utitls/Logo.jsx create mode 100644 app/mobile/src/utitls/package.json diff --git a/app/mobile/src/context/useCardContext.hook.js b/app/mobile/src/context/useCardContext.hook.js index 5db18f34..38afc7fe 100644 --- a/app/mobile/src/context/useCardContext.hook.js +++ b/app/mobile/src/context/useCardContext.hook.js @@ -11,6 +11,7 @@ import { getContactChannelSummary } from 'api/getContactChannelSummary'; export function useCardContext() { const [state, setState] = useState({ + cards: new Map(), }); const store = useContext(StoreContext); @@ -18,11 +19,100 @@ export function useCardContext() { const curRevision = useRef(null); const setRevision = useRef(null); const syncing = useRef(false); + const cards = useRef(new Map()); + const cardChannels = useRef(new Map()); const updateState = (value) => { setState((s) => ({ ...s, ...value })) } + const setCardDetail = (cardId, detail, revision) => { + let card = cards.current.get(cardId); + if (card?.data) { + card.data.cardDetail = detail; + card.data.detailRevision = revision; + cards.current.set(cardId, card); + } + } + const setCardProfile = (cardId, profile, revision) => { + let card = cards.current.get(cardId); + if (card?.data) { + card.data.cardProfile = profile; + card.data.profileRevision = revision; + cards.current.set(cardId, card); + } + } + const setCardRevision = (cardId, revision) => { + let card = cards.current.get(cardId); + if (card) { + card.revision = revision; + cards.current.set(cardId, card); + } + } + const setCardOffsync = (cardId, offsync) => { + let card = cards.current.get(cardId); + if (card) { + card.offsync = offsync; + cards.current.set(cardId, card); + } + } + const clearCardChannels = (cardId) => { + let card = cards.current.get(cardId); + if (card) { + card.channels = new Map(); + cards.current.set(cardId, card); + } + } + const setCardChannel = (cardId, channel) => { + let card = cards.current.get(cardId); + if (card) { + card.channels.set(channel.id, channel); + cards.current.set(cardId, card); + } + } + const setCardChannelDetail = (cardId, channelId, detail, revision) => { + let card = cards.current.get(cardId); + if (card) { + let channel = card.channels.get(channelId); + if (channel?.data) { + channel.data.channelDetail = detail; + channel.data.detailRevision = revision; + card.channels.set(channelId, channel); + cards.current.set(cardId, card); + } + } + } + const setCardChannelSummary = (cardId, channelId, summary, revision) => { + let card = cards.current.get(cardId); + if (card) { + let channel = card.channels.get(channelId); + if (channel?.data) { + channel.data.channelSummary = detail; + channel.data.topicRevision = revision; + card.channels.set(channelId, channel); + cards.current.set(cardId, card); + } + } + } + const setCardChannelRevision = (cardId, channelId, revision) => { + let card = cards.current.get(cardId); + if (card) { + let channel = card.channels.get(channelId); + if (channel) { + channel.revision = revision; + card.channels.set(channelId, channel); + cards.current.set(cardId, card); + } + } + } + const clearCardChannel = (cardId, channelId) => { + let card = cards.current.get(cardId); + if (card) { + card.channels.delete(channelId); + cards.current.set(cardId, card); + } + } + const sync = async () => { if (!syncing.current && setRevision.current !== curRevision.current) { syncing.current = true; @@ -38,6 +128,7 @@ export function useCardContext() { if (card.data) { if (card.data.cardDetail && card.data.cardProfile) { await store.actions.setCardItem(guid, card); + cards.current.set(cardId, card); } else { const view = await store.actions.getCardItemView(guid, card.id); @@ -47,16 +138,21 @@ export function useCardContext() { assembled.data.cardDetail = await getCardDetail(server, appToken, card.id); assembled.data.cardProfile = await getCardProfile(server, appToken, card.id); await store.actions.setCardItem(guid, assembled); + cards.curent.set(assembled.id, assembled); } else { if (view.detailRevision != detailRevision) { const detail = await getCardDetail(server, appToken, card.id); await store.actions.setCardItemDetail(guid, card.id, detailRevision, detail); + setCardDetail(card.id, detail, detailRevision); } if (view.profileRevision != profileRevision) { const profile = await getCardProfile(server, appToken, card.id); await store.actions.setCardItemProfile(guid, card.id, profileRevision, profile); + setCardProfile(card.id, profile, profileRevision); } + await store.actions.setCardItemRevision(guid, card.id, card.revision); + setCardRevision(card.id, card.revision); } } @@ -71,6 +167,7 @@ export function useCardContext() { await updateCardChannelItems(card.id, cardServer, cardToken, notifiedView, null); await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedChannel); await store.actions.setCardItemNotifiedView(guid, card.id, notifiedView); + clearCardChannel(card.id); } else { if (status.notifiedChannel != notifiedChannel) { @@ -84,11 +181,13 @@ export function useCardContext() { } if (status.offsync) { await store.actions.clearCardItemOffsync(guid, card.id); + setCardOffsync(card.id, false); } } catch(err) { console.log(err); await store.actions.setCardItemOffsync(guid, card.id); + setCardOffsync(card.id, true); } } } @@ -96,6 +195,7 @@ export function useCardContext() { //TODO clear card channel topics await store.actions.clearCardChannelItems(guid, card.id); await store.actions.clearCardItem(guid, card.id); + cards.current.delete(card.id); } } @@ -108,6 +208,7 @@ export function useCardContext() { return; } + updateState({ cards: cards.current }); syncing.current = false; sync(); } @@ -120,6 +221,7 @@ export function useCardContext() { if (channel.data) { if (channel.data.channelDetail && channel.data.channelSummary) { await store.actions.setCardChannelItem(guid, cardId, channel); + setCardChannel(cardId, channel); } else { const { detailRevision, topicRevision, channelDetail, channelSummary } = channel.data; @@ -130,22 +232,27 @@ export function useCardContext() { assembled.data.channelDetail = await getChannelDetail(cardServer, cardToken, channel.id); assembled.data.channelSummary = await getChannelSummary(cardServer, cardToken, channel.id); await store.actions.setCardChannelItem(guid, cardId, assembled); + setCardChannel(cardId, assembled); } else { if (view.detailRevision != detailRevision) { const detail = await getChannelDetail(cardServer, cardToken, channel.id); await store.actions.setCardChannelItemDetail(guid, cardId, channel.id, detailRevision, detail); + setCardChannelDetail(cardId, channel.id, detail, detailRevision); } if (view.topicRevision != topicRevision) { const summary = await getChannelSummary(cardServer, channel.id); await store.actions.setCardChannelItemSummary(guid, cardId, channel.id, topicRevision, summary); + setCardChannelSummary(cardId, channel.id, summary, topicRevision); } await store.actions.setCardChannelItemRevision(guid, cardId, channel.revision); + setCardChannelRevision(cardId, channel.id, channel.revision); } } } else { await store.actions.clearCardChannelItem(guid, cardId, channel.id); + clearCardChannel(cardId, channel.id); } } } @@ -153,13 +260,17 @@ export function useCardContext() { const actions = { setSession: async (access) => { const { guid, server, appToken } = access; - - // load - + cards.current = new Map(); + const cardItems = await store.actions.getCardItems(guid); + for (item of cardItems) { + cards.current.set(item.cardId, { ...item, channels: new Map() }); + } + const cardChannelItems = await store.actions.getCardChannelItems(guid); + for (item of cardChannelItems) { + setCardChannel(item.cardId, item); + } const revision = await store.actions.getCardRevision(guid); - - // update - + updateState({ cards: cards.current }); setRevision.current = revision; curRevision.current = revision; session.current = access; diff --git a/app/mobile/src/context/useChannelContext.hook.js b/app/mobile/src/context/useChannelContext.hook.js index 6354febf..aa5eaa62 100644 --- a/app/mobile/src/context/useChannelContext.hook.js +++ b/app/mobile/src/context/useChannelContext.hook.js @@ -20,6 +20,30 @@ export function useChannelContext() { setState((s) => ({ ...s, ...value })) } + const setChannelDetails = (channelId, details, revision) => { + let channel = channels.current.get(channelId); + if (channel?.data) { + channel.data.channelDetails = details; + channel.data.detailRevision = revision; + channels.current.set(channelId, channel); + } + } + const setChannelSummary = (channelId, summary, revision) => { + let channel = channels.current.get(channelId); + if (channel?.data) { + channel.data.channelSummary = summary; + channel.data.topicRevision = revision; + channels.curent.set(channelId, channel); + } + } + const setChannelRevision = (channelId, revision) => { + let channel = channels.current.get(channelId); + if (channel) { + channel.revision = revision; + channels.current.set(channelId, channel); + } + } + const sync = async () => { if (!syncing.current && setRevision.current !== curRevision.current) { @@ -34,6 +58,7 @@ export function useChannelContext() { if (channel.data) { if (channel.data.channelDetail && channel.data.channelSummary) { await store.actions.setChannelItem(guid, channel); + channels.current.set(channel.id, channel); } else { const { detailRevision, topicRevision, channelDetail, channelSummary } = channel.data; @@ -44,27 +69,33 @@ export function useChannelContext() { assembled.data.channelDetail = await getChannelDetail(server, appToken, channel.id); assembled.data.channelSummary = await getChannelSummary(server, appToken, channel.id); await store.actions.setChannelItem(guid, assembled); + channels.current.set(assembled.id, assembled); } else { if (view.detailRevision != detailRevision) { const detail = await getChannelDetail(server, appToken, channel.id); await store.actions.setChannelItemDetail(guid, channel.id, detailRevision, detail); + setChannelDetail(channel.id, detail, detailRevision); } if (view.topicRevision != topicRevision) { const summary = await getChannelSummary(server, appToken, channel.id); await store.actions.setChannelItemSummary(guid, channel.id, topicRevision, summary); + setChannelSummary(channel.id, summary, topicRevision); } - await store.actions.setChannelItemRevision(guid, channel.revision); + await store.actions.setChannelItemRevision(guid, channel.id, channel.revision); + setChannelRevision(channel.id, channel.revision); } } } else { await store.actions.clearChannelItem(guid, channel.id); + channels.current.delete(channel.id); } } setRevision.current = revision; await store.actions.setChannelRevision(guid, revision); + updateState({ channels: channels.current }); } catch(err) { console.log(err); diff --git a/app/mobile/src/context/useStoreContext.hook.js b/app/mobile/src/context/useStoreContext.hook.js index 0589dd95..428417d2 100644 --- a/app/mobile/src/context/useStoreContext.hook.js +++ b/app/mobile/src/context/useStoreContext.hook.js @@ -139,7 +139,7 @@ export function useStoreContext() { }; }, getCardItems: async (guid) => { - const values = await getAppValues(db.current, `SELECT card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel FROM channel_${guid}`, []); + const values = await getAppValues(db.current, `SELECT card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel FROM card_${guid}`, []); return values.map(card => ({ cardId: card.card_id, revision: card.revision, diff --git a/app/mobile/src/utitls/Logo.jsx b/app/mobile/src/utitls/Logo.jsx new file mode 100644 index 00000000..e6661126 --- /dev/null +++ b/app/mobile/src/utitls/Logo.jsx @@ -0,0 +1,31 @@ +import { Image } from 'react-native'; +import avatar from 'images/avatar.png'; +import appstore from 'images/appstore.png'; +import solution from 'images/solution.png'; +import team from 'images/team.png'; + +export function Logo({ src, width, height, radius }) { + return ( +
+ { src === 'team' && ( + + )} + { src === 'avatar' && ( + + )} + { src === 'appstore' && ( + + )} + { src === 'solution' && ( + + )} + { !src && ( + + )} + { src && src.startsWith('http') && ( + + )} +
+ ); +} + diff --git a/app/mobile/src/utitls/package.json b/app/mobile/src/utitls/package.json new file mode 100644 index 00000000..6e3a19f2 --- /dev/null +++ b/app/mobile/src/utitls/package.json @@ -0,0 +1,3 @@ +{ + "name": "utils" +}