import {BSON} from "realm"; import {Button, Paragraph, useTheme} from "react-native-paper"; import {Globe, History, Plus, ServerOff} from "lucide-react-native"; import {Alert, FlatList, NativeSyntheticEvent, Text, View} from "react-native"; import React, {useCallback, useEffect, useLayoutEffect, useMemo, useState} from "react"; import ContextMenu, {ContextMenuOnPressNativeEvent} from "react-native-context-menu-view"; import {EmptyStatePlaceholder} from "../components/EmptyStatePlaceholder"; import {AMUICard, AMUICardDetail} from "../components/AMUICard"; import TimeAgo from "../components/TimeAgo"; import RealmContext from "../models/RealmContext"; import {AMServer} from "../models/AMServer"; import ObjectId = BSON.ObjectId; const {useRealm, useQuery} = RealmContext; function ServerCard(props: { server: AMServer, navigation: any }) { const realm = useRealm(); const pageCallback = useCallback(() => { props.navigation.navigate('server', { serverId: props.server._id.toHexString() }); }, [props.navigation, props.server]); const pageContextMenuCallback = useCallback((action: NativeSyntheticEvent) => { switch (action.nativeEvent.index) { case 0: pageCallback(); break; case 1: realm.write(() => { realm.delete(props.server); }); break; } }, [realm, props.server]); return ( {props.server.serverAddress} {props.server.lastUsed ? () : (never)} ) } export default function ServerManager({route, navigation}) { const realm = useRealm(); const theme = useTheme(); const [searchQuery, setSearchQuery] = useState(''); const query = useQuery(AMServer); const servers = useMemo(() => { let q = query; if (searchQuery !== '') { q = q.filtered("serverName CONTAINS[c] $0 OR serverAddress CONTAINS[c] $0", searchQuery); } return q.sorted("lastUsed"); }, [query, searchQuery]); // enable searchbar useLayoutEffect(() => { navigation.setOptions({ headerSearchBarOptions: { type: "text", value: searchQuery, autoCorrect: "none", autoCapitalize: "none", onChangeText: e => setSearchQuery(e.nativeEvent.text) }, }) }, [navigation, setSearchQuery]); // handle deep links once/render useEffect(() => { handleDeepLink(realm, navigation, route); }, []); if (!servers.length) { return ( }/> {(!searchQuery || !query.length) && ( )} ); } return ( i._id.toString()} style={{padding: 16, paddingTop: 24}} contentContainerStyle={{paddingBottom: 40}} ItemSeparatorComponent={() => } renderItem={i => }/> ) } async function handleDeepLink(realm, navigation, route) { if (!route.params?.serverAddress) { return; } let serverId: ObjectId; const serverUrl = decodeURIComponent(route.params.serverAddress); const item = realm.objects(AMServer).filtered("serverAddress = $0", serverUrl); if (item.length) { serverId = item[0]._id; } else { try { new URL(serverUrl); realm.write(() => { const newServer = realm.create(AMServer, AMServer.generate(serverUrl)); newServer.serverName = "Imported Server"; serverId = newServer._id; }); } catch (TypeError) { Alert.alert("Invalid Server URL", "The server URL provided is invalid."); } } // clear param from route navigation.setParams({serverAddress: null}); if (serverId) { // give it some time to let everything load (and the user sees the initial list) await new Promise(resolve => setTimeout(resolve, 500)); navigation.navigate('server', { serverId: serverId.toHexString() }); } return null; }