Make the custom accent-color picker actually retint the app
NooColors (the color source for nearly the whole redesigned UI) only had two states: the fixed violet palette, or a Material You dynamic scheme when "Match wallpaper" was on. The 5-swatch custom accent picker still wrote to SettingsController.seedColor, but nothing read it back into NooColors - it only reached the underlying Material ColorScheme, which the Noo-styled UI doesn't use, so every custom swatch looked identically purple. Add NooColors.fromSeed, which retints just the accent/accentText/ accentSoft roles from a chosen seed color via ColorScheme.fromSeed (bg/surface/fg etc. stay the fixed warm-neutral palette, unlike dynamic color which reshapes everything to match the wallpaper), and wire it into AppTheme.light/dark. Add a "Default" (Noo violet) swatch to the picker, and move SettingsController's initial seed color to that same violet so a fresh install - or any device without dynamic color - keeps today's look instead of picking up the leftover Nextcloud-blue default from before seed colors did anything visible.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:lucide_icons_flutter/lucide_icons.dart';
|
||||
import 'package:noo/theme/app_theme.dart';
|
||||
import 'package:noo/theme/design_tokens.dart';
|
||||
import 'package:noo/widgets/noo/core/noo_avatar.dart';
|
||||
import 'package:noo/widgets/noo/core/noo_badge.dart';
|
||||
@@ -17,6 +18,45 @@ import 'noo_test_utils.dart';
|
||||
void main() {
|
||||
setUpNooTests();
|
||||
|
||||
group('NooColors.fromSeed', () {
|
||||
test('the default accent returns the untouched fixed palette', () {
|
||||
expect(
|
||||
identical(
|
||||
NooColors.fromSeed(AppTheme.defaultAccent, Brightness.light),
|
||||
NooColors.light,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
expect(
|
||||
identical(
|
||||
NooColors.fromSeed(AppTheme.defaultAccent, Brightness.dark),
|
||||
NooColors.dark,
|
||||
),
|
||||
isTrue,
|
||||
);
|
||||
});
|
||||
|
||||
test('a custom seed retints only the accent roles', () {
|
||||
const seed = Color(0xFF009688); // Ocean Teal
|
||||
final light = NooColors.fromSeed(seed, Brightness.light);
|
||||
expect(light.accent, seed);
|
||||
expect(light.accentText, seed);
|
||||
expect(light.accentSoft, isNot(NooColors.light.accentSoft));
|
||||
// The rest of the palette is untouched - a named accent choice
|
||||
// retints the brand color, it doesn't reshape the surface.
|
||||
expect(light.bg, NooColors.light.bg);
|
||||
expect(light.surface, NooColors.light.surface);
|
||||
expect(light.fg1, NooColors.light.fg1);
|
||||
|
||||
final dark = NooColors.fromSeed(seed, Brightness.dark);
|
||||
expect(dark.accent, seed);
|
||||
// Dark accentText is a lighter/desaturated tint for contrast, not
|
||||
// the raw seed itself.
|
||||
expect(dark.accentText, isNot(seed));
|
||||
expect(dark.bg, NooColors.dark.bg);
|
||||
});
|
||||
});
|
||||
|
||||
group('NooAvatar', () {
|
||||
testNooWidgets('current user uses accent-soft/accent-text', (
|
||||
tester,
|
||||
|
||||
@@ -15,10 +15,13 @@ void setUpNooTests() {
|
||||
/// Themes built through the real [AppTheme] (non-dynamic), so the
|
||||
/// [NooColors] extension is registered exactly as in the app. Built lazily
|
||||
/// inside test bodies - AppTheme touches Google Fonts, which needs the test
|
||||
/// binding to exist first.
|
||||
/// binding to exist first. Seeded with [AppTheme.defaultAccent] (not just
|
||||
/// any color) so component tests exercise the exact fixed [NooColors.light]/
|
||||
/// `.dark` palette their color assertions are written against, rather than
|
||||
/// a [NooColors.fromSeed] retint - see its doc comment.
|
||||
ThemeData nooTheme(Brightness brightness) => brightness == Brightness.light
|
||||
? AppTheme.light(AppTheme.defaultNextcloudBlue, useDynamicColor: false)
|
||||
: AppTheme.dark(AppTheme.defaultNextcloudBlue, useDynamicColor: false);
|
||||
? AppTheme.light(AppTheme.defaultAccent, useDynamicColor: false)
|
||||
: AppTheme.dark(AppTheme.defaultAccent, useDynamicColor: false);
|
||||
|
||||
Future<void> pumpNoo(
|
||||
WidgetTester tester,
|
||||
@@ -43,7 +46,8 @@ Future<void> pumpNoo(
|
||||
/// Runs [body] once per theme, each as its own named test.
|
||||
void testNooWidgets(
|
||||
String description,
|
||||
Future<void> Function(WidgetTester tester, ThemeData theme, NooColors colors) body,
|
||||
Future<void> Function(WidgetTester tester, ThemeData theme, NooColors colors)
|
||||
body,
|
||||
) {
|
||||
for (final brightness in Brightness.values) {
|
||||
testWidgets('$description (${brightness.name})', (tester) async {
|
||||
@@ -59,7 +63,10 @@ BoxDecoration decorationOf(WidgetTester tester, Finder finder) {
|
||||
final boxes = find.ancestor(
|
||||
of: finder,
|
||||
matching: find.byWidgetPredicate(
|
||||
(w) => w is DecoratedBox && w.decoration is BoxDecoration && (w.decoration as BoxDecoration).color != null,
|
||||
(w) =>
|
||||
w is DecoratedBox &&
|
||||
w.decoration is BoxDecoration &&
|
||||
(w.decoration as BoxDecoration).color != null,
|
||||
),
|
||||
matchRoot: true,
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user