Files
ppc_amnet/amnet-native/app/ServerAddModal.tsx

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);
}
}