mirror of
https://github.com/balzack/databag.git
synced 2025-02-15 21:19:16 +00:00
support resyncing of contacts
This commit is contained in:
parent
cb544071ce
commit
43bf6d0d04
@ -310,7 +310,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 18;
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
DEVELOPMENT_TEAM = 3P65PQ7SUR;
|
DEVELOPMENT_TEAM = 3P65PQ7SUR;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
@ -348,7 +348,7 @@
|
|||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 18;
|
CURRENT_PROJECT_VERSION = 19;
|
||||||
DEVELOPMENT_TEAM = 3P65PQ7SUR;
|
DEVELOPMENT_TEAM = 3P65PQ7SUR;
|
||||||
INFOPLIST_FILE = Databag/Info.plist;
|
INFOPLIST_FILE = Databag/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = Databag;
|
INFOPLIST_KEY_CFBundleDisplayName = Databag;
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import { useState, useRef, useContext } from 'react';
|
import { useState, useRef, useContext } from 'react';
|
||||||
import { StoreContext } from 'context/StoreContext';
|
import { StoreContext } from 'context/StoreContext';
|
||||||
import { UploadContext } from 'context/UploadContext';
|
import { UploadContext } from 'context/UploadContext';
|
||||||
|
import { getCard } from 'api/getCard';
|
||||||
import { getCards } from 'api/getCards';
|
import { getCards } from 'api/getCards';
|
||||||
import { getCardProfile } from 'api/getCardProfile';
|
import { getCardProfile } from 'api/getCardProfile';
|
||||||
import { setCardProfile } from 'api/setCardProfile';
|
import { setCardProfile } from 'api/setCardProfile';
|
||||||
@ -42,15 +43,16 @@ export function useCardContext() {
|
|||||||
const syncing = useRef(false);
|
const syncing = useRef(false);
|
||||||
const cards = useRef(new Map());
|
const cards = useRef(new Map());
|
||||||
const cardChannels = useRef(new Map());
|
const cardChannels = useRef(new Map());
|
||||||
|
const resync = useRef([]);
|
||||||
|
|
||||||
const updateState = (value) => {
|
const updateState = (value) => {
|
||||||
setState((s) => ({ ...s, ...value }))
|
setState((s) => ({ ...s, ...value }))
|
||||||
}
|
}
|
||||||
|
|
||||||
const getCard = (cardId) => {
|
const getCardEntry = (cardId) => {
|
||||||
const card = cards.current.get(cardId);
|
const card = cards.current.get(cardId);
|
||||||
if (!card) {
|
if (!card) {
|
||||||
throw new Error('cared not found');
|
throw new Error('card not found');
|
||||||
}
|
}
|
||||||
return card;
|
return card;
|
||||||
}
|
}
|
||||||
@ -213,12 +215,12 @@ export function useCardContext() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const sync = async () => {
|
const sync = async () => {
|
||||||
if (!syncing.current && setRevision.current !== curRevision.current) {
|
if (!syncing.current && (setRevision.current !== curRevision.current || resync.current.length > 0)) {
|
||||||
syncing.current = true;
|
syncing.current = true;
|
||||||
|
const { server, appToken, guid } = session.current;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const revision = curRevision.current;
|
const revision = curRevision.current;
|
||||||
const { server, appToken, guid } = session.current;
|
|
||||||
|
|
||||||
// get and store
|
// get and store
|
||||||
const delta = await getCards(server, appToken, setRevision.current);
|
const delta = await getCards(server, appToken, setRevision.current);
|
||||||
@ -254,41 +256,7 @@ export function useCardContext() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const status = await store.actions.getCardItemStatus(guid, card.id);
|
await syncCard(card);
|
||||||
const cardServer = status.profile.node;
|
|
||||||
const cardToken = status.profile.guid + '.' + status.detail.token;
|
|
||||||
if (status.detail.status === 'connected') {
|
|
||||||
try {
|
|
||||||
const { notifiedView, notifiedProfile, notifiedArticle, notifiedChannel } = card.data;
|
|
||||||
if (status.notifiedView !== notifiedView) {
|
|
||||||
await store.actions.clearCardChannelItems(guid, card.id);
|
|
||||||
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) {
|
|
||||||
await updateCardChannelItems(card.id, cardServer, cardToken, status.notifiedView, status.notifiedChannel)
|
|
||||||
await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (status.notifiedProfile != notifiedProfile) {
|
|
||||||
const message = await getContactProfile(cardServer, cardToken);
|
|
||||||
await setCardProfile(server, appToken, card.id, message);
|
|
||||||
await store.actions.setCardItemNotifiedProfile(guid, card.id, notifiedProfile);
|
|
||||||
}
|
|
||||||
if (status.offsync) {
|
|
||||||
await store.actions.clearCardItemOffsync(guid, card.id);
|
|
||||||
setCardOffsync(card.id, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(err) {
|
|
||||||
console.log("card1:", err);
|
|
||||||
await store.actions.setCardItemOffsync(guid, card.id);
|
|
||||||
setCardOffsync(card.id, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
//TODO clear card channel topics
|
//TODO clear card channel topics
|
||||||
@ -307,12 +275,65 @@ export function useCardContext() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (resync.current.length > 0) {
|
||||||
|
const ids = resync.current;
|
||||||
|
resync.current = [];
|
||||||
|
|
||||||
|
for(let i = 0; i < ids.length; i++) {
|
||||||
|
const item = cards.current.get(ids[i]);
|
||||||
|
if (item) {
|
||||||
|
const card = await getCard(server, appToken, ids[i]);
|
||||||
|
await syncCard(card);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
updateState({ cards: cards.current });
|
updateState({ cards: cards.current });
|
||||||
syncing.current = false;
|
syncing.current = false;
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const syncCard = async (card) => {
|
||||||
|
|
||||||
|
const { server, appToken, guid } = session.current;
|
||||||
|
const status = await store.actions.getCardItemStatus(guid, card.id);
|
||||||
|
const cardServer = status.profile.node;
|
||||||
|
const cardToken = status.profile.guid + '.' + status.detail.token;
|
||||||
|
if (status.detail.status === 'connected') {
|
||||||
|
try {
|
||||||
|
const { notifiedView, notifiedProfile, notifiedArticle, notifiedChannel } = card.data;
|
||||||
|
if (status.notifiedView !== notifiedView) {
|
||||||
|
await store.actions.clearCardChannelItems(guid, card.id);
|
||||||
|
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) {
|
||||||
|
await updateCardChannelItems(card.id, cardServer, cardToken, status.notifiedView, status.notifiedChannel)
|
||||||
|
await store.actions.setCardItemNotifiedChannel(guid, card.id, notifiedChannel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (status.notifiedProfile != notifiedProfile) {
|
||||||
|
const message = await getContactProfile(cardServer, cardToken);
|
||||||
|
await setCardProfile(server, appToken, card.id, message);
|
||||||
|
await store.actions.setCardItemNotifiedProfile(guid, card.id, notifiedProfile);
|
||||||
|
}
|
||||||
|
if (status.offsync) {
|
||||||
|
await store.actions.clearCardItemOffsync(guid, card.id);
|
||||||
|
setCardOffsync(card.id, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(err) {
|
||||||
|
console.log("card1:", err);
|
||||||
|
await store.actions.setCardItemOffsync(guid, card.id);
|
||||||
|
setCardOffsync(card.id, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const updateCardChannelItems = async (cardId, cardServer, cardToken, notifiedView, notifiedChannel) => {
|
const updateCardChannelItems = async (cardId, cardServer, cardToken, notifiedView, notifiedChannel) => {
|
||||||
const { guid } = session.current;
|
const { guid } = session.current;
|
||||||
const delta = await getContactChannels(cardServer, cardToken, notifiedView, notifiedChannel);
|
const delta = await getContactChannels(cardServer, cardToken, notifiedView, notifiedChannel);
|
||||||
@ -501,19 +522,19 @@ export function useCardContext() {
|
|||||||
return await store.actions.clearCardChannelTopicItems(guid, cardId, channelId);
|
return await store.actions.clearCardChannelTopicItems(guid, cardId, channelId);
|
||||||
},
|
},
|
||||||
getChannelTopic: async (cardId, channelId, topicId) => {
|
getChannelTopic: async (cardId, channelId, topicId) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
return await getContactChannelTopic(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId);
|
return await getContactChannelTopic(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId);
|
||||||
},
|
},
|
||||||
getChannelTopics: async (cardId, channelId, revision) => {
|
getChannelTopics: async (cardId, channelId, revision) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
return await getContactChannelTopics(profile.node, `${profile.guid}.${detail.token}`, channelId, revision);
|
return await getContactChannelTopics(profile.node, `${profile.guid}.${detail.token}`, channelId, revision);
|
||||||
},
|
},
|
||||||
getChannelTopicAssetUrl: (cardId, channelId, topicId, assetId) => {
|
getChannelTopicAssetUrl: (cardId, channelId, topicId, assetId) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
return getContactChannelTopicAssetUrl(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId, assetId);
|
return getContactChannelTopicAssetUrl(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId, assetId);
|
||||||
},
|
},
|
||||||
addChannelTopic: async (cardId, channelId, message, files) => {
|
addChannelTopic: async (cardId, channelId, message, files) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
const node = profile.node;
|
const node = profile.node;
|
||||||
const token = `${profile.guid}.${detail.token}`;
|
const token = `${profile.guid}.${detail.token}`;
|
||||||
if (files?.length > 0) {
|
if (files?.length > 0) {
|
||||||
@ -535,17 +556,21 @@ export function useCardContext() {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
setChannelTopicSubject: async (cardId, channelId, topicId, data) => {
|
setChannelTopicSubject: async (cardId, channelId, topicId, data) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
return await setContactChannelTopicSubject(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId, data);
|
return await setContactChannelTopicSubject(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId, data);
|
||||||
},
|
},
|
||||||
removeChannel: async (cardId, channelId) => {
|
removeChannel: async (cardId, channelId) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
return await removeContactChannel(profile.node, `${profile.guid}.${detail.token}`, channelId);
|
return await removeContactChannel(profile.node, `${profile.guid}.${detail.token}`, channelId);
|
||||||
},
|
},
|
||||||
removeChannelTopic: async (cardId, channelId, topicId) => {
|
removeChannelTopic: async (cardId, channelId, topicId) => {
|
||||||
const { detail, profile } = getCard(cardId);
|
const { detail, profile } = getCardEntry(cardId);
|
||||||
return await removeContactChannelTopic(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId);
|
return await removeContactChannelTopic(profile.node, `${profile.guid}.${detail.token}`, channelId, topicId);
|
||||||
},
|
},
|
||||||
|
resync: (cardId) => {
|
||||||
|
resync.current.push(cardId);
|
||||||
|
sync();
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return { state, actions }
|
return { state, actions }
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { useEffect, useState, useRef, useContext } from 'react';
|
import { useEffect, useState, useRef, useContext } from 'react';
|
||||||
import SQLite from "react-native-sqlite-storage";
|
import SQLite from "react-native-sqlite-storage";
|
||||||
|
|
||||||
const DATABAG_DB = 'databag_v046.db';
|
const DATABAG_DB = 'databag_v047.db';
|
||||||
|
|
||||||
export function useStoreContext() {
|
export function useStoreContext() {
|
||||||
const [state, setState] = useState({});
|
const [state, setState] = useState({});
|
||||||
|
@ -20,7 +20,10 @@ export function CardItem({ item, openContact }) {
|
|||||||
<Text style={styles.name} numberOfLines={1} ellipsizeMode={'tail'}>{ item.name }</Text>
|
<Text style={styles.name} numberOfLines={1} ellipsizeMode={'tail'}>{ item.name }</Text>
|
||||||
<Text style={styles.handle} numberOfLines={1} ellipsizeMode={'tail'}>{ item.handle }</Text>
|
<Text style={styles.handle} numberOfLines={1} ellipsizeMode={'tail'}>{ item.handle }</Text>
|
||||||
</View>
|
</View>
|
||||||
{ item.status === 'connected' && (
|
{ item.status === 'connected' && item.offsync === 1 && (
|
||||||
|
<View style={styles.offsync} />
|
||||||
|
)}
|
||||||
|
{ item.status === 'connected' && item.offsync !== 1 && (
|
||||||
<View style={styles.connected} />
|
<View style={styles.connected} />
|
||||||
)}
|
)}
|
||||||
{ item.status === 'requested' && (
|
{ item.status === 'requested' && (
|
||||||
|
@ -48,6 +48,12 @@ export const styles = StyleSheet.create({
|
|||||||
borderRadius: 4,
|
borderRadius: 4,
|
||||||
backgroundColor: Colors.connecting,
|
backgroundColor: Colors.connecting,
|
||||||
},
|
},
|
||||||
|
offsync: {
|
||||||
|
width: 8,
|
||||||
|
height: 8,
|
||||||
|
borderRadius: 4,
|
||||||
|
backgroundColor: Colors.error,
|
||||||
|
},
|
||||||
pending: {
|
pending: {
|
||||||
width: 8,
|
width: 8,
|
||||||
height: 8,
|
height: 8,
|
||||||
|
@ -39,6 +39,7 @@ export function useCards() {
|
|||||||
status: detail.status,
|
status: detail.status,
|
||||||
offsync: item.offsync,
|
offsync: item.offsync,
|
||||||
blocked: item.blocked,
|
blocked: item.blocked,
|
||||||
|
offsync: item.offsync,
|
||||||
updated: detail.statusUpdated,
|
updated: detail.statusUpdated,
|
||||||
logo: profile.imageSet ? card.actions.getCardLogo(item.cardId, profile.revision) : 'avatar',
|
logo: profile.imageSet ? card.actions.getCardLogo(item.cardId, profile.revision) : 'avatar',
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,18 @@ import Colors from 'constants/Colors';
|
|||||||
|
|
||||||
export function ContactTitle({ contact, closeContact }) {
|
export function ContactTitle({ contact, closeContact }) {
|
||||||
const { state, actions } = useContact(contact, closeContact);
|
const { state, actions } = useContact(contact, closeContact);
|
||||||
return (<Text style={styles.title}>{ `${state.handle}@${state.node}` }</Text>);
|
|
||||||
|
return (
|
||||||
|
<TouchableOpacity style={styles.resync} activeOpacity={1} onPress={actions.resync}>
|
||||||
|
<View style={styles.icon} />
|
||||||
|
<Text style={styles.title}>{ `${state.handle}@${state.node}` }</Text>
|
||||||
|
<View style={styles.icon}>
|
||||||
|
{ state.offsync === 1 && (
|
||||||
|
<Ionicons name="exclamationcircleo" size={16} color={Colors.alert} />
|
||||||
|
)}
|
||||||
|
</View>
|
||||||
|
</TouchableOpacity>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function Contact({ contact, closeContact }) {
|
export function Contact({ contact, closeContact }) {
|
||||||
|
@ -18,6 +18,16 @@ export const styles = StyleSheet.create({
|
|||||||
title: {
|
title: {
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
},
|
},
|
||||||
|
resync: {
|
||||||
|
display: 'flex',
|
||||||
|
flexDirection: 'row',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
},
|
||||||
|
icon: {
|
||||||
|
width: 32,
|
||||||
|
paddingLeft: 8
|
||||||
|
},
|
||||||
drawer: {
|
drawer: {
|
||||||
paddingTop: 16,
|
paddingTop: 16,
|
||||||
},
|
},
|
||||||
|
@ -18,7 +18,8 @@ export function useContact(contact, close) {
|
|||||||
status: null,
|
status: null,
|
||||||
cardId: null,
|
cardId: null,
|
||||||
guid: null,
|
guid: null,
|
||||||
busy: false
|
busy: false,
|
||||||
|
offsync: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const dimensions = useWindowDimensions();
|
const dimensions = useWindowDimensions();
|
||||||
@ -42,10 +43,10 @@ export function useContact(contact, close) {
|
|||||||
if (contact?.card) {
|
if (contact?.card) {
|
||||||
const selected = card.state.cards.get(contact.card);
|
const selected = card.state.cards.get(contact.card);
|
||||||
if (selected) {
|
if (selected) {
|
||||||
const { profile, detail, cardId } = selected;
|
const { offsync, profile, detail, cardId } = selected;
|
||||||
const { name, handle, node, location, description, guid, imageSet, revision } = profile;
|
const { name, handle, node, location, description, guid, imageSet, revision } = profile;
|
||||||
const logo = imageSet ? card.actions.getCardLogo(cardId, revision) : 'avatar';
|
const logo = imageSet ? card.actions.getCardLogo(cardId, revision) : 'avatar';
|
||||||
updateState({ name, handle, node, location, description, logo, cardId, guid, status: detail.status });
|
updateState({ offsync, name, handle, node, location, description, logo, cardId, guid, status: detail.status });
|
||||||
stateSet = true;
|
stateSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,12 +57,12 @@ export function useContact(contact, close) {
|
|||||||
const { cardId, profile, detail } = selected;
|
const { cardId, profile, detail } = selected;
|
||||||
const { name, handle, node, location, description, guid, imageSet, revision } = profile;
|
const { name, handle, node, location, description, guid, imageSet, revision } = profile;
|
||||||
const logo = imageSet ? card.actions.getCardLogo(cardId, revision) : 'avatar';
|
const logo = imageSet ? card.actions.getCardLogo(cardId, revision) : 'avatar';
|
||||||
updateState({ name, handle, node, location, description, logo, cardId, guid, status: detail.status });
|
updateState({ offsync, name, handle, node, location, description, logo, cardId, guid, status: detail.status });
|
||||||
stateSet = true;
|
stateSet = true;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const { name, handle, node, location, description, logo, guid } = contact.account;
|
const { name, handle, node, location, description, logo, guid } = contact.account;
|
||||||
updateState({ name, handle, node, location, description, logo, guid, cardId: null, status: null });
|
updateState({ offsync: false, name, handle, node, location, description, logo, guid, cardId: null, status: null });
|
||||||
stateSet = true;
|
stateSet = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -176,6 +177,9 @@ export function useContact(contact, close) {
|
|||||||
close();
|
close();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
resync: () => {
|
||||||
|
card.actions.resync(contact.card);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { state, actions };
|
return { state, actions };
|
||||||
|
Loading…
Reference in New Issue
Block a user