diff --git a/client/mobile/package.json b/client/mobile/package.json index 02cb40fe..996ea379 100644 --- a/client/mobile/package.json +++ b/client/mobile/package.json @@ -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", diff --git a/client/mobile/src/Entry.tsx b/client/mobile/src/Entry.tsx index 9577e4b9..3920f022 100644 --- a/client/mobile/src/Entry.tsx +++ b/client/mobile/src/Entry.tsx @@ -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 ( - - {serverList.map((serverInfo, i) => { - return ( - selectServer(serverInfo)} - onLongPress={() => { - if (i !== 0) { - setSelectedServer(serverInfo.url); - } - }} - /> - ); - })} + + + {serverList.map((serverInfo, i) => { + return ( + selectServer(serverInfo)} + onLongPress={() => { + if (i !== 0) { + setSelectedServer(serverInfo.url); + } + }} + /> + ); + })} - setDialogVisible(true)} - /> + setDialogVisible(true)} + /> - setSelectedServer('')} - destructiveButtonIndex={0} - options={[ - { - label: translate('core.deleteServer'), - onPress: () => { - removeServer(selectedServer); + setSelectedServer('')} + destructiveButtonIndex={0} + options={[ + { + label: translate('core.deleteServer'), + onPress: () => { + removeServer(selectedServer); + }, }, - }, - ]} - showCancelButton={true} - /> + ]} + showCancelButton={true} + /> + + setDialogVisible(false)} + > + + {translate('core.inputServerUrl')}: - setDialogVisible(false)} - > - - {translate('core.inputServerUrl')}: + - + + - setLoading(false); - }} - /> - - - + + { + Clipboard.setString(cid); + showToast(translate('core.copySuccess')); + }} + > + + cid: {cid} + + + + + {toastEl} + ); }); Entry.displayName = 'Entry'; @@ -109,6 +140,9 @@ const styles = StyleSheet.create({ height: '100%', padding: 20, }, + main: { + flex: 1, + }, item: { marginBottom: 8, }, diff --git a/client/mobile/src/components/ServerCard.tsx b/client/mobile/src/components/ServerCard.tsx index 39011b72..83c65a5a 100644 --- a/client/mobile/src/components/ServerCard.tsx +++ b/client/mobile/src/components/ServerCard.tsx @@ -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; @@ -24,10 +19,16 @@ export const ServerCard: React.FC = React.memo((props) => { > {props.name} - {props.url && {props.url}} + {props.url && ( + + {props.url} + + )} {props.version && ( - version: {props.version} + + version: {props.version} + )} ); @@ -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', }, }); diff --git a/client/mobile/src/hooks/useToast.tsx b/client/mobile/src/hooks/useToast.tsx new file mode 100644 index 00000000..5bfbe272 --- /dev/null +++ b/client/mobile/src/hooks/useToast.tsx @@ -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: ( + setVisible(false)} + autoDismiss={3500} + swipeable={true} + /> + ), + }; +} diff --git a/client/mobile/src/lib/i18n/translations/en.json b/client/mobile/src/lib/i18n/translations/en.json index 6111ab24..ff5e209a 100644 --- a/client/mobile/src/lib/i18n/translations/en.json +++ b/client/mobile/src/lib/i18n/translations/en.json @@ -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", diff --git a/client/mobile/src/lib/i18n/translations/zh.json b/client/mobile/src/lib/i18n/translations/zh.json index cea2e828..98df03f1 100644 --- a/client/mobile/src/lib/i18n/translations/zh.json +++ b/client/mobile/src/lib/i18n/translations/zh.json @@ -4,6 +4,7 @@ "core.deleteServer": "删除服务器", "core.inputServerUrl": "输入服务器地址", "core.confirm": "确认", + "core.copySuccess": "复制成功", "core.invalidUrl": "输入不是一个有效的url", "core.addServerError": "添加服务器失败, 可能输入的地址不是一个Tailchat服务地址", "core.foregroundServiceTip": "持续保持服务正常运行, 关闭后可能无法正常接受到消息推送", diff --git a/client/mobile/yarn.lock b/client/mobile/yarn.lock index dfafbafd..a39dc065 100644 --- a/client/mobile/yarn.lock +++ b/client/mobile/yarn.lock @@ -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"