mirror of
https://github.com/balzack/databag.git
synced 2025-03-13 00:50:03 +00:00
merging add channel support
This commit is contained in:
parent
84d8598f29
commit
aaf7d38836
@ -1,15 +1,19 @@
|
||||
import { useEffect } from 'react';
|
||||
import { View, FlatList, Text, TextInput, TouchableOpacity } from 'react-native';
|
||||
import { Switch, KeyboardAvoidingView, Modal, View, FlatList, Text, TextInput, TouchableOpacity } from 'react-native';
|
||||
import Ionicons from 'react-native-vector-icons/AntDesign';
|
||||
import { styles } from './Channels.styled';
|
||||
import { useChannels } from './useChannels.hook';
|
||||
import { Colors } from 'constants/Colors';
|
||||
import { ChannelItem } from './channelItem/ChannelItem';
|
||||
import { AddMember } from './addMember/AddMember';
|
||||
|
||||
export function Channels({ navigation, openConversation }) {
|
||||
|
||||
const { state, actions } = useChannels();
|
||||
|
||||
const addTopic = async () => {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (navigation) {
|
||||
navigation.setOptions({
|
||||
@ -63,6 +67,54 @@ export function Channels({ navigation, openConversation }) {
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
<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.addField}>
|
||||
<TextInput style={styles.input} value={state.addSubject} onChangeText={actions.setAddSubject}
|
||||
autoCapitalize="words" placeholder="Subject (optional)" placeholderTextColor={Colors.grey} />
|
||||
</View>
|
||||
<Text style={styles.label}>Members:</Text>
|
||||
{ state.contacts.length == 0 && (
|
||||
<View style={styles.emptyMembers}>
|
||||
<Text style={styles.empty}>No Connected Contacts</Text>
|
||||
</View>
|
||||
)}
|
||||
{ state.contacts.length > 0 && (
|
||||
<FlatList style={styles.addMembers}
|
||||
data={state.contacts}
|
||||
renderItem={({ item }) => <AddMember members={state.addMembers} item={item}
|
||||
setCard={actions.setAddMember} clearCard={actions.clearAddMember} />}
|
||||
keyExtractor={item => item.cardId}
|
||||
/>
|
||||
)}
|
||||
<View style={styles.addControls}>
|
||||
<View style={styles.sealed}>
|
||||
{ state.sealable && (
|
||||
<>
|
||||
<Switch style={styles.switch} trackColor={styles.track}
|
||||
value={state.sealed} onValueChange={actions.setSealed} />
|
||||
<Text>Sealed</Text>
|
||||
</>
|
||||
)}
|
||||
</View>
|
||||
<TouchableOpacity style={styles.cancel} onPress={actions.hideAdding}>
|
||||
<Text>Cancel</Text>
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.save} onPress={addTopic}>
|
||||
<Text style={styles.saveText}>Create</Text>
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
</View>
|
||||
</KeyboardAvoidingView>
|
||||
</Modal>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -33,6 +33,21 @@ export const styles = StyleSheet.create({
|
||||
color: Colors.text,
|
||||
fontSize: 14,
|
||||
},
|
||||
addField: {
|
||||
width: '100%',
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 4,
|
||||
padding: 8,
|
||||
marginBottom: 8,
|
||||
maxHeight: 92,
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
input: {
|
||||
fontSize: 14,
|
||||
flexGrow: 1,
|
||||
},
|
||||
icon: {
|
||||
paddingLeft: 8,
|
||||
},
|
||||
@ -77,5 +92,86 @@ export const styles = StyleSheet.create({
|
||||
borderBottomWidth: 1,
|
||||
borderColor: Colors.divider,
|
||||
},
|
||||
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',
|
||||
},
|
||||
cancel: {
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.lightgrey,
|
||||
borderRadius: 4,
|
||||
padding: 4,
|
||||
marginRight: 8,
|
||||
width: 72,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
save: {
|
||||
backgroundColor: Colors.primary,
|
||||
borderRadius: 4,
|
||||
padding: 4,
|
||||
marginRight: 8,
|
||||
width: 72,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
saveText: {
|
||||
color: Colors.white,
|
||||
},
|
||||
addControls: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
},
|
||||
sealed: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
flexGrow: 1,
|
||||
alignItems: 'center',
|
||||
},
|
||||
sealedText: {
|
||||
color: Colors.text,
|
||||
},
|
||||
track: {
|
||||
false: Colors.grey,
|
||||
true: Colors.background,
|
||||
},
|
||||
switch: {
|
||||
transform: [{ scaleX: .7 }, { scaleY: .7 }],
|
||||
},
|
||||
});
|
||||
|
||||
|
31
app/mobile/src/session/channels/addMember/AddMember.jsx
Normal file
31
app/mobile/src/session/channels/addMember/AddMember.jsx
Normal file
@ -0,0 +1,31 @@
|
||||
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, setCard, clearCard }) {
|
||||
|
||||
const { state, actions } = useAddMember(item, members);
|
||||
|
||||
const setMember = (set) => {
|
||||
if (set) {
|
||||
setCard(item.cardId);
|
||||
}
|
||||
else {
|
||||
clearCard(item.cardId);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<TouchableOpacity activeOpacity={1} style={styles.container} onPress={() => setMember(!state.member)}>
|
||||
<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} />
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
@ -0,0 +1,73 @@
|
||||
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,36 @@
|
||||
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);
|
||||
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.getCardImageUrl(cardId) : 'avatar' });
|
||||
}, [card.state]);
|
||||
|
||||
const actions = {
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
@ -11,6 +11,12 @@ export function useChannels() {
|
||||
const [state, setState] = useState({
|
||||
filter: null,
|
||||
channels: [],
|
||||
adding: false,
|
||||
contacts: [],
|
||||
addMembers: [],
|
||||
addSubject: null,
|
||||
sealed: false,
|
||||
sealable: false,
|
||||
});
|
||||
|
||||
const channel = useContext(ChannelContext);
|
||||
@ -149,6 +155,45 @@ export function useChannels() {
|
||||
return { cardId, channelId, subject, message, logo, timestamp, updated, locked, unlocked };
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
const { status, sealKey } = account.state;
|
||||
if (status?.seal?.publicKey && sealKey?.public && sealKey?.private && sealKey?.public === status.seal.publicKey) {
|
||||
updateState({ sealable: true });
|
||||
}
|
||||
else {
|
||||
updateState({ sealed: false, sealable: false });
|
||||
}
|
||||
}, [account.state]);
|
||||
|
||||
useEffect(() => {
|
||||
const contacts = [];
|
||||
card.state.cards.forEach(entry => {
|
||||
contacts.push(entry.card);
|
||||
});
|
||||
const filtered = contacts.filter(contact => {
|
||||
if (contact.detail.status !== 'connected') {
|
||||
return false;
|
||||
}
|
||||
if (state.sealed && !contact.profile.seal) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
const sorted = filtered.sort((a, b) => {
|
||||
const aName = a?.profile?.name;
|
||||
const bName = b?.profile?.name;
|
||||
if (aName === bName) {
|
||||
return 0;
|
||||
}
|
||||
if (!aName || (aName < bName)) {
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
});
|
||||
const addMembers = state.addMembers.filter(item => sorted.some(contact => contact.cardId === item));
|
||||
updateState({ contacts: sorted, addMembers });
|
||||
}, [card.state, state.sealed]);
|
||||
|
||||
useEffect(() => {
|
||||
syncChannels();
|
||||
}, [app.state, card.state, channel.state, state.filter]);
|
||||
@ -205,9 +250,29 @@ export function useChannels() {
|
||||
};
|
||||
|
||||
const actions = {
|
||||
setSealed: (sealed) => {
|
||||
updateState({ sealed });
|
||||
},
|
||||
setFilter: (filter) => {
|
||||
updateState({ filter });
|
||||
},
|
||||
showAdding: () => {
|
||||
updateState({ adding: true });
|
||||
},
|
||||
hideAdding: () => {
|
||||
updateState({ adding: false });
|
||||
},
|
||||
setAddSubject: (addSubject) => {
|
||||
updateState({ addSubject });
|
||||
},
|
||||
setAddMember: (cardId) => {
|
||||
updateState({ addMembers: [ ...state.addMembers, cardId ] });
|
||||
},
|
||||
clearAddMember: (cardId) => {
|
||||
updateState({ addMembers: state.addMembers.filter(item => item !== cardId) });
|
||||
},
|
||||
addTopic: () => {
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
|
Loading…
Reference in New Issue
Block a user