From 9ffd2f6c7f42c0f6c5d0d951b998f5b0b6c9a498 Mon Sep 17 00:00:00 2001 From: Roland Osborne Date: Mon, 27 Feb 2023 10:31:26 -0800 Subject: [PATCH] more channels refactor --- app/mobile/src/context/sealUtil.js | 2 +- .../src/context/useStoreContext.hook.js | 10 +- .../channels/channelItem/ChannelItem.jsx | 4 +- .../src/session/channels/useChannels.hook.js | 112 ++++++++++++------ 4 files changed, 85 insertions(+), 43 deletions(-) diff --git a/app/mobile/src/context/sealUtil.js b/app/mobile/src/context/sealUtil.js index eb54af50..1af3fe0f 100644 --- a/app/mobile/src/context/sealUtil.js +++ b/app/mobile/src/context/sealUtil.js @@ -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) { diff --git a/app/mobile/src/context/useStoreContext.hook.js b/app/mobile/src/context/useStoreContext.hook.js index fcf5f71b..081b3f29 100644 --- a/app/mobile/src/context/useStoreContext.hook.js +++ b/app/mobile/src/context/useStoreContext.hook.js @@ -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]); diff --git a/app/mobile/src/session/channels/channelItem/ChannelItem.jsx b/app/mobile/src/session/channels/channelItem/ChannelItem.jsx index 829df563..bd7baa22 100644 --- a/app/mobile/src/session/channels/channelItem/ChannelItem.jsx +++ b/app/mobile/src/session/channels/channelItem/ChannelItem.jsx @@ -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 ( openConversation(item.cardId, item.channelId, item.revision)}> - + { item.locked && !item.unlocked && ( diff --git a/app/mobile/src/session/channels/useChannels.hook.js b/app/mobile/src/session/channels/useChannels.hook.js index 318b03e5..eee7ba11 100644 --- a/app/mobile/src/session/channels/useChannels.hook.js +++ b/app/mobile/src/session/channels/useChannels.hook.js @@ -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 });