Update fonts, upadte logging, and auth.

This commit is contained in:
LukeGus
2025-08-08 00:40:32 -05:00
parent d0b139e388
commit 08f9143993
7 changed files with 160 additions and 63 deletions
+2 -2
View File
@@ -35,8 +35,8 @@ function App() {
}
return (
<div className="flex">
<main>
<div className="flex min-h-svh w-full">
<main className="flex-1 w-full">
{renderActiveView()}
</main>
</div>
+4 -8
View File
@@ -68,16 +68,14 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement {
}, []);
return (
<div className="flex min-h-screen">
<HomepageSidebar
onSelectView={onSelectView}
disabled={!loggedIn || authLoading}
isAdmin={isAdmin}
username={loggedIn ? username : null}
/>
<div className="flex-1 bg-background grid grid-cols-3 items-center">
<div className="col-span-1"></div>
<div className="col-span-1 flex justify-center">
>
<div className="w-full min-h-svh grid place-items-center">
<div className="flex flex-row items-center justify-center gap-8">
<HomepageAuth
setLoggedIn={setLoggedIn}
setIsAdmin={setIsAdmin}
@@ -87,13 +85,11 @@ export function Homepage({onSelectView}: HomepageProps): React.ReactElement {
dbError={dbError}
setDbError={setDbError}
/>
</div>
<div className="col-span-1 flex justify-center">
<HomepageUpdateLog
loggedIn={loggedIn}
/>
</div>
</div>
</div>
</HomepageSidebar>
);
}
+8 -3
View File
@@ -14,7 +14,7 @@ import {
SidebarGroupLabel,
SidebarMenu,
SidebarMenuButton,
SidebarMenuItem, SidebarProvider,
SidebarMenuItem, SidebarProvider, SidebarInset,
} from "@/components/ui/sidebar.tsx"
import {
@@ -44,6 +44,7 @@ interface SidebarProps {
disabled?: boolean;
isAdmin?: boolean;
username?: string | null;
children?: React.ReactNode;
}
function handleLogout() {
@@ -72,7 +73,8 @@ export function HomepageSidebar({
getView,
disabled,
isAdmin,
username
username,
children,
}: SidebarProps): React.ReactElement {
const [adminSheetOpen, setAdminSheetOpen] = React.useState(false);
const [allowRegistration, setAllowRegistration] = React.useState(true);
@@ -160,7 +162,7 @@ export function HomepageSidebar({
};
return (
<div>
<div className="min-h-svh">
<SidebarProvider>
<Sidebar>
<SidebarContent>
@@ -430,6 +432,9 @@ export function HomepageSidebar({
</Sheet>
)}
</Sidebar>
<SidebarInset>
{children}
</SidebarInset>
</SidebarProvider>
</div>
)
+1 -1
View File
@@ -98,7 +98,7 @@ export function HomepageUpdateLog({loggedIn}: HomepageUpdateLogProps) {
};
return (
<div className="w-[400px] h-[600px] mr-8 flex flex-col border border-border rounded-lg bg-card p-4">
<div className="w-[400px] h-[600px] flex flex-col border border-border rounded-lg bg-card p-4">
<div>
<h3 className="text-lg font-semibold mb-3">Updates & Releases</h3>
+25
View File
@@ -38,6 +38,7 @@ import {
import {ScrollArea} from "@/components/ui/scroll-area.tsx";
import {Input} from "@/components/ui/input.tsx";
import {getSSHHosts} from "@/apps/SSH/ssh-axios";
import {Checkbox} from "@/components/ui/checkbox.tsx";
interface SSHHost {
id: number;
@@ -186,6 +187,17 @@ export function SSHSidebar({onSelectView, onHostConnect, allTabs, runCommandOnTa
}
};
function getCookie(name: string) {
return document.cookie.split('; ').reduce((r, v) => {
const parts = v.split('=');
return parts[0] === name ? decodeURIComponent(parts[1]) : r;
}, "");
}
const updateRightClickCopyPaste = (checked) => {
document.cookie = `rightClickCopyPaste=${checked}; expires=2147483647; path=/`;
}
return (
<SidebarProvider>
<Sidebar className="h-full flex flex-col overflow-hidden">
@@ -332,6 +344,19 @@ export function SSHSidebar({onSelectView, onHostConnect, allTabs, runCommandOnTa
</AccordionContent>
</AccordionItem>
</Accordion>
<Separator className="p-0.25"/>
<div className="flex items-center space-x-2 mt-5">
<Checkbox id="enable-copy-paste" onCheckedChange={updateRightClickCopyPaste}
defaultChecked={getCookie("rightClickCopyPaste") === "true"}/>
<label
htmlFor="enable-paste"
className="text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
>
Enable rightclick copy/paste
</label>
</div>
</div>
</SheetContent>
</Sheet>
+72 -1
View File
@@ -52,6 +52,49 @@ export const SSHTerminal = forwardRef<any, SSHTerminalProps>(function SSHTermina
fitAddonRef.current?.fit();
}
function getCookie(name: string) {
return document.cookie.split('; ').reduce((r, v) => {
const parts = v.split('=');
return parts[0] === name ? decodeURIComponent(parts[1]) : r;
}, "");
}
function getUseRightClickCopyPaste() {
return getCookie("rightClickCopyPaste") === "true"
}
async function writeTextToClipboard(text: string): Promise<void> {
try {
if (navigator.clipboard && navigator.clipboard.writeText) {
await navigator.clipboard.writeText(text);
return;
}
} catch (_) {
}
const textarea = document.createElement('textarea');
textarea.value = text;
textarea.style.position = 'fixed';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.focus();
textarea.select();
try {
document.execCommand('copy');
} finally {
document.body.removeChild(textarea);
}
}
async function readTextFromClipboard(): Promise<string> {
try {
if (navigator.clipboard && navigator.clipboard.readText) {
return await navigator.clipboard.readText();
}
} catch (_) {
}
return '';
}
useEffect(() => {
if (!terminal || !xtermRef.current || !hostConfig) return;
@@ -59,7 +102,7 @@ export const SSHTerminal = forwardRef<any, SSHTerminalProps>(function SSHTermina
cursorBlink: true,
cursorStyle: 'bar',
scrollback: 10000,
fontSize: 15,
fontSize: 14,
fontFamily: '"JetBrains Mono Nerd Font", "MesloLGS NF", "FiraCode Nerd Font", "Cascadia Code", "JetBrains Mono", Consolas, "Courier New", monospace',
theme: {
background: '#09090b',
@@ -88,6 +131,31 @@ export const SSHTerminal = forwardRef<any, SSHTerminalProps>(function SSHTermina
terminal.loadAddon(webLinksAddon);
terminal.open(xtermRef.current);
const element = xtermRef.current;
const handleContextMenu = async (e: MouseEvent) => {
if (!getUseRightClickCopyPaste()) return;
e.preventDefault();
e.stopPropagation();
try {
if (terminal.hasSelection()) {
const selection = terminal.getSelection();
if (selection) {
await writeTextToClipboard(selection);
terminal.clearSelection();
}
} else {
const pasteText = await readTextFromClipboard();
if (pasteText) {
terminal.paste(pasteText);
}
}
} catch (_) {
}
};
if (element) {
element.addEventListener('contextmenu', handleContextMenu);
}
const resizeObserver = new ResizeObserver(() => {
if (resizeTimeout.current) clearTimeout(resizeTimeout.current);
resizeTimeout.current = setTimeout(() => {
@@ -158,6 +226,9 @@ export const SSHTerminal = forwardRef<any, SSHTerminalProps>(function SSHTermina
return () => {
resizeObserver.disconnect();
if (element) {
element.removeEventListener('contextmenu', handleContextMenu);
}
if (resizeTimeout.current) clearTimeout(resizeTimeout.current);
if (pingIntervalRef.current) {
clearInterval(pingIntervalRef.current);