diff --git a/.metadata b/.metadata index 3cacdddcd..3eef71ede 100644 --- a/.metadata +++ b/.metadata @@ -1,10 +1,30 @@ # This file tracks properties of this Flutter project. # Used by Flutter tool to assess capabilities and perform upgrades etc. # -# This file should be version controlled and should not be manually edited. +# This file should be version controlled. version: - revision: ba78539bdb74dd05144a2490c453383078f81cdd - channel: master + revision: ffccd96b62ee8cec7740dab303538c5fc26ac543 + channel: stable -project_type: package +project_type: plugin + +# Tracks metadata for the flutter migrate command +migration: + platforms: + - platform: root + create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543 + base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543 + - platform: linux + create_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543 + base_revision: ffccd96b62ee8cec7740dab303538c5fc26ac543 + + # User provided section + + # List of Local paths (relative to this file) that should be + # ignored by the migrate tool. + # + # Files that are not part of the templates will be ignored by default. + unmanaged_files: + - 'lib/main.dart' + - 'ios/Runner.xcodeproj/project.pbxproj' diff --git a/example/linux/flutter/generated_plugin_registrant.cc b/example/linux/flutter/generated_plugin_registrant.cc index ec4c9730b..f1ec7c3e7 100644 --- a/example/linux/flutter/generated_plugin_registrant.cc +++ b/example/linux/flutter/generated_plugin_registrant.cc @@ -7,9 +7,13 @@ #include "generated_plugin_registrant.h" #include +#include void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) handy_window_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "HandyWindowPlugin"); handy_window_plugin_register_with_registrar(handy_window_registrar); + g_autoptr(FlPluginRegistrar) yaru_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "YaruPlugin"); + yaru_plugin_register_with_registrar(yaru_registrar); } diff --git a/example/linux/flutter/generated_plugins.cmake b/example/linux/flutter/generated_plugins.cmake index 8dcfb394d..5a63161c0 100644 --- a/example/linux/flutter/generated_plugins.cmake +++ b/example/linux/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST handy_window + yaru ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/lib/src/settings.dart b/lib/src/settings.dart new file mode 100644 index 000000000..2b29508f4 --- /dev/null +++ b/lib/src/settings.dart @@ -0,0 +1,32 @@ +import 'package:flutter/foundation.dart'; +import 'package:flutter/services.dart'; + +abstract class YaruSettings { + const YaruSettings._(); + const factory YaruSettings() = YaruMethodChannel; + + Future getThemeName(); + Stream get themeNameChanged; +} + +class YaruMethodChannel extends YaruSettings { + const YaruMethodChannel() : super._(); + + @visibleForTesting + final methodChannel = const MethodChannel('yaru'); + + @visibleForTesting + final eventChannel = const EventChannel('yaru/events'); + + @override + Future getThemeName() async { + return methodChannel.invokeMethod('getThemeName'); + } + + @override + Stream get themeNameChanged { + return eventChannel + .receiveBroadcastStream('themeNameChanged') + .map((event) => event as String?); + } +} diff --git a/lib/src/widgets/inherited_theme.dart b/lib/src/widgets/inherited_theme.dart index fa201f6c9..569375f73 100644 --- a/lib/src/widgets/inherited_theme.dart +++ b/lib/src/widgets/inherited_theme.dart @@ -1,11 +1,9 @@ import 'dart:async'; -import 'package:dbus/dbus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:gsettings/gsettings.dart'; import 'package:platform/platform.dart'; - +import 'package:yaru/src/settings.dart'; import 'package:yaru/yaru.dart'; YaruVariant? _detectYaruVariant(Platform platform) { @@ -84,7 +82,7 @@ class YaruTheme extends StatefulWidget { this.child, this.data = const YaruThemeData(), @visibleForTesting Platform? platform, - @visibleForTesting GSettings? settings, + @visibleForTesting YaruSettings? settings, }) : assert( builder != null || child != null, 'Either builder or child must be provided', @@ -102,7 +100,7 @@ class YaruTheme extends StatefulWidget { final YaruThemeData data; final Platform _platform; - final GSettings? _settings; + final YaruSettings? _settings; /// The data from the closest [YaruTheme] instance that encloses the given /// context. @@ -122,18 +120,16 @@ class YaruTheme extends StatefulWidget { class _YaruThemeState extends State { YaruVariant? _variant; - GSettings? _settings; - StreamSubscription>? _subscription; + YaruSettings? _settings; + StreamSubscription? _subscription; @override void initState() { super.initState(); if (widget.data.variant == null && !kIsWeb && widget._platform.isLinux) { - _settings = widget._settings ?? GSettings('org.gnome.desktop.interface'); - _subscription = _settings!.keysChanged.listen((keys) { - if (keys.contains('gtk-theme')) { - updateVariant(); - } + _settings = widget._settings ?? const YaruSettings(); + _subscription = _settings!.themeNameChanged.listen((name) { + updateVariant(name); }); updateVariant(); } @@ -143,34 +139,31 @@ class _YaruThemeState extends State { void dispose() { super.dispose(); _subscription?.cancel(); - if (widget._settings == null) { - _settings?.close(); - } } // "Yaru-prussiangreen-dark" => YaruAccent.prussianGreen - YaruVariant? resolveVariant(String name) { - if (name.endsWith('-dark')) { - name = name.substring(0, name.length - 5); + YaruVariant? resolveVariant(String? name) { + if (name?.endsWith('-dark') == true) { + name = name!.substring(0, name.length - 5); } - if (name.startsWith('Yaru-')) { - name = name.substring(5); + if (name?.startsWith('Yaru-') == true) { + name = name!.substring(5); } if (name == 'Yaru') { return YaruVariant.orange; } for (final value in YaruVariant.values) { - if (value.name.toLowerCase() == name.toLowerCase()) { + if (value.name.toLowerCase() == name?.toLowerCase()) { return value; } } return _detectYaruVariant(widget._platform); } - Future updateVariant() async { + Future updateVariant([String? value]) async { assert(!kIsWeb && widget._platform.isLinux); - final name = await _settings?.get('gtk-theme') as DBusString; - setState(() => _variant = resolveVariant(name.value)); + final name = value ?? await _settings?.getThemeName(); + setState(() => _variant = resolveVariant(name)); } ThemeMode resolveMode() { diff --git a/linux/CMakeLists.txt b/linux/CMakeLists.txt new file mode 100644 index 000000000..0be9b4022 --- /dev/null +++ b/linux/CMakeLists.txt @@ -0,0 +1,47 @@ +# The Flutter tooling requires that developers have CMake 3.10 or later +# installed. You should not increase this version, as doing so will cause +# the plugin to fail to compile for some customers of the plugin. +cmake_minimum_required(VERSION 3.10) + +# Project-level configuration. +set(PROJECT_NAME "yaru") +project(${PROJECT_NAME} LANGUAGES CXX) + +# This value is used when generating builds using this plugin, so it must +# not be changed. +set(PLUGIN_NAME "yaru_plugin") + +# Define the plugin library target. Its name must not be changed (see comment +# on PLUGIN_NAME above). +# +# Any new source files that you add to the plugin should be added here. +add_library(${PLUGIN_NAME} SHARED + "yaru_plugin.cc" +) + +# Apply a standard set of build settings that are configured in the +# application-level CMakeLists.txt. This can be removed for plugins that want +# full control over build settings. +apply_standard_settings(${PLUGIN_NAME}) + +# Symbols are hidden by default to reduce the chance of accidental conflicts +# between plugins. This should not be removed; any symbols that should be +# exported should be explicitly exported with the FLUTTER_PLUGIN_EXPORT macro. +set_target_properties(${PLUGIN_NAME} PROPERTIES + CXX_VISIBILITY_PRESET hidden) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) + +# Source include directories and library dependencies. Add any plugin-specific +# dependencies here. +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) +target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) + +# List of absolute paths to libraries that should be bundled with the plugin. +# This list could contain prebuilt libraries, or libraries created by an +# external build triggered from this build file. +set(yaru_bundled_libraries + "" + PARENT_SCOPE +) diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc new file mode 100644 index 000000000..e71a16d23 --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.cc @@ -0,0 +1,11 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#include "generated_plugin_registrant.h" + + +void fl_register_plugins(FlPluginRegistry* registry) { +} diff --git a/linux/flutter/generated_plugin_registrant.h b/linux/flutter/generated_plugin_registrant.h new file mode 100644 index 000000000..e0f0a47bc --- /dev/null +++ b/linux/flutter/generated_plugin_registrant.h @@ -0,0 +1,15 @@ +// +// Generated file. Do not edit. +// + +// clang-format off + +#ifndef GENERATED_PLUGIN_REGISTRANT_ +#define GENERATED_PLUGIN_REGISTRANT_ + +#include + +// Registers Flutter plugins. +void fl_register_plugins(FlPluginRegistry* registry); + +#endif // GENERATED_PLUGIN_REGISTRANT_ diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake new file mode 100644 index 000000000..2e1de87a7 --- /dev/null +++ b/linux/flutter/generated_plugins.cmake @@ -0,0 +1,23 @@ +# +# Generated file, do not edit. +# + +list(APPEND FLUTTER_PLUGIN_LIST +) + +list(APPEND FLUTTER_FFI_PLUGIN_LIST +) + +set(PLUGIN_BUNDLED_LIBRARIES) + +foreach(plugin ${FLUTTER_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${plugin}/linux plugins/${plugin}) + target_link_libraries(${BINARY_NAME} PRIVATE ${plugin}_plugin) + list(APPEND PLUGIN_BUNDLED_LIBRARIES $) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${plugin}_bundled_libraries}) +endforeach(plugin) + +foreach(ffi_plugin ${FLUTTER_FFI_PLUGIN_LIST}) + add_subdirectory(flutter/ephemeral/.plugin_symlinks/${ffi_plugin}/linux plugins/${ffi_plugin}) + list(APPEND PLUGIN_BUNDLED_LIBRARIES ${${ffi_plugin}_bundled_libraries}) +endforeach(ffi_plugin) diff --git a/linux/include/yaru/yaru_plugin.h b/linux/include/yaru/yaru_plugin.h new file mode 100644 index 000000000..b285b4923 --- /dev/null +++ b/linux/include/yaru/yaru_plugin.h @@ -0,0 +1,26 @@ +#ifndef FLUTTER_PLUGIN_YARU_PLUGIN_H_ +#define FLUTTER_PLUGIN_YARU_PLUGIN_H_ + +#include + +G_BEGIN_DECLS + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __attribute__((visibility("default"))) +#else +#define FLUTTER_PLUGIN_EXPORT +#endif + +typedef struct _YaruPlugin YaruPlugin; +typedef struct { + GObjectClass parent_class; +} YaruPluginClass; + +FLUTTER_PLUGIN_EXPORT GType yaru_plugin_get_type(); + +FLUTTER_PLUGIN_EXPORT void yaru_plugin_register_with_registrar( + FlPluginRegistrar* registrar); + +G_END_DECLS + +#endif // FLUTTER_PLUGIN_YARU_PLUGIN_H_ diff --git a/linux/yaru_plugin.cc b/linux/yaru_plugin.cc new file mode 100644 index 000000000..82b44383f --- /dev/null +++ b/linux/yaru_plugin.cc @@ -0,0 +1,108 @@ +#include "include/yaru/yaru_plugin.h" + +#include +#include + +#define YARU_PLUGIN(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), yaru_plugin_get_type(), YaruPlugin)) + +struct _YaruPlugin { + GObject parent_instance; + gint theme_name_changed_id; +}; + +G_DEFINE_TYPE(YaruPlugin, yaru_plugin, g_object_get_type()) + +static FlValue* get_theme_name() { + GtkSettings* settings = gtk_settings_get_default(); + if (settings == nullptr) { + return fl_value_new_null(); + } + + g_autofree gchar* value = nullptr; + g_object_get(settings, "gtk-theme-name", &value, nullptr); + return fl_value_new_string(value); +} + +// Called when a method call is received from Flutter. +static void yaru_plugin_handle_method_call(YaruPlugin* self, + FlMethodCall* method_call) { + g_autoptr(FlMethodResponse) response = nullptr; + + const gchar* method = fl_method_call_get_name(method_call); + + if (strcmp(method, "getThemeName") == 0) { + g_autoptr(FlValue) result = get_theme_name(); + response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); + } else { + response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); + } + + fl_method_call_respond(method_call, response, nullptr); +} + +static void yaru_plugin_dispose(GObject* object) { + G_OBJECT_CLASS(yaru_plugin_parent_class)->dispose(object); +} + +static void yaru_plugin_class_init(YaruPluginClass* klass) { + G_OBJECT_CLASS(klass)->dispose = yaru_plugin_dispose; +} + +static void yaru_plugin_init(YaruPlugin* self) {} + +static void method_call_cb(FlMethodChannel* channel, FlMethodCall* method_call, + gpointer user_data) { + YaruPlugin* plugin = YARU_PLUGIN(user_data); + yaru_plugin_handle_method_call(plugin, method_call); +} + +static void theme_name_changed_cb(GObject* object, GParamSpec* pspec, + gpointer user_data) { + FlEventChannel* channel = FL_EVENT_CHANNEL(user_data); + g_autoptr(FlValue) event = get_theme_name(); + fl_event_channel_send(channel, event, nullptr, nullptr); +} + +static FlMethodErrorResponse* listen_events_cb(FlEventChannel* channel, + FlValue* args, + gpointer user_data) { + YaruPlugin* plugin = YARU_PLUGIN(user_data); + if (plugin->theme_name_changed_id == 0) { + plugin->theme_name_changed_id = + g_signal_connect(gtk_settings_get_default(), "notify::gtk-theme-name", + G_CALLBACK(theme_name_changed_cb), channel); + } + return nullptr; +} + +static FlMethodErrorResponse* cancel_events_cb(FlEventChannel* channel, + FlValue* args, + gpointer user_data) { + YaruPlugin* plugin = YARU_PLUGIN(user_data); + if (plugin->theme_name_changed_id != 0) { + g_signal_handler_disconnect(gtk_settings_get_default(), + plugin->theme_name_changed_id); + plugin->theme_name_changed_id = 0; + } + return nullptr; +} + +void yaru_plugin_register_with_registrar(FlPluginRegistrar* registrar) { + g_autoptr(YaruPlugin) plugin = + YARU_PLUGIN(g_object_new(yaru_plugin_get_type(), nullptr)); + + g_autoptr(FlStandardMethodCodec) codec = fl_standard_method_codec_new(); + FlBinaryMessenger* messenger = fl_plugin_registrar_get_messenger(registrar); + + g_autoptr(FlMethodChannel) method_channel = + fl_method_channel_new(messenger, "yaru", FL_METHOD_CODEC(codec)); + fl_method_channel_set_method_call_handler( + method_channel, method_call_cb, g_object_ref(plugin), g_object_unref); + + g_autoptr(FlEventChannel) event_channel = + fl_event_channel_new(messenger, "yaru/events", FL_METHOD_CODEC(codec)); + fl_event_channel_set_stream_handlers(event_channel, listen_events_cb, + cancel_events_cb, g_object_ref(plugin), + g_object_unref); +} diff --git a/pubspec.yaml b/pubspec.yaml index a3a68d735..18e7941da 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -10,10 +10,8 @@ environment: flutter: ">=3.3.0" dependencies: - dbus: ^0.7.0 flutter: sdk: flutter - gsettings: ^0.2.5 platform: ^3.1.0 yaru_colors: ^0.1.0 @@ -48,3 +46,7 @@ flutter: - asset: packages/yaru/src/text/fonts/Ubuntu-BI.ttf weight: 700 style: italic + plugin: + platforms: + linux: + pluginClass: YaruPlugin diff --git a/test/settings_test.dart b/test/settings_test.dart new file mode 100644 index 000000000..e2e56676e --- /dev/null +++ b/test/settings_test.dart @@ -0,0 +1,48 @@ +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:yaru/src/settings.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + test('getThemeName', () async { + const settings = YaruMethodChannel(); + settings.methodChannel.setMockMethodCallHandler((methodCall) async { + expect(methodCall, isMethodCall('getThemeName', arguments: null)); + return 'foo'; + }); + expect(await settings.getThemeName(), 'foo'); + }); + + test('themeNameChanged', () async { + const settings = YaruMethodChannel(); + + const codec = StandardMethodCodec(); + final channel = settings.eventChannel.name; + final messenger = + TestDefaultBinaryMessengerBinding.instance!.defaultBinaryMessenger; + + Future emitEvent(Object? event) { + return messenger.handlePlatformMessage( + channel, + codec.encodeSuccessEnvelope(event), + (_) {}, + ); + } + + messenger.setMockMessageHandler(channel, (message) async { + expect( + codec.decodeMethodCall(message), + anyOf([ + isMethodCall('listen', arguments: 'themeNameChanged'), + isMethodCall('cancel', arguments: null), + ]), + ); + return codec.encodeSuccessEnvelope(null); + }); + + settings.themeNameChanged.listen(expectAsync1((ev) => expect(ev, 'bar'))); + + await emitEvent('bar'); + }); +} diff --git a/test/widget_test.dart b/test/widget_test.dart index 3af2fd246..850ea9274 100644 --- a/test/widget_test.dart +++ b/test/widget_test.dart @@ -1,17 +1,16 @@ import 'dart:async'; -import 'package:dbus/dbus.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; -import 'package:gsettings/gsettings.dart'; import 'package:mockito/annotations.dart'; import 'package:mockito/mockito.dart'; import 'package:platform/platform.dart'; import 'package:yaru/yaru.dart'; +import 'package:yaru/src/settings.dart'; import 'widget_test.mocks.dart'; -@GenerateMocks([GSettings]) +@GenerateMocks([YaruSettings]) void main() { testWidgets('variant', (tester) async { await tester.pumpTheme(variant: YaruVariant.blue); @@ -21,46 +20,45 @@ void main() { group('gtk-theme', () { testWidgets('unknown', (tester) async { - final settings = createMockGSettings(theme: ''); + final settings = createMockSettings(theme: ''); await tester.pumpTheme(settings: settings); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, null); }); testWidgets('yaru', (tester) async { - final settings = createMockGSettings(theme: 'Yaru'); + final settings = createMockSettings(theme: 'Yaru'); await tester.pumpTheme(settings: settings); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.orange); }); testWidgets('dark', (tester) async { - final settings = createMockGSettings(theme: 'Yaru-dark'); + final settings = createMockSettings(theme: 'Yaru-dark'); await tester.pumpTheme(settings: settings); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.orange); }); testWidgets('color', (tester) async { - final settings = createMockGSettings(theme: 'Yaru-blue'); + final settings = createMockSettings(theme: 'Yaru-blue'); await tester.pumpTheme(settings: settings); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.blue); }); testWidgets('change', (tester) async { - final settings = createMockGSettings(theme: 'Yaru-blue'); - final keysChanged = StreamController>(sync: true); - addTearDown(keysChanged.close); - when(settings.keysChanged).thenAnswer((_) => keysChanged.stream); + final settings = createMockSettings(theme: 'Yaru-blue'); + final themeNameChanged = StreamController(sync: true); + addTearDown(themeNameChanged.close); + when(settings.themeNameChanged) + .thenAnswer((_) => themeNameChanged.stream); await tester.pumpTheme(settings: settings); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.blue); - when(settings.get('gtk-theme')) - .thenAnswer((_) async => const DBusString('Yaru-red')); - keysChanged.add(['gtk-theme']); + themeNameChanged.add('Yaru-red'); await tester.pump(); expect(YaruTheme.of(context).variant, YaruVariant.red); }); @@ -68,57 +66,57 @@ void main() { group('desktop', () { testWidgets('unknown', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'unknown', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, isNull); }); testWidgets('budgie', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'budgie-desktop', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.ubuntuBudgieBlue); }); testWidgets('ubuntu', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'GNOME:ubuntu', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.orange); }); testWidgets('kde', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'KDE', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.kubuntuBlue); }); testWidgets('lubuntu', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'LXQt', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.lubuntuBlue); }); testWidgets('mate', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'MATE', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.ubuntuMateGreen); }); testWidgets('xubuntu', (tester) async { - final settings = createMockGSettings(); + final settings = createMockSettings(); await tester.pumpTheme(desktop: 'XFCE', settings: settings); - await untilCalled(settings.get('gtk-theme')); + await untilCalled(settings.getThemeName()); final context = tester.element(find.byType(Container)); expect(YaruTheme.of(context).variant, YaruVariant.xubuntuBlue); }); @@ -153,10 +151,10 @@ void main() { }); } -MockGSettings createMockGSettings({String theme = ''}) { - final settings = MockGSettings(); - when(settings.keysChanged).thenAnswer((_) => const Stream.empty()); - when(settings.get('gtk-theme')).thenAnswer((_) async => DBusString(theme)); +MockYaruSettings createMockSettings({String theme = ''}) { + final settings = MockYaruSettings(); + when(settings.themeNameChanged).thenAnswer((_) => const Stream.empty()); + when(settings.getThemeName()).thenAnswer((_) async => theme); return settings; } @@ -166,7 +164,7 @@ extension ThemeTester on WidgetTester { bool? highContrast, ThemeMode? themeMode, String desktop = '', - GSettings? settings, + YaruSettings? settings, }) async { final data = YaruThemeData( variant: variant, diff --git a/test/widget_test.mocks.dart b/test/widget_test.mocks.dart index c07fc0b12..5994ecf86 100644 --- a/test/widget_test.mocks.dart +++ b/test/widget_test.mocks.dart @@ -1,12 +1,12 @@ -// Mocks generated by Mockito 5.1.0 from annotations +// Mocks generated by Mockito 5.3.0 from annotations // in yaru/test/widget_test.dart. // Do not manually edit this file. -import 'dart:async' as _i4; +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _i3; -import 'package:dbus/dbus.dart' as _i2; -import 'package:gsettings/src/gsettings.dart' as _i3; import 'package:mockito/mockito.dart' as _i1; +import 'package:yaru/src/settings.dart' as _i2; // ignore_for_file: type=lint // ignore_for_file: avoid_redundant_argument_values @@ -17,61 +17,22 @@ import 'package:mockito/mockito.dart' as _i1; // ignore_for_file: prefer_const_constructors // ignore_for_file: unnecessary_parenthesis // ignore_for_file: camel_case_types +// ignore_for_file: subtype_of_sealed_class -class _FakeDBusValue_0 extends _i1.Fake implements _i2.DBusValue {} - -/// A class which mocks [GSettings]. +/// A class which mocks [YaruSettings]. /// /// See the documentation for Mockito's code generation for more information. -class MockGSettings extends _i1.Mock implements _i3.GSettings { - MockGSettings() { +class MockYaruSettings extends _i1.Mock implements _i2.YaruSettings { + MockYaruSettings() { _i1.throwOnMissingStub(this); } @override - String get schemaName => - (super.noSuchMethod(Invocation.getter(#schemaName), returnValue: '') - as String); - @override - _i4.Stream> get keysChanged => (super.noSuchMethod( - Invocation.getter(#keysChanged), - returnValue: Stream>.empty()) as _i4.Stream>); - @override - _i4.Future> list() => - (super.noSuchMethod(Invocation.method(#list, []), - returnValue: Future>.value([])) - as _i4.Future>); - @override - _i4.Future<_i2.DBusValue> get(String? name) => - (super.noSuchMethod(Invocation.method(#get, [name]), - returnValue: Future<_i2.DBusValue>.value(_FakeDBusValue_0())) - as _i4.Future<_i2.DBusValue>); - @override - _i4.Future<_i2.DBusValue> getDefault(String? name) => - (super.noSuchMethod(Invocation.method(#getDefault, [name]), - returnValue: Future<_i2.DBusValue>.value(_FakeDBusValue_0())) - as _i4.Future<_i2.DBusValue>); - @override - _i4.Future isSet(String? name) => - (super.noSuchMethod(Invocation.method(#isSet, [name]), - returnValue: Future.value(false)) as _i4.Future); - @override - _i4.Future set(String? name, _i2.DBusValue? value) => - (super.noSuchMethod(Invocation.method(#set, [name, value]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i4.Future); - @override - _i4.Future unset(String? name) => - (super.noSuchMethod(Invocation.method(#unset, [name]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i4.Future); - @override - _i4.Future setAll(Map? values) => - (super.noSuchMethod(Invocation.method(#setAll, [values]), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i4.Future); + _i3.Stream get themeNameChanged => + (super.noSuchMethod(Invocation.getter(#themeNameChanged), + returnValue: _i3.Stream.empty()) as _i3.Stream); @override - _i4.Future close() => (super.noSuchMethod(Invocation.method(#close, []), - returnValue: Future.value(), - returnValueForMissingStub: Future.value()) as _i4.Future); + _i3.Future getThemeName() => + (super.noSuchMethod(Invocation.method(#getThemeName, []), + returnValue: _i3.Future.value()) as _i3.Future); }