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
3 changes: 2 additions & 1 deletion Packages/macOS/CmuxNext/Sources/CmuxNextDiff/DiffPrefs.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import Foundation
/// the page keeps (webviews/src/viewer-prefs.ts `sanitizeViewerPrefs`).
public nonisolated enum DiffPrefKey {
public static let section = "diff"
static let booleans: Set<String> = ["wordWrap", "wordDiffs", "lineNumbers", "showBackgrounds", "expandUnchanged"]
static let booleans: Set<String> = ["wordWrap", "wordDiffs", "lineNumbers", "showBackgrounds", "expandUnchanged",
"groupByKind"]
static let choices: [String: Set<String>] = [
"layout": ["split", "unified"],
"diffIndicators": ["bars", "classic", "none"],
Expand Down
131 changes: 131 additions & 0 deletions Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Localizable.xcstrings
Original file line number Diff line number Diff line change
Expand Up @@ -64068,6 +64068,137 @@
}
}
},
"settings.diff.groupByKind": {
"extractionState": "manual",
"localizations": {
"en": {
"stringUnit": {
"state": "translated",
"value": "Group Files by Kind"
}
},
"ja": {
"stringUnit": {
"state": "needs_review",
"value": "ファイルを種類別にグループ化"
}
},
"ar": {
"stringUnit": {
"state": "needs_review",
"value": "تجميع الملفات حسب النوع"
}
},
"bs": {
"stringUnit": {
"state": "needs_review",
"value": "Grupiši datoteke po vrsti"
}
},
"da": {
"stringUnit": {
"state": "needs_review",
"value": "Gruppér filer efter type"
}
},
"de": {
"stringUnit": {
"state": "needs_review",
"value": "Dateien nach Art gruppieren"
}
},
"es": {
"stringUnit": {
"state": "needs_review",
"value": "Agrupar archivos por tipo"
}
},
"fr": {
"stringUnit": {
"state": "needs_review",
"value": "Grouper les fichiers par type"
}
},
"it": {
"stringUnit": {
"state": "needs_review",
"value": "Raggruppa i file per tipo"
}
},
"km": {
"stringUnit": {
"state": "needs_review",
"value": "ដាក់ជាក្រុមឯកសារតាមប្រភេទ"
}
},
"ko": {
"stringUnit": {
"state": "needs_review",
"value": "파일을 종류별로 그룹화"
}
},
"nb": {
"stringUnit": {
"state": "needs_review",
"value": "Grupper filer etter type"
}
},
"pl": {
"stringUnit": {
"state": "needs_review",
"value": "Grupuj pliki według rodzaju"
}
},
"pt-BR": {
"stringUnit": {
"state": "needs_review",
"value": "Agrupar arquivos por tipo"
}
},
"ru": {
"stringUnit": {
"state": "needs_review",
"value": "Группировать файлы по типу"
}
},
"th": {
"stringUnit": {
"state": "needs_review",
"value": "จัดกลุ่มไฟล์ตามประเภท"
}
},
"tr": {
"stringUnit": {
"state": "needs_review",
"value": "Dosyaları türe göre grupla"
}
},
"uk": {
"stringUnit": {
"state": "needs_review",
"value": "Групувати файли за типом"
}
},
"vi": {
"stringUnit": {
"state": "needs_review",
"value": "Nhóm tệp theo loại"
}
},
"zh-Hans": {
"stringUnit": {
"state": "needs_review",
"value": "按类型分组文件"
}
},
"zh-Hant": {
"stringUnit": {
"state": "needs_review",
"value": "按類型分組檔案"
}
}
}
},
"settings.diff.layout": {
"extractionState": "manual",
"localizations": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ nonisolated enum DiffViewerSettingsSchema {
toggle("showBackgrounds", SettingsText.keyed("settings.diff.showBackgrounds", "Change Backgrounds"), true, ["background", "color"]),
toggle("expandUnchanged", SettingsText.keyed("settings.diff.expandUnchanged", "Expand Unchanged Lines"), false,
["unchanged", "context", "expand"]),
// Off by default: the familiar order is the order the diff arrived in, and a reorder
// nobody can turn off has no business being the default. The toolbar's toggle writes
// this row, so turning it on now lasts past the tab (webviews/src/viewer-prefs.ts).
toggle("groupByKind", SettingsText.keyed("settings.diff.groupByKind", "Group Files by Kind"), false,
["group", "kind", "tests", "generated", "order", "sort"]),
]
}
}
6 changes: 6 additions & 0 deletions docs/mdm/com.manaflow.cmux.json
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,12 @@
"title" : "Expand Unchanged Lines",
"type" : "boolean"
},
"diff.groupByKind" : {
"default" : false,
"description" : "diff.groupByKind",
"title" : "Group Files by Kind",
"type" : "boolean"
},
"diff.layout" : {
"default" : "unified",
"description" : "diff.layout",
Expand Down
10 changes: 10 additions & 0 deletions docs/mdm/com.manaflow.cmux.plist
Original file line number Diff line number Diff line change
Expand Up @@ -3205,6 +3205,16 @@
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_default</key>
<false/>
<key>pfm_name</key>
<string>diff.groupByKind</string>
<key>pfm_title</key>
<string>Group Files by Kind</string>
<key>pfm_type</key>
<string>boolean</string>
</dict>
<dict>
<key>pfm_default</key>
<false/>
Expand Down
1 change: 1 addition & 0 deletions docs/mdm/managed-preferences.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ Files: `com.manaflow.cmux.plist` (ProfileManifests: iMazing Profile Editor, Prof
| `diff.lineNumbers` | boolean | `true` | | Line Numbers |
| `diff.showBackgrounds` | boolean | `true` | | Change Backgrounds |
| `diff.expandUnchanged` | boolean | `false` | | Expand Unchanged Lines |
| `diff.groupByKind` | boolean | `false` | | Group Files by Kind |
| `markdown.remoteImages` | boolean | `false` | | Load Web Images Automatically. Web image sites can see your address and when you open a document. When off, each document asks before loading its web images. |
| `markdown.layout.width` | real | `72` | 30 to 1000 | Text Width. The widest a line of text gets, in characters (30 to 1000). On a wider window the text stays centered with margins. Wide tables and code scroll sideways in their own box. |
| `markdown.layout.fullWidth` | boolean | `false` | | Full Width. Text fills the whole pane instead of the text width. |
Expand Down
1 change: 1 addition & 0 deletions schemas/defaults/cmux-next.json
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@
"setting.diff.colors": "theme",
"setting.diff.diffIndicators": "bars",
"setting.diff.expandUnchanged": false,
"setting.diff.groupByKind": false,
"setting.diff.layout": "unified",
"setting.diff.lineNumbers": true,
"setting.diff.showBackgrounds": true,
Expand Down
4 changes: 2 additions & 2 deletions schemas/settings-export/settings-schema.sources.sha256
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ f6190cfeca4fa8b6e7a8fc495646e4f1febdbf801e79cac5030ae811aa5e28c1 Packages/macOS

69d7e7fe1d80c27c5ca44664c5b145d3151b9f3374f7c1885d8d66168c2ffdf4 Packages/macOS/CmuxNext/Sources/CmuxNextSettings/LinkRules/BrowserExternalURLWildcardToken.swift

b223d9a61808ba238ca903c9294704f02d422f0206f7f9a3045f1ceb83450dff Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Localizable.xcstrings
5b947bcc40c92b1f511e717579f7776b2d2e7233fdbe2fd3b87aa4f9c4889879 Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Localizable.xcstrings

e9de7365e47f67dee0d803eb974aa58404888670588b0064be42b523dc463ffa Packages/macOS/CmuxNext/Sources/CmuxNextSettings/MainPaneSetting.swift

Expand Down Expand Up @@ -324,7 +324,7 @@ b2c7a42ded8d358de1d247e1a95761c6924f48f9b55ef2b50b55897f515a67c1 Packages/macOS

a9aa2826a915c5886057e7f782451f9d9c3d8d4f5cbcd4bed953040944b15566 Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Schema/DeterministicJSON.swift

f8b2429d8bd0ab7336241ffc38b147582440a6829d44e5a30b0795cf21d42bc0 Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Schema/DiffViewerSettingsSchema.swift
a5b9b7a60596f31e8e1e5af4b215665dc822d664d1da568d5d7bdf073f69f2f3 Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Schema/DiffViewerSettingsSchema.swift

e36a5c327fb10a60497bdfebd32c71ca655869150d9d6adf0fd2142822d84a97 Packages/macOS/CmuxNext/Sources/CmuxNextSettings/Schema/EditorSettingsSchema.swift

Expand Down
50 changes: 49 additions & 1 deletion schemas/settings/settings-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@
"diff.wordDiffs",
"diff.lineNumbers",
"diff.showBackgrounds",
"diff.expandUnchanged"
"diff.expandUnchanged",
"diff.groupByKind"
],
"title" : {
"key" : "settings.group.diffViewer",
Expand Down Expand Up @@ -16492,6 +16493,53 @@
},
"validation" : "portable"
},
{
"accepts" : [
true,
false
],
"agent_refusal" : null,
"agent_settable" : true,
"consumers" : [
"cmux-next"
],
"default" : false,
"default_label" : null,
"group" : {
"key" : "settings.group.diffViewer",
"text" : "Diff Viewer"
},
"help" : null,
"kept_on_reset_all" : false,
"key" : "diff.groupByKind",
"keywords" : [
"diff",
"group",
"kind",
"tests",
"generated",
"order",
"sort"
],
"kind" : "toggle",
"page_hidden" : false,
"path" : [
"diff",
"groupByKind"
],
"refuses" : [
"true",
1,
null
],
"section" : "appearance",
"summary" : null,
"title" : {
"key" : "settings.diff.groupByKind",
"text" : "Group Files by Kind"
},
"validation" : "portable"
},
{
"accepts" : [
true,
Expand Down
4 changes: 2 additions & 2 deletions webviews/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -619,10 +619,10 @@ export function App({ config, initialStatus }: ConfigProps) {
dispatch({ type: "set-option", key: "layout", value: layout });
};
// Dispatches an options change and persists it globally when the key is a
// persisted preference (`collapsed` and `groupByKind` stay session-local; see ViewerPrefs).
// persisted preference (`collapsed` stays session-local; see ViewerPrefs).
const setOption = (key: keyof DiffViewerOptions, value: any) => {
dispatch({ type: "set-option", key, value });
if (key !== "collapsed" && key !== "groupByKind") {
if (key !== "collapsed") {
saveViewerPrefs({ [key]: value }, writes);
}
};
Expand Down
22 changes: 9 additions & 13 deletions webviews/src/diff-viewer/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,6 @@ export function initialAppState(config: DiffViewerConfig, initialStatus: DiffVie
options: {
collapsed: false,
...defaultDiffViewerOptions(payload),
// Outside `defaultDiffViewerOptions`, which diff-option-defaults.test.ts holds to the
// exported `diff.*` schema: this one has no schema row yet. The delineated diff is opt-in
// from the toolbar while it is session-local, because a reorder of the file column that a
// reader cannot durably turn off is not a default (familiar first). It moves in there, and
// can become the default, once `diff.groupByKind` has its row and the toggle sticks.
groupByKind: false,
...seededOptions,
layout: initialDiffViewerLayout(payload),
} as DiffViewerOptions,
Expand All @@ -156,18 +150,20 @@ export function initialAppState(config: DiffViewerConfig, initialStatus: DiffVie
/**
* The display options before any stored pref. In cmux NEXT (the page host; its config's transport
* is `page`) they are the defaults of the `diff.*` settings (DiffViewerSettingsSchema.swift), and
* diff-option-defaults.test.ts holds every key here to the exported schema — which is why
* `groupByKind`, the one display option with no schema row yet, is defaulted by the caller and
* named in the type rather than left to drift in here. Word changes are on there (Leo,
* 2026-10-20). The classic viewer and the dev server embed their config and keep word changes off.
* diff-option-defaults.test.ts holds every key here to the exported schema. Word changes are on
* there (Leo, 2026-10-20). The classic viewer and the dev server embed their config and keep word
* changes off.
*
* `groupByKind` is off here: the familiar order is the order the diff arrived in, and the grouping
* is turned on from the toolbar. Now that `diff.groupByKind` has a schema row, turning it on lasts
* past the tab, which is what a default would have to be worth before it becomes one.
*/
export function defaultDiffViewerOptions(
payload: DiffViewerPayload,
): Omit<DiffViewerOptions, "collapsed" | "layout" | "groupByKind"> {
export function defaultDiffViewerOptions(payload: DiffViewerPayload): Omit<DiffViewerOptions, "collapsed" | "layout"> {
return {
colors: "theme",
diffIndicators: "bars",
expandUnchanged: false,
groupByKind: false,
lineNumbers: true,
showBackgrounds: true,
wordDiffs: payload.transport?.kind === "page",
Expand Down
23 changes: 14 additions & 9 deletions webviews/src/viewer-prefs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,13 @@ import type { DiffViewerOptions } from "./pierre-options";
* `cmux.diff.prefs.set {key, value}` (diff/pageStore.ts), and web storage is never touched (the
* page host pool clears it). The host seeds first paint through `payload.viewerOptions`.
*
* `groupByKind` is session-local for now, like `collapsed`: the host only accepts the `diff.*`
* keys it has schema rows for (`DiffPrefKey.booleans`), so sending it would be refused and
* dropped without a word. Giving it a row is the new-setting checklist (schema row, agent policy,
* 21 locales, regenerated settings exports) and lands on its own, once the defaults snapshot is
* green on base; `test/viewer-prefs-host-keys.test.ts` fails if the two lists drift apart again.
* Until then the grouping is off by default (state.ts) and turned on from the toolbar for the
* session: a reorder nobody can durably turn off has no business being the default.
* `groupByKind` is persisted like the rest since it got its `diff.groupByKind` schema row: it
* shipped as a toolbar toggle that reset itself on every reopen, because the host refuses a
* `diff.*` key it has no row for (`DiffPrefKey.booleans`) and `saveViewerPrefs` swallows that
* refusal. `test/viewer-prefs-host-keys.test.ts` fails if the two lists drift apart again. It
* stays off by default (state.ts): a reorder of the file column is the reader's to ask for.
*/
export type ViewerPrefs = Partial<Omit<DiffViewerOptions, "collapsed" | "groupByKind">> & {
export type ViewerPrefs = Partial<Omit<DiffViewerOptions, "collapsed">> & {
collapsedFiles?: string[];
};

Expand All @@ -51,7 +49,14 @@ export function sanitizeViewerPrefs(raw: unknown): ViewerPrefs {
if (source.colors === "theme" || source.colors === "muted" || source.colors === "standard") {
prefs.colors = source.colors;
}
for (const key of ["wordWrap", "wordDiffs", "lineNumbers", "showBackgrounds", "expandUnchanged"] as const) {
for (const key of [
"wordWrap",
"wordDiffs",
"lineNumbers",
"showBackgrounds",
"expandUnchanged",
"groupByKind",
] as const) {
if (typeof source[key] === "boolean") {
prefs[key] = source[key];
}
Expand Down
Loading