1import * as Schema from "effect/Schema";
2import * as Struct from "effect/Struct";
3import { ClientSettingsPatch } from "./settings.ts";
4import { EnvironmentTheme } from "./server.ts";
5
6export const UiThemePreferences = Schema.Struct({
7 selection: Schema.String.check(Schema.isMaxLength(128)),
8 mode: Schema.Literals(["system", "light", "dark"]),
9 halves: Schema.Struct({
10 light: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(128))),
11 dark: Schema.optionalKey(Schema.String.check(Schema.isMaxLength(128))),
12 }),
13 customThemes: Schema.Array(
14 Schema.Struct({
15 ...EnvironmentTheme.fields,
16 colors: Schema.requiredKey(EnvironmentTheme.fields.colors),
17 collection: Schema.optionalKey(Schema.Struct({ id: Schema.String, label: Schema.String })),
18 managed: Schema.optionalKey(Schema.Boolean),
19 }),
20 ).check(Schema.isMaxLength(64)),
21});
22export type UiThemePreferences = typeof UiThemePreferences.Type;
23
24/** Only portable presentation preferences belong in a personal profile. */
25export const UiSettingsValues = Schema.Struct({
26 ...Struct.pick(ClientSettingsPatch.fields, [
27 "diffColorScheme",
28 "chatWidth",
29 "appearanceContrast",
30 "panelAnimationDurationMs",
31 "diffFilesCollapsed",
32 "diffIgnoreWhitespace",
33 "diffLayout",
34 "environmentIdentificationMode",
35 "fontSizeInterface",
36 "fontSizePrompt",
37 "fontSizeCode",
38 "fontSizeTerminal",
39 "fontFamilyCode",
40 "fontFamilyComposer",
41 "fontFamilySans",
42 "fontFamilyTerminal",
43 "fontSmoothing",
44 "persistComposerContextStrip",
45 "contextWindowMeterEnabled",
46 "composerCollapseOnScroll",
47 "composerRichTextEnabled",
48 "sendShortcut",
49 "followUpBehavior",
50 "proactivePanelsEnabled",
51 "showSkillsInSlashMenu",
52 "sidebarWorkingShelfEnabled",
53 "sidebarProjectGroupingMode",
54 "sidebarProjectSortOrder",
55 "sidebarThreadSortOrder",
56 "sidebarThreadPreviewCount",
57 "timestampFormat",
58 "wordWrap",
59 ]),
60 theme: Schema.optionalKey(UiThemePreferences),
61});
62export type UiSettingsValues = typeof UiSettingsValues.Type;
63
64const Revision = Schema.Int.check(Schema.isGreaterThanOrEqualTo(0));
65export const UiSettingsProfile = Schema.Struct({
66 revision: Revision,
67 values: UiSettingsValues,
68 fieldRevisions: Schema.Record(Schema.String, Revision),
69});
70export type UiSettingsProfile = typeof UiSettingsProfile.Type;
71
72export const UiSettingsPatchInput = Schema.Struct({
73 patch: UiSettingsValues,
74 baseRevisions: Schema.Record(Schema.String, Revision),
75});
76export type UiSettingsPatchInput = typeof UiSettingsPatchInput.Type;
77
78export const UiSettingsPatchResult = Schema.Struct({
79 profile: UiSettingsProfile,
80 conflicts: Schema.Array(Schema.String),
81});
82export type UiSettingsPatchResult = typeof UiSettingsPatchResult.Type;
83
84export class UiSettingsError extends Schema.TaggedError<UiSettingsError>()("UiSettingsError", {
85 operation: Schema.Literals(["read", "write"]),
86 cause: Schema.Defect(),
87}) {
88 override get message(): string {
89 return "Unable to sync UI settings. Reconnect to the profile environment to try again.";
90 }
91}