Skip to content

Commit

Permalink
[Presentation] Added a custom scaffold for mobile and desktop / tablet
Browse files Browse the repository at this point in the history
  • Loading branch information
Wolfteam committed Jul 11, 2021
1 parent b8fc6a1 commit d76725f
Show file tree
Hide file tree
Showing 27 changed files with 772 additions and 459 deletions.
135 changes: 135 additions & 0 deletions lib/presentation/desktop_tablet_scaffold.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:genshindb/application/bloc.dart';
import 'package:genshindb/generated/l10n.dart';
import 'package:genshindb/presentation/artifacts/artifacts_page.dart';
import 'package:genshindb/presentation/characters/characters_page.dart';
import 'package:genshindb/presentation/home/home_page.dart';
import 'package:genshindb/presentation/map/map_page.dart';
import 'package:genshindb/presentation/settings/settings_page.dart';
import 'package:genshindb/presentation/shared/extensions/focus_scope_node_extensions.dart';
import 'package:genshindb/presentation/shared/genshin_db_icons.dart';
import 'package:genshindb/presentation/weapons/weapons_page.dart';

typedef OnWillPop = Future<bool> Function();

class DesktopTabletScaffold extends StatefulWidget {
final int defaultIndex;
final TabController tabController;

const DesktopTabletScaffold({
Key? key,
required this.defaultIndex,
required this.tabController,
}) : super(key: key);

@override
_DesktopTabletScaffoldState createState() => _DesktopTabletScaffoldState();
}

class _DesktopTabletScaffoldState extends State<DesktopTabletScaffold> {
late int _index;

@override
void initState() {
_index = widget.defaultIndex;
super.initState();
}

@override
Widget build(BuildContext context) {
final s = S.of(context);
final extended = MediaQuery.of(context).orientation != Orientation.portrait;
return Scaffold(
body: SafeArea(
child: BlocListener<MainTabBloc, MainTabState>(
listener: (ctx, state) async {
state.maybeMap(
initial: (s) => _changeCurrentTab(s.currentSelectedTab),
orElse: () => {},
);
},
child: Row(
children: <Widget>[
NavigationRail(
selectedIndex: _index,
onDestinationSelected: (index) => _gotoTab(index),
labelType: extended ? null : NavigationRailLabelType.selected,
extended: extended,
destinations: <NavigationRailDestination>[
NavigationRailDestination(
icon: const Icon(Icons.people),
selectedIcon: const Icon(Icons.people),
label: Text(s.characters),
),
NavigationRailDestination(
icon: const Icon(GenshinDb.crossed_swords),
selectedIcon: const Icon(GenshinDb.crossed_swords),
label: Text(s.weapons),
),
NavigationRailDestination(
icon: const Icon(Icons.home),
selectedIcon: const Icon(Icons.home),
label: Text(s.home),
),
NavigationRailDestination(
icon: const Icon(GenshinDb.overmind),
selectedIcon: const Icon(GenshinDb.overmind),
label: Text(s.artifacts),
),
NavigationRailDestination(
icon: const Icon(Icons.map),
selectedIcon: const Icon(Icons.map),
label: Text(s.map),
),
NavigationRailDestination(
icon: const Icon(Icons.settings),
selectedIcon: const Icon(Icons.settings),
label: Text(s.settings),
),
],
),
const VerticalDivider(thickness: 1, width: 1),
// This is the main content.
Expanded(
child: TabBarView(
controller: widget.tabController,
physics: const NeverScrollableScrollPhysics(),
children: [
const CharactersPage(),
const WeaponsPage(),
HomePage(),
const ArtifactsPage(),
MapPage(),
],
),
)
],
),
),
),
);
}

void _changeCurrentTab(int index) {
FocusScope.of(context).removeFocus();
widget.tabController.index = index;

setState(() {
_index = index;
});
}

Future<void> _gotoTab(int newIndex) async {
if (newIndex == 5) {
await _gotoSettingsPage();
return;
}
context.read<MainTabBloc>().add(MainTabEvent.goToTab(index: newIndex));
}

Future<void> _gotoSettingsPage() async {
final route = MaterialPageRoute(builder: (c) => SettingsPage());
await Navigator.push(context, route);
}
}
146 changes: 88 additions & 58 deletions lib/presentation/home/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:genshindb/application/bloc.dart';
import 'package:genshindb/generated/l10n.dart';
import 'package:genshindb/presentation/home/widgets/sliver_calculators_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_daily_check_in_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_game_codes_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_materials_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_monsters_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_notifications_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_settings_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_tierlist_card.dart';
import 'package:genshindb/presentation/home/widgets/sliver_wish_simulator_card.dart';
import 'package:genshindb/presentation/home/widgets/calculators_card.dart';
import 'package:genshindb/presentation/home/widgets/daily_check_in_card.dart';
import 'package:genshindb/presentation/home/widgets/elements_card.dart';
import 'package:genshindb/presentation/home/widgets/game_codes_card.dart';
import 'package:genshindb/presentation/home/widgets/materials_card.dart';
import 'package:genshindb/presentation/home/widgets/monsters_card.dart';
import 'package:genshindb/presentation/home/widgets/notifications_card.dart';
import 'package:genshindb/presentation/home/widgets/settings_card.dart';
import 'package:genshindb/presentation/home/widgets/tierlist_card.dart';
import 'package:genshindb/presentation/home/widgets/wish_simulator_card.dart';
import 'package:genshindb/presentation/today_materials/today_materials_page.dart';
import 'package:responsive_builder/responsive_builder.dart';

