mirror of
https://gitea.tendokyu.moe/ppc/amnet.git
synced 2026-09-27 00:50:06 +03:00
add https/port warnings
This commit is contained in:
+111
-37
@@ -1,20 +1,31 @@
|
||||
"use client";
|
||||
|
||||
import {z} from "zod";
|
||||
import React from "react";
|
||||
import Link from "next/link";
|
||||
import React, {useState} from "react";
|
||||
import TimeAgo from "react-timeago";
|
||||
import {useForm} from "react-hook-form";
|
||||
import {useRouter} from "next/navigation";
|
||||
import {ChevronRight, Earth, History, Loader, Plus, Trash} from "lucide-react";
|
||||
import {AppRouterInstance} from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import {
|
||||
ChevronRight,
|
||||
Earth,
|
||||
History,
|
||||
Loader,
|
||||
Network,
|
||||
Plus,
|
||||
ShieldAlert,
|
||||
SquareArrowOutUpRight,
|
||||
Trash
|
||||
} from "lucide-react";
|
||||
import {useLiveQuery} from "dexie-react-hooks";
|
||||
import {AimeServer, db} from "@/lib/database";
|
||||
import {zodResolver} from "@hookform/resolvers/zod";
|
||||
|
||||
import {Card} from "@/components/ui/card";
|
||||
import {Input} from "@/components/ui/input";
|
||||
import {Button} from "@/components/ui/button";
|
||||
import {Footer} from "@/components/ui/footer";
|
||||
import {Separator} from "@/components/ui/separator";
|
||||
import {Form, FormControl, FormField, FormItem, FormMessage} from "@/components/ui/form";
|
||||
import {
|
||||
ContextMenu,
|
||||
ContextMenuContent,
|
||||
@@ -22,11 +33,11 @@ import {
|
||||
ContextMenuSeparator,
|
||||
ContextMenuTrigger
|
||||
} from "@/components/ui/context-menu";
|
||||
import {AppRouterInstance} from "next/dist/shared/lib/app-router-context.shared-runtime";
|
||||
import {Footer} from "@/components/ui/footer";
|
||||
import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert";
|
||||
import {Form, FormControl, FormField, FormItem, FormMessage} from "@/components/ui/form";
|
||||
|
||||
const serverAdditionSchema = z.object({
|
||||
address: z.string().min(14).startsWith("http")
|
||||
address: z.string().startsWith("http")
|
||||
});
|
||||
|
||||
function redirectToServerPage(router: AppRouterInstance, server: AimeServer) {
|
||||
@@ -47,10 +58,13 @@ function ServerList(props: { servers: AimeServer[] | undefined }) {
|
||||
|
||||
if (!props.servers.length) {
|
||||
return (
|
||||
<div className="flex flex-col gap-2 items-center text-gray-500 pt-5">
|
||||
<Earth className="h-8 w-8"/>
|
||||
<span className="text-center">No servers found. Add one below!</span>
|
||||
</div>
|
||||
<>
|
||||
<div className="flex flex-col gap-2 items-center text-gray-500 pt-6 pb-5">
|
||||
<Earth className="h-8 w-8"/>
|
||||
<span className="text-center">No servers found. Add one below!</span>
|
||||
</div>
|
||||
<ServerAddForm/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -63,10 +77,12 @@ function ServerList(props: { servers: AimeServer[] | undefined }) {
|
||||
<div className="flex-grow flex flex-col gap-4">
|
||||
<h4 className="text-2xl font-semibold">{s.name}</h4>
|
||||
<div className="text-md flex gap-3 flex-wrap">
|
||||
<div className="flex items-center gap-2 text-gray-500">
|
||||
<History className="h-5 w-5"/>
|
||||
<TimeAgo date={s.lastConnected}/>
|
||||
</div>
|
||||
{s.lastConnected > 0 && (
|
||||
<div className="flex items-center gap-2 text-gray-500">
|
||||
<History className="h-5 w-5"/>
|
||||
<TimeAgo date={s.lastConnected}/>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex items-center gap-2 text-gray-500">
|
||||
<Earth className="h-5 w-5"/>
|
||||
<code>{s.address}</code>
|
||||
@@ -84,7 +100,7 @@ function ServerList(props: { servers: AimeServer[] | undefined }) {
|
||||
Select Server
|
||||
</ContextMenuItem>
|
||||
<ContextMenuSeparator/>
|
||||
<ContextMenuItem className="text-red-500">
|
||||
<ContextMenuItem className="text-red-500" onClick={() => db.servers.delete(s.id)}>
|
||||
<Trash className="mr-2 h-4 w-4"/> Remove Server
|
||||
</ContextMenuItem>
|
||||
</ContextMenuContent>
|
||||
@@ -100,6 +116,10 @@ function ServerAddForm() {
|
||||
resolver: zodResolver(serverAdditionSchema)
|
||||
});
|
||||
|
||||
const [showHttpsWarning, setHttpsWarning] = useState(false);
|
||||
const [showPortWarning, setPortWarning] = useState(false);
|
||||
const [blockSubmit, setBlockSubmit] = useState(true);
|
||||
|
||||
async function onSubmit(values: z.infer<typeof serverAdditionSchema>) {
|
||||
const existingServer = await db.servers
|
||||
.where("address")
|
||||
@@ -111,8 +131,13 @@ function ServerAddForm() {
|
||||
if (!existingServer) {
|
||||
const newId = await db.servers.add({
|
||||
name: "Server",
|
||||
address: values.address,
|
||||
lastConnected: Date.now()
|
||||
lastConnected: 0,
|
||||
address: values.address
|
||||
});
|
||||
|
||||
// set server name using id
|
||||
await db.servers.update(newId, {
|
||||
name: `Server #${newId}`
|
||||
});
|
||||
|
||||
router.push(`/servers/${newId}`);
|
||||
@@ -121,26 +146,75 @@ function ServerAddForm() {
|
||||
}
|
||||
}
|
||||
|
||||
function handleAddressChange(event: React.ChangeEvent<HTMLInputElement>, callback: (value: React.ChangeEvent<HTMLInputElement>) => void) {
|
||||
try {
|
||||
const address = new URL(event.target.value);
|
||||
|
||||
setBlockSubmit(false);
|
||||
setPortWarning(!address.port);
|
||||
setHttpsWarning(address.protocol !== "http:");
|
||||
} catch {
|
||||
setBlockSubmit(true);
|
||||
setPortWarning(false);
|
||||
setHttpsWarning(false);
|
||||
}
|
||||
|
||||
callback(event);
|
||||
}
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="flex gap-3 items-start">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="address"
|
||||
render={({field}) => (
|
||||
<FormItem className="flex-grow">
|
||||
<FormControl>
|
||||
<Input placeholder="Server Address" {...field} />
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Button type="submit" variant="outline" size="icon" className="flex-shrink-0">
|
||||
<Plus className="h-4 w-4"/>
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
<>
|
||||
{(showHttpsWarning || showPortWarning) && (<div></div>)}
|
||||
{showHttpsWarning && (
|
||||
<Alert variant="blank" className="text-yellow-500 border-yellow-500">
|
||||
<ShieldAlert className="h-5 w-5 text-yellow-500"/>
|
||||
<AlertTitle>HTTPS Warning</AlertTitle>
|
||||
<AlertDescription>
|
||||
AimeNet doesn't support HTTPS out-the-box.
|
||||
If you're using HTTPS, ensure a reverse-proxy or <Link target="_blank"
|
||||
className="underline"
|
||||
href="https://learn.microsoft.com/en-us/aspnet/core/fundamentals/servers/httpsys">
|
||||
HTTP.SYS <SquareArrowOutUpRight className="inline h-3 w-3"/>
|
||||
</Link> has been configured and a valid, trusted SSL certificate has been configured.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
{(showPortWarning && !showHttpsWarning) && (
|
||||
<Alert variant="blank" className="text-purple-500 border-purple-500">
|
||||
<Network className="h-5 w-5 text-purple-500"/>
|
||||
<AlertTitle>Default Port Detected</AlertTitle>
|
||||
<AlertDescription>
|
||||
Ensure you've set the correct port in the address field. By default, AimeNet uses
|
||||
port <code>6070</code>.
|
||||
</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="flex gap-3 items-start">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="address"
|
||||
|
||||
render={({field}) => (
|
||||
<FormItem className="flex-grow">
|
||||
<FormControl>
|
||||
<Input {...field}
|
||||
placeholder="Server Address (http://192.168.1.1:6070)"
|
||||
onChange={e => handleAddressChange(e, field.onChange)}/>
|
||||
</FormControl>
|
||||
<FormMessage/>
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Button type="submit" disabled={blockSubmit} variant="outline" size="icon"
|
||||
className="flex-shrink-0">
|
||||
<Plus className="h-4 w-4"/>
|
||||
</Button>
|
||||
</form>
|
||||
</Form>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user