optimizing conversation load

This commit is contained in:
Roland Osborne 2023-03-03 10:30:28 -08:00
parent 74305a0994
commit ef1c81343d
8 changed files with 103 additions and 41 deletions

View File

@ -87,16 +87,18 @@ export function useConversationContext() {
if (!curTopicMarker.current) {
const delta = await getTopicDelta(cardId, channelId, null, COUNT, null, null);
await setTopicDelta(cardId, channelId, delta.topics);
await setMarkerAndSync(cardId, channelId, delta.marker, delta.revision);
curTopicMarker.current = delta.marker;
const marker = delta.marker ? delta.marker : 1;
await setMarkerAndSync(cardId, channelId, marker, delta.revision);
curTopicMarker.current = marker;
curSyncRevision.current = delta.revision;
updateState({ loaded: true, offsync: false, topics: topics.current, card: cardValue, channel: channelValue });
}
else if (loadMore && marker) {
const delta = await getTopicDelta(cardId, channelId, null, COUNT, null, curTopicMarker.current);
const marker = delta.marker ? delta.marker : 1;
await setTopicDelta(cardId, channelId, delta.topics);
await setTopicMarker(cardId, channelId, delta.marker);
curTopicMarker.current = delta.marker;
await setTopicMarker(cardId, channelId, marker);
curTopicMarker.current = marker;
updateState({ loaded: true, offsync: false, topics: topics.current, card: cardValue, channel: channelValue });
}
else if (ignoreRevision || topicRevision > curSyncRevision.current) {
@ -105,8 +107,6 @@ export function useConversationContext() {
await setSyncRevision(cardId, channelId, delta.revision);
curSyncRevision.current = delta.revision;
updateState({ loaded: true, offsync: false, topics: topics.current, card: cardValue, channel: channelValue });
console.log("HEADER", delta);
}
else {
updateState({ loaded: true, offsync: false, topics: topics.current, card: cardValue, channel: channelValue });
@ -419,7 +419,6 @@ console.log("HEADER", delta);
topic[field] = value;
}
topics.current.set(topicId, { ...topic });
updateState({ topics: topics.current });
};
return { state, actions }

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_123.db';
const DATABAG_DB = 'db_v_126.db';
export function useStoreContext() {
const [state, setState] = useState({});

View File

@ -56,7 +56,7 @@ export function Conversation({ navigation, cardId, channelId, closeConversation,
),
});
}
}, [navigation, state.subject]);
}, [navigation, state.subject, state.loaded]);
useEffect(() => {
return () => { closeConversation(); };
@ -85,7 +85,7 @@ export function Conversation({ navigation, cardId, channelId, closeConversation,
<ActivityIndicator color={Colors.grey} size="large" />
</View>
)}
{ state.loaded && (
{ state.loaded && state.topics.length !== 0 && (
<FlatList style={styles.conversation}
contentContainerStyle={styles.topics}
data={state.topics}
@ -93,14 +93,18 @@ export function Conversation({ navigation, cardId, channelId, closeConversation,
initialNumToRender={16}
renderItem={({item}) => <TopicItem item={item} focused={item.topicId === state.focus}
focus={() => actions.setFocus(item.topicId)} hosting={state.host == null}
sealed={state.sealed} sealKey={state.sealKey}
remove={actions.removeTopic} update={actions.editTopic} block={actions.blockTopic}
report={actions.reportTopic} />}
report={actions.reportTopic} contentKey={state.contentKey} /> }
keyExtractor={item => item.topicId}
/>
)}
{ state.loaded && state.topics.length === 0 && (
<View style={styles.empty}>
<Text style={styles.emptytext}>Empty Topic</Text>
</View>
<AddTopic />
)}
</View>
<AddTopic contentKey={state.contentKey} />
</View>
</View>
);

View File

@ -67,5 +67,15 @@ export const styles = StyleSheet.create({
alignItems: 'center',
justifyContent: 'center',
},
empty: {
display: 'flex',
flexGrow: 1,
alignItems: 'center',
justifyContent: 'center',
},
emptytext: {
fontSize: 18,
color: Colors.disabled,
},
});

View File

@ -13,9 +13,9 @@ import { VideoFile } from './videoFile/VideoFile';
import { AudioFile } from './audioFile/AudioFile';
import { ImageFile } from './imageFile/ImageFile';
export function AddTopic({ sealed, sealKey }) {
export function AddTopic({ contentKey }) {
const { state, actions } = useAddTopic(sealed, sealKey);
const { state, actions } = useAddTopic(contentKey);
const message = useRef();
const addImage = async () => {
@ -132,22 +132,22 @@ export function AddTopic({ sealed, sealKey }) {
onSubmitEditing={sendMessage} returnKeyType="send"
autoCapitalize="sentences" placeholder="New Message" multiline={true} />
<View style={styles.addButtons}>
{ !sealed && state.enableImage && (
{ !state.locked && state.enableImage && (
<TouchableOpacity style={styles.addButton} onPress={addImage}>
<AntIcons name="picture" size={20} color={Colors.text} />
</TouchableOpacity>
)}
{ !sealed && state.enableVideo && (
{ !state.locked && state.enableVideo && (
<TouchableOpacity style={styles.addButton} onPress={addVideo}>
<MatIcons name="video-outline" size={24} color={Colors.text} />
</TouchableOpacity>
)}
{ !sealed && state.enableAudio && (
{ !state.locked && state.enableAudio && (
<TouchableOpacity style={styles.addButton} onPress={addAudio}>
<MatIcons name="music-box-outline" size={20} color={Colors.text} />
</TouchableOpacity>
)}
{ !sealed && (
{ !state.locked && (
<View style={styles.divider} />
)}
<TouchableOpacity style={styles.addButton} onPress={actions.showFontSize}>
@ -161,10 +161,13 @@ export function AddTopic({ sealed, sealKey }) {
{ state.busy && (
<ActivityIndicator color={Colors.primary} />
)}
{ !state.busy && (state.message || state.assets.length > 0) && (
{ state.locked && !contentKey && (
<MatIcons name="lock" size={20} color={Colors.lightgrey} />
)}
{ !state.busy && (!state.locked || contentKey) && (state.message || state.assets.length > 0) && (
<MatIcons name="send-outline" size={20} color={Colors.text} />
)}
{ !state.busy && !(state.message || state.assets.length > 0) && (
{ !state.busy && (!state.locked || contentKey) && !(state.message || state.assets.length > 0) && (
<MatIcons name="send-outline" size={20} color={Colors.lightgrey} />
)}
</TouchableOpacity>

View File

@ -5,7 +5,7 @@ import Colors from 'constants/Colors';
import { getChannelSeals, getContentKey, encryptTopicSubject } from 'context/sealUtil';
import { AccountContext } from 'context/AccountContext';
export function useAddTopic(sealed, sealKey) {
export function useAddTopic(contentKey) {
const [state, setState] = useState({
message: null,
@ -21,6 +21,7 @@ export function useAddTopic(sealed, sealKey) {
enableImage: false,
enableAudio: false,
enableVideo: false,
locked: true,
});
const assetId = useRef(0);
@ -33,7 +34,8 @@ export function useAddTopic(sealed, sealKey) {
useEffect(() => {
const { enableVideo, enableAudio, enableImage } = conversation.state.channel?.detail || {};
updateState({ enableImage, enableAudio, enableVideo });
const locked = conversation.state.channel?.detail?.dataType === 'superbasic' ? false : true;
updateState({ enableImage, enableAudio, enableVideo, locked });
}, [conversation.state]);
const actions = {
@ -107,20 +109,12 @@ export function useAddTopic(sealed, sealKey) {
updateState({ color, colorSet: true });
},
addTopic: async () => {
if (!state.busy) {
if (!state.busy && (!state.locked || contentKey)) {
try {
updateState({ busy: true });
let contentKey;
const type = conversation.state.channel?.detail?.dataType === 'superbasic' ? 'superbasictopic' : 'sealedtopic';
if (type === 'sealedtopic') {
const channelDetail = conversation.state.channel?.detail;
const seals = getChannelSeals(channelDetail?.data);
const sealKey = account.state.sealKey;
contentKey = await getContentKey(seals, sealKey);
}
const assemble = (assets) => {
if (type === 'superbasictopic') {
if (!state.locked) {
if (assets?.length) {
return {
assets,
@ -146,6 +140,7 @@ export function useAddTopic(sealed, sealKey) {
return encryptTopicSubject({ message }, contentKey);
}
};
const type = state.locked ? "sealedtopic" : "superbasictopic";
await conversation.actions.addTopic(type, assemble, state.assets);
updateState({ busy: false, assets: [], message: null,
size: 'medium', sizeSet: false, textSize: 14,

View File

@ -7,7 +7,7 @@ import moment from 'moment';
import { useWindowDimensions } from 'react-native';
import Colors from 'constants/Colors';
import { getCardByGuid } from 'context/cardUtil';
import { getChannelSeals, isUnsealed, getContentKey, decryptTopicSubject } from 'context/sealUtil';
import { decryptTopicSubject } from 'context/sealUtil';
export function useTopicItem(item, hosting, remove, contentKey) {
@ -118,9 +118,26 @@ export function useTopicItem(item, hosting, remove, contentKey) {
}
}
else if (dataType === 'sealedtopic') {
if (unsealedDetail) {
let unsealed = unsealedDetail;
if (!unsealed && contentKey) {
try {
unsealed = decryptTopicSubject(detail?.data, contentKey);
(async () => {
try {
await conversation.actions.unsealTopic(topicId, revision, unsealed);
}
catch(err) {
console.log(err);
}
})();
}
catch(err) {
console.log(err);
}
}
if (unsealed) {
sealed = false;
parsed = unsealedDetail.message;
parsed = unsealed.message;
message = parsed?.text;
if (parsed?.textSize === 'small') {
fontSize = 10;
@ -140,7 +157,6 @@ export function useTopicItem(item, hosting, remove, contentKey) {
}
else {
sealed = true;
unsealTopic(topicId, revision, detail);
}
}
@ -162,18 +178,15 @@ export function useTopicItem(item, hosting, remove, contentKey) {
const deletable = editable || hosting;
updateState({ logo, name, nameSet, known, sealed, message, fontSize, fontColor, timestamp, transform, status, assets, deletable, editable, editData: parsed, editMessage: message });
}, [conversation.state, card.state, account.state, item]);
}, [conversation.state, card.state, account.state, item, contentKey]);
const unsealTopic = async (topicId, revision, topicDetail) => {
try {
console.log("UNSEAL", topicId);
const channelDetail = conversation.state.channel?.detail;
const seals = getChannelSeals(channelDetail?.data);
const sealKey = account.state.sealKey;
if (isUnsealed(seals, sealKey)) {
const contentKey = await getContentKey(seals, sealKey);
const unsealed = decryptTopicSubject(topicDetail.data, contentKey);
await conversation.actions.unsealTopic(topicId, revision, unsealed);
}
}
catch(err) {

View File

@ -4,6 +4,7 @@ import { CardContext } from 'context/CardContext';
import { AccountContext } from 'context/AccountContext';
import { ConversationContext } from 'context/ConversationContext';
import { getChannelSubjectLogo } from 'context/channelUtil';
import { getChannelSeals, isUnsealed, getContentKey, decryptTopicSubject } from 'context/sealUtil';
export function useConversation() {
const [state, setState] = useState({
@ -11,6 +12,7 @@ export function useConversation() {
logo: null,
topic: [],
loaded: false,
contentKey: null,
});
const updateState = (value) => {
@ -22,6 +24,42 @@ export function useConversation() {
const conversation = useContext(ConversationContext);
const account = useContext(AccountContext);
const contentKey = useRef();
const keyId = useRef();
useEffect(() => {
setContentKey();
}, [conversation.state, account.state]);
const setContentKey = async () => {
const type = conversation.state.channel?.detail?.dataType;
if (type === 'sealed') {
const cardId = conversation.state.card?.card?.cardId;
const channelId = conversation.state.channel?.channelId;
const contentId = `${cardId}:${channelId}`;
if (contentId !== keyId.current) {
const channelDetail = conversation.state.channel?.detail;
const seals = getChannelSeals(channelDetail?.data);
const sealKey = account.state.sealKey;
if (isUnsealed(seals, sealKey)) {
contentKey.current = await getContentKey(seals, sealKey);
keyId.current = contentId;
updateState({ contentKey: contentKey.current });
}
else if (keyId.current != null) {
contentKey.current = null;
keyId.current = null;
updateState({ contentKey: null });
}
}
}
else if (keyId.current != null) {
contentKey.current = null;
keyId.current = null;
updateState({ contentKey: null });
}
};
useEffect(() => {
const loaded = conversation.state.loaded;
const cardId = conversation.state.card?.cardId;