veilidchat/lib/theme/views/widget_helpers.dart

233 lines
7.4 KiB
Dart
Raw Normal View History

2024-02-11 00:29:58 -05:00
import 'package:async_tools/async_tools.dart';
2023-09-23 22:19:53 -04:00
import 'package:awesome_extensions/awesome_extensions.dart';
2024-02-27 12:45:58 -05:00
import 'package:bloc_tools/bloc_tools.dart';
2023-07-24 09:31:51 -04:00
import 'package:blurry_modal_progress_hud/blurry_modal_progress_hud.dart';
2023-07-26 14:20:29 -04:00
import 'package:flutter/material.dart';
2024-01-09 20:58:27 -05:00
import 'package:flutter_bloc/flutter_bloc.dart';
2023-07-24 09:31:51 -04:00
import 'package:flutter_spinkit/flutter_spinkit.dart';
2023-08-04 01:00:38 -04:00
import 'package:flutter_translate/flutter_translate.dart';
2023-08-02 21:09:28 -04:00
import 'package:motion_toast/motion_toast.dart';
2023-07-28 20:36:05 -04:00
import 'package:quickalert/quickalert.dart';
2023-07-23 23:13:21 -04:00
import '../theme.dart';
2023-08-02 21:09:28 -04:00
2023-07-23 23:13:21 -04:00
extension BorderExt on Widget {
2023-07-26 15:58:38 -04:00
DecoratedBox debugBorder() => DecoratedBox(
decoration: BoxDecoration(border: Border.all(color: Colors.redAccent)),
child: this);
2023-07-23 23:13:21 -04:00
}
2023-07-24 09:31:51 -04:00
extension ModalProgressExt on Widget {
2023-08-02 21:09:28 -04:00
BlurryModalProgressHUD withModalHUD(BuildContext context, bool isLoading) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
return BlurryModalProgressHUD(
inAsyncCall: isLoading,
blurEffectIntensity: 4,
2024-02-11 14:17:10 -05:00
progressIndicator: buildProgressIndicator(),
2023-08-02 21:09:28 -04:00
color: scale.tertiaryScale.appBackground.withAlpha(64),
child: this);
}
2023-07-24 09:31:51 -04:00
}
2023-07-28 20:36:05 -04:00
2024-02-11 14:17:10 -05:00
Widget buildProgressIndicator() => Builder(builder: (context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
return SpinKitFoldingCube(
color: scale.tertiaryScale.primary,
2024-02-11 14:17:10 -05:00
size: 80,
);
});
Widget waitingPage({String? text}) => Builder(builder: (context) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
return ColoredBox(
color: scale.tertiaryScale.primaryText,
child: Center(
child: Column(children: [
buildProgressIndicator().expanded(),
if (text != null) Text(text)
])));
});
2023-07-28 20:36:05 -04:00
2024-02-11 14:17:10 -05:00
Widget debugPage(String text) => Builder(
builder: (context) => ColoredBox(
color: Theme.of(context).colorScheme.error,
child: Center(child: Text(text))));
2023-07-28 20:36:05 -04:00
2024-02-11 14:17:10 -05:00
Widget errorPage(Object err, StackTrace? st) => Builder(
builder: (context) => ColoredBox(
2024-01-08 21:37:08 -05:00
color: Theme.of(context).colorScheme.error,
2024-02-11 14:17:10 -05:00
child: Center(child: ErrorWidget(err))));
2024-01-08 21:37:08 -05:00
Widget asyncValueBuilder<T>(
AsyncValue<T> av, Widget Function(BuildContext, T) builder) =>
av.when(
2024-02-11 14:17:10 -05:00
loading: waitingPage,
error: errorPage,
2024-01-08 21:37:08 -05:00
data: (d) => Builder(builder: (context) => builder(context, d)));
extension AsyncValueBuilderExt<T> on AsyncValue<T> {
Widget builder(Widget Function(BuildContext, T) builder) =>
asyncValueBuilder<T>(this, builder);
2024-02-11 14:17:10 -05:00
Widget buildNotData(
{Widget Function()? loading,
Widget Function(Object, StackTrace?)? error}) =>
when(
loading: () => (loading ?? waitingPage)(),
error: (e, st) => (error ?? errorPage)(e, st),
data: (d) => debugPage('AsyncValue should not be data here'));
2024-01-08 21:37:08 -05:00
}
2024-02-27 12:45:58 -05:00
extension BusyAsyncValueBuilderExt<T> on BlocBusyState<AsyncValue<T>> {
Widget builder(Widget Function(BuildContext, T) builder) =>
AbsorbPointer(absorbing: busy, child: state.builder(builder));
Widget buildNotData(
{Widget Function()? loading,
Widget Function(Object, StackTrace?)? error}) =>
AbsorbPointer(
absorbing: busy,
child: state.buildNotData(loading: loading, error: error));
}
2024-01-09 20:58:27 -05:00
class AsyncBlocBuilder<B extends StateStreamable<AsyncValue<S>>, S>
extends BlocBuilder<B, AsyncValue<S>> {
AsyncBlocBuilder({
required BlocWidgetBuilder<S> builder,
2024-02-11 14:17:10 -05:00
Widget Function()? loading,
Widget Function(Object, StackTrace?)? error,
2024-01-09 20:58:27 -05:00
super.key,
super.bloc,
super.buildWhen,
}) : super(
builder: (context, state) => state.when(
2024-02-11 14:17:10 -05:00
loading: () => (loading ?? waitingPage)(),
error: (e, st) => (error ?? errorPage)(e, st),
2024-01-09 20:58:27 -05:00
data: (d) => builder(context, d)));
}
2023-07-28 20:36:05 -04:00
Future<void> showErrorModal(
BuildContext context, String title, String text) async {
await QuickAlert.show(
context: context,
type: QuickAlertType.error,
title: title,
text: text,
//backgroundColor: Colors.black,
//titleColor: Colors.white,
//textColor: Colors.white,
);
}
2023-08-02 21:09:28 -04:00
void showErrorToast(BuildContext context, String message) {
MotionToast.error(
2023-08-04 01:00:38 -04:00
title: Text(translate('toast.error')),
description: Text(message),
).show(context);
}
void showInfoToast(BuildContext context, String message) {
MotionToast.info(
title: Text(translate('toast.info')),
2023-08-02 21:09:28 -04:00
description: Text(message),
).show(context);
}
2023-09-23 22:19:53 -04:00
// Widget insetBorder(
// {required BuildContext context,
// required bool enabled,
// required Color color,
// required Widget child}) {
// if (!enabled) {
// return child;
// }
// return Stack({
// children: [] {
// DecoratedBox(decoration: BoxDecoration()
// child,
// }
// })
// }
2024-04-07 23:16:06 -04:00
Widget styledTitleContainer({
required BuildContext context,
required String title,
required Widget child,
Color? borderColor,
Color? backgroundColor,
Color? titleColor,
2024-04-07 23:16:06 -04:00
}) {
2023-09-23 22:19:53 -04:00
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final textTheme = theme.textTheme;
2023-09-24 15:30:54 -04:00
return DecoratedBox(
2023-09-23 22:19:53 -04:00
decoration: ShapeDecoration(
2024-04-07 23:16:06 -04:00
color: borderColor ?? scale.primaryScale.border,
2023-09-23 22:19:53 -04:00
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
)),
child: Column(children: [
Text(
title,
style: textTheme.titleMedium!
.copyWith(color: titleColor ?? scale.primaryScale.borderText),
2024-04-10 16:13:08 -04:00
).paddingLTRB(8, 8, 8, 4),
2023-09-23 22:19:53 -04:00
DecoratedBox(
decoration: ShapeDecoration(
2024-04-07 23:16:06 -04:00
color:
backgroundColor ?? scale.primaryScale.subtleBackground,
2023-09-23 22:19:53 -04:00
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(16),
)),
child: child)
.paddingAll(4)
.expanded()
]));
}
2024-04-10 16:13:08 -04:00
Widget styledBottomSheet({
required BuildContext context,
required String title,
required Widget child,
Color? borderColor,
Color? backgroundColor,
Color? titleColor,
2024-04-10 16:13:08 -04:00
}) {
final theme = Theme.of(context);
final scale = theme.extension<ScaleScheme>()!;
final textTheme = theme.textTheme;
return DecoratedBox(
decoration: ShapeDecoration(
color: borderColor ?? scale.primaryScale.dialogBorder,
2024-04-10 16:13:08 -04:00
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)))),
child: Column(mainAxisSize: MainAxisSize.min, children: [
Text(
title,
style: textTheme.titleMedium!
.copyWith(color: titleColor ?? scale.primaryScale.borderText),
2024-04-10 16:13:08 -04:00
).paddingLTRB(8, 8, 8, 4),
DecoratedBox(
decoration: ShapeDecoration(
color:
backgroundColor ?? scale.primaryScale.subtleBackground,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16)))),
child: child)
.paddingLTRB(4, 4, 4, 0)
]));
}
2024-01-08 21:37:08 -05:00
bool get isPlatformDark =>
WidgetsBinding.instance.platformDispatcher.platformBrightness ==
Brightness.dark;