mirror of
https://github.com/balzack/databag.git
synced 2025-02-14 12:39:17 +00:00
support topic creation
This commit is contained in:
parent
fe850ea2e2
commit
fc6898fe68
@ -1,11 +1,12 @@
|
|||||||
import { useContext } from 'react';
|
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 { styles } from './Channels.styled';
|
||||||
import { useChannels } from './useChannels.hook';
|
import { useChannels } from './useChannels.hook';
|
||||||
import Ionicons from '@expo/vector-icons/AntDesign';
|
import Ionicons from '@expo/vector-icons/AntDesign';
|
||||||
import { ChannelItem } from './channelItem/ChannelItem';
|
import { ChannelItem } from './channelItem/ChannelItem';
|
||||||
import Colors from 'constants/Colors';
|
import Colors from 'constants/Colors';
|
||||||
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
|
import { SafeAreaProvider, SafeAreaView } from 'react-native-safe-area-context';
|
||||||
|
import { AddMember } from './addMember/AddMember';
|
||||||
|
|
||||||
export function ChannelsTitle({ state, actions }) {
|
export function ChannelsTitle({ state, actions }) {
|
||||||
return (
|
return (
|
||||||
@ -16,7 +17,7 @@ export function ChannelsTitle({ state, actions }) {
|
|||||||
autoCapitalize="none" placeholderTextColor={Colors.disabled} placeholder="Topics" />
|
autoCapitalize="none" placeholderTextColor={Colors.disabled} placeholder="Topics" />
|
||||||
<View style={styles.space} />
|
<View style={styles.space} />
|
||||||
</View>
|
</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" }, ]} ]}/>
|
<Ionicons name={'message1'} size={16} color={Colors.white} style={[styles.box, { transform: [ { rotateY: "180deg" }, ]} ]}/>
|
||||||
<Text style={styles.newtext}>New</Text>
|
<Text style={styles.newtext}>New</Text>
|
||||||
</TouchableOpacity>
|
</TouchableOpacity>
|
||||||
@ -26,13 +27,52 @@ export function ChannelsTitle({ state, actions }) {
|
|||||||
|
|
||||||
export function ChannelsBody({ state, actions, openConversation }) {
|
export function ChannelsBody({ state, actions, openConversation }) {
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
<FlatList style={styles.channels}
|
<FlatList style={styles.channels}
|
||||||
data={state.channels}
|
data={state.channels}
|
||||||
renderItem={({ item }) => <ChannelItem item={item} openConversation={openConversation} />}
|
renderItem={({ item }) => <ChannelItem item={item} openConversation={openConversation} />}
|
||||||
keyExtractor={item => (`${item.cardId}:${item.channelId}`)}
|
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 }) {
|
export function Channels({ openConversation }) {
|
||||||
|
@ -91,5 +91,92 @@ export const styles = StyleSheet.create({
|
|||||||
borderTopWidth: 1,
|
borderTopWidth: 1,
|
||||||
borderColor: Colors.divider,
|
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,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
26
app/mobile/src/session/channels/addMember/AddMember.jsx
Normal file
26
app/mobile/src/session/channels/addMember/AddMember.jsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -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 }],
|
||||||
|
},
|
||||||
|
|
||||||
|
})
|
||||||
|
|
@ -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 };
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,8 @@ export function useChannels() {
|
|||||||
channels: [],
|
channels: [],
|
||||||
tabbed: null,
|
tabbed: null,
|
||||||
filter: null,
|
filter: null,
|
||||||
|
adding: false,
|
||||||
|
connected: [],
|
||||||
});
|
});
|
||||||
|
|
||||||
const items = useRef([]);
|
const items = useRef([]);
|
||||||
@ -27,6 +29,11 @@ export function useChannels() {
|
|||||||
setState((s) => ({ ...s, ...value }));
|
setState((s) => ({ ...s, ...value }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const contacts = Array.from(card.state.cards.values());
|
||||||
|
updateState({ connected: contacts.filter(contact => contact.detail.status === 'connected') });
|
||||||
|
}, [card]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (dimensions.width > config.tabbedWidth) {
|
if (dimensions.width > config.tabbedWidth) {
|
||||||
updateState({ tabbed: false });
|
updateState({ tabbed: false });
|
||||||
@ -179,6 +186,12 @@ export function useChannels() {
|
|||||||
setFilter: (filter) => {
|
setFilter: (filter) => {
|
||||||
updateState({ filter });
|
updateState({ filter });
|
||||||
},
|
},
|
||||||
|
showAdding: () => {
|
||||||
|
updateState({ adding: true });
|
||||||
|
},
|
||||||
|
hideAdding: () => {
|
||||||
|
updateState({ adding: false });
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return { state, actions };
|
return { state, actions };
|
||||||
|
Loading…
Reference in New Issue
Block a user