diff --git a/lib/ui/home_widget.dart b/lib/ui/home_widget.dart index b54308304..189996a26 100644 --- a/lib/ui/home_widget.dart +++ b/lib/ui/home_widget.dart @@ -4,7 +4,6 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; -import 'package:google_nav_bar/google_nav_bar.dart'; import 'package:photos/core/configuration.dart'; import 'package:photos/core/event_bus.dart'; import 'package:photos/events/local_photos_updated_event.dart'; @@ -21,6 +20,7 @@ import 'package:photos/ui/loading_photos_widget.dart'; import 'package:photos/ui/loading_widget.dart'; import 'package:photos/ui/memories_widget.dart'; import 'package:photos/services/user_service.dart'; +import 'package:photos/ui/nav_bar.dart'; import 'package:photos/ui/settings_button.dart'; import 'package:photos/ui/shared_collections_gallery.dart'; import 'package:logging/logging.dart'; diff --git a/lib/ui/nav_bar.dart b/lib/ui/nav_bar.dart new file mode 100644 index 000000000..2b7904d81 --- /dev/null +++ b/lib/ui/nav_bar.dart @@ -0,0 +1,430 @@ +library google_nav_bar; + +import 'dart:async'; +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + +class GNav extends StatefulWidget { + const GNav({ + Key key, + this.tabs, + this.selectedIndex = 0, + this.onTabChange, + this.gap, + this.padding, + this.activeColor, + this.color, + this.rippleColor, + this.hoverColor, + this.backgroundColor, + this.tabBackgroundColor, + this.tabBorderRadius, + this.iconSize, + this.textStyle, + this.curve, + this.tabMargin, + this.debug, + this.duration, + this.tabBorder, + this.tabActiveBorder, + this.tabShadow, + this.haptic, + this.tabBackgroundGradient, + this.mainAxisAlignment = MainAxisAlignment.spaceBetween, + }) : super(key: key); + + final List tabs; + final int selectedIndex; + final Function onTabChange; + final double gap; + final double tabBorderRadius; + final double iconSize; + final Color activeColor; + final Color backgroundColor; + final Color tabBackgroundColor; + final Color color; + final Color rippleColor; + final Color hoverColor; + final EdgeInsetsGeometry padding; + final EdgeInsetsGeometry tabMargin; + final TextStyle textStyle; + final Duration duration; + final Curve curve; + final bool debug; + final bool haptic; + final Border tabBorder; + final Border tabActiveBorder; + final List tabShadow; + final Gradient tabBackgroundGradient; + final MainAxisAlignment mainAxisAlignment; + + @override + _GNavState createState() => _GNavState(); +} + +class _GNavState extends State { + int selectedIndex; + bool clickable = true; + + @override + void initState() { + super.initState(); + } + + @override + Widget build(BuildContext context) { + selectedIndex = widget.selectedIndex; + + return Container( + color: widget.backgroundColor ?? Colors.transparent, + // padding: EdgeInsets.all(12), + // alignment: Alignment.center, + child: Row( + mainAxisAlignment: widget.mainAxisAlignment, + children: widget.tabs + .map((t) => GButton( + key: t.key, + border: t.border ?? widget.tabBorder, + activeBorder: t.activeBorder ?? widget.tabActiveBorder, + shadow: t.shadow ?? widget.tabShadow, + borderRadius: + t.borderRadius ?? widget.tabBorderRadius != null + ? BorderRadius.all( + Radius.circular(widget.tabBorderRadius)) + : const BorderRadius.all(Radius.circular(100.0)), + debug: widget.debug ?? false, + margin: t.margin ?? widget.tabMargin, + active: selectedIndex == widget.tabs.indexOf(t), + gap: t.gap ?? widget.gap, + iconActiveColor: t.iconActiveColor ?? widget.activeColor, + iconColor: t.iconColor ?? widget.color, + iconSize: t.iconSize ?? widget.iconSize, + textColor: t.textColor ?? widget.activeColor, + rippleColor: t.rippleColor ?? + widget.rippleColor ?? + Colors.transparent, + hoverColor: t.hoverColor ?? + widget.hoverColor ?? + Colors.transparent, + padding: t.padding ?? widget.padding, + textStyle: t.textStyle ?? widget.textStyle, + text: t.text, + icon: t.icon, + haptic: widget.haptic ?? true, + leading: t.leading, + curve: widget.curve ?? Curves.easeInCubic, + backgroundGradient: + t.backgroundGradient ?? widget.tabBackgroundGradient, + backgroundColor: t.backgroundColor ?? + widget.tabBackgroundColor ?? + Colors.transparent, + duration: + widget.duration ?? const Duration(milliseconds: 500), + onPressed: () { + if (!clickable) return; + setState(() { + selectedIndex = widget.tabs.indexOf(t); + clickable = false; + }); + widget.onTabChange(selectedIndex); + + Future.delayed( + widget.duration ?? + const Duration(milliseconds: 500), () { + setState(() { + clickable = true; + }); + }); + }, + )) + .toList())); + } +} + +class GButton extends StatefulWidget { + final bool active; + final bool debug; + final bool haptic; + final double gap; + final Color iconColor; + final Color rippleColor; + final Color hoverColor; + final Color iconActiveColor; + final Color textColor; + final EdgeInsetsGeometry padding; + final EdgeInsetsGeometry margin; + final TextStyle textStyle; + final double iconSize; + final Function onPressed; + final String text; + final IconData icon; + final Color backgroundColor; + final Duration duration; + final Curve curve; + final Gradient backgroundGradient; + final Widget leading; + final BorderRadius borderRadius; + final Border border; + final Border activeBorder; + final List shadow; + final String semanticLabel; + + const GButton({ + Key key, + this.active, + this.haptic, + this.backgroundColor, + this.icon, + this.iconColor, + this.rippleColor, + this.hoverColor, + this.iconActiveColor, + this.text = '', + this.textColor, + this.padding, + this.margin, + this.duration, + this.debug, + this.gap, + this.curve, + this.textStyle, + this.iconSize, + this.leading, + this.onPressed, + this.backgroundGradient, + this.borderRadius, + this.border, + this.activeBorder, + this.shadow, + this.semanticLabel, + }) : super(key: key); + + @override + _GButtonState createState() => _GButtonState(); +} + +class _GButtonState extends State { + @override + Widget build(BuildContext context) { + return Semantics( + label: widget.semanticLabel ?? widget.text, + child: Button( + borderRadius: widget.borderRadius, + border: widget.border, + activeBorder: widget.activeBorder, + shadow: widget.shadow, + debug: widget.debug, + duration: widget.duration, + iconSize: widget.iconSize, + active: widget.active, + onPressed: () { + if (widget.haptic) HapticFeedback.selectionClick(); + widget.onPressed(); + }, + padding: widget.padding, + margin: widget.margin, + gap: widget.gap, + color: widget.backgroundColor, + rippleColor: widget.rippleColor, + hoverColor: widget.hoverColor, + gradient: widget.backgroundGradient, + curve: widget.curve, + leading: widget.leading, + iconActiveColor: widget.iconActiveColor, + iconColor: widget.iconColor, + icon: widget.icon, + text: Text( + widget.text, + style: widget.textStyle ?? + TextStyle(fontWeight: FontWeight.w600, color: widget.textColor), + ), + ), + ); + } +} + +class Button extends StatefulWidget { + const Button( + {Key key, + this.icon, + this.iconSize, + this.leading, + this.iconActiveColor, + this.iconColor, + this.text, + this.gap = 0, + this.color, + this.rippleColor, + this.hoverColor, + this.onPressed, + this.duration, + this.curve, + this.padding = const EdgeInsets.all(25), + this.margin = const EdgeInsets.all(0), + this.active = false, + this.debug, + this.gradient, + this.borderRadius = const BorderRadius.all(Radius.circular(100.0)), + this.border, + this.activeBorder, + this.shadow}) + : super(key: key); + + final IconData icon; + final double iconSize; + final Text text; + final Widget leading; + final Color iconActiveColor; + final Color iconColor; + final Color color; + final Color rippleColor; + final Color hoverColor; + final double gap; + final bool active; + final bool debug; + final VoidCallback onPressed; + final EdgeInsetsGeometry padding; + final EdgeInsetsGeometry margin; + final Duration duration; + final Curve curve; + final Gradient gradient; + final BorderRadius borderRadius; + final Border border; + final Border activeBorder; + final List shadow; + + @override + _ButtonState createState() => _ButtonState(); +} + +class _ButtonState extends State