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