File size: 5,017 Bytes
101ebaa
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
"use client";

import { useEffect, useRef, useState } from "react";
import { Menu, Sun, Moon } from "lucide-react";
import Link from "next/link";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { useTheme } from "./ThemeProvider";
import { Button } from "@/components/ui/button";

export default function Navbar() {
    const [isOpen, setIsOpen] = useState(false);
    const { theme, toggleTheme } = useTheme();
    const router = useRouter();

    const adminHoldTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
    const adminGestureTriggeredRef = useRef(false);

    const clearAdminHoldTimer = () => {
        if (adminHoldTimerRef.current) {
            clearTimeout(adminHoldTimerRef.current);
            adminHoldTimerRef.current = null;
        }
    };

    useEffect(() => {
        const onWindowBlur = () => {
            clearAdminHoldTimer();
            adminGestureTriggeredRef.current = false;
        };
        window.addEventListener("blur", onWindowBlur);
        return () => {
            window.removeEventListener("blur", onWindowBlur);
        };
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, []);

    return (
        <nav className="fixed inset-x-0 top-0 z-50 bg-background/90 backdrop-blur supports-[backdrop-filter]:bg-background/70 shadow-[0_1px_0_rgba(255,255,255,0.03)]">
            <div className="mx-auto flex h-16 max-w-6xl items-center justify-between px-4 sm:px-6">
                <Link
                    href="/"
                    className="flex items-center gap-2.5"
                    onPointerDown={(e) => {
                        if (!e.ctrlKey) return;
                        adminGestureTriggeredRef.current = false;
                        clearAdminHoldTimer();
                        adminHoldTimerRef.current = setTimeout(() => {
                            adminGestureTriggeredRef.current = true;
                            router.push("/admin");
                        }, 3000);
                    }}
                    onPointerUp={() => {
                        clearAdminHoldTimer();
                    }}
                    onPointerLeave={() => {
                        clearAdminHoldTimer();
                    }}
                    onPointerCancel={() => {
                        clearAdminHoldTimer();
                    }}
                    onClick={(e) => {
                        if (adminGestureTriggeredRef.current) {
                            e.preventDefault();
                            adminGestureTriggeredRef.current = false;
                        }
                    }}
                >
                    <Image
                        src="/teich.svg"
                        alt="TeichAI Logo"
                        width={32}
                        height={32}
                        className="rounded-lg"
                    />
                    <span className="text-lg font-semibold tracking-tight text-foreground">TeichAI Requests</span>
                </Link>

                <div className="hidden items-center gap-1 md:flex">
                    <Button
                        onClick={toggleTheme}
                        variant="ghost"
                        size="icon"
                        className="ml-1"
                        aria-label="Toggle theme"
                    >
                        {theme === "dark" ? <Sun className="size-4" /> : <Moon className="size-4" />}
                    </Button>

                    <Button asChild className="ml-1">
                        <a href="https://huggingface.co/TeichAI" target="_blank" rel="noopener noreferrer">
                            HF Hub
                        </a>
                    </Button>
                </div>

                <div className="flex items-center gap-1 md:hidden">
                    <Button
                        onClick={toggleTheme}
                        variant="ghost"
                        size="icon"
                        aria-label="Toggle theme"
                    >
                        {theme === "dark" ? <Sun className="size-5" /> : <Moon className="size-5" />}
                    </Button>

                    <Button
                        variant="ghost"
                        size="icon"
                        aria-label="Open menu"
                        onClick={() => setIsOpen(!isOpen)}
                    >
                        <Menu className="size-5" />
                    </Button>
                </div>
            </div>

            {isOpen && (
                <div className="border-t border-border bg-background p-4 md:hidden">
                    <Button asChild className="w-full">
                        <a href="https://huggingface.co/TeichAI" target="_blank" rel="noopener noreferrer">
                            HF Hub
                        </a>
                    </Button>
                </div>
            )}
        </nav>
    );
}