mirror of
https://gitea.tendokyu.moe/ppc/amnet.git
synced 2026-09-22 22:28:22 +03:00
109 lines
4.2 KiB
TypeScript
109 lines
4.2 KiB
TypeScript
import {Button, Paragraph, useTheme} from "react-native-paper";
|
|
import {Globe, History, Plus, ServerOff} from "lucide-react-native";
|
|
import {FlatList, NativeSyntheticEvent, Text, View} from "react-native";
|
|
import React, {useCallback, 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";
|
|
|
|
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<ContextMenuOnPressNativeEvent>) => {
|
|
switch (action.nativeEvent.index) {
|
|
case 0:
|
|
pageCallback();
|
|
break;
|
|
|
|
case 1:
|
|
realm.write(() => {
|
|
realm.delete(props.server);
|
|
});
|
|
break;
|
|
}
|
|
}, [realm, props.server]);
|
|
|
|
return (
|
|
<ContextMenu onPress={pageContextMenuCallback} actions={[
|
|
{title: `Select ${props.server.serverName}`, systemIcon: "chevron.right"},
|
|
{title: "Delete Server", systemIcon: "trash", destructive: true}
|
|
]}>
|
|
<AMUICard title={props.server.serverName} onPress={pageCallback}>
|
|
<AMUICardDetail>
|
|
<Globe size={18} color="gray"/>
|
|
<Text style={{color: "gray", fontFamily: "JetBrainsMono_400Regular"}}>
|
|
{props.server.serverAddress}
|
|
</Text>
|
|
</AMUICardDetail>
|
|
<AMUICardDetail>
|
|
<History size={18} color="gray"/>
|
|
{props.server.lastUsed
|
|
? (<TimeAgo style={{color: "gray"}} dateTo={props.server.lastUsed}/>)
|
|
: (<Paragraph style={{color: "gray"}}>never</Paragraph>)}
|
|
</AMUICardDetail>
|
|
</AMUICard>
|
|
</ContextMenu>
|
|
)
|
|
}
|
|
|
|
export default function ServerManager({navigation}) {
|
|
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]);
|
|
|
|
if (!servers.length) {
|
|
return (
|
|
<View style={{gap: 10, flex: 1, justifyContent: "center", alignItems: "center"}}>
|
|
<EmptyStatePlaceholder message="No servers found" icon={<ServerOff color="gray"/>}/>
|
|
{(!searchQuery || !query.length) && (
|
|
<Button mode="text"
|
|
onPress={() => navigation.navigate('add-server')}
|
|
icon={() => <Plus size={18} color={theme.colors.primary}/>}>Add Server</Button>)}
|
|
</View>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<FlatList contentInsetAdjustmentBehavior="always"
|
|
data={servers}
|
|
keyExtractor={i => i._id.toString()}
|
|
style={{padding: 16, paddingTop: 24}}
|
|
contentContainerStyle={{paddingBottom: 40}}
|
|
ItemSeparatorComponent={() => <View style={{height: 15}}/>}
|
|
renderItem={i => <ServerCard navigation={navigation} server={i.item}/>}/>
|
|
)
|
|
} |