mirror of
https://github.com/arsvendg/Stirling-PDF.git
synced 2026-07-15 11:00:47 +02:00
feat: add Agents UI to proprietary right sidebar (#6454)
Update UI to include agents Run `task dev:all` to test
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
* Generates and persists a unique UUID in localStorage for WAU tracking
|
||||
*/
|
||||
|
||||
import { generateId } from "@app/utils/generateId";
|
||||
|
||||
const BROWSER_ID_KEY = "stirling_browser_id";
|
||||
|
||||
/**
|
||||
@@ -28,19 +30,6 @@ export function getBrowserId(): string {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a UUID v4
|
||||
*/
|
||||
function generateUUID(): string {
|
||||
// Use crypto.randomUUID if available (modern browsers)
|
||||
if (typeof crypto !== "undefined" && crypto.randomUUID) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
// Fallback to manual UUID generation
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||||
const r = (Math.random() * 16) | 0;
|
||||
const v = c === "x" ? r : (r & 0x3) | 0x8;
|
||||
return v.toString(16);
|
||||
});
|
||||
return generateId();
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { generateId } from "@app/utils/generateId";
|
||||
|
||||
export interface BookmarkPayload {
|
||||
title: string;
|
||||
pageNumber: number;
|
||||
@@ -12,13 +14,7 @@ export interface BookmarkNode {
|
||||
expanded: boolean;
|
||||
}
|
||||
|
||||
const createBookmarkId = () => {
|
||||
if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
|
||||
return `bookmark-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
||||
};
|
||||
const createBookmarkId = () => generateId();
|
||||
|
||||
export const createBookmarkNode = (
|
||||
bookmark?: Partial<BookmarkNode>,
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
export function generateId(): string {
|
||||
if (
|
||||
typeof crypto !== "undefined" &&
|
||||
typeof crypto.randomUUID === "function"
|
||||
) {
|
||||
return crypto.randomUUID();
|
||||
}
|
||||
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
|
||||
const r = (Math.random() * 16) | 0;
|
||||
return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import { flushSync } from "react-dom";
|
||||
|
||||
type ViewTransitionDoc = Document & {
|
||||
startViewTransition?: (cb: () => void) => { finished: Promise<void> };
|
||||
};
|
||||
|
||||
/**
|
||||
* Run a state update inside a View Transition so the browser cross-fades
|
||||
* (and morphs any elements sharing a {@code view-transition-name}) between
|
||||
* the before/after DOMs.
|
||||
*
|
||||
* Falls back to a plain synchronous update when the API is unavailable
|
||||
* (Firefox <130, JSDOM, motion-reduced preference).
|
||||
*/
|
||||
export function withViewTransition(update: () => void): Promise<void> {
|
||||
if (typeof document === "undefined") {
|
||||
update();
|
||||
return Promise.resolve();
|
||||
}
|
||||
const doc = document as ViewTransitionDoc;
|
||||
if (doc.startViewTransition) {
|
||||
return doc.startViewTransition(() => flushSync(update)).finished;
|
||||
}
|
||||
update();
|
||||
return Promise.resolve();
|
||||
}
|
||||
Reference in New Issue
Block a user