Skip to content

Commit

Permalink
Allow to show a floating message (replacement for SnackBar)
Browse files Browse the repository at this point in the history
  • Loading branch information
g123k committed Jul 27, 2023
1 parent 7a019d2 commit a82869d
Show file tree
Hide file tree
Showing 13 changed files with 154 additions and 37 deletions.
22 changes: 11 additions & 11 deletions packages/smooth_app/lib/background/background_task.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import 'package:smooth_app/background/background_task_manager.dart';
import 'package:smooth_app/background/background_task_refresh_later.dart';
import 'package:smooth_app/database/local_database.dart';
import 'package:smooth_app/generic_lib/duration_constants.dart';
import 'package:smooth_app/widgets/smooth_floating_message.dart';

/// Abstract background task.
abstract class BackgroundTask {
Expand Down Expand Up @@ -96,11 +97,11 @@ abstract class BackgroundTask {
/// [BackgroundTaskRefreshLater].
bool mayRunNow() => true;

/// SnackBar message when we add the task, like "Added to the task queue!"
/// Floating message when we add the task, like "Added to the task queue!"
///
/// Null if no SnackBar message wanted (like, stealth mode).
/// Null if no message wanted (like, stealth mode).
@protected
String? getSnackBarMessage(final AppLocalizations appLocalizations);
String? getFloatingMessage(final AppLocalizations appLocalizations);

/// Adds this task to the [BackgroundTaskManager].
@protected
Expand All @@ -116,14 +117,13 @@ abstract class BackgroundTask {
if (!showSnackBar) {
return;
}
final String? snackBarMessage =
getSnackBarMessage(AppLocalizations.of(widget.context));
if (snackBarMessage != null) {
ScaffoldMessenger.of(widget.context).showSnackBar(
SnackBar(
content: Text(snackBarMessage),
duration: SnackBarDuration.medium,
),
final String? floatingMessage =
getFloatingMessage(AppLocalizations.of(widget.context));
if (floatingMessage != null) {
SmoothFloatingMessage(message: floatingMessage).show(
widget.context,
duration: SnackBarDuration.medium,
alignment: Alignment.topCenter,
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ class BackgroundTaskCrop extends BackgroundTaskUpload {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) =>
String? getFloatingMessage(final AppLocalizations appLocalizations) =>
appLocalizations.product_task_background_schedule;

/// Returns a new background task about cropping an existing image.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ class BackgroundTaskDetails extends BackgroundTaskBarcode {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) =>
String? getFloatingMessage(final AppLocalizations appLocalizations) =>
appLocalizations.product_task_background_schedule;

/// Returns a new background task about changing a product.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ class BackgroundTaskDownloadProducts extends BackgroundTaskProgressing {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) => null;
String? getFloatingMessage(final AppLocalizations appLocalizations) => null;

static BackgroundTask _getNewTask(
final String uniqueId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ class BackgroundTaskFullRefresh extends BackgroundTaskPaged {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) =>
String? getFloatingMessage(final AppLocalizations appLocalizations) =>
appLocalizations.background_task_title_full_refresh;

static BackgroundTaskFullRefresh _getNewTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ class BackgroundTaskHungerGames extends BackgroundTaskBarcode {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) => null;
String? getFloatingMessage(final AppLocalizations appLocalizations) => null;

/// Returns a new background task about hunger games.
static BackgroundTaskHungerGames _getNewTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ class BackgroundTaskImage extends BackgroundTaskUpload {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) =>
String? getFloatingMessage(final AppLocalizations appLocalizations) =>
appLocalizations.image_upload_queued;

/// Returns a new background task about changing a product.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ class BackgroundTaskOffline extends BackgroundTaskProgressing {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) =>
String? getFloatingMessage(final AppLocalizations appLocalizations) =>
appLocalizations.background_task_title_top_n;

static BackgroundTaskOffline _getNewTask(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:convert';

import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:openfoodfacts/openfoodfacts.dart';
import 'package:smooth_app/background/background_task_barcode.dart';
Expand Down Expand Up @@ -64,7 +65,7 @@ class BackgroundTaskRefreshLater extends BackgroundTaskBarcode {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) => null;
String? getFloatingMessage(final AppLocalizations appLocalizations) => null;

/// Returns a new background task about refreshing a product later.
static BackgroundTaskRefreshLater _getNewTask(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ class BackgroundTaskTopBarcodes extends BackgroundTaskProgressing {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) => null;
String? getFloatingMessage(final AppLocalizations appLocalizations) => null;

static BackgroundTask _getNewTask(
final String uniqueId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class BackgroundTaskUnselect extends BackgroundTaskBarcode {
}

@override
String? getSnackBarMessage(final AppLocalizations appLocalizations) =>
String? getFloatingMessage(final AppLocalizations appLocalizations) =>
appLocalizations.product_task_background_schedule;

/// Returns a new background task about unselecting a product image.
Expand Down
32 changes: 16 additions & 16 deletions packages/smooth_app/lib/pages/product/edit_product_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import 'package:smooth_app/pages/product/product_image_gallery_view.dart';
import 'package:smooth_app/pages/product/simple_input_page.dart';
import 'package:smooth_app/pages/product/simple_input_page_helpers.dart';
import 'package:smooth_app/widgets/smooth_app_bar.dart';
import 'package:smooth_app/widgets/smooth_floating_message.dart';
import 'package:smooth_app/widgets/smooth_scaffold.dart';

/// Page where we can indirectly edit all data about a product.
Expand Down Expand Up @@ -99,22 +100,21 @@ class _EditProductPageState extends State<EditProductPage> with UpToDateMixin {
button: true,
value: appLocalizations.clipboard_barcode_copy,
excludeSemantics: true,
child: IconButton(
icon: const Icon(Icons.copy),
tooltip: appLocalizations.clipboard_barcode_copy,
onPressed: () {
Clipboard.setData(
ClipboardData(text: barcode),
);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
appLocalizations.clipboard_barcode_copied(barcode),
),
),
);
},
),
child: Builder(builder: (BuildContext context) {
return IconButton(
icon: const Icon(Icons.copy),
tooltip: appLocalizations.clipboard_barcode_copy,
onPressed: () {
Clipboard.setData(
ClipboardData(text: barcode),
);

SmoothFloatingMessage(
message: appLocalizations.clipboard_barcode_copied(barcode),
).show(context, alignment: AlignmentDirectional.bottomCenter);
},
);
}),
)
],
),
Expand Down
116 changes: 116 additions & 0 deletions packages/smooth_app/lib/widgets/smooth_floating_message.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:smooth_app/generic_lib/design_constants.dart';

class SmoothFloatingMessage {
SmoothFloatingMessage({
required this.message,
});

final String message;

OverlayEntry? _entry;
Timer? _autoDismissMessage;

/// Show the message during [duration].
/// You can call [hide] if you want to dismiss it before
void show(
BuildContext context, {
AlignmentGeometry? alignment,
Duration? duration,
}) {
_entry?.remove();

final double appBarHeight = Scaffold.maybeOf(context)?.hasAppBar == true
? (Scaffold.of(context).appBarMaxHeight ?? kToolbarHeight)
: 0.0;

_entry = OverlayEntry(builder: (BuildContext context) {
return _SmoothFloatingMessageView(
message: message,
alignment: alignment,
margin: EdgeInsetsDirectional.only(
top: appBarHeight,
start: SMALL_SPACE,
end: SMALL_SPACE,
bottom: SMALL_SPACE,
),
);
});

Overlay.of(context).insert(_entry!);
_autoDismissMessage = Timer(duration ?? const Duration(seconds: 5), () {
hide();
});
}

void hide() {
_autoDismissMessage?.cancel();
_entry?.remove();
}
}

class _SmoothFloatingMessageView extends StatefulWidget {
const _SmoothFloatingMessageView({
required this.message,
this.alignment,
this.margin,
});

final String message;
final AlignmentGeometry? alignment;
final EdgeInsetsGeometry? margin;

@override
State<_SmoothFloatingMessageView> createState() =>
_SmoothFloatingMessageViewState();
}

class _SmoothFloatingMessageViewState extends State<_SmoothFloatingMessageView>
with SingleTickerProviderStateMixin {
bool initial = true;

@override
void initState() {
super.initState();

WidgetsBinding.instance.addPostFrameCallback((_) {
setState(() {
initial = false;
});
});
}

@override
Widget build(BuildContext context) {
final SnackBarThemeData snackBarTheme = Theme.of(context).snackBarTheme;

return AnimatedOpacity(
opacity: initial ? 0.0 : 1.0,
duration: const Duration(milliseconds: 200),
child: SafeArea(
top: false,
child: Container(
width: initial ? 0.0 : null,
height: initial ? 0.0 : null,
margin: widget.margin,
alignment: widget.alignment ?? AlignmentDirectional.topCenter,
child: Card(
elevation: 4.0,
shadowColor: Colors.black.withOpacity(0.1),
color: snackBarTheme.backgroundColor,
child: Container(
padding: const EdgeInsets.all(8.0),
child: Text(
widget.message,
textAlign: TextAlign.center,
style: snackBarTheme.contentTextStyle,
),
),
),
),
),
);
}
}

0 comments on commit a82869d

Please sign in to comment.