Skip to content

Commit

Permalink
Merge pull request #3050 from jonataslaw/snackbar-fix
Browse files Browse the repository at this point in the history
Snackbar fix
  • Loading branch information
jonataslaw authored Mar 8, 2024
2 parents 272aa46 + 5155b2f commit 2d54f9a
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 31 deletions.
10 changes: 5 additions & 5 deletions example/.metadata
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This file should be version controlled and should not be manually edited.

version:
revision: "e1e47221e86272429674bec4f1bd36acc4fc7b77"
revision: "ba393198430278b6595976de84fe170f553cc728"
channel: "stable"

project_type: app
Expand All @@ -13,11 +13,11 @@ project_type: app
migration:
platforms:
- platform: root
create_revision: e1e47221e86272429674bec4f1bd36acc4fc7b77
base_revision: e1e47221e86272429674bec4f1bd36acc4fc7b77
create_revision: ba393198430278b6595976de84fe170f553cc728
base_revision: ba393198430278b6595976de84fe170f553cc728
- platform: ios
create_revision: e1e47221e86272429674bec4f1bd36acc4fc7b77
base_revision: e1e47221e86272429674bec4f1bd36acc4fc7b77
create_revision: ba393198430278b6595976de84fe170f553cc728
base_revision: ba393198430278b6595976de84fe170f553cc728

# User provided section

