support topic creation

This commit is contained in:
Roland Osborne 2022-10-11 15:19:58 -07:00
parent fe850ea2e2
commit fc6898fe68
6 changed files with 285 additions and 8 deletions

View File

@ -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" />
<View style={styles.space} />
</View>
<TouchableOpacity style={styles.add}>
<TouchableOpacity style={styles.add} onPress={actions.showAdding}>
<Ionicons name={'message1'} size={16} color={Colors.white} style={[styles.box, { transform: [ { rotateY: "180deg" }, ]} ]}/>
<Text style={styles.newtext}>New</Text>
</TouchableOpacity>
@ -26,13 +27,52 @@ export function ChannelsTitle({ state, actions }) {
export function ChannelsBody({ state, actions, openConversation }) {
return (
<>
<FlatList style={styles.channels}
data={state.channels}
renderItem={({ item }) => <ChannelItem item={item} openConversation={openConversation} />}
keyExtractor={item => (`${item.cardId}:${item.channelId}`)}
/>
<Modal
animationType="fade"
transparent={true}
visible={state.adding}
supportedOrientations={['portrait', 'landscape']}
onRequestClose={actions.hideAdding}
>
<KeyboardAvoidingView behavior="height" style={styles.addWrapper}>
<View style={styles.addContainer}>
<Text style={styles.addHeader}>New Topic:</Text>
<View style={styles.inputField}>
<TextInput style={styles.input} value={state.subjectUpdate} onChangeText={actions.setSubjectUpdate}
autoCapitalize="words" placeholder="Subject" />
</View>
<Text style={styles.label}>Members:</Text>
{ state.connected.length == 0 && (
<View style={styles.emptyMembers}>
<Text style={styles.empty}>No Connected Contacts</Text>
</View>
)}
{ state.connected.length > 0 && (
<FlatList style={styles.addMembers}
data={state.connected}
renderItem={({ item }) => <AddMember members={[]} item={item} />}
keyExtractor={item => item.cardId}
/>
)}
<View style={styles.addControls}>
<TouchableOpacity style={styles.cancel} onPress={actions.hideAdding}>
<Text>Cancel</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.save} onPress={actions.hideAdding}>
<Text style={styles.saveText}>Save</Text>
</TouchableOpacity>
</View>
</View>
</KeyboardAvoidingView>
</Modal>
</>
);
}
export function Channels({ openConversation }) {

View File

@ -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,
},
})

View File

@ -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 (
<View style={styles.container}>
<Logo src={state.logo} width={32} height={32} radius={6} />
<View style={styles.detail}>
<Text style={styles.name} numberOfLines={1} ellipsizeMode={'tail'}>{ state.name }</Text>
<Text style={styles.handle} numberOfLines={1} ellipsizeMode={'tail'}>{ state.handle }</Text>
</View>
<Switch style={styles.switch} trackColor={styles.track}
value={state.member} onValueChange={setMember} />
</View>
);
}

View File

@ -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 }],
},
})

View File

@ -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 };
}

View File

@ -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 };