Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions apps/desktop/src/settings/DesktopClientSettings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ const clientSettings: ClientSettings = {
browserDefaultZoomFactor: 1.25,
browserDefaultAppearance: "dark",
browserAutoShowFloatingPreview: false,
compactLegacySidebarStatuses: false,
confirmQuit: true,
confirmThreadArchive: true,
confirmThreadDelete: false,
Expand Down
3 changes: 3 additions & 0 deletions apps/desktop/src/settings/LastCodeSettingsImport.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ describe("LastCodeSettingsImport", () => {
const sourceCustom = ProviderInstanceId.make("source_custom");
const lastCodeCustom = ProviderInstanceId.make("lastcode_custom");
const sourceClient = { ...DEFAULT_CLIENT_SETTINGS, fontSizeInterface: 17 };
Reflect.deleteProperty(sourceClient, "compactLegacySidebarStatuses");
Reflect.deleteProperty(sourceClient, "legacySidebarScale");
Reflect.deleteProperty(sourceClient, "roundedProjectIcons");
sourceClient.favorites = [
Expand All @@ -103,6 +104,7 @@ describe("LastCodeSettingsImport", () => {
};
const destinationClient = {
...DEFAULT_CLIENT_SETTINGS,
compactLegacySidebarStatuses: true,
legacySidebarScale: 75,
roundedProjectIcons: true,
environmentIconColors: { primary: "#2563eb", remote: "#7c3aed" },
Expand Down Expand Up @@ -215,6 +217,7 @@ describe("LastCodeSettingsImport", () => {
) as unknown,
);
assert.equal(importedClient.fontSizeInterface, 17);
assert.equal(importedClient.compactLegacySidebarStatuses, true);
assert.equal(importedClient.legacySidebarScale, 75);
assert.equal(importedClient.roundedProjectIcons, true);
assert.deepEqual(importedClient.environmentIconColors, {
Expand Down
1 change: 1 addition & 0 deletions apps/desktop/src/settings/LastCodeSettingsImport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ function mergeClientSettings(sourceRaw: string, destinationRaw: string | null):
...source,
favorites,
providerModelPreferences,
compactLegacySidebarStatuses: destination.compactLegacySidebarStatuses,
environmentIconColors: destination.environmentIconColors,
legacySidebarScale: destination.legacySidebarScale,
roundedProjectIcons: destination.roundedProjectIcons,
Expand Down
19 changes: 18 additions & 1 deletion apps/web/src/components/LegacySidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,7 @@ function buildThreadJumpLabelMap(input: {

interface SidebarThreadRowProps {
thread: SidebarThreadSummary;
compactStatusIndicators: boolean;
showLocalEnvironmentIcon: boolean;
configuredEnvironmentIconColor: EnvironmentIconColor | undefined;
projectCwd: string | null;
Expand Down Expand Up @@ -889,7 +890,9 @@ export const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThr
</TooltipPopup>
</Tooltip>
)}
{threadStatus && <ThreadStatusLabel status={threadStatus} />}
{threadStatus && (
<ThreadStatusLabel status={threadStatus} compact={props.compactStatusIndicators} />
)}
{renamingThreadKey === threadKey ? (
<input
ref={handleRenameInputRef}
Expand Down Expand Up @@ -1137,6 +1140,7 @@ export const SidebarThreadRow = memo(function SidebarThreadRow(props: SidebarThr

interface SidebarProjectThreadListProps {
legacySidebarScale: LegacySidebarScale;
compactStatusIndicators: boolean;
scaleStyle: CSSProperties;
providerEntriesByEnvironmentId: ReadonlyMap<string, ReadonlyMap<string, ProviderInstanceEntry>>;
environmentIconColors: Readonly<Record<string, EnvironmentIconColor>>;
Expand Down Expand Up @@ -1201,6 +1205,7 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(
) {
const {
legacySidebarScale,
compactStatusIndicators,
scaleStyle,
providerEntriesByEnvironmentId,
environmentIconColors,
Expand Down Expand Up @@ -1271,6 +1276,7 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(
<SidebarThreadRow
key={threadKey}
thread={thread}
compactStatusIndicators={compactStatusIndicators}
showLocalEnvironmentIcon={showLocalEnvironmentIcon}
configuredEnvironmentIconColor={environmentIconColors[thread.environmentId]}
projectCwd={projectCwd}
Expand Down Expand Up @@ -1344,6 +1350,7 @@ const SidebarProjectThreadList = memo(function SidebarProjectThreadList(

interface SidebarProjectItemProps {
legacySidebarScale: LegacySidebarScale;
compactStatusIndicators: boolean;
scaleStyle: CSSProperties;
providerEntriesByEnvironmentId: ReadonlyMap<string, ReadonlyMap<string, ProviderInstanceEntry>>;
desktopLocalEnvironmentIds: ReadonlySet<EnvironmentId>;
Expand Down Expand Up @@ -1372,6 +1379,7 @@ interface SidebarProjectItemProps {
const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjectItemProps) {
const {
legacySidebarScale,
compactStatusIndicators,
scaleStyle,
providerEntriesByEnvironmentId,
project,
Expand Down Expand Up @@ -2755,6 +2763,7 @@ const SidebarProjectItem = memo(function SidebarProjectItem(props: SidebarProjec

<SidebarProjectThreadList
legacySidebarScale={legacySidebarScale}
compactStatusIndicators={compactStatusIndicators}
scaleStyle={scaleStyle}
providerEntriesByEnvironmentId={providerEntriesByEnvironmentId}
environmentIconColors={props.environmentIconColors}
Expand Down Expand Up @@ -3213,6 +3222,7 @@ interface SidebarProjectsContentProps {
attachProjectListAutoAnimateRef: (node: HTMLElement | null) => void;
projectsLength: number;
legacySidebarScale: LegacySidebarScale;
compactStatusIndicators: boolean;
projectTreeScaleStyle: CSSProperties;
providerEntriesByEnvironmentId: ReadonlyMap<string, ReadonlyMap<string, ProviderInstanceEntry>>;
desktopLocalEnvironmentIds: ReadonlySet<EnvironmentId>;
Expand Down Expand Up @@ -3328,6 +3338,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
attachProjectListAutoAnimateRef,
projectsLength,
legacySidebarScale,
compactStatusIndicators,
projectTreeScaleStyle,
providerEntriesByEnvironmentId,
desktopLocalEnvironmentIds,
Expand Down Expand Up @@ -3461,6 +3472,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
{(dragHandleProps) => (
<SidebarProjectItem
legacySidebarScale={legacySidebarScale}
compactStatusIndicators={compactStatusIndicators}
scaleStyle={projectTreeScaleStyle}
providerEntriesByEnvironmentId={providerEntriesByEnvironmentId}
desktopLocalEnvironmentIds={desktopLocalEnvironmentIds}
Expand Down Expand Up @@ -3501,6 +3513,7 @@ const SidebarProjectsContent = memo(function SidebarProjectsContent(
<SidebarProjectListRow
key={project.projectKey}
legacySidebarScale={legacySidebarScale}
compactStatusIndicators={compactStatusIndicators}
scaleStyle={projectTreeScaleStyle}
providerEntriesByEnvironmentId={providerEntriesByEnvironmentId}
desktopLocalEnvironmentIds={desktopLocalEnvironmentIds}
Expand Down Expand Up @@ -3557,6 +3570,9 @@ export default function LegacySidebar() {
const projectGroupingSettings = useClientSettings(selectProjectGroupingSettings);
const sidebarThreadPreviewCount = useClientSettings((s) => s.sidebarThreadPreviewCount);
const legacySidebarScale = useClientSettings<LegacySidebarScale>((s) => s.legacySidebarScale);
const compactStatusIndicators = useClientSettings(
(settings) => settings.compactLegacySidebarStatuses,
);
const environmentIconColors = useClientSettings((s) => s.environmentIconColors);
const showLocalEnvironmentIcon = useClientSettings((s) => s.showLocalEnvironmentIcon);
const serverProviders = useAtomValue(primaryServerProvidersAtom);
Expand Down Expand Up @@ -4247,6 +4263,7 @@ export default function LegacySidebar() {
attachProjectListAutoAnimateRef={attachProjectListAutoAnimateRef}
projectsLength={projects.length}
legacySidebarScale={legacySidebarScale}
compactStatusIndicators={compactStatusIndicators}
projectTreeScaleStyle={scaleStyle}
providerEntriesByEnvironmentId={providerEntriesByEnvironmentId}
desktopLocalEnvironmentIds={desktopLocalEnvironmentIds}
Expand Down
1 change: 1 addition & 0 deletions apps/web/src/components/ThreadStatusIndicators.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ export function ThreadStatusLabel({
<TooltipTrigger
render={
<span
role="img"
aria-label={status.label}
className={`inline-flex size-3.5 shrink-0 items-center justify-center ${status.colorClass}`}
/>
Expand Down
13 changes: 13 additions & 0 deletions apps/web/src/components/settings/LastCodeSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,19 @@ export function LastCodeSettingsPanel() {
/>
}
/>
<SettingsRow
{...searchableSetting("compact-status-indicators")}
description="Show colored dot only for agent status, hiding labels like “Working” and “Completed.”"
control={
<Switch
checked={clientSettings.compactLegacySidebarStatuses}
onCheckedChange={(checked) =>
updateClientSettings({ compactLegacySidebarStatuses: Boolean(checked) })
}
aria-label="Compact status indicators"
/>
}
/>
</SettingsSection>
<SettingsSection
id="environment-icons"
Expand Down
3 changes: 3 additions & 0 deletions apps/web/src/components/settings/settingsSearch.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ describe("searchSettings", () => {
it("matches normalized title substrings", () => {
expect(searchSettings(" WORD WRAP ", ITEMS).map((item) => item.id)).toEqual(["word-wrap"]);
expect(searchSettings("glass").map((item) => item.id)).toEqual(["setting-glass-opacity"]);
expect(searchSettings("compact status").map((item) => item.id)).toEqual([
"compact-status-indicators",
]);
expect(searchSettings("xyzzy")).toEqual([]);
});

Expand Down
5 changes: 5 additions & 0 deletions apps/web/src/components/settings/settingsSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,11 @@ export const SETTINGS_SEARCH_ITEMS = [
title: "Scale legacy sidebar",
to: "/settings/lastcode",
},
{
id: "compact-status-indicators",
title: "Compact status indicators",
to: "/settings/lastcode",
},
{
id: "rounded-project-icons",
title: "Rounded project icons",
Expand Down
5 changes: 5 additions & 0 deletions docs/user/thread-sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ LastCode header, Search field, Projects heading, drafts, status notices, and foo
their standard size. On desktop, **View -> Actual Size**, **Zoom In**, and **Zoom Out** continue to
zoom the whole application and compose with the legacy sidebar scale.

To keep the same status colors while using less horizontal space, enable **Compact status
indicators** in **Settings -> LastCode -> Appearance**. Legacy thread rows then show only the
colored status dot; the full status remains available as a tooltip. This preference is off by
default.

## Environment icons in LastCode

Open **Settings -> LastCode -> Environments** to choose the icon color for the primary machine and
Expand Down
11 changes: 11 additions & 0 deletions packages/contracts/src/settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ describe("ClientSettings environment icons", () => {
describe("ClientSettings sidebar", () => {
it("defaults to the current sidebar with automatic merge and inactivity settling", () => {
const settings = decodeClientSettings({});
expect(settings.compactLegacySidebarStatuses).toBe(false);
expect(settings.legacySidebarEnabled).toBe(false);
expect(settings.legacySidebarScale).toBe(100);
expect(settings.sidebarAutoSettleAfterDays).toBe(3);
Expand All @@ -138,6 +139,16 @@ describe("ClientSettings sidebar", () => {
);
});

it("preserves compact legacy sidebar status indicators", () => {
expect(
decodeClientSettings({ compactLegacySidebarStatuses: true }).compactLegacySidebarStatuses,
).toBe(true);
expect(
decodeClientSettingsPatch({ compactLegacySidebarStatuses: true })
.compactLegacySidebarStatuses,
).toBe(true);
});

it.each([50, 75, 100])("accepts a legacy sidebar scale within 50..100: %s", (value) => {
expect(decodeClientSettings({ legacySidebarScale: value }).legacySidebarScale).toBe(value);
expect(decodeClientSettingsPatch({ legacySidebarScale: value }).legacySidebarScale).toBe(value);
Expand Down
4 changes: 4 additions & 0 deletions packages/contracts/src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,9 @@ export const ClientSettingsSchema = Schema.Struct({
confirmQuit: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),
confirmThreadArchive: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(false))),
confirmThreadDelete: Schema.Boolean.pipe(Schema.withDecodingDefault(Effect.succeed(true))),
compactLegacySidebarStatuses: Schema.Boolean.pipe(
Schema.withDecodingDefault(Effect.succeed(false)),
),
Comment thread
lastobelus marked this conversation as resolved.
dismissedProviderUpdateNotificationKeys: Schema.Array(TrimmedNonEmptyString).pipe(
Schema.withDecodingDefault(Effect.succeed([])),
),
Expand Down Expand Up @@ -902,6 +905,7 @@ export const ClientSettingsPatch = Schema.Struct({
confirmQuit: Schema.optionalKey(Schema.Boolean),
confirmThreadArchive: Schema.optionalKey(Schema.Boolean),
confirmThreadDelete: Schema.optionalKey(Schema.Boolean),
compactLegacySidebarStatuses: Schema.optionalKey(Schema.Boolean),
diffIgnoreWhitespace: Schema.optionalKey(Schema.Boolean),
environmentIdentificationMode: Schema.optionalKey(EnvironmentIdentificationMode),
environmentIconColors: Schema.optionalKey(Schema.Record(EnvironmentId, EnvironmentIconColor)),
Expand Down