Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Snackbar fix #3050

Merged
merged 3 commits into from
Mar 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading