syncing channels

This commit is contained in:
balzack 2022-09-20 00:50:53 -07:00
parent 450e4ff7a0
commit 8b09d214b7
9 changed files with 139 additions and 40 deletions

View File

@ -1,4 +1,4 @@
export function getCardImageUrl(token, cardId, revision) {
return `/contact/cards/${cardId}/profile/image?agent=${token}&revision=${revision}`
export function getCardImageUrl(server, token, cardId, revision) {
return `https://${server}/contact/cards/${cardId}/profile/image?agent=${token}&revision=${revision}`
}

View File

@ -66,19 +66,19 @@ export function useAppContext() {
create: async (server, username, password, token) => {
await addAccount(server, username, password, token);
const access = await setLogin(username, server, password)
await setSession({ ...access, server });
await store.actions.setSession({ ...access, server});
await setSession({ ...access, server });
},
access: async (server, token) => {
const access = await setAccountAccess(server, token);
await setSession({ ...access, server });
await store.actions.setSession({ ...access, server});
await setSession({ ...access, server });
},
login: async (username, password) => {
const acc = username.split('@');
const access = await setLogin(acc[0], acc[1], password)
await setSession({ ...access, server: acc[1] });
await store.actions.setSession({ ...access, server: acc[1]});
await setSession({ ...access, server: acc[1] });
},
logout: async () => {
await clearSession();

View File

@ -8,6 +8,7 @@ import { getContactChannels } from 'api/getContactChannels';
import { getContactChannelTopics } from 'api/getContactChannelTopics';
import { getContactChannelDetail } from 'api/getContactChannelDetail';
import { getContactChannelSummary } from 'api/getContactChannelSummary';
import { getCardImageUrl } from 'api/getCardImageUrl';
export function useCardContext() {
const [state, setState] = useState({
@ -26,19 +27,38 @@ export function useCardContext() {
setState((s) => ({ ...s, ...value }))
}
const setCard = (cardId, card) => {
let updated = cards.current.get(cardId);
if (updated == null) {
updated = { channels: new Map() };
}
cards.current.set(cardId, {
...updated,
cardId: cardId,
revision: card?.revision,
detailRevision: card?.data?.detailRevision,
profileRevision: card?.data?.profileRevision,
detail: card?.data?.cardDetail,
profile: card?.data?.cardProfile,
notifiedView: card?.data?.notifiedView,
notifiedProfile: card?.data?.notifiedProfile,
notifiedArtile: card?.data?.notifiedArticle,
notifiedChannel: card?.data?.notifiedChannel,
});
}
const setCardDetail = (cardId, detail, revision) => {
let card = cards.current.get(cardId);
if (card?.data) {
card.data.cardDetail = detail;
card.data.detailRevision = revision;
if (card) {
card.detail = detail;
card.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;
if (card) {
card.profile = profile;
card.profileRevision = revision;
cards.current.set(cardId, card);
}
}
@ -64,6 +84,17 @@ export function useCardContext() {
}
}
const setCardChannel = (cardId, channel) => {
setCardChannelItem(cardId, {
cardId: cardId,
channelId: channel?.id,
revision: channel?.revision,
detailRevision: channel?.data?.detailRevision,
topicRevision: channel?.data?.topicRevision,
detail: channel?.data?.channelDetail,
summary: channel?.data?.channelSummary,
});
}
const setCardChannelItem = (cardId, channel) => {
let card = cards.current.get(cardId);
if (card) {
card.channels.set(channel.id, channel);
@ -74,9 +105,9 @@ export function useCardContext() {
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;
if (channel) {
channel.detail = detail;
channel.detailRevision = revision;
card.channels.set(channelId, channel);
cards.current.set(cardId, card);
}
@ -86,9 +117,9 @@ export function useCardContext() {
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;
if (channel) {
channel.summary = detail;
channel.topicRevision = revision;
card.channels.set(channelId, channel);
cards.current.set(cardId, card);
}
@ -128,7 +159,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);
setCard(card.id, card);
}
else {
const view = await store.actions.getCardItemView(guid, card.id);
@ -138,7 +169,7 @@ 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);
setCard(assembled.id, assembled);
}
else {
if (view.detailRevision != detailRevision) {
@ -185,7 +216,7 @@ export function useCardContext() {
}
}
catch(err) {
console.log(err);
console.log("card1:", err);
await store.actions.setCardItemOffsync(guid, card.id);
setCardOffsync(card.id, true);
}
@ -203,7 +234,7 @@ export function useCardContext() {
await store.actions.setCardRevision(guid, revision);
}
catch(err) {
console.log(err);
console.log("card2:", err);
syncing.current = false;
return;
}
@ -267,7 +298,7 @@ export function useCardContext() {
}
const cardChannelItems = await store.actions.getCardChannelItems(guid);
for (item of cardChannelItems) {
setCardChannel(item.cardId, item);
setCardChannelItem(item.cardId, item);
}
const revision = await store.actions.getCardRevision(guid);
updateState({ cards: cards.current });
@ -283,6 +314,10 @@ export function useCardContext() {
curRevision.current = rev;
sync();
},
getCardLogo: (cardId, revision) => {
const { server, appToken } = session.current;
return getCardImageUrl(server, appToken, cardId, revision);
}
}
return { state, actions }

View File

@ -20,19 +20,29 @@ export function useChannelContext() {
setState((s) => ({ ...s, ...value }))
}
const setChannelDetails = (channelId, details, revision) => {
const setChannel = (channelId, channel) => {
channels.current.set(channelId, {
channelId: channel?.id,
revision: channel?.revision,
detail: channel?.data?.channelDetail,
summary: channel?.data?.channelSummary,
detailRevision: channel?.data?.detailRevision,
topicRevision: channel?.data?.topicRevision,
});
}
const setChannelDetails = (channelId, detail, revision) => {
let channel = channels.current.get(channelId);
if (channel?.data) {
channel.data.channelDetails = details;
channel.data.detailRevision = revision;
channel.detail = detail;
channel.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;
if (channel) {
channel.summary = summary;
channel.topicRevision = revision;
channels.curent.set(channelId, channel);
}
}
@ -58,7 +68,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);
setChannel(channel.id, channel);
}
else {
const { detailRevision, topicRevision, channelDetail, channelSummary } = channel.data;
@ -69,7 +79,7 @@ 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);
setChannel(assembled.id, assembled);
}
else {
if (view.detailRevision != detailRevision) {

View File

@ -1,7 +1,7 @@
import { useEffect, useState, useRef, useContext } from 'react';
import SQLite from "react-native-sqlite-storage";
const DATABAG_DB = 'databag_v019.db';
const DATABAG_DB = 'databag_v025.db';
export function useStoreContext() {
const [state, setState] = useState({});
@ -113,18 +113,20 @@ export function useStoreContext() {
await db.current.executeSql(`UPDATE card_${guid} set profile_revision=?, profile=? where card_id=?`, [revision, encodeObject(profile), cardId]);
},
getCardItemStatus: async (guid, cardId) => {
const values = await getAppValues(db.current, `SELECT detail, profile, notified_view, notified_article, notified_profile, notified_channel, offsync FROM card_${guid} WHERE card_id=?`, [cardId]);
const values = await getAppValues(db.current, `SELECT detail, profile, profile_revision, detail_revision, notified_view, notified_article, notified_profile, notified_channel, offsync FROM card_${guid} WHERE card_id=?`, [cardId]);
if (!values.length) {
return null;
}
return {
detail: decodeObject(values[0].detail),
profile: decodeObject(values[0].profile),
offsync: values[0].offsync,
profileRevision: values[0].profile_revision,
detailRevision: values[0].detail_revision,
notifiedView: values[0].notified_view,
notifiedArticle: values[0].notified_article,
notifiedProfile: values[0].notified_profile,
notifiedChannel: values[0].notified_cahnnel,
offsync: values[0].offsync,
};
},
getCardItemView: async (guid, cardId) => {

View File

@ -3,6 +3,7 @@ import { FlatList, ScrollView, View, TextInput, TouchableOpacity, Text } from 'r
import { styles } from './Channels.styled';
import { useChannels } from './useChannels.hook';
import Ionicons from '@expo/vector-icons/AntDesign';
import { ChannelItem } from './channelItem/ChannelItem';
export function Channels() {
@ -18,7 +19,7 @@ export function Channels() {
</View>
<FlatList style={styles.channels}
data={state.channels}
renderItem={({ item }) => <Text>{ item.channelId }</Text>}
renderItem={({ item }) => <ChannelItem item={item} />}
keyExtractor={item => (`${item.cardId}:${item.channelId}`)}
/>
</View>

View File

@ -0,0 +1,7 @@
import { Text } from 'react-native';
import { Logo } from 'utils/Logo';
export function ChannelItem({ item }) {
return <Logo src={item.logo} width={32} height={32} />
}

View File

@ -1,6 +1,7 @@
import { useState, useEffect, useContext } from 'react';
import { useWindowDimensions } from 'react-native';
import { useNavigate } from 'react-router-dom';
import { CardContext } from 'context/CardContext';
import { ChannelContext } from 'context/ChannelContext';
import config from 'constants/Config';
@ -12,14 +13,57 @@ export function useChannels() {
});
const channel = useContext(ChannelContext);
const card = useContext(CardContext);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
const getCard = (guid) => {
let contact = null
card.state.cards.forEach((card, cardId, map) => {
if (card?.profile?.guid === guid) {
contact = card;
}
});
return contact;
}
const setChannelEntry = (item) => {
let contacts = [];
if (item?.detail?.members) {
item.detail.members.forEach(guid => {
contacts.push(getCard(guid));
})
}
let logo = null;
if (contacts.length === 0) {
logo = 'solution';
}
else if (contacts.length === 1) {
if (contacts[0]?.profile?.imageSet) {
logo = card.actions.getCardLogo(contacts[0].cardId, contacts[0].profileRevision);
}
else {
logo = 'avatar';
}
}
else {
logo = 'appstore';
}
return {
channelId: item.channelId,
contacts: contacts,
logo: logo,
}
}
useEffect(() => {
updateState({ channels: Array.from(channel.state.channels.values()) });
}, [channel]);
const channels = Array.from(channel.state.channels.values()).map(item => setChannelEntry(item));
updateState({ channels });
}, [channel, card]);
const actions = {
setTopic: (topic) => {

View File

@ -1,4 +1,4 @@
import { Image } from 'react-native';
import { Image, View } from 'react-native';
import avatar from 'images/avatar.png';
import appstore from 'images/appstore.png';
import solution from 'images/solution.png';
@ -6,7 +6,7 @@ import team from 'images/team.png';
export function Logo({ src, width, height, radius }) {
return (
<div style={{ borderRadius: radius, overflow: 'hidden' }}>
<View style={{ borderRadius: radius, overflow: 'hidden' }}>
{ src === 'team' && (
<Image source={team} style={{ width, height }} />
)}
@ -23,9 +23,9 @@ export function Logo({ src, width, height, radius }) {
<Image source={avatar} style={{ width, height }} />
)}
{ src && src.startsWith('http') && (
<Image source={src} style={{ width, height }} />
<Image source={{ uri:src }} resizeMode={'contain'} style={{ width, height }} />
)}
</div>
</View>
);
}