From 2ceeeb8afacc9f79954a388befefed5c57586924 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:26:34 +0300 Subject: [PATCH 1/2] feat(theme): map editor_colors to QueryaWorkbenchTheme Add workbenchThemeFromQueryaColors for chrome/git tokens in editor_colors; ignore editor syntax keys and do not auto-map background to canvas. --- .../querya_workbench_theme_from_manifest.dart | 71 +++++++++++++++++++ 1 file changed, 71 insertions(+) create mode 100644 lib/core/theme/parser/querya_workbench_theme_from_manifest.dart diff --git a/lib/core/theme/parser/querya_workbench_theme_from_manifest.dart b/lib/core/theme/parser/querya_workbench_theme_from_manifest.dart new file mode 100644 index 00000000..d1f99b92 --- /dev/null +++ b/lib/core/theme/parser/querya_workbench_theme_from_manifest.dart @@ -0,0 +1,71 @@ +import 'dart:ui'; + +import 'package:flutter/foundation.dart'; + +import '../querya_workbench_theme.dart'; +import 'color_parser.dart'; + +/// Workbench keys accepted in Querya custom `editor_colors`. +/// +/// Editor syntax/surface keys are mapped separately by [editorThemeFromQueryaColors]. +/// The generic `background` key is intentionally not mapped to canvas/editorBackground. +const _knownWorkbenchColorKeys = { + 'canvas', + 'surface', + 'sidebarBackground', + 'editorBackground', + 'mutedForeground', + 'accent', + 'onAccent', + 'borderSubtle', + 'destructive', + 'success', + 'warning', + 'gitModified', + 'gitUntracked', +}; + +/// Builds [QueryaWorkbenchTheme] from Querya custom `editor_colors`. +/// +/// Missing keys and invalid optional colors fall back to [fallback]. +QueryaWorkbenchTheme workbenchThemeFromQueryaColors({ + required Map colors, + required QueryaWorkbenchTheme fallback, +}) { + if (kDebugMode) { + for (final key in colors.keys) { + if (!_knownWorkbenchColorKeys.contains(key)) { + debugPrint('Querya theme: ignored editor_colors workbench key "$key"'); + } + } + } + + Color pick(String key, Color defaultValue) { + final raw = colors[key]; + if (raw == null) return defaultValue; + try { + return parseQueryaThemeColor(raw); + } on FormatException { + if (kDebugMode) { + debugPrint('Querya theme: invalid editor_colors."$key": $raw'); + } + return defaultValue; + } + } + + return fallback.copyWith( + canvas: pick('canvas', fallback.canvas), + surface: pick('surface', fallback.surface), + sidebarBackground: pick('sidebarBackground', fallback.sidebarBackground), + editorBackground: pick('editorBackground', fallback.editorBackground), + mutedForeground: pick('mutedForeground', fallback.mutedForeground), + accent: pick('accent', fallback.accent), + onAccent: pick('onAccent', fallback.onAccent), + borderSubtle: pick('borderSubtle', fallback.borderSubtle), + destructive: pick('destructive', fallback.destructive), + success: pick('success', fallback.success), + warning: pick('warning', fallback.warning), + gitModified: pick('gitModified', fallback.gitModified), + gitUntracked: pick('gitUntracked', fallback.gitUntracked), + ); +} From 2c7e6865c19ded36b88753a6a3708478b841cd23 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:26:34 +0300 Subject: [PATCH 2/2] test(theme): cover editor_colors QueryaWorkbenchTheme mapping Closes #102. --- ...ya_workbench_theme_from_manifest_test.dart | 72 +++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 test/core/theme/parser/querya_workbench_theme_from_manifest_test.dart diff --git a/test/core/theme/parser/querya_workbench_theme_from_manifest_test.dart b/test/core/theme/parser/querya_workbench_theme_from_manifest_test.dart new file mode 100644 index 00000000..8b740293 --- /dev/null +++ b/test/core/theme/parser/querya_workbench_theme_from_manifest_test.dart @@ -0,0 +1,72 @@ +import 'dart:io'; + +import 'package:flutter_test/flutter_test.dart'; +import 'package:querya_desktop/core/theme/parser/color_parser.dart'; +import 'package:querya_desktop/core/theme/parser/querya_theme_manifest.dart'; +import 'package:querya_desktop/core/theme/parser/querya_workbench_theme_from_manifest.dart'; +import 'package:querya_desktop/core/theme/querya_theme.dart'; + +void main() { + group('workbenchThemeFromQueryaColors', () { + test('full fixture maps custom workbench values', () { + final raw = + File('test/fixtures/themes/querya_custom_dark.json').readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final workbench = workbenchThemeFromQueryaColors( + colors: manifest.editorColors, + fallback: QueryaTheme.darkDefault.workbench, + ); + + expect(workbench.canvas, parseQueryaThemeColor('#09090B')); + expect(workbench.surface, parseQueryaThemeColor('#111827')); + expect(workbench.sidebarBackground, parseQueryaThemeColor('#0B0F19')); + expect(workbench.editorBackground, parseQueryaThemeColor('#0F1117')); + expect(workbench.accent, parseQueryaThemeColor('#38BDF8')); + expect(workbench.gitModified, parseQueryaThemeColor('#FBBF24')); + expect(workbench.gitUntracked, parseQueryaThemeColor('#34D399')); + }); + + test('minimal fixture falls back for missing workbench fields', () { + final raw = File('test/fixtures/themes/querya_custom_minimal.json') + .readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final fallback = QueryaTheme.darkDefault.workbench; + final workbench = workbenchThemeFromQueryaColors( + colors: manifest.editorColors, + fallback: fallback, + ); + + expect(workbench.canvas, fallback.canvas); + expect(workbench.surface, fallback.surface); + expect(workbench.accent, fallback.accent); + expect(workbench.gitModified, fallback.gitModified); + }); + + test('invalid optional color uses fallback value', () { + final fallback = QueryaTheme.darkDefault.workbench; + final workbench = workbenchThemeFromQueryaColors( + colors: const { + 'canvas': '#09090B', + 'accent': 'not-a-color', + 'gitModified': 'ZZZZZZ', + }, + fallback: fallback, + ); + + expect(workbench.canvas, parseQueryaThemeColor('#09090B')); + expect(workbench.accent, fallback.accent); + expect(workbench.gitModified, fallback.gitModified); + }); + + test('does not map editor background key to workbench canvas', () { + final fallback = QueryaTheme.darkDefault.workbench; + final workbench = workbenchThemeFromQueryaColors( + colors: const {'background': '#010203'}, + fallback: fallback, + ); + + expect(workbench.canvas, fallback.canvas); + expect(workbench.editorBackground, fallback.editorBackground); + }); + }); +}