From 973d9c61cffeb6c67d44ac69639423fc176c410a Mon Sep 17 00:00:00 2001 From: Shawn Date: Mon, 14 Nov 2022 09:14:08 -0700 Subject: [PATCH] Update collectibles --- lib/logic/collectibles_logic.dart | 32 ++++++++++++++- lib/ui/common/collectible_item.dart | 2 +- .../screens/collection/collection_screen.dart | 21 +++++----- .../collection/widgets/_collection_list.dart | 39 ++++++++----------- .../widgets/_collection_list_card.dart | 12 +++--- .../home/widgets/_animated_arrow_button.dart | 8 ++-- .../ephemeral/Flutter-Generated.xcconfig | 8 ++-- .../ephemeral/flutter_export_environment.sh | 8 ++-- 8 files changed, 74 insertions(+), 56 deletions(-) diff --git a/lib/logic/collectibles_logic.dart b/lib/logic/collectibles_logic.dart index f2ec907b..dc6f2b50 100644 --- a/lib/logic/collectibles_logic.dart +++ b/lib/logic/collectibles_logic.dart @@ -10,7 +10,13 @@ class CollectiblesLogic with ThrottledSaveLoadMixin { final List all = collectiblesData; /// Current state for each collectible - final statesById = ValueNotifier>({}); + late final statesById = ValueNotifier>({})..addListener(_updateCounts); + + int _discoveredCount = 0; + int get discoveredCount => _discoveredCount; + + int _exploredCount = 0; + int get exploredCount => _exploredCount; CollectibleData? fromId(String? id) => id == null ? null : all.firstWhereOrNull((o) => o.id == id); @@ -18,13 +24,35 @@ class CollectiblesLogic with ThrottledSaveLoadMixin { return all.where((o) => o.wonder == wonder).toList(growable: false); } - void updateState(String id, int state) { + void setState(String id, int state) { Map states = Map.of(statesById.value); states[id] = state; statesById.value = states; scheduleSave(); } + void _updateCounts() { + _discoveredCount = _exploredCount = 0; + statesById.value.forEach((_, state) { + if (state == CollectibleState.discovered) _discoveredCount++; + if (state == CollectibleState.explored) _exploredCount++; + }); + } + + /// Get a discovered item, sorted by the order of wondersLogic.all + CollectibleData? getFirstDiscoveredOrNull() { + List discovered = []; + statesById.value.forEach((key, value) { + if (value == CollectibleState.discovered) discovered.add(fromId(key)!); + }); + for (var w in wondersLogic.all) { + for (var d in discovered) { + if (d.wonder == w.type) return d; + } + } + return null; + } + bool isLost(WonderType wonderType, int i) { final datas = forWonder(wonderType); final states = statesById.value; diff --git a/lib/ui/common/collectible_item.dart b/lib/ui/common/collectible_item.dart index 5fa39dc0..5bb0174a 100644 --- a/lib/ui/common/collectible_item.dart +++ b/lib/ui/common/collectible_item.dart @@ -23,7 +23,7 @@ class CollectibleItem extends StatelessWidget with GetItMixin { // wait to update the state, to ensure the hero works properly: await Future.delayed($styles.times.pageTransition); - collectiblesLogic.updateState(collectible.id, CollectibleState.discovered); + collectiblesLogic.setState(collectible.id, CollectibleState.discovered); } @override diff --git a/lib/ui/screens/collection/collection_screen.dart b/lib/ui/screens/collection/collection_screen.dart index 0e59a6cd..69574fae 100644 --- a/lib/ui/screens/collection/collection_screen.dart +++ b/lib/ui/screens/collection/collection_screen.dart @@ -6,14 +6,13 @@ import 'package:wonders/logic/common/string_utils.dart'; import 'package:wonders/logic/data/collectible_data.dart'; import 'package:wonders/logic/data/wonder_data.dart'; import 'package:wonders/ui/common/controls/simple_header.dart'; -import 'package:wonders/ui/common/gradient_container.dart'; import 'package:wonders/ui/common/modals/app_modals.dart'; part 'widgets/_collectible_image.dart'; -part 'widgets/_newly_discovered_items_btn.dart'; +part 'widgets/_collection_footer.dart'; part 'widgets/_collection_list.dart'; part 'widgets/_collection_list_card.dart'; -part 'widgets/_collection_footer.dart'; +part 'widgets/_newly_discovered_items_btn.dart'; class CollectionScreen extends StatefulWidget with GetItStatefulWidgetMixin { CollectionScreen({required this.fromId, Key? key}) : super(key: key); @@ -25,13 +24,13 @@ class CollectionScreen extends StatefulWidget with GetItStatefulWidgetMixin { } class _CollectionScreenState extends State with GetItStateMixin { - Map _states = collectiblesLogic.statesById.value; final GlobalKey _scrollKey = GlobalKey(); @override void initState() { super.initState(); - if (widget.fromId.isNotEmpty && _states[widget.fromId] == CollectibleState.discovered) { + final states = collectiblesLogic.statesById.value; + if (widget.fromId.isNotEmpty && states[widget.fromId] == CollectibleState.discovered) { scheduleMicrotask(() => _scrollToTarget(false)); } } @@ -52,12 +51,11 @@ class _CollectionScreenState extends State with GetItStateMixi @override Widget build(BuildContext context) { - _states = watchX((CollectiblesLogic o) => o.statesById); - int discovered = 0, explored = 0, total = collectiblesLogic.all.length; - _states.forEach((_, state) { - if (state == CollectibleState.discovered) discovered++; - if (state == CollectibleState.explored) explored++; - }); + // Rebuild when collectible states change + watchX((CollectiblesLogic o) => o.statesById); + int discovered = collectiblesLogic.discoveredCount; + int explored = collectiblesLogic.exploredCount; + int total = collectiblesLogic.all.length; return ColoredBox( color: $styles.colors.greyStrong, @@ -69,7 +67,6 @@ class _CollectionScreenState extends State with GetItStateMixi _NewlyDiscoveredItemsBtn(count: discovered, onPressed: _scrollToTarget), Flexible( child: _CollectionList( - states: _states, fromId: widget.fromId, scrollKey: _scrollKey, onReset: discovered + explored > 0 ? _handleReset : null, diff --git a/lib/ui/screens/collection/widgets/_collection_list.dart b/lib/ui/screens/collection/widgets/_collection_list.dart index 57a50ef6..7e4d5ef2 100644 --- a/lib/ui/screens/collection/widgets/_collection_list.dart +++ b/lib/ui/screens/collection/widgets/_collection_list.dart @@ -1,30 +1,31 @@ part of '../collection_screen.dart'; @immutable -class _CollectionList extends StatelessWidget { - const _CollectionList({ +class _CollectionList extends StatelessWidget with GetItMixin { + _CollectionList({ Key? key, - required this.states, this.onReset, - this.fromId, + required this.fromId, this.scrollKey, }) : super(key: key); - final Map states; final VoidCallback? onReset; final Key? scrollKey; - final String? fromId; + final String fromId; WonderType? get scrollTargetWonder { - String? id = fromId; - if (states[id] != CollectibleState.discovered) { - id = states.keys.firstWhereOrNull((id) => states[id] == CollectibleState.discovered); + CollectibleData? item; + if (fromId.isEmpty) { + item = collectiblesLogic.getFirstDiscoveredOrNull(); + } else { + item = collectiblesLogic.fromId(fromId); } - return collectiblesLogic.fromId(id)?.wonder; + return item?.wonder; } @override Widget build(BuildContext context) { + watchX((CollectiblesLogic o) => o.statesById); List wonders = wondersLogic.all; bool vtMode = context.isLandscape == false; final scrollWonder = scrollTargetWonder; @@ -36,7 +37,6 @@ class _CollectionList extends StatelessWidget { height: vtMode ? 300 : 400, width: vtMode ? null : 600, fromId: fromId, - states: states, data: d, ); }).toList() @@ -46,17 +46,12 @@ class _CollectionList extends StatelessWidget { scrollDirection: vtMode ? Axis.vertical : Axis.horizontal, child: Padding( padding: EdgeInsets.all($styles.insets.lg), - child: vtMode - ? SeparatedColumn( - mainAxisSize: MainAxisSize.min, - separatorBuilder: () => Gap($styles.insets.lg), - children: collections, - ) - : SeparatedRow( - separatorBuilder: () => Gap($styles.insets.xl * 2), - mainAxisSize: MainAxisSize.min, - children: collections, - ), + child: SeparatedFlex( + direction: vtMode ? Axis.vertical : Axis.horizontal, + mainAxisSize: MainAxisSize.min, + separatorBuilder: () => Gap($styles.insets.lg), + children: collections, + ), ), ); } diff --git a/lib/ui/screens/collection/widgets/_collection_list_card.dart b/lib/ui/screens/collection/widgets/_collection_list_card.dart index a89d2172..a1a94eca 100644 --- a/lib/ui/screens/collection/widgets/_collection_list_card.dart +++ b/lib/ui/screens/collection/widgets/_collection_list_card.dart @@ -1,23 +1,21 @@ part of '../collection_screen.dart'; -class _CollectionListCard extends StatelessWidget { - const _CollectionListCard( - {Key? key, this.width, this.height, required this.data, required this.fromId, required this.states}) - : super(key: key); +class _CollectionListCard extends StatelessWidget with GetItMixin { + _CollectionListCard({Key? key, this.width, this.height, required this.data, required this.fromId}) : super(key: key); final double? width; final double? height; final WonderData data; - final String? fromId; - final Map states; + final String fromId; void _showDetails(BuildContext context, CollectibleData collectible) { context.push(ScreenPaths.artifact(collectible.artifactId)); - Future.delayed(300.ms).then((_) => collectiblesLogic.updateState(collectible.id, CollectibleState.explored)); + Future.delayed(300.ms).then((_) => collectiblesLogic.setState(collectible.id, CollectibleState.explored)); } @override Widget build(BuildContext context) { + final states = watchX((CollectiblesLogic o) => o.statesById); List collectibles = collectiblesLogic.forWonder(data.type); return Center( child: SizedBox( diff --git a/lib/ui/screens/home/widgets/_animated_arrow_button.dart b/lib/ui/screens/home/widgets/_animated_arrow_button.dart index 54de2f42..716f2f0f 100644 --- a/lib/ui/screens/home/widgets/_animated_arrow_button.dart +++ b/lib/ui/screens/home/widgets/_animated_arrow_button.dart @@ -7,11 +7,13 @@ class _AnimatedArrowButton extends StatelessWidget { final String semanticTitle; final VoidCallback onTap; + // Fades to 0 and back to 1 final _fadeOutIn = TweenSequence([ TweenSequenceItem(tween: Tween(begin: 1, end: 0), weight: .5), TweenSequenceItem(tween: Tween(begin: 0, end: 1), weight: .5), ]); + // Holds top alignment for first half, then jumps down and slides back up final _slideDown = TweenSequence([ TweenSequenceItem(tween: Tween(begin: 1, end: 1), weight: .5), TweenSequenceItem(tween: Tween(begin: -1, end: 1), weight: .5) @@ -20,11 +22,9 @@ class _AnimatedArrowButton extends StatelessWidget { @override Widget build(BuildContext context) { final Duration duration = $styles.times.med; + final btnLbl = StringUtils.supplant($strings.animatedArrowSemanticSwipe, {'{title}': semanticTitle}); return AppBtn.basic( - semanticLabel: StringUtils.supplant( - $strings.animatedArrowSemanticSwipe, - {'{title}': semanticTitle}, - ), + semanticLabel: btnLbl, onPressed: onTap, child: SizedBox( height: 80, diff --git a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig index 038fdd8a..28393795 100644 --- a/macos/Flutter/ephemeral/Flutter-Generated.xcconfig +++ b/macos/Flutter/ephemeral/Flutter-Generated.xcconfig @@ -1,10 +1,10 @@ // This is a generated file; do not edit or check into version control. -FLUTTER_ROOT=/Users/shawn/Dev/flutter -FLUTTER_APPLICATION_PATH=/Users/shawn/Dev/gskinner/flutter-wonders-app +FLUTTER_ROOT=C:\_dev\sdks\flutter +FLUTTER_APPLICATION_PATH=C:\_dev\gskinner\flutter_wonders_app COCOAPODS_PARALLEL_CODE_SIGN=true FLUTTER_BUILD_DIR=build -FLUTTER_BUILD_NAME=1.9.6 -FLUTTER_BUILD_NUMBER=1.9.6 +FLUTTER_BUILD_NAME=1.9.7 +FLUTTER_BUILD_NUMBER=1.9.7 DART_OBFUSCATION=false TRACK_WIDGET_CREATION=true TREE_SHAKE_ICONS=false diff --git a/macos/Flutter/ephemeral/flutter_export_environment.sh b/macos/Flutter/ephemeral/flutter_export_environment.sh index a868a11d..c6874b00 100755 --- a/macos/Flutter/ephemeral/flutter_export_environment.sh +++ b/macos/Flutter/ephemeral/flutter_export_environment.sh @@ -1,11 +1,11 @@ #!/bin/sh # This is a generated file; do not edit or check into version control. -export "FLUTTER_ROOT=/Users/shawn/Dev/flutter" -export "FLUTTER_APPLICATION_PATH=/Users/shawn/Dev/gskinner/flutter-wonders-app" +export "FLUTTER_ROOT=C:\_dev\sdks\flutter" +export "FLUTTER_APPLICATION_PATH=C:\_dev\gskinner\flutter_wonders_app" export "COCOAPODS_PARALLEL_CODE_SIGN=true" export "FLUTTER_BUILD_DIR=build" -export "FLUTTER_BUILD_NAME=1.9.6" -export "FLUTTER_BUILD_NUMBER=1.9.6" +export "FLUTTER_BUILD_NAME=1.9.7" +export "FLUTTER_BUILD_NUMBER=1.9.7" export "DART_OBFUSCATION=false" export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false"