databag/app/mobile/src/context/useCardContext.hook.js

179 lines
7.0 KiB
JavaScript
Raw Normal View History

2022-09-15 08:03:20 +00:00
import { useState, useRef, useContext } from 'react';
import { StoreContext } from 'context/StoreContext';
2022-09-15 18:26:03 +00:00
import { getCards } from 'api/getCards';
import { getCardProfile } from 'api/getCardProfile';
import { getCardDetail } from 'api/getCardDetail';
2022-09-15 08:03:20 +00:00
2022-09-16 06:18:46 +00:00
import { getContactChannelTopics } from 'api/getContactChannelTopics';
import { getContactChannelDetail } from 'api/getContactChannelDetail';
import { getContactChannelSummary } from 'api/getContactChannelSummary';
2022-09-15 08:03:20 +00:00
export function useCardContext() {
const [state, setState] = useState({
});
const store = useContext(StoreContext);
const session = useRef(null);
const curRevision = useRef(null);
const setRevision = useRef(null);
const syncing = useRef(false);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }))
}
const sync = async () => {
if (!syncing.current && setRevision.current !== curRevision.current) {
syncing.current = true;
try {
const revision = curRevision.current;
const { server, appToken, guid } = session.current;
// get and store
2022-09-15 18:26:03 +00:00
const delta = await getCards(server, appToken, setRevision.current);
for (let card of delta) {
if (card.data) {
if (card.data.cardDetail && card.data.cardProfile) {
await store.actions.setCardItem(guid, card);
}
else {
const view = await store.actions.getCardItemView(guid, card.id);
2022-09-15 22:12:06 +00:00
if (view == null) {
console.log('alert: expected card not synced');
let assembled = JSON.parse(JSON.stringify(card));
assembled.data.cardDetail = await getCardDetail(server, appToken, card.id);
assembled.data.cardProfile = await getCardProfile(server, appToken, card.id);
await store.actions.setCardItem(guid, assembled);
2022-09-15 18:26:03 +00:00
}
2022-09-15 22:12:06 +00:00
else {
if (view.detailRevision != detailRevision) {
const detail = await getCardDetail(server, appToken, card.id);
await store.actions.setCardItemDetail(guid, card.id, detailRevision, detail);
}
if (view.profileRevision != profileRevision) {
const profile = await getCardProfile(server, appToken, card.id);
await store.actions.setCardItemProfile(guid, card.id, profileRevision, profile);
}
2022-09-15 18:26:03 +00:00
}
2022-09-15 22:12:06 +00:00
}
const status = await store.actions.getCardItemStatus(guid, card.id);
2022-09-16 06:18:46 +00:00
const cardServer = status.cardProfile.node;
const cardToken = status.cardDetail.token;
2022-09-15 22:12:06 +00:00
if (status.detail.status === 'connected') {
2022-09-16 06:18:46 +00:00
try {
const { notifiedView, notifiedProfile, notifiedArticle, notifiedChannel } = card.data;
if (status.notifiedView !== notifiedView) {
await store.actions.clearCardChannelItems(guid, card.id);
await updateCardChannelItems(guid, card.id, cardServer, cardToken, notifiedView, null);
2022-09-15 22:12:06 +00:00
await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedChannel);
2022-09-16 06:18:46 +00:00
await store.actions.setCardItemNotifiedView(guid, card.id, notifiedView);
}
else {
if (status.notifiedChannel != notifiedChannel) {
await updateCardChannelItems(guid, card.id, cardServer, cardToken, status.notifiedChannel)
await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedView, notifiedChannel);
}
}
if (status.notifiedProflile != notifiedProfile) {
// TODO update contact profile if different
await store.actions.setCardItemNotifiedProfile(guid, card.id, notifiedProfile);
}
if (status.offsync) {
await store.actions.clearCardItemOffsync(guid, cardId);
2022-09-15 18:26:03 +00:00
}
}
2022-09-16 06:18:46 +00:00
catch(err) {
console.log(err);
await store.actions.setCardItemOffsync(guid, cardId);
}
2022-09-15 18:26:03 +00:00
}
}
else {
2022-09-15 22:12:06 +00:00
//TODO clear card channel topics
await store.actions.clearCardChannelItems(guid, card.id);
2022-09-15 18:26:03 +00:00
await store.actions.clearCardItem(guid, card.id);
}
}
2022-09-15 08:03:20 +00:00
setRevision.current = revision;
2022-09-15 18:26:03 +00:00
await store.actions.setCardRevision(guid, revision);
2022-09-15 08:03:20 +00:00
}
catch(err) {
console.log(err);
syncing.current = false;
return;
}
syncing.current = false;
sync();
}
};
2022-09-16 06:18:46 +00:00
const updateCardChannelItems = async (cardId, cardServer, cardToken, notifiedView, notifiedChannel) => {
const { guid } = session.current;
const delta = await getContactChannels(cardServer, cardToken, notifiedView, notifiedChannel);
for (let channel of delta) {
if (channel.data) {
if (channel.data.channelDetail && channel.data.channelSummary) {
await store.actions.setCardChannelItem(guid, cardId, channel);
}
else {
const { detailRevision, topicRevision, channelDetail, channelSummary } = channel.data;
const view = await store.actions.getCardChannelItemView(guid, cardId, channel.id);
if (view == null) {
console.log('alert: expected channel not synced');
let assembled = JSON.parse(JSON.stringify(channel));
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);
}
else {
if (view.detailRevision != detailRevision) {
const detail = await getChannelDetail(cardServer, cardToken, channel.id);
await store.actions.setCardChannelItemDetail(guid, cardId, channel.id, detailRevision, detail);
}
if (view.topicRevision != topicRevision) {
const summary = await getChannelSummary(cardServer, channel.id);
await store.actions.setCardChannelItemSummary(guid, cardId, channel.id, topicRevision, summary);
}
await store.actions.setCardChannelItemRevision(guid, cardId, channel.revision);
}
}
}
else {
await store.actions.clearCardChannelItem(guid, cardId, channel.id);
}
}
}
2022-09-15 08:03:20 +00:00
const actions = {
setSession: async (access) => {
const { guid, server, appToken } = access;
// load
const revision = await store.actions.getCardRevision(guid);
// update
setRevision.current = revision;
curRevision.current = revision;
session.current = access;
},
clearSession: () => {
session.current = {};
updateState({ account: null });
},
setRevision: (rev) => {
curRevision.current = rev;
sync();
},
}
return { state, actions }
}