more channels refactor

This commit is contained in:
Roland Osborne 2023-02-27 10:31:26 -08:00
parent 233bcb01e9
commit 9ffd2f6c7f
4 changed files with 85 additions and 43 deletions

View File

@ -69,7 +69,7 @@ export function decryptChannelSubject(subject, contentKey) {
if (!str) {
return null;
}
return JSON.parse(dec.toString(CryptoJS.enc.Utf8));
return JSON.parse(str);
}
export function encryptTopicSubject(subject, contentKey) {

View File

@ -1,7 +1,7 @@
import { useEffect, useState, useRef, useContext } from 'react';
import SQLite from "react-native-sqlite-storage";
const DATABAG_DB = 'db_v_107.db';
const DATABAG_DB = 'db_v_110.db';
export function useStoreContext() {
const [state, setState] = useState({});
@ -102,8 +102,8 @@ export function useStoreContext() {
await db.current.executeSql("INSERT OR REPLACE INTO app (key, value) values (?, ?);", [dataId, encodeObject(revision)]);
},
setCardItem: async (guid, card) => {
const { id, revision, data } = card;
await db.current.executeSql(`INSERT OR REPLACE INTO card_${guid} (card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`, [card.cardId, card.revision, card.detailRevision, card.profileRevision, encodeObject(card.detail), encodeObject(card.profile), null, null, null, null]);
const { cardId, revision, detailRevision, profileRevision, detail, profile } = card;
await db.current.executeSql(`INSERT OR REPLACE INTO card_${guid} (card_id, revision, detail_revision, profile_revision, detail, profile, notified_view, notified_profile, notified_article, notified_channel) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?);`, [cardId, revision, detailRevision, profileRevision, encodeObject(detail), encodeObject(profile), null, null, null, null]);
},
clearCardItem: async (guid, cardId) => {
await db.current.executeSql(`DELETE FROM card_${guid} WHERE card_id=?`, [cardId]);
@ -168,8 +168,8 @@ export function useStoreContext() {
await db.current.executeSql("INSERT OR REPLACE INTO app (key, value) values (?, ?);", [dataId, encodeObject(revision)]);
},
setChannelItem: async (guid, channel) => {
const { id, revision, detailRevision, topicRevision, detail, summary } = channel;
await db.current.executeSql(`INSERT OR REPLACE INTO channel_${guid} (channel_id, revision, detail_revision, topic_revision, detail, summary, unsealed_detail, unsealed_summary) values (?, ?, ?, ?, ?, ?, null, null);`, [id, revision, detailRevision, topicRevision, encodeObject(detail), encodeObject(summary)]);
const { channelId, revision, detailRevision, topicRevision, detail, summary } = channel;
await db.current.executeSql(`INSERT OR REPLACE INTO channel_${guid} (channel_id, revision, detail_revision, topic_revision, detail, summary, unsealed_detail, unsealed_summary) values (?, ?, ?, ?, ?, ?, null, null);`, [channelId, revision, detailRevision, topicRevision, encodeObject(detail), encodeObject(summary)]);
},
clearChannelItem: async (guid, channelId) => {
await db.current.executeSql(`DELETE FROM channel_${guid} WHERE channel_id=?`, [channelId]);

View File

@ -4,13 +4,13 @@ import { Logo } from 'utils/Logo';
import { styles } from './ChannelItem.styled';
import { useChannelItem } from './useChannelItem.hook';
import Colors from 'constants/Colors';
import Ionicons from 'react-native-vector-icons/AntDesign';
import Ionicons from 'react-native-vector-icons/MaterialCommunityIcons';
export function ChannelItem({ item, openConversation }) {
return (
<TouchableOpacity style={styles.container} activeOpacity={1} onPress={() => openConversation(item.cardId, item.channelId, item.revision)}>
<Logo src={item.logo} width={32} height={32} radius={6} />
<Logo src={item.logo} width={32} height={32} radius={3} />
<View style={styles.detail}>
<View style={styles.subject}>
{ item.locked && !item.unlocked && (

View File

@ -1,10 +1,10 @@
import { useState, useEffect, useContext } from 'react';
import { useState, useRef, useEffect, useContext } from 'react';
import { ChannelContext } from 'context/ChannelContext';
import { CardContext } from 'context/CardContext';
import { AccountContext } from 'context/AccountContext';
import { AppContext } from 'context/AppContext';
import { ProfileContext } from 'context/ProfileContext';
import { getChannelSeals, isUnsealed } from 'context/sealUtil';
import { getChannelSeals, isUnsealed, getContentKey, decryptChannelSubject } from 'context/sealUtil';
import { getCardByGuid } from 'context/cardUtil';
export function useChannels() {
@ -19,11 +19,16 @@ export function useChannels() {
const profile = useContext(ProfileContext);
const app = useContext(AppContext);
const syncing = useRef(false);
const resync = useRef(false);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
}
const setChannelItem = (loginTimestamp, cardId, channelId, item) => {
const setChannelItem = async (loginTimestamp, cardId, channelId, item) => {
console.log('set channel item', cardId, channelId);
const timestamp = item.summary.lastTopic.created;
const { readRevision, topicRevision } = item;
@ -33,15 +38,33 @@ export function useChannels() {
let message;
let subject;
if (item.detail.dataType === 'sealed') {
console.log("SEALED TYPE");
locked = true;
console.log("CHECK1");
const seals = getChannelSeals(item.detail.data);
console.log("CHECK2");
if (isUnsealed(seals, account.state.sealKey)) {
console.log("CHECK3");
unlocked = true;
if (item.detail.unsealedDetail) {
if (item.unsealedDetail) {
subject = item.detail.unsealedDetail.subject;
}
else {
// decrypt detail
console.log("TRYING");
try {
const contentKey = await getContentKey(seals, account.state.sealKey);
const unsealed = decryptChannelSubject(item.detail.data, contentKey);
if (cardId) {
await card.actions.setUnsealedChannelSubject(cardId, channelId, item.revision, unsealed);
}
else {
await channel.actions.setUnsealedChannelSubject(channelId, item.detailRevision, unsealed);
}
subject = unsealed.subject;
}
catch(err) {
console.log(err);
}
}
if (item.summary.lastTopic.dataType === 'sealedtopic') {
if (item.summary.unsealedSummary) {
@ -123,38 +146,57 @@ export function useChannels() {
}
useEffect(() => {
const { loginTimestamp } = app.state;
const channels = [];
channel.state.channels.forEach((item, channelId) => {
channels.push(setChannelItem(loginTimestamp, null, channelId, item));
});
card.state.cards.forEach((cardItem, cardId) => {
cardItem.channels.forEach((channelItem, channelId) => {
channels.push(setChannelItem(loginTimestamp, cardId, channelId, channelItem));
});
});
const filtered = channels.filter(item => {
if (!state.filter) {
return true;
}
const filterCase = state.filter.toUpperCase();
const subjectCase = item.subject.toUpperCase();
return subjectCase.includes(filterCase);
});
const sorted = filtered.sort((a, b) => {
const aCreated = a?.timestamp;
const bCreated = b?.timestamp;
if (aCreated === bCreated) {
return 0;
}
if (!aCreated || aCreated < bCreated) {
return 1;
}
return -1;
});
updateState({ channels: sorted });
syncChannels();
}, [app.state, card.state, channel.state, state.filter]);
const syncChannels = async () => {
if (!syncing.current) {
syncing.current = true;
const { loginTimestamp } = app.state;
const items = [];
channel.state.channels.forEach((item, channelId) => {
items.push({ loginTimestamp, channelId, channelItem: item });
});
card.state.cards.forEach((cardItem, cardId) => {
cardItem.channels.forEach((channelItem, channelId) => {
items.push({ loginTimestamp, cardId, channelId, channelItem });
});
});
const channels = [];
for (let i = 0; i < items.length; i++) {
const { loginTimestamp, cardId, channelId, channelItem } = items[i];
channels.push(await setChannelItem(loginTimestamp, cardId, channelId, channelItem));
}
const filtered = channels.filter(item => {
if (!state.filter) {
return true;
}
const filterCase = state.filter.toUpperCase();
const subjectCase = item.subject.toUpperCase();
return subjectCase.includes(filterCase);
});
const sorted = filtered.sort((a, b) => {
const aCreated = a?.timestamp;
const bCreated = b?.timestamp;
if (aCreated === bCreated) {
return 0;
}
if (!aCreated || aCreated < bCreated) {
return 1;
}
return -1;
});
updateState({ channels: sorted });
syncing.current = false;
if(resync.current) {
resync.current = false;
await syncChannels();
}
}
};
const actions = {
setFilter: (filter) => {
updateState({ filter });