feat(settings): Keymap category — preset select (T-451)
The keybindings-ui extension contributes a Keymap SettingsCategory: a preset select (Default / Vim / VS Code / JetBrains) reading the active preset from kKeymapPresetSetting. Picking one routes through a new schema affordance — SettingsField.applyCommandPrefix — running `keymap.preset.<value>`, which calls KeymapService.setPreset to persist and reload the layered keymap live. The prefix path keeps the engine generic: settings a subsystem applies via a command (rather than a bare key write) declare the prefix; the scope tag and current-value read still use the key. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -5907,3 +5907,5 @@ INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, chang
|
|||||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'status', 'in_progress', 'done', NULL, '2026-06-17 10:22:42', '2026-06-17 10:22:42.544', '2026-06-17 10:22:42.544', NULL, 'b150c458bb2754f0369000e65406dec2', 2) ON CONFLICT(hash) DO NOTHING;
|
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'status', 'in_progress', 'done', NULL, '2026-06-17 10:22:42', '2026-06-17 10:22:42.544', '2026-06-17 10:22:42.544', NULL, 'b150c458bb2754f0369000e65406dec2', 2) ON CONFLICT(hash) DO NOTHING;
|
||||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'status', 'backlog', 'in_progress', NULL, '2026-06-17 10:29:07', '2026-06-17 10:29:07.736', '2026-06-17 10:29:07.736', NULL, '431cacc8adfb10c478617292fac8776f', 2) ON CONFLICT(hash) DO NOTHING;
|
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'status', 'backlog', 'in_progress', NULL, '2026-06-17 10:29:07', '2026-06-17 10:29:07.736', '2026-06-17 10:29:07.736', NULL, '431cacc8adfb10c478617292fac8776f', 2) ON CONFLICT(hash) DO NOTHING;
|
||||||
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'status', 'in_progress', 'done', NULL, '2026-06-17 10:31:23', '2026-06-17 10:31:23.935', '2026-06-17 10:31:23.935', NULL, '9228abe9a3eb9b340c91717b4dade863', 2) ON CONFLICT(hash) DO NOTHING;
|
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'status', 'in_progress', 'done', NULL, '2026-06-17 10:31:23', '2026-06-17 10:31:23.935', '2026-06-17 10:31:23.935', NULL, '9228abe9a3eb9b340c91717b4dade863', 2) ON CONFLICT(hash) DO NOTHING;
|
||||||
|
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'status', 'backlog', 'in_progress', NULL, '2026-06-17 10:44:25', '2026-06-17 10:44:25.018', '2026-06-17 10:44:25.018', NULL, '4626e79f524f63e003c0f93511e8cdce', 2) ON CONFLICT(hash) DO NOTHING;
|
||||||
|
INSERT INTO ticket_history (ticket_record_id, field, old_value, new_value, changed_by, changed_at, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'status', 'in_progress', 'done', NULL, '2026-06-17 10:48:30', '2026-06-17 10:48:30.719', '2026-06-17 10:48:30.719', NULL, '3758ec372c9635bfd7756a8939f4b329', 2) ON CONFLICT(hash) DO NOTHING;
|
||||||
|
|||||||
@@ -7175,3 +7175,5 @@ INSERT INTO tickets (record_id, type, parent_record_id, title, description, stat
|
|||||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Cross-category settings search', 'The search box filters fields across ALL categories; results render as carded groups under category subheaders, editable inline, with per-category match counts shown in the rail. Zero-match categories dim. Wireframe: settings-search.png.', 'done', 'high', NULL, NULL, NULL, '2026-06-16 11:18:45', '2026-06-17 10:22:42.544', NULL, 'a10a68df4d4cf7ed0f639d74dda41d37', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD09XWEXRJ4JS8MFPQGJEY5M', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Cross-category settings search', 'The search box filters fields across ALL categories; results render as carded groups under category subheaders, editable inline, with per-category match counts shown in the rail. Zero-match categories dim. Wireframe: settings-search.png.', 'done', 'high', NULL, NULL, NULL, '2026-06-16 11:18:45', '2026-06-17 10:22:42.544', NULL, 'a10a68df4d4cf7ed0f639d74dda41d37', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Activity settings category (fold level + display)', 'Register the Claude-activity settings schema: activity fold level (T-183) and related conversation display options, via the standard field renderer (T-448).', 'in_progress', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:57', '2026-06-17 10:29:07.736', NULL, 'a9ef8003e03def2e2ba4c1f59fbba07f', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Activity settings category (fold level + display)', 'Register the Claude-activity settings schema: activity fold level (T-183) and related conversation display options, via the standard field renderer (T-448).', 'in_progress', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:57', '2026-06-17 10:29:07.736', NULL, 'a9ef8003e03def2e2ba4c1f59fbba07f', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||||
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Activity settings category (fold level + display)', 'Register the Claude-activity settings schema: activity fold level (T-183) and related conversation display options, via the standard field renderer (T-448).', 'done', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:57', '2026-06-17 10:31:23.935', NULL, 'a7ddd9362097e6a2f7df764faf7cbf79', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A6K9B60ADTFBZA6NBVJFM', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Activity settings category (fold level + display)', 'Register the Claude-activity settings schema: activity fold level (T-183) and related conversation display options, via the standard field renderer (T-448).', 'done', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:57', '2026-06-17 10:31:23.935', NULL, 'a7ddd9362097e6a2f7df764faf7cbf79', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||||
|
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Keymap settings category (preset select + options)', 'Register the keymap settings schema: preset enum select (default / vscode / jetbrains / vim — T-115, T-64, T-65, T-66) wired to KeymapService.setPreset, plus related options (e.g. sequence-timeout). Reuses the schema field renderer (T-448).', 'in_progress', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:11', '2026-06-17 10:44:25.018', NULL, 'c5d65c432709c0ffad00237e82b7a23c', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||||
|
INSERT INTO tickets (record_id, type, parent_record_id, title, description, status, priority, assigned_to, team, decision_ref, created_at, updated_at, deleted_at, hash, canonical_version) VALUES ('06FD0A0ZTS9JZCSQ4W8ZVEH2VR', 'task', '06FD07ECS3GK2V7Z2WYYPJHJYC', 'Keymap settings category (preset select + options)', 'Register the keymap settings schema: preset enum select (default / vscode / jetbrains / vim — T-115, T-64, T-65, T-66) wired to KeymapService.setPreset, plus related options (e.g. sequence-timeout). Reuses the schema field renderer (T-448).', 'done', 'medium', NULL, NULL, NULL, '2026-06-16 11:19:11', '2026-06-17 10:48:30.719', NULL, '4678d116aadfaea65526200caf8e0ece', 2) ON CONFLICT(record_id) DO UPDATE SET type=excluded.type, parent_record_id=excluded.parent_record_id, title=excluded.title, description=excluded.description, status=excluded.status, priority=excluded.priority, assigned_to=excluded.assigned_to, team=excluded.team, decision_ref=excluded.decision_ref, updated_at=excluded.updated_at, deleted_at=excluded.deleted_at, hash=excluded.hash, canonical_version=excluded.canonical_version WHERE excluded.updated_at > tickets.updated_at OR (excluded.updated_at = tickets.updated_at AND excluded.hash > tickets.hash);
|
||||||
|
|||||||
@@ -48,6 +48,10 @@ heading, and (b) bumping `pubspec.yaml` `version:` in the same commit.
|
|||||||
conversation fold level (none / tools / thinking / everything) as a schema
|
conversation fold level (none / tools / thinking / everything) as a schema
|
||||||
field; picking a level applies live to the activity stream. (T-453)
|
field; picking a level applies live to the activity stream. (T-453)
|
||||||
|
|
||||||
|
- **Settings → Keymap category.** A preset select (Default / Vim / VS Code /
|
||||||
|
JetBrains); picking one switches the active keymap live via the preset
|
||||||
|
command. (T-451)
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
- **Theme picker relabelled "Theme…".** The ⌘K theme picker's command title
|
- **Theme picker relabelled "Theme…".** The ⌘K theme picker's command title
|
||||||
|
|||||||
@@ -42,5 +42,39 @@ class KeybindingsUiExtension extends ClideExtension {
|
|||||||
return IpcResponse.ok(id: '', data: {'preset': entry.key});
|
return IpcResponse.ok(id: '', data: {'preset': entry.key});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
// Keymap settings category (T-451). The select reads the active preset
|
||||||
|
// from kKeymapPresetSetting; picking one runs `keymap.preset.<value>`
|
||||||
|
// (applyCommandPrefix), which calls KeymapService.setPreset — persisting
|
||||||
|
// and reloading the layered keymap live.
|
||||||
|
const SettingsCategoryContribution(
|
||||||
|
id: 'keymap',
|
||||||
|
category: SettingsCategory(
|
||||||
|
id: 'keymap',
|
||||||
|
title: 'Keymap',
|
||||||
|
iconName: 'keyboard',
|
||||||
|
priority: 20,
|
||||||
|
sections: [
|
||||||
|
SettingsSection(
|
||||||
|
label: 'Preset',
|
||||||
|
fields: [
|
||||||
|
SettingsField(
|
||||||
|
key: kKeymapPresetSetting,
|
||||||
|
kind: SettingsFieldKind.select,
|
||||||
|
label: 'Active preset',
|
||||||
|
help: 'Keyboard layout for the whole app.',
|
||||||
|
defaultValue: 'default',
|
||||||
|
applyCommandPrefix: 'keymap.preset.',
|
||||||
|
options: [
|
||||||
|
SettingsOption(value: 'default', label: 'Default'),
|
||||||
|
SettingsOption(value: 'vim', label: 'Vim'),
|
||||||
|
SettingsOption(value: 'vscode', label: 'VS Code'),
|
||||||
|
SettingsOption(value: 'jetbrains', label: 'JetBrains'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -206,7 +206,19 @@ class _Control extends StatelessWidget {
|
|||||||
case SettingsFieldKind.toggle:
|
case SettingsFieldKind.toggle:
|
||||||
return _ToggleControl(checked: value == true, onChanged: _set);
|
return _ToggleControl(checked: value == true, onChanged: _set);
|
||||||
case SettingsFieldKind.select:
|
case SettingsFieldKind.select:
|
||||||
return _SelectControl(field: field, value: value?.toString(), onPick: _set);
|
return _SelectControl(
|
||||||
|
field: field,
|
||||||
|
value: value?.toString(),
|
||||||
|
onPick: (v) {
|
||||||
|
final prefix = field.applyCommandPrefix;
|
||||||
|
if (prefix != null) {
|
||||||
|
// Value selects a command (the subsystem applies + persists).
|
||||||
|
ClideKernel.of(context).commands.execute('$prefix$v');
|
||||||
|
} else {
|
||||||
|
_set(v);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
case SettingsFieldKind.text:
|
case SettingsFieldKind.text:
|
||||||
return _EditControl(field: field, value: value?.toString() ?? '', numeric: false, onCommit: _set);
|
return _EditControl(field: field, value: value?.toString() ?? '', numeric: false, onCommit: _set);
|
||||||
case SettingsFieldKind.number:
|
case SettingsFieldKind.number:
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ class SettingsField {
|
|||||||
this.min,
|
this.min,
|
||||||
this.max,
|
this.max,
|
||||||
this.fileCommand,
|
this.fileCommand,
|
||||||
|
this.applyCommandPrefix,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String key;
|
final String key;
|
||||||
@@ -73,6 +74,13 @@ class SettingsField {
|
|||||||
|
|
||||||
/// For [SettingsFieldKind.file]: the command id the row's button invokes.
|
/// For [SettingsFieldKind.file]: the command id the row's button invokes.
|
||||||
final String? fileCommand;
|
final String? fileCommand;
|
||||||
|
|
||||||
|
/// For [SettingsFieldKind.select]: when set, picking option `<value>` runs
|
||||||
|
/// the command `<applyCommandPrefix><value>` instead of writing [key]
|
||||||
|
/// directly — for settings a subsystem applies via a command (and only then
|
||||||
|
/// persists). The current value is still read from [key], so the scope tag
|
||||||
|
/// and selection still work. Example: `'keymap.preset.'` → `keymap.preset.vim`.
|
||||||
|
final String? applyCommandPrefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A carded group of fields (surface.md "sectioned cards"). [label] is the
|
/// A carded group of fields (surface.md "sectioned cards"). [label] is the
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
library;
|
library;
|
||||||
|
|
||||||
import 'package:clide/builtin/keybindings_ui/keybindings_ui.dart';
|
import 'package:clide/builtin/keybindings_ui/keybindings_ui.dart';
|
||||||
|
import 'package:clide/extension/extension.dart';
|
||||||
import 'package:clide/kernel/kernel.dart';
|
import 'package:clide/kernel/kernel.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
@@ -46,4 +47,16 @@ void main() {
|
|||||||
await f.services.commands.execute('keymap.preset.default');
|
await f.services.commands.execute('keymap.preset.default');
|
||||||
expect(f.services.settings.get<String>(kKeymapPresetSetting), 'default');
|
expect(f.services.settings.get<String>(kKeymapPresetSetting), 'default');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('contributes a Keymap settings category routed through the preset commands (T-451)', () {
|
||||||
|
final category = KeybindingsUiExtension().contributions
|
||||||
|
.whereType<SettingsCategoryContribution>()
|
||||||
|
.firstWhere((c) => c.id == 'keymap')
|
||||||
|
.category;
|
||||||
|
expect(category.title, 'Keymap');
|
||||||
|
final field = category.sections.expand((s) => s.fields).firstWhere((f) => f.key == kKeymapPresetSetting);
|
||||||
|
expect(field.kind, SettingsFieldKind.select);
|
||||||
|
expect(field.applyCommandPrefix, 'keymap.preset.');
|
||||||
|
expect(field.options.map((o) => o.value), containsAll(['default', 'vim', 'vscode', 'jetbrains']));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:clide/builtin/settings_ui/settings_ui.dart';
|
import 'package:clide/builtin/settings_ui/settings_ui.dart';
|
||||||
|
import 'package:clide/clide.dart' show IpcResponse;
|
||||||
import 'package:clide/extension/extension.dart';
|
import 'package:clide/extension/extension.dart';
|
||||||
import 'package:clide/kernel/kernel.dart';
|
import 'package:clide/kernel/kernel.dart';
|
||||||
import 'package:clide/widgets/widgets.dart';
|
import 'package:clide/widgets/widgets.dart';
|
||||||
@@ -105,6 +106,47 @@ void main() {
|
|||||||
await tester.pump();
|
await tester.pump();
|
||||||
expect(f.services.settings.get<String>('app.demo.level'), 'debug');
|
expect(f.services.settings.get<String>('app.demo.level'), 'debug');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('a select with applyCommandPrefix runs the command, not a key write', (tester) async {
|
||||||
|
var ran = '';
|
||||||
|
f.services.commands.register(
|
||||||
|
CommandContribution(
|
||||||
|
id: 'test.apply.vim',
|
||||||
|
command: 'test.apply.vim',
|
||||||
|
run: (_) async {
|
||||||
|
ran = 'vim';
|
||||||
|
return IpcResponse.ok(id: '', data: const {});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
const cat = SettingsCategory(
|
||||||
|
id: 'k',
|
||||||
|
title: 'K',
|
||||||
|
sections: [
|
||||||
|
SettingsSection(
|
||||||
|
label: 'P',
|
||||||
|
fields: [
|
||||||
|
SettingsField(
|
||||||
|
key: 'app.k.preset',
|
||||||
|
kind: SettingsFieldKind.select,
|
||||||
|
label: 'Preset',
|
||||||
|
defaultValue: 'default',
|
||||||
|
applyCommandPrefix: 'test.apply.',
|
||||||
|
options: [SettingsOption(value: 'default', label: 'Default'), SettingsOption(value: 'vim', label: 'Vim')],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
await tester.pumpWidget(harness(f, _bounded(const SettingsCategoryView(category: cat))));
|
||||||
|
await tester.tap(find.bySemanticsLabel(RegExp(r'^Preset:')));
|
||||||
|
await tester.pump();
|
||||||
|
await tester.tap(find.text('Vim'));
|
||||||
|
await tester.pump();
|
||||||
|
expect(ran, 'vim');
|
||||||
|
// The key is applied by the command, not written directly by the engine.
|
||||||
|
expect(f.services.settings.get<String>('app.k.preset'), isNull);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('scope tag (T-449)', () {
|
group('scope tag (T-449)', () {
|
||||||
|
|||||||
Reference in New Issue
Block a user