feat(rn): 增加服务器选择入口

pull/90/head
moonrailgun 2 years ago
parent a15e1270a0
commit f8a4055628

@ -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",

@ -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}
/>
<AppMain />
{selectedServerInfo ? (
<AppMain host={selectedServerInfo.url} />
) : (
<Entry />
)}
</SafeAreaView>
);
}

@ -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<Props> = React.memo((props) => {
return (
<View style={styles.root}>
<WebView source={{ uri: 'https://nightly.paw.msgbyte.com/' }} />
<WebView source={{ uri: props.host }} />
</View>
);
});

@ -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 (
<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}
onPress={() => selectServer(serverInfo)}
/>
);
})}
<ServerCard name={'添加服务器'} onPress={() => Alert.alert('暂不支持')} />
</ScrollView>
);
});
Entry.displayName = 'Entry';
const styles = StyleSheet.create({
root: {
height: '100%',
padding: 20,
},
item: {
marginBottom: 8,
},
});

@ -0,0 +1,48 @@
import React from 'react';
import {
StyleProp,
StyleSheet,
Text,
TouchableOpacity,
ViewStyle,
} from 'react-native';
interface ServerCardProps {
style?: StyleProp<ViewStyle>;
name: string;
url?: string;
onPress?: () => void;
}
export const ServerCard: React.FC<ServerCardProps> = React.memo((props) => {
return (
<TouchableOpacity
style={[styles.root, props.style]}
onPress={props.onPress}
>
<Text style={styles.name}>{props.name}</Text>
{props.url && <Text style={styles.url}>{props.url}</Text>}
</TouchableOpacity>
);
});
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',
},
});

@ -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<ServerStoreState>()(
immer((set) => ({
serverList: defaultServerList,
selectedServerInfo: null,
addServer: (url: string) => {
set((state) => {
state.serverList.push({
url,
});
});
},
selectServer: (serverInfo: ServerInfo) => {
set({
selectedServerInfo: serverInfo,
});
},
}))
);

@ -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"

Loading…
Cancel
Save