mirror of
https://gitea.tendokyu.moe/ppc/amnet.git
synced 2026-09-25 07:38:17 +03:00
149 lines
5.6 KiB
TypeScript
149 lines
5.6 KiB
TypeScript
import {StatusBar} from "expo-status-bar";
|
|
import {Card, Text, useTheme} from "react-native-paper";
|
|
import {useCallback, useEffect, useLayoutEffect, useState} from "react";
|
|
import {Alert, Platform, TextInput, TouchableOpacity, View} from "react-native";
|
|
|
|
import {useModalStyles} from "../utils/ModalStyles";
|
|
import RealmContext from "../models/RealmContext";
|
|
import {AMServer} from "../models/AMServer";
|
|
|
|
const {useRealm} = RealmContext;
|
|
|
|
export default function ServerAddModal({route, navigation}) {
|
|
const realm = useRealm();
|
|
const theme = useTheme();
|
|
const modalStyles = useModalStyles();
|
|
|
|
const [serverAddress, setServerAddress] = useState('');
|
|
|
|
// add option to add server address when loading a share link
|
|
useEffect(() => {
|
|
handleDeepLink(realm, navigation, route, setServerAddress);
|
|
}, []);
|
|
|
|
if (Platform.OS === 'ios') {
|
|
useLayoutEffect(() => {
|
|
navigation.setOptions({
|
|
headerLeft: () => <TouchableOpacity onPress={() => navigation.goBack()}>
|
|
<Text variant="bodyMedium" style={modalStyles.headerText}>Cancel</Text>
|
|
</TouchableOpacity>,
|
|
});
|
|
}, [navigation, modalStyles]);
|
|
}
|
|
|
|
useLayoutEffect(() => {
|
|
let urlValid = false;
|
|
|
|
try {
|
|
const protocol = new URL(serverAddress).protocol;
|
|
urlValid = protocol.localeCompare("http:", undefined, {sensitivity: "case"}) === 0 || protocol.localeCompare("https:", undefined, {sensitivity: "case"}) === 0;
|
|
} catch {
|
|
// do nothing
|
|
}
|
|
|
|
const themeOptions = urlValid ? modalStyles.headerText : {color: theme.colors.outline};
|
|
navigation.setOptions({
|
|
headerRight: () => <TouchableOpacity disabled={!urlValid} onPress={() => saveServer(serverAddress)}>
|
|
<Text variant="bodyMedium" style={{...themeOptions, fontWeight: "600"}}>Save</Text>
|
|
</TouchableOpacity>
|
|
})
|
|
}, [navigation, modalStyles, serverAddress]);
|
|
|
|
const saveServer = useCallback(async (address: string) => {
|
|
if (address.startsWith("https:")) {
|
|
await new Promise<void>(done => {
|
|
Alert.alert(
|
|
"HTTPS Warning",
|
|
"By default, AMNet doesn't support HTTPS without advanced configuration. It's highly likely you won't be able to connect.",
|
|
[
|
|
{
|
|
text: "Keep HTTPS",
|
|
style: "destructive",
|
|
onPress: () => done()
|
|
},
|
|
{
|
|
text: "Change to HTTP",
|
|
isPreferred: true,
|
|
onPress: () => {
|
|
address = address.replace(/^https:/i, "http:");
|
|
done();
|
|
}
|
|
},
|
|
]);
|
|
});
|
|
}
|
|
|
|
let serverObject = realm.objects<AMServer>(AMServer.schema.name).find(x => x.serverAddress == address);
|
|
if (!serverObject) {
|
|
realm.write(() => {
|
|
serverObject = realm.create<AMServer>(AMServer.schema.name, AMServer.generate(address));
|
|
});
|
|
}
|
|
|
|
navigation.goBack();
|
|
setTimeout(() => {
|
|
navigation.popTo('app', {
|
|
screen: "servers",
|
|
params: {
|
|
screen: "server",
|
|
params: {
|
|
serverId: serverObject._id.toHexString()
|
|
}
|
|
}
|
|
});
|
|
}, 500);
|
|
}, [realm]);
|
|
|
|
return (<>
|
|
{Platform.OS == 'ios' && <StatusBar style="light"/>}
|
|
<View style={{display: "flex", gap: 10, justifyContent: "center", paddingHorizontal: 15, paddingTop: 25}}>
|
|
<Card mode="contained">
|
|
<Card.Content>
|
|
<View style={{...modalStyles.formItemRow, gap: 10}}>
|
|
<Text variant="bodyMedium" style={{...modalStyles.formItemName, minWidth: 0}}>
|
|
Address
|
|
</Text>
|
|
<TextInput style={modalStyles.formItemInput}
|
|
autoFocus
|
|
numberOfLines={1}
|
|
keyboardType="url"
|
|
autoComplete="off"
|
|
textContentType="URL"
|
|
autoCapitalize="none"
|
|
value={serverAddress}
|
|
onChangeText={setServerAddress}
|
|
placeholder="http://192.168.1.2:6070"
|
|
placeholderTextColor={theme.colors.outline}/>
|
|
</View>
|
|
</Card.Content>
|
|
</Card>
|
|
|
|
<Text variant="bodyMedium" style={modalStyles.formFootnote}>
|
|
AMNet uses HTTP by default. HTTPS will not work unless specifically configured using HTTP.SYS
|
|
</Text>
|
|
</View>
|
|
</>)
|
|
}
|
|
|
|
function handleDeepLink(realm, navigation, route, setAddress: (address: string) => void) {
|
|
if (!route.params?.address) {
|
|
return;
|
|
}
|
|
|
|
const serverUrl = decodeURIComponent(route.params.address);
|
|
const item = realm.objects(AMServer).filtered("serverAddress = $0", serverUrl);
|
|
|
|
if (item.length) {
|
|
// clear modal without animating it
|
|
navigation.setOptions({animation: "none"});
|
|
navigation.goBack();
|
|
|
|
// allow the homepage to render before moving on
|
|
setTimeout(() => navigation.popTo('server', {
|
|
serverId: item[0]._id.toHexString()
|
|
}), 1000);
|
|
} else {
|
|
setAddress(serverUrl);
|
|
}
|
|
}
|