From f46b336e04f8d7a2e737a6241d0e00ba6aa9d6aa Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:23:55 +0300 Subject: [PATCH 1/2] feat(theme): map editor_colors to QueryaEditorTheme Add editorThemeFromQueryaColors with parseQueryaThemeColor parsing and fallback to the preset editor theme; ignore workbench keys for TP-07. --- .../querya_editor_theme_from_manifest.dart | 83 +++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 lib/core/theme/parser/querya_editor_theme_from_manifest.dart diff --git a/lib/core/theme/parser/querya_editor_theme_from_manifest.dart b/lib/core/theme/parser/querya_editor_theme_from_manifest.dart new file mode 100644 index 00000000..c91e13c0 --- /dev/null +++ b/lib/core/theme/parser/querya_editor_theme_from_manifest.dart @@ -0,0 +1,83 @@ +import 'dart:ui'; + +import 'package:flutter/foundation.dart'; + +import '../querya_editor_theme.dart'; +import 'color_parser.dart'; + +const _knownEditorColorKeys = { + 'background', + 'foreground', + 'lineHighlight', + 'selection', + 'lineNumber', + 'bracketMatch', + 'widgetBorder', + 'comment', + 'keyword', + 'string', + 'number', + 'operator', + 'function', + 'type', +}; + +/// Builds [QueryaEditorTheme] from Querya custom `editor_colors`. +/// +/// Missing keys and invalid optional colors fall back to [fallback]. +/// Workbench-related keys in the same map are ignored here (handled separately). +QueryaEditorTheme editorThemeFromQueryaColors({ + required Map colors, + required QueryaEditorTheme fallback, +}) { + if (kDebugMode) { + for (final key in colors.keys) { + if (!_knownEditorColorKeys.contains(key)) { + debugPrint('Querya theme: ignored editor_colors 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; + } + } + + Color? pickOptional(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( + background: pick('background', fallback.background), + foreground: pick('foreground', fallback.foreground), + lineHighlight: pick('lineHighlight', fallback.lineHighlight), + selection: pick('selection', fallback.selection), + lineNumber: pick('lineNumber', fallback.lineNumber), + bracketMatch: pick('bracketMatch', fallback.bracketMatch), + widgetBorder: pickOptional('widgetBorder', fallback.widgetBorder), + comment: pick('comment', fallback.comment), + keyword: pick('keyword', fallback.keyword), + string: pick('string', fallback.string), + number: pick('number', fallback.number), + operator: pick('operator', fallback.operator), + function: pick('function', fallback.function), + type: pick('type', fallback.type), + ); +} From 1920e2b60e1de671e5e2bd8e118433877ed0ab97 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:23:55 +0300 Subject: [PATCH 2/2] test(theme): cover editor_colors QueryaEditorTheme mapping Closes #101. --- ...uerya_editor_theme_from_manifest_test.dart | 61 +++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 test/core/theme/parser/querya_editor_theme_from_manifest_test.dart diff --git a/test/core/theme/parser/querya_editor_theme_from_manifest_test.dart b/test/core/theme/parser/querya_editor_theme_from_manifest_test.dart new file mode 100644 index 00000000..acee07e5 --- /dev/null +++ b/test/core/theme/parser/querya_editor_theme_from_manifest_test.dart @@ -0,0 +1,61 @@ +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_editor_theme_from_manifest.dart'; +import 'package:querya_desktop/core/theme/parser/querya_theme_manifest.dart'; +import 'package:querya_desktop/core/theme/querya_theme.dart'; + +void main() { + group('editorThemeFromQueryaColors', () { + test('full fixture maps custom editor values', () { + final raw = + File('test/fixtures/themes/querya_custom_dark.json').readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final editor = editorThemeFromQueryaColors( + colors: manifest.editorColors, + fallback: QueryaTheme.darkDefault.editor, + ); + + expect(editor.background, parseQueryaThemeColor('#0F1117')); + expect(editor.foreground, parseQueryaThemeColor('#E2E8F0')); + expect(editor.selection, parseQueryaThemeColor('#264F78')); + expect(editor.lineNumber, parseQueryaThemeColor('#64748B')); + expect(editor.widgetBorder, parseQueryaThemeColor('#38BDF866')); + expect(editor.keyword, parseQueryaThemeColor('#569CD6')); + }); + + test('minimal fixture falls back for missing editor fields', () { + final raw = File('test/fixtures/themes/querya_custom_minimal.json') + .readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final fallback = QueryaTheme.darkDefault.editor; + final editor = editorThemeFromQueryaColors( + colors: manifest.editorColors, + fallback: fallback, + ); + + expect(editor.background, parseQueryaThemeColor('#010203')); + expect(editor.foreground, fallback.foreground); + expect(editor.selection, fallback.selection); + expect(editor.comment, fallback.comment); + expect(editor.widgetBorder, fallback.widgetBorder); + }); + + test('invalid optional color uses fallback value', () { + final fallback = QueryaTheme.darkDefault.editor; + final editor = editorThemeFromQueryaColors( + colors: const { + 'background': '#0F1117', + 'selection': 'bad-color', + 'keyword': 'ZZZZZZ', + }, + fallback: fallback, + ); + + expect(editor.background, parseQueryaThemeColor('#0F1117')); + expect(editor.selection, fallback.selection); + expect(editor.keyword, fallback.keyword); + }); + }); +}