import 'widgets/my_inventory_card.dart';
import 'widgets/sliver_characters_birthday_card.dart';
import 'widgets/sliver_elements_card.dart';
import 'widgets/sliver_main_title.dart';
import 'widgets/sliver_my_inventory_card.dart';
import 'widgets/sliver_settings_card.dart';
import 'widgets/sliver_tierlist_card.dart';
import 'widgets/sliver_today_char_ascension_materials.dart';
import 'widgets/sliver_today_main_title.dart';
import 'widgets/sliver_today_weapon_materials.dart';
import 'widgets/tierlist_card.dart';

class HomePage extends StatefulWidget {
@override
Expand All @@ -45,61 +45,91 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin<
SliverTodayCharAscensionMaterials(),
_buildClickableTitle(s.forWeapons, s.seeAll, context, onClick: () => _gotoMaterialsPage(context)),
SliverTodayWeaponMaterials(),
SliverMainTitle(title: s.elements),
SliverElementsCard(),
..._buildMenu(s),
SliverMainTitle(title: s.gameSpecific),
SliverToBoxAdapter(
child: SizedBox(
height: 160,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) => _buildGameSectionMenus(index),
),
),
),
SliverMainTitle(title: s.tools),
SliverToBoxAdapter(
child: SizedBox(
height: 160,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: 4,
itemBuilder: (context, index) => _buildToolsSectionMenu(index),
),
),
),
SliverMainTitle(title: s.others),
SliverToBoxAdapter(
child: SizedBox(
height: 160,
child: ListView.builder(
physics: const BouncingScrollPhysics(),
scrollDirection: Axis.horizontal,
itemCount: 3,
itemBuilder: (context, index) => _buildOthersSectionMenu(index),
),
),
),
SliverToBoxAdapter(
child: ResponsiveBuilder(
builder: (ctx, size) => size.deviceScreenType == DeviceScreenType.desktop || size.deviceScreenType == DeviceScreenType.tablet
? const SizedBox(height: 1)
: const SettingsCard(iconToTheLeft: true),
),
),
],
);
}

