feat(mobile): add cid in entry view

pull/90/head
moonrailgun 2 years ago
parent 3c121e42eb
commit 781d413527

@ -17,6 +17,7 @@
"@formatjs/intl": "^2.6.9",
"@notifee/react-native": "^7.6.1",
"@react-native-async-storage/async-storage": "^1.17.11",
"@react-native-community/clipboard": "^1.5.1",
"immer": "^9.0.19",
"lodash": "^4.17.21",
"mini-star": "^2.0.8",

@ -1,5 +1,6 @@
import React, { useState } from 'react';
import { Alert, ScrollView, StyleSheet, TextInput } from 'react-native';
import React, { useEffect, useState } from 'react';
import { Alert, StyleSheet, ScrollView } from 'react-native';
import Clipboard from '@react-native-community/clipboard';
import { ServerCard } from './components/ServerCard';
import { useServerStore } from './store/server';
import Dialog from 'react-native-ui-lib/dialog';
@ -9,9 +10,13 @@ import {
Text,
View,
ActionSheet,
TextField,
TouchableOpacity,
} from 'react-native-ui-lib';
import { isValidUrl } from './lib/utils';
import { translate } from './lib/i18n';
import { getClientId } from './lib/notifications/getui';
import { useToast } from './hooks/useToast';
export const Entry: React.FC = React.memo(() => {
const { serverList, selectServer, addServer, removeServer } =
@ -20,86 +25,112 @@ export const Entry: React.FC = React.memo(() => {
const [serverUrl, setServerUrl] = useState('');
const [loading, setLoading] = useState(false);
const [selectedServer, setSelectedServer] = useState('');
const [cid, setCid] = useState('');
const { toastEl, showToast } = useToast();
useEffect(() => {
getClientId().then((cid) => {
setCid(cid);
});
}, []);
return (
<ScrollView style={styles.root}>
{serverList.map((serverInfo, i) => {
return (
<ServerCard
key={`${i}#${serverInfo.url}`}
style={styles.item}
name={serverInfo.name ?? serverInfo.url}
url={serverInfo.url}
version={serverInfo.version}
onPress={() => selectServer(serverInfo)}
onLongPress={() => {
if (i !== 0) {
setSelectedServer(serverInfo.url);
}
}}
/>
);
})}
<View style={styles.root}>
<ScrollView style={styles.main}>
{serverList.map((serverInfo, i) => {
return (
<ServerCard
key={`${i}#${serverInfo.url}`}
style={styles.item}
name={serverInfo.name ?? serverInfo.url}
url={serverInfo.url}
version={serverInfo.version}
onPress={() => selectServer(serverInfo)}
onLongPress={() => {
if (i !== 0) {
setSelectedServer(serverInfo.url);
}
}}
/>
);
})}
<ServerCard
name={translate('core.addServer')}
onPress={() => setDialogVisible(true)}
/>
<ServerCard
name={translate('core.addServer')}
onPress={() => setDialogVisible(true)}
/>
<ActionSheet
visible={!!selectedServer}
message={`${translate('core.selectedServer')}: ${selectedServer}`}
onDismiss={() => setSelectedServer('')}
destructiveButtonIndex={0}
options={[
{
label: translate('core.deleteServer'),
onPress: () => {
removeServer(selectedServer);
<ActionSheet
visible={!!selectedServer}
message={`${translate('core.selectedServer')}: ${selectedServer}`}
onDismiss={() => setSelectedServer('')}
destructiveButtonIndex={0}
options={[
{
label: translate('core.deleteServer'),
onPress: () => {
removeServer(selectedServer);
},
},
},
]}
showCancelButton={true}
/>
]}
showCancelButton={true}
/>
<Dialog
visible={dialogVisible}
panDirection={PanningProvider.Directions.DOWN}
onDismiss={() => setDialogVisible(false)}
>
<View backgroundColor="white" style={styles.dialog}>
<Text>{translate('core.inputServerUrl')}:</Text>
<Dialog
visible={dialogVisible}
panDirection={PanningProvider.Directions.DOWN}
onDismiss={() => setDialogVisible(false)}
>
<View backgroundColor="white" style={styles.dialog}>
<Text>{translate('core.inputServerUrl')}:</Text>
<TextField
style={styles.textInput}
migrate={true}
inputMode="url"
value={serverUrl}
onChangeText={setServerUrl}
/>
<TextInput
style={styles.textInput}
inputMode="url"
value={serverUrl}
onChangeText={setServerUrl}
/>
<Button
label={translate('core.confirm')}
disabled={loading}
onPress={async () => {
if (!isValidUrl(serverUrl)) {
Alert.alert(translate('core.invalidUrl'));
return;
}
<Button
label={translate('core.confirm')}
disabled={loading}
onPress={async () => {
if (!isValidUrl(serverUrl)) {
Alert.alert(translate('core.invalidUrl'));
return;
}
setLoading(true);
try {
await addServer(serverUrl);
setDialogVisible(false);
} catch (e) {
Alert.alert(translate('core.addServerError'));
}
setLoading(true);
try {
await addServer(serverUrl);
setDialogVisible(false);
} catch (e) {
Alert.alert(translate('core.addServerError'));
}
setLoading(false);
}}
/>
</View>
</Dialog>
</ScrollView>
setLoading(false);
}}
/>
</View>
</Dialog>
</ScrollView>
<View>
<TouchableOpacity
onPress={() => {
Clipboard.setString(cid);
showToast(translate('core.copySuccess'));
}}
>
<Text grey40 center={true}>
cid: {cid}
</Text>
</TouchableOpacity>
</View>
{toastEl}
</View>
);
});
Entry.displayName = 'Entry';
@ -109,6 +140,9 @@ const styles = StyleSheet.create({
height: '100%',
padding: 20,
},
main: {
flex: 1,
},
item: {
marginBottom: 8,
},

@ -1,11 +1,6 @@
import React from 'react';
import {
StyleProp,
StyleSheet,
Text,
TouchableOpacity,
ViewStyle,
} from 'react-native';
import { StyleProp, StyleSheet, ViewStyle } from 'react-native';
import { TouchableOpacity, Text } from 'react-native-ui-lib';
interface ServerCardProps {
style?: StyleProp<ViewStyle>;
@ -24,10 +19,16 @@ export const ServerCard: React.FC<ServerCardProps> = React.memo((props) => {
>
<Text style={styles.name}>{props.name}</Text>
{props.url && <Text style={styles.url}>{props.url}</Text>}
{props.url && (
<Text style={styles.url} grey30>
{props.url}
</Text>
)}
{props.version && (
<Text style={styles.version}>version: {props.version}</Text>
<Text style={styles.version} grey30>
version: {props.version}
</Text>
)}
</TouchableOpacity>
);
@ -49,12 +50,12 @@ const styles = StyleSheet.create({
textAlign: 'center',
},
version: {
color: '#999',
// color: '#999',
textAlign: 'center',
fontSize: 10,
},
url: {
color: '#999',
// color: '#999',
textAlign: 'center',
},
});

@ -0,0 +1,28 @@
import React, { useCallback, useState } from 'react';
import { Incubator, ToastPresets } from 'react-native-ui-lib';
const { Toast } = Incubator;
export function useToast() {
const [visible, setVisible] = useState(false);
const [message, setMessage] = useState('');
const showToast = useCallback((text: string) => {
setVisible(true);
setMessage(text);
}, []);
return {
showToast,
toastEl: (
<Toast
preset={ToastPresets.SUCCESS}
visible={visible}
message={message}
onDismiss={() => setVisible(false)}
autoDismiss={3500}
swipeable={true}
/>
),
};
}

@ -4,6 +4,7 @@
"core.deleteServer": "Delete Server",
"core.inputServerUrl": "Input Server Url",
"core.confirm": "Confirm",
"core.copySuccess": "Copy Success",
"core.invalidUrl": "Input is not a valid url",
"core.addServerError": "Failed to add server, maybe the address entered is not a Tailchat service address",
"core.foregroundServiceTip": "Continue to keep the service running normally, and may not be able to receive message pushes after closing",

@ -4,6 +4,7 @@
"core.deleteServer": "删除服务器",
"core.inputServerUrl": "输入服务器地址",
"core.confirm": "确认",
"core.copySuccess": "复制成功",
"core.invalidUrl": "输入不是一个有效的url",
"core.addServerError": "添加服务器失败, 可能输入的地址不是一个Tailchat服务地址",
"core.foregroundServiceTip": "持续保持服务正常运行, 关闭后可能无法正常接受到消息推送",

@ -1679,6 +1679,11 @@
prompts "^2.4.0"
semver "^6.3.0"
"@react-native-community/clipboard@^1.5.1":
version "1.5.1"
resolved "https://registry.npmmirror.com/@react-native-community/clipboard/-/clipboard-1.5.1.tgz#32abb3ea2eb91ee3f9c5fb1d32d5783253c9fabe"
integrity sha512-AHAmrkLEH5UtPaDiRqoULERHh3oNv7Dgs0bTC0hO5Z2GdNokAMPT5w8ci8aMcRemcwbtdHjxChgtjbeA38GBdA==
"@react-native-community/eslint-config@^3.2.0":
version "3.2.0"
resolved "https://registry.npmmirror.com/@react-native-community/eslint-config/-/eslint-config-3.2.0.tgz#42f677d5fff385bccf1be1d3b8faa8c086cf998d"

Loading…
Cancel
Save