mirror of
https://github.com/balzack/databag.git
synced 2025-02-12 03:29:16 +00:00
preparing conversation screen
This commit is contained in:
parent
8d5209396a
commit
4479ba5dca
@ -43,34 +43,31 @@ export function Session() {
|
||||
const screenParams = { headerShown: true, headerTintColor: Colors.primary };
|
||||
|
||||
const ConversationStackScreen = () => {
|
||||
const conversation = useContext(ConversationContext);
|
||||
const [cardId, setCardId] = useState();
|
||||
const [channelId, setChannelId] = useState();
|
||||
|
||||
const setConversation = async (navigation, cardId, channelId) => {
|
||||
const openConversation = async (navigation, card, channel) => {
|
||||
setCardId(card);
|
||||
setChannelId(channel);
|
||||
navigation.navigate('conversation');
|
||||
await conversation.actions.setConversation(cardId, channelId);
|
||||
}
|
||||
const clearConversation = (navigation) => {
|
||||
navigation.dispatch(
|
||||
CommonActions.reset({ index: 0, routes: [ { name: 'channels' }, ], })
|
||||
);
|
||||
conversation.actions.clearConversation();
|
||||
const closeConversation = (navigation) => {
|
||||
setCardId(null);
|
||||
setChannelId(null);
|
||||
}
|
||||
const openDetails = (navigation) => {
|
||||
navigation.navigate('details');
|
||||
}
|
||||
|
||||
return (
|
||||
<ConversationStack.Navigator
|
||||
initialRouteName="channels"
|
||||
screenOptions={({ route }) => (screenParams)}
|
||||
screenListeners={{ state: (e) => { if (e?.data?.state?.index === 0) { conversation.actions.clearConversation() }} }}>
|
||||
<ConversationStack.Navigator initialRouteName="channels" screenOptions={({ route }) => (screenParams)} >
|
||||
|
||||
<ConversationStack.Screen name="channels" options={stackParams}>
|
||||
{(props) => <Channels navigation={props.navigation} openConversation={(cardId, channelId) => setConversation(props.navigation, cardId, channelId)} />}
|
||||
{(props) => <Channels navigation={props.navigation} openConversation={(cardId, channelId) => openConversation(props.navigation, cardId, channelId)} />}
|
||||
</ConversationStack.Screen>
|
||||
|
||||
<ConversationStack.Screen name="conversation" options={{ ...stackParams, headerTitle: (props) => <ConversationHeader closeConversation={clearConversation} openDetails={openDetails} /> }}>
|
||||
{(props) => <ConversationBody />}
|
||||
<ConversationStack.Screen name="conversation" options={stackParams}>
|
||||
{(props) => <Conversation navigation={props.navigation} cardId={cardId} channelId={channelId} openDetails={() => openDetails(props.navigation)} closeConversation={closeConversation} /> }
|
||||
</ConversationStack.Screen>
|
||||
|
||||
<ConversationStack.Screen name="details" options={{ ...stackParams, headerTitle: (props) => <DetailsHeader /> }}>
|
||||
@ -143,13 +140,17 @@ export function Session() {
|
||||
|
||||
const conversation = useContext(ConversationContext);
|
||||
const [channel, setChannel] = useState(false);
|
||||
const [cardId, setCardId] = useState();
|
||||
const [channelId, setChannelId] = useState();
|
||||
|
||||
const setConversation = (cardId, channelId) => {
|
||||
conversation.actions.setConversation(cardId, channelId);
|
||||
const setConversation = (card, channel) => {
|
||||
setCardId(card);
|
||||
setChannelId(channel);
|
||||
setChannel(true);
|
||||
};
|
||||
const clearConversation = () => {
|
||||
conversation.actions.clearConversation();
|
||||
const closeConversation = () => {
|
||||
setCardId(null);
|
||||
setChannelId(null);
|
||||
setChannel(false);
|
||||
};
|
||||
const openDetails = () => {
|
||||
@ -169,8 +170,8 @@ export function Session() {
|
||||
|
||||
return (
|
||||
<View style={styles.home}>
|
||||
<SafeAreaView edges={['top', 'bottom']} style={styles.sidebar}>
|
||||
<SafeAreaView edges={['left']} style={styles.options}>
|
||||
<SafeAreaView edges={['top', 'bottom', 'left']} style={styles.sidebar}>
|
||||
<View edges={['left']} style={styles.options}>
|
||||
<TouchableOpacity style={styles.option} onPress={openProfile}>
|
||||
<ProfileIcon color={Colors.text} size={20} />
|
||||
<Text style={styles.profileLabel}>Profile</Text>
|
||||
@ -179,14 +180,16 @@ export function Session() {
|
||||
<CardsIcon color={Colors.text} size={20} />
|
||||
<Text style={styles.profileLabel}>Contacts</Text>
|
||||
</TouchableOpacity>
|
||||
</SafeAreaView>
|
||||
</View>
|
||||
<View style={styles.channels}>
|
||||
<Channels openConversation={setConversation} />
|
||||
<Channels cardId={cardId} channelId={channelId} openConversation={setConversation} />
|
||||
</View>
|
||||
</SafeAreaView>
|
||||
<View style={styles.conversation}>
|
||||
{ channel && (
|
||||
<Conversation closeConversation={clearConversation} openDetails={openDetails} />
|
||||
<SafeAreaView edges={['top', 'bottom', 'right']}>
|
||||
<Conversation cardId={cardId} channelId={channelId} closeConversation={closeConversation} openDetails={openDetails} />
|
||||
</SafeAreaView>
|
||||
)}
|
||||
{ !channel && (
|
||||
<Welcome />
|
||||
@ -262,9 +265,13 @@ export function Session() {
|
||||
};
|
||||
|
||||
return (
|
||||
<DetailDrawer.Navigator screenOptions={{ ...drawerParams, drawerStyle: { width: '45%' } }}
|
||||
drawerContent={(props) => <Details closeConversation={closeConversation} />}
|
||||
>
|
||||
<DetailDrawer.Navigator screenOptions={{ ...drawerParams, drawerStyle: { width: '45%' } }} drawerContent={(props) => (
|
||||
<ScrollView style={styles.drawer}>
|
||||
<SafeAreaView edges={['top', 'bottom', 'right']}>
|
||||
<Details closeConversation={closeConversation} />
|
||||
</SafeAreaView>
|
||||
</ScrollView>
|
||||
)}>
|
||||
<DetailDrawer.Screen name="contact">
|
||||
{(props) => <ContactDrawerScreen navParams={{...navParams, detailNav: props.navigation}} />}
|
||||
</DetailDrawer.Screen>
|
||||
|
@ -80,9 +80,12 @@ export const styles = StyleSheet.create({
|
||||
height: '100%',
|
||||
width: '33%',
|
||||
maxWidth: 500,
|
||||
borderRightWidth: 1,
|
||||
borderColor: Colors.divider,
|
||||
},
|
||||
conversation: {
|
||||
width: '67%',
|
||||
backgroundColor: Colors.formFocus,
|
||||
},
|
||||
drawer: {
|
||||
width: '100%',
|
||||
|
@ -7,14 +7,15 @@ import { Colors } from 'constants/Colors';
|
||||
import { ChannelItem } from './channelItem/ChannelItem';
|
||||
import { AddMember } from './addMember/AddMember';
|
||||
|
||||
export function Channels({ navigation, openConversation }) {
|
||||
export function Channels({ cardId, channelId, navigation, openConversation }) {
|
||||
|
||||
const { state, actions } = useChannels();
|
||||
|
||||
const addChannel = async () => {
|
||||
try {
|
||||
await actions.addChannel();
|
||||
const channelId = await actions.addChannel();
|
||||
actions.hideAdding();
|
||||
openConversation(null, channelId);
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
@ -57,7 +58,7 @@ export function Channels({ navigation, openConversation }) {
|
||||
</View>
|
||||
)}
|
||||
{ state.channels.length == 0 && (
|
||||
<View style={styles.content}>
|
||||
<View style={styles.notfound}>
|
||||
<Text style={styles.notfoundtext}>No Topics Found</Text>
|
||||
</View>
|
||||
)}
|
||||
@ -66,7 +67,7 @@ export function Channels({ navigation, openConversation }) {
|
||||
style={styles.content}
|
||||
data={state.channels}
|
||||
initialNumToRender={25}
|
||||
renderItem={({ item }) => <ChannelItem item={item} openConversation={openConversation} />}
|
||||
renderItem={({ item }) => <ChannelItem cardId={cardId} channelId={channelId} item={item} openConversation={openConversation} />}
|
||||
keyExtractor={item => (`${item.cardId}:${item.channelId}`)}
|
||||
/>
|
||||
)}
|
||||
|
@ -78,10 +78,23 @@ export const styles = StyleSheet.create({
|
||||
flexShrink: 1,
|
||||
paddingLeft: 4,
|
||||
},
|
||||
notfound: {
|
||||
flexGrow: 1,
|
||||
flexShrink: 1,
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
display: 'flex',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
notfoundtext: {
|
||||
fontSize: 18,
|
||||
color: Colors.disabled,
|
||||
},
|
||||
columnbottom: {
|
||||
paddingLeft: 24,
|
||||
paddingRight: 16,
|
||||
paddingTop: 8,
|
||||
paddingBottom: 16,
|
||||
borderTopWidth: 1,
|
||||
borderColor: Colors.divider,
|
||||
},
|
||||
|
@ -6,10 +6,12 @@ import { useChannelItem } from './useChannelItem.hook';
|
||||
import Colors from 'constants/Colors';
|
||||
import Ionicons from 'react-native-vector-icons/MaterialCommunityIcons';
|
||||
|
||||
export function ChannelItem({ item, openConversation }) {
|
||||
export function ChannelItem({ cardId, channelId, item, openConversation }) {
|
||||
|
||||
const container = (cardId === item.cardId && channelId === item.channelId) ? styles.active : styles.container;
|
||||
|
||||
return (
|
||||
<TouchableOpacity style={styles.container} activeOpacity={1} onPress={() => openConversation(item.cardId, item.channelId, item.revision)}>
|
||||
<TouchableOpacity style={container} activeOpacity={1} onPress={() => openConversation(item.cardId, item.channelId, item.revision)}>
|
||||
<Logo src={item.logo} width={32} height={32} radius={3} />
|
||||
<View style={styles.detail}>
|
||||
<View style={styles.subject}>
|
||||
|
@ -13,6 +13,18 @@ export const styles = StyleSheet.create({
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
active: {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
height: 48,
|
||||
alignItems: 'center',
|
||||
borderBottomWidth: 1,
|
||||
borderColor: Colors.itemDivider,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
backgroundColor: Colors.formFocus,
|
||||
},
|
||||
detail: {
|
||||
paddingLeft: 12,
|
||||
display: 'flex',
|
||||
|
@ -6,6 +6,7 @@ import { AppContext } from 'context/AppContext';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
import { getChannelSeals, isUnsealed, getContentKey, encryptChannelSubject, decryptChannelSubject, decryptTopicSubject } from 'context/sealUtil';
|
||||
import { getCardByGuid } from 'context/cardUtil';
|
||||
import { getChannelSubjectLogo } from 'context/channelUtil';
|
||||
|
||||
export function useChannels() {
|
||||
const [state, setState] = useState({
|
||||
@ -37,20 +38,15 @@ export function useChannels() {
|
||||
const timestamp = item.summary.lastTopic.created;
|
||||
const { readRevision, topicRevision } = item;
|
||||
|
||||
// extract or decrypt subject
|
||||
let locked;
|
||||
let unlocked;
|
||||
let message;
|
||||
let subject;
|
||||
// decrypt subject and message
|
||||
let locked = false;
|
||||
let unlocked = false;
|
||||
if (item.detail.dataType === 'sealed') {
|
||||
locked = true;
|
||||
const seals = getChannelSeals(item.detail.data);
|
||||
if (isUnsealed(seals, account.state.sealKey)) {
|
||||
unlocked = true;
|
||||
if (item.unsealedDetail) {
|
||||
subject = item.unsealedDetail.subject;
|
||||
}
|
||||
else {
|
||||
if (!item.unsealedDetail) {
|
||||
try {
|
||||
const contentKey = await getContentKey(seals, account.state.sealKey);
|
||||
const unsealed = decryptChannelSubject(item.detail.data, contentKey);
|
||||
@ -66,10 +62,7 @@ export function useChannels() {
|
||||
}
|
||||
}
|
||||
if (item.summary.lastTopic.dataType === 'sealedtopic') {
|
||||
if (item.unsealedSummary) {
|
||||
message = item.unsealedSummary.message.text;
|
||||
}
|
||||
else {
|
||||
if (!item.unsealedSummary) {
|
||||
try {
|
||||
const contentKey = await getContentKey(seals, account.state.sealKey);
|
||||
const unsealed = decryptTopicSubject(item.summary.lastTopic.data, contentKey);
|
||||
@ -87,18 +80,20 @@ export function useChannels() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let message;
|
||||
if (item?.detail?.dataType === 'sealed') {
|
||||
if (typeof item?.unsealedSummary?.message?.text === 'string') {
|
||||
message = item.unsealedSummary.message.text;
|
||||
}
|
||||
}
|
||||
if (item.detail.dataType === 'superbasic') {
|
||||
locked = false;
|
||||
unlocked = false;
|
||||
try {
|
||||
subject = JSON.parse(item.detail.data).subject;
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
if (item.summary.lastTopic.dataType === 'superbasictopic') {
|
||||
try {
|
||||
message = JSON.parse(item.summary.lastTopic.data).text;
|
||||
const data = JSON.parse(item.summary.lastTopic.data);
|
||||
if (typeof data.text === 'string') {
|
||||
message = data.text;
|
||||
}
|
||||
}
|
||||
catch(err) {
|
||||
console.log(err);
|
||||
@ -106,50 +101,8 @@ export function useChannels() {
|
||||
}
|
||||
}
|
||||
|
||||
const contacts = [];
|
||||
if (cardId) {
|
||||
contacts.push(cardId);
|
||||
}
|
||||
item.detail.members.forEach(guid => {
|
||||
if (guid !== profile.state.identity.guid) {
|
||||
contacts.push(getCardByGuid(card.state.cards, guid)?.card?.cardId);
|
||||
}
|
||||
})
|
||||
|
||||
if (!subject) {
|
||||
if (contacts.length === 0) {
|
||||
subject = 'Notes';
|
||||
}
|
||||
else {
|
||||
const names = [];
|
||||
contacts.forEach(id => {
|
||||
const contact = card.state.cards.get(id);
|
||||
if (contact?.card.profile?.name) {
|
||||
names.push(contact.card.profile.name);
|
||||
}
|
||||
else {
|
||||
names.push(contact?.card.profile?.handle);
|
||||
}
|
||||
});
|
||||
subject = names.join(', ');
|
||||
}
|
||||
}
|
||||
|
||||
if (contacts.length === 0) {
|
||||
logo = 'solution';
|
||||
}
|
||||
else if (contacts.length === 1) {
|
||||
const contact = card.state.cards.get(contacts[0]);
|
||||
if (contact?.card?.profile?.imageSet) {
|
||||
logo = card.actions.getCardImageUrl(contacts[0])
|
||||
}
|
||||
else {
|
||||
logo = 'avatar';
|
||||
}
|
||||
}
|
||||
else {
|
||||
logo = 'appstore';
|
||||
}
|
||||
const profileGuid = profile.state?.identity?.guid;
|
||||
const { logo, subject } = getChannelSubjectLogo(cardId, profileGuid, item, card.state.cards, card.actions.getCardImageUrl);
|
||||
|
||||
const updated = (loginTimestamp < timestamp) && (readRevision < topicRevision);
|
||||
|
||||
|
@ -1,13 +1,54 @@
|
||||
import { Text, } from 'react-native';
|
||||
import { useEffect, useContext } from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import { ConversationContext } from 'context/ConversationContext';
|
||||
import { useConversation } from './useConversation.hook';
|
||||
import { styles } from './Conversation.styled';
|
||||
import { Colors } from 'constants/Colors';
|
||||
import Ionicons from 'react-native-vector-icons/AntDesign';
|
||||
import { Logo } from 'utils/Logo';
|
||||
|
||||
export function ConversationHeader({ closeConversation, openDetails, state, actions }) {
|
||||
return <Text>ConversationHeader</Text>;
|
||||
}
|
||||
export function Conversation({ navigation, cardId, channelId, closeConversation, openDetails }) {
|
||||
|
||||
export function ConversationBody({ state, actions }) {
|
||||
return <Text>ConversationBody</Text>
|
||||
}
|
||||
const conversation = useContext(ConversationContext);
|
||||
const { state, actions } = useConversation();
|
||||
|
||||
export function Conversation({ closeConversation, openDetails }) {
|
||||
return <Text>Conversation</Text>;
|
||||
useEffect(() => {
|
||||
if (navigation) {
|
||||
navigation.setOptions({
|
||||
headerTitle: () => (
|
||||
<View style={styles.title}>
|
||||
<Text style={styles.titletext}>{ state.subject }</Text>
|
||||
</View>
|
||||
),
|
||||
headerRight: () => (
|
||||
<TouchableOpacity onPress={openDetails}>
|
||||
<Ionicons name={'setting'} size={24} color={Colors.primary} style={styles.titlebutton} />
|
||||
</TouchableOpacity>
|
||||
),
|
||||
});
|
||||
}
|
||||
}, [navigation, state.subject]);
|
||||
|
||||
useEffect(() => {
|
||||
conversation.actions.setConversation(cardId, channelId);
|
||||
return () => { conversation.actions.clearConversation() };
|
||||
}, [cardId, channelId]);
|
||||
|
||||
return (
|
||||
<View>
|
||||
{ !navigation && (
|
||||
<View style={styles.header}>
|
||||
<TouchableOpacity style={styles.headertitle} onPress={openDetails}>
|
||||
<Logo src={state.logo} width={32} height={32} radius={2} />
|
||||
<Text style={styles.titletext}>{ state.subject }</Text>
|
||||
<Ionicons name={'setting'} size={24} color={Colors.primary} style={styles.titlebutton} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.headerclose} onPress={closeConversation}>
|
||||
<Ionicons name={'close'} size={28} color={Colors.grey} style={styles.titlebutton} />
|
||||
</TouchableOpacity>
|
||||
</View>
|
||||
)}
|
||||
<Text>Conversation</Text>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ export const styles = StyleSheet.create({
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
paddingLeft: 16,
|
||||
paddingTop: 16,
|
||||
paddingTop: 8,
|
||||
paddingBottom: 8,
|
||||
},
|
||||
titletext: {
|
||||
|
@ -1,7 +1,33 @@
|
||||
import { useState } from 'react';
|
||||
import { useEffect, useState, useContext } from 'react';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
import { CardContext } from 'context/CardContext';
|
||||
import { ConversationContext } from 'context/ConversationContext';
|
||||
import { getChannelSubjectLogo } from 'context/channelUtil';
|
||||
|
||||
export function useConversation() {
|
||||
const [state, setState] = useState({});
|
||||
const [state, setState] = useState({
|
||||
subject: null,
|
||||
logo: null,
|
||||
});
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const profile = useContext(ProfileContext);
|
||||
const card = useContext(CardContext);
|
||||
const conversation = useContext(ConversationContext);
|
||||
|
||||
useEffect(() => {
|
||||
const cardId = conversation.state.card?.cardId;
|
||||
const profileGuid = profile.state.identity?.guid;
|
||||
const channel = conversation.state.channel;
|
||||
const cards = card.state.cards;
|
||||
cardImageUrl = card.actions.getCardImageUrl;
|
||||
const { logo, subject } = getChannelSubjectLogo(cardId, profileGuid, channel, cards, cardImageUrl);
|
||||
updateState({ logo, subject });
|
||||
}, [conversation.state, card.state, profile.state]);
|
||||
|
||||
|
||||
const actions = {};
|
||||
|
||||
|
@ -3,6 +3,7 @@ import { CardContext } from 'context/CardContext';
|
||||
import { ChannelContext } from 'context/ChannelContext';
|
||||
import { ProfileContext } from 'context/ProfileContext';
|
||||
import { getCardByGuid } from 'context/cardUtil';
|
||||
import { getChannelSubjectLogo } from 'context/channelUtil';
|
||||
import moment from 'moment';
|
||||
|
||||
export function useBlockedTopics() {
|
||||
@ -44,47 +45,9 @@ export function useBlockedTopics() {
|
||||
timestamp = moment(date).format('M/DD/YYYY');
|
||||
}
|
||||
|
||||
let subject;
|
||||
if (item?.detail?.data) {
|
||||
try {
|
||||
topic = JSON.parse(item?.detail?.data).subject;
|
||||
subject = topic;
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
if (!subject) {
|
||||
let contacts = [];
|
||||
if (item.cardId) {
|
||||
contacts.push(card.state.cards.get(item.cardId));
|
||||
}
|
||||
if (item.channel.detail?.members) {
|
||||
const profileGuid = profile.state.identity.guid;
|
||||
item.channel.detail.members.forEach(guid => {
|
||||
if (profileGuid !== guid) {
|
||||
const contact = getCardByGuid(card.state.cards, guid);
|
||||
contacts.push(contact);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
if (contacts.length) {
|
||||
let names = [];
|
||||
for (let contact of contacts) {
|
||||
if (contact?.card?.profile?.name) {
|
||||
names.push(contact.card.profile.name);
|
||||
}
|
||||
else if (contact?.card?.profile?.handle) {
|
||||
names.push(contact.card.profile.handle);
|
||||
}
|
||||
}
|
||||
subject = names.join(', ');
|
||||
}
|
||||
else {
|
||||
subject = "Notes";
|
||||
}
|
||||
}
|
||||
const profileGuid = profile.state?.identity?.guid;
|
||||
const { logo, subject } = getChannelSubjectLogo(item.cardId, profileGuid, item.channel, card.state.cards, card.actions.getCardImageUrl);
|
||||
|
||||
return {
|
||||
id: `${item.cardId}:${item.channel.channelId}`,
|
||||
|
@ -12,7 +12,7 @@ export function Welcome() {
|
||||
return (
|
||||
<SafeAreaView style={styles.container}>
|
||||
<Text style={styles.header}>Databag</Text>
|
||||
<Text style={styles.label}>Communication for the decentralized web</Text>
|
||||
<Text style={styles.label}>Communication for the Decentralized Web</Text>
|
||||
<Image style={styles.image} source={session} />
|
||||
<View style={styles.steps}>
|
||||
<Text style={styles.stepstext}>Setup your profile</Text>
|
||||
|
Loading…
Reference in New Issue
Block a user