List<Widget> _buildMenu(S s) {
var iconToTheLeft = false;
final map = <String, int>{
s.myInventory: 1,
s.calculators: 2,
s.materials: 3,
s.notifications: 4,
s.monsters: 5,
s.dailyCheckIn: 6,
s.wishSimulator: 7,
s.tierListBuilder: 8,
s.gameCodes: 9,
s.settings: 10,
};
final menu = <Widget>[];

for (final kvp in map.entries) {
menu.add(SliverMainTitle(title: kvp.key));
menu.add(_getItemCard(kvp.value, iconToTheLeft));
iconToTheLeft = !iconToTheLeft;
Widget _buildGameSectionMenus(int index) {
switch (index) {
case 0:
return const MaterialsCard(iconToTheLeft: true);
case 1:
return const MonstersCard(iconToTheLeft: true);
case 2:
return ElementsCard();
default:
throw Exception('Invalid game section');
}
return menu;
}

Widget _getItemCard(int position, bool iconToTheLeft) {
switch (position) {
Widget _buildToolsSectionMenu(int index) {
switch (index) {
case 0:
return const MyInventoryCard(iconToTheLeft: true);
case 1:
return SliverMyInventoryCard(iconToTheLeft: iconToTheLeft);
return const CalculatorsCard(iconToTheLeft: true);
case 2:
return SliverCalculatorsCard(iconToTheLeft: iconToTheLeft);
return const NotificationsCard(iconToTheLeft: true);
case 3:
return SliverMaterialsCard(iconToTheLeft: iconToTheLeft);
case 4:
return SliverNotificationsCard(iconToTheLeft: iconToTheLeft);
case 5:
return SliverMonstersCard(iconToTheLeft: iconToTheLeft);
case 6:
return SliverDailyCheckInCard(iconToTheLeft: iconToTheLeft);
case 7:
return SliverWishSimulatorCard(iconToTheLeft: iconToTheLeft);
case 8:
return SliverTierList(iconToTheLeft: iconToTheLeft);
case 9:
return SliverGameCodesCard(iconToTheLeft: iconToTheLeft);
case 10:
return SliverSettingsCard(iconToTheLeft: iconToTheLeft);
return const TierListCard(iconToTheLeft: true);
default:
throw Exception('Invalid tool section');
}
}

Widget _buildOthersSectionMenu(int index) {
switch (index) {
case 0:
return const GameCodesCard(iconToTheLeft: true);
case 1:
return const DailyCheckInCard(iconToTheLeft: true);
case 2:
return const WishSimulatorCard(iconToTheLeft: true);
default:
throw Exception('Invalid menu item card');
throw Exception('Invalid other section');
}
}

Expand All @@ -123,7 +153,7 @@ class _HomePageState extends State<HomePage> with AutomaticKeepAliveClientMixin<
title: Text(
title,
textAlign: TextAlign.start,
style: theme.textTheme.subtitle1!.copyWith(fontWeight: FontWeight.bold),
style: theme.textTheme.subtitle1!.copyWith(fontWeight: FontWeight.bold, fontSize: 18),
),
),
),
Expand Down
61 changes: 61 additions & 0 deletions lib/presentation/home/widgets/ascension_material_item_card.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import 'package:flutter/material.dart';
import 'package:genshindb/generated/l10n.dart';
import 'package:genshindb/presentation/shared/extensions/i18n_extensions.dart';
import 'package:genshindb/presentation/shared/material_item_button.dart';
import 'package:genshindb/presentation/shared/styles.dart';

class AscensionMaterialItemCard extends StatelessWidget {
final String name;
final String image;
final List<int> days;
final Widget child;

const AscensionMaterialItemCard({
Key? key,
required this.name,
required this.image,
required this.days,
required this.child,
}) : super(key: key);

@override
Widget build(BuildContext context) {
final s = S.of(context);
final theme = Theme.of(context);
final obtainOn = s.translateDays(days);

return Card(
margin: Styles.edgeInsetAll10,
shape: Styles.cardShape,
child: Container(
width: 250,
padding: Styles.edgeInsetAll5,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
MaterialItemButton(image: image, size: 100),
Tooltip(
message: name,
child: Text(
name,
textAlign: TextAlign.center,
overflow: TextOverflow.ellipsis,
style: theme.textTheme.subtitle1!.copyWith(fontWeight: FontWeight.bold),
),
),
Tooltip(
message: obtainOn,
child: Text(
obtainOn,
textAlign: TextAlign.center,
overflow: TextOverflow.visible,
style: theme.textTheme.subtitle2!.copyWith(fontSize: 12),
),
),
child,
],
),
),
);
}
}

0 comments on commit d76725f

Please sign in to comment.