2024-07-27 21:05:51 +08:00
|
|
|
import 'package:appflowy/generated/flowy_svgs.g.dart';
|
2024-03-04 09:43:00 +07:00
|
|
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
|
|
|
import 'package:appflowy/startup/tasks/app_widget.dart';
|
2024-12-30 16:35:41 +08:00
|
|
|
import 'package:appflowy/util/theme_extension.dart';
|
2024-07-08 13:45:57 +08:00
|
|
|
import 'package:appflowy/workspace/presentation/home/menu/sidebar/space/shared_widget.dart';
|
2021-12-07 23:01:23 +05:30
|
|
|
import 'package:easy_localization/easy_localization.dart';
|
2024-03-04 09:43:00 +07:00
|
|
|
import 'package:flowy_infra/size.dart';
|
2021-10-20 14:56:25 +08:00
|
|
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
2024-03-04 09:43:00 +07:00
|
|
|
import 'package:flowy_infra_ui/style_widget/text_input.dart';
|
2021-10-20 14:56:25 +08:00
|
|
|
import 'package:flowy_infra_ui/widget/buttons/primary_button.dart';
|
|
|
|
import 'package:flowy_infra_ui/widget/buttons/secondary_button.dart';
|
2024-03-04 09:43:00 +07:00
|
|
|
import 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
2021-10-20 14:56:25 +08:00
|
|
|
import 'package:flowy_infra_ui/widget/spacing.dart';
|
2024-08-17 11:04:43 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2024-07-08 13:45:57 +08:00
|
|
|
import 'package:toastification/toastification.dart';
|
2024-09-12 14:40:19 +08:00
|
|
|
import 'package:universal_platform/universal_platform.dart';
|
2024-03-04 09:43:00 +07:00
|
|
|
|
2021-10-20 14:56:25 +08:00
|
|
|
export 'package:flowy_infra_ui/widget/dialog/styled_dialogs.dart';
|
2024-10-15 15:12:59 +08:00
|
|
|
export 'package:toastification/toastification.dart';
|
2021-10-20 14:56:25 +08:00
|
|
|
|
2024-10-14 20:38:04 +08:00
|
|
|
class NavigatorCustomDialog extends StatefulWidget {
|
|
|
|
const NavigatorCustomDialog({
|
|
|
|
super.key,
|
|
|
|
required this.child,
|
|
|
|
this.cancel,
|
|
|
|
this.confirm,
|
|
|
|
this.hideCancelButton = false,
|
|
|
|
});
|
|
|
|
|
|
|
|
final Widget child;
|
|
|
|
final void Function()? cancel;
|
|
|
|
final void Function()? confirm;
|
|
|
|
final bool hideCancelButton;
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<NavigatorCustomDialog> createState() => _NavigatorCustomDialog();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _NavigatorCustomDialog extends State<NavigatorCustomDialog> {
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return StyledDialog(
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
|
|
|
...[
|
|
|
|
ConstrainedBox(
|
|
|
|
constraints: const BoxConstraints(
|
|
|
|
maxWidth: 400,
|
|
|
|
maxHeight: 260,
|
|
|
|
),
|
|
|
|
child: widget.child,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
if (widget.confirm != null) ...[
|
|
|
|
const VSpace(20),
|
|
|
|
OkCancelButton(
|
|
|
|
onOkPressed: () {
|
|
|
|
widget.confirm?.call();
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
onCancelPressed: widget.hideCancelButton
|
|
|
|
? null
|
|
|
|
: () {
|
|
|
|
widget.cancel?.call();
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
|
|
|
),
|
|
|
|
],
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 16:05:55 +08:00
|
|
|
class NavigatorTextFieldDialog extends StatefulWidget {
|
|
|
|
const NavigatorTextFieldDialog({
|
2023-06-23 10:54:35 +08:00
|
|
|
super.key,
|
2021-10-20 14:56:25 +08:00
|
|
|
required this.title,
|
2023-06-23 10:54:35 +08:00
|
|
|
this.autoSelectAllText = false,
|
2021-10-23 20:32:39 +08:00
|
|
|
required this.value,
|
2024-03-04 09:43:00 +07:00
|
|
|
required this.onConfirm,
|
|
|
|
this.onCancel,
|
2024-02-07 18:38:53 +01:00
|
|
|
this.maxLength,
|
2024-03-04 09:43:00 +07:00
|
|
|
this.hintText,
|
2023-06-23 10:54:35 +08:00
|
|
|
});
|
|
|
|
|
|
|
|
final String value;
|
|
|
|
final String title;
|
2024-03-04 09:43:00 +07:00
|
|
|
final VoidCallback? onCancel;
|
|
|
|
final void Function(String, BuildContext) onConfirm;
|
2023-06-23 10:54:35 +08:00
|
|
|
final bool autoSelectAllText;
|
2024-02-07 18:38:53 +01:00
|
|
|
final int? maxLength;
|
2024-03-04 09:43:00 +07:00
|
|
|
final String? hintText;
|
2021-10-20 14:56:25 +08:00
|
|
|
|
|
|
|
@override
|
2023-06-23 10:54:35 +08:00
|
|
|
State<NavigatorTextFieldDialog> createState() =>
|
|
|
|
_NavigatorTextFieldDialogState();
|
2021-10-20 14:56:25 +08:00
|
|
|
}
|
|
|
|
|
2023-06-23 10:54:35 +08:00
|
|
|
class _NavigatorTextFieldDialogState extends State<NavigatorTextFieldDialog> {
|
2021-10-23 20:32:39 +08:00
|
|
|
String newValue = "";
|
2023-06-23 10:54:35 +08:00
|
|
|
final controller = TextEditingController();
|
2021-10-20 14:56:25 +08:00
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
2024-02-07 18:38:53 +01:00
|
|
|
super.initState();
|
2021-10-23 20:32:39 +08:00
|
|
|
newValue = widget.value;
|
2023-06-23 10:54:35 +08:00
|
|
|
controller.text = newValue;
|
|
|
|
if (widget.autoSelectAllText) {
|
|
|
|
controller.selection = TextSelection(
|
|
|
|
baseOffset: 0,
|
|
|
|
extentOffset: newValue.length,
|
|
|
|
);
|
|
|
|
}
|
2024-02-07 18:38:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void dispose() {
|
|
|
|
controller.dispose();
|
|
|
|
super.dispose();
|
2021-10-20 14:56:25 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return StyledDialog(
|
|
|
|
child: Column(
|
|
|
|
children: <Widget>[
|
2023-04-14 01:21:10 -04:00
|
|
|
FlowyText.medium(
|
|
|
|
widget.title,
|
|
|
|
color: Theme.of(context).colorScheme.tertiary,
|
|
|
|
fontSize: FontSizes.s16,
|
|
|
|
),
|
|
|
|
VSpace(Insets.m),
|
2021-10-20 14:56:25 +08:00
|
|
|
FlowyFormTextInput(
|
2024-03-04 09:43:00 +07:00
|
|
|
hintText:
|
|
|
|
widget.hintText ?? LocaleKeys.dialogCreatePageNameHint.tr(),
|
2023-06-23 10:54:35 +08:00
|
|
|
controller: controller,
|
2024-02-07 18:38:53 +01:00
|
|
|
textStyle: Theme.of(context)
|
|
|
|
.textTheme
|
|
|
|
.bodySmall
|
|
|
|
?.copyWith(fontSize: FontSizes.s16),
|
|
|
|
maxLength: widget.maxLength,
|
|
|
|
showCounter: false,
|
2021-10-23 20:32:39 +08:00
|
|
|
autoFocus: true,
|
2021-10-20 14:56:25 +08:00
|
|
|
onChanged: (text) {
|
2021-10-23 20:32:39 +08:00
|
|
|
newValue = text;
|
2021-10-20 14:56:25 +08:00
|
|
|
},
|
2021-11-11 23:11:15 +08:00
|
|
|
onEditingComplete: () {
|
2024-03-04 09:43:00 +07:00
|
|
|
widget.onConfirm(newValue, context);
|
2021-11-11 23:11:15 +08:00
|
|
|
AppGlobals.nav.pop();
|
|
|
|
},
|
2021-10-20 14:56:25 +08:00
|
|
|
),
|
2023-04-14 01:21:10 -04:00
|
|
|
VSpace(Insets.xl),
|
2021-10-24 18:54:41 +08:00
|
|
|
OkCancelButton(
|
|
|
|
onOkPressed: () {
|
2024-08-28 18:53:16 +08:00
|
|
|
if (newValue.isEmpty) {
|
|
|
|
showToastNotification(
|
|
|
|
context,
|
|
|
|
message: LocaleKeys.space_spaceNameCannotBeEmpty.tr(),
|
|
|
|
);
|
|
|
|
return;
|
|
|
|
}
|
2024-03-04 09:43:00 +07:00
|
|
|
widget.onConfirm(newValue, context);
|
2022-09-15 16:05:55 +08:00
|
|
|
Navigator.of(context).pop();
|
2021-10-24 18:54:41 +08:00
|
|
|
},
|
|
|
|
onCancelPressed: () {
|
2024-03-04 09:43:00 +07:00
|
|
|
widget.onCancel?.call();
|
2022-09-15 16:05:55 +08:00
|
|
|
Navigator.of(context).pop();
|
2021-10-24 18:54:41 +08:00
|
|
|
},
|
2023-11-14 22:33:07 +08:00
|
|
|
),
|
2021-10-20 14:56:25 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 16:05:55 +08:00
|
|
|
class NavigatorAlertDialog extends StatefulWidget {
|
|
|
|
const NavigatorAlertDialog({
|
2024-01-25 16:37:36 +01:00
|
|
|
super.key,
|
2022-09-15 16:05:55 +08:00
|
|
|
required this.title,
|
|
|
|
this.cancel,
|
2024-01-25 16:37:36 +01:00
|
|
|
this.confirm,
|
2024-03-04 09:43:00 +07:00
|
|
|
this.hideCancelButton = false,
|
2024-03-21 17:40:23 +01:00
|
|
|
this.constraints,
|
2023-12-08 20:01:54 +07:00
|
|
|
});
|
2022-09-15 16:05:55 +08:00
|
|
|
|
2024-01-25 16:37:36 +01:00
|
|
|
final String title;
|
|
|
|
final void Function()? cancel;
|
|
|
|
final void Function()? confirm;
|
2024-03-04 09:43:00 +07:00
|
|
|
final bool hideCancelButton;
|
2024-03-21 17:40:23 +01:00
|
|
|
final BoxConstraints? constraints;
|
2024-01-25 16:37:36 +01:00
|
|
|
|
2022-09-15 16:05:55 +08:00
|
|
|
@override
|
|
|
|
State<NavigatorAlertDialog> createState() => _CreateFlowyAlertDialog();
|
2021-11-10 15:09:24 +08:00
|
|
|
}
|
|
|
|
|
2022-09-15 16:05:55 +08:00
|
|
|
class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
|
2021-11-10 15:09:24 +08:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return StyledDialog(
|
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
|
|
|
...[
|
2023-08-17 23:46:39 +08:00
|
|
|
ConstrainedBox(
|
2024-03-21 17:40:23 +01:00
|
|
|
constraints: widget.constraints ??
|
|
|
|
const BoxConstraints(
|
|
|
|
maxWidth: 400,
|
|
|
|
maxHeight: 260,
|
|
|
|
),
|
2023-08-17 23:46:39 +08:00
|
|
|
child: FlowyText.medium(
|
|
|
|
widget.title,
|
|
|
|
fontSize: FontSizes.s16,
|
2023-11-28 10:43:22 +08:00
|
|
|
textAlign: TextAlign.center,
|
2023-08-17 23:46:39 +08:00
|
|
|
color: Theme.of(context).colorScheme.tertiary,
|
|
|
|
maxLines: null,
|
|
|
|
),
|
2022-11-10 14:22:18 +08:00
|
|
|
),
|
2021-11-10 15:09:24 +08:00
|
|
|
],
|
|
|
|
if (widget.confirm != null) ...[
|
|
|
|
const VSpace(20),
|
2023-04-10 15:10:42 +08:00
|
|
|
OkCancelButton(
|
|
|
|
onOkPressed: () {
|
|
|
|
widget.confirm?.call();
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
2024-03-04 09:43:00 +07:00
|
|
|
onCancelPressed: widget.hideCancelButton
|
2024-01-30 09:33:34 +08:00
|
|
|
? null
|
|
|
|
: () {
|
|
|
|
widget.cancel?.call();
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
},
|
2023-11-14 22:33:07 +08:00
|
|
|
),
|
|
|
|
],
|
2021-11-10 15:09:24 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-09-15 16:05:55 +08:00
|
|
|
class NavigatorOkCancelDialog extends StatelessWidget {
|
2023-04-10 15:10:42 +08:00
|
|
|
const NavigatorOkCancelDialog({
|
2023-12-08 20:01:54 +07:00
|
|
|
super.key,
|
2023-04-10 15:10:42 +08:00
|
|
|
this.onOkPressed,
|
|
|
|
this.onCancelPressed,
|
|
|
|
this.okTitle,
|
|
|
|
this.cancelTitle,
|
|
|
|
this.title,
|
2024-03-22 16:15:18 +07:00
|
|
|
this.message,
|
2023-04-10 15:10:42 +08:00
|
|
|
this.maxWidth,
|
2024-07-15 15:23:23 +08:00
|
|
|
this.titleUpperCase = true,
|
2024-07-22 09:43:48 +02:00
|
|
|
this.autoDismiss = true,
|
2023-12-08 20:01:54 +07:00
|
|
|
});
|
2021-10-20 14:56:25 +08:00
|
|
|
|
2024-01-25 16:37:36 +01:00
|
|
|
final VoidCallback? onOkPressed;
|
|
|
|
final VoidCallback? onCancelPressed;
|
|
|
|
final String? okTitle;
|
|
|
|
final String? cancelTitle;
|
|
|
|
final String? title;
|
2024-03-22 16:15:18 +07:00
|
|
|
final String? message;
|
2024-01-25 16:37:36 +01:00
|
|
|
final double? maxWidth;
|
2024-07-15 15:23:23 +08:00
|
|
|
final bool titleUpperCase;
|
2024-07-22 09:43:48 +02:00
|
|
|
final bool autoDismiss;
|
2024-01-25 16:37:36 +01:00
|
|
|
|
2021-10-20 14:56:25 +08:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-07-22 09:43:48 +02:00
|
|
|
final onCancel = onCancelPressed == null
|
|
|
|
? null
|
|
|
|
: () {
|
|
|
|
onCancelPressed?.call();
|
|
|
|
if (autoDismiss) {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
}
|
|
|
|
};
|
2021-10-20 14:56:25 +08:00
|
|
|
return StyledDialog(
|
|
|
|
maxWidth: maxWidth ?? 500,
|
2024-03-22 16:15:18 +07:00
|
|
|
padding: EdgeInsets.symmetric(horizontal: Insets.xl, vertical: Insets.l),
|
2021-10-20 14:56:25 +08:00
|
|
|
child: Column(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: <Widget>[
|
|
|
|
if (title != null) ...[
|
2022-11-19 17:53:30 +08:00
|
|
|
FlowyText.medium(
|
2024-07-15 15:23:23 +08:00
|
|
|
titleUpperCase ? title!.toUpperCase() : title!,
|
2022-11-19 17:53:30 +08:00
|
|
|
fontSize: FontSizes.s16,
|
2024-03-22 16:15:18 +07:00
|
|
|
maxLines: 3,
|
2022-11-19 17:53:30 +08:00
|
|
|
),
|
2021-10-20 14:56:25 +08:00
|
|
|
VSpace(Insets.sm * 1.5),
|
2022-11-10 14:22:18 +08:00
|
|
|
Container(
|
2024-05-23 11:07:09 +08:00
|
|
|
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
2023-04-10 15:10:42 +08:00
|
|
|
height: 1,
|
|
|
|
),
|
2021-10-20 14:56:25 +08:00
|
|
|
VSpace(Insets.m * 1.5),
|
|
|
|
],
|
2024-03-22 16:15:18 +07:00
|
|
|
if (message != null)
|
|
|
|
FlowyText.medium(
|
|
|
|
message!,
|
|
|
|
maxLines: 3,
|
|
|
|
),
|
2021-10-20 14:56:25 +08:00
|
|
|
SizedBox(height: Insets.l),
|
|
|
|
OkCancelButton(
|
2022-09-15 16:05:55 +08:00
|
|
|
onOkPressed: () {
|
|
|
|
onOkPressed?.call();
|
2024-07-22 09:43:48 +02:00
|
|
|
if (autoDismiss) {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
}
|
2022-09-15 16:05:55 +08:00
|
|
|
},
|
2024-07-22 09:43:48 +02:00
|
|
|
onCancelPressed: onCancel,
|
2021-10-20 14:56:25 +08:00
|
|
|
okTitle: okTitle?.toUpperCase(),
|
|
|
|
cancelTitle: cancelTitle?.toUpperCase(),
|
2023-11-14 22:33:07 +08:00
|
|
|
),
|
2021-10-20 14:56:25 +08:00
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class OkCancelButton extends StatelessWidget {
|
2023-04-10 15:10:42 +08:00
|
|
|
const OkCancelButton({
|
2023-12-08 20:01:54 +07:00
|
|
|
super.key,
|
2023-04-10 15:10:42 +08:00
|
|
|
this.onOkPressed,
|
|
|
|
this.onCancelPressed,
|
|
|
|
this.okTitle,
|
|
|
|
this.cancelTitle,
|
|
|
|
this.minHeight,
|
2023-04-14 01:21:10 -04:00
|
|
|
this.alignment = MainAxisAlignment.spaceAround,
|
2023-08-17 23:46:39 +08:00
|
|
|
this.mode = TextButtonMode.big,
|
2023-12-08 20:01:54 +07:00
|
|
|
});
|
2021-10-20 14:56:25 +08:00
|
|
|
|
2024-01-25 16:37:36 +01:00
|
|
|
final VoidCallback? onOkPressed;
|
|
|
|
final VoidCallback? onCancelPressed;
|
|
|
|
final String? okTitle;
|
|
|
|
final String? cancelTitle;
|
|
|
|
final double? minHeight;
|
|
|
|
final MainAxisAlignment alignment;
|
|
|
|
final TextButtonMode mode;
|
|
|
|
|
2021-10-20 14:56:25 +08:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2021-10-24 18:54:41 +08:00
|
|
|
return SizedBox(
|
|
|
|
height: 48,
|
|
|
|
child: Row(
|
2023-04-14 01:21:10 -04:00
|
|
|
mainAxisAlignment: alignment,
|
2021-10-24 18:54:41 +08:00
|
|
|
children: <Widget>[
|
|
|
|
if (onCancelPressed != null)
|
|
|
|
SecondaryTextButton(
|
2023-10-25 06:29:50 -07:00
|
|
|
cancelTitle ?? LocaleKeys.button_cancel.tr(),
|
2022-09-15 16:05:55 +08:00
|
|
|
onPressed: onCancelPressed,
|
2023-08-17 23:46:39 +08:00
|
|
|
mode: mode,
|
2021-10-24 18:54:41 +08:00
|
|
|
),
|
2024-01-30 09:33:34 +08:00
|
|
|
if (onCancelPressed != null) HSpace(Insets.m),
|
2021-10-24 18:54:41 +08:00
|
|
|
if (onOkPressed != null)
|
|
|
|
PrimaryTextButton(
|
2023-10-25 06:29:50 -07:00
|
|
|
okTitle ?? LocaleKeys.button_ok.tr(),
|
2022-09-15 16:05:55 +08:00
|
|
|
onPressed: onOkPressed,
|
2023-08-17 23:46:39 +08:00
|
|
|
mode: mode,
|
2021-10-24 18:54:41 +08:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
2021-10-20 14:56:25 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2024-07-08 13:45:57 +08:00
|
|
|
|
|
|
|
void showToastNotification(
|
|
|
|
BuildContext context, {
|
2024-12-30 16:35:41 +08:00
|
|
|
String? message,
|
|
|
|
TextSpan? richMessage,
|
2024-07-08 13:45:57 +08:00
|
|
|
String? description,
|
2024-07-11 12:55:22 +08:00
|
|
|
ToastificationType type = ToastificationType.success,
|
2024-08-27 10:49:31 +08:00
|
|
|
ToastificationCallbacks? callbacks,
|
2024-08-26 09:51:57 +08:00
|
|
|
double bottomPadding = 100,
|
2024-07-08 13:45:57 +08:00
|
|
|
}) {
|
2024-12-30 16:35:41 +08:00
|
|
|
assert(
|
|
|
|
(message == null) != (richMessage == null),
|
|
|
|
"Exactly one of message or richMessage must be non-null.",
|
|
|
|
);
|
|
|
|
toastification.showCustom(
|
2024-09-27 17:45:49 +08:00
|
|
|
alignment: Alignment.bottomCenter,
|
|
|
|
autoCloseDuration: const Duration(milliseconds: 3000),
|
2024-12-30 16:35:41 +08:00
|
|
|
callbacks: callbacks ?? const ToastificationCallbacks(),
|
|
|
|
builder: (_, item) {
|
|
|
|
return UniversalPlatform.isMobile
|
|
|
|
? _MobileToast(
|
|
|
|
message: message,
|
|
|
|
type: type,
|
|
|
|
bottomPadding: bottomPadding,
|
|
|
|
description: description,
|
|
|
|
)
|
|
|
|
: _DesktopToast(
|
|
|
|
message: message,
|
|
|
|
richMessage: richMessage,
|
|
|
|
type: type,
|
|
|
|
onDismiss: () => toastification.dismiss(item),
|
|
|
|
);
|
|
|
|
},
|
2024-07-08 13:45:57 +08:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2024-12-30 16:35:41 +08:00
|
|
|
class _MobileToast extends StatelessWidget {
|
|
|
|
const _MobileToast({
|
|
|
|
this.message,
|
2024-07-27 21:05:51 +08:00
|
|
|
this.type = ToastificationType.success,
|
2024-08-26 09:51:57 +08:00
|
|
|
this.bottomPadding = 100,
|
2024-11-18 10:33:51 +08:00
|
|
|
this.description,
|
2024-07-27 21:05:51 +08:00
|
|
|
});
|
|
|
|
|
2024-12-30 16:35:41 +08:00
|
|
|
final String? message;
|
2024-07-27 21:05:51 +08:00
|
|
|
final ToastificationType type;
|
2024-08-26 09:51:57 +08:00
|
|
|
final double bottomPadding;
|
2024-11-18 10:33:51 +08:00
|
|
|
final String? description;
|
2024-07-27 21:05:51 +08:00
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2024-12-30 16:35:41 +08:00
|
|
|
if (message == null) {
|
|
|
|
return const SizedBox.shrink();
|
|
|
|
}
|
2024-08-19 11:06:34 +08:00
|
|
|
final hintText = FlowyText.regular(
|
2024-12-30 16:35:41 +08:00
|
|
|
message!,
|
2024-08-19 11:06:34 +08:00
|
|
|
fontSize: 16.0,
|
|
|
|
figmaLineHeight: 18.0,
|
|
|
|
color: Colors.white,
|
|
|
|
maxLines: 10,
|
|
|
|
);
|
2024-11-18 10:33:51 +08:00
|
|
|
final descriptionText = description != null
|
|
|
|
? FlowyText.regular(
|
|
|
|
description!,
|
|
|
|
fontSize: 12,
|
|
|
|
color: Colors.white,
|
|
|
|
maxLines: 10,
|
|
|
|
)
|
|
|
|
: null;
|
2024-07-27 21:05:51 +08:00
|
|
|
return Container(
|
|
|
|
alignment: Alignment.bottomCenter,
|
2024-11-18 10:33:51 +08:00
|
|
|
padding: EdgeInsets.only(
|
|
|
|
bottom: bottomPadding,
|
|
|
|
left: 16,
|
|
|
|
right: 16,
|
|
|
|
),
|
2024-07-27 21:05:51 +08:00
|
|
|
child: Container(
|
2024-11-18 10:33:51 +08:00
|
|
|
padding: const EdgeInsets.symmetric(
|
|
|
|
horizontal: 12.0,
|
|
|
|
vertical: 13.0,
|
|
|
|
),
|
2024-07-27 21:05:51 +08:00
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
|
|
color: const Color(0xE5171717),
|
|
|
|
),
|
2024-08-19 11:06:34 +08:00
|
|
|
child: type == ToastificationType.success
|
2024-11-18 10:33:51 +08:00
|
|
|
? Column(
|
2024-08-19 11:06:34 +08:00
|
|
|
mainAxisSize: MainAxisSize.min,
|
2024-11-18 10:33:51 +08:00
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
2024-08-19 11:06:34 +08:00
|
|
|
children: [
|
2024-11-18 10:33:51 +08:00
|
|
|
Row(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
|
|
if (type == ToastificationType.success) ...[
|
|
|
|
const FlowySvg(
|
|
|
|
FlowySvgs.success_s,
|
|
|
|
blendMode: null,
|
|
|
|
),
|
|
|
|
const HSpace(8.0),
|
|
|
|
],
|
|
|
|
Expanded(child: hintText),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
if (descriptionText != null) ...[
|
|
|
|
const VSpace(4.0),
|
|
|
|
descriptionText,
|
2024-08-19 11:06:34 +08:00
|
|
|
],
|
|
|
|
],
|
|
|
|
)
|
2024-11-18 10:33:51 +08:00
|
|
|
: Column(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
hintText,
|
|
|
|
if (descriptionText != null) ...[
|
|
|
|
const VSpace(4.0),
|
|
|
|
descriptionText,
|
|
|
|
],
|
|
|
|
],
|
|
|
|
),
|
2024-07-27 21:05:51 +08:00
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-12-30 16:35:41 +08:00
|
|
|
class _DesktopToast extends StatelessWidget {
|
|
|
|
const _DesktopToast({
|
|
|
|
this.message,
|
|
|
|
this.richMessage,
|
|
|
|
required this.type,
|
|
|
|
this.onDismiss,
|
|
|
|
});
|
|
|
|
|
|
|
|
final String? message;
|
|
|
|
final TextSpan? richMessage;
|
|
|
|
final ToastificationType type;
|
|
|
|
final void Function()? onDismiss;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return Center(
|
|
|
|
child: Container(
|
|
|
|
constraints: const BoxConstraints(maxWidth: 360.0),
|
|
|
|
padding: const EdgeInsets.symmetric(horizontal: 12.0, vertical: 8.0),
|
|
|
|
margin: const EdgeInsets.only(bottom: 32.0),
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: Theme.of(context).isLightMode
|
|
|
|
? const Color(0xFF333333)
|
|
|
|
: const Color(0xFF363D49),
|
|
|
|
borderRadius: const BorderRadius.all(Radius.circular(8.0)),
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: [
|
|
|
|
// icon
|
|
|
|
FlowySvg(
|
|
|
|
switch (type) {
|
|
|
|
ToastificationType.warning => FlowySvgs.toast_warning_filled_s,
|
|
|
|
ToastificationType.success => FlowySvgs.toast_checked_filled_s,
|
|
|
|
ToastificationType.error => FlowySvgs.toast_error_filled_s,
|
|
|
|
_ => throw UnimplementedError(),
|
|
|
|
},
|
|
|
|
size: const Size.square(20.0),
|
|
|
|
blendMode: null,
|
|
|
|
),
|
|
|
|
const HSpace(8.0),
|
|
|
|
// text
|
|
|
|
Flexible(
|
|
|
|
child: message != null
|
|
|
|
? FlowyText(
|
|
|
|
message!,
|
|
|
|
maxLines: 2,
|
|
|
|
figmaLineHeight: 20.0,
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
color: const Color(0xFFFFFFFF),
|
|
|
|
)
|
|
|
|
: RichText(
|
|
|
|
text: richMessage!,
|
|
|
|
maxLines: 2,
|
|
|
|
overflow: TextOverflow.ellipsis,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
const HSpace(16.0),
|
|
|
|
// close
|
|
|
|
MouseRegion(
|
|
|
|
cursor: SystemMouseCursors.click,
|
|
|
|
child: GestureDetector(
|
|
|
|
behavior: HitTestBehavior.opaque,
|
|
|
|
onTap: onDismiss,
|
|
|
|
child: const SizedBox.square(
|
|
|
|
dimension: 24.0,
|
|
|
|
child: Center(
|
|
|
|
child: FlowySvg(
|
|
|
|
FlowySvgs.toast_close_s,
|
|
|
|
size: Size.square(16.0),
|
|
|
|
color: Color(0xFFBDBDBD),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-07-08 13:45:57 +08:00
|
|
|
Future<void> showConfirmDeletionDialog({
|
|
|
|
required BuildContext context,
|
|
|
|
required String name,
|
|
|
|
required String description,
|
|
|
|
required VoidCallback onConfirm,
|
|
|
|
}) {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (_) {
|
|
|
|
final title = LocaleKeys.space_deleteConfirmation.tr() + name;
|
|
|
|
return Dialog(
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
|
|
),
|
|
|
|
child: SizedBox(
|
|
|
|
width: 440,
|
2024-07-11 12:55:22 +08:00
|
|
|
child: ConfirmPopup(
|
2024-07-08 13:45:57 +08:00
|
|
|
title: title,
|
|
|
|
description: description,
|
|
|
|
onConfirm: onConfirm,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2024-07-11 12:55:22 +08:00
|
|
|
|
|
|
|
Future<void> showConfirmDialog({
|
|
|
|
required BuildContext context,
|
|
|
|
required String title,
|
|
|
|
required String description,
|
|
|
|
VoidCallback? onConfirm,
|
2024-07-30 17:32:30 +08:00
|
|
|
VoidCallback? onCancel,
|
2024-07-16 08:50:50 +02:00
|
|
|
String? confirmLabel,
|
|
|
|
ConfirmPopupStyle style = ConfirmPopupStyle.onlyOk,
|
2024-07-11 12:55:22 +08:00
|
|
|
}) {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (_) {
|
|
|
|
return Dialog(
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
|
|
),
|
|
|
|
child: SizedBox(
|
|
|
|
width: 440,
|
|
|
|
child: ConfirmPopup(
|
|
|
|
title: title,
|
|
|
|
description: description,
|
|
|
|
onConfirm: () => onConfirm?.call(),
|
2024-07-30 17:32:30 +08:00
|
|
|
onCancel: () => onCancel?.call(),
|
2024-07-16 08:50:50 +02:00
|
|
|
confirmLabel: confirmLabel,
|
|
|
|
style: style,
|
2024-07-11 12:55:22 +08:00
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2024-07-16 13:23:07 +08:00
|
|
|
|
|
|
|
Future<void> showCancelAndConfirmDialog({
|
|
|
|
required BuildContext context,
|
|
|
|
required String title,
|
|
|
|
required String description,
|
|
|
|
VoidCallback? onConfirm,
|
2024-09-11 20:15:27 +08:00
|
|
|
VoidCallback? onCancel,
|
2024-07-16 13:23:07 +08:00
|
|
|
String? confirmLabel,
|
|
|
|
}) {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (_) {
|
|
|
|
return Dialog(
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
|
|
),
|
|
|
|
child: SizedBox(
|
|
|
|
width: 440,
|
|
|
|
child: ConfirmPopup(
|
|
|
|
title: title,
|
|
|
|
description: description,
|
|
|
|
onConfirm: () => onConfirm?.call(),
|
|
|
|
confirmLabel: confirmLabel,
|
|
|
|
confirmButtonColor: Theme.of(context).colorScheme.primary,
|
2024-09-11 20:15:27 +08:00
|
|
|
onCancel: () => onCancel?.call(),
|
2024-07-16 13:23:07 +08:00
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2024-07-31 15:49:35 +02:00
|
|
|
|
|
|
|
Future<void> showCustomConfirmDialog({
|
|
|
|
required BuildContext context,
|
|
|
|
required String title,
|
|
|
|
required String description,
|
|
|
|
required Widget Function(BuildContext) builder,
|
|
|
|
VoidCallback? onConfirm,
|
2024-11-05 00:13:19 +01:00
|
|
|
VoidCallback? onCancel,
|
2024-07-31 15:49:35 +02:00
|
|
|
String? confirmLabel,
|
|
|
|
ConfirmPopupStyle style = ConfirmPopupStyle.onlyOk,
|
|
|
|
bool closeOnConfirm = true,
|
|
|
|
}) {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (context) {
|
|
|
|
return Dialog(
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
|
|
),
|
|
|
|
child: SizedBox(
|
|
|
|
width: 440,
|
|
|
|
child: ConfirmPopup(
|
|
|
|
title: title,
|
|
|
|
description: description,
|
|
|
|
onConfirm: () => onConfirm?.call(),
|
2024-11-05 00:13:19 +01:00
|
|
|
onCancel: onCancel,
|
2024-07-31 15:49:35 +02:00
|
|
|
confirmLabel: confirmLabel,
|
2024-11-05 00:13:19 +01:00
|
|
|
confirmButtonColor: Theme.of(context).colorScheme.primary,
|
2024-07-31 15:49:35 +02:00
|
|
|
style: style,
|
|
|
|
closeOnAction: closeOnConfirm,
|
|
|
|
child: builder(context),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
2024-09-03 16:58:38 +08:00
|
|
|
|
|
|
|
Future<void> showCancelAndDeleteDialog({
|
|
|
|
required BuildContext context,
|
|
|
|
required String title,
|
|
|
|
required String description,
|
2024-09-15 23:46:41 +08:00
|
|
|
Widget Function(BuildContext)? builder,
|
2024-09-03 16:58:38 +08:00
|
|
|
VoidCallback? onDelete,
|
|
|
|
String? confirmLabel,
|
2024-09-16 21:01:08 +08:00
|
|
|
bool closeOnAction = false,
|
2024-09-03 16:58:38 +08:00
|
|
|
}) {
|
|
|
|
return showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (_) {
|
|
|
|
return Dialog(
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.circular(12.0),
|
|
|
|
),
|
|
|
|
child: SizedBox(
|
|
|
|
width: 440,
|
|
|
|
child: ConfirmPopup(
|
|
|
|
title: title,
|
|
|
|
description: description,
|
|
|
|
onConfirm: () => onDelete?.call(),
|
2024-09-16 21:01:08 +08:00
|
|
|
closeOnAction: closeOnAction,
|
2024-09-03 16:58:38 +08:00
|
|
|
confirmLabel: confirmLabel,
|
|
|
|
confirmButtonColor: Theme.of(context).colorScheme.error,
|
2024-09-15 23:46:41 +08:00
|
|
|
child: builder?.call(context),
|
2024-09-03 16:58:38 +08:00
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|