From e74d4b053ae7b1d60b53db499b9a4d9b2c043783 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 16:35:25 +0200 Subject: [PATCH 01/10] fix: controls not working on touch devices --- .../flutter_deck_controls_listener.dart | 50 ++++++++++++++----- .../lib/src/flutter_deck_app.dart | 2 +- .../lib/src/flutter_deck_slide.dart | 1 + 3 files changed, 40 insertions(+), 13 deletions(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart index 6f764c6..3b7dd4c 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart @@ -24,11 +24,11 @@ class FlutterDeckControlsListener extends StatelessWidget { /// [child] is the widget that will be wrapped by this widget. It should be /// the root of the slide deck. /// - /// [notifier] is the [FlutterDeckControlsNotifier] that will be used to - /// control the slide deck. + /// [controlsNotifier] is the [FlutterDeckControlsNotifier] that will be used + /// to control the slide deck. const FlutterDeckControlsListener({ required this.child, - required this.notifier, + required this.controlsNotifier, super.key, }); @@ -36,7 +36,29 @@ class FlutterDeckControlsListener extends StatelessWidget { final Widget child; /// The notifier used to control the slide deck. - final FlutterDeckControlsNotifier notifier; + final FlutterDeckControlsNotifier controlsNotifier; + + void _onHorizontalSwipe(DragEndDetails? details) { + final velocity = details?.primaryVelocity; + + if (velocity == null) return; + + velocity > 0 ? controlsNotifier.previous() : controlsNotifier.next(); + } + + void _onMouseHover(PointerEvent event) { + controlsNotifier.showControls(); + } + + void _onTap() { + final controlsVisible = controlsNotifier.controlsVisible; + + controlsNotifier.showControls(); + + if (!controlsVisible) return; + + controlsNotifier.next(); + } @override Widget build(BuildContext context) { @@ -45,13 +67,17 @@ class FlutterDeckControlsListener extends StatelessWidget { Widget widget = Focus( autofocus: true, child: ListenableBuilder( - listenable: notifier, + listenable: controlsNotifier, builder: (context, child) => MouseRegion( - cursor: notifier.controlsVisible + cursor: controlsNotifier.controlsVisible ? MouseCursor.defer : SystemMouseCursors.none, - onHover: (_) => notifier.showControls(), - child: child, + onHover: _onMouseHover, + child: GestureDetector( + onHorizontalDragEnd: _onHorizontalSwipe, + onTap: _onTap, + child: child, + ), ), child: child, ), @@ -62,10 +88,10 @@ class FlutterDeckControlsListener extends StatelessWidget { if (controls.presenterToolbarVisible || shortcuts.enabled) { widget = Actions( actions: >{ - GoNextIntent: GoNextAction(notifier), - GoPreviousIntent: GoPreviousAction(notifier), - ToggleDrawerIntent: ToggleDrawerAction(notifier), - ToggleMarkerIntent: ToggleMarkerAction(notifier), + GoNextIntent: GoNextAction(controlsNotifier), + GoPreviousIntent: GoPreviousAction(controlsNotifier), + ToggleDrawerIntent: ToggleDrawerAction(controlsNotifier), + ToggleMarkerIntent: ToggleMarkerAction(controlsNotifier), }, child: widget, ); diff --git a/packages/flutter_deck/lib/src/flutter_deck_app.dart b/packages/flutter_deck/lib/src/flutter_deck_app.dart index 7037535..330165c 100644 --- a/packages/flutter_deck/lib/src/flutter_deck_app.dart +++ b/packages/flutter_deck/lib/src/flutter_deck_app.dart @@ -270,7 +270,7 @@ class _FlutterDeckAppState extends State { presenterController: _presenterController, themeNotifier: _themeNotifier, child: FlutterDeckControlsListener( - notifier: _controlsNotifier, + controlsNotifier: _controlsNotifier, child: FlutterDeckTheme( data: theme, child: child!, diff --git a/packages/flutter_deck/lib/src/flutter_deck_slide.dart b/packages/flutter_deck/lib/src/flutter_deck_slide.dart index 22c8a46..51df7dd 100644 --- a/packages/flutter_deck/lib/src/flutter_deck_slide.dart +++ b/packages/flutter_deck/lib/src/flutter_deck_slide.dart @@ -404,6 +404,7 @@ class FlutterDeckSlide extends FlutterDeckSlideWidget { notifier: context.flutterDeck.markerNotifier, child: Scaffold( drawer: const FlutterDeckDrawer(), + drawerEnableOpenDragGesture: false, body: _SlideBody(child: _builder(context)), ), ), From e0bf0d69066b9c17814f502ec067f8060738da4a Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 16:38:07 +0200 Subject: [PATCH 02/10] feat: add control gestures configuration --- .../flutter_deck_controls_configuration.dart | 48 +++++++++++++++++-- 1 file changed, 44 insertions(+), 4 deletions(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart index 432e2e4..8788b10 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart @@ -4,8 +4,8 @@ import 'package:flutter/widgets.dart'; /// The configuration for the slide deck controls. class FlutterDeckControlsConfiguration { /// Creates a configuration for the slide deck controls. By default, the - /// presenter toolbar is visible and the default keyboard controls are - /// enabled. + /// presenter toolbar is visible, the default keyboard controls are + /// enabled, and gestures are enabled on mobile platforms only. /// /// The default keyboard shortcuts are: /// - Next slide: \[ArrowRight\] @@ -19,22 +19,58 @@ class FlutterDeckControlsConfiguration { /// - [LogicalKeyboardKey] for a list of all available keys. const FlutterDeckControlsConfiguration({ this.presenterToolbarVisible = true, + this.gestures = const FlutterDeckGesturesConfiguration.mobileOnly(), this.shortcuts = const FlutterDeckShortcutsConfiguration(), }); /// Creates a configuration for the slide deck controls where they are /// disabled. const FlutterDeckControlsConfiguration.disabled() - : presenterToolbarVisible = false, - shortcuts = const FlutterDeckShortcutsConfiguration(enabled: false); + : this( + presenterToolbarVisible: false, + gestures: const FlutterDeckGesturesConfiguration.disabled(), + shortcuts: const FlutterDeckShortcutsConfiguration.disabled(), + ); /// Whether the presenter toolbar is visible or not. final bool presenterToolbarVisible; + /// The configuration for the slide deck controls gestures. + final FlutterDeckGesturesConfiguration gestures; + /// The configuration for the slide deck keyboard shortcuts. final FlutterDeckShortcutsConfiguration shortcuts; } +/// The configuration for the slide deck control gestures. +/// +/// The gesture controls are only available on [supportedPlatforms]. By default, +/// gestures are enabled on all platforms. +class FlutterDeckGesturesConfiguration { + /// Creates a configuration for the slide deck control gestures. + const FlutterDeckGesturesConfiguration({ + this.supportedPlatforms = const {...TargetPlatform.values}, + }); + + /// Creates a configuration for the slide deck control gestures where they are + /// disabled. + const FlutterDeckGesturesConfiguration.disabled() + : this(supportedPlatforms: const {}); + + /// Creates a configuration for the slide deck control gestures where they are + /// enabled on mobile platforms only. + const FlutterDeckGesturesConfiguration.mobileOnly() + : this( + supportedPlatforms: const { + TargetPlatform.android, + TargetPlatform.iOS, + }, + ); + + /// The platforms where gestures are enabled. + final Set supportedPlatforms; +} + /// The configuration for the slide deck keyboard shortcuts. class FlutterDeckShortcutsConfiguration { /// Creates a configuration for the slide deck keyboard shortcuts. By default, @@ -59,6 +95,10 @@ class FlutterDeckShortcutsConfiguration { const SingleActivator(LogicalKeyboardKey.period), }); + /// Creates a configuration for the slide deck keyboard shortcuts where they + /// are disabled. + const FlutterDeckShortcutsConfiguration.disabled() : this(enabled: false); + /// Whether keyboard shortcuts are enabled or not. final bool enabled; From 1855ab0e955758b83c270c838df6a256dbfede2d Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 16:53:19 +0200 Subject: [PATCH 03/10] feat: handle control gestures only on supported platforms --- .../flutter_deck_controls_configuration.dart | 4 ++++ .../flutter_deck_controls_listener.dart | 17 ++++++++++++----- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart index 8788b10..b60dbfd 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_configuration.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; @@ -69,6 +70,9 @@ class FlutterDeckGesturesConfiguration { /// The platforms where gestures are enabled. final Set supportedPlatforms; + + /// Whether gestures are enabled on the current platform or not. + bool get enabled => supportedPlatforms.contains(defaultTargetPlatform); } /// The configuration for the slide deck keyboard shortcuts. diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart index 3b7dd4c..5dfae45 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart @@ -63,6 +63,17 @@ class FlutterDeckControlsListener extends StatelessWidget { @override Widget build(BuildContext context) { final controls = context.flutterDeck.globalConfiguration.controls; + final gesturesEnabled = controls.gestures.enabled; + + Widget? gestureDetector(Widget? child) { + if (!gesturesEnabled) return child; + + return GestureDetector( + onHorizontalDragEnd: _onHorizontalSwipe, + onTap: _onTap, + child: child, + ); + } Widget widget = Focus( autofocus: true, @@ -73,11 +84,7 @@ class FlutterDeckControlsListener extends StatelessWidget { ? MouseCursor.defer : SystemMouseCursors.none, onHover: _onMouseHover, - child: GestureDetector( - onHorizontalDragEnd: _onHorizontalSwipe, - onTap: _onTap, - child: child, - ), + child: gestureDetector(child), ), child: child, ), From 1cbc164817b44f995a2143db079e073e31a69491 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 17:03:07 +0200 Subject: [PATCH 04/10] docs: update controls-related docs --- README.md | 1 + doc/website/source/get-started.md | 1 + doc/website/source/playback/controls.md | 18 +++++++++++++++--- packages/flutter_deck/README.md | 1 + .../flutter_deck_configuration.dart | 5 +++-- 5 files changed, 21 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index b91c7fc..4fad97d 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,7 @@ FlutterDeckApp( ), controls: const FlutterDeckControlsConfiguration( presenterToolbarVisible: true, + gestures: FlutterDeckGesturesConfiguration.mobileOnly(), shortcuts: FlutterDeckShortcutsConfiguration( enabled: true, nextSlide: SingleActivator(LogicalKeyboardKey.arrowRight), diff --git a/doc/website/source/get-started.md b/doc/website/source/get-started.md index 385cdf8..0026137 100644 --- a/doc/website/source/get-started.md +++ b/doc/website/source/get-started.md @@ -52,6 +52,7 @@ FlutterDeckApp( ), controls: const FlutterDeckControlsConfiguration( presenterToolbarVisible: true, + gestures: FlutterDeckGesturesConfiguration.mobileOnly(), shortcuts: FlutterDeckShortcutsConfiguration( enabled: true, nextSlide: SingleActivator(LogicalKeyboardKey.arrowRight), diff --git a/doc/website/source/playback/controls.md b/doc/website/source/playback/controls.md index d4a2239..7adb755 100644 --- a/doc/website/source/playback/controls.md +++ b/doc/website/source/playback/controls.md @@ -2,7 +2,8 @@ title: Controls navOrder: 1 --- -By default, every slide deck comes with a presenter toolbar that can be used to control the slide deck. Also, some of the controls can be accessed by using keyboard shortcuts. + +By default, every slide deck comes with a presenter toolbar that can be used to control the slide deck. Also, some of the controls can be accessed by using keyboard shortcuts or touch gestures. To disable all the controls (e.g. you use your own UI to control the slide deck), set the `controls` property for the slide deck configuration to `FlutterDeckControlsConfiguration.disabled()`: @@ -24,12 +25,23 @@ FlutterDeckConfiguration( ) ``` -To disable the keyboard shortcuts, set the `shortcuts` property to `FlutterDeckShortcutsConfiguration(enabled: false)`: +To disable the keyboard shortcuts, set the `shortcuts` property to `FlutterDeckShortcutsConfiguration.disabled()`: + +```dart +FlutterDeckConfiguration( + controls: const FlutterDeckControlsConfiguration( + shortcuts: FlutterDeckShortcutsConfiguration.disabled(), + ), + <...> +) +``` + +To disable the touch gestures, set the `gestures` property to `FlutterDeckGesturesConfiguration.disabled()`: ```dart FlutterDeckConfiguration( controls: const FlutterDeckControlsConfiguration( - shortcuts: FlutterDeckShortcutsConfiguration(enabled: false), + gestures: FlutterDeckGesturesConfiguration.disabled(), ), <...> ) diff --git a/packages/flutter_deck/README.md b/packages/flutter_deck/README.md index c666ccf..ac1e46b 100644 --- a/packages/flutter_deck/README.md +++ b/packages/flutter_deck/README.md @@ -88,6 +88,7 @@ FlutterDeckApp( ), controls: const FlutterDeckControlsConfiguration( presenterToolbarVisible: true, + gestures: FlutterDeckGesturesConfiguration.mobileOnly(), shortcuts: FlutterDeckShortcutsConfiguration( enabled: true, nextSlide: SingleActivator(LogicalKeyboardKey.arrowRight), diff --git a/packages/flutter_deck/lib/src/configuration/flutter_deck_configuration.dart b/packages/flutter_deck/lib/src/configuration/flutter_deck_configuration.dart index a7d0b3e..5c48e1c 100644 --- a/packages/flutter_deck/lib/src/configuration/flutter_deck_configuration.dart +++ b/packages/flutter_deck/lib/src/configuration/flutter_deck_configuration.dart @@ -38,8 +38,9 @@ class FlutterDeckConfiguration { /// for the [FlutterDeckSlide]. final FlutterDeckBackgroundConfiguration background; - /// Configures the controls for the slide deck. By default, the presenter - /// toolbar is visible and the default keyboard controls are enabled. + /// Configures the controls for the slide deck. By default, the presenter + /// toolbar is visible, the default keyboard controls are enabled, and + /// gestures are enabled on mobile platforms only. /// /// The default keyboard shortcuts are: /// - Next slide: \[ArrowRight\] From af8e3d81faa6d47948722bd749f1cafea4604938 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 21:36:19 +0200 Subject: [PATCH 05/10] feat: disable gestures when marker is enabled --- .../flutter_deck_controls_listener.dart | 42 ++++++++++++------- .../lib/src/flutter_deck_app.dart | 1 + 2 files changed, 29 insertions(+), 14 deletions(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart index 5dfae45..dc3a00e 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_listener.dart @@ -2,8 +2,10 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_deck/src/controls/actions/actions.dart'; import 'package:flutter_deck/src/controls/flutter_deck_controls_notifier.dart'; import 'package:flutter_deck/src/flutter_deck.dart'; +import 'package:flutter_deck/src/widgets/internal/internal.dart'; -/// A widget that handles controls (actions and shortcuts) for the slide deck. +/// A widget that handles controls (actions, gestures and shortcuts) for the +/// slide deck. /// /// Key bindings are defined in global deck configuration. The following /// shortcuts are supported: @@ -26,9 +28,13 @@ class FlutterDeckControlsListener extends StatelessWidget { /// /// [controlsNotifier] is the [FlutterDeckControlsNotifier] that will be used /// to control the slide deck. + /// + /// [markerNotifier] is the [FlutterDeckMarkerNotifier] that will be used to + /// control the slide deck's marker. const FlutterDeckControlsListener({ required this.child, required this.controlsNotifier, + required this.markerNotifier, super.key, }); @@ -38,6 +44,9 @@ class FlutterDeckControlsListener extends StatelessWidget { /// The notifier used to control the slide deck. final FlutterDeckControlsNotifier controlsNotifier; + /// The notifier used to control the slide deck's marker. + final FlutterDeckMarkerNotifier markerNotifier; + void _onHorizontalSwipe(DragEndDetails? details) { final velocity = details?.primaryVelocity; @@ -55,7 +64,7 @@ class FlutterDeckControlsListener extends StatelessWidget { controlsNotifier.showControls(); - if (!controlsVisible) return; + if (!controlsVisible || markerNotifier.enabled) return; controlsNotifier.next(); } @@ -63,17 +72,6 @@ class FlutterDeckControlsListener extends StatelessWidget { @override Widget build(BuildContext context) { final controls = context.flutterDeck.globalConfiguration.controls; - final gesturesEnabled = controls.gestures.enabled; - - Widget? gestureDetector(Widget? child) { - if (!gesturesEnabled) return child; - - return GestureDetector( - onHorizontalDragEnd: _onHorizontalSwipe, - onTap: _onTap, - child: child, - ); - } Widget widget = Focus( autofocus: true, @@ -84,7 +82,23 @@ class FlutterDeckControlsListener extends StatelessWidget { ? MouseCursor.defer : SystemMouseCursors.none, onHover: _onMouseHover, - child: gestureDetector(child), + child: ListenableBuilder( + listenable: markerNotifier, + builder: (context, child) { + if (!controls.gestures.enabled) return child!; + + if (markerNotifier.enabled) { + return GestureDetector(onTap: _onTap, child: child); + } + + return GestureDetector( + onHorizontalDragEnd: _onHorizontalSwipe, + onTap: _onTap, + child: child, + ); + }, + child: child, + ), ), child: child, ), diff --git a/packages/flutter_deck/lib/src/flutter_deck_app.dart b/packages/flutter_deck/lib/src/flutter_deck_app.dart index 330165c..5ca3bc4 100644 --- a/packages/flutter_deck/lib/src/flutter_deck_app.dart +++ b/packages/flutter_deck/lib/src/flutter_deck_app.dart @@ -271,6 +271,7 @@ class _FlutterDeckAppState extends State { themeNotifier: _themeNotifier, child: FlutterDeckControlsListener( controlsNotifier: _controlsNotifier, + markerNotifier: _markerNotifier, child: FlutterDeckTheme( data: theme, child: child!, From 404243b7a389e5018f13daa6d7017cc27e877177 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 22:07:55 +0200 Subject: [PATCH 06/10] fix: do not hide the control toolbar when the cursor is over it --- .../src/controls/flutter_deck_controls.dart | 53 +++++++++++-------- .../flutter_deck_controls_notifier.dart | 15 +++++- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart index fcaccc7..d5bd3c5 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart @@ -1,6 +1,7 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_deck/src/controls/actions/actions.dart'; +import 'package:flutter_deck/src/controls/flutter_deck_controls_notifier.dart'; import 'package:flutter_deck/src/controls/localized_shortcut_labeler.dart'; import 'package:flutter_deck/src/flutter_deck.dart'; import 'package:flutter_deck/src/flutter_deck_layout.dart'; @@ -53,9 +54,9 @@ class FlutterDeckControls extends StatelessWidget { children: [ child!, if (controlsNotifier.controlsVisible) - const Align( + Align( alignment: AlignmentDirectional.bottomCenter, - child: _Controls(), + child: _Controls(controlsNotifier: controlsNotifier), ), ], ), @@ -65,29 +66,37 @@ class FlutterDeckControls extends StatelessWidget { } class _Controls extends StatelessWidget { - const _Controls(); + const _Controls({ + required this.controlsNotifier, + }); + + final FlutterDeckControlsNotifier controlsNotifier; @override Widget build(BuildContext context) { - return Theme( - data: ThemeData.light(), - child: Builder( - builder: (context) => Container( - margin: FlutterDeckLayout.slidePadding, - padding: const EdgeInsets.all(4), - decoration: BoxDecoration( - borderRadius: BorderRadius.circular(32), - color: Theme.of(context).colorScheme.surface, - ), - child: const Row( - mainAxisSize: MainAxisSize.min, - children: [ - _PreviousButton(), - _SlideNumberButton(), - _NextButton(), - _MarkerControls(), - _OptionsMenuButton(), - ], + return MouseRegion( + onEnter: (_) => controlsNotifier.toggleControlsVisibleDuration(), + onExit: (_) => controlsNotifier.toggleControlsVisibleDuration(), + child: Theme( + data: ThemeData.light(), + child: Builder( + builder: (context) => Container( + margin: FlutterDeckLayout.slidePadding, + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(32), + color: Theme.of(context).colorScheme.surface, + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + _PreviousButton(), + _SlideNumberButton(), + _NextButton(), + _MarkerControls(), + _OptionsMenuButton(), + ], + ), ), ), ), diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart index fc123d1..8415f58 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart @@ -8,6 +8,8 @@ import 'package:flutter_deck/src/flutter_deck_router.dart'; import 'package:flutter_deck/src/widgets/internal/drawer/drawer.dart'; import 'package:flutter_deck/src/widgets/internal/marker/marker.dart'; +const _defaultControlsVisibleDuration = Duration(seconds: 3); + /// The [ChangeNotifier] used to control the slide deck and handle cursor and /// deck controls visibility. class FlutterDeckControlsNotifier @@ -33,6 +35,7 @@ class FlutterDeckControlsNotifier final FlutterDeckRouter _router; var _controlsVisible = false; + Duration _controlsVisibleDuration = _defaultControlsVisibleDuration; Timer? _controlsVisibleTimer; Set _disabledIntents = {}; @@ -116,7 +119,7 @@ class FlutterDeckControlsNotifier _setControlsVisible(true); _controlsVisibleTimer = Timer( - const Duration(seconds: 3), + _controlsVisibleDuration, () => _setControlsVisible(false), ); } @@ -130,6 +133,16 @@ class FlutterDeckControlsNotifier notifyListeners(); } + /// Toggle the cursor and controls visibility duration. + /// + /// The value toggles between 3 seconds and infinite (no auto-hide). + void toggleControlsVisibleDuration() { + _controlsVisibleDuration = + _controlsVisibleDuration > _defaultControlsVisibleDuration + ? _defaultControlsVisibleDuration + : const Duration(days: 1); // Infinite enough for this use case... + } + /// Whether the given [intent] is disabled. bool intentDisabled(Intent intent) => _disabledIntents.contains(intent); } From 81000f626b37b15c595536586bb325b7cf821d50 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 22:11:28 +0200 Subject: [PATCH 07/10] chore: resolve controls notifier from context --- .../lib/src/controls/flutter_deck_controls.dart | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart index d5bd3c5..0069325 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart @@ -1,7 +1,6 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_deck/src/controls/actions/actions.dart'; -import 'package:flutter_deck/src/controls/flutter_deck_controls_notifier.dart'; import 'package:flutter_deck/src/controls/localized_shortcut_labeler.dart'; import 'package:flutter_deck/src/flutter_deck.dart'; import 'package:flutter_deck/src/flutter_deck_layout.dart'; @@ -54,9 +53,9 @@ class FlutterDeckControls extends StatelessWidget { children: [ child!, if (controlsNotifier.controlsVisible) - Align( + const Align( alignment: AlignmentDirectional.bottomCenter, - child: _Controls(controlsNotifier: controlsNotifier), + child: _Controls(), ), ], ), @@ -66,14 +65,12 @@ class FlutterDeckControls extends StatelessWidget { } class _Controls extends StatelessWidget { - const _Controls({ - required this.controlsNotifier, - }); - - final FlutterDeckControlsNotifier controlsNotifier; + const _Controls(); @override Widget build(BuildContext context) { + final controlsNotifier = context.flutterDeck.controlsNotifier; + return MouseRegion( onEnter: (_) => controlsNotifier.toggleControlsVisibleDuration(), onExit: (_) => controlsNotifier.toggleControlsVisibleDuration(), From 72e555d35983f290815f03c2a979c9c7dab445b4 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 22:21:51 +0200 Subject: [PATCH 08/10] chore: update CHANGELOG.md --- packages/flutter_deck/CHANGELOG.md | 8 ++++++++ .../lib/src/controls/flutter_deck_controls.dart | 10 +++++----- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/packages/flutter_deck/CHANGELOG.md b/packages/flutter_deck/CHANGELOG.md index 4a9153e..725a69b 100644 --- a/packages/flutter_deck/CHANGELOG.md +++ b/packages/flutter_deck/CHANGELOG.md @@ -1,3 +1,11 @@ +# NEXT + +- fix: show controls on tap on mobile devices (iOS and Android) +- fix: controls are auto-hidden when the cursor is over them +- feat: add swipe left/right gestures to navigate between slides +- feat: add control gestures configuration +- docs: update documentation website + # 0.17.0 - feat: allow using any widget as a slide diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart index 0069325..3ad9fc8 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls.dart @@ -71,11 +71,11 @@ class _Controls extends StatelessWidget { Widget build(BuildContext context) { final controlsNotifier = context.flutterDeck.controlsNotifier; - return MouseRegion( - onEnter: (_) => controlsNotifier.toggleControlsVisibleDuration(), - onExit: (_) => controlsNotifier.toggleControlsVisibleDuration(), - child: Theme( - data: ThemeData.light(), + return Theme( + data: ThemeData.light(), + child: MouseRegion( + onEnter: (_) => controlsNotifier.toggleControlsVisibleDuration(), + onExit: (_) => controlsNotifier.toggleControlsVisibleDuration(), child: Builder( builder: (context) => Container( margin: FlutterDeckLayout.slidePadding, From 0d52c142db92f2fd11b651dcd2ae5be855672396 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 22:23:38 +0200 Subject: [PATCH 09/10] refactor: Duration -> var --- .../lib/src/controls/flutter_deck_controls_notifier.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart index 8415f58..46b2bf4 100644 --- a/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart +++ b/packages/flutter_deck/lib/src/controls/flutter_deck_controls_notifier.dart @@ -35,7 +35,7 @@ class FlutterDeckControlsNotifier final FlutterDeckRouter _router; var _controlsVisible = false; - Duration _controlsVisibleDuration = _defaultControlsVisibleDuration; + var _controlsVisibleDuration = _defaultControlsVisibleDuration; Timer? _controlsVisibleTimer; Set _disabledIntents = {}; From 147af302cd3c3d60301f322398ae31c5316e20c8 Mon Sep 17 00:00:00 2001 From: Mangirdas Kazlauskas Date: Mon, 30 Dec 2024 22:32:37 +0200 Subject: [PATCH 10/10] ci: update cspell.json --- .github/cspell.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/cspell.json b/.github/cspell.json index 24a1831..e24f842 100644 --- a/.github/cspell.json +++ b/.github/cspell.json @@ -15,6 +15,6 @@ } ], "useGitignore": true, - "words": ["flutter_deck", "Mangirdas", "Kazlauskas"], - "ignorePaths": ["doc/website/source/showcase.md"] + "words": ["flutter_deck", "Mangirdas", "Kazlauskas", "subclassing"], + "ignorePaths": ["**/doc/website/source/showcase.md"] }