From 484417e329ec25fb05b5870561be3459e9697883 Mon Sep 17 00:00:00 2001 From: Pascal Welsch Date: Mon, 3 Jan 2022 00:47:37 +0100 Subject: [PATCH 1/3] Add inheritMaterialTheme and inheritCupertinoTheme to show method It is impossible to detect if a user configured cupertino theme is present or not. Thus users should inform wiredash about which theme to grab the values from --- example/lib/main.dart | 2 +- lib/src/common/utils/context_cache.dart | 21 ++++++++++ lib/src/feedback/wiredash_model.dart | 8 ++++ lib/src/wiredash_controller.dart | 51 +++++++++++-------------- lib/src/wiredash_widget.dart | 13 ++++++- 5 files changed, 63 insertions(+), 32 deletions(-) create mode 100644 lib/src/common/utils/context_cache.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index 36c5bd0c..8042634b 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -139,7 +139,7 @@ class _HomePage extends StatelessWidget { /// Since the `Wiredash` widget is at the root of the widget tree this /// method can be accessed from anywhere in the code. onPressed: () { - Wiredash.of(context).show(context); + Wiredash.of(context).show(inheritMaterialTheme: true); }, child: Icon(Icons.feedback_outlined), ), diff --git a/lib/src/common/utils/context_cache.dart b/lib/src/common/utils/context_cache.dart new file mode 100644 index 00000000..6eafa583 --- /dev/null +++ b/lib/src/common/utils/context_cache.dart @@ -0,0 +1,21 @@ +import 'package:flutter/widgets.dart'; +import 'package:wiredash/wiredash.dart'; + +/// Use to bind the [BuildContext] to the current [Wiredash] widget +final Expando _expando = Expando(); + +extension WiredashWithBuildContext on Wiredash { + /// The context that is attached to the Wiredash widget using + /// `Wiredash.of(context)` + BuildContext? get showBuildContext { + return _expando[this] as BuildContext?; + } + + /// Attach a [BuildContext] to the this [Wiredash] widget + /// + /// This setter creates a weak reference to the context. It is free for + /// garbage collection once the [Wiredash] widget gets garbage collected + set showBuildContext(BuildContext? context) { + _expando[this] = context; + } +} diff --git a/lib/src/feedback/wiredash_model.dart b/lib/src/feedback/wiredash_model.dart index 8c52a0d0..ddd2b98a 100644 --- a/lib/src/feedback/wiredash_model.dart +++ b/lib/src/feedback/wiredash_model.dart @@ -4,6 +4,8 @@ import 'package:wiredash/src/common/options/feedback_options.dart'; import 'package:wiredash/src/common/services/services.dart'; import 'package:wiredash/src/common/theme/wiredash_theme_data.dart'; import 'package:wiredash/src/feedback/data/retrying_feedback_submitter.dart'; +import 'package:wiredash/src/wiredash_controller.dart'; +import 'package:wiredash/src/wiredash_widget.dart'; class WiredashModel with ChangeNotifier { WiredashModel(this.services); @@ -29,6 +31,12 @@ class WiredashModel with ChangeNotifier { notifyListeners(); } + /// Temporary theme that overrides the `Wiredash.theme` property for the + /// current 'show' session + /// + /// Also see + /// - [Wiredash.of] + /// - [WiredashController.show] WiredashThemeData? _themeFromContext; WiredashThemeData? get themeFromContext => _themeFromContext; diff --git a/lib/src/wiredash_controller.dart b/lib/src/wiredash_controller.dart index 1a0c0f46..b73e2b30 100644 --- a/lib/src/wiredash_controller.dart +++ b/lib/src/wiredash_controller.dart @@ -1,6 +1,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:wiredash/src/common/build_info/build_info.dart'; +import 'package:wiredash/src/common/utils/context_cache.dart'; import 'package:wiredash/src/feedback/wiredash_model.dart'; import 'package:wiredash/wiredash.dart'; @@ -86,41 +87,33 @@ class WiredashController { /// /// If a Wiredash feedback flow is already active (=a feedback sheet is open), /// does nothing. - void show([BuildContext? context]) { + void show({bool? inheritMaterialTheme, bool? inheritCupertinoTheme}) { + assert( + () { + if (inheritCupertinoTheme == true && inheritMaterialTheme == true) { + throw 'You can not enabled both, ' + 'inheritCupertinoTheme and inheritMaterialTheme'; + } + return true; + }(), + ); // reset theme at every call _model.themeFromContext = null; + final context = _model.services.wiredashWidget.showBuildContext; if (context != null) { // generate theme from current context - final materialTheme = Theme.of(context); - final cupertinoTheme = CupertinoTheme.of(context); - final materialColor = materialTheme.colorScheme.secondary; - final cupertinoColor = cupertinoTheme.primaryColor; - - late Color color; - const defaultCupertinoTheme = CupertinoThemeData(); - // When the primary cupertino color is set, use this one - if (defaultCupertinoTheme.primaryColor != cupertinoColor) { - color = cupertinoColor; - } else { - // always fallback to material color, which is more likely to be set - // in the flutter world - color = materialColor; - } - - late Brightness brightness; - if (materialTheme.brightness == Brightness.dark || - cupertinoTheme.brightness == Brightness.dark) { - // When one is dark, assume either of them is explicitly set - brightness = Brightness.dark; - } else { - // fallback to light - brightness = Brightness.light; + if (inheritMaterialTheme == true) { + final materialTheme = Theme.of(context); + _model.themeFromContext = WiredashThemeData.fromColor( + color: materialTheme.colorScheme.secondary, + brightness: materialTheme.brightness, + ); } - - if (materialTheme != ThemeData.fallback()) { + if (inheritCupertinoTheme == true) { + final cupertinoTheme = CupertinoTheme.of(context); _model.themeFromContext = WiredashThemeData.fromColor( - color: color, - brightness: brightness, + color: cupertinoTheme.primaryColor, + brightness: cupertinoTheme.brightness ?? Brightness.light, ); } } diff --git a/lib/src/wiredash_widget.dart b/lib/src/wiredash_widget.dart index 1bc34f38..02b90235 100644 --- a/lib/src/wiredash_widget.dart +++ b/lib/src/wiredash_widget.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:wiredash/src/common/options/wiredash_options.dart'; import 'package:wiredash/src/common/services/services.dart'; import 'package:wiredash/src/common/theme/wiredash_theme.dart'; +import 'package:wiredash/src/common/utils/context_cache.dart'; import 'package:wiredash/src/common/utils/project_credential_validator.dart'; import 'package:wiredash/src/common/widgets/screencapture.dart'; import 'package:wiredash/src/feedback/backdrop/backdrop_controller_provider.dart'; @@ -121,7 +122,9 @@ class Wiredash extends StatefulWidget { static WiredashController? maybeOf(BuildContext context) { final state = context.findAncestorStateOfType(); if (state == null) return null; - + // cache context in a short lived object like the widget + // it gets later retrieved by the `show()` method to read the theme + state.widget.showBuildContext = context; return WiredashController(state._services.wiredashModel); } @@ -135,7 +138,13 @@ class Wiredash extends StatefulWidget { /// ``` static WiredashController of(BuildContext context) { final state = context.findAncestorStateOfType(); - return WiredashController(state!._services.wiredashModel); + if (state == null) { + throw StateError('Could not find WiredashState in ancestors'); + } + // cache context in a short lived object like the widget + // it gets later retrieved by the `show()` method to read the theme + state.widget.showBuildContext = context; + return WiredashController(state._services.wiredashModel); } } From 11180e8c172c0289a5cf9fd82f99f19dbafc4806 Mon Sep 17 00:00:00 2001 From: Pascal Welsch Date: Mon, 3 Jan 2022 00:49:15 +0100 Subject: [PATCH 2/3] Favour theme from show() --- lib/src/wiredash_widget.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/src/wiredash_widget.dart b/lib/src/wiredash_widget.dart index 02b90235..e890a985 100644 --- a/lib/src/wiredash_widget.dart +++ b/lib/src/wiredash_widget.dart @@ -210,8 +210,8 @@ class WiredashState extends State { @override Widget build(BuildContext context) { - final theme = widget.theme ?? - _services.wiredashModel.themeFromContext ?? + final theme = _services.wiredashModel.themeFromContext ?? + widget.theme ?? WiredashThemeData(); // Assign app an key so it doesn't lose state when wrapped, unwrapped From a468ac76c722a5e8ef5ce1d5712b9ccd39dbecb8 Mon Sep 17 00:00:00 2001 From: Pascal Welsch Date: Mon, 3 Jan 2022 01:09:55 +0100 Subject: [PATCH 3/3] Add show method to changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5dcb0100..638df3f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ * Hide backdrop content in screenshot mode * [#165](https://github.com/wiredashio/wiredash-sdk/pull/165) Validate email address * [#166](https://github.com/wiredashio/wiredash-sdk/pull/166) Make email address optional. Set `WiredashFeedbackOptions(askForUserEmail: true)` to enable it +* [#167](https://github.com/wiredashio/wiredash-sdk/pull/167) New `inheritMaterialTheme` and `inheritCupertinoTheme` properties for `Wiredash.of(context).show()` to inherit the theme ## 1.0.0-alpha.1 - A Whole New World * Completely rewritten UI layer