diff --git a/client/mobile/package.json b/client/mobile/package.json index 93f68c4e..8c2f54e2 100644 --- a/client/mobile/package.json +++ b/client/mobile/package.json @@ -1,5 +1,5 @@ { - "name": "Tailchat", + "name": "tailchat-mobile", "version": "0.0.1", "private": true, "scripts": { @@ -10,9 +10,11 @@ "test": "jest" }, "dependencies": { + "immer": "^9.0.19", "react": "18.2.0", "react-native": "0.71.2", - "react-native-webview": "^11.26.1" + "react-native-webview": "^11.26.1", + "zustand": "^4.3.2" }, "devDependencies": { "@babel/core": "^7.20.0", diff --git a/client/mobile/src/App.tsx b/client/mobile/src/App.tsx index 56a2fd80..8f3d4fef 100644 --- a/client/mobile/src/App.tsx +++ b/client/mobile/src/App.tsx @@ -8,10 +8,15 @@ import React from 'react'; import { SafeAreaView, StatusBar, useColorScheme } from 'react-native'; import { AppMain } from './AppMain'; +import { Entry } from './Entry'; +import { useServerStore } from './store/server'; import { theme } from './theme'; function App(): JSX.Element { const isDarkMode = useColorScheme() === 'dark'; + const selectedServerInfo = useServerStore( + (state) => state.selectedServerInfo + ); const backgroundStyle = { backgroundColor: isDarkMode ? theme.contentBg.dark : theme.contentBg.light, @@ -24,7 +29,11 @@ function App(): JSX.Element { backgroundColor={backgroundStyle.backgroundColor} /> - + {selectedServerInfo ? ( + + ) : ( + + )} ); } diff --git a/client/mobile/src/AppMain.tsx b/client/mobile/src/AppMain.tsx index df27b57f..f91d85c4 100644 --- a/client/mobile/src/AppMain.tsx +++ b/client/mobile/src/AppMain.tsx @@ -8,10 +8,13 @@ import { WebView } from 'react-native-webview'; * 由webview提供 */ -export const AppMain: React.FC = React.memo(() => { +interface Props { + host: string; +} +export const AppMain: React.FC = React.memo((props) => { return ( - + ); }); diff --git a/client/mobile/src/Entry.tsx b/client/mobile/src/Entry.tsx new file mode 100644 index 00000000..455324d4 --- /dev/null +++ b/client/mobile/src/Entry.tsx @@ -0,0 +1,37 @@ +import React from 'react'; +import { Alert, ScrollView, StyleSheet } from 'react-native'; +import { ServerCard } from './components/ServerCard'; +import { useServerStore } from './store/server'; + +export const Entry: React.FC = React.memo(() => { + const { serverList, selectServer } = useServerStore(); + + return ( + + {serverList.map((serverInfo, i) => { + return ( + selectServer(serverInfo)} + /> + ); + })} + + Alert.alert('暂不支持')} /> + + ); +}); +Entry.displayName = 'Entry'; + +const styles = StyleSheet.create({ + root: { + height: '100%', + padding: 20, + }, + item: { + marginBottom: 8, + }, +}); diff --git a/client/mobile/src/components/ServerCard.tsx b/client/mobile/src/components/ServerCard.tsx new file mode 100644 index 00000000..b70e6580 --- /dev/null +++ b/client/mobile/src/components/ServerCard.tsx @@ -0,0 +1,48 @@ +import React from 'react'; +import { + StyleProp, + StyleSheet, + Text, + TouchableOpacity, + ViewStyle, +} from 'react-native'; + +interface ServerCardProps { + style?: StyleProp; + name: string; + url?: string; + onPress?: () => void; +} +export const ServerCard: React.FC = React.memo((props) => { + return ( + + {props.name} + + {props.url && {props.url}} + + ); +}); +ServerCard.displayName = 'ServerCard'; + +const styles = StyleSheet.create({ + root: { + height: 56, + padding: 8, + backgroundColor: 'white', + borderRadius: 4, + borderColor: '#ccc', + borderWidth: 1, + justifyContent: 'center', + }, + name: { + fontSize: 16, + textAlign: 'center', + }, + url: { + color: '#999', + textAlign: 'center', + }, +}); diff --git a/client/mobile/src/store/server.ts b/client/mobile/src/store/server.ts new file mode 100644 index 00000000..f5fb8940 --- /dev/null +++ b/client/mobile/src/store/server.ts @@ -0,0 +1,41 @@ +import { create } from 'zustand'; +import { immer } from 'zustand/middleware/immer'; + +interface ServerInfo { + name?: string; + version?: string; + url: string; +} + +interface ServerStoreState { + selectedServerInfo: ServerInfo | null; + serverList: ServerInfo[]; + addServer: (url: string) => void; + selectServer: (serverInfo: ServerInfo) => void; +} + +const defaultServerList: ServerInfo[] = [ + { + name: 'Tailchat Nightly', + url: 'https://nightly.paw.msgbyte.com/', + }, +]; + +export const useServerStore = create()( + immer((set) => ({ + serverList: defaultServerList, + selectedServerInfo: null, + addServer: (url: string) => { + set((state) => { + state.serverList.push({ + url, + }); + }); + }, + selectServer: (serverInfo: ServerInfo) => { + set({ + selectedServerInfo: serverInfo, + }); + }, + })) +); diff --git a/client/mobile/yarn.lock b/client/mobile/yarn.lock index 92547aec..a5cfd632 100644 --- a/client/mobile/yarn.lock +++ b/client/mobile/yarn.lock @@ -3687,6 +3687,11 @@ image-size@^0.6.0: resolved "https://registry.npmmirror.com/image-size/-/image-size-0.6.3.tgz#e7e5c65bb534bd7cdcedd6cb5166272a85f75fb2" integrity sha512-47xSUiQioGaB96nqtp5/q55m0aBQSQdyIloMOc/x+QVTDZLNmXE892IIDrJ0hM1A5vcNUDD5tDffkSP5lCaIIA== +immer@^9.0.19: + version "9.0.19" + resolved "https://registry.npmmirror.com/immer/-/immer-9.0.19.tgz#67fb97310555690b5f9cd8380d38fc0aabb6b38b" + integrity sha512-eY+Y0qcsB4TZKwgQzLaE/lqYMlKhv5J9dyd2RhhtGhNo2njPXDqU9XPfcNfa3MIDsdtZt5KlkIsirlo4dHsWdQ== + import-fresh@^2.0.0: version "2.0.0" resolved "https://registry.npmmirror.com/import-fresh/-/import-fresh-2.0.0.tgz#d81355c15612d386c61f9ddd3922d4304822a546" @@ -6669,7 +6674,7 @@ urix@^0.1.0: resolved "https://registry.npmmirror.com/urix/-/urix-0.1.0.tgz#da937f7a62e21fec1fd18d49b35c2935067a6c72" integrity sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg== -use-sync-external-store@^1.0.0: +use-sync-external-store@1.2.0, use-sync-external-store@^1.0.0: version "1.2.0" resolved "https://registry.npmmirror.com/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz#7dbefd6ef3fe4e767a0cf5d7287aacfb5846928a" integrity sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA== @@ -6911,3 +6916,10 @@ yocto-queue@^0.1.0: version "0.1.0" resolved "https://registry.npmmirror.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +zustand@^4.3.2: + version "4.3.2" + resolved "https://registry.npmmirror.com/zustand/-/zustand-4.3.2.tgz#bb121fcad84c5a569e94bd1a2695e1a93ba85d39" + integrity sha512-rd4haDmlwMTVWVqwvgy00ny8rtti/klRoZjFbL/MAcDnmD5qSw/RZc+Vddstdv90M5Lv6RPgWvm1Hivyn0QgJw== + dependencies: + use-sync-external-store "1.2.0"