2022-08-29 20:38:28 -06:00
|
|
|
import 'package:flutter_svg/flutter_svg.dart';
|
|
|
|
import 'package:package_info_plus/package_info_plus.dart';
|
|
|
|
import 'package:wonders/common_libs.dart';
|
|
|
|
import 'package:wonders/logic/data/wonder_data.dart';
|
|
|
|
import 'package:wonders/ui/common/app_backdrop.dart';
|
|
|
|
import 'package:wonders/ui/common/app_icons.dart';
|
2022-12-22 10:36:46 -07:00
|
|
|
import 'package:wonders/ui/common/controls/app_header.dart';
|
2022-09-07 13:28:41 -06:00
|
|
|
import 'package:wonders/ui/common/controls/locale_switcher.dart';
|
2022-12-19 14:13:25 -07:00
|
|
|
import 'package:wonders/ui/common/pop_navigator_underlay.dart';
|
2022-08-29 20:38:28 -06:00
|
|
|
import 'package:wonders/ui/screens/home_menu/about_dialog_content.dart';
|
|
|
|
|
2022-12-21 10:57:31 -07:00
|
|
|
class HomeMenu extends StatefulWidget {
|
2022-08-29 20:38:28 -06:00
|
|
|
const HomeMenu({Key? key, required this.data}) : super(key: key);
|
|
|
|
final WonderData data;
|
|
|
|
|
2022-12-21 10:57:31 -07:00
|
|
|
@override
|
|
|
|
State<HomeMenu> createState() => _HomeMenuState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _HomeMenuState extends State<HomeMenu> {
|
2022-08-29 20:38:28 -06:00
|
|
|
void _handleAboutPressed(BuildContext context) async {
|
|
|
|
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
2022-12-21 10:57:31 -07:00
|
|
|
if (!mounted) return;
|
2022-08-29 20:38:28 -06:00
|
|
|
showAboutDialog(
|
|
|
|
context: context,
|
|
|
|
applicationName: $strings.appName,
|
|
|
|
applicationVersion: packageInfo.version,
|
|
|
|
applicationLegalese: '© 2022 gskinner',
|
|
|
|
children: [AboutDialogContent()],
|
|
|
|
applicationIcon: Container(
|
|
|
|
color: $styles.colors.black,
|
|
|
|
padding: EdgeInsets.all($styles.insets.xs),
|
|
|
|
child: Image.asset(
|
|
|
|
ImagePaths.appLogoPlain,
|
|
|
|
fit: BoxFit.cover,
|
|
|
|
width: 52,
|
|
|
|
filterQuality: FilterQuality.high,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
void _handleCollectionPressed(BuildContext context) => context.push(ScreenPaths.collection(''));
|
|
|
|
|
2022-12-21 10:57:31 -07:00
|
|
|
void _handleTimelinePressed(BuildContext context) => context.push(ScreenPaths.timeline(widget.data.type));
|
2022-08-29 20:38:28 -06:00
|
|
|
|
|
|
|
void _handleWonderPressed(BuildContext context, WonderData data) => Navigator.pop(context, data.type);
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2022-11-14 15:53:48 -07:00
|
|
|
final double gridWidth = (context.heightPx / 2).clamp(200, 350);
|
2022-08-29 20:38:28 -06:00
|
|
|
return Stack(
|
|
|
|
children: [
|
|
|
|
/// Backdrop / Underlay
|
|
|
|
AppBackdrop(
|
|
|
|
strength: .5,
|
2023-01-04 21:32:50 -07:00
|
|
|
child: Container(color: $styles.colors.greyStrong.withOpacity(.5)),
|
2022-08-29 20:38:28 -06:00
|
|
|
),
|
|
|
|
|
2022-12-19 14:13:25 -07:00
|
|
|
PopNavigatorUnderlay(),
|
|
|
|
|
2022-12-22 10:36:46 -07:00
|
|
|
AppHeader(
|
|
|
|
isTransparent: true,
|
2022-12-22 13:24:55 -07:00
|
|
|
backIcon: AppIcons.close,
|
2022-12-22 10:36:46 -07:00
|
|
|
trailing: (_) => LocaleSwitcher(),
|
2022-09-07 13:28:41 -06:00
|
|
|
),
|
2022-08-29 20:38:28 -06:00
|
|
|
|
|
|
|
/// Content
|
|
|
|
Positioned.fill(
|
|
|
|
child: SafeArea(
|
|
|
|
child: Padding(
|
2022-10-27 10:23:07 -06:00
|
|
|
padding: EdgeInsets.symmetric(horizontal: $styles.insets.lg).copyWith(top: $styles.insets.lg),
|
2022-10-07 11:53:52 -06:00
|
|
|
child: Center(
|
|
|
|
child: SizedBox(
|
|
|
|
width: gridWidth,
|
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.end,
|
|
|
|
children: [
|
|
|
|
Gap($styles.insets.md),
|
|
|
|
Spacer(),
|
|
|
|
_buildIconGrid(context)
|
|
|
|
.animate()
|
|
|
|
.fade(duration: $styles.times.fast)
|
|
|
|
.scale(begin: .8, curve: Curves.easeOut),
|
|
|
|
Gap($styles.insets.lg),
|
|
|
|
_buildBottomBtns(context),
|
|
|
|
Spacer(),
|
|
|
|
Gap($styles.insets.md),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
2022-08-29 20:38:28 -06:00
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2022-09-06 16:31:22 -06:00
|
|
|
),
|
2022-08-29 20:38:28 -06:00
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _buildIconGrid(BuildContext context) {
|
|
|
|
return GridView.count(
|
|
|
|
physics: NeverScrollableScrollPhysics(),
|
|
|
|
crossAxisCount: 3,
|
|
|
|
clipBehavior: Clip.none,
|
|
|
|
shrinkWrap: true,
|
|
|
|
crossAxisSpacing: $styles.insets.sm,
|
|
|
|
mainAxisSpacing: $styles.insets.sm,
|
|
|
|
children: [
|
|
|
|
_buildGridBtn(context, wondersLogic.all[0]),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[1]),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[2]),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[3]),
|
|
|
|
Padding(
|
|
|
|
padding: EdgeInsets.all($styles.insets.sm),
|
|
|
|
child: SvgPicture.asset(SvgPaths.compassFull, color: $styles.colors.offWhite),
|
|
|
|
),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[4]),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[5]),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[6]),
|
|
|
|
_buildGridBtn(context, wondersLogic.all[7]),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
Widget _buildBottomBtns(BuildContext context) {
|
2022-09-01 14:45:55 -06:00
|
|
|
return ValueListenableBuilder(
|
|
|
|
valueListenable: settingsLogic.currentLocale,
|
|
|
|
builder: (_, __, ___) {
|
|
|
|
return SeparatedColumn(
|
|
|
|
separatorBuilder: () => Divider(thickness: 1.5, height: 1).animate().scale(
|
|
|
|
duration: $styles.times.slow,
|
|
|
|
delay: $styles.times.pageTransition + 200.ms,
|
|
|
|
curve: Curves.easeOutBack,
|
|
|
|
),
|
|
|
|
children: [
|
|
|
|
_MenuTextBtn(
|
|
|
|
label: $strings.homeMenuButtonExplore,
|
|
|
|
icon: AppIcons.timeline,
|
|
|
|
onPressed: () => _handleTimelinePressed(context)),
|
|
|
|
_MenuTextBtn(
|
|
|
|
label: $strings.homeMenuButtonView,
|
|
|
|
icon: AppIcons.collection,
|
|
|
|
onPressed: () => _handleCollectionPressed(context)),
|
|
|
|
_MenuTextBtn(
|
|
|
|
label: $strings.homeMenuButtonAbout,
|
|
|
|
icon: AppIcons.info,
|
|
|
|
onPressed: () => _handleAboutPressed(context),
|
|
|
|
),
|
|
|
|
]
|
|
|
|
.animate(interval: 50.ms)
|
|
|
|
.fade(delay: $styles.times.pageTransition + 50.ms)
|
|
|
|
.slide(begin: Offset(0, .1), curve: Curves.easeOut),
|
|
|
|
);
|
|
|
|
});
|
2022-08-29 20:38:28 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
Widget _buildGridBtn(BuildContext context, WonderData btnData) {
|
2022-12-21 10:57:31 -07:00
|
|
|
bool isSelected = btnData == widget.data;
|
2022-08-29 20:38:28 -06:00
|
|
|
return AspectRatio(
|
|
|
|
aspectRatio: 1,
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
borderRadius: BorderRadius.circular($styles.corners.md),
|
|
|
|
boxShadow: !isSelected
|
|
|
|
? null
|
|
|
|
: [
|
|
|
|
BoxShadow(
|
|
|
|
color: Colors.black.withOpacity(.3),
|
|
|
|
blurRadius: 3,
|
|
|
|
spreadRadius: 3,
|
|
|
|
offset: Offset(0, 2),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
child: ClipRRect(
|
|
|
|
borderRadius: BorderRadius.circular($styles.corners.md),
|
|
|
|
child: AppBtn(
|
|
|
|
border: !isSelected ? null : BorderSide(color: $styles.colors.offWhite, width: 5),
|
|
|
|
bgColor: btnData.type.fgColor,
|
|
|
|
onPressed: () => _handleWonderPressed(context, btnData),
|
|
|
|
padding: EdgeInsets.zero,
|
|
|
|
semanticLabel: btnData.title,
|
|
|
|
child: SizedBox.expand(child: Image.asset(btnData.type.homeBtn, fit: BoxFit.cover)),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class _MenuTextBtn extends StatelessWidget {
|
|
|
|
const _MenuTextBtn({Key? key, required this.label, required this.onPressed, required this.icon}) : super(key: key);
|
|
|
|
final String label;
|
|
|
|
final VoidCallback onPressed;
|
|
|
|
final AppIcons icon;
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return AppBtn(
|
|
|
|
expand: true,
|
2022-10-27 10:23:07 -06:00
|
|
|
padding: EdgeInsets.symmetric(vertical: $styles.insets.md),
|
2022-08-29 20:38:28 -06:00
|
|
|
onPressed: onPressed,
|
|
|
|
bgColor: Colors.transparent,
|
|
|
|
semanticLabel: label,
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: [
|
|
|
|
AppIcon(icon, color: $styles.colors.offWhite),
|
|
|
|
Gap($styles.insets.xs),
|
|
|
|
Text(label, style: $styles.text.bodyBold.copyWith(height: 1)),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|