Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
f11bd59
refactor(desktop): restyle Account settings page
Kitenite May 4, 2026
2482984
refactor(desktop): polish Appearance settings page
Kitenite May 4, 2026
ec0c665
refactor(desktop): horizontally center settings content
Kitenite May 4, 2026
4c35764
refactor(desktop): polish Notifications settings page
Kitenite May 4, 2026
4c0fe8e
refactor(desktop): polish RingtoneCard selection state
Kitenite May 4, 2026
ccc7a06
fix(desktop): move ringtone play button back to corner
Kitenite May 4, 2026
54f5729
refactor(desktop): swap RingtoneCard play/check positions
Kitenite May 4, 2026
9a676d9
style(desktop): soften selected ringtone border to primary/40
Kitenite May 4, 2026
fd03a31
refactor(desktop): remove dead telemetry UI from General settings
Kitenite May 4, 2026
87ffc80
refactor(desktop): polish Keyboard shortcuts settings page
Kitenite May 4, 2026
9495ba8
refactor(desktop): polish Git & worktrees settings page
Kitenite May 4, 2026
6ebcf88
refactor(desktop): polish v2 Agents settings page
Kitenite May 4, 2026
f8c933c
refactor(desktop): tone down V2AgentCard styling
Kitenite May 4, 2026
a4fc71e
refactor(desktop): collapse V2 agent cards into a single bordered list
Kitenite May 4, 2026
d173004
style(desktop): drop bg-card from V2 agents list container
Kitenite May 4, 2026
89c764c
style(desktop): pad expanded V2 agent content from header
Kitenite May 4, 2026
8d3bf74
refactor(desktop): adopt 1Code horizontal-row pattern for V2 agent fi…
Kitenite May 4, 2026
44defaa
refactor(desktop): convert ringtone picker to bordered list rows
Kitenite May 4, 2026
c0db7b7
refactor(desktop): polish v2 Terminal settings page
Kitenite May 4, 2026
8e0f9ea
fix(desktop): put play button to the right of the check in ringtone rows
Kitenite May 4, 2026
2f652a1
refactor(desktop): collapse theme section into 1Code-style row + drop…
Kitenite May 4, 2026
848a3a5
refactor(desktop): unify theme section header into the bordered list
Kitenite May 4, 2026
e1be06e
style(desktop): drop divider lines between appearance sections
Kitenite May 4, 2026
7647bf5
refactor(desktop): redesign terminal presets list
Kitenite May 4, 2026
f4c810c
refactor(desktop): unify v2 presets into one card and quiet the rows
Kitenite May 4, 2026
bfe32fb
refactor(desktop): convert PresetEditorSheet to a centered Dialog
Kitenite May 4, 2026
835f177
style(desktop): widen PresetEditorDialog to max-w-4xl
Kitenite May 4, 2026
4bd4e9b
refactor(desktop): two-column layout for PresetEditorDialog body
Kitenite May 4, 2026
157c94b
chore(desktop): drop unused DialogDescription import in PresetEditorD…
Kitenite May 4, 2026
4cfb272
refactor(desktop): single column PresetEditorDialog with settings rows
Kitenite May 4, 2026
1e447a5
refactor(desktop): unify PresetEditorDialog rows on the V2AgentCard p…
Kitenite May 4, 2026
2df2c8d
style(desktop): drop the inner card border around PresetEditorDialog …
Kitenite May 4, 2026
b096442
style(desktop): drop row dividers in PresetEditorDialog
Kitenite May 4, 2026
9421c53
refactor(desktop): tighter row controls in PresetEditorDialog
Kitenite May 4, 2026
6b64621
revert(desktop): bring back two Switch rows for Auto-run
Kitenite May 4, 2026
4343edc
revert(desktop): bring back stacked radios for Applies to
Kitenite May 4, 2026
4ae0b10
style(desktop): restore segmented Applies to in an inline row
Kitenite May 4, 2026
6eb4a13
style(desktop): more breathing room between PresetEditorDialog rows
Kitenite May 4, 2026
602ec3e
refactor(desktop): drop bordered cards in Links settings
Kitenite May 4, 2026
fa6722e
refactor(desktop): redesign Models settings around the lighter sectio…
Kitenite May 4, 2026
d227690
refactor(desktop): horizontal ConfigRow + Active badge + ghost Sign out
Kitenite May 4, 2026
ea57854
Revert "refactor(desktop): horizontal ConfigRow + Active badge + ghos…
Kitenite May 4, 2026
c538f08
refactor(desktop): simpler Anthropic Advanced section in Models
Kitenite May 4, 2026
6294dfd
chore(desktop): drop unused hasAnthropicConfig in ModelsSettings
Kitenite May 4, 2026
3533b90
refactor(desktop): align Organization settings with the rest of settings
Kitenite May 4, 2026
5fe928e
style(desktop): drop dividers between Organization info rows
Kitenite May 4, 2026
3052ad8
style(desktop): drop explicit Change buttons in Organization rows
Kitenite May 4, 2026
368c986
chore(desktop): drop unused Button import in OrganizationSettings
Kitenite May 4, 2026
7542529
style(desktop): drop Change button on Account avatar; click avatar to…
Kitenite May 4, 2026
4243723
style(desktop): align project settings section heading with the rest
Kitenite May 4, 2026
38f9104
style(desktop): flatten integrations settings rows
Kitenite May 4, 2026
0de61e5
style(desktop): standardize billing settings page
Kitenite May 4, 2026
5b786f8
style(desktop): standardize API keys settings page
Kitenite May 4, 2026
78d3f1c
style(desktop): flatten billing plan + upgrade into borderless rows
Kitenite May 4, 2026
9ddc44a
style(desktop): give Pro and Enterprise plans a premium accent
Kitenite May 4, 2026
68cdb21
style(desktop): revert gradient billing accent to a monochrome pill
Kitenite May 4, 2026
1688dca
refactor(desktop): tighten v2 project settings sections
Kitenite May 4, 2026
9d6a23a
feat(desktop): rename / GitHub link / softer delete on v2 project set…
Kitenite May 4, 2026
ae993d9
style(desktop): bump section descriptions to text-sm + tighter copy
Kitenite May 4, 2026
a0bde86
style(desktop): tighter v2 project settings layout
Kitenite May 4, 2026
94d5c95
style(desktop): tighter agent detail layout to match v2 project
Kitenite May 4, 2026
087dc9b
style(desktop): align host settings with v2 project vocabulary
Kitenite May 4, 2026
6033eff
style(desktop): align daemon section heading with the rest of settings
Kitenite May 4, 2026
0b236b0
style(desktop): chevron-disclosure for daemon sessions; surface unava…
Kitenite May 4, 2026
6c376f0
style(desktop): hoist daemon action buttons into the section header
Kitenite May 4, 2026
1fcc0c3
fix(desktop): align daemon status row to text baseline
Kitenite May 4, 2026
6b07576
style(desktop): move daemon version next to heading; drop session-tab…
Kitenite May 4, 2026
ae3ef0e
other styles
Kitenite May 4, 2026
a8c9bb4
Merge origin/main into settings-cleanup-v1
Kitenite May 4, 2026
1bc1780
revert(desktop): drop last-visited settings page persistence
Kitenite May 4, 2026
3d552d3
Merge remote-tracking branch 'origin/main' into settings-cleanup-v1
Kitenite May 4, 2026
e2b2b0d
style(desktop): align v2 project icon field with settings vocabulary
Kitenite May 4, 2026
cc32565
fix(desktop): use real <button> for agent drag handle
Kitenite May 4, 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
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
export {
readLastMigrationRunAt,
useMigrateV1DataToV2,
V1_MIGRATION_LAST_RUN_AT_EVENT,
V1_MIGRATION_SUMMARY_EVENT,
} from "./useMigrateV1DataToV2";
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,28 @@ function getShownKey(organizationId: string): string {
return `v1-migration-modal-shown-${organizationId}`;
}

