diff --git a/app/mobile/src/session/channels/Channels.jsx b/app/mobile/src/session/channels/Channels.jsx index a23d1bd9..f2fbf85e 100644 --- a/app/mobile/src/session/channels/Channels.jsx +++ b/app/mobile/src/session/channels/Channels.jsx @@ -1,11 +1,12 @@ import { useContext } from 'react'; -import { FlatList, ScrollView, View, TextInput, TouchableOpacity, Text } from 'react-native'; +import { FlatList, Modal, KeyboardAvoidingView, ScrollView, View, TextInput, TouchableOpacity, Text } from 'react-native'; import { styles } from './Channels.styled'; import { useChannels } from './useChannels.hook'; import Ionicons from '@expo/vector-icons/AntDesign'; import { ChannelItem } from './channelItem/ChannelItem'; import Colors from 'constants/Colors'; import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context'; +import { AddMember } from './addMember/AddMember'; export function ChannelsTitle({ state, actions }) { return ( @@ -16,7 +17,7 @@ export function ChannelsTitle({ state, actions }) { autoCapitalize="none" placeholderTextColor={Colors.disabled} placeholder="Topics" /> - + New @@ -26,13 +27,52 @@ export function ChannelsTitle({ state, actions }) { export function ChannelsBody({ state, actions, openConversation }) { return ( - } - keyExtractor={item => (`${item.cardId}:${item.channelId}`)} - /> + <> + } + keyExtractor={item => (`${item.cardId}:${item.channelId}`)} + /> + + + + New Topic: + + + + Members: + { state.connected.length == 0 && ( + + No Connected Contacts + + )} + { state.connected.length > 0 && ( + } + keyExtractor={item => item.cardId} + /> + )} + + + Cancel + + + Save + + + + + + ); - } export function Channels({ openConversation }) { diff --git a/app/mobile/src/session/channels/Channels.styled.js b/app/mobile/src/session/channels/Channels.styled.js index bff21364..13ae217c 100644 --- a/app/mobile/src/session/channels/Channels.styled.js +++ b/app/mobile/src/session/channels/Channels.styled.js @@ -91,5 +91,92 @@ export const styles = StyleSheet.create({ borderTopWidth: 1, borderColor: Colors.divider, }, + cancel: { + borderWidth: 1, + borderColor: Colors.lightgrey, + borderRadius: 4, + padding: 4, + marginRight: 8, + width: 72, + display: 'flex', + alignItems: 'center', + }, + save: { + backgroundColor: Colors.primary, + borderRadius: 4, + padding: 4, + marginRight: 8, + width: 72, + display: 'flex', + alignItems: 'center', + }, + saveText: { + color: Colors.white, + }, + addControls: { + display: 'flex', + flexDirection: 'row', + justifyContent: 'flex-end', + }, + addWrapper: { + display: 'flex', + width: '100%', + height: '100%', + alignItems: 'center', + justifyContent: 'center', + backgroundColor: 'rgba(52, 52, 52, 0.8)' + }, + addContainer: { + backgroundColor: Colors.formBackground, + padding: 16, + width: '80%', + maxWidth: 400, + }, + addHeader: { + fontSize: 18, + paddingBottom: 16, + }, + addMembers: { + width: '100%', + borderWidth: 1, + borderColor: Colors.lightgrey, + borderRadius: 4, + marginBottom: 8, + height: 200, + }, + emptyMembers: { + width: '100%', + borderWidth: 1, + borderColor: Colors.lightgrey, + borderRadius: 4, + marginBottom: 8, + height: 200, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + inputField: { + width: '100%', + borderWidth: 1, + borderColor: Colors.lightgrey, + borderRadius: 4, + padding: 8, + marginBottom: 8, + maxHeight: 92, + display: 'flex', + flexDirection: 'row', + }, + input: { + fontSize: 14, + flexGrow: 1, + }, + empty: { + fontSize: 14, + color: Colors.grey, + }, + label: { + fontSize: 12, + color: Colors.grey, + }, }) diff --git a/app/mobile/src/session/channels/addMember/AddMember.jsx b/app/mobile/src/session/channels/addMember/AddMember.jsx new file mode 100644 index 00000000..884ccdc3 --- /dev/null +++ b/app/mobile/src/session/channels/addMember/AddMember.jsx @@ -0,0 +1,26 @@ +import { Alert, Text, Switch, TouchableOpacity, View } from 'react-native'; +import { Logo } from 'utils/Logo'; +import { styles } from './AddMember.styled'; +import { useAddMember } from './useAddMember.hook'; +import Colors from 'constants/Colors'; + +export function AddMember({ members, item }) { + + const { state, actions } = useAddMember(item, members); + + const setMember = () => { + }; + + return ( + + + + { state.name } + { state.handle } + + + + ); +} + diff --git a/app/mobile/src/session/channels/addMember/AddMember.styled.js b/app/mobile/src/session/channels/addMember/AddMember.styled.js new file mode 100644 index 00000000..472241d3 --- /dev/null +++ b/app/mobile/src/session/channels/addMember/AddMember.styled.js @@ -0,0 +1,74 @@ +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, + }, + connected: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.connected, + }, + requested: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.requested, + }, + connecting: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.connecting, + }, + pending: { + width: 8, + height: 8, + borderRadius: 4, + backgroundColor: Colors.pending, + }, + confirmed: { + width: 8, + height: 8, + 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/channels/addMember/useAddMember.hook.js b/app/mobile/src/session/channels/addMember/useAddMember.hook.js new file mode 100644 index 00000000..74bae60e --- /dev/null +++ b/app/mobile/src/session/channels/addMember/useAddMember.hook.js @@ -0,0 +1,37 @@ +import { useState, useEffect, useRef, useContext } from 'react'; +import { CardContext } from 'context/CardContext'; + +export function useAddMember(item, members) { + + const [state, setState] = useState({ + name: null, + handle: null, + logo: null, + cardId: null, + member: false, + }); + + 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; + updateState({ cardId, name, handle: `${handle}@${node}`, + logo: profile.imageSet ? card.actions.getCardLogo(cardId, revision) : 'avatar' }); + }, [card]); + + const actions = { + }; + + return { state, actions }; +} + diff --git a/app/mobile/src/session/channels/useChannels.hook.js b/app/mobile/src/session/channels/useChannels.hook.js index 1bb4950d..5bf2357a 100644 --- a/app/mobile/src/session/channels/useChannels.hook.js +++ b/app/mobile/src/session/channels/useChannels.hook.js @@ -14,6 +14,8 @@ export function useChannels() { channels: [], tabbed: null, filter: null, + adding: false, + connected: [], }); const items = useRef([]); @@ -27,6 +29,11 @@ export function useChannels() { setState((s) => ({ ...s, ...value })); } + useEffect(() => { + const contacts = Array.from(card.state.cards.values()); + updateState({ connected: contacts.filter(contact => contact.detail.status === 'connected') }); + }, [card]); + useEffect(() => { if (dimensions.width > config.tabbedWidth) { updateState({ tabbed: false }); @@ -179,6 +186,12 @@ export function useChannels() { setFilter: (filter) => { updateState({ filter }); }, + showAdding: () => { + updateState({ adding: true }); + }, + hideAdding: () => { + updateState({ adding: false }); + }, }; return { state, actions };