Add app update detection and multi-folder project support
All checks were successful
Build App / build-linux (push) Successful in 2m54s
Build App / build-windows (push) Successful in 4m18s
Build Container / build-container (push) Successful in 1m30s

Feature 1 - Update Detection: Query Gitea releases API on startup (3s
delay) and every 24h, compare patch versions by platform, show pulsing
"Update" button in TopBar with dialog for release notes/downloads.
Settings: auto-check toggle, manual check, dismiss per-version.

Feature 2 - Multi-Folder Projects: Replace single `path` with
`paths: Vec<ProjectPath>` (host_path + mount_name). Each folder mounts
to `/workspace/{mount_name}`. Auto-migrate old single-path JSON on load.
Container recreation via paths-fingerprint label. AddProjectDialog and
ProjectCard support add/remove/edit of multiple folders.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-28 21:18:33 +00:00
parent 854f59a95a
commit 7e1cc92aa4
23 changed files with 1163 additions and 98 deletions

View File

@@ -3,10 +3,13 @@ import ApiKeyInput from "./ApiKeyInput";
import DockerSettings from "./DockerSettings";
import AwsSettings from "./AwsSettings";
import { useSettings } from "../../hooks/useSettings";
import { useUpdates } from "../../hooks/useUpdates";
export default function SettingsPanel() {
const { appSettings, saveSettings } = useSettings();
const { appVersion, checkForUpdates } = useUpdates();
const [globalInstructions, setGlobalInstructions] = useState(appSettings?.global_claude_instructions ?? "");
const [checkingUpdates, setCheckingUpdates] = useState(false);
// Sync local state when appSettings change
useEffect(() => {
@@ -18,6 +21,20 @@ export default function SettingsPanel() {
await saveSettings({ ...appSettings, global_claude_instructions: globalInstructions || null });
};
const handleCheckNow = async () => {
setCheckingUpdates(true);
try {
await checkForUpdates();
} finally {
setCheckingUpdates(false);
}
};
const handleAutoCheckToggle = async () => {
if (!appSettings) return;
await saveSettings({ ...appSettings, auto_check_updates: !appSettings.auto_check_updates });
};
return (
<div className="p-4 space-y-6">
<h2 className="text-xs font-semibold uppercase text-[var(--text-secondary)]">
@@ -40,6 +57,38 @@ export default function SettingsPanel() {
className="w-full px-2 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded focus:outline-none focus:border-[var(--accent)] resize-y font-mono"
/>
</div>
{/* Updates section */}
<div>
<label className="block text-sm font-medium mb-2">Updates</label>
<div className="space-y-2">
{appVersion && (
<p className="text-xs text-[var(--text-secondary)]">
Current version: <span className="text-[var(--text-primary)] font-mono">{appVersion}</span>
</p>
)}
<div className="flex items-center gap-2">
<label className="text-xs text-[var(--text-secondary)]">Auto-check for updates</label>
<button
onClick={handleAutoCheckToggle}
className={`px-2 py-0.5 text-xs rounded transition-colors ${
appSettings?.auto_check_updates !== false
? "bg-[var(--success)] text-white"
: "bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-secondary)]"
}`}
>
{appSettings?.auto_check_updates !== false ? "ON" : "OFF"}
</button>
</div>
<button
onClick={handleCheckNow}
disabled={checkingUpdates}
className="px-3 py-1.5 text-xs bg-[var(--bg-primary)] border border-[var(--border-color)] rounded hover:bg-[var(--border-color)] disabled:opacity-50 transition-colors"
>
{checkingUpdates ? "Checking..." : "Check now"}
</button>
</div>
</div>
</div>
);
}