diff --git a/aimenet-web/app/cards/page.tsx b/aimenet-web/app/cards/page.tsx
index b09a022..8350aca 100644
--- a/aimenet-web/app/cards/page.tsx
+++ b/aimenet-web/app/cards/page.tsx
@@ -17,25 +17,24 @@ import {
ContextMenuTrigger
} from "@/components/ui/context-menu";
import {AimeCardEntry} from "@/components/aime-card";
+import {IncognitoStorageWarning} from "@/components/incognito-warning";
function CardAddButton() {
- return (
+ return (<>
+
- );
+ >);
}
function CardList(props: { cards: AimeCard[] | undefined }) {
- if (!props.cards) {
- return ();
- }
-
- if (!props.cards.length) {
+ if (!props.cards?.length) {
return (<>
+
No cards found
@@ -76,7 +75,7 @@ export default function CardManagerPage() {
-
+ {cards ? : }
diff --git a/aimenet-web/components/incognito-warning.tsx b/aimenet-web/components/incognito-warning.tsx
new file mode 100644
index 0000000..a58e602
--- /dev/null
+++ b/aimenet-web/components/incognito-warning.tsx
@@ -0,0 +1,32 @@
+import {ServerOff} from "lucide-react";
+import detectIncognito from "detectincognitojs";
+import React, {useEffect, useState} from "react";
+import {Alert, AlertDescription, AlertTitle} from "@/components/ui/alert";
+
+export function IncognitoStorageWarning() {
+ const [showWarning, setShowWarning] = useState(false);
+
+ useEffect(() => {
+ const check = async () => {
+ try {
+ const {isPrivate} = await detectIncognito();
+ setShowWarning(isPrivate);
+ } catch {
+ setShowWarning(false);
+ }
+ };
+
+ check().catch(console.error);
+ }, []);
+
+ return (showWarning && (
+
+
+ Private Session Detected
+
+ You're currently using a private browsing session. When you close the tab, all data (including
+ cards) will be lost. Switch to a regular browsing session to ensure your data is saved.
+
+
+ ));
+}
\ No newline at end of file
diff --git a/aimenet-web/package-lock.json b/aimenet-web/package-lock.json
index 273de41..74efe3f 100644
--- a/aimenet-web/package-lock.json
+++ b/aimenet-web/package-lock.json
@@ -16,8 +16,10 @@
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
+ "@uidotdev/usehooks": "^2.4.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
+ "detectincognitojs": "^1.3.5",
"dexie": "^4.0.8",
"dexie-react-hooks": "^1.1.7",
"lucide-react": "^0.424.0",
@@ -1389,6 +1391,19 @@
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@uidotdev/usehooks": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@uidotdev/usehooks/-/usehooks-2.4.1.tgz",
+ "integrity": "sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "react": ">=18.0.0",
+ "react-dom": ">=18.0.0"
+ }
+ },
"node_modules/@ungap/structured-clone": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz",
@@ -2152,6 +2167,12 @@
"integrity": "sha512-ypdmJU/TbBby2Dxibuv7ZLW3Bs1QEmM7nHjEANfohJLvE0XVujisn1qPJcZxg+qDucsr+bP6fLD1rPS3AhJ7EQ==",
"license": "MIT"
},
+ "node_modules/detectincognitojs": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/detectincognitojs/-/detectincognitojs-1.3.5.tgz",
+ "integrity": "sha512-jX5vs3toLR8aEtc5ChGC3xt0/0N+g6HpIWskcf+U1pYp4kiCdUABZLzQlkf2BVsx/Abgy9Eh9G3VV6P7p3iFiQ==",
+ "license": "MIT"
+ },
"node_modules/dexie": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/dexie/-/dexie-4.0.8.tgz",
diff --git a/aimenet-web/package.json b/aimenet-web/package.json
index c46e495..012ea7f 100644
--- a/aimenet-web/package.json
+++ b/aimenet-web/package.json
@@ -17,8 +17,10 @@
"@radix-ui/react-separator": "^1.1.0",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-toast": "^1.2.1",
+ "@uidotdev/usehooks": "^2.4.1",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
+ "detectincognitojs": "^1.3.5",
"dexie": "^4.0.8",
"dexie-react-hooks": "^1.1.7",
"lucide-react": "^0.424.0",