diff --git a/src/renderer/src/components/security-settings-dialog.tsx b/src/renderer/src/components/security-settings-dialog.tsx index e43c820..46e897a 100644 --- a/src/renderer/src/components/security-settings-dialog.tsx +++ b/src/renderer/src/components/security-settings-dialog.tsx @@ -1,15 +1,22 @@ -import { type ReactNode } from 'react' +import { useState, type ReactNode } from 'react' -import { CheckIcon } from 'lucide-react' -import { toast } from 'sonner' +import { LockIcon } from 'lucide-react' import { useShallow } from 'zustand/react/shallow' -import { notvex } from '@/lib/ipc' import { usePrefsStore } from '@/store/prefs.store' +import { ChangePasswordDialog } from './change-password-dialog' import { KeyFileSetting } from './settings/KeyFileSetting' import { Button } from './ui/button' import { Checkbox } from './ui/checkbox' import { Dialog, DialogContent, DialogHeader, DialogTitle } from './ui/dialog' +import { + Select, + SelectContent, + SelectGroup, + SelectItem, + SelectTrigger, + SelectValue +} from './ui/select' import { Separator } from './ui/separator' interface Props { @@ -17,20 +24,22 @@ interface Props { onClose: () => void } -async function handleOpenBackupsFolder(): Promise { - const res = await notvex.vault.openBackupsFolder() - if (!res.success) toast.error(res.error) -} - export function SecuritySettingsDialog({ open, onClose }: Props): ReactNode { const { setPref } = usePrefsStore() - const { lockOnMinimize, allowScreenCapture } = usePrefsStore( + const { autoLockMinutes, lockOnMinimize, allowScreenCapture } = usePrefsStore( useShallow((s) => ({ + autoLockMinutes: s.autoLockMinutes, lockOnMinimize: s.lockOnMinimize, allowScreenCapture: s.allowScreenCapture })) ) + const [changePasswordOpen, setChangePasswordOpen] = useState(false) + + const handleAutoLockChange = (minutes: string): void => { + void setPref('autoLockMinutes', Number(minutes)) + } + const handleLockOnMinimize = (checked: boolean): void => { void setPref('lockOnMinimize', checked) } @@ -58,6 +67,26 @@ export function SecuritySettingsDialog({ open, onClose }: Props): ReactNode { Auto-lock

+ + + + handleLockOnMinimize(v === true)} /> - - - - - - - - @@ -106,50 +119,51 @@ export function SecuritySettingsDialog({ open, onClose }: Props): ReactNode { - {/* ── Key file ── */} - - - - - {/* ── Backups ── */} + {/* ── Authentication ── */}

- Backups -

-

- Plain point-in-time copies of your vault file, created automatically before - format-changing updates. Safe to delete — not a restore feature, just browsable via - your file explorer. + Authentication

- + + + +
- {/* ── Unlock attempts ── */} + {/* ── Always-on protections ── */}

- Unlock attempts + Always-on protections +

+

+ Notvex always locks the vault when the system sleeps or the screen locks, and applies + a progressive delay after repeated failed unlock attempts. These protections are built + in and cannot be turned off.

- - - -
+ + setChangePasswordOpen(false)} + /> ) } @@ -157,29 +171,19 @@ export function SecuritySettingsDialog({ open, onClose }: Props): ReactNode { function SettingRow({ label, description, - readonly = false, children }: { label: string description?: string - readonly?: boolean children: React.ReactNode }): ReactNode { return (
-

{label}

+

{label}

{description &&

{description}

}
{children}
) } - -function ReadonlyCheck(): ReactNode { - return ( -
- -
- ) -} diff --git a/src/renderer/src/components/settings/KeyFileSetting.tsx b/src/renderer/src/components/settings/KeyFileSetting.tsx index 2df4fcc..2dec555 100644 --- a/src/renderer/src/components/settings/KeyFileSetting.tsx +++ b/src/renderer/src/components/settings/KeyFileSetting.tsx @@ -128,14 +128,13 @@ export function KeyFileSetting(): ReactNode { return (
-

- Key file -

- -

- A key file adds a second factor to unlock your vault. You need both your password and the - key file to access your notes. If you lose the key file, access is permanently lost. -

+
+

Key file

+

+ A key file adds a second factor to unlock your vault. You need both your password and the + key file to access your notes. If you lose the key file, access is permanently lost. +

+
{keyFileStep === 'idle' && ( <> diff --git a/src/renderer/src/components/sidebar.tsx b/src/renderer/src/components/sidebar.tsx index e6a2a56..6bd45f1 100644 --- a/src/renderer/src/components/sidebar.tsx +++ b/src/renderer/src/components/sidebar.tsx @@ -26,12 +26,10 @@ import { useCreateNote } from '@/hooks/use-create-note' import { useIsDev } from '@/hooks/use-is-dev' import { notvex } from '@/lib/ipc' import { cn, truncatePath } from '@/lib/utils' -import { usePrefsStore } from '@/store/prefs.store' import { useUiStore } from '@/store/ui.store' import { useVaultStore } from '@/store/vault.store' import type { Tag } from '@shared/types' import { AppLogo } from './AppLogo' -import { ChangePasswordDialog } from './change-password-dialog' import { AppVersionDialog } from './dialogs/AppVersionDialog' import { SecuritySettingsDialog } from './security-settings-dialog' import { TagCreateModal } from './tags/TagCreateModal' @@ -49,14 +47,6 @@ import { } from './ui/dropdown-menu' import { InputGroup, InputGroupAddon, InputGroupButton, InputGroupInput } from './ui/input-group' import { Kbd } from './ui/kbd' -import { - Select, - SelectContent, - SelectGroup, - SelectItem, - SelectTrigger, - SelectValue -} from './ui/select' import { Sidebar as ShadcnSidebar, SidebarContent, @@ -84,6 +74,11 @@ const handleSaveCopy = async (): Promise => { if (result.data) toast.success('Copy saved successfully') } +const handleOpenBackupsFolder = async (): Promise => { + const res = await notvex.vault.openBackupsFolder() + if (!res.success) toast.error(res.error) +} + export function Sidebar(): React.ReactNode { const { loadTags, loadTagCounts, setStatus, setActiveNoteId, setNotes } = useVaultStore() const { tags, tagCounts, notes, currentVaultPath } = useVaultStore( @@ -107,9 +102,6 @@ export function Sidebar(): React.ReactNode { })) ) - const { setPref } = usePrefsStore() - const autoLockMinutes = usePrefsStore((s) => s.autoLockMinutes) - const handleNewNote = useCreateNote() const { isCopied, copyToClipboard } = useCopyToClipboard() const isDev = useIsDev() @@ -117,7 +109,6 @@ export function Sidebar(): React.ReactNode { const searchContainerRef = useRef(null) const [appVersionOpen, setAppVersionOpen] = useState(false) const [settingsPopoverOpen, setSettingsPopoverOpen] = useState(false) - const [changePasswordOpen, setChangePasswordOpen] = useState(false) const [securitySettingsOpen, setSecuritySettingsOpen] = useState(false) const [createModalOpen, setCreateModalOpen] = useState(false) const [createModalKey, setCreateModalKey] = useState(0) @@ -141,10 +132,6 @@ export function Sidebar(): React.ReactNode { setNotes([]) } - const handleAutoLockChange = (minutes: string): void => { - void setPref('autoLockMinutes', Number(minutes)) - } - const allNotesCount = notes.filter((n) => !n.isTrashed).length const pinnedCount = notes.filter((n) => n.isPinned && !n.isTrashed).length const trashCount = notes.filter((n) => n.isTrashed).length @@ -184,28 +171,8 @@ export function Sidebar(): React.ReactNode { - - Auto-lock - e.preventDefault()}> - - - {currentVaultPath && ( <> - Vault Location @@ -221,29 +188,17 @@ export function Sidebar(): React.ReactNode { - + Save a vault copy as... + + Open backups folder + + )} - - Security - { - setChangePasswordOpen(true) - setSettingsPopoverOpen(false) - }} - > - Change password - setAppVersionOpen(false)} /> - setChangePasswordOpen(false)} - /> setSecuritySettingsOpen(false)}