function getLastRunAtKey(organizationId: string): string {
return `v1-migration-last-run-at-${organizationId}`;
}

export const V1_MIGRATION_SUMMARY_EVENT = "v1-migration-summary-updated";
export const V1_MIGRATION_LAST_RUN_AT_EVENT = "v1-migration-last-run-at-updated";

export function readLastMigrationRunAt(organizationId: string): number | null {
const raw = localStorage.getItem(getLastRunAtKey(organizationId));
if (!raw) return null;
const value = Number(raw);
return Number.isFinite(value) ? value : null;
}

function persistLastRunAt(organizationId: string) {
localStorage.setItem(getLastRunAtKey(organizationId), String(Date.now()));
window.dispatchEvent(
new CustomEvent(V1_MIGRATION_LAST_RUN_AT_EVENT, {
detail: { organizationId },
}),
);
}

function persistSummary(organizationId: string, summary: MigrationSummary) {
localStorage.setItem(
Expand Down Expand Up @@ -136,6 +157,7 @@ export function useMigrateV1DataToV2({
hostService,
collections,
});
persistLastRunAt(organizationId);

// Persist summary unconditionally before any early-return paths — it's
// an idempotent side effect and must survive strict-mode effect
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import { Avatar } from "@superset/ui/atoms/Avatar";
import { Button } from "@superset/ui/button";
import { Card, CardContent } from "@superset/ui/card";
import { Input } from "@superset/ui/input";
import { toast } from "@superset/ui/sonner";
import { useLiveQuery } from "@tanstack/react-db";
import { useEffect, useState } from "react";
import { HiOutlinePencil } from "react-icons/hi2";
import { apiTrpcClient } from "renderer/lib/api-trpc-client";
import { authClient } from "renderer/lib/auth-client";
import { electronTrpc } from "renderer/lib/electron-trpc";
Expand Down Expand Up @@ -110,90 +108,88 @@ export function AccountSettings({ visibleItems }: AccountSettingsProps) {
</p>
</div>

<div className="space-y-8">
{showProfile && (
<div>
<h3 className="text-sm font-medium mb-4">Profile</h3>
{isLoading ? (
<ProfileSkeleton />
) : user ? (
<Card>
<CardContent>
<ul className="space-y-6">
<li className="flex items-center justify-between gap-8 pb-6 border-b border-border">
<div className="flex-1">
<div className="text-sm font-medium mb-1">Avatar</div>
<div className="text-xs text-muted-foreground">
Recommended size is 256x256px
</div>
</div>
<button
type="button"
onClick={handleAvatarUpload}
className="relative w-8 h-8 group cursor-pointer"
>
<Avatar
size="md"
fullName={user.name}
image={avatarPreview}
/>
<div className="absolute inset-0 bg-black/50 rounded-full opacity-0 group-hover:opacity-100 transition-opacity flex items-center justify-center">
<HiOutlinePencil className="h-4 w-4 text-white" />
</div>
</button>
</li>

<li className="flex items-center justify-between gap-8 pb-6 border-b border-border">
<div className="flex-1 text-sm font-medium">Name</div>
<div className="flex-1">
<Input
value={nameValue}
onChange={(e) => setNameValue(e.target.value)}
onBlur={handleNameBlur}
placeholder="Your name"
className="w-full"
/>
</div>
</li>

<li className="flex items-center justify-between gap-8">
<div className="flex-1 text-sm font-medium">Email</div>
<div className="flex-1">
<Input
value={user.email}
readOnly
disabled
className="w-full"
/>
</div>
</li>
</ul>
</CardContent>
</Card>
) : (
<Card>
<CardContent>
<p className="text-muted-foreground">
Unable to load user info
</p>
</CardContent>
</Card>
)}
</div>
)}
<div className="space-y-3">
{showProfile &&
(isLoading ? (
<ProfileSkeleton />
) : user ? (
<>
<SettingRow label="Avatar" hint="Recommended size 256×256.">
<button
type="button"
onClick={handleAvatarUpload}
disabled={selectImageMutation.isPending}
className="rounded-full transition-opacity hover:opacity-80 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-100"
aria-label="Change avatar"
>
<Avatar
size="xl"
fullName={user.name}
image={avatarPreview}
/>
</button>
</SettingRow>

<SettingRow label="Name">
<Input
value={nameValue}
onChange={(e) => setNameValue(e.target.value)}
onBlur={handleNameBlur}
placeholder="Your name"
className="w-80"
/>
</SettingRow>

<SettingRow label="Email">
<Input
value={user.email}
readOnly
className="w-80 opacity-60"
/>
</SettingRow>
Comment on lines +143 to +149
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Email input has no accessible name — WCAG 1.3.1 Level A gap.

The SettingRow helper uses a plain <div> for the label with no htmlFor prop, and the Input elements have no id to form a programmatic association. The Email field is the most critical — it has neither a placeholder nor an aria-label, so assistive technologies have nothing to announce as the control's label. The Name input is partially covered by its placeholder, but a real <label> association is still required per WCAG.

OrganizationSettings.tsx's SettingsRow already solves this correctly with <Label htmlFor={htmlFor}> + matching id on each Input. Aligning SettingRow here to the same pattern fixes both the accessibility gap and the inconsistency.

🛡️ Proposed fix
-interface SettingRowProps {
+interface SettingRowProps {
   label: string;
   hint?: string;
+  htmlFor?: string;
   children: React.ReactNode;
 }

-function SettingRow({ label, hint, children }: SettingRowProps) {
+function SettingRow({ label, hint, htmlFor, children }: SettingRowProps) {
   return (
     <div className="flex items-center justify-between gap-8">
       <div className="flex-1 min-w-0">
-        <div className="text-sm font-medium">{label}</div>
+        <Label htmlFor={htmlFor} className="text-sm font-medium">{label}</Label>
         {hint && (
           <div className="text-xs text-muted-foreground mt-0.5">{hint}</div>
         )}
       </div>
       <div className="flex-shrink-0">{children}</div>
     </div>
   );
 }

Then add id/htmlFor at each call-site:

-<SettingRow label="Name">
+<SettingRow label="Name" htmlFor="account-name">
   <Input
+    id="account-name"
     value={nameValue}
     ...
   />
 </SettingRow>

-<SettingRow label="Email">
+<SettingRow label="Email" htmlFor="account-email">
   <Input
+    id="account-email"
     value={user.email}
     readOnly
     ...
   />
 </SettingRow>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/settings/account/components/AccountSettings/AccountSettings.tsx`
around lines 143 - 149, The Email input lacks a programmatic label association;
update SettingRow to render a proper <Label htmlFor={htmlFor}> (mirroring
OrganizationSettings' SettingsRow) and ensure each Input in AccountSettings
(e.g., the Email and Name inputs inside AccountSettings.tsx) receives a matching
id prop (unique per field) and the SettingRow call sites pass that same htmlFor
value; also remove reliance on placeholder for labeling and prefer the explicit
label/id pairing so assistive tech can announce the controls.

</>
) : (
<p className="text-sm text-muted-foreground">
Unable to load user info
</p>
))}

{showSignOut && (
<div className={showProfile ? "pt-6 border-t" : ""}>
<h3 className="text-sm font-medium mb-2">Sign Out</h3>
<p className="text-sm text-muted-foreground mb-4">
Sign out of your Superset account on this device.
</p>
<Button variant="outline" onClick={() => signOutMutation.mutate()}>
Sign Out
</Button>
<div className={showProfile ? "pt-5" : undefined}>
<SettingRow
label="Sign out of this device"
hint="You'll need to sign in again to use Superset on this device."
>
<Button
variant="outline"
onClick={() => signOutMutation.mutate()}
>
Sign out
</Button>
</SettingRow>
</div>
)}
</div>
</div>
);
}

interface SettingRowProps {
label: string;
hint?: string;
children: React.ReactNode;
}

function SettingRow({ label, hint, children }: SettingRowProps) {
return (
<div className="flex items-center justify-between gap-8">
<div className="flex-1 min-w-0">
<div className="text-sm font-medium">{label}</div>
{hint && (
<div className="text-xs text-muted-foreground mt-0.5">{hint}</div>
)}
</div>
<div className="flex-shrink-0">{children}</div>
</div>
);
}
Original file line number Diff line number Diff line change
@@ -1,28 +1,26 @@
import { Card, CardContent } from "@superset/ui/card";
import { Skeleton } from "@superset/ui/skeleton";

export function ProfileSkeleton() {
return (
<Card>
<CardContent>
<ul className="space-y-6">
<li className="flex items-center justify-between gap-8 pb-6 border-b border-border">
<div className="flex-1">
<Skeleton className="h-4 w-16 mb-2" />
<Skeleton className="h-3 w-40" />
</div>
<Skeleton className="h-8 w-8 rounded-full" />
</li>
<li className="flex items-center justify-between gap-8 pb-6 border-b border-border">
<Skeleton className="h-4 w-12" />
<Skeleton className="h-10 flex-1" />
</li>
<li className="flex items-center justify-between gap-8">
<Skeleton className="h-4 w-12" />
<Skeleton className="h-10 flex-1" />
</li>
</ul>
</CardContent>
</Card>
<div className="space-y-3">
<div className="flex items-center justify-between gap-8">
<div className="flex-1">
<Skeleton className="h-4 w-16 mb-2" />
<Skeleton className="h-3 w-40" />
</div>
<div className="flex items-center gap-3">
<Skeleton className="size-12 rounded-full" />
<Skeleton className="h-8 w-20" />
</div>
Comment on lines +11 to +14
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Skeleton has a phantom rectangular placeholder that doesn't correspond to the rendered Avatar row.

The actual Avatar SettingRow in AccountSettings.tsx renders only a circular avatar button on the right side; there is no adjacent rectangular element. The h-8 w-20 skeleton (Line 13) appears to be a leftover from the previous design that had a separate "Change" button next to the avatar.

🔧 Proposed fix
 <div className="flex items-center gap-3">
   <Skeleton className="size-12 rounded-full" />
-  <Skeleton className="h-8 w-20" />
 </div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div className="flex items-center gap-3">
<Skeleton className="size-12 rounded-full" />
<Skeleton className="h-8 w-20" />
</div>
<div className="flex items-center gap-3">
<Skeleton className="size-12 rounded-full" />
</div>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@apps/desktop/src/renderer/routes/_authenticated/settings/account/components/AccountSettings/components/ProfileSkeleton/ProfileSkeleton.tsx`
around lines 11 - 14, ProfileSkeleton renders a phantom rectangular placeholder
that doesn't exist in the real Avatar SettingRow; in the ProfileSkeleton
component remove the extra Skeleton with className "h-8 w-20" (the rectangular
placeholder) so only the circular Skeleton remains and the markup matches
AccountSettings' Avatar row; reference the ProfileSkeleton component and ensure
the remaining Skeleton keeps its "size-12 rounded-full" classes and alignment
consistent with SettingRow in AccountSettings.tsx.

</div>
<div className="flex items-center justify-between gap-8">
<Skeleton className="h-4 w-12" />
<Skeleton className="h-9 w-80" />
</div>
<div className="flex items-center justify-between gap-8">
<Skeleton className="h-4 w-12" />
<Skeleton className="h-9 w-80" />
</div>
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ function V1AgentsSettings({ visibleItems }: AgentsSettingsProps) {
);

return (
<div className="p-6 max-w-5xl w-full">
<div className="p-6 max-w-5xl w-full mx-auto">
<div className="mb-8">
<h2 className="text-xl font-semibold">Agents</h2>
<p className="text-sm text-muted-foreground mt-1">
Expand Down
Loading
Loading