diff --git a/app/mobile/App.js b/app/mobile/App.js
index 3f6e4b6d..bd69a45e 100644
--- a/app/mobile/App.js
+++ b/app/mobile/App.js
@@ -14,6 +14,7 @@ import { CardContextProvider } from 'context/CardContext';
import { ChannelContextProvider } from 'context/ChannelContext';
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
import { NavigationContainer } from '@react-navigation/native';
+import { ConversationContextProvider } from 'context/ConversationContext';
export default function App() {
@@ -23,20 +24,22 @@ export default function App() {
-
-
-
-
- } />
- } />
- } />
- } />
- } />
- } />
-
-
-
-
+
+
+
+
+
+ } />
+ } />
+ } />
+ } />
+ } />
+ } />
+
+
+
+
+
diff --git a/app/mobile/src/context/ConversationContext.js b/app/mobile/src/context/ConversationContext.js
new file mode 100644
index 00000000..08cde892
--- /dev/null
+++ b/app/mobile/src/context/ConversationContext.js
@@ -0,0 +1,14 @@
+import { createContext } from 'react';
+import { useConversationContext } from './useConversationContext.hook';
+
+export const ConversationContext = createContext({});
+
+export function ConversationContextProvider({ children }) {
+ const { state, actions } = useConversationContext();
+ return (
+
+ {children}
+
+ );
+}
+
diff --git a/app/mobile/src/context/useConversationContext.hook.js b/app/mobile/src/context/useConversationContext.hook.js
new file mode 100644
index 00000000..22b678b7
--- /dev/null
+++ b/app/mobile/src/context/useConversationContext.hook.js
@@ -0,0 +1,151 @@
+import { useState, useEffect, useRef, useContext } from 'react';
+import { StoreContext } from 'context/StoreContext';
+import { CardContext } from 'context/CardContext';
+import { ChannelContext } from 'context/ChannelContext';
+import { ProfileContext } from 'context/ProfileContext';
+
+export function useConversationContext() {
+ const [state, setState] = useState({
+ subject: null,
+ logo: null,
+ contacts: [],
+ topics: [],
+ });
+ const store = useContext(StoreContext);
+ const card = useContext(CardContext);
+ const channel = useContext(ChannelContext);
+ const profile = useContext(ProfileContext);
+ const topics = useRef(new Map());
+ const revision = useRef(0);
+ const syncing = useRef(false);
+ const cardId = useRef(null);
+ const channelId = useRef(null);
+ const setView = useRef(0);
+
+ const updateState = (value) => {
+ setState((s) => ({ ...s, ...value }))
+ }
+
+ const sync = async () => {
+ const curView = setView.current;
+ const item = getChannel(cardId.current, channelId.current);
+ if (!syncing.current && item?.revision !== revision.current) {
+ syncing.current = true;
+
+ // stuff
+ setChannel(item);
+
+ if (curView === setView.current) {
+ revision.current = item?.revision;
+ }
+ syncing.current = false;
+ sync();
+ }
+ }
+
+ const getCard = (guid) => {
+ let contact = null
+ card.state.cards.forEach((card, cardId, map) => {
+ if (card?.profile?.guid === guid) {
+ contact = card;
+ }
+ });
+ return contact;
+ }
+
+ const getChannel = (cardId, channelId) => {
+ if (cardId) {
+ const entry = card.state.cards.get(cardId);
+ return entry?.channels.get(channelId);
+ }
+ return channel.state.channels.get(channelId);
+ }
+
+ const setChannel = (item) => {
+ let contacts = [];
+ let logo = null;
+ let subject = null;
+
+ if (!item) {
+ updateState({ contacts, logo, subject });
+ return;
+ }
+
+ if (item.cardId) {
+ contacts.push(card.state.cards.get(item.cardId));
+ }
+ if (item?.detail?.members) {
+ const profileGuid = profile.state.profile.guid;
+ item.detail.members.forEach(guid => {
+ if (profileGuid !== guid) {
+ const contact = getCard(guid);
+ contacts.push(contact);
+ }
+ })
+ }
+
+ 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';
+ }
+
+ if (item?.detail?.data) {
+ try {
+ subject = JSON.parse(item?.detail?.data).subject;
+ }
+ catch (err) {
+ console.log(err);
+ }
+ }
+ if (!subject) {
+ if (contacts.length) {
+ let names = [];
+ for (let contact of contacts) {
+ if (contact?.profile?.name) {
+ names.push(contact.profile.name);
+ }
+ else if (contact?.profile?.handle) {
+ names.push(contact?.profile?.handle);
+ }
+ }
+ subject = names.join(', ');
+ }
+ else {
+ subject = "Notes";
+ }
+ }
+
+ updateState({ subject, logo, contacts });
+ }
+
+ useEffect(() => {
+ sync();
+ }, [card, channel]);
+
+ const actions = {
+ setChannel: (channel) => {
+ if (channel.cardId !== cardId.current || channel.channelId !== channelId.current) {
+ setView.current++;
+ revision.current = 0;
+ topics.current = new Map();
+ channelId.current = channel.channelId;
+ cardId.current = channel.cardId;
+ sync();
+ }
+ },
+ }
+
+ return { state, actions }
+}
+
+
diff --git a/app/mobile/src/session/conversation/Conversation.jsx b/app/mobile/src/session/conversation/Conversation.jsx
index d01b4103..647ec4c7 100644
--- a/app/mobile/src/session/conversation/Conversation.jsx
+++ b/app/mobile/src/session/conversation/Conversation.jsx
@@ -1,5 +1,5 @@
-import { View, TouchableOpacity, Text } from 'react-native';
-import { useLayoutEffect } from 'react';
+import { View, TouchableOpacity, Text, FlatList } from 'react-native';
+import { useState, useRef } from 'react';
import { useConversation } from './useConversation.hook';
import { styles } from './Conversation.styled';
import { useNavigation } from '@react-navigation/native';
@@ -33,15 +33,12 @@ export function ConversationBody({ channel }) {
const { state, actions } = useConversation(channel?.cardId, channel?.channelId);
return (
-
- CHANNEL
- { channel && (
- <>
- { channel?.cardId }
- { channel?.channelId }
- >
- )}
-
+ ITEM { item.id }}
+ keyExtractor={item => item.id}
+ />
);
}
diff --git a/app/mobile/src/session/conversation/Conversation.styled.js b/app/mobile/src/session/conversation/Conversation.styled.js
index 5d399ee7..b7d539dc 100644
--- a/app/mobile/src/session/conversation/Conversation.styled.js
+++ b/app/mobile/src/session/conversation/Conversation.styled.js
@@ -41,5 +41,8 @@ export const styles = StyleSheet.create({
action: {
paddingLeft: 8,
},
+ topics: {
+ height: '100%',
+ },
})
diff --git a/app/mobile/src/session/conversation/useConversation.hook.js b/app/mobile/src/session/conversation/useConversation.hook.js
index a2f337f6..e6e42244 100644
--- a/app/mobile/src/session/conversation/useConversation.hook.js
+++ b/app/mobile/src/session/conversation/useConversation.hook.js
@@ -1,105 +1,28 @@
import { useState, useEffect, useContext } from 'react';
-import { CardContext } from 'context/CardContext';
-import { ChannelContext } from 'context/ChannelContext';
-import { ProfileContext } from 'context/ProfileContext';
+import { ConversationContext } from 'context/ConversationContext';
export function useConversation(cardId, channelId) {
const [state, setState] = useState({
+ topics: [],
subject: null,
logo: null,
});
- const card = useContext(CardContext);
- const channel = useContext(ChannelContext);
- const profile = useContext(ProfileContext);
+ const conversation = useContext(ConversationContext);
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;
- }
+ useEffect(() => {
+ conversation.actions.setChannel({ cardId, channelId });
+ }, [cardId, channelId]);
useEffect(() => {
-console.log(cardId, channelId);
- let item;
- if (cardId) {
- const entry = card.state.cards.get(cardId);
- if (entry) {
- item = entry.channels.get(channelId);
- }
- }
- else {
- item = channel.state.channels.get(channelId);
- }
-
- let contacts = [];
- if (item.cardId) {
- contacts.push(card.state.cards.get(item.cardId));
- }
- if (item?.detail?.members) {
- const profileGuid = profile.state.profile.guid;
- item.detail.members.forEach(guid => {
- if (profileGuid !== guid) {
- const contact = getCard(guid);
- contacts.push(contact);
- }
- })
- }
-
- 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';
- }
-
- let subject = null;
- if (item?.detail?.data) {
- try {
- subject = JSON.parse(item?.detail?.data).subject;
- }
- catch (err) {
- console.log(err);
- }
- }
- if (!subject) {
- if (contacts.length) {
- let names = [];
- for (let contact of contacts) {
- if (contact?.profile?.name) {
- names.push(contact.profile.name);
- }
- else if (contact?.profile?.handle) {
- names.push(contact?.profile?.handle);
- }
- }
- subject = names.join(', ');
- }
- else {
- subject = "Notes";
- }
- }
-
- updateState({ subject, logo });
- }, [cardId, channelId, profile, card, channel]);
+ const { topics, subject, logo } = conversation.state;
+ updateState({ topics, subject, logo });
+ }, [conversation]);
const actions = {
};
diff --git a/app/mobile/src/session/profile/Profile.jsx b/app/mobile/src/session/profile/Profile.jsx
index e4584b5b..c192aa4a 100644
--- a/app/mobile/src/session/profile/Profile.jsx
+++ b/app/mobile/src/session/profile/Profile.jsx
@@ -23,6 +23,8 @@ export function Profile() {
const { state, actions } = useProfile();
+console.log(state.imageSource);
+
const setVisible = async (visible) => {
try {
await actions.setVisible(visible);
diff --git a/app/mobile/src/session/profile/useProfile.hook.js b/app/mobile/src/session/profile/useProfile.hook.js
index d129b9da..32521b26 100644
--- a/app/mobile/src/session/profile/useProfile.hook.js
+++ b/app/mobile/src/session/profile/useProfile.hook.js
@@ -70,6 +70,7 @@ export function useProfile() {
navigate('/');
},
setVisible: async (visible) => {
+ updateState({ visible });
await account.actions.setSearchable(visible);
},
setProfileImage: async (data) => {