added cache for channels and cards

This commit is contained in:
balzack 2022-09-19 22:39:53 -07:00
parent 566dcd0f20
commit 450e4ff7a0
5 changed files with 184 additions and 8 deletions

View File

@ -11,6 +11,7 @@ import { getContactChannelSummary } from 'api/getContactChannelSummary';
export function useCardContext() { export function useCardContext() {
const [state, setState] = useState({ const [state, setState] = useState({
cards: new Map(),
}); });
const store = useContext(StoreContext); const store = useContext(StoreContext);
@ -18,11 +19,100 @@ export function useCardContext() {
const curRevision = useRef(null); const curRevision = useRef(null);
const setRevision = useRef(null); const setRevision = useRef(null);
const syncing = useRef(false); const syncing = useRef(false);
const cards = useRef(new Map());
const cardChannels = useRef(new Map());
const updateState = (value) => { const updateState = (value) => {
setState((s) => ({ ...s, ...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 () => { const sync = async () => {
if (!syncing.current && setRevision.current !== curRevision.current) { if (!syncing.current && setRevision.current !== curRevision.current) {
syncing.current = true; syncing.current = true;
@ -38,6 +128,7 @@ export function useCardContext() {
if (card.data) { if (card.data) {
if (card.data.cardDetail && card.data.cardProfile) { if (card.data.cardDetail && card.data.cardProfile) {
await store.actions.setCardItem(guid, card); await store.actions.setCardItem(guid, card);
cards.current.set(cardId, card);
} }
else { else {
const view = await store.actions.getCardItemView(guid, card.id); 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.cardDetail = await getCardDetail(server, appToken, card.id);
assembled.data.cardProfile = await getCardProfile(server, appToken, card.id); assembled.data.cardProfile = await getCardProfile(server, appToken, card.id);
await store.actions.setCardItem(guid, assembled); await store.actions.setCardItem(guid, assembled);
cards.curent.set(assembled.id, assembled);
} }
else { else {
if (view.detailRevision != detailRevision) { if (view.detailRevision != detailRevision) {
const detail = await getCardDetail(server, appToken, card.id); const detail = await getCardDetail(server, appToken, card.id);
await store.actions.setCardItemDetail(guid, card.id, detailRevision, detail); await store.actions.setCardItemDetail(guid, card.id, detailRevision, detail);
setCardDetail(card.id, detail, detailRevision);
} }
if (view.profileRevision != profileRevision) { if (view.profileRevision != profileRevision) {
const profile = await getCardProfile(server, appToken, card.id); const profile = await getCardProfile(server, appToken, card.id);
await store.actions.setCardItemProfile(guid, card.id, profileRevision, profile); 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 updateCardChannelItems(card.id, cardServer, cardToken, notifiedView, null);
await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedChannel); await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedChannel);
await store.actions.setCardItemNotifiedView(guid, card.id, notifiedView); await store.actions.setCardItemNotifiedView(guid, card.id, notifiedView);
clearCardChannel(card.id);
} }
else { else {
if (status.notifiedChannel != notifiedChannel) { if (status.notifiedChannel != notifiedChannel) {
@ -84,11 +181,13 @@ export function useCardContext() {
} }
if (status.offsync) { if (status.offsync) {
await store.actions.clearCardItemOffsync(guid, card.id); await store.actions.clearCardItemOffsync(guid, card.id);
setCardOffsync(card.id, false);
} }
} }
catch(err) { catch(err) {
console.log(err); console.log(err);
await store.actions.setCardItemOffsync(guid, card.id); await store.actions.setCardItemOffsync(guid, card.id);
setCardOffsync(card.id, true);
} }
} }
} }
@ -96,6 +195,7 @@ export function useCardContext() {
//TODO clear card channel topics //TODO clear card channel topics
await store.actions.clearCardChannelItems(guid, card.id); await store.actions.clearCardChannelItems(guid, card.id);
await store.actions.clearCardItem(guid, card.id); await store.actions.clearCardItem(guid, card.id);
cards.current.delete(card.id);
} }
} }
@ -108,6 +208,7 @@ export function useCardContext() {
return; return;
} }
updateState({ cards: cards.current });
syncing.current = false; syncing.current = false;
sync(); sync();
} }
@ -120,6 +221,7 @@ export function useCardContext() {
if (channel.data) { if (channel.data) {
if (channel.data.channelDetail && channel.data.channelSummary) { if (channel.data.channelDetail && channel.data.channelSummary) {
await store.actions.setCardChannelItem(guid, cardId, channel); await store.actions.setCardChannelItem(guid, cardId, channel);
setCardChannel(cardId, channel);
} }
else { else {
const { detailRevision, topicRevision, channelDetail, channelSummary } = channel.data; 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.channelDetail = await getChannelDetail(cardServer, cardToken, channel.id);
assembled.data.channelSummary = await getChannelSummary(cardServer, cardToken, channel.id); assembled.data.channelSummary = await getChannelSummary(cardServer, cardToken, channel.id);
await store.actions.setCardChannelItem(guid, cardId, assembled); await store.actions.setCardChannelItem(guid, cardId, assembled);
setCardChannel(cardId, assembled);
} }
else { else {
if (view.detailRevision != detailRevision) { if (view.detailRevision != detailRevision) {
const detail = await getChannelDetail(cardServer, cardToken, channel.id); const detail = await getChannelDetail(cardServer, cardToken, channel.id);
await store.actions.setCardChannelItemDetail(guid, cardId, channel.id, detailRevision, detail); await store.actions.setCardChannelItemDetail(guid, cardId, channel.id, detailRevision, detail);
setCardChannelDetail(cardId, channel.id, detail, detailRevision);
} }
if (view.topicRevision != topicRevision) { if (view.topicRevision != topicRevision) {
const summary = await getChannelSummary(cardServer, channel.id); const summary = await getChannelSummary(cardServer, channel.id);
await store.actions.setCardChannelItemSummary(guid, cardId, channel.id, topicRevision, summary); await store.actions.setCardChannelItemSummary(guid, cardId, channel.id, topicRevision, summary);
setCardChannelSummary(cardId, channel.id, summary, topicRevision);
} }
await store.actions.setCardChannelItemRevision(guid, cardId, channel.revision); await store.actions.setCardChannelItemRevision(guid, cardId, channel.revision);
setCardChannelRevision(cardId, channel.id, channel.revision);
} }
} }
} }
else { else {
await store.actions.clearCardChannelItem(guid, cardId, channel.id); await store.actions.clearCardChannelItem(guid, cardId, channel.id);
clearCardChannel(cardId, channel.id);
} }
} }
} }
@ -153,13 +260,17 @@ export function useCardContext() {
const actions = { const actions = {
setSession: async (access) => { setSession: async (access) => {
const { guid, server, appToken } = access; const { guid, server, appToken } = access;
cards.current = new Map();
// load 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); const revision = await store.actions.getCardRevision(guid);
updateState({ cards: cards.current });
// update
setRevision.current = revision; setRevision.current = revision;
curRevision.current = revision; curRevision.current = revision;
session.current = access; session.current = access;

View File

@ -20,6 +20,30 @@ export function useChannelContext() {
setState((s) => ({ ...s, ...value })) 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 () => { const sync = async () => {
if (!syncing.current && setRevision.current !== curRevision.current) { if (!syncing.current && setRevision.current !== curRevision.current) {
@ -34,6 +58,7 @@ export function useChannelContext() {
if (channel.data) { if (channel.data) {
if (channel.data.channelDetail && channel.data.channelSummary) { if (channel.data.channelDetail && channel.data.channelSummary) {
await store.actions.setChannelItem(guid, channel); await store.actions.setChannelItem(guid, channel);
channels.current.set(channel.id, channel);
} }
else { else {
const { detailRevision, topicRevision, channelDetail, channelSummary } = channel.data; 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.channelDetail = await getChannelDetail(server, appToken, channel.id);
assembled.data.channelSummary = await getChannelSummary(server, appToken, channel.id); assembled.data.channelSummary = await getChannelSummary(server, appToken, channel.id);
await store.actions.setChannelItem(guid, assembled); await store.actions.setChannelItem(guid, assembled);
channels.current.set(assembled.id, assembled);
} }
else { else {
if (view.detailRevision != detailRevision) { if (view.detailRevision != detailRevision) {
const detail = await getChannelDetail(server, appToken, channel.id); const detail = await getChannelDetail(server, appToken, channel.id);
await store.actions.setChannelItemDetail(guid, channel.id, detailRevision, detail); await store.actions.setChannelItemDetail(guid, channel.id, detailRevision, detail);
setChannelDetail(channel.id, detail, detailRevision);
} }
if (view.topicRevision != topicRevision) { if (view.topicRevision != topicRevision) {
const summary = await getChannelSummary(server, appToken, channel.id); const summary = await getChannelSummary(server, appToken, channel.id);
await store.actions.setChannelItemSummary(guid, channel.id, topicRevision, summary); 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 { else {
await store.actions.clearChannelItem(guid, channel.id); await store.actions.clearChannelItem(guid, channel.id);
channels.current.delete(channel.id);
} }
} }
setRevision.current = revision; setRevision.current = revision;
await store.actions.setChannelRevision(guid, revision); await store.actions.setChannelRevision(guid, revision);
updateState({ channels: channels.current });
} }
catch(err) { catch(err) {
console.log(err); console.log(err);

View File

@ -139,7 +139,7 @@ export function useStoreContext() {
}; };
}, },
getCardItems: async (guid) => { 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 => ({ return values.map(card => ({
cardId: card.card_id, cardId: card.card_id,
revision: card.revision, revision: card.revision,

View File

@ -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 (
<div style={{ borderRadius: radius, overflow: 'hidden' }}>
{ src === 'team' && (
<Image source={team} style={{ width, height }} />
)}
{ src === 'avatar' && (
<Image source={avatar} style={{ width, height }} />
)}
{ src === 'appstore' && (
<Image source={appstore} style={{ width, height }} />
)}
{ src === 'solution' && (
<Image source={solution} style={{ width, height }} />
)}
{ !src && (
<Image source={avatar} style={{ width, height }} />
)}
{ src && src.startsWith('http') && (
<Image source={src} style={{ width, height }} />
)}
</div>
);
}

View File

@ -0,0 +1,3 @@
{
"name": "utils"
}