linting mobile app

This commit is contained in:
balzack 2024-10-26 22:58:19 -07:00
parent f3b839f96b
commit efda85f07e
17 changed files with 226 additions and 120 deletions

View File

@ -5,7 +5,7 @@
"scripts": { "scripts": {
"android": "react-native run-android", "android": "react-native run-android",
"ios": "react-native run-ios", "ios": "react-native run-ios",
"lint": "eslint .", "lint": "eslint --fix .",
"format": "prettier --single-quote true --print-width 200 --write src", "format": "prettier --single-quote true --print-width 200 --write src",
"start": "react-native start", "start": "react-native start",
"test": "jest" "test": "jest"
@ -50,8 +50,9 @@
"@types/react-test-renderer": "^18.0.0", "@types/react-test-renderer": "^18.0.0",
"babel-jest": "^29.6.3", "babel-jest": "^29.6.3",
"eslint": "^8.19.0", "eslint": "^8.19.0",
"eslint-plugin-prettier": "5.0.0",
"jest": "^29.6.3", "jest": "^29.6.3",
"prettier": "2.8.8", "prettier": "3.3.3",
"react-test-renderer": "18.2.0", "react-test-renderer": "18.2.0",
"typescript": "5.0.4" "typescript": "5.0.4"
}, },

View File

