mirror of
https://github.com/balzack/databag.git
synced 2025-03-13 09:00:06 +00:00
passing shared item to conversation
This commit is contained in:
parent
cc4fd187bb
commit
b30ff56093
@ -1,5 +1,5 @@
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import {Text, StatusBar} from 'react-native';
|
||||
import React, { useState, useEffect, useRef } from 'react';
|
||||
import {Alert, Text, StatusBar} from 'react-native';
|
||||
import {AppContextProvider} from './src/context/AppContext';
|
||||
import {DisplayContextProvider} from './src/context/DisplayContext';
|
||||
import {NativeRouter} from 'react-router-native';
|
||||
@ -102,10 +102,14 @@ const databagColors = {
|
||||
|
||||
function App(): React.JSX.Element {
|
||||
const colorScheme = useColorScheme();
|
||||
const [share, setShare] = useState(null as null | { filePath: string, mimeType: string });
|
||||
|
||||
useEffect(() => {
|
||||
ReceiveSharingIntent.getReceivedFiles(files => {
|
||||
console.log("GOT FILES!!!", files);
|
||||
if (files && files.length) {
|
||||
const { filePath, mimeType } = files[0];
|
||||
setShare({ filePath, mimeType });
|
||||
}
|
||||
},
|
||||
(error) =>{
|
||||
console.log(error);
|
||||
@ -134,7 +138,7 @@ function App(): React.JSX.Element {
|
||||
<Route path="/" element={<Text>EMPTY</Text>} />
|
||||
<Route path="/access" element={<Access />} />
|
||||
<Route path="/service" element={<Service />} />
|
||||
<Route path="/session" element={<Session />} />
|
||||
<Route path="/session" element={<Session share={share} />} />
|
||||
</Routes>
|
||||
</NativeRouter>
|
||||
</PaperProvider>
|
||||
|
@ -20,6 +20,7 @@ export const en = {
|
||||
setup: 'Setup',
|
||||
accounts: 'Accounts',
|
||||
noAccounts: 'No Accounts',
|
||||
selectShare: 'Select Sharing Topic',
|
||||
|
||||
membership: 'Membership',
|
||||
channelGuest: 'Topic Guest',
|
||||
@ -313,6 +314,7 @@ export const fr = {
|
||||
setup: 'Installation',
|
||||
accounts: 'Comptes',
|
||||
noAccounts: 'Aucun Compte',
|
||||
selectShare: 'Sélectionnez le Sujet de Partage',
|
||||
|
||||
addingTitle: 'Ajout d\'un Compte',
|
||||
addingLink: 'Utilisez le lien suivant pour créer un compte',
|
||||
@ -601,6 +603,7 @@ export const sp = {
|
||||
setup: 'Configuración',
|
||||
accounts: 'Cuentas',
|
||||
noAccounts: 'No hay cuentas',
|
||||
selectShare: 'Seleccionar Tema Para Compartir',
|
||||
|
||||
addingTitle: 'Añadiendo cuenta',
|
||||
addingLink: 'Utilice el siguiente enlace para crear una cuenta',
|
||||
@ -889,6 +892,7 @@ export const pt = {
|
||||
setup: 'configurar',
|
||||
accounts: 'Contas',
|
||||
noAccounts: 'Sem Contas',
|
||||
selectShare: 'Selecione o Tópico de Compartilhamento',
|
||||
|
||||
addingTitle: 'Adicionando conta',
|
||||
addingLink: 'Use o seguinte link para criar uma conta',
|
||||
@ -1178,7 +1182,8 @@ export const de = {
|
||||
setup: 'Aufstellen',
|
||||
accounts: 'Konten',
|
||||
noAccounts: 'Keine Konten',
|
||||
|
||||
selectShare: 'Wählen Sie Das Thema Zum Teilen Aus',
|
||||
|
||||
addingTitle: 'Konto hinzufügen',
|
||||
addingLink: 'Verwenden Sie den folgenden Link, um ein Konto zu erstellen',
|
||||
addingToken: 'Verwenden Sie das folgende Token, um ein Konto vom Anmeldebildschirm aus zu erstellen',
|
||||
@ -1466,6 +1471,7 @@ export const ru = {
|
||||
setup: 'настраивать',
|
||||
accounts: 'Учетные записи',
|
||||
noAccounts: 'Нет учетных записей',
|
||||
selectShare: 'Выберите тему для обмена',
|
||||
|
||||
addingTitle: 'Добавление аккаунта',
|
||||
addingLink: 'Используйте следующую ссылку для создания аккаунта',
|
||||
|
@ -8,8 +8,9 @@ import {Focus} from 'databag-client-sdk';
|
||||
import {BlurView} from '@react-native-community/blur';
|
||||
import {Card} from '../card/Card';
|
||||
import {Confirm} from '../confirm/Confirm';
|
||||
import {Selector} from '../selector/Selector';
|
||||
|
||||
export function Content({openConversation, textCard}: {openConversation: ()=>void, textCard: {cardId: null|string}}) {
|
||||
export function Content({share, closeAll, openConversation, textCard}: { share: { filePath: string, mimeType: string}, closeAll: ()=>void, openConversation: ()=>void, textCard: {cardId: null|string}}) {
|
||||
const [add, setAdd] = useState(false);
|
||||
const [adding, setAdding] = useState(false);
|
||||
const [sealedTopic, setSealedTopic] = useState(false);
|
||||
@ -28,6 +29,17 @@ export function Content({openConversation, textCard}: {openConversation: ()=>voi
|
||||
});
|
||||
const cards = state.sealSet && sealedTopic ? state.sealable : state.connected;
|
||||
|
||||
const select = (cardId: string, channelId: string) => {
|
||||
actions.setFocus(cardId, channelId);
|
||||
openConversation();
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (share) {
|
||||
closeAll();
|
||||
}
|
||||
}, [share]);
|
||||
|
||||
useEffect(() => {
|
||||
if (textCard.cardId) {
|
||||
openTopic(textCard.cardId);
|
||||
@ -105,8 +117,7 @@ export function Content({openConversation, textCard}: {openConversation: ()=>voi
|
||||
renderItem={({item}) => {
|
||||
const {sealed, focused, hosted, unread, imageUrl, subject, message} = item;
|
||||
const open = () => {
|
||||
actions.setFocus(item.cardId, item.channelId);
|
||||
openConversation();
|
||||
select(item.cardId, item.channelId);
|
||||
};
|
||||
const Wrap = (state.layout === 'large' && focused) ? Surface : View;
|
||||
return (
|
||||
@ -231,6 +242,7 @@ export function Content({openConversation, textCard}: {openConversation: ()=>voi
|
||||
</View>
|
||||
</Modal>
|
||||
<Confirm show={alert} params={alertParams} />
|
||||
<Selector share={share} selected={select} channels={state.channels} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ export function useContent() {
|
||||
connected: [] as Card[],
|
||||
sealable: [] as Card[],
|
||||
sorted: [] as Channel[],
|
||||
channels: [] as ChannelParams[],
|
||||
filtered: [] as ChannelParams[],
|
||||
filter: '',
|
||||
topic: '',
|
||||
@ -158,7 +159,7 @@ export function useContent() {
|
||||
return true;
|
||||
});
|
||||
|
||||
updateState({filtered});
|
||||
updateState({channels, filtered});
|
||||
}, [state.sorted, state.cards, state.guid, state.filter, state.focused]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import React, { useState } from 'react';
|
||||
import React, { useState, useEffect } from 'react';
|
||||
import { SafeAreaView, Platform, Modal, ScrollView, View } from 'react-native';
|
||||
import {useTheme, Switch, Surface, Icon, Divider, Button, IconButton, Text, TextInput} from 'react-native-paper';
|
||||
import {styles} from './Details.styled';
|
||||
|
80
app/client/mobile/src/selector/Selector.styled.ts
Normal file
80
app/client/mobile/src/selector/Selector.styled.ts
Normal file
@ -0,0 +1,80 @@
|
||||
import {StyleSheet} from 'react-native';
|
||||
import { Colors } from '../constants/Colors';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
modal: {
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
blur: {
|
||||
position: 'absolute',
|
||||
width: '100%',
|
||||
height: '100%',
|
||||
},
|
||||
content: {
|
||||
position: 'relative',
|
||||
width: '80%',
|
||||
display: 'flex',
|
||||
flexDirection: 'column',
|
||||
borderRadius: 8,
|
||||
},
|
||||
data: {
|
||||
width: '100%',
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
},
|
||||
channels: {
|
||||
minHeight: 100,
|
||||
maxHeight: 400,
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
borderRadius: 8,
|
||||
overflow: 'hidden'
|
||||
},
|
||||
header: {
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
},
|
||||
title: {
|
||||
flexGrow: 1,
|
||||
paddingLeft: 16,
|
||||
fontSize: 20,
|
||||
},
|
||||
close: {
|
||||
backgroundColor: 'transparent',
|
||||
},
|
||||
controls: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
gap: 16,
|
||||
justifyContent: 'flex-end',
|
||||
padding: 16,
|
||||
},
|
||||
empty: {
|
||||
fontSize: 18,
|
||||
color: Colors.placeholder,
|
||||
},
|
||||
control: {
|
||||
borderRadius: 4,
|
||||
},
|
||||
list: {
|
||||
width: '100%',
|
||||
height: 200,
|
||||
},
|
||||
channel: {
|
||||
width: '100%',
|
||||
height: 48,
|
||||
paddingTop: 8,
|
||||
paddingBottom: 8,
|
||||
paddingRight: 16,
|
||||
paddingLeft: 16,
|
||||
borderBottomWidth: 1,
|
||||
},
|
||||
});
|
92
app/client/mobile/src/selector/Selector.tsx
Normal file
92
app/client/mobile/src/selector/Selector.tsx
Normal file
@ -0,0 +1,92 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { Modal, View, FlatList } from 'react-native';
|
||||
import {useTheme, Surface, Button, Text, IconButton} from 'react-native-paper';
|
||||
import {BlurView} from '@react-native-community/blur';
|
||||
import { styles } from './Selector.styled';
|
||||
import { useSelector } from './useSelector.hook';
|
||||
import { ChannelParams } from '../content/Content';
|
||||
import { Channel } from '../channel/Channel';
|
||||
|
||||
export function Selector({ share, selected, channels }: { share: { filePath: string, mimeType: string }, selected: (cardId: string, channelId: string)=>void, channels: ChannelParams[] }) {
|
||||
const { state, actions } = useSelector();
|
||||
const [show, setShow] = useState(false);
|
||||
const theme = useTheme();
|
||||
const [topic, setTopic] = useState(null as null | { cardId: string, channelId: stirng});
|
||||
|
||||
useEffect(() => {
|
||||
if (share) {
|
||||
setShow(true);
|
||||
}
|
||||
}, [share]);
|
||||
|
||||
const select = () => {
|
||||
const { cardId, channelId } = topic;
|
||||
setShow(false);
|
||||
selected(cardId, channelId);
|
||||
}
|
||||
|
||||
return (
|
||||
<Modal animationType="fade" transparent={true} supportedOrientations={['portrait', 'landscape']} visible={show} onRequestClose={()=>setShow(false)}>
|
||||
<View style={styles.modal}>
|
||||
<BlurView style={styles.blur} blurType="dark" blurAmount={6} reducedTransparencyFallbackColor="dark" />
|
||||
<Surface elevation={3} style={styles.content}>
|
||||
<View style={styles.header}>
|
||||
<Text style={styles.title}>{ state.strings.selectShare }</Text>
|
||||
<IconButton style={styles.close} icon="close" size={24} onPress={() => setShow(false)} />
|
||||
</View>
|
||||
<View style={styles.data}>
|
||||
<Surface elevation={1} mode="flat" style={styles.channels}>
|
||||
{ channels.length === 0 && (
|
||||
<Text style={styles.empty}>{ state.strings.noTopics }</Text>
|
||||
)}
|
||||
{ channels.length > 0 && (
|
||||
<FlatList
|
||||
style={styles.list}
|
||||
data={channels}
|
||||
initialNumToRender={32}
|
||||
showsVerticalScrollIndicator={false}
|
||||
renderItem={({item}) => {
|
||||
const {cardId, channelId, sealed, focused, hosted, unread, imageUrl, subject, message} = item;
|
||||
const select = () => {
|
||||
setTopic({ cardId, channelId });
|
||||
};
|
||||
return (
|
||||
<Surface elevation={topic?.cardId === cardId && topic?.channelId === channelId ? 0 : 2 }>
|
||||
<Channel
|
||||
containerStyle={{
|
||||
...styles.channel,
|
||||
borderColor: theme.colors.outlineVariant,
|
||||
}}
|
||||
select={select}
|
||||
unread={false}
|
||||
sealed={sealed}
|
||||
hosted={hosted}
|
||||
imageUrl={imageUrl}
|
||||
notesPlaceholder={state.strings.notes}
|
||||
subjectPlaceholder={state.strings.unknown}
|
||||
subject={subject}
|
||||
messagePlaceholder={`[${state.strings.sealed}]`}
|
||||
message={message}
|
||||
/>
|
||||
</Surface>
|
||||
);
|
||||
}}
|
||||
keyExtractor={channel => `${channel.cardId}:${channel.channelId}`}
|
||||
/>
|
||||
)}
|
||||
</Surface>
|
||||
</View>
|
||||
<View style={styles.controls}>
|
||||
<Button style={styles.control} mode="outlined" onPress={()=>setShow(false)}>
|
||||
{state.strings.cancel}
|
||||
</Button>
|
||||
<Button style={styles.control} disabled={topic==null} mode="contained" onPress={select}>
|
||||
{state.strings.selectImage}
|
||||
</Button>
|
||||
</View>
|
||||
</Surface>
|
||||
</View>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
|
24
app/client/mobile/src/selector/useSelector.hook.ts
Normal file
24
app/client/mobile/src/selector/useSelector.hook.ts
Normal file
@ -0,0 +1,24 @@
|
||||
import { useState, useContext, useEffect } from 'react'
|
||||
import { AppContext } from '../context/AppContext'
|
||||
import { DisplayContext } from '../context/DisplayContext';
|
||||
import { ContextType } from '../context/ContextType'
|
||||
import { Channel } from 'databag-client-sdk';
|
||||
|
||||
export function useSelector() {
|
||||
const app = useContext(AppContext) as ContextType
|
||||
const display = useContext(DisplayContext) as ContextType
|
||||
const [state, setState] = useState({
|
||||
strings: display.state.strings,
|
||||
channels: [] as Channel[],
|
||||
})
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const updateState = (value: any) => {
|
||||
setState((s) => ({ ...s, ...value }))
|
||||
}
|
||||
|
||||
const actions = {
|
||||
}
|
||||
|
||||
return { state, actions }
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
import React, {useState, useCallback, useEffect} from 'react';
|
||||
import {SafeAreaView, Pressable, View, useColorScheme} from 'react-native';
|
||||
import {SafeAreaView, Modal, Pressable, View, useColorScheme} from 'react-native';
|
||||
import {RingContextProvider} from '../context/RingContext';
|
||||
import {styles} from './Session.styled';
|
||||
import {IconButton, Surface, Text, Icon} from 'react-native-paper';
|
||||
@ -30,7 +30,7 @@ const DetailsDrawer = createDrawerNavigator();
|
||||
const ContactStack = createNativeStackNavigator();
|
||||
const ContentStack = createNativeStackNavigator();
|
||||
|
||||
export function Session() {
|
||||
export function Session({ share }: { share: { filePath: string, mimeType: string }}) {
|
||||
const {state} = useSession();
|
||||
const scheme = useColorScheme();
|
||||
const [tab, setTab] = useState('content');
|
||||
@ -39,6 +39,7 @@ export function Session() {
|
||||
const [dismissed, setDismissed] = useState(false);
|
||||
const [disconnected, setDisconnected] = useState(false);
|
||||
const [showDisconnected, setShowDisconnected] = useState(false);
|
||||
const [focus, setFocus] = useState(false);
|
||||
|
||||
const textContact = (cardId: null|string) => {
|
||||
setTextCard({ cardId });
|
||||
@ -48,7 +49,7 @@ export function Session() {
|
||||
setCallCard({ card });
|
||||
}
|
||||
|
||||
const sessionNav = {strings: state.strings, callContact, callCard, textContact, textCard};
|
||||
const sessionNav = {strings: state.strings, callContact, callCard, textContact, textCard, focus, setFocus, share};
|
||||
const showContent = {display: tab === 'content' ? 'flex' : 'none'};
|
||||
const showContact = {display: tab === 'contacts' ? 'flex' : 'none'};
|
||||
const showSettings = {display: tab === 'settings' ? 'flex' : 'none'};
|
||||
@ -66,6 +67,12 @@ export function Session() {
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
if (share) {
|
||||
contentTab();
|
||||
}
|
||||
}, [share]);
|
||||
|
||||
useEffect(() => {
|
||||
if (state.appState && !state.sdkState) {
|
||||
setDisconnected(true);
|
||||
@ -91,7 +98,7 @@ export function Session() {
|
||||
...styles.body,
|
||||
...showContent,
|
||||
}}>
|
||||
<ContentTab textCard={textCard} scheme={scheme} contentTab={contentTab} />
|
||||
<ContentTab share={share} textCard={textCard} scheme={scheme} contentTab={contentTab} />
|
||||
</View>
|
||||
<View
|
||||
style={{
|
||||
@ -205,7 +212,7 @@ export function Session() {
|
||||
);
|
||||
}
|
||||
|
||||
function ContentTab({scheme, textCard, contentTab}: {scheme: string, textCard: {cardId: null|string}, contentTab: ()=>void}) {
|
||||
function ContentTab({scheme, textCard, contentTab, share}: {scheme: string, textCard: {cardId: null|string}, contentTab: ()=>void, share: {filePath: string, mimeType: string}}) {
|
||||
const openConversation = (props) => {
|
||||
props.navigation.navigate('conversation');
|
||||
contentTab();
|
||||
@ -216,7 +223,7 @@ function ContentTab({scheme, textCard, contentTab}: {scheme: string, textCard: {
|
||||
<ContentStack.Navigator initialRouteName="contacts" screenOptions={{headerShown: false}}>
|
||||
<ContentStack.Screen name="content" options={{headerBackTitleVisible: false}}>
|
||||
{props => (
|
||||
<Content textCard={textCard} openConversation={()=>openConversation(props)} />
|
||||
<Content share={share} textCard={textCard} closeAll={()=>props.navigation.popToTop()} openConversation={()=>openConversation(props)} />
|
||||
)}
|
||||
</ContentStack.Screen>
|
||||
<ContentStack.Screen name="conversation" options={styles.noHeader}>
|
||||
@ -279,11 +286,10 @@ function ContactTab({scheme, textContact, callContact}: {scheme: string, textCon
|
||||
}
|
||||
|
||||
function DetailsScreen({nav}) {
|
||||
const [focus, setFocus] = useState(false);
|
||||
|
||||
const closeAll = (props) => {
|
||||
props.navigation.closeDrawer();
|
||||
setFocus(false);
|
||||
nav.setFocus(false);
|
||||
}
|
||||
|
||||
const DetailsComponent = useCallback(
|
||||
@ -307,7 +313,7 @@ function DetailsScreen({nav}) {
|
||||
headerShown: false,
|
||||
overlayColor: 'rgba(8,8,8,.9)',
|
||||
}}>
|
||||
<DetailsDrawer.Screen name="details">{({navigation}) => <ProfileScreen nav={{...nav, focus, setFocus, details: navigation}} />}</DetailsDrawer.Screen>
|
||||
<DetailsDrawer.Screen name="details">{({navigation}) => <ProfileScreen nav={{...nav, details: navigation}} />}</DetailsDrawer.Screen>
|
||||
</DetailsDrawer.Navigator>
|
||||
);
|
||||
}
|
||||
@ -448,7 +454,7 @@ function HomeScreen({nav}) {
|
||||
<Identity openSettings={nav.settings.openDrawer} openContacts={nav.contacts.openDrawer} />
|
||||
</Surface>
|
||||
<Surface style={styles.channels} elevation={2} mode="flat">
|
||||
<Content textCard={nav.textCard} openConversation={()=>nav.setFocus(true)} />
|
||||
<Content share={nav.share} textCard={nav.textCard} closeAll={()=>{}} openConversation={()=>nav.setFocus(true)} />
|
||||
</Surface>
|
||||
</View>
|
||||
<Surface style={styles.right} mode="flat">
|
||||
|
Loading…
Reference in New Issue
Block a user