Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9196dff
Add comprehensive menu system with File, Edit, View, and Help menus t…
jonax1337 Jan 10, 2026
5ee426d
Add undo/redo tracking for entry and group operations
jonax1337 Jan 10, 2026
6160d59
Replace OpenRecentDialog with inline submenu in File menu for recent …
jonax1337 Jan 10, 2026
0bd8d6b
Add data-tauri-drag-region attributes to title bar elements and imple…
jonax1337 Jan 10, 2026
e4e03f2
Refactor database opening to use Tauri command instead of shell plugi…
jonax1337 Jan 10, 2026
835011a
Update components/OpenRecentDialog.tsx
jonax1337 Jan 10, 2026
a7734c2
Update components/main-app/hooks/useKeyboardShortcuts.ts
jonax1337 Jan 10, 2026
462f0e2
Update components/About.tsx
jonax1337 Jan 10, 2026
35cef5c
Initial plan
Copilot Jan 10, 2026
31ee6f0
Update components/group-tree/index.tsx
jonax1337 Jan 10, 2026
aedc1b8
Update components/main-app/index.tsx
jonax1337 Jan 10, 2026
ce9e9e9
Update components/main-app/index.tsx
jonax1337 Jan 10, 2026
d03d681
Update components/CustomTitleBar.tsx
jonax1337 Jan 10, 2026
991077c
Remove handlePaste function and related props based on review feedback
Copilot Jan 10, 2026
3fef9b4
Add conditional new instance handling for database creation when a da…
jonax1337 Jan 10, 2026
b07860f
Merge branch 'enhancement/title-bar-actions' of https://github.com/jo…
jonax1337 Jan 10, 2026
e71bbe4
Remove unused copy and paste handlers from MainApp component
jonax1337 Jan 10, 2026
68bebef
Add Copy icon import to CustomTitleBar component
jonax1337 Jan 10, 2026
24e09a2
Merge branch 'enhancement/title-bar-actions' into copilot/sub-pr-36
jonax1337 Jan 10, 2026
e42c475
Merge pull request #37 from jonax1337/copilot/sub-pr-36
jonax1337 Jan 10, 2026
ffeaf68
Initial plan
Copilot Jan 10, 2026
9f7f5fa
Add validation for recent database paths to ensure they exist and are…
Copilot Jan 10, 2026
629b288
Optimize file validation to read only header bytes instead of entire …
Copilot Jan 10, 2026
4ca6082
Move import to top of file and add clarification about timeout handling
Copilot Jan 10, 2026
1f68142
Move validate_database_file function to maintain logical grouping and…
jonax1337 Jan 10, 2026
ac1fcfd
Merge pull request #38 from jonax1337/copilot/sub-pr-36
jonax1337 Jan 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions app/about/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
"use client";

import { About } from "@/components/About";

export default function AboutPage() {
return <About />;
}
78 changes: 78 additions & 0 deletions components/About.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
"use client";

import { Button } from "@/components/ui/button";
import { ScrollArea } from "@/components/ui/scroll-area";
import { Github, Heart } from "lucide-react";
import { getCurrentWebviewWindow } from "@tauri-apps/api/webviewWindow";
import { CustomTitleBar } from "@/components/CustomTitleBar";
import { open } from "@tauri-apps/plugin-shell";

export function About() {
const handleClose = async () => {
const window = getCurrentWebviewWindow();
await window.close();
};

Comment thread
jonax1337 marked this conversation as resolved.
return (
<div className="flex h-screen w-full flex-col">
<CustomTitleBar
title="About"
hideMaximize={true}
/>

<ScrollArea className="flex-1">
<div className="flex flex-col items-center justify-center p-12 space-y-8">
{/* App Icon and Title */}
<div className="flex flex-col items-center space-y-4">
<img

Check warning on line 27 in components/About.tsx

View workflow job for this annotation

GitHub Actions / check (22.x)

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
src="/app-icon.png"
alt="App Icon"
className="h-24 w-24"
/>
<div className="text-center space-y-2">
<h1 className="text-3xl font-bold tracking-tight">Simple Password Manager</h1>
<p className="text-sm text-muted-foreground">Version 1.0.0</p>
</div>
</div>

{/* Description */}
<p className="text-center text-muted-foreground max-w-md leading-relaxed">
A secure and modern password manager built with the proven KeePass database format.
Keep your passwords safe with strong encryption.
</p>

{/* Links */}
<div className="flex flex-col gap-3 w-full max-w-xs">
<Button
variant="outline"
className="w-full justify-center gap-2"
onClick={() => open('https://github.com/jonax1337/Password-Manager')}
>
<Github className="h-4 w-4" />
View on GitHub
</Button>
</div>

{/* Tech Stack - Simple badges */}
<div className="flex flex-wrap justify-center gap-2 mt-4">
<span className="text-xs px-3 py-1 rounded-full bg-secondary text-secondary-foreground">Tauri</span>
<span className="text-xs px-3 py-1 rounded-full bg-secondary text-secondary-foreground">React</span>
<span className="text-xs px-3 py-1 rounded-full bg-secondary text-secondary-foreground">Next.js</span>
<span className="text-xs px-3 py-1 rounded-full bg-secondary text-secondary-foreground">Rust</span>
<span className="text-xs px-3 py-1 rounded-full bg-secondary text-secondary-foreground">TypeScript</span>
</div>

{/* Footer */}
<div className="pt-8 text-center space-y-1">
<p className="text-xs text-muted-foreground flex items-center justify-center gap-1">
Made with <Heart className="h-3 w-3 fill-current text-red-500" /> by Jonas Laux
</p>
<p className="text-xs text-muted-foreground">
Open Source • MIT License
</p>
</div>
</div>
</ScrollArea>
</div>
);
}
89 changes: 89 additions & 0 deletions components/AboutDialog.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
"use client";

