-
-
Notifications
You must be signed in to change notification settings - Fork 125
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
19 changed files
with
1,150 additions
and
23 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,2 @@ | ||
ignore: | ||
- influxui | ||
- vclibs |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
import 'package:biyi_app/utils/extended_colors.dart'; | ||
import 'package:biyi_app/widgets/alert/alert_style.dart'; | ||
import 'package:biyi_app/widgets/alert/alert_theme.dart'; | ||
import 'package:reflect_ui/reflect_ui.dart'; | ||
|
||
enum AlertType { | ||
success, | ||
info, | ||
warning, | ||
danger; | ||
} | ||
|
||
/// Attract user attention with important static message | ||
class Alert extends StatefulWidget { | ||
const Alert({ | ||
super.key, | ||
this.style, | ||
this.type = AlertType.info, | ||
this.icon, | ||
this.title, | ||
this.titleBuilder, | ||
this.message, | ||
this.messageBuilder, | ||
this.actions, | ||
}); | ||
|
||
final AlertStyle? style; | ||
|
||
/// Alert type | ||
final AlertType? type; | ||
|
||
final Widget? icon; | ||
|
||
/// Alert title | ||
final String? title; | ||
|
||
/// Alert title builder | ||
final WidgetBuilder? titleBuilder; | ||
|
||
/// Alert message | ||
final String? message; | ||
|
||
/// Alert message builder | ||
final WidgetBuilder? messageBuilder; | ||
|
||
final List<Widget>? actions; | ||
|
||
@override | ||
State<Alert> createState() => _AlertState(); | ||
} | ||
|
||
class _AlertState extends State<Alert> { | ||
@override | ||
Widget build(BuildContext context) { | ||
final AlertThemeData? themeData = AlertTheme.of(context); | ||
final AlertThemeData defaults = _AlertDefaults(context); | ||
AlertStyle mergedStyle = widget.style ?? const AlertStyle(); | ||
|
||
switch (widget.type!) { | ||
case AlertType.success: | ||
mergedStyle = mergedStyle // merge success style | ||
.merge(themeData?.successStyle) | ||
.merge(defaults.successStyle); | ||
break; | ||
case AlertType.info: | ||
mergedStyle = mergedStyle // merge info style | ||
.merge(themeData?.infoStyle) | ||
.merge(defaults.infoStyle); | ||
break; | ||
case AlertType.warning: | ||
mergedStyle = mergedStyle // merge warning style | ||
.merge(themeData?.warningStyle) | ||
.merge(defaults.warningStyle); | ||
break; | ||
case AlertType.danger: | ||
mergedStyle = mergedStyle // merge danger style | ||
.merge(themeData?.dangerStyle) | ||
.merge(defaults.dangerStyle); | ||
break; | ||
} | ||
|
||
final Widget? iconWidget = widget.icon != null | ||
? IconTheme( | ||
data: IconThemeData( | ||
size: mergedStyle.iconSize, | ||
color: mergedStyle.titleStyle!.color, | ||
), | ||
child: widget.icon!, | ||
) | ||
: null; | ||
|
||
final Widget? titleWidget = widget.titleBuilder != null | ||
? widget.titleBuilder!(context) | ||
: widget.title != null | ||
? Text(widget.title!) | ||
: null; | ||
|
||
final Widget? messageWidget = widget.messageBuilder != null | ||
? widget.messageBuilder!(context) | ||
: widget.message != null | ||
? Text(widget.message!) | ||
: null; | ||
|
||
return Container( | ||
padding: const EdgeInsets.all(12), | ||
decoration: BoxDecoration( | ||
color: mergedStyle.backgroundColor, | ||
), | ||
child: GappedRow( | ||
gap: 8, | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
if (iconWidget != null) iconWidget, | ||
Expanded( | ||
child: GappedColumn( | ||
gap: 8, | ||
mainAxisSize: MainAxisSize.min, | ||
crossAxisAlignment: CrossAxisAlignment.start, | ||
children: [ | ||
if (titleWidget != null) | ||
DefaultTextStyle( | ||
style: mergedStyle.titleStyle!, | ||
child: titleWidget, | ||
), | ||
if (messageWidget != null) | ||
DefaultTextStyle( | ||
style: mergedStyle.messageStyle!, | ||
child: messageWidget, | ||
), | ||
if ((widget.actions ?? []).isNotEmpty) | ||
Padding( | ||
padding: const EdgeInsets.only(top: 4), | ||
child: GappedRow(gap: 8, children: widget.actions!), | ||
), | ||
], | ||
), | ||
), | ||
], | ||
), | ||
); | ||
} | ||
} | ||
|
||
class _AlertDefaults extends AlertThemeData { | ||
_AlertDefaults(this.context) : super(); | ||
|
||
final BuildContext context; | ||
late final ThemeData _theme = Theme.of(context); | ||
|
||
@override | ||
AlertStyle? get successStyle { | ||
return AlertStyle.fromColor(_theme, ExtendedColors.green); | ||
} | ||
|
||
@override | ||
AlertStyle? get infoStyle { | ||
return AlertStyle.fromColor(_theme, ExtendedColors.blue); | ||
} | ||
|
||
@override | ||
AlertStyle? get warningStyle { | ||
return AlertStyle.fromColor(_theme, ExtendedColors.yellow); | ||
} | ||
|
||
@override | ||
AlertStyle? get dangerStyle { | ||
return AlertStyle.fromColor(_theme, ExtendedColors.red); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/material.dart' show MaterialColor, ThemeData; | ||
import 'package:flutter/widgets.dart'; | ||
|
||
class AlertStyle with Diagnosticable { | ||
const AlertStyle({ | ||
this.backgroundColor, | ||
this.iconSize, | ||
this.titleStyle, | ||
this.messageStyle, | ||
}); | ||
|
||
factory AlertStyle.fromColor(ThemeData theme, MaterialColor color) { | ||
return AlertStyle( | ||
backgroundColor: color.shade50, | ||
iconSize: 20, | ||
titleStyle: theme.textTheme.bodyMedium?.copyWith( | ||
color: color.shade700, | ||
fontWeight: FontWeight.w600, | ||
), | ||
messageStyle: theme.textTheme.bodyMedium?.copyWith( | ||
color: color.shade600, | ||
), | ||
); | ||
} | ||
|
||
final Color? backgroundColor; | ||
|
||
final double? iconSize; | ||
|
||
final TextStyle? titleStyle; | ||
|
||
final TextStyle? messageStyle; | ||
|
||
AlertStyle copyWith({ | ||
Color? backgroundColor, | ||
double? iconSize, | ||
TextStyle? titleStyle, | ||
TextStyle? messageStyle, | ||
}) { | ||
return AlertStyle( | ||
backgroundColor: backgroundColor ?? this.backgroundColor, | ||
iconSize: iconSize ?? this.iconSize, | ||
titleStyle: titleStyle ?? this.titleStyle, | ||
messageStyle: messageStyle ?? this.messageStyle, | ||
); | ||
} | ||
|
||
/// Returns a copy of this AlertStyle where the non-null fields in [style] | ||
/// have replaced the corresponding null fields in this AlertStyle. | ||
/// | ||
/// In other words, [style] is used to fill in unspecified (null) fields | ||
/// this AlertStyle. | ||
AlertStyle merge(AlertStyle? style) { | ||
if (style == null) { | ||
return this; | ||
} | ||
return copyWith( | ||
backgroundColor: style.backgroundColor, | ||
iconSize: iconSize ?? style.iconSize, | ||
titleStyle: titleStyle ?? style.titleStyle, | ||
messageStyle: messageStyle ?? style.messageStyle, | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
// ignore_for_file: annotate_overrides | ||
|
||
import 'package:biyi_app/widgets/alert/alert_style.dart'; | ||
import 'package:flutter/foundation.dart'; | ||
import 'package:flutter/material.dart'; | ||
import 'package:theme_tailor_annotation/theme_tailor_annotation.dart'; | ||
|
||
part 'alert_theme.tailor.dart'; | ||
|
||
@TailorMixin() | ||
class AlertThemeData extends ThemeExtension<AlertThemeData> | ||
with DiagnosticableTreeMixin, _$AlertThemeDataTailorMixin { | ||
const AlertThemeData({ | ||
this.successStyle, | ||
this.infoStyle, | ||
this.warningStyle, | ||
this.dangerStyle, | ||
}); | ||
|
||
final AlertStyle? successStyle; | ||
final AlertStyle? infoStyle; | ||
final AlertStyle? warningStyle; | ||
final AlertStyle? dangerStyle; | ||
} | ||
|
||
class AlertTheme extends InheritedTheme { | ||
const AlertTheme({ | ||
super.key, | ||
required this.data, | ||
required super.child, | ||
}); | ||
|
||
final AlertThemeData data; | ||
|
||
static AlertThemeData? of(BuildContext context) { | ||
final theme = context.dependOnInheritedWidgetOfExactType<AlertTheme>(); | ||
return theme?.data ?? Theme.of(context).extension<AlertThemeData>(); | ||
} | ||
|
||
@override | ||
Widget wrap(BuildContext context, Widget child) { | ||
return AlertTheme(data: data, child: child); | ||
} | ||
|
||
@override | ||
bool updateShouldNotify(AlertTheme oldWidget) => data != oldWidget.data; | ||
} |
Oops, something went wrong.