diff --git a/app/mobile/src/context/useCardContext.hook.js b/app/mobile/src/context/useCardContext.hook.js
index 619d45c3..3fa1fba3 100644
--- a/app/mobile/src/context/useCardContext.hook.js
+++ b/app/mobile/src/context/useCardContext.hook.js
@@ -366,7 +366,7 @@ export function useCardContext() {
return getCardImageUrl(server, token, cardId, profileRevision);
},
removeChannel: async (cardId, channelId) => {
- const { detail, profile } = cards.current.get(cardId) || {};
+ const { detail, profile } = cards.current.get(cardId)?.card || {};
const cardToken = `${profile?.guid}.${detail?.token}`;
return await removeContactChannel(profile?.node, cardToken, channelId);
},
diff --git a/app/mobile/src/context/useConversationContext.hook.js b/app/mobile/src/context/useConversationContext.hook.js
index ec7ac727..a706dee2 100644
--- a/app/mobile/src/context/useConversationContext.hook.js
+++ b/app/mobile/src/context/useConversationContext.hook.js
@@ -157,7 +157,6 @@ export function useConversationContext() {
clearConversation: async () => {
conversationId.current = null;
reset.current = true;
- await sync();
},
setChannelSubject: async (type, subject) => {
const { cardId, channelId } = conversationId.current || {};
diff --git a/app/mobile/src/session/Session.jsx b/app/mobile/src/session/Session.jsx
index 61fffa12..1cad472e 100644
--- a/app/mobile/src/session/Session.jsx
+++ b/app/mobile/src/session/Session.jsx
@@ -168,6 +168,8 @@ export function Session() {
useEffect(() => {
navParams.detailNav.closeDrawer();
+ setChannelId(null);
+ setCardId(null);
setChannel(false);
}, [navParams.closeCount]);
@@ -263,20 +265,18 @@ export function Session() {
const DetailDrawerScreen = ({ navParams }) => {
const [closeCount, setCloseCount] = useState(0);
- const closeConversation = () => {
+ const clearConversation = (navigation) => {
setCloseCount(closeCount+1);
};
return (
(
-
-
-
-
-
+
+ clearConversation(props.navigation)} />
+
)}>
- {(props) => }
+ {(props) => }
);
diff --git a/app/mobile/src/session/channels/useChannels.hook.js b/app/mobile/src/session/channels/useChannels.hook.js
index 2339415a..d84ed9f7 100644
--- a/app/mobile/src/session/channels/useChannels.hook.js
+++ b/app/mobile/src/session/channels/useChannels.hook.js
@@ -26,7 +26,8 @@ export function useChannels() {
const account = useContext(AccountContext);
const profile = useContext(ProfileContext);
const app = useContext(AppContext);
-
+
+ const filter = useRef();
const syncing = useRef(false);
const resync = useRef(false);
@@ -154,6 +155,7 @@ export function useChannels() {
useEffect(() => {
syncChannels();
+ filter.current = state.filter;
}, [app.state, card.state, channel.state, state.filter, state.sealable]);
const syncChannels = async () => {
@@ -179,10 +181,10 @@ export function useChannels() {
channels.push(await setChannelItem(loginTimestamp, cardId, channelId, channelItem));
}
const filtered = channels.filter(item => {
- if (!state.filter) {
+ if (!filter.current) {
return true;
}
- const filterCase = state.filter.toUpperCase();
+ const filterCase = filter.current.toUpperCase();
const subjectCase = item.subject.toUpperCase();
return subjectCase.includes(filterCase);
});
diff --git a/app/mobile/src/session/conversation/Conversation.jsx b/app/mobile/src/session/conversation/Conversation.jsx
index eb595fe5..79c6104a 100644
--- a/app/mobile/src/session/conversation/Conversation.jsx
+++ b/app/mobile/src/session/conversation/Conversation.jsx
@@ -1,4 +1,4 @@
-import { useEffect, useContext } from 'react';
+import { useEffect, useState, useContext } from 'react';
import { View, Text, TouchableOpacity } from 'react-native';
import { ConversationContext } from 'context/ConversationContext';
import { useConversation } from './useConversation.hook';
@@ -9,6 +9,7 @@ import { Logo } from 'utils/Logo';
export function Conversation({ navigation, cardId, channelId, closeConversation, openDetails }) {
+ const [ready, setReady] = useState(false);
const conversation = useContext(ConversationContext);
const { state, actions } = useConversation();
@@ -30,21 +31,27 @@ export function Conversation({ navigation, cardId, channelId, closeConversation,
}, [navigation, state.subject]);
useEffect(() => {
- conversation.actions.setConversation(cardId, channelId);
- return () => { conversation.actions.clearConversation() };
+ (async () => {
+ setReady(false);
+ await conversation.actions.setConversation(cardId, channelId);
+ setReady(true);
+ })();
+ return () => { conversation.actions.clearConversation(); };
}, [cardId, channelId]);
return (
{ !navigation && (
-
-
- { state.subject }
-
-
+ { ready && (
+
+
+ { state.subject }
+
+
+ )}
-
+
)}
diff --git a/app/mobile/src/session/conversation/Conversation.styled.js b/app/mobile/src/session/conversation/Conversation.styled.js
index d00d6b75..f0b9c210 100644
--- a/app/mobile/src/session/conversation/Conversation.styled.js
+++ b/app/mobile/src/session/conversation/Conversation.styled.js
@@ -16,27 +16,31 @@ export const styles = StyleSheet.create({
flexGrow: 1,
borderBottomWidth: 1,
borderColor: Colors.divider,
+ height: 48,
+ marginLeft: 16,
+ marginRight: 16,
},
headertitle: {
display: 'flex',
+ flexShrink: 1,
flexDirection: 'row',
alignItems: 'center',
- paddingLeft: 16,
+ paddingLeft: 8,
paddingTop: 8,
paddingBottom: 8,
},
titletext: {
fontSize: 18,
+ flexShrink: 1,
paddingLeft: 16,
paddingRight: 16,
},
titlebutton: {
- paddingRight: 16,
+ paddingRight: 8,
},
headerclose: {
flexGrow: 1,
alignItems: 'flex-end',
- paddingTop: 8,
},
});
diff --git a/app/mobile/src/session/details/Details.jsx b/app/mobile/src/session/details/Details.jsx
index e5e022d6..7c44be7a 100644
--- a/app/mobile/src/session/details/Details.jsx
+++ b/app/mobile/src/session/details/Details.jsx
@@ -5,11 +5,30 @@ import { Logo } from 'utils/Logo';
import AntIcons from 'react-native-vector-icons/AntDesign';
import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
import Colors from 'constants/Colors';
+import { MemberItem } from './memberItem/MemberItem';
export function Details({ channel, clearConversation }) {
const { state, actions } = useDetails();
+ const toggle = async (cardId, selected) => {
+ try {
+ if (selected) {
+ await actions.clearCard(cardId);
+ }
+ else {
+ await actions.setCard(cardId);
+ }
+ }
+ catch (err) {
+ console.log(err);
+ Alert.alert(
+ 'Failed to Update Membership',
+ 'Please try again.'
+ );
+ }
+ };
+
const saveSubject = async () => {
try {
await actions.saveSubject();
@@ -199,8 +218,8 @@ export function Details({ channel, clearConversation }) {
}
+ data={state.members}
+ renderItem={({ item }) => }
keyExtractor={item => item.cardId}
/>
@@ -242,7 +261,7 @@ export function Details({ channel, clearConversation }) {
Channel Members:
MEMBER }
+ renderItem={({ item }) => }
keyExtractor={item => item.cardId}
/>
diff --git a/app/mobile/src/session/details/memberItem/MemberItem.jsx b/app/mobile/src/session/details/memberItem/MemberItem.jsx
new file mode 100644
index 00000000..1f880257
--- /dev/null
+++ b/app/mobile/src/session/details/memberItem/MemberItem.jsx
@@ -0,0 +1,31 @@
+import { TouchableOpacity, Switch, Text, View } from 'react-native';
+import MatIcons from 'react-native-vector-icons/MaterialCommunityIcons';
+import { styles } from './MemberItem.styled';
+import { Logo } from 'utils/Logo';
+import { Colors } from 'constants/Colors';
+
+export function MemberItem({ item, hostId, toggle }) {
+
+ const select = () => {
+ if (toggle) {
+ toggle(item.cardId, item.selected);
+ }
+ };
+
+ return (
+
+
+
+ { item.name }
+ { item.handle }
+
+ { hostId === item.cardId && (
+
+ )}
+ { toggle && (
+
+ )}
+
+ );
+}
+
diff --git a/app/mobile/src/session/details/memberItem/MemberItem.styled.js b/app/mobile/src/session/details/memberItem/MemberItem.styled.js
new file mode 100644
index 00000000..936710bc
--- /dev/null
+++ b/app/mobile/src/session/details/memberItem/MemberItem.styled.js
@@ -0,0 +1,42 @@
+import { StyleSheet } from 'react-native';
+import { Colors } from 'constants/Colors';
+
+export const styles = StyleSheet.create({
+ container: {
+ width: '100%',
+ display: 'flex',
+ flexDirection: 'row',
+ height: 48,
+ alignItems: 'center',
+ borderBottomWidth: 1,
+ borderColor: Colors.itemDivider,
+ paddingLeft: 8,
+ paddingRight: 8,
+ },
+ detail: {
+ paddingLeft: 12,
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ flexGrow: 1,
+ flexShrink: 1,
+ },
+ space: {
+ height: 64,
+ },
+ name: {
+ color: Colors.text,
+ fontSize: 14,
+ },
+ handle: {
+ color: Colors.text,
+ fontSize: 12,
+ },
+ track: {
+ false: Colors.grey,
+ true: Colors.background,
+ },
+ switch: {
+ transform: [{ scaleX: .7 }, { scaleY: .7 }],
+ },
+});
diff --git a/app/mobile/src/session/details/useDetails.hook.js b/app/mobile/src/session/details/useDetails.hook.js
index 4fdb132c..80ecda51 100644
--- a/app/mobile/src/session/details/useDetails.hook.js
+++ b/app/mobile/src/session/details/useDetails.hook.js
@@ -5,6 +5,7 @@ import { CardContext } from 'context/CardContext';
import { AccountContext } from 'context/AccountContext';
import { ProfileContext } from 'context/ProfileContext';
import { getChannelSubjectLogo } from 'context/channelUtil';
+import { getCardByGuid } from 'context/cardUtil';
import { getChannelSeals, isUnsealed, getContentKey, updateChannelSubject } from 'context/sealUtil';
import moment from 'moment';
@@ -23,11 +24,11 @@ export function useDetails() {
pushEnabled: false,
locked: false,
unlocked: false,
- count: 0,
seals: null,
sealKey: null,
deleteBusy: false,
blockBusy: false,
+ unknown: 0,
});
const card = useContext(CardContext);
@@ -64,18 +65,49 @@ export function useDetails() {
updateState({ locked, unlocked, seals, sealKey, notification });
}, [account.state, conversation.state]);
- useEffect(() => {
- const connected = [];
- card.state.cards.forEach(contact => {
- if (contact?.card?.detail?.status === 'connected') {
- connected.push(contact.card);
- }
- });
- updateState({ connected });
- }, [card.state]);
+ const setMemberItem = (contact, guids) => {
+ return {
+ cardId: contact?.cardId,
+ name: contact?.profile?.name,
+ handle: contact?.profile?.handle,
+ node: contact?.profile?.node,
+ logo: contact?.profile?.imageSet ? card.actions.getCardImageUrl(contact.cardId) : 'avatar',
+ selected: guids.includes(contact?.profile?.guid),
+ }
+ };
useEffect(() => {
- const hostId = conversation.state.card?.cardId;
+ let unknown = 0;
+ let members = new Map();
+ const host = conversation.state.card;
+ if (host) {
+ members.set(host.card?.cardId, setMemberItem(host.card, []));
+ }
+ const guids = conversation.state.channel?.detail?.members || [];
+ guids.forEach(guid => {
+ if (guid !== profile.state.identity?.guid) {
+ const contact = getCardByGuid(card.state.cards, guid);
+ if (contact) {
+ members.set(contact.card?.cardId, setMemberItem(contact.card, []));
+ }
+ else {
+ unknown++;
+ }
+ }
+ });
+
+ const connected = new Map();
+ card.state.cards.forEach(contact => {
+ if (contact?.card?.detail?.status === 'connected') {
+ connected.set(contact.card?.cardId, setMemberItem(contact.card, guids));
+ }
+ });
+
+ updateState({ connected: Array.from(connected.values()), members: Array.from(members.values()), unknown });
+ }, [card.state, conversation.state]);
+
+ useEffect(() => {
+ const hostId = conversation.state.card?.card.cardId;
const profileGuid = profile.state.identity?.guid;
const channel = conversation.state.channel;
const cards = card.state.cards;
@@ -128,6 +160,24 @@ export function useDetails() {
setSubjectUpdate: (subjectUpdate) => {
updateState({ subjectUpdate });
},
+ setCard: async (cardId) => {
+ updateState({ connected: state.connected.map(contact => {
+ if(contact.cardId === cardId) {
+ return { ...contact, selected: true }
+ }
+ return contact;
+ }) });
+ await conversation.actions.setChannelCard(cardId);
+ },
+ clearCard: async (cardId) => {
+ updateState({ connected: state.connected.map(contact => {
+ if(contact.cardId === cardId) {
+ return { ...contact, selected: false }
+ }
+ return contact;
+ }) });
+ await conversation.actions.clearChannelCard(cardId);
+ },
saveSubject: async () => {
if (state.locked) {
const contentKey = await getContentKey(state.seals, state.sealKey);
diff --git a/app/mobile/src/session/profile/blockedTopics/useBlockedTopics.hook.js b/app/mobile/src/session/profile/blockedTopics/useBlockedTopics.hook.js
index 70a6c63f..8f4ace38 100644
--- a/app/mobile/src/session/profile/blockedTopics/useBlockedTopics.hook.js
+++ b/app/mobile/src/session/profile/blockedTopics/useBlockedTopics.hook.js
@@ -69,7 +69,7 @@ export function useBlockedTopics() {
});
channel.state.channels.forEach((channelItem, channelId, map) => {
if (channelItem.blocked) {
- marged.push({ channel: channelItem });
+ merged.push({ channel: channelItem });
}
});
const items = merged.map(setChannelItem);