import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { ExternalLink, Github } from "lucide-react";

interface AboutDialogProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}

export function AboutDialog({ open, onOpenChange }: AboutDialogProps) {
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="sm:max-w-[500px]">
<DialogHeader>
<div className="flex items-center gap-3 mb-2">
<img

Check warning on line 24 in components/AboutDialog.tsx

View workflow job for this annotation

GitHub Actions / check (22.x)

Using `<img>` could result in slower LCP and higher bandwidth. Consider using `<Image />` from `next/image` or a custom image loader to automatically optimize images. This may incur additional usage or cost from your provider. See: https://nextjs.org/docs/messages/no-img-element
src="/app-icon.png"
alt="App Icon"
className="h-12 w-12"
/>
<div>
<DialogTitle className="text-2xl">Simple Password Manager</DialogTitle>
<DialogDescription className="mt-1">
Version 1.0.0
</DialogDescription>
</div>
</div>
</DialogHeader>

<div className="space-y-4 py-4">
<p className="text-sm text-muted-foreground">
A secure, modern password manager built with KeePass database format (.kdbx).
Keep your passwords safe with strong encryption and a clean, intuitive interface.
</p>

<div className="space-y-2">
<h4 className="text-sm font-semibold">Features</h4>
<ul className="text-sm text-muted-foreground space-y-1 list-disc list-inside">
<li>KeePass 2.x database format support</li>
<li>Strong encryption (AES-256, ChaCha20)</li>
<li>Password generator with strength meter</li>
<li>Breach checking with Have I Been Pwned</li>
<li>Auto-lock and quick unlock</li>
<li>Cross-platform support</li>
</ul>
</div>

<div className="flex gap-2 pt-2">
<Button
variant="outline"
size="sm"
onClick={() => window.open('https://github.com/jonax1337/Password-Manager', '_blank')}
className="flex-1"
>
<Github className="h-4 w-4 mr-2" />
GitHub Repository
</Button>
<Button
variant="outline"
size="sm"
onClick={() => window.open('https://github.com/jonax1337/Password-Manager/issues', '_blank')}
className="flex-1"
>
<ExternalLink className="h-4 w-4 mr-2" />
Report Issue
</Button>
</div>

<div className="pt-2 border-t">
<p className="text-xs text-muted-foreground text-center">
Built with Tauri, React, and Next.js
</p>
<p className="text-xs text-muted-foreground text-center mt-1">
© 2026 Simple Password Manager. Open Source Software.
</p>
</div>
</div>
</DialogContent>
</Dialog>
);
}
36 changes: 25 additions & 11 deletions components/CreateDatabaseDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,24 @@ import {
DialogTitle,
} from "@/components/ui/dialog";
import { FolderOpen } from "lucide-react";
import { createDatabase } from "@/lib/tauri";
import { createDatabase, openDatabaseInNewInstance } from "@/lib/tauri";
import { useToast } from "@/components/ui/use-toast";
import { open } from "@tauri-apps/plugin-dialog";
import { saveLastDatabasePath } from "@/lib/storage";
import { saveLastDatabasePath, addRecentDatabase } from "@/lib/storage";
import { PasswordStrengthMeter } from "@/components/PasswordStrengthMeter";

interface CreateDatabaseDialogProps {
isOpen: boolean;
onClose: () => void;
onSuccess: () => void;
onSuccess: (openedInNewInstance: boolean) => void;
hasOpenDatabase?: boolean;
}

export function CreateDatabaseDialog({
isOpen,
onClose,
onSuccess,
hasOpenDatabase = false,
}: CreateDatabaseDialogProps) {
const [folderPath, setFolderPath] = useState("");
const [fileName, setFileName] = useState("");
Expand Down Expand Up @@ -92,20 +94,32 @@ export function CreateDatabaseDialog({
const fullPath = `${folderPath}\\${fileNameWithExt}`;

await createDatabase(fullPath, password);
saveLastDatabasePath(fullPath);
addRecentDatabase(fullPath);

toast({
title: "Success",
description: "Database created successfully",
variant: "success",
});
if (hasOpenDatabase) {
// Open in new instance if a database is already open
await openDatabaseInNewInstance(fullPath);
toast({
title: "Success",
description: "Database created and opened in new window",
variant: "success",
});
onSuccess(true);
} else {
// Open in current instance
saveLastDatabasePath(fullPath);
toast({
title: "Success",
description: "Database created successfully",
variant: "success",
});
onSuccess(false);
}

setFolderPath("");
setFileName("");
setPassword("");
setConfirmPassword("");

onSuccess();
onClose();
} catch (error: any) {
toast({
Expand Down
Loading
Loading