@ -1,5 +1,4 @@
import {StyleSheet} from 'react-native'; import {StyleSheet} from 'react-native';
import {Colors} from '../constants/Colors';
export const styles = StyleSheet.create({ export const styles = StyleSheet.create({
modal: { modal: {

View File

@ -1,3 +1,4 @@
import React from 'react';
import {Modal, View} from 'react-native'; import {Modal, View} from 'react-native';
import {BlurView} from '@react-native-community/blur'; import {BlurView} from '@react-native-community/blur';
import {Surface, Text, Button} from 'react-native-paper'; import {Surface, Text, Button} from 'react-native-paper';

View File

@ -1,5 +1,4 @@
import {StyleSheet} from 'react-native'; import {StyleSheet} from 'react-native';
import {Colors} from '../constants/Colors';
export const styles = StyleSheet.create({ export const styles = StyleSheet.create({
contacts: { contacts: {
@ -9,6 +8,12 @@ export const styles = StyleSheet.create({
width: '100%', width: '100%',
height: '100%', height: '100%',
}, },
button: {
borderRadius: 8,
},
indicator: {
borderRightWidth: 2,
},
header: { header: {
position: 'relative', position: 'relative',
display: 'flex', display: 'flex',

View File

@ -30,7 +30,7 @@ export function Contacts({openRegistry, openContact}: {openRegistry: () => void;
/> />
</Surface> </Surface>
<Button icon="account-plus" mode="contained" style={{borderRadius: 8}} onPress={openRegistry}> <Button icon="account-plus" mode="contained" style={styles.button} onPress={openRegistry}>
{state.strings.add} {state.strings.add}
</Button> </Button>
</SafeAreaView> </SafeAreaView>
@ -49,14 +49,28 @@ export function Contacts({openRegistry, openContact}: {openRegistry: () => void;
const options = item.status === 'connected' && !item.offsync ? [message, call] : []; const options = item.status === 'connected' && !item.offsync ? [message, call] : [];
const select = () => { const select = () => {
const {guid, handle, node, name, location, description, offsync, imageUrl, cardId, status} = item; const {guid, handle, node, name, location, description, offsync, imageUrl, cardId, status} = item;
const params = {guid, handle, node, name, location, description, offsync, imageUrl, cardId, status}; const params = {
guid,
handle,
node,
name,
location,
description,
offsync,
imageUrl,
cardId,
status,
};
openContact(params); openContact(params);
}; };
const status = item.offsync ? 'offsync' : item.status; const status = item.offsync ? 'offsync' : item.status;
return ( return (
<View style={{borderRightWidth: 2, borderColor: Colors[status]}}> <View style={{...styles.indicator, borderColor: Colors[status]}}>
<Card <Card
containerStyle={{...styles.card, borderColor: theme.colors.outlineVariant}} containerStyle={{
...styles.card,
borderColor: theme.colors.outlineVariant,
}}
imageUrl={item.imageUrl} imageUrl={item.imageUrl}
name={item.name} name={item.name}
handle={item.handle} handle={item.handle}

View File

@ -2,7 +2,7 @@ import {useState, useContext, useEffect} from 'react';
import {AppContext} from '../context/AppContext'; import {AppContext} from '../context/AppContext';
import {DisplayContext} from '../context/DisplayContext'; import {DisplayContext} from '../context/DisplayContext';
import {ContextType} from '../context/ContextType'; import {ContextType} from '../context/ContextType';
import {Card, Channel} from 'databag-client-sdk'; import {Card} from 'databag-client-sdk';
export function useContacts() { export function useContacts() {
const app = useContext(AppContext) as ContextType; const app = useContext(AppContext) as ContextType;
@ -15,7 +15,6 @@ export function useContacts() {
filter: '', filter: '',
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updateState = (value: any) => { const updateState = (value: any) => {
setState(s => ({...s, ...value})); setState(s => ({...s, ...value}));
}; };
@ -55,11 +54,13 @@ export function useContacts() {
return () => { return () => {
contact.removeCardListener(setCards); contact.removeCardListener(setCards);
}; };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
useEffect(() => { useEffect(() => {
const filtered = state.cards.sort(compare).filter(select); const filtered = state.cards.sort(compare).filter(select);
updateState({filtered}); updateState({filtered});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state.sortAsc, state.filter, state.cards]); }, [state.sortAsc, state.filter, state.cards]);
const actions = { const actions = {

View File

@ -6,7 +6,15 @@ import {LocalStore} from '../LocalStore';
const DATABAG_DB = 'db_v213.db'; const DATABAG_DB = 'db_v213.db';
const SETTINGS_DB = 'ls_v001.db'; const SETTINGS_DB = 'ls_v001.db';
const databag = new DatabagSDK({tagBatch: 32, topicBatch: 32, articleTypes: [], channelTypes: ['sealed', 'superbasic']}, new NativeCrypto()); const databag = new DatabagSDK(
{
tagBatch: 32,
topicBatch: 32,
articleTypes: [],
channelTypes: ['sealed', 'superbasic'],
},
new NativeCrypto(),
);
export function useAppContext() { export function useAppContext() {
const local = useRef(new LocalStore()); const local = useRef(new LocalStore());

View File

@ -1,9 +1,8 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import {Button, Surface, Icon, Text, IconButton, Divider} from 'react-native-paper'; import {Icon, Text, IconButton, Divider} from 'react-native-paper';
import {ScrollView, Modal, Image, SafeAreaView, View} from 'react-native'; import {ScrollView, Image, SafeAreaView, View} from 'react-native';
import {styles} from './Profile.styled'; import {styles} from './Profile.styled';
import {useProfile} from './useProfile.hook'; import {useProfile} from './useProfile.hook';
import {BlurView} from '@react-native-community/blur';
import {Confirm} from '../confirm/Confirm'; import {Confirm} from '../confirm/Confirm';
export type ContactParams = { export type ContactParams = {
@ -19,8 +18,7 @@ export type ContactParams = {
offsync?: boolean; offsync?: boolean;
}; };
export function Profile({close, params}) { export function Profile({close, params}: {close: () => void; params: ContactParams}) {
const [alert, setAlert] = useState(false);
const {state, actions} = useProfile(params); const {state, actions} = useProfile(params);
const [confirmShow, setConfirmShow] = useState(false); const [confirmShow, setConfirmShow] = useState(false);
const [busy, setBusy] = useState(false); const [busy, setBusy] = useState(false);
@ -31,18 +29,18 @@ export function Profile({close, params}) {
const [denying, setDenying] = useState(false); const [denying, setDenying] = useState(false);
const [reporting, setReporting] = useState(false); const [reporting, setReporting] = useState(false);
const [saving, setSaving] = useState(false); const [saving, setSaving] = useState(false);
const [connecting, setConnecting] = useState(false);
const [disconnecting, setDisconnecting] = useState(false); const [disconnecting, setDisconnecting] = useState(false);
const [resyncing, setResyncing] = useState(false);
const [canceling, setCanceling] = useState(false); const [canceling, setCanceling] = useState(false);
const [accepting, setAccepting] = useState(false); const [accepting, setAccepting] = useState(false);
const [confirming, setConfirming] = useState(false);
const confirmAction = (title: string, prompt: string, label: string, loading: (boolean) => void, action: () => Promise<void>) => { const confirmAction = (title: string, prompt: string, label: string, loading: (boolean) => void, action: () => Promise<void>) => {
setConfirmParams({ setConfirmParams({
title, title,
prompt, prompt,
cancel: {label: state.strings.cancel, action: () => setConfirmShow(false)}, cancel: {
label: state.strings.cancel,
action: () => setConfirmShow(false),
},
confirm: { confirm: {
label, label,
action: async () => { action: async () => {
@ -75,7 +73,14 @@ export function Profile({close, params}) {
setConfirmShow(false); setConfirmShow(false);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
setConfirmParams({title: state.strings.error, prompt: state.strings.tryAgain, cancel: {label: state.strings.cancel, action: () => setConfirmShow(false)}}); setConfirmParams({
title: state.strings.error,
prompt: state.strings.tryAgain,
cancel: {
label: state.strings.cancel,
action: () => setConfirmShow(false),
},
});
} }
}; };
@ -88,7 +93,7 @@ export function Profile({close, params}) {
</View> </View>
)} )}
<Text style={styles.headerLabel} adjustsFontSizeToFit={true} numberOfLines={1}>{`${state.handle}${state.node ? '/' + state.node : ''}`}</Text> <Text style={styles.headerLabel} adjustsFontSizeToFit={true} numberOfLines={1}>{`${state.handle}${state.node ? '/' + state.node : ''}`}</Text>
{close && <View style={styles.spaceHolder}></View>} {close && <View style={styles.spaceHolder} />}
</SafeAreaView> </SafeAreaView>
<View style={styles.image}> <View style={styles.image}>
@ -149,8 +154,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>
@ -183,8 +187,7 @@ export function Profile({close, params}) {
icon="account-remove" icon="account-remove"
size={32} size={32}
onPress={() => { onPress={() => {
const {removing, confirmRemove, remove} = state.strings; confirmAction(state.strings.removing, state.strings.confirmRemove, state.strings.remove, setRemoving, actions.remove);
confirmAction(removing, confirmRemove, remove, setRemoving, actions.remove);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.remove}</Text> <Text style={styles.actionLabel}>{state.strings.remove}</Text>
@ -198,8 +201,7 @@ export function Profile({close, params}) {
icon="eye-remove-outline" icon="eye-remove-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {blocking, confirmBlocking, block} = state.strings; confirmAction(state.strings.blocking, state.strings.confirmBlocking, state.strings.block, setBlocking, actions.block);
confirmAction(blocking, confirmBlocking, block, setBlocking, actions.block);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.block}</Text> <Text style={styles.actionLabel}>{state.strings.block}</Text>
@ -213,8 +215,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>
@ -289,8 +290,7 @@ export function Profile({close, params}) {
icon="account-remove" icon="account-remove"
size={32} size={32}
onPress={() => { onPress={() => {
const {removing, confirmRemove, remove} = state.strings; confirmAction(state.strings.removing, state.strings.confirmRemove, state.strings.remove, setRemoving, actions.remove);
confirmAction(removing, confirmRemove, remove, setRemoving, actions.remove);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.remove}</Text> <Text style={styles.actionLabel}>{state.strings.remove}</Text>
@ -304,8 +304,7 @@ export function Profile({close, params}) {
icon="eye-remove-outline" icon="eye-remove-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {blocking, confirmBlocking, block} = state.strings; confirmAction(state.strings.blocking, state.strings.confirmBlocking, state.strings.block, setBlocking, actions.block);
confirmAction(blocking, confirmBlocking, block, setBlocking, actions.block);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.block}</Text> <Text style={styles.actionLabel}>{state.strings.block}</Text>
@ -319,8 +318,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>
@ -381,8 +379,7 @@ export function Profile({close, params}) {
icon="account-remove" icon="account-remove"
size={32} size={32}
onPress={() => { onPress={() => {
const {removing, confirmRemove, remove} = state.strings; confirmAction(state.strings.removing, state.strings.confirmRemove, state.strings.remove, setRemoving, actions.remove);
confirmAction(removing, confirmRemove, remove, setRemoving, actions.remove);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.remove}</Text> <Text style={styles.actionLabel}>{state.strings.remove}</Text>
@ -396,8 +393,7 @@ export function Profile({close, params}) {
icon="eye-remove-outline" icon="eye-remove-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {blocking, confirmBlocking, block} = state.strings; confirmAction(state.strings.blocking, state.strings.confirmBlocking, state.strings.block, setBlocking, actions.block);
confirmAction(blocking, confirmBlocking, block, setBlocking, actions.block);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.block}</Text> <Text style={styles.actionLabel}>{state.strings.block}</Text>
@ -411,8 +407,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>
@ -445,8 +440,7 @@ export function Profile({close, params}) {
icon="account-remove" icon="account-remove"
size={32} size={32}
onPress={() => { onPress={() => {
const {removing, confirmRemove, remove} = state.strings; confirmAction(state.strings.removing, state.strings.confirmRemove, state.strings.remove, setRemoving, actions.remove);
confirmAction(removing, confirmRemove, remove, setRemoving, actions.remove);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.remove}</Text> <Text style={styles.actionLabel}>{state.strings.remove}</Text>
@ -460,8 +454,7 @@ export function Profile({close, params}) {
icon="eye-remove-outline" icon="eye-remove-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {blocking, confirmBlocking, block} = state.strings; confirmAction(state.strings.blocking, state.strings.confirmBlocking, state.strings.block, setBlocking, actions.block);
confirmAction(blocking, confirmBlocking, block, setBlocking, actions.block);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.block}</Text> <Text style={styles.actionLabel}>{state.strings.block}</Text>
@ -475,8 +468,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>
@ -495,8 +487,7 @@ export function Profile({close, params}) {
icon="electric-switch" icon="electric-switch"
size={32} size={32}
onPress={() => { onPress={() => {
const {disconnecting, confirmDisconnecting, disconnect} = state.strings; confirmAction(state.strings.disconnecting, state.strings.confirmDisconnect, state.strings.disconnect, setDisconnecting, actions.disconnect);
confirmAction(disconnecting, confirmDisconnect, disconnect, setDisconnecting, actions.disconnect);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.disconnect}</Text> <Text style={styles.actionLabel}>{state.strings.disconnect}</Text>
@ -510,8 +501,7 @@ export function Profile({close, params}) {
icon="account-remove" icon="account-remove"
size={32} size={32}
onPress={() => { onPress={() => {
const {removing, confirmRemove, remove} = state.strings; confirmAction(state.strings.removing, state.strings.confirmRemove, state.strings.remove, setRemoving, actions.remove);
confirmAction(removing, confirmRemove, remove, setRemoving, actions.remove);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.remove}</Text> <Text style={styles.actionLabel}>{state.strings.remove}</Text>
@ -525,8 +515,7 @@ export function Profile({close, params}) {
icon="eye-remove-outline" icon="eye-remove-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {blocking, confirmBlocking, block} = state.strings; confirmAction(state.strings.blocking, state.strings.confirmBlocking, state.strings.block, setBlocking, actions.block);
confirmAction(blocking, confirmBlocking, block, setBlocking, actions.block);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.block}</Text> <Text style={styles.actionLabel}>{state.strings.block}</Text>
@ -540,8 +529,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>
@ -574,8 +562,7 @@ export function Profile({close, params}) {
icon="electric-switch" icon="electric-switch"
size={32} size={32}
onPress={() => { onPress={() => {
const {disconnecting, confirmDisconnecting, disconnect} = state.strings; confirmAction(state.strings.disconnecting, state.strings.confirmDisconnect, state.strings.disconnect, setDisconnecting, actions.disconnect);
confirmAction(disconnecting, confirmDisconnect, disconnect, setDisconnecting, actions.disconnect);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.disconnect}</Text> <Text style={styles.actionLabel}>{state.strings.disconnect}</Text>
@ -589,8 +576,7 @@ export function Profile({close, params}) {
icon="account-remove" icon="account-remove"
size={32} size={32}
onPress={() => { onPress={() => {
const {removing, confirmRemove, remove} = state.strings; confirmAction(state.strings.removing, state.strings.confirmRemove, state.strings.remove, setRemoving, actions.remove);
confirmAction(removing, confirmRemove, remove, setRemoving, actions.remove);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.remove}</Text> <Text style={styles.actionLabel}>{state.strings.remove}</Text>
@ -604,8 +590,7 @@ export function Profile({close, params}) {
icon="eye-remove-outline" icon="eye-remove-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {blocking, confirmBlocking, block} = state.strings; confirmAction(state.strings.blocking, state.strings.confirmBlocking, state.strings.block, setBlocking, actions.block);
confirmAction(blocking, confirmBlocking, block, setBlocking, actions.block);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.block}</Text> <Text style={styles.actionLabel}>{state.strings.block}</Text>
@ -619,8 +604,7 @@ export function Profile({close, params}) {
icon="alert-octagon-outline" icon="alert-octagon-outline"
size={32} size={32}
onPress={() => { onPress={() => {
const {reporting, confirmReporting, report} = state.strings; confirmAction(state.strings.reporting, state.strings.confirmReporting, state.strings.report, setReporting, actions.report);
confirmAction(reporting, confirmReporting, report, setReporting, actions.report);
}} }}
/> />
<Text style={styles.actionLabel}>{state.strings.report}</Text> <Text style={styles.actionLabel}>{state.strings.report}</Text>

View File

@ -5,7 +5,7 @@ import {ContextType} from '../context/ContextType';
import {Card} from 'databag-client-sdk'; import {Card} from 'databag-client-sdk';
import {ContactParams} from './Profile'; import {ContactParams} from './Profile';
export function useProfile(params: ProfileParams) { export function useProfile(params: ContactParams) {
const app = useContext(AppContext) as ContextType; const app = useContext(AppContext) as ContextType;
const display = useContext(DisplayContext) as ContextType; const display = useContext(DisplayContext) as ContextType;
const [state, setState] = useState({ const [state, setState] = useState({
@ -24,7 +24,6 @@ export function useProfile(params: ProfileParams) {
statusLabel: '', statusLabel: '',
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updateState = (value: any) => { const updateState = (value: any) => {
setState(s => ({...s, ...value})); setState(s => ({...s, ...value}));
}; };
@ -40,7 +39,18 @@ export function useProfile(params: ProfileParams) {
const cardId = params.cardId ? params.cardId : null; const cardId = params.cardId ? params.cardId : null;
const status = params.status ? params.status : ''; const status = params.status ? params.status : '';
const offsync = params.offsync ? params.offsync : false; const offsync = params.offsync ? params.offsync : false;
updateState({guid, handle, node, name, location, description, imageUrl, cardId, status, offsync}); updateState({
guid,
handle,
node,
name,
location,
description,
imageUrl,
cardId,
status,
offsync,
});
}, [params]); }, [params]);
const getStatusLabel = (card?: Card) => { const getStatusLabel = (card?: Card) => {
@ -69,11 +79,22 @@ export function useProfile(params: ProfileParams) {
}; };
useEffect(() => { useEffect(() => {
const card = state.cards.find(card => card.guid === state.guid); const saved = state.cards.find(card => card.guid === state.guid);
const statusLabel = getStatusLabel(card); const statusLabel = getStatusLabel(saved);
if (card) { if (saved) {
const {handle, node, name, location, description, imageUrl, cardId, status, offsync} = card; const {handle, node, name, location, description, imageUrl, cardId, status, offsync} = saved;
updateState({handle, node, name, location, description, imageUrl, cardId, status, offsync, statusLabel}); updateState({
handle,
node,
name,
location,
description,
imageUrl,
cardId,
status,
offsync,
statusLabel,
});
} else { } else {
updateState({cardId: null, status: '', offsync: false, statusLabel}); updateState({cardId: null, status: '', offsync: false, statusLabel});
} }
@ -88,6 +109,7 @@ export function useProfile(params: ProfileParams) {
return () => { return () => {
contact.removeCardListener(setCards); contact.removeCardListener(setCards);
}; };
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []); }, []);
const actions = { const actions = {

View File

@ -1,5 +1,4 @@
import {StyleSheet} from 'react-native'; import {StyleSheet} from 'react-native';
import {Colors} from '../constants/Colors';
export const styles = StyleSheet.create({ export const styles = StyleSheet.create({
registry: { registry: {
@ -26,17 +25,6 @@ export const styles = StyleSheet.create({
marginLeft: 0, marginLeft: 0,
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
input: {
flex: 3,
flexGrow: 1,
backgroundColor: 'transparent',
paddingTop: 0,
paddingBottom: 0,
display: 'flex',
height: 40,
maxHeight: 40,
borderRadius: 8,
},
divider: { divider: {
width: '100%', width: '100%',
height: 2, height: 2,

View File

@ -1,6 +1,6 @@
import React from 'react'; import React from 'react';
import {SafeAreaView, View, FlatList} from 'react-native'; import {SafeAreaView, View, FlatList} from 'react-native';
import {Text, IconButton, Icon, Divider, Button, TextInput, Surface, useTheme} from 'react-native-paper'; import {Text, IconButton, Divider, TextInput, Surface, useTheme} from 'react-native-paper';
import {ContactParams} from '../profile/Profile'; import {ContactParams} from '../profile/Profile';
import {styles} from './Registry.styled'; import {styles} from './Registry.styled';
import {useRegistry} from './useRegistry.hook'; import {useRegistry} from './useRegistry.hook';
@ -53,12 +53,23 @@ export function Registry({close, openContact}: {close: () => void; openContact:
renderItem={({item}) => { renderItem={({item}) => {
const select = () => { const select = () => {
const {guid, handle, node, name, location, description, imageUrl} = item; const {guid, handle, node, name, location, description, imageUrl} = item;
const params = {guid, handle, node, name, location, description, imageUrl}; const params = {
guid,
handle,
node,
name,
location,
description,
imageUrl,
};
openContact(params); openContact(params);
}; };
return ( return (
<Card <Card
containerStyle={{...styles.card, borderColor: theme.colors.outlineVariant}} containerStyle={{
...styles.card,
borderColor: theme.colors.outlineVariant,
}}
imageUrl={item.imageUrl} imageUrl={item.imageUrl}
name={item.name} name={item.name}
handle={item.handle} handle={item.handle}

View File

@ -17,7 +17,6 @@ export function useRegistry() {
profiles: [] as Profile[], profiles: [] as Profile[],
}); });
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updateState = (value: any) => { const updateState = (value: any) => {
setState(s => ({...s, ...value})); setState(s => ({...s, ...value}));
}; };
@ -31,9 +30,9 @@ export function useRegistry() {
update.current = null; update.current = null;
try { try {
const contact = app.state.session?.getContact(); const contact = app.state.session?.getContact();
const username = params.username ? params.username : null; const handle = params.username ? params.username : null;
const server = params.server ? params.server : null; const node = params.server ? params.server : null;
const profiles = await contact.getRegistry(username, server); const profiles = await contact.getRegistry(handle, node);
updateState({profiles}); updateState({profiles});
} catch (err) { } catch (err) {
console.log(err); console.log(err);
@ -54,6 +53,7 @@ export function useRegistry() {
getRegistry(state.username, state.server); getRegistry(state.username, state.server);
}, 1000); }, 1000);
} }
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [state.username, state.server]); }, [state.username, state.server]);
const actions = { const actions = {

View File

@ -5,6 +5,10 @@ export const styles = StyleSheet.create({
width: '100%', width: '100%',
height: '100%', height: '100%',
}, },
full: {
width: '100%',
height: '100%',
},
frame: { frame: {
display: 'flex', display: 'flex',
flexDirection: 'row', flexDirection: 'row',

View File

@ -3,7 +3,6 @@ import {SafeAreaView, View, useColorScheme} from 'react-native';
import {styles} from './Session.styled'; import {styles} from './Session.styled';
import {IconButton, Surface, Text} from 'react-native-paper'; import {IconButton, Surface, Text} from 'react-native-paper';
import {Settings} from '../settings/Settings'; import {Settings} from '../settings/Settings';
import {Channels} from '../channels/Channels';
import {Contacts} from '../contacts/Contacts'; import {Contacts} from '../contacts/Contacts';
import {Registry} from '../registry/Registry'; import {Registry} from '../registry/Registry';
import {Profile, ContactParams} from '../profile/Profile'; import {Profile, ContactParams} from '../profile/Profile';
@ -23,7 +22,6 @@ const ProfileDrawer = createDrawerNavigator();
const DetailsDrawer = createDrawerNavigator(); const DetailsDrawer = createDrawerNavigator();
const ContactStack = createStackNavigator(); const ContactStack = createStackNavigator();
const ContentStack = createStackNavigator();
export function Session() { export function Session() {
const {state} = useSession(); const {state} = useSession();
@ -31,24 +29,35 @@ export function Session() {
const [tab, setTab] = useState('content'); const [tab, setTab] = useState('content');
const sessionNav = {strings: state.strings}; const sessionNav = {strings: state.strings};
const showContent = {display: tab === 'content' ? 'flex' : 'none'};
const ChannelsRoute = () => <Channels />; const showContact = {display: tab === 'contacts' ? 'flex' : 'none'};
const ContactsRoute = () => <ContactTab />; const showSettings = {display: tab === 'settings' ? 'flex' : 'none'};
const SettingsRoute = () => <Settings showLogout={true} />;
return ( return (
<View style={styles.session}> <View style={styles.session}>
{state.layout !== 'large' && ( {state.layout !== 'large' && (
<Surface elevation={2}> <Surface elevation={2}>
<SafeAreaView style={{width: '100%', height: '100%'}}> <SafeAreaView style={styles.full}>
<View style={styles.screen}> <View style={styles.screen}>
<View style={{...styles.body, display: tab === 'content' ? 'flex' : 'none'}}> <View
style={{
...styles.body,
...showContent,
}}>
<ContentTab scheme={scheme} /> <ContentTab scheme={scheme} />
</View> </View>
<View style={{...styles.body, display: tab === 'contacts' ? 'flex' : 'none'}}> <View
style={{
...styles.body,
...showContact,
}}>
<ContactTab scheme={scheme} /> <ContactTab scheme={scheme} />
</View> </View>
<View style={{...styles.body, display: tab === 'settings' ? 'flex' : 'none'}}> <View
style={{
...styles.body,
...showSettings,
}}>
<Surface elevation={0}> <Surface elevation={0}>
<Settings showLogout={true} /> <Settings showLogout={true} />
</Surface> </Surface>
@ -141,7 +150,7 @@ function ContentTab({scheme}: {scheme: string}) {
<NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}> <NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}>
<ContactStack.Navigator initialRouteName="contacts" screenOptions={{headerShown: false}}> <ContactStack.Navigator initialRouteName="contacts" screenOptions={{headerShown: false}}>
<ContactStack.Screen name="content" options={{headerBackTitleVisible: false}}> <ContactStack.Screen name="content" options={{headerBackTitleVisible: false}}>
{props => <Text>CONTENT</Text>} {() => <Text>CONTENT</Text>}
</ContactStack.Screen> </ContactStack.Screen>
</ContactStack.Navigator> </ContactStack.Navigator>
</NavigationContainer> </NavigationContainer>
@ -149,11 +158,9 @@ function ContentTab({scheme}: {scheme: string}) {
} }
function ContactTab({scheme}: {scheme: string}) { function ContactTab({scheme}: {scheme: string}) {
const [contactParams, setContactParams] = useState({guid: ''} as ContactParams); const [contactParams, setContactParams] = useState({
const openContact = (params: ContactParams, nav) => { guid: '',
setContactParams(params); } as ContactParams);
nav.navigate('profile');
};
return ( return (
<NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}> <NavigationContainer theme={scheme === 'dark' ? DarkTheme : DefaultTheme}>
@ -171,7 +178,12 @@ function ContactTab({scheme}: {scheme: string}) {
/> />
)} )}
</ContactStack.Screen> </ContactStack.Screen>
<ContactStack.Screen name="registry" options={{headerBackTitleVisible: false, ...TransitionPresets.ScaleFromCenterAndroid}}> <ContactStack.Screen
name="registry"
options={{
headerBackTitleVisible: false,
...TransitionPresets.ScaleFromCenterAndroid,
}}>
{props => ( {props => (
<Registry <Registry
close={props.navigation.goBack} close={props.navigation.goBack}
@ -182,7 +194,12 @@ function ContactTab({scheme}: {scheme: string}) {
/> />
)} )}
</ContactStack.Screen> </ContactStack.Screen>
<ContactStack.Screen name="profile" options={{headerBackTitleVisible: false, ...TransitionPresets.ScaleFromCenterAndroid}}> <ContactStack.Screen
name="profile"
options={{
headerBackTitleVisible: false,
...TransitionPresets.ScaleFromCenterAndroid,
}}>
{props => <Profile close={props.navigation.goBack} params={contactParams} />} {props => <Profile close={props.navigation.goBack} params={contactParams} />}
</ContactStack.Screen> </ContactStack.Screen>
</ContactStack.Navigator> </ContactStack.Navigator>
@ -206,7 +223,9 @@ function DetailsScreen({nav}) {
} }
function ProfileScreen({nav}) { function ProfileScreen({nav}) {
const [contactParams, setContactParams] = useState({guid: ''} as ContactParams); const [contactParams, setContactParams] = useState({
guid: '',
} as ContactParams);
const openContact = (params: ContactParams, open: () => {}) => { const openContact = (params: ContactParams, open: () => {}) => {
setContactParams(params); setContactParams(params);
open(); open();

View File

@ -18,6 +18,10 @@ export const styles = StyleSheet.create({
inputIcon: { inputIcon: {
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
full: {
width: '100%',
height: '100%',
},
container: { container: {
width: 600, width: 600,
maxWidth: '80%', maxWidth: '80%',

View File

@ -1,6 +1,6 @@
import React, {useState} from 'react'; import React, {useState} from 'react';
import {Surface, Button, Text, IconButton, Divider, Icon, TextInput, RadioButton, Switch} from 'react-native-paper'; import {Surface, Button, Text, IconButton, Divider, Icon, TextInput, RadioButton, Switch} from 'react-native-paper';
import {SafeAreaView, TouchableOpacity, Modal, View, Image, ScrollView} from 'react-native'; import {TouchableOpacity, Modal, View, Image, ScrollView} from 'react-native';
import {styles} from './Settings.styled'; import {styles} from './Settings.styled';
import {useSettings} from './useSettings.hook'; import {useSettings} from './useSettings.hook';
import ImagePicker from 'react-native-image-crop-picker'; import ImagePicker from 'react-native-image-crop-picker';
@ -37,7 +37,8 @@ export function Settings({showLogout}: {showLogout: boolean}) {
const [secretCopy, setSecretCopy] = useState(false); const [secretCopy, setSecretCopy] = useState(false);
const [confirmingAuth, setConfirmingAuth] = useState(false); const [confirmingAuth, setConfirmingAuth] = useState(false);
const [authMessage, setAuthMessage] = useState(''); const [authMessage, setAuthMessage] = useState('');
const [alertParams, setAlertParams] = useState({
const alertParams = {
title: state.strings.error, title: state.strings.error,
prompt: state.strings.tryAgain, prompt: state.strings.tryAgain,
cancel: { cancel: {
@ -46,7 +47,7 @@ export function Settings({showLogout}: {showLogout: boolean}) {
setAlert(false); setAlert(false);
}, },
}, },
}); };
const changeLogin = () => { const changeLogin = () => {
actions.setPassword(''); actions.setPassword('');
@ -321,7 +322,7 @@ export function Settings({showLogout}: {showLogout: boolean}) {
return ( return (
<View> <View>
<ScrollView showsVerticalScrollIndicator={false} style={{width: '100%', height: '100%'}}> <ScrollView showsVerticalScrollIndicator={false} style={styles.full}>
<View style={styles.settings}> <View style={styles.settings}>
<Text style={styles.header} adjustsFontSizeToFit={true} numberOfLines={1}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text> <Text style={styles.header} adjustsFontSizeToFit={true} numberOfLines={1}>{`${state.profile.handle}${state.profile.node ? '/' + state.profile.node : ''}`}</Text>
<View style={styles.image}> <View style={styles.image}>

View File

@ -2167,6 +2167,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@pkgr/core@npm:^0.1.0":
version: 0.1.1
resolution: "@pkgr/core@npm:0.1.1"
checksum: 6f25fd2e3008f259c77207ac9915b02f1628420403b2630c92a07ff963129238c9262afc9e84344c7a23b5cc1f3965e2cd17e3798219f5fd78a63d144d3cceba
languageName: node
linkType: hard
"@react-native-clipboard/clipboard@npm:^1.14.2": "@react-native-clipboard/clipboard@npm:^1.14.2":
version: 1.14.2 version: 1.14.2
resolution: "@react-native-clipboard/clipboard@npm:1.14.2" resolution: "@react-native-clipboard/clipboard@npm:1.14.2"
@ -3192,9 +3199,10 @@ __metadata:
crypto-js: ^4.2.0 crypto-js: ^4.2.0
databag-client-sdk: ^0.0.22 databag-client-sdk: ^0.0.22
eslint: ^8.19.0 eslint: ^8.19.0
eslint-plugin-prettier: 5.0.0
jest: ^29.6.3 jest: ^29.6.3
jsencrypt: ^3.3.2 jsencrypt: ^3.3.2
prettier: 2.8.8 prettier: 3.3.3
react: 18.2.0 react: 18.2.0
react-dom: ^18.3.1 react-dom: ^18.3.1
react-native: 0.74.3 react-native: 0.74.3
@ -4783,6 +4791,25 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"eslint-plugin-prettier@npm:5.0.0":
version: 5.0.0
resolution: "eslint-plugin-prettier@npm:5.0.0"
dependencies:
prettier-linter-helpers: ^1.0.0
synckit: ^0.8.5
peerDependencies:
"@types/eslint": ">=8.0.0"
eslint: ">=8.0.0"
prettier: ">=3.0.0"
peerDependenciesMeta:
"@types/eslint":
optional: true
eslint-config-prettier:
optional: true
checksum: 84e88744b9050f2d5ef31b94e85294dda16f3a53c2449f9d33eac8ae6264889b459bf35a68e438fb6b329c2a1d6491aac4bfa00d86317e7009de3dad0311bec6
languageName: node
linkType: hard
"eslint-plugin-prettier@npm:^4.2.1": "eslint-plugin-prettier@npm:^4.2.1":
version: 4.2.1 version: 4.2.1
resolution: "eslint-plugin-prettier@npm:4.2.1" resolution: "eslint-plugin-prettier@npm:4.2.1"
@ -8108,12 +8135,12 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"prettier@npm:2.8.8": "prettier@npm:3.3.3":
version: 2.8.8 version: 3.3.3
resolution: "prettier@npm:2.8.8" resolution: "prettier@npm:3.3.3"
bin: bin:
prettier: bin-prettier.js prettier: bin/prettier.cjs
checksum: b49e409431bf129dd89238d64299ba80717b57ff5a6d1c1a8b1a28b590d998a34e083fa13573bc732bb8d2305becb4c9a4407f8486c81fa7d55100eb08263cf8 checksum: bc8604354805acfdde6106852d14b045bb20827ad76a5ffc2455b71a8257f94de93f17f14e463fe844808d2ccc87248364a5691488a3304f1031326e62d9276e
languageName: node languageName: node
linkType: hard linkType: hard
@ -9516,6 +9543,16 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"synckit@npm:^0.8.5":
version: 0.8.8
resolution: "synckit@npm:0.8.8"
dependencies:
"@pkgr/core": ^0.1.0
tslib: ^2.6.2
checksum: 9ed5d33abb785f5f24e2531efd53b2782ca77abf7912f734d170134552b99001915531be5a50297aa45c5701b5c9041e8762e6cd7a38e41e2461c1e7fccdedf8
languageName: node
linkType: hard
"tar@npm:^6.1.11, tar@npm:^6.2.1": "tar@npm:^6.1.11, tar@npm:^6.2.1":
version: 6.2.1 version: 6.2.1
resolution: "tar@npm:6.2.1" resolution: "tar@npm:6.2.1"
@ -9655,6 +9692,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"tslib@npm:^2.6.2":
version: 2.8.0
resolution: "tslib@npm:2.8.0"
checksum: de852ecd81adfdb4870927e250763345f07dc13fe7f395ce261424966bb122a0992ad844c3ec875c9e63e72afe2220a150712984e44dfd1a8a7e538a064e3d46
languageName: node
linkType: hard
"tsutils@npm:^3.21.0": "tsutils@npm:^3.21.0":
version: 3.21.0 version: 3.21.0
resolution: "tsutils@npm:3.21.0" resolution: "tsutils@npm:3.21.0"