From 99b2de526956a8a5cf31c03e38e5e3aec1a72201 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:28:43 +0300 Subject: [PATCH 1/3] feat(theme): build QueryaTheme from custom manifest Wire shadcn/editor/workbench mappers into queryaThemeFromManifest, apply tokenColors to the editor, and preserve manifest syntax rules on QueryaTheme. --- .../parser/querya_theme_from_manifest.dart | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 lib/core/theme/parser/querya_theme_from_manifest.dart diff --git a/lib/core/theme/parser/querya_theme_from_manifest.dart b/lib/core/theme/parser/querya_theme_from_manifest.dart new file mode 100644 index 00000000..7142b5a3 --- /dev/null +++ b/lib/core/theme/parser/querya_theme_from_manifest.dart @@ -0,0 +1,48 @@ +import 'package:flutter/material.dart'; + +import '../querya_theme.dart'; +import 'apply_token_colors_to_editor.dart'; +import 'querya_editor_theme_from_manifest.dart'; +import 'querya_theme_color_scheme.dart'; +import 'querya_theme_manifest.dart'; +import 'querya_workbench_theme_from_manifest.dart'; + +/// Builds a [QueryaTheme] from a parsed Querya custom theme manifest. +QueryaTheme queryaThemeFromManifest(QueryaThemeManifest manifest) { + final fallback = + manifest.isLight ? QueryaTheme.lightDefault : QueryaTheme.darkDefault; + final brightness = + manifest.isLight ? Brightness.light : Brightness.dark; + + var editor = editorThemeFromQueryaColors( + colors: manifest.editorColors, + fallback: fallback.editor, + ); + final workbench = workbenchThemeFromQueryaColors( + colors: manifest.editorColors, + fallback: fallback.workbench, + ); + + if (manifest.editorColors.containsKey('editorBackground') && + editor.background != workbench.editorBackground) { + editor = editor.copyWith(background: workbench.editorBackground); + } + + final tokenColors = manifest.tokenColors; + if (tokenColors.isNotEmpty) { + editor = applyTokenColorsToEditor(editor, tokenColors); + } + + final colorScheme = colorSchemeFromQueryaThemeColors( + colors: manifest.shadcnColors, + fallback: fallback, + ); + + return fallback.copyWith( + workbench: workbench, + editor: editor, + brightness: brightness, + colorScheme: colorScheme, + tokenColors: tokenColors, + ); +} From 6777eac56e9d28cedc3a67593ef9f89e9a235c2d Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:28:43 +0300 Subject: [PATCH 2/3] test(theme): cover QueryaTheme factory from custom manifest Closes #103. --- .../querya_theme_from_manifest_test.dart | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 test/core/theme/parser/querya_theme_from_manifest_test.dart diff --git a/test/core/theme/parser/querya_theme_from_manifest_test.dart b/test/core/theme/parser/querya_theme_from_manifest_test.dart new file mode 100644 index 00000000..095413e9 --- /dev/null +++ b/test/core/theme/parser/querya_theme_from_manifest_test.dart @@ -0,0 +1,70 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +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_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('queryaThemeFromManifest', () { + test('full dark fixture builds dark QueryaTheme', () { + final raw = + File('test/fixtures/themes/querya_custom_dark.json').readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final theme = queryaThemeFromManifest(manifest); + + expect(theme.brightness, Brightness.dark); + expect(theme.colorScheme.primary, parseQueryaThemeColor('#38BDF8')); + expect(theme.workbench.canvas, parseQueryaThemeColor('#09090B')); + expect(theme.editor.background, parseQueryaThemeColor('#0F1117')); + expect(theme.editor.selection, parseQueryaThemeColor('#264F78')); + }); + + test('full light fixture builds light QueryaTheme', () { + final raw = + File('test/fixtures/themes/querya_custom_light.json').readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final theme = queryaThemeFromManifest(manifest); + + expect(theme.brightness, Brightness.light); + expect(theme.colorScheme.background, parseQueryaThemeColor('#F8FAFC')); + expect(theme.workbench.surface, parseQueryaThemeColor('#FFFFFF')); + expect(theme.editor.foreground, parseQueryaThemeColor('#1E293B')); + }); + + test('preserves tokenColors from manifest', () { + final raw = + File('test/fixtures/themes/querya_custom_dark.json').readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final theme = queryaThemeFromManifest(manifest); + + expect(theme.tokenColors.length, manifest.tokenColors.length); + expect(theme.tokenColors.first.scopes, ['comment', 'comment.line']); + }); + + test('minimal fixture falls back to preset defaults', () { + final raw = File('test/fixtures/themes/querya_custom_minimal.json') + .readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + final theme = queryaThemeFromManifest(manifest); + final fallback = QueryaTheme.darkDefault; + + expect(theme.brightness, Brightness.dark); + expect(theme.colorScheme.primary, parseQueryaThemeColor('#FF00AA')); + expect(theme.editor.background, parseQueryaThemeColor('#010203')); + expect(theme.editor.foreground, fallback.editor.foreground); + expect(theme.workbench.canvas, fallback.workbench.canvas); + expect(theme.tokenColors, isEmpty); + }); + + test('does not create ThemeData', () { + final raw = + File('test/fixtures/themes/querya_custom_dark.json').readAsStringSync(); + final manifest = QueryaThemeManifest.fromJsonString(raw); + + expect(queryaThemeFromManifest(manifest), isA()); + }); + }); +} From d1cff84eccb1f27b33d3fb0aecf3002008f8fc42 Mon Sep 17 00:00:00 2001 From: ZhuchkaTriplesix Date: Sun, 14 Jun 2026 00:30:35 +0300 Subject: [PATCH 3/3] fix(theme): use const fallback in manifest factory test Satisfy prefer_const_declarations analyzer hint. --- test/core/theme/parser/querya_theme_from_manifest_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/core/theme/parser/querya_theme_from_manifest_test.dart b/test/core/theme/parser/querya_theme_from_manifest_test.dart index 095413e9..e6e1c814 100644 --- a/test/core/theme/parser/querya_theme_from_manifest_test.dart +++ b/test/core/theme/parser/querya_theme_from_manifest_test.dart @@ -49,7 +49,7 @@ void main() { .readAsStringSync(); final manifest = QueryaThemeManifest.fromJsonString(raw); final theme = queryaThemeFromManifest(manifest); - final fallback = QueryaTheme.darkDefault; + const fallback = QueryaTheme.darkDefault; expect(theme.brightness, Brightness.dark); expect(theme.colorScheme.primary, parseQueryaThemeColor('#FF00AA'));