mirror of
https://github.com/Xevion/dynamic-preauth.git
synced 2025-12-06 11:14:58 -06:00
Finish up highlight, minor increase in time, switch to react-use-webhook, client only rendering
This commit is contained in:
@@ -22,6 +22,7 @@
|
|||||||
"react": "^19.0.0",
|
"react": "^19.0.0",
|
||||||
"react-dom": "^19.0.0",
|
"react-dom": "^19.0.0",
|
||||||
"react-tooltip": "^5.28.0",
|
"react-tooltip": "^5.28.0",
|
||||||
|
"react-use-websocket": "^4.11.1",
|
||||||
"tailwind-merge": "^2.5.5",
|
"tailwind-merge": "^2.5.5",
|
||||||
"tailwindcss": "^3.4.17"
|
"tailwindcss": "^3.4.17"
|
||||||
},
|
},
|
||||||
|
|||||||
8
frontend/pnpm-lock.yaml
generated
8
frontend/pnpm-lock.yaml
generated
@@ -47,6 +47,9 @@ importers:
|
|||||||
react-tooltip:
|
react-tooltip:
|
||||||
specifier: ^5.28.0
|
specifier: ^5.28.0
|
||||||
version: 5.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 5.28.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
react-use-websocket:
|
||||||
|
specifier: ^4.11.1
|
||||||
|
version: 4.11.1
|
||||||
tailwind-merge:
|
tailwind-merge:
|
||||||
specifier: ^2.5.5
|
specifier: ^2.5.5
|
||||||
version: 2.5.5
|
version: 2.5.5
|
||||||
@@ -1964,6 +1967,9 @@ packages:
|
|||||||
react: '>=16.14.0'
|
react: '>=16.14.0'
|
||||||
react-dom: '>=16.14.0'
|
react-dom: '>=16.14.0'
|
||||||
|
|
||||||
|
react-use-websocket@4.11.1:
|
||||||
|
resolution: {integrity: sha512-39e8mK2a2A1h8uY3ePF45b2q0vwMOmaEy7J5qEhQg4n7vYa5oDLmqutG36kZQgAQ/3KCZS0brlGRbbZJ0+zfKQ==}
|
||||||
|
|
||||||
react@19.0.0:
|
react@19.0.0:
|
||||||
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
|
resolution: {integrity: sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -4668,6 +4674,8 @@ snapshots:
|
|||||||
react: 19.0.0
|
react: 19.0.0
|
||||||
react-dom: 19.0.0(react@19.0.0)
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
|
|
||||||
|
react-use-websocket@4.11.1: {}
|
||||||
|
|
||||||
react@19.0.0: {}
|
react@19.0.0: {}
|
||||||
|
|
||||||
read-cache@1.0.0:
|
read-cache@1.0.0:
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ const Demo = ({ class: className }: DemoProps) => {
|
|||||||
highlightedTimeoutRef.current = setTimeout(() => {
|
highlightedTimeoutRef.current = setTimeout(() => {
|
||||||
highlightedTimeoutRef.current = null;
|
highlightedTimeoutRef.current = null;
|
||||||
setHighlightedToken(null);
|
setHighlightedToken(null);
|
||||||
}, 1250);
|
}, 1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -74,7 +74,7 @@ const Demo = ({ class: className }: DemoProps) => {
|
|||||||
className={cn(
|
className={cn(
|
||||||
"transition-colors border hover:border-zinc-500 duration-100 ease-in border-transparent",
|
"transition-colors border hover:border-zinc-500 duration-100 ease-in border-transparent",
|
||||||
{
|
{
|
||||||
"bg-zinc-500 animate-pulse-border border-white text-zinc-50":
|
"bg-zinc-500 animate-pulse-border border-zinc-300 text-zinc-50":
|
||||||
highlightedToken === download.token,
|
highlightedToken === download.token,
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { withBackend } from "@/util";
|
import { withBackend } from "@/util";
|
||||||
import { useEffect, useRef, useState } from "react";
|
import { useEffect, useRef, useState } from "react";
|
||||||
|
import useWebSocket from "react-use-websocket";
|
||||||
|
|
||||||
export interface Download {
|
export interface Download {
|
||||||
token: number;
|
token: number;
|
||||||
@@ -16,107 +17,78 @@ export interface Executable {
|
|||||||
|
|
||||||
export interface UseSocketResult {
|
export interface UseSocketResult {
|
||||||
id: number | null;
|
id: number | null;
|
||||||
status: Status;
|
|
||||||
executables: Executable[] | null;
|
executables: Executable[] | null;
|
||||||
downloads: Download[] | null;
|
downloads: Download[] | null;
|
||||||
buildLog: string | null;
|
buildLog: string | null;
|
||||||
deleteDownload: (id: number) => void;
|
deleteDownload: (id: number) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface UseSocketProps {
|
||||||
|
notify?: (token: number) => void;
|
||||||
|
}
|
||||||
|
|
||||||
export type Status = "connected" | "disconnected" | "connecting";
|
export type Status = "connected" | "disconnected" | "connecting";
|
||||||
|
|
||||||
function useSocket(): UseSocketResult {
|
function useSocket({ notify }: UseSocketProps): UseSocketResult {
|
||||||
|
const { sendMessage, lastMessage, readyState } = useWebSocket(
|
||||||
|
withBackend(
|
||||||
|
window.location.protocol === "https:" ? "wss://" : "ws://",
|
||||||
|
"/ws"
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
const [id, setId] = useState<number | null>(null);
|
const [id, setId] = useState<number | null>(null);
|
||||||
const [downloads, setDownloads] = useState<Download[] | null>(null);
|
const [downloads, setDownloads] = useState<Download[] | null>(null);
|
||||||
const [executables, setExecutables] = useState<{
|
const [executables, setExecutables] = useState<{
|
||||||
build_log: string | null;
|
build_log: string | null;
|
||||||
executables: Executable[];
|
executables: Executable[];
|
||||||
} | null>(null);
|
} | null>(null);
|
||||||
const [status, setStatus] = useState<Status>("connecting");
|
|
||||||
|
|
||||||
const socketRef = useRef<WebSocket | null>(null);
|
useEffect(() => {
|
||||||
const allowReconnectRef = useRef<boolean>(true);
|
{
|
||||||
|
if (lastMessage == null) return;
|
||||||
|
const data = JSON.parse(lastMessage.data);
|
||||||
|
|
||||||
|
if (data.type == undefined)
|
||||||
|
throw new Error("Received message without type");
|
||||||
|
|
||||||
|
switch (data.type) {
|
||||||
|
case "notify":
|
||||||
|
const token = data.token as number;
|
||||||
|
if (notify != null) notify(token);
|
||||||
|
break;
|
||||||
|
case "state":
|
||||||
|
setId(data.session.id as number);
|
||||||
|
setDownloads(data.session.downloads as Download[]);
|
||||||
|
break;
|
||||||
|
case "executables":
|
||||||
|
setExecutables({
|
||||||
|
build_log: data.build_log,
|
||||||
|
executables: data.executables as Executable[],
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.warn("Received unknown message type", data.type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [lastMessage]);
|
||||||
|
|
||||||
function deleteDownload(download_token: number) {
|
function deleteDownload(download_token: number) {
|
||||||
if (socketRef.current == null) {
|
if (readyState !== WebSocket.OPEN) return;
|
||||||
console.error("Socket is null");
|
|
||||||
return;
|
sendMessage(
|
||||||
} else if (socketRef.current.readyState !== WebSocket.OPEN) {
|
|
||||||
console.error("Socket is not open", socketRef.current.readyState);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
socketRef.current.send(
|
|
||||||
JSON.stringify({
|
JSON.stringify({
|
||||||
type: "delete-download-token",
|
type: "delete-download-token",
|
||||||
token: download_token,
|
id: download_token,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
function connect() {
|
|
||||||
const socket = new WebSocket(
|
|
||||||
withBackend(
|
|
||||||
window.location.protocol === "https:" ? "wss://" : "ws://",
|
|
||||||
"/ws"
|
|
||||||
)
|
|
||||||
);
|
|
||||||
socketRef.current = socket;
|
|
||||||
|
|
||||||
socket.onmessage = (event) => {
|
|
||||||
const data = JSON.parse(event.data);
|
|
||||||
|
|
||||||
if (data.type == undefined)
|
|
||||||
throw new Error("Received message without type");
|
|
||||||
|
|
||||||
switch (data.type) {
|
|
||||||
case "state":
|
|
||||||
setId(data.session.id as number);
|
|
||||||
setDownloads(data.session.downloads as Download[]);
|
|
||||||
break;
|
|
||||||
case "executables":
|
|
||||||
setExecutables({
|
|
||||||
build_log: data.build_log,
|
|
||||||
executables: data.executables as Executable[],
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
console.warn("Received unknown message type", data.type);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
socket.onclose = (event) => {
|
|
||||||
console.warn("WebSocket connection closed", event);
|
|
||||||
|
|
||||||
socketRef.current = null;
|
|
||||||
if (allowReconnectRef.current) {
|
|
||||||
setId(null);
|
|
||||||
setDownloads(null);
|
|
||||||
setExecutables(null);
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
connect();
|
|
||||||
}, 3000);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
connect();
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
// Close the socket when the component is unmounted
|
|
||||||
console.debug("Unmounting, closing WebSocket connection");
|
|
||||||
socketRef.current?.close();
|
|
||||||
allowReconnectRef.current = false;
|
|
||||||
};
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id,
|
id,
|
||||||
downloads,
|
downloads,
|
||||||
status,
|
|
||||||
executables: executables?.executables ?? null,
|
executables: executables?.executables ?? null,
|
||||||
buildLog: executables?.build_log,
|
buildLog: executables?.build_log ?? null,
|
||||||
deleteDownload,
|
deleteDownload,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import Demo from "@/components/Demo";
|
|||||||
<Base>
|
<Base>
|
||||||
<div class="w-screen h-screen flex flex-col items-center middle">
|
<div class="w-screen h-screen flex flex-col items-center middle">
|
||||||
<div
|
<div
|
||||||
class="noise-card rounded-sm relative z-20 border-zinc-700 md:border w-full max-w-[40rem] md:mt-16 mb-8 shadow-lg"
|
class="noise-card rounded-sm relative z-20 border-zinc-700 md:border w-full max-w-[40rem] min-h-[41.25rem] md:mt-16 mb-8 shadow-lg"
|
||||||
style={{
|
style={{
|
||||||
backgroundPosition:
|
backgroundPosition:
|
||||||
Math.random() * 100 + "px " + Math.random() * 100 + "px",
|
Math.random() * 100 + "px " + Math.random() * 100 + "px",
|
||||||
@@ -43,7 +43,7 @@ import Demo from "@/components/Demo";
|
|||||||
<span class="px-3 text-2xl font-bebas tracking-wide">Demo</span>
|
<span class="px-3 text-2xl font-bebas tracking-wide">Demo</span>
|
||||||
<hr class="w-32 h-px border-0 bg-zinc-600 my-0" />
|
<hr class="w-32 h-px border-0 bg-zinc-600 my-0" />
|
||||||
</div>
|
</div>
|
||||||
<Demo client:load />
|
<Demo client:only />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,16 +4,13 @@ export default {
|
|||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
animation: {
|
animation: {
|
||||||
"pulse-border": "pulse-border 1s ease-in-out infinite",
|
"pulse-border": "pulse-border 1s cubic-bezier(0.4, 0, 0.6, 1) infinite",
|
||||||
"pulse-dark": "pulse-dark 2.5s ease-in-out infinite",
|
"pulse-dark": "pulse-dark 2.5s ease-in-out infinite",
|
||||||
},
|
},
|
||||||
keyframes: {
|
keyframes: {
|
||||||
"pulse-border": {
|
"pulse-border": {
|
||||||
"0%, 100%": {
|
|
||||||
"--tw-border-opacity": "1",
|
|
||||||
},
|
|
||||||
"50%": {
|
"50%": {
|
||||||
"--tw-border-opacity": "0.5",
|
borderColor: "rgba(100, 100, 100)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"pulse-dark": {
|
"pulse-dark": {
|
||||||
|
|||||||
Reference in New Issue
Block a user