From 3cf037775efb613019678ac5cecb093c1aa0c4c7 Mon Sep 17 00:00:00 2001 From: balzack Date: Mon, 10 Oct 2022 22:05:15 -0700 Subject: [PATCH] updating membership --- app/mobile/src/api/setChannelCard.js | 5 ++-- .../src/context/useChannelContext.hook.js | 8 ++++++ .../context/useConversationContext.hook.js | 18 ++++++++++++ app/mobile/src/session/details/Details.jsx | 28 +++++++++++++++++-- .../src/session/details/Details.styled.js | 10 ++++++- .../session/details/memberItem/MemberItem.jsx | 25 ++++++++++++++--- .../details/memberItem/MemberItem.styled.js | 8 ++++++ .../details/memberItem/useMemberItem.hook.js | 20 ++++++++++++- .../src/session/details/useDetails.hook.js | 15 ++++++++++ 9 files changed, 127 insertions(+), 10 deletions(-) diff --git a/app/mobile/src/api/setChannelCard.js b/app/mobile/src/api/setChannelCard.js index c9da3287..b8dda084 100644 --- a/app/mobile/src/api/setChannelCard.js +++ b/app/mobile/src/api/setChannelCard.js @@ -1,7 +1,8 @@ import { checkResponse, fetchWithTimeout } from './fetchUtil'; -export async function setChannelCard(token, channelId, cardId ) { - let channel = await fetchWithTimeout(`/content/channels/${channelId}/cards/${cardId}?agent=${token}`, {method: 'PUT'}); +export async function setChannelCard(server, token, channelId, cardId ) { +console.log("SETTING"); + let channel = await fetchWithTimeout(`https://${server}/content/channels/${channelId}/cards/${cardId}?agent=${token}`, {method: 'PUT'}); checkResponse(channel); return await channel.json(); } diff --git a/app/mobile/src/context/useChannelContext.hook.js b/app/mobile/src/context/useChannelContext.hook.js index 9a5a5be4..40c53b25 100644 --- a/app/mobile/src/context/useChannelContext.hook.js +++ b/app/mobile/src/context/useChannelContext.hook.js @@ -246,6 +246,14 @@ export function useChannelContext() { const { server, appToken } = session.current; return await removeChannelTopic(server, appToken, channelId, topicId); }, + setCard: async (channelId, cardId) => { + const { server, appToken } = session.current; + return await setChannelCard(server, appToken, channelId, cardId); + }, + clearCard: async (channelId, cardId) => { + const { server, appToken } = session.current; + return await clearChannelCard(server, appToken, channelId, cardId); + }, } return { state, actions } diff --git a/app/mobile/src/context/useConversationContext.hook.js b/app/mobile/src/context/useConversationContext.hook.js index 2589c7b7..0ce26f01 100644 --- a/app/mobile/src/context/useConversationContext.hook.js +++ b/app/mobile/src/context/useConversationContext.hook.js @@ -357,6 +357,24 @@ export function useConversationContext() { await remove(cardId, channelId); } }, + setCard: async (id) => { + if (conversationId.current) { + const { cardId, channelId } = conversationId.current; + if (cardId) { + throw new Error("can only set members on hosted channel"); + } + await channel.actions.setCard(channelId, id); + } + }, + clearCard: async (id) => { + if (conversationId.current) { + const { cardId, channelId } = conversationId.current; + if (cardId) { + throw new Error("can only clear members on hosted channel"); + } + await channel.actions.clearCard(channelId, id); + } + }, } return { state, actions } diff --git a/app/mobile/src/session/details/Details.jsx b/app/mobile/src/session/details/Details.jsx index 24df4073..a8af618a 100644 --- a/app/mobile/src/session/details/Details.jsx +++ b/app/mobile/src/session/details/Details.jsx @@ -65,7 +65,7 @@ export function DetailsBody({ channel, clearConversation }) { )} { !state.hostId && ( - + Edit Membership )} @@ -85,7 +85,7 @@ export function DetailsBody({ channel, clearConversation }) { } + renderItem={({ item }) => } keyExtractor={item => item.cardId} /> @@ -115,6 +115,30 @@ export function DetailsBody({ channel, clearConversation }) { + + + + Channel Members: + } + keyExtractor={item => item.cardId} + /> + + + Done + + + + + + ) } diff --git a/app/mobile/src/session/details/Details.styled.js b/app/mobile/src/session/details/Details.styled.js index 7e054a7e..3fa527d5 100644 --- a/app/mobile/src/session/details/Details.styled.js +++ b/app/mobile/src/session/details/Details.styled.js @@ -147,6 +147,14 @@ export const styles = StyleSheet.create({ fontSize: 18, paddingBottom: 16, }, - + editMembers: { + width: '100%', + borderWidth: 1, + borderColor: Colors.lightgrey, + borderRadius: 4, + padding: 8, + marginBottom: 8, + height: 250, + }, }) diff --git a/app/mobile/src/session/details/memberItem/MemberItem.jsx b/app/mobile/src/session/details/memberItem/MemberItem.jsx index 87e49cb8..db690645 100644 --- a/app/mobile/src/session/details/memberItem/MemberItem.jsx +++ b/app/mobile/src/session/details/memberItem/MemberItem.jsx @@ -1,13 +1,26 @@ -import { Text, TouchableOpacity, View } from 'react-native'; +import { Alert, Text, Switch, TouchableOpacity, View } from 'react-native'; import { Logo } from 'utils/Logo'; import { styles } from './MemberItem.styled'; import { useMemberItem } from './useMemberItem.hook'; import Ionicons from '@expo/vector-icons/MaterialCommunityIcons'; import Colors from 'constants/Colors'; -export function MemberItem({ hostId, item }) { +export function MemberItem({ hostId, editable, members, item }) { - const { state, actions } = useMemberItem(item); + const { state, actions } = useMemberItem(item, members); + + const setMember = async (member) => { + try { + actions.setMember(member); + } + catch (err) { + console.log(err); + Alert.alert( + 'Failed to Update Membership', + 'Please try again.' + ); + } + }; return ( @@ -16,9 +29,13 @@ export function MemberItem({ hostId, item }) { { state.name } { state.handle } - { hostId === state.cardId && ( + { !editable && hostId === state.cardId && ( )} + { editable && ( + + )} ); } diff --git a/app/mobile/src/session/details/memberItem/MemberItem.styled.js b/app/mobile/src/session/details/memberItem/MemberItem.styled.js index 38306c69..8a94994a 100644 --- a/app/mobile/src/session/details/memberItem/MemberItem.styled.js +++ b/app/mobile/src/session/details/memberItem/MemberItem.styled.js @@ -62,5 +62,13 @@ export const styles = StyleSheet.create({ borderRadius: 4, backgroundColor: Colors.confirmed, }, + track: { + false: Colors.grey, + true: Colors.background, + }, + switch: { + transform: [{ scaleX: .7 }, { scaleY: .7 }], + }, + }) diff --git a/app/mobile/src/session/details/memberItem/useMemberItem.hook.js b/app/mobile/src/session/details/memberItem/useMemberItem.hook.js index 6579e3b6..d7490de9 100644 --- a/app/mobile/src/session/details/memberItem/useMemberItem.hook.js +++ b/app/mobile/src/session/details/memberItem/useMemberItem.hook.js @@ -1,22 +1,30 @@ import { useState, useEffect, useRef, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; import { CardContext } from 'context/CardContext'; +import { ConversationContext } from 'context/ConversationContext'; -export function useMemberItem(item) { +export function useMemberItem(item, members) { const [state, setState] = useState({ name: null, handle: null, logo: null, cardId: null, + member: false, }); + const conversation = useContext(ConversationContext); const card = useContext(CardContext); const updateState = (value) => { setState((s) => ({ ...s, ...value })); } + useEffect(() => { + const member = members.filter(contact => item.cardId === contact.cardId); + updateState({ member: member.length > 0 }); + }, [members]); + useEffect(() => { const { cardId, revision, profile } = item; const { name, handle, node } = profile; @@ -25,6 +33,16 @@ export function useMemberItem(item) { }, [card]); const actions = { + setMember: (member) => { + updateState({ member }); + if (member) { +console.log("SET CARD:", item.cardId); + conversation.actions.setCard(item.cardId); + } + else { + conversation.actions.clearCard(item.cardId); + } + }, }; return { state, actions }; diff --git a/app/mobile/src/session/details/useDetails.hook.js b/app/mobile/src/session/details/useDetails.hook.js index 000e7851..71ba7ad6 100644 --- a/app/mobile/src/session/details/useDetails.hook.js +++ b/app/mobile/src/session/details/useDetails.hook.js @@ -1,6 +1,7 @@ import { useState, useEffect, useRef, useContext } from 'react'; import { useNavigate } from 'react-router-dom'; import { ConversationContext } from 'context/ConversationContext'; +import { CardContext } from 'context/CardContext'; export function useDetails() { @@ -10,10 +11,13 @@ export function useDetails() { logo: null, hostId: null, contacts: [], + connected: [], editSubject: false, + editMembers: false, subjectUpdate: null, }); + const card = useContext(CardContext); const conversation = useContext(ConversationContext); const navigate = useNavigate(); @@ -21,6 +25,11 @@ export function useDetails() { setState((s) => ({ ...s, ...value })); } + useEffect(() => { + const contacts = Array.from(card.state.cards.values()); + updateState({ connected: contacts.filter(contact => contact.detail.status === 'connected') }); + }, [card]); + useEffect(() => { const { topic, subject, created, logo, host, contacts } = conversation.state; updateState({ subject, created, logo, hostId: host, subjectUpdate: topic, @@ -28,6 +37,12 @@ export function useDetails() { }, [conversation]); const actions = { + showEditMembers: () => { + updateState({ editMembers: true }); + }, + hideEditMembers: () => { + updateState({ editMembers: false }); + }, showEditSubject: () => { updateState({ editSubject: true }); },