Expand Down
15 changes: 12 additions & 3 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,18 @@ class First extends StatelessWidget {
leading: IconButton(
icon: const Icon(Icons.more),
onPressed: () {
print('THEME CHANGED');
Get.changeTheme(
Get.isDarkMode ? ThemeData.light() : ThemeData.dark());
Get.snackbar(
'title',
"message",
mainButton:
TextButton(onPressed: () {}, child: const Text('button')),
isDismissible: true,
duration: Duration(seconds: 5),
snackbarStatus: (status) => print(status),
);
// print('THEME CHANGED');
// Get.changeTheme(
// Get.isDarkMode ? ThemeData.light() : ThemeData.dark());
},
),
),
Expand Down
4 changes: 2 additions & 2 deletions example_nav2/android/local.properties
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
sdk.dir=C:\\Users\\anike\\AppData\\Local\\Android\\sdk
flutter.sdk=C:\\flutter
sdk.dir=/Users/jonatasborges/Library/Android/sdk
flutter.sdk=/Users/jonatasborges/flutter
2 changes: 2 additions & 0 deletions lib/get_navigation/src/root/get_root.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class ConfigData {
final Duration defaultDialogTransitionDuration;
final Routing routing;
final Map<String, String?> parameters;
final SnackBarQueue snackBarQueue = SnackBarQueue();

ConfigData({
required this.routingCallback,
Expand Down Expand Up @@ -340,6 +341,7 @@ class GetRootState extends State<GetRoot> with WidgetsBindingObserver {
void onClose() {
config.onDispose?.call();
Get.clearTranslations();
config.snackBarQueue.disposeControllers();
RouterReportManager.instance.clearRouteKeys();
RouterReportManager.dispose();
Get.resetInstance(clearRouteBindings: true);
Expand Down
8 changes: 8 additions & 0 deletions lib/get_navigation/src/snackbar/snackbar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ class GetSnackBar extends StatefulWidget {
/// The title displayed to the user
final String? title;

/// Defines how the snack bar area, including margin, will behave during hit testing.
///
/// If this property is null and [margin] is not null, then [HitTestBehavior.deferToChild] is used by default.
///
/// Please refer to [HitTestBehavior] for a detailed explanation of every behavior.
final HitTestBehavior? hitTestBehavior;

/// The direction in which the SnackBar can be dismissed.
///
/// Default is [DismissDirection.down] when
Expand Down Expand Up @@ -203,6 +210,7 @@ class GetSnackBar extends StatefulWidget {
this.overlayColor = Colors.transparent,
this.userInputForm,
this.snackbarStatus,
this.hitTestBehavior,
}) : super(key: key);

@override
Expand Down
39 changes: 29 additions & 10 deletions lib/get_navigation/src/snackbar/snackbar_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import 'dart:ui';
import 'package:flutter/material.dart';

import '../../../get.dart';
import '../root/get_root.dart';

class SnackbarController {
static final _snackBarQueue = _SnackBarQueue();
static bool get isSnackbarBeingShown => _snackBarQueue._isJobInProgress;
final key = GlobalKey<GetSnackBarState>();

static bool get isSnackbarBeingShown =>
GetRootState.controller.config.snackBarQueue.isJobInProgress;

late Animation<double> _filterBlurAnimation;
late Animation<Color?> _filterColorAnimation;

Expand Down Expand Up @@ -60,7 +62,7 @@ class SnackbarController {
/// Only one GetSnackbar will be displayed at a time, and this method returns
/// a future to when the snackbar disappears.
Future<void> show() {
return _snackBarQueue._addJob(this);
return GetRootState.controller.config.snackBarQueue.addJob(this);
}

void _cancelTimer() {
Expand Down Expand Up @@ -243,6 +245,7 @@ class SnackbarController {
snackbar.onHover?.call(snackbar, SnackHoverState.entered),
onExit: (_) => snackbar.onHover?.call(snackbar, SnackHoverState.exited),
child: GestureDetector(
behavior: snackbar.hitTestBehavior ?? HitTestBehavior.deferToChild,
onTap: snackbar.onTap != null
? () => snackbar.onTap?.call(snackbar)
: null,
Expand All @@ -261,6 +264,7 @@ class SnackbarController {

Widget _getDismissibleSnack(Widget child) {
return Dismissible(
behavior: snackbar.hitTestBehavior ?? HitTestBehavior.opaque,
direction: snackbar.dismissDirection ?? _getDefaultDismissDirection(),
resizeDuration: null,
confirmDismiss: (_) {
Expand Down Expand Up @@ -348,15 +352,15 @@ class SnackbarController {
}

static Future<void> cancelAllSnackbars() async {
await _snackBarQueue._cancelAllJobs();
await GetRootState.controller.config.snackBarQueue.cancelAllJobs();
}

static Future<void> closeCurrentSnackbar() async {
await _snackBarQueue._closeCurrentJob();
await GetRootState.controller.config.snackBarQueue.closeCurrentJob();
}
}

class _SnackBarQueue {
class SnackBarQueue {
final _queue = GetQueue();
final _snackbarList = <SnackbarController>[];

Expand All @@ -365,22 +369,37 @@ class _SnackBarQueue {
return _snackbarList.first;
}

bool get _isJobInProgress => _snackbarList.isNotEmpty;
bool get isJobInProgress => _snackbarList.isNotEmpty;

Future<void> _addJob(SnackbarController job) async {
Future<void> addJob(SnackbarController job) async {
_snackbarList.add(job);
final data = await _queue.add(job._show);
_snackbarList.remove(job);
return data;
}

Future<void> _cancelAllJobs() async {
Future<void> cancelAllJobs() async {
await _currentSnackbar?.close();
_queue.cancelAllJobs();
_snackbarList.clear();
}

Future<void> _closeCurrentJob() async {
void disposeControllers() {
if (_currentSnackbar != null) {
_currentSnackbar?._removeOverlay();
_currentSnackbar?._controller.dispose();
_snackbarList.remove(_currentSnackbar);
}

_queue.cancelAllJobs();

for (var element in _snackbarList) {
element._controller.dispose();
}
_snackbarList.clear();
}

Future<void> closeCurrentJob() async {
if (_currentSnackbar == null) return;
await _currentSnackbar!.close();
}
Expand Down
3 changes: 2 additions & 1 deletion lib/get_utils/src/equality/equality.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ mixin Equality {
List get props;

@override
bool operator ==(dynamic other) {
bool operator ==(Object other) {
return identical(this, other) ||
runtimeType == other.runtimeType &&
other is Equality &&
const DeepCollectionEquality().equals(props, other.props);
}

Expand Down
21 changes: 11 additions & 10 deletions test/navigation/snackbar_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,17 @@ void main() {
});

testWidgets("test snackbar dismissible", (tester) async {
const dismissDirection = DismissDirection.vertical;
const dismissDirection = DismissDirection.down;
const snackBarTapTarget = Key('snackbar-tap-target');

late final GetSnackBar getBar;
const GetSnackBar getBar = GetSnackBar(
key: ValueKey('dismissible'),
message: 'bar1',
duration: Duration(seconds: 2),
isDismissible: true,
snackPosition: SnackPosition.bottom,
dismissDirection: dismissDirection,
);

await tester.pumpWidget(GetMaterialApp(
home: Scaffold(
Expand All @@ -121,12 +128,6 @@ void main() {
GestureDetector(
key: snackBarTapTarget,
onTap: () {
getBar = const GetSnackBar(
message: 'bar1',
duration: Duration(seconds: 2),
isDismissible: true,
dismissDirection: dismissDirection,
);
Get.showSnackbar(getBar);
},
behavior: HitTestBehavior.opaque,
Expand Down Expand Up @@ -154,9 +155,9 @@ void main() {
await tester.pump(const Duration(milliseconds: 500));
expect(find.byWidget(getBar), findsOneWidget);
await tester.ensureVisible(find.byWidget(getBar));
await tester.drag(find.byWidget(getBar), const Offset(0.0, 50.0));
await tester.drag(find.byType(Dismissible), const Offset(0.0, 50.0));
await tester.pumpAndSettle();
await tester.pump(const Duration(milliseconds: 500));

expect(Get.isSnackbarOpen, false);
});

Expand Down

0 comments on commit 2d54f9a

Please sign in to comment.