feat: ephemeral profiles

This commit is contained in:
zhom
2026-02-22 10:17:25 +04:00
parent 2e193987df
commit 3732d3a6e1
21 changed files with 354 additions and 33 deletions
+2
View File
@@ -494,6 +494,7 @@ export default function Home() {
camoufoxConfig?: CamoufoxConfig;
wayfernConfig?: WayfernConfig;
groupId?: string;
ephemeral?: boolean;
}) => {
try {
await invoke<BrowserProfile>("create_browser_profile_new", {
@@ -508,6 +509,7 @@ export default function Home() {
groupId:
profileData.groupId ||
(selectedGroupId !== "default" ? selectedGroupId : undefined),
ephemeral: profileData.ephemeral,
});
// No need to manually reload - useProfileEvents will handle the update
+28
View File
@@ -8,6 +8,7 @@ import { LoadingButton } from "@/components/loading-button";
import { ProxyFormDialog } from "@/components/proxy-form-dialog";
import { SharedCamoufoxConfigForm } from "@/components/shared-camoufox-config-form";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import {
Dialog,
DialogContent,
@@ -75,6 +76,7 @@ interface CreateProfileDialogProps {
camoufoxConfig?: CamoufoxConfig;
wayfernConfig?: WayfernConfig;
groupId?: string;
ephemeral?: boolean;
}) => Promise<void>;
selectedGroupId?: string;
crossOsUnlocked?: boolean;
@@ -164,6 +166,7 @@ export function CreateProfileDialog({
const { vpnConfigs } = useVpnEvents();
const [showProxyForm, setShowProxyForm] = useState(false);
const [isCreating, setIsCreating] = useState(false);
const [ephemeral, setEphemeral] = useState(false);
const [releaseTypes, setReleaseTypes] = useState<BrowserReleaseTypes>();
const [isLoadingReleaseTypes, setIsLoadingReleaseTypes] = useState(false);
const [releaseTypesError, setReleaseTypesError] = useState<string | null>(
@@ -382,6 +385,7 @@ export function CreateProfileDialog({
wayfernConfig: finalWayfernConfig,
groupId:
selectedGroupId !== "default" ? selectedGroupId : undefined,
ephemeral,
});
} else {
// Default to Camoufox
@@ -405,6 +409,7 @@ export function CreateProfileDialog({
camoufoxConfig: finalCamoufoxConfig,
groupId:
selectedGroupId !== "default" ? selectedGroupId : undefined,
ephemeral,
});
}
} else {
@@ -459,6 +464,7 @@ export function CreateProfileDialog({
setWayfernConfig({
os: getCurrentOS() as WayfernOS, // Reset to current OS
});
setEphemeral(false);
onClose();
};
@@ -660,6 +666,28 @@ export function CreateProfileDialog({
/>
</div>
{/* Ephemeral Toggle */}
<div className="flex items-center gap-2">
<Checkbox
id="ephemeral"
checked={ephemeral}
onCheckedChange={(checked) =>
setEphemeral(checked === true)
}
/>
<div className="flex flex-col">
<Label
htmlFor="ephemeral"
className="cursor-pointer"
>
Ephemeral
</Label>
<span className="text-xs text-muted-foreground">
Browser data is deleted when closed
</span>
</div>
</div>
{selectedBrowser === "wayfern" ? (
// Wayfern Configuration
<div className="space-y-6">
+21 -9
View File
@@ -1940,7 +1940,14 @@ export function ProfilesDataTable({
}
}}
>
{display}
<span className="flex items-center gap-1">
{display}
{profile.ephemeral && (
<span className="px-1 py-0.5 text-[10px] leading-none rounded bg-muted text-muted-foreground font-medium">
Ephemeral
</span>
)}
</span>
</button>
);
},
@@ -2397,6 +2404,7 @@ export function ProfilesDataTable({
)}
{(profile.browser === "camoufox" ||
profile.browser === "wayfern") &&
!profile.ephemeral &&
meta.onCopyCookiesToProfile && (
<DropdownMenuItem
onClick={() => {
@@ -2414,6 +2422,7 @@ export function ProfilesDataTable({
)}
{(profile.browser === "camoufox" ||
profile.browser === "wayfern") &&
!profile.ephemeral &&
meta.onImportCookies && (
<DropdownMenuItem
onClick={() => {
@@ -2431,6 +2440,7 @@ export function ProfilesDataTable({
)}
{(profile.browser === "camoufox" ||
profile.browser === "wayfern") &&
!profile.ephemeral &&
meta.onExportCookies && (
<DropdownMenuItem
onClick={() => {
@@ -2446,14 +2456,16 @@ export function ProfilesDataTable({
</span>
</DropdownMenuItem>
)}
<DropdownMenuItem
onClick={() => {
meta.onCloneProfile?.(profile);
}}
disabled={isDisabled}
>
Clone Profile
</DropdownMenuItem>
{!profile.ephemeral && (
<DropdownMenuItem
onClick={() => {
meta.onCloneProfile?.(profile);
}}
disabled={isDisabled}
>
Clone Profile
</DropdownMenuItem>
)}
<DropdownMenuItem
onClick={() => {
setProfileToDelete(profile);
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "Copy Cookies",
"configure": "Configure",
"clone": "Clone Profile"
}
},
"ephemeral": "Ephemeral",
"ephemeralDescription": "Browser data is deleted when closed",
"ephemeralBadge": "Ephemeral"
},
"createProfile": {
"title": "Create New Profile",
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "Copiar Cookies",
"configure": "Configurar",
"clone": "Clonar perfil"
}
},
"ephemeral": "Efímero",
"ephemeralDescription": "Los datos del navegador se eliminan al cerrarlo",
"ephemeralBadge": "Efímero"
},
"createProfile": {
"title": "Crear Nuevo Perfil",
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "Copier les cookies",
"configure": "Configurer",
"clone": "Cloner le profil"
}
},
"ephemeral": "Éphémère",
"ephemeralDescription": "Les données du navigateur sont supprimées à la fermeture",
"ephemeralBadge": "Éphémère"
},
"createProfile": {
"title": "Créer un nouveau profil",
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "Cookieをコピー",
"configure": "設定",
"clone": "プロファイルを複製"
}
},
"ephemeral": "一時的",
"ephemeralDescription": "ブラウザを閉じるとデータが削除されます",
"ephemeralBadge": "一時的"
},
"createProfile": {
"title": "新しいプロファイルを作成",
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "Copiar Cookies",
"configure": "Configurar",
"clone": "Clonar perfil"
}
},
"ephemeral": "Efêmero",
"ephemeralDescription": "Os dados do navegador são excluídos ao fechar",
"ephemeralBadge": "Efêmero"
},
"createProfile": {
"title": "Criar Novo Perfil",
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "Копировать Cookie",
"configure": "Настроить",
"clone": "Клонировать профиль"
}
},
"ephemeral": "Временный",
"ephemeralDescription": "Данные браузера удаляются при закрытии",
"ephemeralBadge": "Временный"
},
"createProfile": {
"title": "Создать новый профиль",
+4 -1
View File
@@ -158,7 +158,10 @@
"copyCookies": "复制 Cookies",
"configure": "配置",
"clone": "克隆配置文件"
}
},
"ephemeral": "临时",
"ephemeralDescription": "关闭浏览器时数据将被删除",
"ephemeralBadge": "临时"
},
"createProfile": {
"title": "创建新配置文件",
+1
View File
@@ -29,6 +29,7 @@ export interface BrowserProfile {
sync_enabled?: boolean; // Whether sync is enabled for this profile
last_sync?: number; // Timestamp of last successful sync (epoch seconds)
host_os?: string; // OS where profile was created ("macos", "windows", "linux")
ephemeral?: boolean;
}
export type SyncStatus = "Disabled" | "Syncing" | "Synced" | "Error";