From 9b84d7ca7a2140f083cdd44597fd2a2acf99f113 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 20 Jan 2024 17:45:03 +0200 Subject: [PATCH 01/32] setup for favorites --- lib/main.dart | 2 + .../screens/misc/favorite_screen.dart | 0 pubspec.lock | 120 ++++++++++-------- pubspec.yaml | 3 +- 4 files changed, 68 insertions(+), 57 deletions(-) create mode 100644 lib/presentation/screens/misc/favorite_screen.dart diff --git a/lib/main.dart b/lib/main.dart index 119d069..dcb6022 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -3,6 +3,7 @@ import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_core/firebase_core.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; +import 'package:hive/hive.dart'; import '/firebase_options.dart'; import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; @@ -29,6 +30,7 @@ Future main() async { options: DefaultFirebaseOptions.currentPlatform, ); final analytics = FirebaseAnalytics.instance; + final favBox = Hive.box('favorite'); runApp(MyApp(analytics: analytics)); } diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart new file mode 100644 index 0000000..e69de29 diff --git a/pubspec.lock b/pubspec.lock index 10051fe..4212f79 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,10 +13,10 @@ packages: dependency: "direct main" description: name: adaptive_theme - sha256: "38b433c0761d9f15017a15c9ff3e15e8905d3e9bad54a489c7939da6bdf782dd" + sha256: b0c4c35b22ef8226757881fe4dce38c40a06c551bca83236022ec7613e157c83 url: "https://pub.dev" source: hosted - version: "3.4.1" + version: "3.5.0" android_intent_plus: dependency: transitive description: @@ -29,10 +29,10 @@ packages: dependency: transitive description: name: archive - sha256: "7b875fd4a20b165a3084bd2d210439b22ebc653f21cea4842729c0c30c82596b" + sha256: "22600aa1e926be775fa5fe7e6894e7fb3df9efda8891c73f70fb3262399a432d" url: "https://pub.dev" source: hosted - version: "3.4.9" + version: "3.4.10" args: dependency: transitive description: @@ -93,10 +93,10 @@ packages: dependency: transitive description: name: cli_util - sha256: b8db3080e59b2503ca9e7922c3df2072cf13992354d5e944074ffa836fba43b7 + sha256: c05b7406fdabc7a49a3929d4af76bcaccbbffcbcdcf185b082e1ae07da323d19 url: "https://pub.dev" source: hosted - version: "0.4.0" + version: "0.4.1" clock: dependency: transitive description: @@ -165,26 +165,26 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: "5e92d510eacd66c354718fd9cc8f66ffdfa025640b645c4742297fb973770508" + sha256: "0240076090d77045d757aecb090616066d23b343840d4c21074094d6fe40a184" url: "https://pub.dev" source: hosted - version: "10.7.4" + version: "10.8.0" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "72977325a72af5ebb8e53b5c5533cb2e33eec481cd46210cfe5427f5efba55d8" + sha256: "6d9baa077d16b47ef5f19d982c4fc475597991aa53b0c601216faa3e1cdab45f" url: "https://pub.dev" source: hosted - version: "3.8.4" + version: "3.9.0" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "8b9710be7e292e2a5ad34fff449d4b668c5808fb339649e69181727a4534f579" + sha256: "89a740249bce9d52a99db4e501be6087ca6749c73c47cff2b174802be10abd81" url: "https://pub.dev" source: hosted - version: "0.5.5+11" + version: "0.5.5+12" firebase_core: dependency: "direct main" description: @@ -248,14 +248,22 @@ packages: url: "https://pub.dev" source: hosted version: "10.6.0" + hive: + dependency: "direct main" + description: + name: hive + sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941" + url: "https://pub.dev" + source: hosted + version: "2.2.3" http: dependency: "direct main" description: name: http - sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139 + sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.2.0" http_parser: dependency: transitive description: @@ -268,10 +276,10 @@ packages: dependency: transitive description: name: image - sha256: "028f61960d56f26414eb616b48b04eb37d700cbe477b7fb09bf1d7ce57fd9271" + sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" url: "https://pub.dev" source: hosted - version: "4.1.3" + version: "4.1.4" js: dependency: transitive description: @@ -356,10 +364,10 @@ packages: dependency: transitive description: name: path_provider_platform_interface - sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c" + sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path_provider_windows: dependency: transitive description: @@ -380,26 +388,26 @@ packages: dependency: transitive description: name: platform - sha256: "0a279f0707af40c890e80b1e9df8bb761694c074ba7e1d4ab1bc4b728e200b59" + sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec" url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "3.1.4" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - sha256: f4f88d4a900933e7267e2b353594774fc0d07fb072b47eedcd5b54e1ea3269f8 + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" url: "https://pub.dev" source: hosted - version: "2.1.7" + version: "2.1.8" pointycastle: dependency: transitive description: name: pointycastle - sha256: "7c1e5f0d23c9016c5bbd8b1473d0d3fb3fc851b876046039509e18e0c7485f2c" + sha256: "43ac87de6e10afabc85c445745a7b799e04de84cebaa4fd7bf55a5e1e9604d29" url: "https://pub.dev" source: hosted - version: "3.7.3" + version: "3.7.4" provider: dependency: "direct main" description: @@ -428,10 +436,10 @@ packages: dependency: transitive description: name: shared_preferences_foundation - sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7" + sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c" url: "https://pub.dev" source: hosted - version: "2.3.4" + version: "2.3.5" shared_preferences_linux: dependency: transitive description: @@ -444,10 +452,10 @@ packages: dependency: transitive description: name: shared_preferences_platform_interface - sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a + sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b" url: "https://pub.dev" source: hosted - version: "2.3.1" + version: "2.3.2" shared_preferences_web: dependency: transitive description: @@ -537,34 +545,34 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: e9aa5ea75c84cf46b3db4eea212523591211c3cf2e13099ee4ec147f54201c86 + sha256: d25bb0ca00432a5e1ee40e69c36c85863addf7cc45e433769d61bed3fe81fd96 url: "https://pub.dev" source: hosted - version: "6.2.2" + version: "6.2.3" url_launcher_android: dependency: transitive description: name: url_launcher_android - sha256: "31222ffb0063171b526d3e569079cf1f8b294075ba323443fdc690842bfd4def" + sha256: "507dc655b1d9cb5ebc756032eb785f114e415f91557b73bf60b7e201dfedeb2f" url: "https://pub.dev" source: hosted - version: "6.2.0" + version: "6.2.2" url_launcher_ios: dependency: transitive description: name: url_launcher_ios - sha256: bba3373219b7abb6b5e0d071b0fe66dfbe005d07517a68e38d4fc3638f35c6d3 + sha256: "75bb6fe3f60070407704282a2d295630cab232991eb52542b18347a8a941df03" url: "https://pub.dev" source: hosted - version: "6.2.1" + version: "6.2.4" url_launcher_linux: dependency: transitive description: name: url_launcher_linux - sha256: "9f2d390e096fdbe1e6e6256f97851e51afc2d9c423d3432f1d6a02a8a9a8b9fd" + sha256: ab360eb661f8879369acac07b6bb3ff09d9471155357da8443fd5d3cf7363811 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" url_launcher_macos: dependency: transitive description: @@ -577,26 +585,26 @@ packages: dependency: transitive description: name: url_launcher_platform_interface - sha256: "980e8d9af422f477be6948bdfb68df8433be71f5743a188968b0c1b887807e50" + sha256: a932c3a8082e118f80a475ce692fde89dc20fddb24c57360b96bc56f7035de1f url: "https://pub.dev" source: hosted - version: "2.2.0" + version: "2.3.1" url_launcher_web: dependency: transitive description: name: url_launcher_web - sha256: "7286aec002c8feecc338cc33269e96b73955ab227456e9fb2a91f7fab8a358e9" + sha256: fff0932192afeedf63cdd50ecbb1bc825d31aed259f02bb8dba0f3b729a5e88b url: "https://pub.dev" source: hosted - version: "2.2.2" + version: "2.2.3" url_launcher_windows: dependency: transitive description: name: url_launcher_windows - sha256: "7754a1ad30ee896b265f8d14078b0513a4dba28d358eabb9d5f339886f4a1adc" + sha256: ecf9725510600aa2bb6d7ddabe16357691b6d2805f66216a97d1b881e21beff7 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.1" vector_math: dependency: transitive description: @@ -617,50 +625,50 @@ packages: dependency: transitive description: name: webview_flutter - sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf" + sha256: "71e1bfaef41016c8d5954291df5e9f8c6172f1f6ff3af01b5656456ddb11f94c" url: "https://pub.dev" source: hosted - version: "4.4.2" + version: "4.4.4" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "8326ee235f87605a2bfc444a4abc897f4abc78d83f054ba7d3d1074ce82b4fbf" + sha256: "161af93c2abaf94ef2192bffb53a3658b2d721a3bf99b69aa1e47814ee18cc96" url: "https://pub.dev" source: hosted - version: "3.12.1" + version: "3.13.2" webview_flutter_platform_interface: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "68e86162aa8fc646ae859e1585995c096c95fc2476881fa0c4a8d10f56013a5a" + sha256: "80b40ae4fb959957eef9fa8970b6c9accda9f49fc45c2b75154696a8e8996cfe" url: "https://pub.dev" source: hosted - version: "2.8.0" + version: "2.9.1" webview_flutter_wkwebview: dependency: transitive description: name: webview_flutter_wkwebview - sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76 + sha256: b99ca8d8bae9c6b43d568218691aa537fb0aeae1d7d34eadf112a6aa36d26506 url: "https://pub.dev" source: hosted - version: "3.9.4" + version: "3.11.0" win32: dependency: transitive description: name: win32 - sha256: b0f37db61ba2f2e9b7a78a1caece0052564d1bc70668156cf3a29d676fe4e574 + sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "5.2.0" xdg_directories: dependency: transitive description: name: xdg_directories - sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2" + sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d url: "https://pub.dev" source: hosted - version: "1.0.3" + version: "1.0.4" xml: dependency: transitive description: @@ -678,5 +686,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.2.0 <4.0.0" - flutter: ">=3.16.0" + dart: ">=3.2.3 <4.0.0" + flutter: ">=3.16.6" diff --git a/pubspec.yaml b/pubspec.yaml index 5e985bd..5721e3d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -20,7 +20,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev version: 1.0.17+19 environment: - sdk: ">=2.18.5 <3.0.0" + sdk: ">=2.18.5 <4.0.0" # Dependencies specify other packages that your package needs in order to work. # To automatically upgrade your package dependencies to the latest versions @@ -46,6 +46,7 @@ dependencies: carousel_slider: ^4.2.1 smooth_page_indicator: ^1.1.0 provider: ^6.1.1 + hive: ^2.2.3 dev_dependencies: flutter_launcher_icons: ^0.13.1 From 9e3119271ec5b738dad57f3d95fb0f73661d7cfc Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 20 Jan 2024 19:15:09 +0200 Subject: [PATCH 02/32] basic func for favorites work --- lib/main.dart | 63 +++++++----- lib/presentation/screens/tower/towers.dart | 97 +++++++++++-------- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 32 ++++++ pubspec.yaml | 1 + 5 files changed, 127 insertions(+), 68 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index dcb6022..2f46e63 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,9 +1,10 @@ import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_core/firebase_core.dart'; +import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; -import 'package:hive/hive.dart'; + import '/firebase_options.dart'; import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; @@ -30,7 +31,7 @@ Future main() async { options: DefaultFirebaseOptions.currentPlatform, ); final analytics = FirebaseAnalytics.instance; - final favBox = Hive.box('favorite'); + await Hive.initFlutter(); runApp(MyApp(analytics: analytics)); } @@ -154,30 +155,40 @@ class _MyHomePageState extends State { : Container(); }, ), - Consumer(builder: (context, globalState, child) { - return IconButton( - onPressed: () { - globalState.switchSearch(); - String value; - if (globalState.isSearchEnabled) { - value = searchOn; - } else { - globalState.updateCurrentQuery(''); - value = searchOff; - } - analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': globalState.activeCategory, - 'widget': searchButton, - 'value': value, - }, - ); - }, - icon: Icon( - !globalState.isSearchEnabled ? Icons.search : Icons.close), - ); - }) + Consumer( + builder: (context, globalState, child) { + return IconButton( + onPressed: () { + globalState.switchSearch(); + String value; + if (globalState.isSearchEnabled) { + value = searchOn; + } else { + globalState.updateCurrentQuery(''); + value = searchOff; + } + analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': globalState.activeCategory, + 'widget': searchButton, + 'value': value, + }, + ); + }, + icon: Icon( + !globalState.isSearchEnabled ? Icons.search : Icons.close), + ); + }, + ), + IconButton( + onPressed: () async { + var favBox = await Hive.openBox('favorite'); + // favBox.deleteFromDisk(); + print(favBox.get(kTowers)); + }, + icon: const Icon(Icons.favorite), + ), ], ), body: !isLoading diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index f6715b1..67bb46d 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -1,3 +1,4 @@ +import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_tower.dart'; @@ -29,7 +30,6 @@ class _TowersState extends State { @override void initState() { super.initState(); - widget.analyticsHelper.logScreenView( screenClass: kMainPagesClass, screenName: kTowers, @@ -66,49 +66,62 @@ class _TowersState extends State { itemBuilder: (context, index) { final tower = filteredTowers[index]; - return Card( - margin: const EdgeInsets.symmetric( - horizontal: 13, vertical: 8), - child: Center( - child: ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8), - horizontalTitleGap: 8, - minVerticalPadding: -4, - leading: ImageOutliner( - imageName: tower.image, - imagePath: towerImage(tower.image), - width: constraintsValues[towerImageWidth], - ), - title: Text( - tower.name, - style: constraintsValues[towerTitleStyle], + return InkWell( + onLongPress: () async { + var favBox = await Hive.openBox('favorite'); + List favList = favBox.get(kTowers, defaultValue: []); + if (favList.contains(tower.id)) { + favList.remove(tower.id); + } else { + favList.add(tower.id); + } + favBox.put(kTowers, favList); + print(favList); + }, + onTap: () { + widget.analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kTowerPagesClass, + 'widget': listTile, + 'value': tower.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleTower( + towerId: tower.id, + analyticsHelper: widget.analyticsHelper, + ), ), - subtitle: Text( - tower.inGameDesc, - overflow: TextOverflow.ellipsis, - maxLines: constraintsValues[towerSubtitleRows], - style: constraintsValues[towerSubtitleStyle], + ); + }, + child: Card( + margin: const EdgeInsets.symmetric( + horizontal: 13, vertical: 8), + child: Center( + child: ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 8), + horizontalTitleGap: 8, + minVerticalPadding: -4, + leading: ImageOutliner( + imageName: tower.image, + imagePath: towerImage(tower.image), + width: constraintsValues[towerImageWidth], + ), + title: Text( + tower.name, + style: constraintsValues[towerTitleStyle], + ), + subtitle: Text( + tower.inGameDesc, + overflow: TextOverflow.ellipsis, + maxLines: constraintsValues[towerSubtitleRows], + style: constraintsValues[towerSubtitleStyle], + ), ), - onTap: () { - widget.analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kTowerPagesClass, - 'widget': listTile, - 'value': tower.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleTower( - towerId: tower.id, - analyticsHelper: widget.analyticsHelper, - ), - ), - ); - }, ), ), ); diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index f1bd702..8b0aac0 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -7,12 +7,14 @@ import Foundation import firebase_analytics import firebase_core +import path_provider_foundation import shared_preferences_foundation import url_launcher_macos func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FLTFirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseAnalyticsPlugin")) FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 4212f79..ceb221d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -256,6 +256,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.2.3" + hive_flutter: + dependency: "direct main" + description: + name: hive_flutter + sha256: dca1da446b1d808a51689fb5d0c6c9510c0a2ba01e22805d492c73b68e33eecc + url: "https://pub.dev" + source: hosted + version: "1.1.0" http: dependency: "direct main" description: @@ -352,6 +360,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_provider: + dependency: transitive + description: + name: path_provider + sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + path_provider_android: + dependency: transitive + description: + name: path_provider_android + sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668" + url: "https://pub.dev" + source: hosted + version: "2.2.2" + path_provider_foundation: + dependency: transitive + description: + name: path_provider_foundation + sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f" + url: "https://pub.dev" + source: hosted + version: "2.3.2" path_provider_linux: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5721e3d..9309bb9 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -47,6 +47,7 @@ dependencies: smooth_page_indicator: ^1.1.0 provider: ^6.1.1 hive: ^2.2.3 + hive_flutter: ^1.1.0 dev_dependencies: flutter_launcher_icons: ^0.13.1 From d027f128f920e21f8a6ec3559d0a3809725448d1 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 20 Jan 2024 20:58:05 +0200 Subject: [PATCH 03/32] WIP trying to change fav status on ui card --- lib/main.dart | 4 +- lib/presentation/screens/tower/towers.dart | 74 ++++++++++++---------- lib/utilities/utils.dart | 17 +++++ 3 files changed, 60 insertions(+), 35 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 2f46e63..5257484 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -184,8 +184,8 @@ class _MyHomePageState extends State { IconButton( onPressed: () async { var favBox = await Hive.openBox('favorite'); - // favBox.deleteFromDisk(); - print(favBox.get(kTowers)); + favBox.deleteFromDisk(); + // print(favBox.get(kTowers)); }, icon: const Icon(Icons.favorite), ), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 67bb46d..5d1ca6c 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -41,6 +41,7 @@ class _TowersState extends State { final constraintsValues = getPreset( MediaQuery.of(context).size, ); + bool isFavorite = false; return Scaffold( body: Column( children: [ @@ -67,16 +68,10 @@ class _TowersState extends State { final tower = filteredTowers[index]; return InkWell( + borderRadius: BorderRadius.circular(20), onLongPress: () async { - var favBox = await Hive.openBox('favorite'); - List favList = favBox.get(kTowers, defaultValue: []); - if (favList.contains(tower.id)) { - favList.remove(tower.id); - } else { - favList.add(tower.id); - } - favBox.put(kTowers, favList); - print(favList); + isFavorite = await handleFavorite(kTowers, tower.id); + setState(() {}); }, onTap: () { widget.analyticsHelper.logEvent( @@ -97,32 +92,45 @@ class _TowersState extends State { ), ); }, - child: Card( - margin: const EdgeInsets.symmetric( - horizontal: 13, vertical: 8), - child: Center( - child: ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8), - horizontalTitleGap: 8, - minVerticalPadding: -4, - leading: ImageOutliner( - imageName: tower.image, - imagePath: towerImage(tower.image), - width: constraintsValues[towerImageWidth], - ), - title: Text( - tower.name, - style: constraintsValues[towerTitleStyle], - ), - subtitle: Text( - tower.inGameDesc, - overflow: TextOverflow.ellipsis, - maxLines: constraintsValues[towerSubtitleRows], - style: constraintsValues[towerSubtitleStyle], + child: Stack( + alignment: AlignmentDirectional.topEnd, + children: [ + Card( + margin: const EdgeInsets.symmetric( + horizontal: 13, vertical: 8), + child: Center( + child: ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 8), + horizontalTitleGap: 8, + minVerticalPadding: -4, + leading: ImageOutliner( + imageName: tower.image, + imagePath: towerImage(tower.image), + width: constraintsValues[towerImageWidth], + ), + title: Text( + tower.name, + style: constraintsValues[towerTitleStyle], + ), + subtitle: Text( + tower.inGameDesc, + overflow: TextOverflow.ellipsis, + maxLines: + constraintsValues[towerSubtitleRows], + style: constraintsValues[towerSubtitleStyle], + ), + ), ), ), - ), + Positioned( + top: 17, + right: 25, + child: isFavorite + ? Icon(Icons.star) + : Icon(Icons.star_border_outlined), + ), + ], ), ); }, diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index e6e4d2f..02a81ad 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,3 +1,4 @@ +import 'package:hive_flutter/hive_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; import '/models/bloons/common/relative_class.dart'; @@ -49,6 +50,22 @@ String extraStatsToString(Stats stats) { return "Status Effects: ${stats.statuseffects}\nIncome Boosts: ${stats.incomeboosts}\nTower Boosts: ${stats.towerboosts}"; } +Future handleFavorite(String category, String id) async { + bool isFavorite; + var favoriteBox = await Hive.openBox('favorite'); + List favoriteList = favoriteBox.get(category, defaultValue: []); + if (favoriteList.contains(id)) { + favoriteList.remove(id); + isFavorite = false; + } else { + favoriteList.add(id); + isFavorite = true; + } + favoriteBox.put(kTowers, favoriteList); + print(favoriteList); + return isFavorite; +} + List filterAndSearchBloons( List bloons, String query, String option) { query = query.toLowerCase(); From ce2c01724288b53484dd1e0f726292f5db8e8f0a Mon Sep 17 00:00:00 2001 From: Shai Date: Sun, 21 Jan 2024 09:55:53 +0200 Subject: [PATCH 04/32] selecting towers to favorite consist after app is closed --- lib/main.dart | 47 +++++++----- lib/presentation/screens/tower/towers.dart | 38 +++++++--- lib/utilities/favorite_state.dart | 87 ++++++++++++++++++++++ lib/utilities/utils.dart | 20 ++++- 4 files changed, 161 insertions(+), 31 deletions(-) create mode 100644 lib/utilities/favorite_state.dart diff --git a/lib/main.dart b/lib/main.dart index 5257484..819ddae 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -4,7 +4,6 @@ import 'package:firebase_core/firebase_core.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; - import '/firebase_options.dart'; import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; @@ -16,8 +15,9 @@ import '/presentation/screens/bloon/bloons.dart'; import '/presentation/screens/hero/heroes.dart'; import '/presentation/screens/maps/maps.dart'; import '/presentation/widgets/loader.dart'; -import 'analytics/analytics_constants.dart'; +import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/global_state.dart'; import '/utilities/constants.dart'; import '/utilities/requests.dart'; @@ -32,29 +32,38 @@ Future main() async { ); final analytics = FirebaseAnalytics.instance; await Hive.initFlutter(); - + await Hive.openBox('favorite'); runApp(MyApp(analytics: analytics)); } class MyApp extends StatelessWidget { const MyApp({super.key, required this.analytics}); final FirebaseAnalytics analytics; + @override Widget build(BuildContext context) { - return ChangeNotifierProvider( - create: (BuildContext context) => GlobalState(), + return MultiProvider( + providers: [ + ChangeNotifierProvider( + create: (BuildContext context) => GlobalState(), + ), + ChangeNotifierProvider( + create: (BuildContext context) => FavoriteState(), + ), + ], child: AdaptiveTheme( - light: Themes.lightTheme, - dark: Themes.darkTheme, - initial: AdaptiveThemeMode.system, - builder: (theme, darkTheme) => MaterialApp( - theme: theme, - darkTheme: darkTheme, - home: MyHomePage( - analytics: analytics, - ), - debugShowCheckedModeBanner: false, - )), + light: Themes.lightTheme, + dark: Themes.darkTheme, + initial: AdaptiveThemeMode.system, + builder: (theme, darkTheme) => MaterialApp( + theme: theme, + darkTheme: darkTheme, + home: MyHomePage( + analytics: analytics, + ), + debugShowCheckedModeBanner: false, + ), + ), ); } } @@ -184,10 +193,10 @@ class _MyHomePageState extends State { IconButton( onPressed: () async { var favBox = await Hive.openBox('favorite'); - favBox.deleteFromDisk(); - // print(favBox.get(kTowers)); + // favBox.deleteFromDisk(); + print(favBox.get(kTowers)); }, - icon: const Icon(Icons.favorite), + icon: const Icon(Icons.star), ), ], ), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 5d1ca6c..7726f14 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -1,4 +1,5 @@ -import 'package:hive_flutter/hive_flutter.dart'; +import 'package:btd6wiki/models/base_model.dart'; +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_tower.dart'; @@ -41,6 +42,9 @@ class _TowersState extends State { final constraintsValues = getPreset( MediaQuery.of(context).size, ); + FavoriteState favoriteState = + Provider.of(context, listen: false); + favoriteState.fillList(kTowers, widget.towers); bool isFavorite = false; return Scaffold( body: Column( @@ -69,9 +73,19 @@ class _TowersState extends State { return InkWell( borderRadius: BorderRadius.circular(20), - onLongPress: () async { - isFavorite = await handleFavorite(kTowers, tower.id); - setState(() {}); + onLongPress: () { + isFavorite = handleFavorite(kTowers, tower.id); + if (isFavorite) { + BaseModel favoriteTower = BaseModel( + tower.id, + tower.name, + tower.image, + tower.type, + ); + favoriteState.addFavoriteTower(favoriteTower); + } else { + favoriteState.removeFavoriteTower(tower.id); + } }, onTap: () { widget.analyticsHelper.logEvent( @@ -123,12 +137,16 @@ class _TowersState extends State { ), ), ), - Positioned( - top: 17, - right: 25, - child: isFavorite - ? Icon(Icons.star) - : Icon(Icons.star_border_outlined), + Consumer( + builder: (context, favoriteState, child) { + return Positioned( + top: 17, + right: 25, + child: favoriteState.isFavoriteTower(tower.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, ), ], ), diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart new file mode 100644 index 0000000..b8b2bf0 --- /dev/null +++ b/lib/utilities/favorite_state.dart @@ -0,0 +1,87 @@ +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:flutter/material.dart'; +import '/models/base_model.dart'; + +class FavoriteState with ChangeNotifier { + var favoriteBox; + List towers = []; + List heroes = []; + List bloons = []; + List bosses = []; + List maps = []; + + void loadFavoriteBox() { + favoriteBox = Hive.box('favorite'); + } + + void fillList(String category, List baseObjects) { + loadFavoriteBox(); + List favoritesIds = favoriteBox.get(category); + + for (var baseObj in baseObjects) { + if (favoritesIds.contains(baseObj.id)) { + BaseModel item = BaseModel( + baseObj.id, + baseObj.name, + baseObj.image, + baseObj.type, + ); + towers.add(item); + } + } + } + + bool isFavoriteTower(String towerId) { + return towers.any((tower) => tower.id == towerId); + } + + void addFavoriteTower(BaseModel tower) { + towers.add(tower); + notifyListeners(); + } + + void removeFavoriteTower(String towerId) { + towers.removeWhere((tower) => tower.id == towerId); + notifyListeners(); + } + + void addFavoriteHero(BaseModel hero) { + heroes.add(hero); + notifyListeners(); + } + + void removeFavoriteHero(BaseModel hero) { + heroes.remove(hero); + notifyListeners(); + } + + void addFavoriteBloon(BaseModel bloon) { + bloons.add(bloon); + notifyListeners(); + } + + void removeFavoriteBloon(BaseModel bloon) { + bloons.remove(bloon); + notifyListeners(); + } + + void addFavoriteBoss(BaseModel boss) { + bosses.add(boss); + notifyListeners(); + } + + void removeFavoriteBoss(BaseModel boss) { + bosses.remove(boss); + notifyListeners(); + } + + void addFavoriteMap(BaseModel map) { + maps.add(map); + notifyListeners(); + } + + void removeFavoriteMap(BaseModel map) { + maps.remove(map); + notifyListeners(); + } +} diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 02a81ad..d8c1032 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -50,9 +50,25 @@ String extraStatsToString(Stats stats) { return "Status Effects: ${stats.statuseffects}\nIncome Boosts: ${stats.incomeboosts}\nTower Boosts: ${stats.towerboosts}"; } -Future handleFavorite(String category, String id) async { +// Future handleFavorite(String category, String id) async { +// bool isFavorite; + +// List favoriteList = favoriteBox.get(category, defaultValue: []); +// if (favoriteList.contains(id)) { +// favoriteList.remove(id); +// isFavorite = false; +// } else { +// favoriteList.add(id); +// isFavorite = true; +// } +// favoriteBox.put(kTowers, favoriteList); +// print(favoriteList); +// return isFavorite; +// } + +bool handleFavorite(String category, String id) { bool isFavorite; - var favoriteBox = await Hive.openBox('favorite'); + var favoriteBox = Hive.box('favorite'); List favoriteList = favoriteBox.get(category, defaultValue: []); if (favoriteList.contains(id)) { favoriteList.remove(id); From 7f752f60282f54f461f73f75aa348bdeef12f5f9 Mon Sep 17 00:00:00 2001 From: Shai Date: Tue, 23 Jan 2024 10:10:37 +0200 Subject: [PATCH 05/32] generalized favorite state, towers and heroes added successfully --- lib/main.dart | 9 +- lib/presentation/screens/hero/heroes.dart | 117 ++++++++++++------- lib/presentation/screens/tower/towers.dart | 11 +- lib/utilities/favorite_state.dart | 125 ++++++++++++--------- lib/utilities/utils.dart | 8 +- 5 files changed, 169 insertions(+), 101 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 819ddae..c143af5 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -107,6 +107,7 @@ class _MyHomePageState extends State { void initState() { super.initState(); loadBaseData(); + setEmptyFavorites(); analyticsHelper = AnalyticsHelper(widget.analytics); pageController = PageController(initialPage: 0); } @@ -192,9 +193,11 @@ class _MyHomePageState extends State { ), IconButton( onPressed: () async { - var favBox = await Hive.openBox('favorite'); - // favBox.deleteFromDisk(); - print(favBox.get(kTowers)); + var favBox = Hive.box('favorite'); + await favBox.deleteFromDisk(); + favBox = await Hive.openBox('favorite'); + print(favBox.values); + // print(favBox.get(kTowers)); }, icon: const Icon(Icons.star), ), diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index e3546b7..e314522 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -1,11 +1,13 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_hero.dart'; +import '/models/base_model.dart'; import '/presentation/screens/hero/single_hero.dart'; import '/presentation/widgets/search_widget.dart'; import '/presentation/widgets/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/global_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; @@ -40,6 +42,11 @@ class _HeroesState extends State { final constraintsValues = getPreset( MediaQuery.of(context).size, ); + + FavoriteState favoriteState = + Provider.of(context, listen: false); + favoriteState.fillList(kHeroes, widget.heroes); + bool isFavorite = false; return Scaffold( body: Column( children: [ @@ -64,48 +71,82 @@ class _HeroesState extends State { itemBuilder: (context, index) { final hero = filteredHeroes[index]; - return Card( - margin: const EdgeInsets.symmetric( - horizontal: 13, vertical: 8), - child: Center( - child: ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8), - horizontalTitleGap: 8, - leading: ImageOutliner( - imageName: hero.image, - imagePath: heroImage(hero.image), - ), - title: Text( + return InkWell( + borderRadius: BorderRadius.circular(20), + onLongPress: () { + isFavorite = handleFavorite(kHeroes, hero.id); + if (isFavorite) { + BaseModel favoriteHero = BaseModel( + hero.id, hero.name, - style: constraintsValues[heroTitleStyle], - ), - subtitle: Text( - hero.inGameDesc, - overflow: TextOverflow.ellipsis, - style: constraintsValues[heroSubtitleStyle], - maxLines: constraintsValues[heroSubtitleRows], + hero.image, + hero.type, + ); + favoriteState.addFavorite(kHeroes, favoriteHero); + } else { + favoriteState.removeFavorite(kHeroes, hero.id); + } + print(favoriteState.favoriteBox.get(kHeroes)); + }, + onTap: () { + widget.analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kHeroPagesClass, + 'widget': listTile, + 'value': hero.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleHero( + heroId: hero.id, + analyticsHelper: widget.analyticsHelper, + ), ), - onTap: () { - widget.analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kHeroPagesClass, - 'widget': listTile, - 'value': hero.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleHero( - heroId: hero.id, - analyticsHelper: widget.analyticsHelper, + ); + }, + child: Stack( + children: [ + Card( + margin: const EdgeInsets.symmetric( + horizontal: 13, vertical: 8), + child: Center( + child: ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 8), + horizontalTitleGap: 8, + leading: ImageOutliner( + imageName: hero.image, + imagePath: heroImage(hero.image), + ), + title: Text( + hero.name, + style: constraintsValues[heroTitleStyle], + ), + subtitle: Text( + hero.inGameDesc, + overflow: TextOverflow.ellipsis, + style: constraintsValues[heroSubtitleStyle], + maxLines: constraintsValues[heroSubtitleRows], ), ), - ); - }, - ), + ), + ), + Consumer( + builder: (context, favoriteState, child) { + return Positioned( + top: 17, + right: 25, + child: favoriteState.isInFavorites( + kHeroes, hero.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, + ), + ], ), ); }, diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 7726f14..f0d19a1 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -1,13 +1,13 @@ -import 'package:btd6wiki/models/base_model.dart'; -import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_tower.dart'; +import '/models/base_model.dart'; import '/presentation/screens/tower/single_tower.dart'; import '/presentation/widgets/search_widget.dart'; import '/presentation/widgets/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/global_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; @@ -82,9 +82,9 @@ class _TowersState extends State { tower.image, tower.type, ); - favoriteState.addFavoriteTower(favoriteTower); + favoriteState.addFavorite(kTowers, favoriteTower); } else { - favoriteState.removeFavoriteTower(tower.id); + favoriteState.removeFavorite(kTowers, tower.id); } }, onTap: () { @@ -142,7 +142,8 @@ class _TowersState extends State { return Positioned( top: 17, right: 25, - child: favoriteState.isFavoriteTower(tower.id) + child: favoriteState.isInFavorites( + kTowers, tower.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), ); diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index b8b2bf0..7afcb7d 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -1,9 +1,11 @@ +import 'package:btd6wiki/utilities/constants.dart'; import 'package:hive_flutter/hive_flutter.dart'; import 'package:flutter/material.dart'; import '/models/base_model.dart'; class FavoriteState with ChangeNotifier { var favoriteBox; + List towers = []; List heroes = []; List bloons = []; @@ -14,74 +16,91 @@ class FavoriteState with ChangeNotifier { favoriteBox = Hive.box('favorite'); } - void fillList(String category, List baseObjects) { + void fillList(String category, List baseObjects) { loadFavoriteBox(); - List favoritesIds = favoriteBox.get(category); + if (favoriteBox.get(category.toString()) != null) { + List favoritesIds = favoriteBox.get(category.toString()); - for (var baseObj in baseObjects) { - if (favoritesIds.contains(baseObj.id)) { - BaseModel item = BaseModel( - baseObj.id, - baseObj.name, - baseObj.image, - baseObj.type, - ); - towers.add(item); + for (var baseObj in baseObjects) { + if (favoritesIds.contains(baseObj.id)) { + BaseModel item = BaseModel( + baseObj.id, + baseObj.name, + baseObj.image, + baseObj.type, + ); + _addToList(category, item); + } } + } else { + print('$category is empty'); + favoriteBox.get(category.toString(), defaultValue: []); } } - bool isFavoriteTower(String towerId) { - return towers.any((tower) => tower.id == towerId); - } - - void addFavoriteTower(BaseModel tower) { - towers.add(tower); - notifyListeners(); - } - - void removeFavoriteTower(String towerId) { - towers.removeWhere((tower) => tower.id == towerId); - notifyListeners(); - } - - void addFavoriteHero(BaseModel hero) { - heroes.add(hero); - notifyListeners(); - } - - void removeFavoriteHero(BaseModel hero) { - heroes.remove(hero); - notifyListeners(); - } - - void addFavoriteBloon(BaseModel bloon) { - bloons.add(bloon); - notifyListeners(); - } - - void removeFavoriteBloon(BaseModel bloon) { - bloons.remove(bloon); - notifyListeners(); + bool isInFavorites(String category, String itemId) { + switch (category) { + case kTowers: + return towers.any((tower) => tower.id == itemId); + case kHeroes: + return heroes.any((hero) => hero.id == itemId); + case kBloons: + return bloons.any((bloon) => bloon.id == itemId); + case kBosses: + return bosses.any((boss) => boss.id == itemId); + case kMaps: + return maps.any((map) => map.id == itemId); + } + return false; } - void addFavoriteBoss(BaseModel boss) { - bosses.add(boss); + void _addToList(String category, BaseModel item) { + switch (category) { + case kTowers: + towers.add(item); + break; + case kHeroes: + heroes.add(item); + break; + case kBloons: + bloons.add(item); + break; + case kBosses: + bosses.add(item); + break; + case kMaps: + maps.add(item); + break; + } notifyListeners(); } - void removeFavoriteBoss(BaseModel boss) { - bosses.remove(boss); + void _removeFromList(String category, String itemId) { + switch (category) { + case kTowers: + towers.removeWhere((tower) => tower.id == itemId); + break; + case kHeroes: + heroes.removeWhere((hero) => hero.id == itemId); + break; + case kBloons: + bloons.removeWhere((bloon) => bloon.id == itemId); + break; + case kBosses: + bosses.removeWhere((boss) => boss.id == itemId); + break; + case kMaps: + maps.removeWhere((map) => map.id == itemId); + break; + } notifyListeners(); } - void addFavoriteMap(BaseModel map) { - maps.add(map); - notifyListeners(); + void addFavorite(String category, BaseModel item) { + _addToList(category, item); } - void removeFavoriteMap(BaseModel map) { - maps.remove(map); - notifyListeners(); + void removeFavorite(String category, String itemId) { + _removeFromList(category, itemId); } } diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index d8c1032..df9bcb5 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -66,6 +66,11 @@ String extraStatsToString(Stats stats) { // return isFavorite; // } +void setEmptyFavorites() { + var favoriteBox = Hive.box('favorite'); + favoriteBox.get(kTowers, defaultValue: []); +} + bool handleFavorite(String category, String id) { bool isFavorite; var favoriteBox = Hive.box('favorite'); @@ -77,8 +82,7 @@ bool handleFavorite(String category, String id) { favoriteList.add(id); isFavorite = true; } - favoriteBox.put(kTowers, favoriteList); - print(favoriteList); + favoriteBox.put(category, favoriteList); return isFavorite; } From 8fb8e085298444025075ff089014ccac6990001b Mon Sep 17 00:00:00 2001 From: Shai Date: Tue, 23 Jan 2024 10:38:11 +0200 Subject: [PATCH 06/32] better order of files --- lib/main.dart | 4 ++-- lib/presentation/screens/bloon/bloons.dart | 4 ++-- lib/presentation/screens/bloon/boss_bloon.dart | 2 +- lib/presentation/screens/bloon/minion_bloon.dart | 2 +- lib/presentation/screens/bloon/single_bloon.dart | 2 +- lib/presentation/screens/hero/heroes.dart | 4 ++-- lib/presentation/screens/hero/single_hero.dart | 4 ++-- lib/presentation/screens/maps/maps.dart | 2 +- lib/presentation/screens/tower/single_tower.dart | 2 +- lib/presentation/screens/tower/towers.dart | 4 ++-- lib/presentation/widgets/{ => bloons}/bloon_aid_widget.dart | 0 lib/presentation/widgets/{ => heroes}/hero_level.dart | 0 lib/presentation/widgets/{ => heroes}/hero_stats.dart | 0 lib/presentation/widgets/{ => misc}/about_us.dart | 2 +- lib/presentation/widgets/{ => misc}/developer_info.dart | 0 lib/presentation/widgets/{ => misc}/drawer_content.dart | 2 +- lib/presentation/widgets/{ => misc}/image_outline.dart | 0 lib/presentation/widgets/{ => misc}/loader.dart | 0 lib/presentation/widgets/{ => misc}/search_widget.dart | 0 lib/presentation/widgets/{ => towers}/path.dart | 0 20 files changed, 17 insertions(+), 17 deletions(-) rename lib/presentation/widgets/{ => bloons}/bloon_aid_widget.dart (100%) rename lib/presentation/widgets/{ => heroes}/hero_level.dart (100%) rename lib/presentation/widgets/{ => heroes}/hero_stats.dart (100%) rename lib/presentation/widgets/{ => misc}/about_us.dart (98%) rename lib/presentation/widgets/{ => misc}/developer_info.dart (100%) rename lib/presentation/widgets/{ => misc}/drawer_content.dart (99%) rename lib/presentation/widgets/{ => misc}/image_outline.dart (100%) rename lib/presentation/widgets/{ => misc}/loader.dart (100%) rename lib/presentation/widgets/{ => misc}/search_widget.dart (100%) rename lib/presentation/widgets/{ => towers}/path.dart (100%) diff --git a/lib/main.dart b/lib/main.dart index c143af5..41fa579 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -9,12 +9,12 @@ import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; import '/models/base/base_map.dart'; import '/models/base_model.dart'; -import '/presentation/widgets/drawer_content.dart'; +import 'presentation/widgets/misc/drawer_content.dart'; import '/presentation/screens/tower/towers.dart'; import '/presentation/screens/bloon/bloons.dart'; import '/presentation/screens/hero/heroes.dart'; import '/presentation/screens/maps/maps.dart'; -import '/presentation/widgets/loader.dart'; +import 'presentation/widgets/misc/loader.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; diff --git a/lib/presentation/screens/bloon/bloons.dart b/lib/presentation/screens/bloon/bloons.dart index ca77ea1..f45d88b 100644 --- a/lib/presentation/screens/bloon/bloons.dart +++ b/lib/presentation/screens/bloon/bloons.dart @@ -1,8 +1,8 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base_model.dart'; -import '/presentation/widgets/search_widget.dart'; -import '/presentation/widgets/image_outline.dart'; +import '../../widgets/misc/search_widget.dart'; +import '../../widgets/misc/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/global_state.dart'; diff --git a/lib/presentation/screens/bloon/boss_bloon.dart b/lib/presentation/screens/bloon/boss_bloon.dart index e43e501..e720352 100644 --- a/lib/presentation/screens/bloon/boss_bloon.dart +++ b/lib/presentation/screens/bloon/boss_bloon.dart @@ -5,7 +5,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/bloons/boss/boss_health_class.dart'; import '/models/bloons/boss/boss_bloon.dart'; -import '/presentation/widgets/bloon_aid_widget.dart'; +import '../../widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; diff --git a/lib/presentation/screens/bloon/minion_bloon.dart b/lib/presentation/screens/bloon/minion_bloon.dart index f59691f..6e1f9db 100644 --- a/lib/presentation/screens/bloon/minion_bloon.dart +++ b/lib/presentation/screens/bloon/minion_bloon.dart @@ -4,7 +4,7 @@ import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/bloons/boss/minion_bloon.dart'; -import '/presentation/widgets/bloon_aid_widget.dart'; +import '../../widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; diff --git a/lib/presentation/screens/bloon/single_bloon.dart b/lib/presentation/screens/bloon/single_bloon.dart index 8c34a3f..2ed1de1 100644 --- a/lib/presentation/screens/bloon/single_bloon.dart +++ b/lib/presentation/screens/bloon/single_bloon.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/bloons/bloon/bloon.dart'; -import '/presentation/widgets/bloon_aid_widget.dart'; +import '../../widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index e314522..6a0d518 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import '/models/base/base_hero.dart'; import '/models/base_model.dart'; import '/presentation/screens/hero/single_hero.dart'; -import '/presentation/widgets/search_widget.dart'; -import '/presentation/widgets/image_outline.dart'; +import '../../widgets/misc/search_widget.dart'; +import '../../widgets/misc/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; diff --git a/lib/presentation/screens/hero/single_hero.dart b/lib/presentation/screens/hero/single_hero.dart index 600014b..645022a 100644 --- a/lib/presentation/screens/hero/single_hero.dart +++ b/lib/presentation/screens/hero/single_hero.dart @@ -5,8 +5,8 @@ import 'package:flutter/services.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import '/models/towers/common/upgrade_info_class.dart'; import '/models/towers/hero/hero.dart'; -import '/presentation/widgets/hero_stats.dart'; -import '/presentation/widgets/hero_level.dart'; +import '../../widgets/heroes/hero_stats.dart'; +import '../../widgets/heroes/hero_level.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; diff --git a/lib/presentation/screens/maps/maps.dart b/lib/presentation/screens/maps/maps.dart index ba07c3a..14a8fe9 100644 --- a/lib/presentation/screens/maps/maps.dart +++ b/lib/presentation/screens/maps/maps.dart @@ -2,7 +2,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_map.dart'; import '/presentation/screens/maps/single_map.dart'; -import '/presentation/widgets/search_widget.dart'; +import '../../widgets/misc/search_widget.dart'; import '/presentation/widgets/maps/map_card.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; diff --git a/lib/presentation/screens/tower/single_tower.dart b/lib/presentation/screens/tower/single_tower.dart index 82db7a9..690354c 100644 --- a/lib/presentation/screens/tower/single_tower.dart +++ b/lib/presentation/screens/tower/single_tower.dart @@ -2,7 +2,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/towers/tower/tower.dart'; -import '/presentation/widgets/path.dart'; +import '../../widgets/towers/path.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index f0d19a1..1d8b6e4 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -3,8 +3,8 @@ import 'package:flutter/material.dart'; import '/models/base/base_tower.dart'; import '/models/base_model.dart'; import '/presentation/screens/tower/single_tower.dart'; -import '/presentation/widgets/search_widget.dart'; -import '/presentation/widgets/image_outline.dart'; +import '../../widgets/misc/search_widget.dart'; +import '../../widgets/misc/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; diff --git a/lib/presentation/widgets/bloon_aid_widget.dart b/lib/presentation/widgets/bloons/bloon_aid_widget.dart similarity index 100% rename from lib/presentation/widgets/bloon_aid_widget.dart rename to lib/presentation/widgets/bloons/bloon_aid_widget.dart diff --git a/lib/presentation/widgets/hero_level.dart b/lib/presentation/widgets/heroes/hero_level.dart similarity index 100% rename from lib/presentation/widgets/hero_level.dart rename to lib/presentation/widgets/heroes/hero_level.dart diff --git a/lib/presentation/widgets/hero_stats.dart b/lib/presentation/widgets/heroes/hero_stats.dart similarity index 100% rename from lib/presentation/widgets/hero_stats.dart rename to lib/presentation/widgets/heroes/hero_stats.dart diff --git a/lib/presentation/widgets/about_us.dart b/lib/presentation/widgets/misc/about_us.dart similarity index 98% rename from lib/presentation/widgets/about_us.dart rename to lib/presentation/widgets/misc/about_us.dart index c0f9a27..b999b99 100644 --- a/lib/presentation/widgets/about_us.dart +++ b/lib/presentation/widgets/misc/about_us.dart @@ -1,6 +1,6 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:flutter/material.dart'; -import '/presentation/widgets/developer_info.dart'; +import 'developer_info.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/constants.dart'; diff --git a/lib/presentation/widgets/developer_info.dart b/lib/presentation/widgets/misc/developer_info.dart similarity index 100% rename from lib/presentation/widgets/developer_info.dart rename to lib/presentation/widgets/misc/developer_info.dart diff --git a/lib/presentation/widgets/drawer_content.dart b/lib/presentation/widgets/misc/drawer_content.dart similarity index 99% rename from lib/presentation/widgets/drawer_content.dart rename to lib/presentation/widgets/misc/drawer_content.dart index c3932c0..735aa29 100644 --- a/lib/presentation/widgets/drawer_content.dart +++ b/lib/presentation/widgets/misc/drawer_content.dart @@ -1,7 +1,7 @@ import 'package:font_awesome_flutter/font_awesome_flutter.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; -import '/presentation/widgets/about_us.dart'; +import 'about_us.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/global_state.dart'; diff --git a/lib/presentation/widgets/image_outline.dart b/lib/presentation/widgets/misc/image_outline.dart similarity index 100% rename from lib/presentation/widgets/image_outline.dart rename to lib/presentation/widgets/misc/image_outline.dart diff --git a/lib/presentation/widgets/loader.dart b/lib/presentation/widgets/misc/loader.dart similarity index 100% rename from lib/presentation/widgets/loader.dart rename to lib/presentation/widgets/misc/loader.dart diff --git a/lib/presentation/widgets/search_widget.dart b/lib/presentation/widgets/misc/search_widget.dart similarity index 100% rename from lib/presentation/widgets/search_widget.dart rename to lib/presentation/widgets/misc/search_widget.dart diff --git a/lib/presentation/widgets/path.dart b/lib/presentation/widgets/towers/path.dart similarity index 100% rename from lib/presentation/widgets/path.dart rename to lib/presentation/widgets/towers/path.dart From 0f82d2ffeca61a3abff5d28c98aa01ea35c7a3bb Mon Sep 17 00:00:00 2001 From: Shai Date: Tue, 23 Jan 2024 10:39:57 +0200 Subject: [PATCH 07/32] moved bloons grids to separate files --- lib/presentation/screens/bloon/bloons.dart | 136 +----------------- .../widgets/bloons/bloons_grid.dart | 78 ++++++++++ .../widgets/bloons/bosses_grid.dart | 72 ++++++++++ 3 files changed, 152 insertions(+), 134 deletions(-) create mode 100644 lib/presentation/widgets/bloons/bloons_grid.dart create mode 100644 lib/presentation/widgets/bloons/bosses_grid.dart diff --git a/lib/presentation/screens/bloon/bloons.dart b/lib/presentation/screens/bloon/bloons.dart index f45d88b..3afdabb 100644 --- a/lib/presentation/screens/bloon/bloons.dart +++ b/lib/presentation/screens/bloon/bloons.dart @@ -1,5 +1,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; +import '../../widgets/bloons/bloons_grid.dart'; +import '../../widgets/bloons/bosses_grid.dart'; import '/models/base_model.dart'; import '../../widgets/misc/search_widget.dart'; import '../../widgets/misc/image_outline.dart'; @@ -124,137 +126,3 @@ class _BloonsState extends State { ); } } - -class BloonsGrid extends StatelessWidget { - const BloonsGrid({ - super.key, - required this.analyticsHelper, - required this.bloons, - required this.constraintsValues, - }); - - final AnalyticsHelper analyticsHelper; - final List bloons; - final Map constraintsValues; - - @override - Widget build(BuildContext context) { - return GridView.builder( - itemCount: bloons.length, - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: constraintsValues[bloonCrossCount], - childAspectRatio: constraintsValues[bloonAspectRatio], - ), - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - primary: false, - itemBuilder: (context, index) { - final bloon = bloons[index]; - return Card( - margin: const EdgeInsets.symmetric( - vertical: 3, - horizontal: 7, - ), - child: Center( - child: ListTile( - titleAlignment: ListTileTitleAlignment.center, - leading: ImageOutliner( - imageName: bloon.image, - imagePath: bloonImage(bloon.image), - width: constraintsValues[bloonImageWidth], - ), - title: Text( - bloon.name, - maxLines: 1, - style: constraintsValues[bloonTitleStyle], - ), - onTap: () { - analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kBloonPagesClass, - 'widget': listTile, - 'value': bloon.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleBloon( - analyticsHelper: analyticsHelper, - bloonId: bloon.id, - ), - ), - ); - }, - ), - ), - ); - }, - ); - } -} - -class BossesGrid extends StatelessWidget { - const BossesGrid({ - super.key, - required this.analyticsHelper, - required this.bossesList, - required this.constraintsValues, - }); - final AnalyticsHelper analyticsHelper; - final List bossesList; - final Map constraintsValues; - - @override - Widget build(BuildContext context) { - return GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: constraintsValues[bossCrossCount], - childAspectRatio: constraintsValues[bossAspectRatio], - ), - physics: const NeverScrollableScrollPhysics(), - primary: false, - itemCount: bossesList.length, - shrinkWrap: true, - itemBuilder: (context, index) { - final boss = bossesList[index]; - - return Card( - child: Center( - child: ListTile( - titleAlignment: ListTileTitleAlignment.center, - leading: ImageOutliner( - imageName: boss.image, - imagePath: bossImage(boss.image), - ), - title: Text( - boss.name, - style: constraintsValues[bossTitleStyle], - ), - onTap: () { - analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kBossPagesClass, - 'widget': listTile, - 'value': boss.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => BossBloon( - analyticsHelper: analyticsHelper, - bossId: boss.id, - ), - ), - ); - }, - ), - ), - ); - }, - ); - } -} diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart new file mode 100644 index 0000000..a22b357 --- /dev/null +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -0,0 +1,78 @@ +import 'package:btd6wiki/analytics/analytics.dart'; +import 'package:btd6wiki/analytics/analytics_constants.dart'; +import 'package:btd6wiki/models/base_model.dart'; +import 'package:btd6wiki/presentation/screens/bloon/single_bloon.dart'; +import 'package:btd6wiki/presentation/widgets/misc/image_outline.dart'; +import 'package:btd6wiki/utilities/constants.dart'; +import 'package:btd6wiki/utilities/images_url.dart'; +import 'package:flutter/material.dart'; + +class BloonsGrid extends StatelessWidget { + const BloonsGrid({ + super.key, + required this.analyticsHelper, + required this.bloons, + required this.constraintsValues, + }); + + final AnalyticsHelper analyticsHelper; + final List bloons; + final Map constraintsValues; + + @override + Widget build(BuildContext context) { + return GridView.builder( + itemCount: bloons.length, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: constraintsValues[bloonCrossCount], + childAspectRatio: constraintsValues[bloonAspectRatio], + ), + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + primary: false, + itemBuilder: (context, index) { + final bloon = bloons[index]; + return Card( + margin: const EdgeInsets.symmetric( + vertical: 3, + horizontal: 7, + ), + child: Center( + child: ListTile( + titleAlignment: ListTileTitleAlignment.center, + leading: ImageOutliner( + imageName: bloon.image, + imagePath: bloonImage(bloon.image), + width: constraintsValues[bloonImageWidth], + ), + title: Text( + bloon.name, + maxLines: 1, + style: constraintsValues[bloonTitleStyle], + ), + onTap: () { + analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kBloonPagesClass, + 'widget': listTile, + 'value': bloon.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleBloon( + analyticsHelper: analyticsHelper, + bloonId: bloon.id, + ), + ), + ); + }, + ), + ), + ); + }, + ); + } +} diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart new file mode 100644 index 0000000..e507da4 --- /dev/null +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -0,0 +1,72 @@ +import 'package:btd6wiki/analytics/analytics.dart'; +import 'package:btd6wiki/analytics/analytics_constants.dart'; +import 'package:btd6wiki/models/base_model.dart'; +import 'package:btd6wiki/presentation/screens/bloon/boss_bloon.dart'; +import 'package:btd6wiki/presentation/widgets/misc/image_outline.dart'; +import 'package:btd6wiki/utilities/constants.dart'; +import 'package:btd6wiki/utilities/images_url.dart'; +import 'package:flutter/material.dart'; + +class BossesGrid extends StatelessWidget { + const BossesGrid({ + super.key, + required this.analyticsHelper, + required this.bossesList, + required this.constraintsValues, + }); + final AnalyticsHelper analyticsHelper; + final List bossesList; + final Map constraintsValues; + + @override + Widget build(BuildContext context) { + return GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: constraintsValues[bossCrossCount], + childAspectRatio: constraintsValues[bossAspectRatio], + ), + physics: const NeverScrollableScrollPhysics(), + primary: false, + itemCount: bossesList.length, + shrinkWrap: true, + itemBuilder: (context, index) { + final boss = bossesList[index]; + + return Card( + child: Center( + child: ListTile( + titleAlignment: ListTileTitleAlignment.center, + leading: ImageOutliner( + imageName: boss.image, + imagePath: bossImage(boss.image), + ), + title: Text( + boss.name, + style: constraintsValues[bossTitleStyle], + ), + onTap: () { + analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kBossPagesClass, + 'widget': listTile, + 'value': boss.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BossBloon( + analyticsHelper: analyticsHelper, + bossId: boss.id, + ), + ), + ); + }, + ), + ), + ); + }, + ); + } +} From 275e3eb7d78370ecd5d41962e73e70555fb402e9 Mon Sep 17 00:00:00 2001 From: Shai Date: Thu, 8 Feb 2024 17:02:45 +0200 Subject: [PATCH 08/32] favorites work now for towers heroes and bloons --- devtools_options.yaml | 1 + lib/hive/favorite_model.dart | 23 ++ lib/hive/favorite_model.g.dart | 53 ++++ lib/hive/favorite_model_adapter.dart | 27 ++ lib/main.dart | 31 +- lib/presentation/screens/bloon/bloons.dart | 10 +- lib/presentation/screens/hero/heroes.dart | 44 +-- lib/presentation/screens/tower/towers.dart | 41 +-- .../widgets/bloons/bloons_grid.dart | 76 +++-- .../widgets/misc/drawer_content.dart | 8 +- lib/utilities/constants.dart | 2 + lib/utilities/favorite_state.dart | 127 +++----- lib/utilities/utils.dart | 37 --- pubspec.lock | 272 +++++++++++++++++- pubspec.yaml | 2 + 15 files changed, 519 insertions(+), 235 deletions(-) create mode 100644 devtools_options.yaml create mode 100644 lib/hive/favorite_model.dart create mode 100644 lib/hive/favorite_model.g.dart create mode 100644 lib/hive/favorite_model_adapter.dart diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..7e7e7f6 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1 @@ +extensions: diff --git a/lib/hive/favorite_model.dart b/lib/hive/favorite_model.dart new file mode 100644 index 0000000..e84db2a --- /dev/null +++ b/lib/hive/favorite_model.dart @@ -0,0 +1,23 @@ +import 'package:hive_flutter/hive_flutter.dart'; + +part 'favorite_model.g.dart'; + +@HiveType(typeId: 1) +class FavoriteModel extends HiveObject { + @HiveField(0) + late final String id; + + @HiveField(1) + late final String name; + + @HiveField(2) + late final String image; + + @HiveField(3) + late final String type; + + @HiveField(4) + late int itemIndex; + + FavoriteModel(this.id, this.name, this.image, this.type, this.itemIndex); +} diff --git a/lib/hive/favorite_model.g.dart b/lib/hive/favorite_model.g.dart new file mode 100644 index 0000000..b3929d1 --- /dev/null +++ b/lib/hive/favorite_model.g.dart @@ -0,0 +1,53 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'favorite_model.dart'; + +// ************************************************************************** +// TypeAdapterGenerator +// ************************************************************************** + +class FavoriteModelAdapter extends TypeAdapter { + @override + final int typeId = 1; + + @override + FavoriteModel read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return FavoriteModel( + fields[0] as String, + fields[1] as String, + fields[2] as String, + fields[3] as String, + fields[4] as int, + ); + } + + @override + void write(BinaryWriter writer, FavoriteModel obj) { + writer + ..writeByte(5) + ..writeByte(0) + ..write(obj.id) + ..writeByte(1) + ..write(obj.name) + ..writeByte(2) + ..write(obj.image) + ..writeByte(3) + ..write(obj.type) + ..writeByte(4) + ..write(obj.itemIndex); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FavoriteModelAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} diff --git a/lib/hive/favorite_model_adapter.dart b/lib/hive/favorite_model_adapter.dart new file mode 100644 index 0000000..53a2967 --- /dev/null +++ b/lib/hive/favorite_model_adapter.dart @@ -0,0 +1,27 @@ +import 'package:hive_flutter/hive_flutter.dart'; +import '/hive/favorite_model.dart'; + +class FavoriteModelBoxAdapter extends TypeAdapter { + @override + final typeId = 1; + + @override + FavoriteModel read(BinaryReader reader) { + return FavoriteModel( + reader.readString(), + reader.readString(), + reader.readString(), + reader.readString(), + reader.readInt(), + ); + } + + @override + void write(BinaryWriter writer, FavoriteModel obj) { + writer.writeString(obj.id); + writer.writeString(obj.name); + writer.writeString(obj.image); + writer.writeString(obj.type); + writer.writeInt(obj.itemIndex); + } +} diff --git a/lib/main.dart b/lib/main.dart index 41fa579..5ca7e32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -5,16 +5,17 @@ import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/firebase_options.dart'; +import '/hive/favorite_model.dart'; import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; import '/models/base/base_map.dart'; import '/models/base_model.dart'; -import 'presentation/widgets/misc/drawer_content.dart'; +import '/presentation/widgets/misc/drawer_content.dart'; import '/presentation/screens/tower/towers.dart'; import '/presentation/screens/bloon/bloons.dart'; import '/presentation/screens/hero/heroes.dart'; import '/presentation/screens/maps/maps.dart'; -import 'presentation/widgets/misc/loader.dart'; +import '/presentation/widgets/misc/loader.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; @@ -32,7 +33,12 @@ Future main() async { ); final analytics = FirebaseAnalytics.instance; await Hive.initFlutter(); - await Hive.openBox('favorite'); + // await Hive.deleteBoxFromDisk(kFavorite); + Hive.registerAdapter(FavoriteModelAdapter()); + // Removed redundant opening + await Hive.openBox>(kFavorite); + // print(Hive.box(kFavorite).toMap()); + runApp(MyApp(analytics: analytics)); } @@ -107,7 +113,6 @@ class _MyHomePageState extends State { void initState() { super.initState(); loadBaseData(); - setEmptyFavorites(); analyticsHelper = AnalyticsHelper(widget.analytics); pageController = PageController(initialPage: 0); } @@ -193,14 +198,24 @@ class _MyHomePageState extends State { ), IconButton( onPressed: () async { - var favBox = Hive.box('favorite'); - await favBox.deleteFromDisk(); - favBox = await Hive.openBox('favorite'); - print(favBox.values); + // await favBox.deleteFromDisk(); + // favBox = await Hive.openBox('favorite'); + print(Hive.box>(kFavorite).toMap()); + // print(favBox.get(kTowers)); }, icon: const Icon(Icons.star), ), + IconButton( + onPressed: () async { + await Hive.deleteFromDisk(); + // favBox = await Hive.openBox('favorite'); + // print(Hive.box(kFavorite).toMap()); + + // print(favBox.get(kTowers)); + }, + icon: const Icon(Icons.remove), + ), ], ), body: !isLoading diff --git a/lib/presentation/screens/bloon/bloons.dart b/lib/presentation/screens/bloon/bloons.dart index 3afdabb..a131760 100644 --- a/lib/presentation/screens/bloon/bloons.dart +++ b/lib/presentation/screens/bloon/bloons.dart @@ -1,18 +1,14 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; -import '../../widgets/bloons/bloons_grid.dart'; -import '../../widgets/bloons/bosses_grid.dart'; import '/models/base_model.dart'; -import '../../widgets/misc/search_widget.dart'; -import '../../widgets/misc/image_outline.dart'; +import '/presentation/widgets/bloons/bloons_grid.dart'; +import '/presentation/widgets/bloons/bosses_grid.dart'; +import '/presentation/widgets/misc/search_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/global_state.dart'; -import '/utilities/images_url.dart'; import '/utilities/constants.dart'; import '/utilities/utils.dart'; -import 'single_bloon.dart'; -import 'boss_bloon.dart'; class Bloons extends StatefulWidget { const Bloons({ diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index 6a0d518..6a2f732 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -1,10 +1,9 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_hero.dart'; -import '/models/base_model.dart'; +import '/presentation/widgets/misc/search_widget.dart'; +import '/presentation/widgets/misc/image_outline.dart'; import '/presentation/screens/hero/single_hero.dart'; -import '../../widgets/misc/search_widget.dart'; -import '../../widgets/misc/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; @@ -43,10 +42,6 @@ class _HeroesState extends State { MediaQuery.of(context).size, ); - FavoriteState favoriteState = - Provider.of(context, listen: false); - favoriteState.fillList(kHeroes, widget.heroes); - bool isFavorite = false; return Scaffold( body: Column( children: [ @@ -57,8 +52,8 @@ class _HeroesState extends State { : Container(), ), Expanded( - child: Consumer( - builder: (context, globalState, child) { + child: Consumer2( + builder: (context, globalState, favoriteState, child) { final filteredHeroes = heroesFromSearch(widget.heroes, globalState.currentQuery); return GridView.builder( @@ -74,19 +69,7 @@ class _HeroesState extends State { return InkWell( borderRadius: BorderRadius.circular(20), onLongPress: () { - isFavorite = handleFavorite(kHeroes, hero.id); - if (isFavorite) { - BaseModel favoriteHero = BaseModel( - hero.id, - hero.name, - hero.image, - hero.type, - ); - favoriteState.addFavorite(kHeroes, favoriteHero); - } else { - favoriteState.removeFavorite(kHeroes, hero.id); - } - print(favoriteState.favoriteBox.get(kHeroes)); + favoriteState.toggleFavorite(hero); }, onTap: () { widget.analyticsHelper.logEvent( @@ -134,17 +117,12 @@ class _HeroesState extends State { ), ), ), - Consumer( - builder: (context, favoriteState, child) { - return Positioned( - top: 17, - right: 25, - child: favoriteState.isInFavorites( - kHeroes, hero.id) - ? const Icon(Icons.star) - : const Icon(Icons.star_border_outlined), - ); - }, + Positioned( + top: 17, + right: 25, + child: favoriteState.isFavorite(hero.type, hero.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), ), ], ), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 1d8b6e4..30fbdc8 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -1,10 +1,9 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_tower.dart'; -import '/models/base_model.dart'; import '/presentation/screens/tower/single_tower.dart'; -import '../../widgets/misc/search_widget.dart'; -import '../../widgets/misc/image_outline.dart'; +import '/presentation/widgets/misc/search_widget.dart'; +import '/presentation/widgets/misc/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; @@ -42,10 +41,7 @@ class _TowersState extends State { final constraintsValues = getPreset( MediaQuery.of(context).size, ); - FavoriteState favoriteState = - Provider.of(context, listen: false); - favoriteState.fillList(kTowers, widget.towers); - bool isFavorite = false; + return Scaffold( body: Column( children: [ @@ -56,8 +52,8 @@ class _TowersState extends State { : Container(), ), Expanded( - child: Consumer( - builder: (context, globalState, child) { + child: Consumer2( + builder: (context, globalState, favoriteState, child) { final filteredTowers = filterAndSearchTowers(widget.towers, globalState.currentQuery, globalState.currentOption); @@ -74,18 +70,7 @@ class _TowersState extends State { return InkWell( borderRadius: BorderRadius.circular(20), onLongPress: () { - isFavorite = handleFavorite(kTowers, tower.id); - if (isFavorite) { - BaseModel favoriteTower = BaseModel( - tower.id, - tower.name, - tower.image, - tower.type, - ); - favoriteState.addFavorite(kTowers, favoriteTower); - } else { - favoriteState.removeFavorite(kTowers, tower.id); - } + favoriteState.toggleFavorite(tower); }, onTap: () { widget.analyticsHelper.logEvent( @@ -137,17 +122,13 @@ class _TowersState extends State { ), ), ), - Consumer( - builder: (context, favoriteState, child) { - return Positioned( - top: 17, - right: 25, - child: favoriteState.isInFavorites( - kTowers, tower.id) + Positioned( + top: 17, + right: 25, + child: + favoriteState.isFavorite(tower.type, tower.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), - ); - }, ), ], ), diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index a22b357..8ed3d98 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -1,11 +1,13 @@ -import 'package:btd6wiki/analytics/analytics.dart'; -import 'package:btd6wiki/analytics/analytics_constants.dart'; -import 'package:btd6wiki/models/base_model.dart'; -import 'package:btd6wiki/presentation/screens/bloon/single_bloon.dart'; -import 'package:btd6wiki/presentation/widgets/misc/image_outline.dart'; -import 'package:btd6wiki/utilities/constants.dart'; -import 'package:btd6wiki/utilities/images_url.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import '/models/base_model.dart'; +import '/presentation/widgets/misc/image_outline.dart'; +import '/presentation/screens/bloon/single_bloon.dart'; +import '/analytics/analytics_constants.dart'; +import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; +import '/utilities/images_url.dart'; +import '/utilities/constants.dart'; class BloonsGrid extends StatelessWidget { const BloonsGrid({ @@ -32,24 +34,12 @@ class BloonsGrid extends StatelessWidget { primary: false, itemBuilder: (context, index) { final bloon = bloons[index]; - return Card( - margin: const EdgeInsets.symmetric( - vertical: 3, - horizontal: 7, - ), - child: Center( - child: ListTile( - titleAlignment: ListTileTitleAlignment.center, - leading: ImageOutliner( - imageName: bloon.image, - imagePath: bloonImage(bloon.image), - width: constraintsValues[bloonImageWidth], - ), - title: Text( - bloon.name, - maxLines: 1, - style: constraintsValues[bloonTitleStyle], - ), + return Consumer( + builder: (context, favoriteState, child) { + return InkWell( + onLongPress: () { + favoriteState.toggleFavorite(bloon); + }, onTap: () { analyticsHelper.logEvent( name: widgetEngagement, @@ -69,8 +59,40 @@ class BloonsGrid extends StatelessWidget { ), ); }, - ), - ), + child: Stack( + children: [ + Card( + margin: const EdgeInsets.symmetric( + vertical: 3, + horizontal: 7, + ), + child: Center( + child: ListTile( + titleAlignment: ListTileTitleAlignment.center, + leading: ImageOutliner( + imageName: bloon.image, + imagePath: bloonImage(bloon.image), + width: constraintsValues[bloonImageWidth], + ), + title: Text( + bloon.name, + maxLines: 1, + style: constraintsValues[bloonTitleStyle], + ), + ), + ), + ), + Positioned( + top: 17, + right: 25, + child: favoriteState.isFavorite(bloon.type, bloon.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ), + ], + ), + ); + }, ); }, ); diff --git a/lib/presentation/widgets/misc/drawer_content.dart b/lib/presentation/widgets/misc/drawer_content.dart index 735aa29..1fcfcb1 100644 --- a/lib/presentation/widgets/misc/drawer_content.dart +++ b/lib/presentation/widgets/misc/drawer_content.dart @@ -27,7 +27,7 @@ class _DrawerContentState extends State { ExpansionTileController(); final ExpansionTileController _mapsExpansionTileController = ExpansionTileController(); - final ExpansionTileController _bloonsExpansionTileControleer = + final ExpansionTileController _bloonsExpansionTileController = ExpansionTileController(); @override @@ -90,7 +90,7 @@ class _DrawerContentState extends State { () { if (value) { _mapsExpansionTileController.collapse(); - _bloonsExpansionTileControleer.collapse(); + _bloonsExpansionTileController.collapse(); } }, ); @@ -153,7 +153,7 @@ class _DrawerContentState extends State { }, ), ExpansionTile( - controller: _bloonsExpansionTileControleer, + controller: _bloonsExpansionTileController, title: Text(capTitles[kBloonsIndex], style: titleStyle.copyWith(color: Colors.teal)), onExpansionChanged: (bool value) { @@ -227,7 +227,7 @@ class _DrawerContentState extends State { setState( () { if (value) { - _bloonsExpansionTileControleer.collapse(); + _bloonsExpansionTileController.collapse(); _towersExpansionTileController.collapse(); } }, diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index ce8ce9d..60c7a71 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -12,6 +12,8 @@ const int kHeroesIndex = 1; const int kBloonsIndex = 2; const int kMapsIndex = 3; +const String kFavorite = 'favorite'; + const List capTitles = [ 'Towers', 'Heroes', diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 7afcb7d..9feda84 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -1,106 +1,63 @@ -import 'package:btd6wiki/utilities/constants.dart'; -import 'package:hive_flutter/hive_flutter.dart'; import 'package:flutter/material.dart'; -import '/models/base_model.dart'; - -class FavoriteState with ChangeNotifier { - var favoriteBox; +import 'package:hive_flutter/hive_flutter.dart'; +import '/hive/favorite_model.dart'; +import '/utilities/constants.dart'; - List towers = []; - List heroes = []; - List bloons = []; - List bosses = []; - List maps = []; +class FavoriteState extends ChangeNotifier { + late Box> _favoriteBox; - void loadFavoriteBox() { - favoriteBox = Hive.box('favorite'); + FavoriteState() { + _favoriteBox = Hive.box>(kFavorite); } - void fillList(String category, List baseObjects) { - loadFavoriteBox(); - if (favoriteBox.get(category.toString()) != null) { - List favoritesIds = favoriteBox.get(category.toString()); + void toggleFavorite(var item) { + FavoriteModel favItem = _createFavoriteItem(item); - for (var baseObj in baseObjects) { - if (favoritesIds.contains(baseObj.id)) { - BaseModel item = BaseModel( - baseObj.id, - baseObj.name, - baseObj.image, - baseObj.type, - ); - _addToList(category, item); - } - } + if (!_favoriteBox.containsKey(favItem.type)) { + _favoriteBox.put(favItem.type, [favItem]); } else { - print('$category is empty'); - favoriteBox.get(category.toString(), defaultValue: []); + List typeList = _favoriteBox.get(favItem.type)!; + if (isFavorite(favItem.type, favItem.id)) { + typeList.removeWhere((element) => element.id == favItem.id); + } else { + typeList.add(favItem); + } + _favoriteBox.put(favItem.type, typeList); } + notifyListeners(); } - bool isInFavorites(String category, String itemId) { - switch (category) { - case kTowers: - return towers.any((tower) => tower.id == itemId); - case kHeroes: - return heroes.any((hero) => hero.id == itemId); - case kBloons: - return bloons.any((bloon) => bloon.id == itemId); - case kBosses: - return bosses.any((boss) => boss.id == itemId); - case kMaps: - return maps.any((map) => map.id == itemId); + bool isFavorite(String type, String id) { + if (!_favoriteBox.containsKey(type)) return false; + List typeList = _favoriteBox.get(type)!; + for (FavoriteModel item in typeList) { + if (item.id == id) return true; } - return false; - } - void _addToList(String category, BaseModel item) { - switch (category) { - case kTowers: - towers.add(item); - break; - case kHeroes: - heroes.add(item); - break; - case kBloons: - bloons.add(item); - break; - case kBosses: - bosses.add(item); - break; - case kMaps: - maps.add(item); - break; - } - notifyListeners(); + return false; } - void _removeFromList(String category, String itemId) { - switch (category) { - case kTowers: - towers.removeWhere((tower) => tower.id == itemId); - break; - case kHeroes: - heroes.removeWhere((hero) => hero.id == itemId); - break; - case kBloons: - bloons.removeWhere((bloon) => bloon.id == itemId); - break; - case kBosses: - bosses.removeWhere((boss) => boss.id == itemId); - break; - case kMaps: - maps.removeWhere((map) => map.id == itemId); - break; + int _getLastIndexOfType(String type) { + if (!_favoriteBox.containsKey(type)) { + return 0; + } else { + var favorites = _favoriteBox.get(type)!; + return favorites.length; } - notifyListeners(); } - void addFavorite(String category, BaseModel item) { - _addToList(category, item); + FavoriteModel _createFavoriteItem(var item) { + return FavoriteModel( + item.id, + item.name, + item.image, + item.type, + _getLastIndexOfType(item.type), + ); } - void removeFavorite(String category, String itemId) { - _removeFromList(category, itemId); + void _updateLastIndexes() { + // TODO implement updating indexes of all the items of the type + // this comes after implementing moveable grid to show the items and change their order } } diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index df9bcb5..e6e4d2f 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,4 +1,3 @@ -import 'package:hive_flutter/hive_flutter.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; import '/models/bloons/common/relative_class.dart'; @@ -50,42 +49,6 @@ String extraStatsToString(Stats stats) { return "Status Effects: ${stats.statuseffects}\nIncome Boosts: ${stats.incomeboosts}\nTower Boosts: ${stats.towerboosts}"; } -// Future handleFavorite(String category, String id) async { -// bool isFavorite; - -// List favoriteList = favoriteBox.get(category, defaultValue: []); -// if (favoriteList.contains(id)) { -// favoriteList.remove(id); -// isFavorite = false; -// } else { -// favoriteList.add(id); -// isFavorite = true; -// } -// favoriteBox.put(kTowers, favoriteList); -// print(favoriteList); -// return isFavorite; -// } - -void setEmptyFavorites() { - var favoriteBox = Hive.box('favorite'); - favoriteBox.get(kTowers, defaultValue: []); -} - -bool handleFavorite(String category, String id) { - bool isFavorite; - var favoriteBox = Hive.box('favorite'); - List favoriteList = favoriteBox.get(category, defaultValue: []); - if (favoriteList.contains(id)) { - favoriteList.remove(id); - isFavorite = false; - } else { - favoriteList.add(id); - isFavorite = true; - } - favoriteBox.put(category, favoriteList); - return isFavorite; -} - List filterAndSearchBloons( List bloons, String query, String option) { query = query.toLowerCase(); diff --git a/pubspec.lock b/pubspec.lock index ceb221d..0a24ba9 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,6 +1,14 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: eb376e9acf6938204f90eb3b1f00b578640d3188b4c8a8ec054f9f479af8d051 + url: "https://pub.dev" + source: hosted + version: "64.0.0" _flutterfire_internals: dependency: transitive description: @@ -17,6 +25,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.5.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "69f54f967773f6c26c7dcb13e93d7ccee8b17a641689da39e878d5cf13b06893" + url: "https://pub.dev" + source: hosted + version: "6.2.0" android_intent_plus: dependency: transitive description: @@ -65,6 +81,70 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.1" + build: + dependency: transitive + description: + name: build + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" + url: "https://pub.dev" + source: hosted + version: "2.4.1" + build_config: + dependency: transitive + description: + name: build_config + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 + url: "https://pub.dev" + source: hosted + version: "1.1.1" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: "0343061a33da9c5810b2d6cee51945127d8f4c060b7fbdd9d54917f0a3feaaa1" + url: "https://pub.dev" + source: hosted + version: "4.0.1" + build_resolvers: + dependency: transitive + description: + name: build_resolvers + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" + url: "https://pub.dev" + source: hosted + version: "2.4.2" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "581bacf68f89ec8792f5e5a0b2c4decd1c948e97ce659dc783688c8a88fbec21" + url: "https://pub.dev" + source: hosted + version: "2.4.8" + build_runner_core: + dependency: transitive + description: + name: build_runner_core + sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + url: "https://pub.dev" + source: hosted + version: "7.2.11" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 + url: "https://pub.dev" + source: hosted + version: "8.8.1" carousel_slider: dependency: "direct main" description: @@ -105,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: f692079e25e7869c14132d39f223f8eec9830eb76131925143b2129c4bb01b37 + url: "https://pub.dev" + source: hosted + version: "4.10.0" collection: dependency: transitive description: @@ -137,6 +225,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.6" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: "40ae61a5d43feea6d24bd22c0537a6629db858963b99b4bc1c3db80676f32368" + url: "https://pub.dev" + source: hosted + version: "2.3.4" fake_async: dependency: transitive description: @@ -209,6 +305,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.10.0" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1" + url: "https://pub.dev" + source: hosted + version: "1.1.0" flutter: dependency: "direct main" description: flutter @@ -248,6 +352,30 @@ packages: url: "https://pub.dev" source: hosted version: "10.6.0" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: "408e3ca148b31c20282ad6f37ebfa6f4bdc8fede5b74bc2f08d9d92b55db3612" + url: "https://pub.dev" + source: hosted + version: "3.2.0" + glob: + dependency: transitive + description: + name: glob + sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + graphs: + dependency: transitive + description: + name: graphs + sha256: aedc5a15e78fc65a6e23bcd927f24c64dd995062bcd1ca6eda65a3cff92a4d19 + url: "https://pub.dev" + source: hosted + version: "2.3.1" hive: dependency: "direct main" description: @@ -264,6 +392,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + hive_generator: + dependency: "direct dev" + description: + name: hive_generator + sha256: "06cb8f58ace74de61f63500564931f9505368f45f98958bd7a6c35ba24159db4" + url: "https://pub.dev" + source: hosted + version: "2.0.1" http: dependency: "direct main" description: @@ -272,6 +408,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: "97486f20f9c2f7be8f514851703d0119c3596d14ea63227af6f7a481ef2b2f8b" + url: "https://pub.dev" + source: hosted + version: "3.2.1" http_parser: dependency: transitive description: @@ -288,6 +432,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.1.4" + io: + dependency: transitive + description: + name: io + sha256: "2ec25704aba361659e10e3e5f5d672068d332fc8ac516421d483a11e5cbd061e" + url: "https://pub.dev" + source: hosted + version: "1.0.4" js: dependency: transitive description: @@ -312,6 +464,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.0" + logging: + dependency: transitive + description: + name: logging + sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340" + url: "https://pub.dev" + source: hosted + version: "1.2.0" matcher: dependency: transitive description: @@ -336,6 +496,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.0" + mime: + dependency: transitive + description: + name: mime + sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + url: "https://pub.dev" + source: hosted + version: "1.0.4" model_viewer_plus: dependency: "direct main" description: @@ -352,6 +520,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + package_config: + dependency: transitive + description: + name: package_config + sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd" + url: "https://pub.dev" + source: hosted + version: "2.1.0" path: dependency: transitive description: @@ -440,6 +616,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.7.4" + pool: + dependency: transitive + description: + name: pool + sha256: "20fe868b6314b322ea036ba325e6fc0711a22948856475e2c2b6306e8ab39c2a" + url: "https://pub.dev" + source: hosted + version: "1.5.1" provider: dependency: "direct main" description: @@ -448,6 +632,22 @@ packages: url: "https://pub.dev" source: hosted version: "6.1.1" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: c63b2876e58e194e4b0828fcb080ad0e06d051cb607a6be51a9e084f47cb9367 + url: "https://pub.dev" + source: hosted + version: "1.2.3" shared_preferences: dependency: transitive description: @@ -504,6 +704,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.2" + shelf: + dependency: transitive + description: + name: shelf + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 + url: "https://pub.dev" + source: hosted + version: "1.4.1" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "9ca081be41c60190ebcb4766b2486a7d50261db7bd0f5d9615f2d653637a84c1" + url: "https://pub.dev" + source: hosted + version: "1.0.4" sky_engine: dependency: transitive description: flutter @@ -517,6 +733,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "6adebc0006c37dd63fe05bca0a929b99f06402fc95aa35bf36d67f5c06de01fd" + url: "https://pub.dev" + source: hosted + version: "1.3.4" source_span: dependency: transitive description: @@ -541,6 +773,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.2" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: "14a00e794c7c11aa145a170587321aedce29769c08d7f58b1d141da75e3b1c6f" + url: "https://pub.dev" + source: hosted + version: "2.1.0" string_scanner: dependency: transitive description: @@ -565,6 +805,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.6.1" + timing: + dependency: transitive + description: + name: timing + sha256: "70a3b636575d4163c477e6de42f247a23b315ae20e86442bebe32d3cabf61c32" + url: "https://pub.dev" + source: hosted + version: "1.0.1" typed_data: dependency: transitive description: @@ -577,10 +825,10 @@ packages: dependency: "direct main" description: name: url_launcher - sha256: d25bb0ca00432a5e1ee40e69c36c85863addf7cc45e433769d61bed3fe81fd96 + sha256: c512655380d241a337521703af62d2c122bf7b77a46ff7dd750092aa9433499c url: "https://pub.dev" source: hosted - version: "6.2.3" + version: "6.2.4" url_launcher_android: dependency: transitive description: @@ -645,6 +893,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + watcher: + dependency: transitive + description: + name: watcher + sha256: "3d2ad6751b3c16cf07c7fca317a1413b3f26530319181b37e3b9039b84fc01d8" + url: "https://pub.dev" + source: hosted + version: "1.1.0" web: dependency: transitive description: @@ -653,6 +909,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.3.0" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d88238e5eac9a42bb43ca4e721edba3c08c6354d4a53063afaa568516217621b + url: "https://pub.dev" + source: hosted + version: "2.4.0" webview_flutter: dependency: transitive description: @@ -673,10 +937,10 @@ packages: dependency: transitive description: name: webview_flutter_platform_interface - sha256: "80b40ae4fb959957eef9fa8970b6c9accda9f49fc45c2b75154696a8e8996cfe" + sha256: d937581d6e558908d7ae3dc1989c4f87b786891ab47bb9df7de548a151779d8d url: "https://pub.dev" source: hosted - version: "2.9.1" + version: "2.10.0" webview_flutter_wkwebview: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 9309bb9..0972b8d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -54,6 +54,8 @@ dev_dependencies: flutter_test: sdk: flutter flutter_lints: ^3.0.1 + hive_generator: ^2.0.0 + build_runner: ^2.1.0 flutter_icons: android: true From 4a97c36053f22976abae75e540c66eb72b4330b6 Mon Sep 17 00:00:00 2001 From: Shai Date: Thu, 8 Feb 2024 18:35:02 +0200 Subject: [PATCH 09/32] now also bosses and maps work --- lib/main.dart | 11 +++- lib/presentation/screens/maps/maps.dart | 18 +++--- .../widgets/bloons/bloons_grid.dart | 44 ++++++------- .../widgets/bloons/bosses_grid.dart | 43 ++++++++----- lib/presentation/widgets/maps/map_card.dart | 62 ++++++++++--------- lib/utilities/favorite_state.dart | 12 ++-- 6 files changed, 104 insertions(+), 86 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 5ca7e32..a48b024 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -33,10 +33,10 @@ Future main() async { ); final analytics = FirebaseAnalytics.instance; await Hive.initFlutter(); - // await Hive.deleteBoxFromDisk(kFavorite); + // await Hive.deleteFromDisk(); Hive.registerAdapter(FavoriteModelAdapter()); // Removed redundant opening - await Hive.openBox>(kFavorite); + await Hive.openBox>(kFavorite); // print(Hive.box(kFavorite).toMap()); runApp(MyApp(analytics: analytics)); @@ -200,7 +200,12 @@ class _MyHomePageState extends State { onPressed: () async { // await favBox.deleteFromDisk(); // favBox = await Hive.openBox('favorite'); - print(Hive.box>(kFavorite).toMap()); + try { + print(Hive.box>(kFavorite).toMap()); + } catch (e) { + print(e); + await Hive.openBox(kFavorite); + } // print(favBox.get(kTowers)); }, diff --git a/lib/presentation/screens/maps/maps.dart b/lib/presentation/screens/maps/maps.dart index 14a8fe9..af85762 100644 --- a/lib/presentation/screens/maps/maps.dart +++ b/lib/presentation/screens/maps/maps.dart @@ -1,11 +1,12 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_map.dart'; +import '/presentation/widgets/misc/search_widget.dart'; import '/presentation/screens/maps/single_map.dart'; -import '../../widgets/misc/search_widget.dart'; import '/presentation/widgets/maps/map_card.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/global_state.dart'; import '/utilities/constants.dart'; import '/utilities/utils.dart'; @@ -59,8 +60,8 @@ class _MapsState extends State { }, ), Expanded( - child: Consumer( - builder: (context, globalState, child) { + child: Consumer2( + builder: (context, globalState, favoriteState, child) { final filteredMaps = filterAndSearchMaps(widget.maps, globalState.currentQuery, globalState.currentOption); return GridView.builder( @@ -71,16 +72,19 @@ class _MapsState extends State { ), shrinkWrap: true, itemBuilder: (context, index) { + BaseMap map = filteredMaps[index]; return Padding( padding: const EdgeInsets.all(5.0), child: GestureDetector( + onLongPress: () { + favoriteState.toggleFavorite(map); + }, onTap: () { widget.analyticsHelper.logEvent( name: widgetEngagement, parameters: { 'screen': kMapPagesClass, - 'widget': listTile, - 'value': filteredMaps[index].id, + 'widget': map.id, }, ); Navigator.push( @@ -88,12 +92,12 @@ class _MapsState extends State { MaterialPageRoute( builder: (context) => SingleMap( analyticsHelper: widget.analyticsHelper, - mapId: filteredMaps[index].id, + mapId: map.id, ), ), ); }, - child: MapCard(singleMap: filteredMaps[index]), + child: MapCard(singleMap: map), ), ); }, diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index 8ed3d98..e3ce793 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -59,37 +59,29 @@ class BloonsGrid extends StatelessWidget { ), ); }, - child: Stack( - children: [ - Card( - margin: const EdgeInsets.symmetric( - vertical: 3, - horizontal: 7, + child: Card( + margin: const EdgeInsets.symmetric( + vertical: 3, + horizontal: 7, + ), + child: Center( + child: ListTile( + titleAlignment: ListTileTitleAlignment.center, + leading: ImageOutliner( + imageName: bloon.image, + imagePath: bloonImage(bloon.image), + width: constraintsValues[bloonImageWidth], ), - child: Center( - child: ListTile( - titleAlignment: ListTileTitleAlignment.center, - leading: ImageOutliner( - imageName: bloon.image, - imagePath: bloonImage(bloon.image), - width: constraintsValues[bloonImageWidth], - ), - title: Text( - bloon.name, - maxLines: 1, - style: constraintsValues[bloonTitleStyle], - ), - ), + title: Text( + bloon.name, + maxLines: 1, + style: constraintsValues[bloonTitleStyle], ), - ), - Positioned( - top: 17, - right: 25, - child: favoriteState.isFavorite(bloon.type, bloon.id) + trailing: favoriteState.isFavorite(bloon.type, bloon.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), ), - ], + ), ), ); }, diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index e507da4..9759096 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -4,8 +4,10 @@ import 'package:btd6wiki/models/base_model.dart'; import 'package:btd6wiki/presentation/screens/bloon/boss_bloon.dart'; import 'package:btd6wiki/presentation/widgets/misc/image_outline.dart'; import 'package:btd6wiki/utilities/constants.dart'; +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:btd6wiki/utilities/images_url.dart'; import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; class BossesGrid extends StatelessWidget { const BossesGrid({ @@ -31,19 +33,12 @@ class BossesGrid extends StatelessWidget { shrinkWrap: true, itemBuilder: (context, index) { final boss = bossesList[index]; - - return Card( - child: Center( - child: ListTile( - titleAlignment: ListTileTitleAlignment.center, - leading: ImageOutliner( - imageName: boss.image, - imagePath: bossImage(boss.image), - ), - title: Text( - boss.name, - style: constraintsValues[bossTitleStyle], - ), + return Consumer( + builder: (context, favoriteState, child) { + return InkWell( + onLongPress: () { + favoriteState.toggleFavorite(boss); + }, onTap: () { analyticsHelper.logEvent( name: widgetEngagement, @@ -63,8 +58,26 @@ class BossesGrid extends StatelessWidget { ), ); }, - ), - ), + child: Card( + child: Center( + child: ListTile( + titleAlignment: ListTileTitleAlignment.center, + leading: ImageOutliner( + imageName: boss.image, + imagePath: bossImage(boss.image), + ), + title: Text( + boss.name, + style: constraintsValues[bossTitleStyle], + ), + trailing: favoriteState.isFavorite(boss.type, boss.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ), + ), + ), + ); + }, ); }, ); diff --git a/lib/presentation/widgets/maps/map_card.dart b/lib/presentation/widgets/maps/map_card.dart index 5e23d64..49e578d 100644 --- a/lib/presentation/widgets/maps/map_card.dart +++ b/lib/presentation/widgets/maps/map_card.dart @@ -1,6 +1,8 @@ import 'package:auto_size_text/auto_size_text.dart'; -import 'package:btd6wiki/models/base/base_map.dart'; +import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; +import '/models/base/base_map.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; import '/utilities/strings.dart'; @@ -12,40 +14,40 @@ class MapCard extends StatelessWidget { @override Widget build(BuildContext context) { - return Card( - elevation: 5, - shadowColor: Colors.black87, - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - Expanded( - child: Image( - semanticLabel: singleMap.name, - image: AssetImage(mapImage(singleMap.image)), - fit: BoxFit.cover, - errorBuilder: (BuildContext context, Object exception, - StackTrace? stackTrace) { - return const Icon(Icons.error); - }, - ), - ), - Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - AutoSizeText( + return Consumer( + builder: (context, favoriteState, child) { + return Card( + elevation: 5, + shadowColor: Colors.black87, + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Expanded( + child: Image( + semanticLabel: singleMap.name, + image: AssetImage(mapImage(singleMap.image)), + fit: BoxFit.cover, + errorBuilder: (BuildContext context, Object exception, + StackTrace? stackTrace) { + return const Icon(Icons.error); + }, + ), + ), + ListTile( + title: AutoSizeText( capitalizeEveryWord(singleMap.name), maxLines: 1, style: bolderNormalStyle, ), - const SizedBox(height: 5), - Text(singleMap.difficulty, style: subtitleStyle), - ], - ), + subtitle: Text(singleMap.difficulty, style: subtitleStyle), + trailing: favoriteState.isFavorite(singleMap.type, singleMap.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ), + ], ), - ], - ), + ); + }, ); } } diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 9feda84..2917e43 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -4,19 +4,20 @@ import '/hive/favorite_model.dart'; import '/utilities/constants.dart'; class FavoriteState extends ChangeNotifier { - late Box> _favoriteBox; + late Box> _favoriteBox; FavoriteState() { - _favoriteBox = Hive.box>(kFavorite); + _favoriteBox = Hive.box>(kFavorite); } void toggleFavorite(var item) { FavoriteModel favItem = _createFavoriteItem(item); if (!_favoriteBox.containsKey(favItem.type)) { - _favoriteBox.put(favItem.type, [favItem]); + _favoriteBox.put(favItem.type, [favItem]); } else { - List typeList = _favoriteBox.get(favItem.type)!; + List typeList = + List.from(_favoriteBox.get(favItem.type)!); if (isFavorite(favItem.type, favItem.id)) { typeList.removeWhere((element) => element.id == favItem.id); } else { @@ -29,7 +30,8 @@ class FavoriteState extends ChangeNotifier { bool isFavorite(String type, String id) { if (!_favoriteBox.containsKey(type)) return false; - List typeList = _favoriteBox.get(type)!; + List typeList = + List.from(_favoriteBox.get(type)!); for (FavoriteModel item in typeList) { if (item.id == id) return true; } From 1a3f68c4189e5d6e19a0280ffb41f7258d6d4866 Mon Sep 17 00:00:00 2001 From: Shai Date: Thu, 8 Feb 2024 20:25:59 +0200 Subject: [PATCH 10/32] WIP orderable grid very basic functionality --- lib/main.dart | 33 ++++++-- .../screens/misc/favorite_screen.dart | 58 ++++++++++++++ .../widgets/misc/orderable_grid.dart | 80 +++++++++++++++++++ lib/utilities/favorite_state.dart | 10 +++ lib/utilities/layout_presets.dart | 4 +- lib/utilities/utils.dart | 2 +- pubspec.lock | 76 +++++++++++------- pubspec.yaml | 1 + 8 files changed, 223 insertions(+), 41 deletions(-) create mode 100644 lib/presentation/widgets/misc/orderable_grid.dart diff --git a/lib/main.dart b/lib/main.dart index a48b024..efae370 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,3 +1,5 @@ +import 'package:btd6wiki/presentation/screens/misc/favorite_screen.dart'; +import 'package:btd6wiki/presentation/widgets/misc/orderable_grid.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -129,7 +131,8 @@ class _MyHomePageState extends State { appBar: AppBar( title: Consumer( builder: (context, globalState, child) { - return Text(globalState.currentTitle); + return Text(MediaQuery.of(context).size.width.toString()); + // return Text(globalState.currentTitle); }, ), actions: [ @@ -200,13 +203,27 @@ class _MyHomePageState extends State { onPressed: () async { // await favBox.deleteFromDisk(); // favBox = await Hive.openBox('favorite'); - try { - print(Hive.box>(kFavorite).toMap()); - } catch (e) { - print(e); - await Hive.openBox(kFavorite); - } - + // try { + // print(Hive.box>(kFavorite).toMap()); + // } catch (e) { + // print(e); + // await Hive.openBox(kFavorite); + // } + // Navigator.push( + // context, + // MaterialPageRoute(builder: (context) => const FavoriteScreen()), + // ); + FavoriteState favS = + Provider.of(context, listen: false); + var list = favS.getListOfType('tower'); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => OrderableGrid( + favoriteItems: list, + gridKey: GlobalKey(), + )), + ); // print(favBox.get(kTowers)); }, icon: const Icon(Icons.star), diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index e69de29..5b01e51 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -0,0 +1,58 @@ +import 'package:btd6wiki/presentation/widgets/misc/orderable_grid.dart'; +import 'package:btd6wiki/utilities/favorite_state.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; +import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; +import 'package:provider/provider.dart'; + +class FavoriteScreen extends StatefulWidget { + const FavoriteScreen({super.key}); + + @override + State createState() => _FavoriteScreenState(); +} + +class _FavoriteScreenState extends State { + final _scrollController = ScrollController(); + final _gridViewKey = GlobalKey(); + final _fruits = ["apple", "banana", "strawberry"]; + + @override + Widget build(BuildContext context) { + final generatedChildren = List.generate( + _fruits.length, + (index) => Container( + key: Key(_fruits.elementAt(index)), + color: Colors.lightBlue, + child: Text( + _fruits.elementAt(index), + ), + ), + ); + + return Scaffold( + appBar: AppBar( + title: const Text('Favorites'), + ), + body: Consumer( + builder: (context, favoriteState, child) { + List categories = + List.from(favoriteState.favoriteBox.keys.toList()); + return ListView.builder( + shrinkWrap: true, + itemCount: categories.length, + itemBuilder: (BuildContext context, int index) { + return categories[index].isNotEmpty + ? OrderableGrid( + gridKey: GlobalKey(), + favoriteItems: + favoriteState.getListOfType(categories[index]), + ) + : Container(); + }, + ); + }, + ), + ); + } +} diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart new file mode 100644 index 0000000..164fa70 --- /dev/null +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -0,0 +1,80 @@ +import 'package:btd6wiki/hive/favorite_model.dart'; +import 'package:btd6wiki/utilities/images_url.dart'; +import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; +import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; +import 'package:provider/provider.dart'; +import 'package:flutter/material.dart'; +import '/utilities/favorite_state.dart'; + +class OrderableGrid extends StatefulWidget { + const OrderableGrid({ + super.key, + required this.gridKey, + required this.favoriteItems, + }); + final GlobalKey gridKey; + final List favoriteItems; + + @override + State createState() => _OrderableGridState(); +} + +class _OrderableGridState extends State { + final _scrollController = ScrollController(); + @override + Widget build(BuildContext context) { + final generatedChildren = List.generate( + widget.favoriteItems.length, + (index) { + FavoriteModel favItem = widget.favoriteItems.elementAt(index); + return InkWell( + key: Key(favItem.id), + child: Card( + color: Colors.lightBlue, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Image(image: AssetImage(towerImage(favItem.image))), + Text(favItem.name), + ], + ), + ), + ); + }, + ); + + return Scaffold( + appBar: AppBar(), + body: Consumer( + builder: (context, favoriteState, child) { + List categories = + List.from(favoriteState.favoriteBox.keys.toList()); + return ReorderableBuilder( + children: generatedChildren, + scrollController: _scrollController, + onReorder: (List orderUpdateEntities) { + for (final orderUpdateEntity in orderUpdateEntities) { + final fruit = + widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); + widget.favoriteItems.insert(orderUpdateEntity.newIndex, fruit); + } + }, + builder: (children) { + return GridView( + key: widget.gridKey, + controller: _scrollController, + shrinkWrap: true, + children: children, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, + mainAxisSpacing: 4, + crossAxisSpacing: 8, + ), + ); + }, + ); + }, + ), + ); + } +} diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 2917e43..afc8b44 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -10,6 +10,16 @@ class FavoriteState extends ChangeNotifier { _favoriteBox = Hive.box>(kFavorite); } + Box> get favoriteBox => _favoriteBox; + + List getListOfType(String type) { + if (_favoriteBox.containsKey(type)) { + return List.from(_favoriteBox.get(type)!); + } + + return []; + } + void toggleFavorite(var item) { FavoriteModel favItem = _createFavoriteItem(item); diff --git a/lib/utilities/layout_presets.dart b/lib/utilities/layout_presets.dart index ba39f4f..ac5fd59 100644 --- a/lib/utilities/layout_presets.dart +++ b/lib/utilities/layout_presets.dart @@ -17,8 +17,8 @@ Map presetUS = { skinCrossCount: 1, skinAspectRatio: 1.0, // bloons - bloonCrossCount: 2, - bloonAspectRatio: 2.85, + bloonCrossCount: 1, + bloonAspectRatio: 5.5, bloonTitleStyle: smallTitleStyle.copyWith(fontSize: 12.0), bloonImageWidth: 28.0, // bosses diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index e6e4d2f..3a3e0f8 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -162,7 +162,7 @@ Future openMail(String mailString) async { } Map getPreset(Size size) { - if (size.width < 310) { + if (size.width < 321) { return presetUS; } else if (size.width < 360) { return presetXS; diff --git a/pubspec.lock b/pubspec.lock index 0a24ba9..bf26608 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -13,18 +13,18 @@ packages: dependency: transitive description: name: _flutterfire_internals - sha256: f5628cd9c92ed11083f425fd1f8f1bc60ecdda458c81d73b143aeda036c35fe7 + sha256: "1a52f1afae8ab7ac4741425114713bdbba802f1ce1e0648e167ffcc6e05e96cf" url: "https://pub.dev" source: hosted - version: "1.3.16" + version: "1.3.21" adaptive_theme: dependency: "direct main" description: name: adaptive_theme - sha256: b0c4c35b22ef8226757881fe4dce38c40a06c551bca83236022ec7613e157c83 + sha256: f4ee609b464e5efc68131d9d15ba9aa1de4e3b5ede64be17781c6e19a52d637d url: "https://pub.dev" source: hosted - version: "3.5.0" + version: "3.6.0" analyzer: dependency: transitive description: @@ -125,10 +125,10 @@ packages: dependency: transitive description: name: build_runner_core - sha256: c9e32d21dd6626b5c163d48b037ce906bbe428bc23ab77bcd77bb21e593b6185 + sha256: "4ae8ffe5ac758da294ecf1802f2aff01558d8b1b00616aa7538ea9a8a5d50799" url: "https://pub.dev" source: hosted - version: "7.2.11" + version: "7.3.0" built_collection: dependency: transitive description: @@ -141,10 +141,10 @@ packages: dependency: transitive description: name: built_value - sha256: c9aabae0718ec394e5bc3c7272e6bb0dc0b32201a08fe185ec1d8401d3e39309 + sha256: a3ec2e0f967bc47f69f95009bb93db936288d61d5343b9436e378b28a2f830c6 url: "https://pub.dev" source: hosted - version: "8.8.1" + version: "8.9.0" carousel_slider: dependency: "direct main" description: @@ -233,6 +233,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.4" + equatable: + dependency: transitive + description: + name: equatable + sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 + url: "https://pub.dev" + source: hosted + version: "2.0.5" fake_async: dependency: transitive description: @@ -261,34 +269,34 @@ packages: dependency: "direct main" description: name: firebase_analytics - sha256: "0240076090d77045d757aecb090616066d23b343840d4c21074094d6fe40a184" + sha256: edb9f9eaecf0e6431e5c12b7fabdb68be3e85ce51f941ccbfa6cb71327e8b535 url: "https://pub.dev" source: hosted - version: "10.8.0" + version: "10.8.5" firebase_analytics_platform_interface: dependency: transitive description: name: firebase_analytics_platform_interface - sha256: "6d9baa077d16b47ef5f19d982c4fc475597991aa53b0c601216faa3e1cdab45f" + sha256: de4a54353cf58412c6da6b660a0dbad8efacb33b345c0286bc3a2edb869124d8 url: "https://pub.dev" source: hosted - version: "3.9.0" + version: "3.9.5" firebase_analytics_web: dependency: transitive description: name: firebase_analytics_web - sha256: "89a740249bce9d52a99db4e501be6087ca6749c73c47cff2b174802be10abd81" + sha256: "77e4c02ffd0204ccc7856221193265c807b7e056fa62855f973a7f77435b5d41" url: "https://pub.dev" source: hosted - version: "0.5.5+12" + version: "0.5.5+17" firebase_core: dependency: "direct main" description: name: firebase_core - sha256: "96607c0e829a581c2a483c658f04e8b159964c3bae2730f73297070bc85d40bb" + sha256: "7e049e32a9d347616edb39542cf92cd53fdb4a99fb6af0a0bff327c14cd76445" url: "https://pub.dev" source: hosted - version: "2.24.2" + version: "2.25.4" firebase_core_platform_interface: dependency: transitive description: @@ -301,10 +309,10 @@ packages: dependency: transitive description: name: firebase_core_web - sha256: d585bdf3c656c3f7821ba1bd44da5f13365d22fcecaf5eb75c4295246aaa83c0 + sha256: "57e61d6010e253b36d38191cefd6199d7849152cdcd234b61ca290cdb278a0ba" url: "https://pub.dev" source: hosted - version: "2.10.0" + version: "2.11.4" fixnum: dependency: transitive description: @@ -334,6 +342,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.1" + flutter_reorderable_grid_view: + dependency: "direct main" + description: + name: flutter_reorderable_grid_view + sha256: ac92a49a8411adfda40f75eff44d0958ee879b0f9d6776bb6154c74aa166aaf1 + url: "https://pub.dev" + source: hosted + version: "4.0.0" flutter_test: dependency: "direct dev" description: flutter @@ -348,10 +364,10 @@ packages: dependency: "direct main" description: name: font_awesome_flutter - sha256: "52671aea66da73b58d42ec6d0912b727a42248dd9a7c76d6c20f275783c48c08" + sha256: "275ff26905134bcb59417cf60ad979136f1f8257f2f449914b2c3e05bbb4cd6f" url: "https://pub.dev" source: hosted - version: "10.6.0" + version: "10.7.0" frontend_server_client: dependency: transitive description: @@ -428,10 +444,10 @@ packages: dependency: transitive description: name: image - sha256: "004a2e90ce080f8627b5a04aecb4cdfac87d2c3f3b520aa291260be5a32c033d" + sha256: "49a0d4b0c12402853d3f227fe7c315601b238d126aa4caa5dbb2dcf99421aa4a" url: "https://pub.dev" source: hosted - version: "4.1.4" + version: "4.1.6" io: dependency: transitive description: @@ -500,10 +516,10 @@ packages: dependency: transitive description: name: mime - sha256: e4ff8e8564c03f255408decd16e7899da1733852a9110a58fe6d1b817684a63e + sha256: "2e123074287cc9fd6c09de8336dae606d1ddb88d9ac47358826db698c176a1f2" url: "https://pub.dev" source: hosted - version: "1.0.4" + version: "1.0.5" model_viewer_plus: dependency: "direct main" description: @@ -921,18 +937,18 @@ packages: dependency: transitive description: name: webview_flutter - sha256: "71e1bfaef41016c8d5954291df5e9f8c6172f1f6ff3af01b5656456ddb11f94c" + sha256: d81b68e88cc353e546afb93fb38958e3717282c5ac6e5d3be4a4aef9fc3c1413 url: "https://pub.dev" source: hosted - version: "4.4.4" + version: "4.5.0" webview_flutter_android: dependency: transitive description: name: webview_flutter_android - sha256: "161af93c2abaf94ef2192bffb53a3658b2d721a3bf99b69aa1e47814ee18cc96" + sha256: "3e5f4e9d818086b0d01a66fb1ff9cc72ab0cc58c71980e3d3661c5685ea0efb0" url: "https://pub.dev" source: hosted - version: "3.13.2" + version: "3.15.0" webview_flutter_platform_interface: dependency: transitive description: @@ -945,10 +961,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: b99ca8d8bae9c6b43d568218691aa537fb0aeae1d7d34eadf112a6aa36d26506 + sha256: "9bf168bccdf179ce90450b5f37e36fe263f591c9338828d6bf09b6f8d0f57f86" url: "https://pub.dev" source: hosted - version: "3.11.0" + version: "3.12.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 0972b8d..13b2331 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -48,6 +48,7 @@ dependencies: provider: ^6.1.1 hive: ^2.2.3 hive_flutter: ^1.1.0 + flutter_reorderable_grid_view: ^4.0.0 dev_dependencies: flutter_launcher_icons: ^0.13.1 From efb48b6593957f1ff0c763fdc2791906d384bbfa Mon Sep 17 00:00:00 2001 From: Shai Date: Fri, 9 Feb 2024 16:40:17 +0200 Subject: [PATCH 11/32] WIP orderable grids show all categories --- assets | 2 +- lib/main.dart | 28 +++---- .../screens/misc/favorite_screen.dart | 38 ++++----- lib/presentation/screens/tower/towers.dart | 1 + .../widgets/misc/orderable_grid.dart | 77 ++++++++++--------- lib/utilities/constants.dart | 1 + lib/utilities/favorite_state.dart | 20 +++++ lib/utilities/utils.dart | 45 +++++++++++ 8 files changed, 136 insertions(+), 76 deletions(-) diff --git a/assets b/assets index 1111b93..52574f7 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 1111b93f2f53913be80a1dfe127392dc50dab714 +Subproject commit 52574f712bbf7cad61a438bb84b52b0453699714 diff --git a/lib/main.dart b/lib/main.dart index efae370..26b029a 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -38,7 +38,8 @@ Future main() async { // await Hive.deleteFromDisk(); Hive.registerAdapter(FavoriteModelAdapter()); // Removed redundant opening - await Hive.openBox>(kFavorite); + await Hive.openBox>(kFavorite, + keyComparator: desiredCategoryOrder); // print(Hive.box(kFavorite).toMap()); runApp(MyApp(analytics: analytics)); @@ -209,21 +210,22 @@ class _MyHomePageState extends State { // print(e); // await Hive.openBox(kFavorite); // } - // Navigator.push( - // context, - // MaterialPageRoute(builder: (context) => const FavoriteScreen()), - // ); - FavoriteState favS = - Provider.of(context, listen: false); - var list = favS.getListOfType('tower'); Navigator.push( context, - MaterialPageRoute( - builder: (context) => OrderableGrid( - favoriteItems: list, - gridKey: GlobalKey(), - )), + MaterialPageRoute(builder: (context) => const FavoriteScreen()), ); + // FavoriteState favS = + // Provider.of(context, listen: false); + // var list = favS.getListOfType(kTowers); + // Navigator.push( + // context, + // MaterialPageRoute( + // builder: (context) => OrderableGrid( + // favoriteItems: list, + // typeName: kTowers, + // gridKey: GlobalKey(), + // )), + // ); // print(favBox.get(kTowers)); }, icon: const Icon(Icons.star), diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index 5b01e51..d3fe88c 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -13,43 +13,31 @@ class FavoriteScreen extends StatefulWidget { } class _FavoriteScreenState extends State { - final _scrollController = ScrollController(); - final _gridViewKey = GlobalKey(); - final _fruits = ["apple", "banana", "strawberry"]; - @override Widget build(BuildContext context) { + FavoriteState favoriteState = + Provider.of(context, listen: false); + print(favoriteState.favoriteBox.keys.toList()); + List categories = + List.from(favoriteState.favoriteBox.keys.toList()); final generatedChildren = List.generate( - _fruits.length, - (index) => Container( - key: Key(_fruits.elementAt(index)), - color: Colors.lightBlue, - child: Text( - _fruits.elementAt(index), - ), + categories.length, + (index) => OrderableGrid( + gridKey: GlobalKey(), + favoriteItems: favoriteState.getListOfType(categories[index]), + typeName: categories[index], ), ); - + print(categories); return Scaffold( appBar: AppBar( title: const Text('Favorites'), ), body: Consumer( builder: (context, favoriteState, child) { - List categories = - List.from(favoriteState.favoriteBox.keys.toList()); - return ListView.builder( + return ListView( shrinkWrap: true, - itemCount: categories.length, - itemBuilder: (BuildContext context, int index) { - return categories[index].isNotEmpty - ? OrderableGrid( - gridKey: GlobalKey(), - favoriteItems: - favoriteState.getListOfType(categories[index]), - ) - : Container(); - }, + children: generatedChildren, ); }, ), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 30fbdc8..23e9a7a 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -88,6 +88,7 @@ class _TowersState extends State { towerId: tower.id, analyticsHelper: widget.analyticsHelper, ), + ), ); }, diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index 164fa70..fcd72c0 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -1,19 +1,22 @@ -import 'package:btd6wiki/hive/favorite_model.dart'; -import 'package:btd6wiki/utilities/images_url.dart'; import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; +import '/hive/favorite_model.dart'; import '/utilities/favorite_state.dart'; +import '/utilities/utils.dart'; class OrderableGrid extends StatefulWidget { const OrderableGrid({ super.key, required this.gridKey, + required this.typeName, required this.favoriteItems, }); + final GlobalKey gridKey; - final List favoriteItems; + final String typeName; + final List favoriteItems; @override State createState() => _OrderableGridState(); @@ -30,11 +33,15 @@ class _OrderableGridState extends State { return InkWell( key: Key(favItem.id), child: Card( - color: Colors.lightBlue, child: Column( mainAxisSize: MainAxisSize.min, children: [ - Image(image: AssetImage(towerImage(favItem.image))), + Expanded( + child: Image( + image: AssetImage( + assetImagePath(widget.typeName, favItem.image)), + ), + ), Text(favItem.name), ], ), @@ -43,38 +50,34 @@ class _OrderableGridState extends State { }, ); - return Scaffold( - appBar: AppBar(), - body: Consumer( - builder: (context, favoriteState, child) { - List categories = - List.from(favoriteState.favoriteBox.keys.toList()); - return ReorderableBuilder( - children: generatedChildren, - scrollController: _scrollController, - onReorder: (List orderUpdateEntities) { - for (final orderUpdateEntity in orderUpdateEntities) { - final fruit = - widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); - widget.favoriteItems.insert(orderUpdateEntity.newIndex, fruit); - } - }, - builder: (children) { - return GridView( - key: widget.gridKey, - controller: _scrollController, - shrinkWrap: true, - children: children, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 4, - mainAxisSpacing: 4, - crossAxisSpacing: 8, - ), - ); - }, - ); - }, - ), + return Column( + children: [ + Text(widget.typeName), + ReorderableBuilder( + children: generatedChildren, + scrollController: _scrollController, + onReorder: (List orderUpdateEntities) { + for (final orderUpdateEntity in orderUpdateEntities) { + final fruit = + widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); + widget.favoriteItems.insert(orderUpdateEntity.newIndex, fruit); + } + }, + builder: (children) { + return GridView( + key: widget.gridKey, + controller: _scrollController, + shrinkWrap: true, + children: children, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, + mainAxisSpacing: 4, + crossAxisSpacing: 8, + ), + ); + }, + ), + ], ); } } diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 60c7a71..a59576e 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -5,6 +5,7 @@ const String kHeroes = 'heroes'; const String kBloons = 'bloons'; const String kBlimps = 'blimps'; const String kBosses = 'bosses'; +const String kMinions = 'minions'; const String kMaps = 'maps'; const int kTowersIndex = 0; diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index afc8b44..0410e06 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -8,6 +8,26 @@ class FavoriteState extends ChangeNotifier { FavoriteState() { _favoriteBox = Hive.box>(kFavorite); + final tempBuffer = >{}; + +// Example desired order: towers, heroes, bloons, bosses, maps, blimps + for (final categoryKey in [ + 'towers', + 'heroes', + 'bloons', + 'bosses', + 'maps', + 'blimps' + ]) { + final values = _favoriteBox.get(categoryKey)??[]; + tempBuffer[categoryKey] = values; + } + + _favoriteBox.clear(); + + for (final entry in tempBuffer.entries) { + _favoriteBox.put(entry.key, entry.value); + } } Box> get favoriteBox => _favoriteBox; diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 3a3e0f8..2e20fb9 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -8,8 +8,35 @@ import '/models/base/base_hero.dart'; import '/models/base/base_map.dart'; import '/models/base_model.dart'; import 'constants.dart'; +import 'images_url.dart'; import 'layout_presets.dart'; + +int desiredCategoryOrder(dynamic key1, dynamic key2) { + // Define the desired order as a list of category keys + final desiredOrder = ['towers', 'heroes', 'bloons', 'bosses', 'maps', 'blimps']; + + // Get the category names from the keys + final category1 = key1.split(':')[0]; + final category2 = key2.split(':')[0]; + + // Find the indices of the categories in the desired order + final index1 = desiredOrder.indexOf(category1); + final index2 = desiredOrder.indexOf(category2); + + // Compare the indices to determine the order + if (index1 == -1 || index2 == -1) { + // Handle unexpected categories (not in desiredOrder) + return 0; // Or throw an error if preferred + } else if (index1 < index2) { + return -1; // Category1 comes before Category2 + } else if (index1 > index2) { + return 1; // Category1 comes after Category2 + } else { + return 0; // Categories have the same desired order (shouldn't happen) + } +} + String formatBigNumber(int number) { if (number < 1000) { return number.toString(); @@ -49,6 +76,24 @@ String extraStatsToString(Stats stats) { return "Status Effects: ${stats.statuseffects}\nIncome Boosts: ${stats.incomeboosts}\nTower Boosts: ${stats.towerboosts}"; } +String assetImagePath(String type, String imageName) { + if (type == kTowers) { + return towerImage(imageName); + } else if (type == kHeroes) { + return heroImage(imageName); + } else if (type == kBloons || type == kBlimps) { + return bloonImage(imageName); + } else if (type == kBosses) { + return bossImage(imageName); + } else if (type == kMinions) { + return minionImage(imageName); + } else if (type == kMaps) { + return mapImage(imageName); + } else { + throw Exception('Unsupported image type - $type'); + } +} + List filterAndSearchBloons( List bloons, String query, String option) { query = query.toLowerCase(); From ef072d882d05748a8ba0255d5d9bd3b291bb4183 Mon Sep 17 00:00:00 2001 From: Shai Date: Fri, 9 Feb 2024 16:56:11 +0200 Subject: [PATCH 12/32] box saves updated order --- .../widgets/misc/orderable_grid.dart | 10 ++++++-- lib/utilities/favorite_state.dart | 23 ++----------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index fcd72c0..869963f 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -57,11 +57,17 @@ class _OrderableGridState extends State { children: generatedChildren, scrollController: _scrollController, onReorder: (List orderUpdateEntities) { + print(orderUpdateEntities); for (final orderUpdateEntity in orderUpdateEntities) { - final fruit = + final favItem = widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); - widget.favoriteItems.insert(orderUpdateEntity.newIndex, fruit); + widget.favoriteItems.insert(orderUpdateEntity.newIndex, favItem); } + for (var name in widget.favoriteItems) { + print(name.name); + } + Provider.of(context, listen: false) + .updateIndexes(widget.typeName, widget.favoriteItems); }, builder: (children) { return GridView( diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 0410e06..6a6a71a 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -8,26 +8,6 @@ class FavoriteState extends ChangeNotifier { FavoriteState() { _favoriteBox = Hive.box>(kFavorite); - final tempBuffer = >{}; - -// Example desired order: towers, heroes, bloons, bosses, maps, blimps - for (final categoryKey in [ - 'towers', - 'heroes', - 'bloons', - 'bosses', - 'maps', - 'blimps' - ]) { - final values = _favoriteBox.get(categoryKey)??[]; - tempBuffer[categoryKey] = values; - } - - _favoriteBox.clear(); - - for (final entry in tempBuffer.entries) { - _favoriteBox.put(entry.key, entry.value); - } } Box> get favoriteBox => _favoriteBox; @@ -88,8 +68,9 @@ class FavoriteState extends ChangeNotifier { ); } - void _updateLastIndexes() { + void updateIndexes(String type, List items) { // TODO implement updating indexes of all the items of the type // this comes after implementing moveable grid to show the items and change their order + _favoriteBox.put(type, items); } } From a1ddd561a2486d577a36e2ee3d17ee86762f8862 Mon Sep 17 00:00:00 2001 From: Shai Date: Fri, 9 Feb 2024 16:57:56 +0200 Subject: [PATCH 13/32] some cleanup --- lib/main.dart | 1 - lib/presentation/screens/misc/favorite_screen.dart | 4 ---- lib/presentation/widgets/misc/orderable_grid.dart | 8 ++------ lib/utilities/favorite_state.dart | 2 -- lib/utilities/utils.dart | 10 ++++++++-- 5 files changed, 10 insertions(+), 15 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 26b029a..04c14a6 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,5 +1,4 @@ import 'package:btd6wiki/presentation/screens/misc/favorite_screen.dart'; -import 'package:btd6wiki/presentation/widgets/misc/orderable_grid.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_core/firebase_core.dart'; diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index d3fe88c..561e1fa 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -1,8 +1,6 @@ import 'package:btd6wiki/presentation/widgets/misc/orderable_grid.dart'; import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; -import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; import 'package:provider/provider.dart'; class FavoriteScreen extends StatefulWidget { @@ -17,7 +15,6 @@ class _FavoriteScreenState extends State { Widget build(BuildContext context) { FavoriteState favoriteState = Provider.of(context, listen: false); - print(favoriteState.favoriteBox.keys.toList()); List categories = List.from(favoriteState.favoriteBox.keys.toList()); final generatedChildren = List.generate( @@ -28,7 +25,6 @@ class _FavoriteScreenState extends State { typeName: categories[index], ), ); - print(categories); return Scaffold( appBar: AppBar( title: const Text('Favorites'), diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index 869963f..c9b05c3 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -54,18 +54,13 @@ class _OrderableGridState extends State { children: [ Text(widget.typeName), ReorderableBuilder( - children: generatedChildren, scrollController: _scrollController, onReorder: (List orderUpdateEntities) { - print(orderUpdateEntities); for (final orderUpdateEntity in orderUpdateEntities) { final favItem = widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); widget.favoriteItems.insert(orderUpdateEntity.newIndex, favItem); } - for (var name in widget.favoriteItems) { - print(name.name); - } Provider.of(context, listen: false) .updateIndexes(widget.typeName, widget.favoriteItems); }, @@ -74,14 +69,15 @@ class _OrderableGridState extends State { key: widget.gridKey, controller: _scrollController, shrinkWrap: true, - children: children, gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 3, mainAxisSpacing: 4, crossAxisSpacing: 8, ), + children: children, ); }, + children: generatedChildren, ), ], ); diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 6a6a71a..5d7ddff 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -69,8 +69,6 @@ class FavoriteState extends ChangeNotifier { } void updateIndexes(String type, List items) { - // TODO implement updating indexes of all the items of the type - // this comes after implementing moveable grid to show the items and change their order _favoriteBox.put(type, items); } } diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 2e20fb9..87098fd 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -11,10 +11,16 @@ import 'constants.dart'; import 'images_url.dart'; import 'layout_presets.dart'; - int desiredCategoryOrder(dynamic key1, dynamic key2) { // Define the desired order as a list of category keys - final desiredOrder = ['towers', 'heroes', 'bloons', 'bosses', 'maps', 'blimps']; + final desiredOrder = [ + 'towers', + 'heroes', + 'bloons', + 'bosses', + 'maps', + 'blimps' + ]; // Get the category names from the keys final category1 = key1.split(':')[0]; From 045da0a6ee4f5c8e8dfb4ef50f4d24e76f873265 Mon Sep 17 00:00:00 2001 From: Shai Date: Fri, 9 Feb 2024 17:39:54 +0200 Subject: [PATCH 14/32] navigation to favorites work now --- lib/analytics/analytics_constants.dart | 2 + lib/main.dart | 35 ++---- .../screens/misc/favorite_screen.dart | 6 +- .../widgets/misc/orderable_grid.dart | 111 +++++++++++------- lib/utilities/utils.dart | 54 ++++++++- 5 files changed, 138 insertions(+), 70 deletions(-) diff --git a/lib/analytics/analytics_constants.dart b/lib/analytics/analytics_constants.dart index 1082787..098ced5 100644 --- a/lib/analytics/analytics_constants.dart +++ b/lib/analytics/analytics_constants.dart @@ -5,6 +5,7 @@ const String kHeroPagesClass = 'hero_pages'; const String kBloonPagesClass = 'bloon_pages'; const String kBossPagesClass = 'boss_pages'; const String kMapPagesClass = 'map_pages'; +const String kFavoritesClass = 'favorites_page'; // ------- Const for event names ------- const String widgetEngagement = 'widget_engagement'; @@ -33,5 +34,6 @@ const String kHeroSkinsPage = 'hero_skins_page'; // ---- General ---- const String expansionTile = 'expansion_tile'; const String listTile = 'list_tile'; +const String card = 'card'; const String buttonOpen = 'opened'; const String buttonClose = 'closed'; diff --git a/lib/main.dart b/lib/main.dart index 04c14a6..b885d7e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -131,8 +131,8 @@ class _MyHomePageState extends State { appBar: AppBar( title: Consumer( builder: (context, globalState, child) { - return Text(MediaQuery.of(context).size.width.toString()); - // return Text(globalState.currentTitle); + // return Text(MediaQuery.of(context).size.width.toString()); + return Text(globalState.currentTitle); }, ), actions: [ @@ -201,41 +201,20 @@ class _MyHomePageState extends State { ), IconButton( onPressed: () async { - // await favBox.deleteFromDisk(); - // favBox = await Hive.openBox('favorite'); - // try { - // print(Hive.box>(kFavorite).toMap()); - // } catch (e) { - // print(e); - // await Hive.openBox(kFavorite); - // } Navigator.push( context, - MaterialPageRoute(builder: (context) => const FavoriteScreen()), + MaterialPageRoute( + builder: (context) => FavoriteScreen( + analyticsHelper: analyticsHelper, + ), + ), ); - // FavoriteState favS = - // Provider.of(context, listen: false); - // var list = favS.getListOfType(kTowers); - // Navigator.push( - // context, - // MaterialPageRoute( - // builder: (context) => OrderableGrid( - // favoriteItems: list, - // typeName: kTowers, - // gridKey: GlobalKey(), - // )), - // ); - // print(favBox.get(kTowers)); }, icon: const Icon(Icons.star), ), IconButton( onPressed: () async { await Hive.deleteFromDisk(); - // favBox = await Hive.openBox('favorite'); - // print(Hive.box(kFavorite).toMap()); - - // print(favBox.get(kTowers)); }, icon: const Icon(Icons.remove), ), diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index 561e1fa..53ebf76 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -1,10 +1,13 @@ +import 'package:btd6wiki/analytics/analytics.dart'; import 'package:btd6wiki/presentation/widgets/misc/orderable_grid.dart'; import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class FavoriteScreen extends StatefulWidget { - const FavoriteScreen({super.key}); + const FavoriteScreen({super.key, required this.analyticsHelper}); + + final AnalyticsHelper analyticsHelper; @override State createState() => _FavoriteScreenState(); @@ -23,6 +26,7 @@ class _FavoriteScreenState extends State { gridKey: GlobalKey(), favoriteItems: favoriteState.getListOfType(categories[index]), typeName: categories[index], + analyticsHelper: widget.analyticsHelper, ), ); return Scaffold( diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index c9b05c3..cdcc099 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -1,3 +1,5 @@ +import 'package:btd6wiki/analytics/analytics.dart'; +import 'package:btd6wiki/analytics/analytics_constants.dart'; import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; import 'package:provider/provider.dart'; @@ -12,11 +14,13 @@ class OrderableGrid extends StatefulWidget { required this.gridKey, required this.typeName, required this.favoriteItems, + required this.analyticsHelper, }); final GlobalKey gridKey; final String typeName; final List favoriteItems; + final AnalyticsHelper analyticsHelper; @override State createState() => _OrderableGridState(); @@ -32,54 +36,81 @@ class _OrderableGridState extends State { FavoriteModel favItem = widget.favoriteItems.elementAt(index); return InkWell( key: Key(favItem.id), + onTap: () { + navigateToPage( + context, + favItem, + widget.analyticsHelper, + kFavoritesClass, + card, + ); + }, child: Card( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Expanded( - child: Image( - image: AssetImage( - assetImagePath(widget.typeName, favItem.image)), + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 3, + child: Image( + image: AssetImage( + assetImagePath(widget.typeName, favItem.image)), + ), ), - ), - Text(favItem.name), - ], + Flexible( + flex: 1, + child: Center( + child: Text( + favItem.name, + textAlign: TextAlign.center, + )), + ), + ], + ), ), ), ); }, ); - return Column( - children: [ - Text(widget.typeName), - ReorderableBuilder( - scrollController: _scrollController, - onReorder: (List orderUpdateEntities) { - for (final orderUpdateEntity in orderUpdateEntities) { - final favItem = - widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); - widget.favoriteItems.insert(orderUpdateEntity.newIndex, favItem); - } - Provider.of(context, listen: false) - .updateIndexes(widget.typeName, widget.favoriteItems); - }, - builder: (children) { - return GridView( - key: widget.gridKey, - controller: _scrollController, - shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 3, - mainAxisSpacing: 4, - crossAxisSpacing: 8, - ), - children: children, - ); - }, - children: generatedChildren, - ), - ], + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text(widget.typeName), + ReorderableBuilder( + scrollController: _scrollController, + onReorder: (List orderUpdateEntities) { + for (final orderUpdateEntity in orderUpdateEntities) { + final favItem = + widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); + widget.favoriteItems + .insert(orderUpdateEntity.newIndex, favItem); + } + Provider.of(context, listen: false) + .updateIndexes(widget.typeName, widget.favoriteItems); + }, + builder: (children) { + return GridView( + key: widget.gridKey, + controller: _scrollController, + shrinkWrap: true, + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + mainAxisSpacing: 15, + crossAxisSpacing: 10, + crossAxisCount: 3, + childAspectRatio: 0.70, + ), + children: children, + ); + }, + children: generatedChildren, + ), + ], + ), ); } } diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 87098fd..06e0204 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,3 +1,10 @@ +import 'package:btd6wiki/analytics/analytics.dart'; +import 'package:btd6wiki/analytics/analytics_constants.dart'; +import 'package:btd6wiki/presentation/screens/bloon/boss_bloon.dart'; +import 'package:btd6wiki/presentation/screens/bloon/single_bloon.dart'; +import 'package:btd6wiki/presentation/screens/hero/single_hero.dart'; +import 'package:btd6wiki/presentation/screens/maps/single_map.dart'; +import 'package:btd6wiki/presentation/screens/tower/single_tower.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; import '/models/bloons/common/relative_class.dart'; @@ -17,9 +24,9 @@ int desiredCategoryOrder(dynamic key1, dynamic key2) { 'towers', 'heroes', 'bloons', + 'blimps', 'bosses', 'maps', - 'blimps' ]; // Get the category names from the keys @@ -43,6 +50,51 @@ int desiredCategoryOrder(dynamic key1, dynamic key2) { } } +void navigateToPage(BuildContext context, var item, + AnalyticsHelper analyticsHelper, String originScreen, String originWidget) { + analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': originScreen, + 'widget': originWidget, + 'value': item.id, + }, + ); + + Map destinations = { + kTowers: SingleTower( + towerId: item.id, + analyticsHelper: analyticsHelper, + ), + kHeroes: SingleHero( + heroId: item.id, + analyticsHelper: analyticsHelper, + ), + kBloons: SingleBloon( + bloonId: item.id, + analyticsHelper: analyticsHelper, + ), + kBlimps: SingleBloon( + bloonId: item.id, + analyticsHelper: analyticsHelper, + ), + kBosses: BossBloon( + bossId: item.id, + analyticsHelper: analyticsHelper, + ), + kMaps: SingleMap( + mapId: item.id, + analyticsHelper: analyticsHelper, + ), + }; + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => destinations[item.type]!, + ), + ); +} + String formatBigNumber(int number) { if (number < 1000) { return number.toString(); From 171e5ea2bda48d479738ecab9219a553e299da19 Mon Sep 17 00:00:00 2001 From: Shai Date: Fri, 9 Feb 2024 17:44:12 +0200 Subject: [PATCH 15/32] fixed imports naming --- lib/main.dart | 13 +++++-------- .../screens/misc/favorite_screen.dart | 8 ++++---- .../widgets/bloons/bosses_grid.dart | 18 +++++++++--------- .../widgets/misc/orderable_grid.dart | 4 ++-- lib/utilities/utils.dart | 14 +++++++------- 5 files changed, 27 insertions(+), 30 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index b885d7e..815e7ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,4 +1,3 @@ -import 'package:btd6wiki/presentation/screens/misc/favorite_screen.dart'; import 'package:firebase_analytics/firebase_analytics.dart'; import 'package:adaptive_theme/adaptive_theme.dart'; import 'package:firebase_core/firebase_core.dart'; @@ -11,6 +10,7 @@ import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; import '/models/base/base_map.dart'; import '/models/base_model.dart'; +import '/presentation/screens/misc/favorite_screen.dart'; import '/presentation/widgets/misc/drawer_content.dart'; import '/presentation/screens/tower/towers.dart'; import '/presentation/screens/bloon/bloons.dart'; @@ -34,13 +34,11 @@ Future main() async { ); final analytics = FirebaseAnalytics.instance; await Hive.initFlutter(); - // await Hive.deleteFromDisk(); Hive.registerAdapter(FavoriteModelAdapter()); - // Removed redundant opening - await Hive.openBox>(kFavorite, - keyComparator: desiredCategoryOrder); - // print(Hive.box(kFavorite).toMap()); - + await Hive.openBox>( + kFavorite, + keyComparator: desiredCategoryOrder, + ); runApp(MyApp(analytics: analytics)); } @@ -131,7 +129,6 @@ class _MyHomePageState extends State { appBar: AppBar( title: Consumer( builder: (context, globalState, child) { - // return Text(MediaQuery.of(context).size.width.toString()); return Text(globalState.currentTitle); }, ), diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index 53ebf76..9cff94c 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -1,8 +1,8 @@ -import 'package:btd6wiki/analytics/analytics.dart'; -import 'package:btd6wiki/presentation/widgets/misc/orderable_grid.dart'; -import 'package:btd6wiki/utilities/favorite_state.dart'; -import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter/material.dart'; +import '/analytics/analytics.dart'; +import '/presentation/widgets/misc/orderable_grid.dart'; +import '/utilities/favorite_state.dart'; class FavoriteScreen extends StatefulWidget { const FavoriteScreen({super.key, required this.analyticsHelper}); diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index 9759096..9c6fa21 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -1,13 +1,13 @@ -import 'package:btd6wiki/analytics/analytics.dart'; -import 'package:btd6wiki/analytics/analytics_constants.dart'; -import 'package:btd6wiki/models/base_model.dart'; -import 'package:btd6wiki/presentation/screens/bloon/boss_bloon.dart'; -import 'package:btd6wiki/presentation/widgets/misc/image_outline.dart'; -import 'package:btd6wiki/utilities/constants.dart'; -import 'package:btd6wiki/utilities/favorite_state.dart'; -import 'package:btd6wiki/utilities/images_url.dart'; -import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:flutter/material.dart'; +import '/analytics/analytics_constants.dart'; +import '/analytics/analytics.dart'; +import '/models/base_model.dart'; +import '/presentation/widgets/misc/image_outline.dart'; +import '/presentation/screens/bloon/boss_bloon.dart'; +import '/utilities/favorite_state.dart'; +import '/utilities/images_url.dart'; +import '/utilities/constants.dart'; class BossesGrid extends StatelessWidget { const BossesGrid({ diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index cdcc099..a75005f 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -1,10 +1,10 @@ -import 'package:btd6wiki/analytics/analytics.dart'; -import 'package:btd6wiki/analytics/analytics_constants.dart'; import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/hive/favorite_model.dart'; +import '/analytics/analytics_constants.dart'; +import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; import '/utilities/utils.dart'; diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 06e0204..0d18b76 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,12 +1,7 @@ -import 'package:btd6wiki/analytics/analytics.dart'; -import 'package:btd6wiki/analytics/analytics_constants.dart'; -import 'package:btd6wiki/presentation/screens/bloon/boss_bloon.dart'; -import 'package:btd6wiki/presentation/screens/bloon/single_bloon.dart'; -import 'package:btd6wiki/presentation/screens/hero/single_hero.dart'; -import 'package:btd6wiki/presentation/screens/maps/single_map.dart'; -import 'package:btd6wiki/presentation/screens/tower/single_tower.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; +import '/analytics/analytics_constants.dart'; +import '/analytics/analytics.dart'; import '/models/bloons/common/relative_class.dart'; import '/models/towers/common/stats_class.dart'; import '/models/towers/common/cost_class.dart'; @@ -14,6 +9,11 @@ import '/models/base/base_tower.dart'; import '/models/base/base_hero.dart'; import '/models/base/base_map.dart'; import '/models/base_model.dart'; +import '/presentation/screens/tower/single_tower.dart'; +import '/presentation/screens/bloon/single_bloon.dart'; +import '/presentation/screens/bloon/boss_bloon.dart'; +import '/presentation/screens/hero/single_hero.dart'; +import '/presentation/screens/maps/single_map.dart'; import 'constants.dart'; import 'images_url.dart'; import 'layout_presets.dart'; From 55974d81a3f70854dc11f74c998c49d5b665ba8e Mon Sep 17 00:00:00 2001 From: Shai Date: Fri, 9 Feb 2024 17:45:02 +0200 Subject: [PATCH 16/32] same --- lib/utilities/utils.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 0d18b76..9ccd435 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -14,9 +14,9 @@ import '/presentation/screens/bloon/single_bloon.dart'; import '/presentation/screens/bloon/boss_bloon.dart'; import '/presentation/screens/hero/single_hero.dart'; import '/presentation/screens/maps/single_map.dart'; -import 'constants.dart'; -import 'images_url.dart'; import 'layout_presets.dart'; +import 'images_url.dart'; +import 'constants.dart'; int desiredCategoryOrder(dynamic key1, dynamic key2) { // Define the desired order as a list of category keys From dbbcb43b185abb7fb0c57a7687fad2dc4c9f3e41 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 12:25:36 +0200 Subject: [PATCH 17/32] added favorite button to single page --- .../screens/bloon/boss_bloon.dart | 31 ++++++++++++++++-- .../screens/bloon/single_bloon.dart | 31 ++++++++++++++++-- .../screens/hero/single_hero.dart | 32 +++++++++++++++++-- lib/presentation/screens/maps/single_map.dart | 31 ++++++++++++++++-- .../screens/tower/single_tower.dart | 31 ++++++++++++++++-- lib/utilities/favorite_state.dart | 7 +++- 6 files changed, 147 insertions(+), 16 deletions(-) diff --git a/lib/presentation/screens/bloon/boss_bloon.dart b/lib/presentation/screens/bloon/boss_bloon.dart index e720352..1fde31b 100644 --- a/lib/presentation/screens/bloon/boss_bloon.dart +++ b/lib/presentation/screens/bloon/boss_bloon.dart @@ -1,4 +1,6 @@ import 'dart:convert'; +import 'package:btd6wiki/utilities/favorite_state.dart'; +import 'package:provider/provider.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; @@ -58,9 +60,32 @@ class _BossBloonState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text(!loading ? boss.name : ''), - ), + appBar: !loading + ? AppBar( + title: Text(boss.name), + actions: [ + Consumer( + builder: (context, favoriteState, child) { + return IconButton( + onPressed: () { + String msg = favoriteState.toggleFavorite(boss); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: const Duration(milliseconds: 400), + ), + ); + }, + icon: favoriteState.isFavorite(boss.type, boss.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, + ), + ], + ) + : AppBar(), body: !loading ? SingleChildScrollView( child: Padding( diff --git a/lib/presentation/screens/bloon/single_bloon.dart b/lib/presentation/screens/bloon/single_bloon.dart index 2ed1de1..75d4376 100644 --- a/lib/presentation/screens/bloon/single_bloon.dart +++ b/lib/presentation/screens/bloon/single_bloon.dart @@ -1,6 +1,8 @@ import 'dart:convert'; +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; import '/models/bloons/bloon/bloon.dart'; import '../../widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; @@ -49,9 +51,32 @@ class _SingleBloonState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text(!loading ? bloon.fullName : ''), - ), + appBar: !loading + ? AppBar( + title: Text(bloon.fullName), + actions: [ + Consumer( + builder: (context, favoriteState, child) { + return IconButton( + onPressed: () { + String msg = favoriteState.toggleFavorite(bloon); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: const Duration(milliseconds: 400), + ), + ); + }, + icon: favoriteState.isFavorite(bloon.type, bloon.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, + ), + ], + ) + : AppBar(), body: !loading ? SingleChildScrollView( child: Padding( diff --git a/lib/presentation/screens/hero/single_hero.dart b/lib/presentation/screens/hero/single_hero.dart index 645022a..2e57269 100644 --- a/lib/presentation/screens/hero/single_hero.dart +++ b/lib/presentation/screens/hero/single_hero.dart @@ -1,7 +1,9 @@ import 'dart:convert'; +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import '/models/towers/common/upgrade_info_class.dart'; import '/models/towers/hero/hero.dart'; @@ -98,9 +100,33 @@ class _SingleHeroState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text(!loading ? singleHero.name : ''), - ), + appBar: !loading + ? AppBar( + title: Text(singleHero.name), + actions: [ + Consumer( + builder: (context, favoriteState, child) { + return IconButton( + onPressed: () { + String msg = favoriteState.toggleFavorite(singleHero); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: const Duration(milliseconds: 400), + ), + ); + }, + icon: favoriteState.isFavorite( + singleHero.type, singleHero.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, + ), + ], + ) + : AppBar(), body: !loading ? SingleChildScrollView( child: Padding( diff --git a/lib/presentation/screens/maps/single_map.dart b/lib/presentation/screens/maps/single_map.dart index 9dbcab8..11916b6 100644 --- a/lib/presentation/screens/maps/single_map.dart +++ b/lib/presentation/screens/maps/single_map.dart @@ -1,6 +1,8 @@ import 'dart:convert'; +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; import '/models/maps/map.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; @@ -48,9 +50,32 @@ class _SingleMapState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text(!loading ? map.name : ''), - ), + appBar: !loading + ? AppBar( + title: Text(map.name), + actions: [ + Consumer( + builder: (context, favoriteState, child) { + return IconButton( + onPressed: () { + String msg = favoriteState.toggleFavorite(map); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: const Duration(milliseconds: 400), + ), + ); + }, + icon: favoriteState.isFavorite(map.type, map.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, + ), + ], + ) + : AppBar(), body: !loading ? SingleChildScrollView( child: Padding( diff --git a/lib/presentation/screens/tower/single_tower.dart b/lib/presentation/screens/tower/single_tower.dart index 690354c..d634766 100644 --- a/lib/presentation/screens/tower/single_tower.dart +++ b/lib/presentation/screens/tower/single_tower.dart @@ -1,6 +1,8 @@ import 'dart:convert'; +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:provider/provider.dart'; import '/models/towers/tower/tower.dart'; import '../../widgets/towers/path.dart'; import '/analytics/analytics_constants.dart'; @@ -67,9 +69,32 @@ class _SingleTowerState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar( - title: Text(!loading ? tower.name : ""), - ), + appBar: !loading + ? AppBar( + title: Text(tower.name), + actions: [ + Consumer( + builder: (context, favoriteState, child) { + return IconButton( + onPressed: () { + String msg = favoriteState.toggleFavorite(tower); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: const Duration(milliseconds: 400), + ), + ); + }, + icon: favoriteState.isFavorite(tower.type, tower.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ); + }, + ), + ], + ) + : AppBar(), body: !loading ? SingleChildScrollView( child: Padding( diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 5d7ddff..0a722f7 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -20,22 +20,27 @@ class FavoriteState extends ChangeNotifier { return []; } - void toggleFavorite(var item) { + String toggleFavorite(var item) { + bool addedToFavorites = false; FavoriteModel favItem = _createFavoriteItem(item); if (!_favoriteBox.containsKey(favItem.type)) { _favoriteBox.put(favItem.type, [favItem]); + addedToFavorites = true; } else { List typeList = List.from(_favoriteBox.get(favItem.type)!); if (isFavorite(favItem.type, favItem.id)) { typeList.removeWhere((element) => element.id == favItem.id); + addedToFavorites = false; } else { typeList.add(favItem); + addedToFavorites = true; } _favoriteBox.put(favItem.type, typeList); } notifyListeners(); + return addedToFavorites ? 'Added to favorites!' : 'Remove from favorites.'; } bool isFavorite(String type, String id) { From 7b1bc13a1e90946f7e2d2c74323e17af0e97029d Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 14:48:25 +0200 Subject: [PATCH 18/32] added snack to all pages except favorite screen --- lib/presentation/screens/bloon/boss_bloon.dart | 13 +++---------- lib/presentation/screens/bloon/single_bloon.dart | 12 ++---------- lib/presentation/screens/hero/heroes.dart | 5 ++--- lib/presentation/screens/hero/single_hero.dart | 12 ++---------- lib/presentation/screens/maps/maps.dart | 5 ++--- lib/presentation/screens/maps/single_map.dart | 15 ++++----------- lib/presentation/screens/tower/single_tower.dart | 12 ++---------- lib/presentation/screens/tower/towers.dart | 6 ++---- lib/presentation/widgets/bloons/bloons_grid.dart | 6 +++--- lib/presentation/widgets/bloons/bosses_grid.dart | 6 +++--- lib/utilities/constants.dart | 2 ++ lib/utilities/utils.dart | 13 +++++++++++++ 12 files changed, 40 insertions(+), 67 deletions(-) diff --git a/lib/presentation/screens/bloon/boss_bloon.dart b/lib/presentation/screens/bloon/boss_bloon.dart index 1fde31b..56d607f 100644 --- a/lib/presentation/screens/bloon/boss_bloon.dart +++ b/lib/presentation/screens/bloon/boss_bloon.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:btd6wiki/utilities/favorite_state.dart'; +import 'package:btd6wiki/utilities/utils.dart'; import 'package:provider/provider.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:carousel_slider/carousel_slider.dart'; @@ -67,16 +68,8 @@ class _BossBloonState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () { - String msg = favoriteState.toggleFavorite(boss); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Center(child: Text(msg)), - duration: const Duration(milliseconds: 400), - ), - ); - }, + onPressed: () => + toggleFavoriteFunc(context, favoriteState, boss), icon: favoriteState.isFavorite(boss.type, boss.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/bloon/single_bloon.dart b/lib/presentation/screens/bloon/single_bloon.dart index 75d4376..1df1601 100644 --- a/lib/presentation/screens/bloon/single_bloon.dart +++ b/lib/presentation/screens/bloon/single_bloon.dart @@ -58,16 +58,8 @@ class _SingleBloonState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () { - String msg = favoriteState.toggleFavorite(bloon); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Center(child: Text(msg)), - duration: const Duration(milliseconds: 400), - ), - ); - }, + onPressed: () => + toggleFavoriteFunc(context, favoriteState, bloon), icon: favoriteState.isFavorite(bloon.type, bloon.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index 6a2f732..4ecd00e 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -68,9 +68,8 @@ class _HeroesState extends State { return InkWell( borderRadius: BorderRadius.circular(20), - onLongPress: () { - favoriteState.toggleFavorite(hero); - }, + onLongPress: () => + toggleFavoriteFunc(context, favoriteState, hero), onTap: () { widget.analyticsHelper.logEvent( name: widgetEngagement, diff --git a/lib/presentation/screens/hero/single_hero.dart b/lib/presentation/screens/hero/single_hero.dart index 2e57269..61239b2 100644 --- a/lib/presentation/screens/hero/single_hero.dart +++ b/lib/presentation/screens/hero/single_hero.dart @@ -107,16 +107,8 @@ class _SingleHeroState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () { - String msg = favoriteState.toggleFavorite(singleHero); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Center(child: Text(msg)), - duration: const Duration(milliseconds: 400), - ), - ); - }, + onPressed: () => toggleFavoriteFunc( + context, favoriteState, singleHero), icon: favoriteState.isFavorite( singleHero.type, singleHero.id) ? const Icon(Icons.star) diff --git a/lib/presentation/screens/maps/maps.dart b/lib/presentation/screens/maps/maps.dart index af85762..52f2c74 100644 --- a/lib/presentation/screens/maps/maps.dart +++ b/lib/presentation/screens/maps/maps.dart @@ -76,9 +76,8 @@ class _MapsState extends State { return Padding( padding: const EdgeInsets.all(5.0), child: GestureDetector( - onLongPress: () { - favoriteState.toggleFavorite(map); - }, + onLongPress: () => + toggleFavoriteFunc(context, favoriteState, map), onTap: () { widget.analyticsHelper.logEvent( name: widgetEngagement, diff --git a/lib/presentation/screens/maps/single_map.dart b/lib/presentation/screens/maps/single_map.dart index 11916b6..b051b8b 100644 --- a/lib/presentation/screens/maps/single_map.dart +++ b/lib/presentation/screens/maps/single_map.dart @@ -1,5 +1,6 @@ import 'dart:convert'; import 'package:btd6wiki/utilities/favorite_state.dart'; +import 'package:btd6wiki/utilities/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; @@ -50,23 +51,15 @@ class _SingleMapState extends State { @override Widget build(BuildContext context) { return Scaffold( - appBar: !loading + appBar: !loading ? AppBar( title: Text(map.name), actions: [ Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () { - String msg = favoriteState.toggleFavorite(map); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Center(child: Text(msg)), - duration: const Duration(milliseconds: 400), - ), - ); - }, + onPressed: () => + toggleFavoriteFunc(context, favoriteState, map), icon: favoriteState.isFavorite(map.type, map.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/tower/single_tower.dart b/lib/presentation/screens/tower/single_tower.dart index d634766..fd44cd1 100644 --- a/lib/presentation/screens/tower/single_tower.dart +++ b/lib/presentation/screens/tower/single_tower.dart @@ -76,16 +76,8 @@ class _SingleTowerState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () { - String msg = favoriteState.toggleFavorite(tower); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Center(child: Text(msg)), - duration: const Duration(milliseconds: 400), - ), - ); - }, + onPressed: () => + toggleFavoriteFunc(context, favoriteState, tower), icon: favoriteState.isFavorite(tower.type, tower.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 23e9a7a..68aeb60 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -69,9 +69,8 @@ class _TowersState extends State { return InkWell( borderRadius: BorderRadius.circular(20), - onLongPress: () { - favoriteState.toggleFavorite(tower); - }, + onLongPress: () => + toggleFavoriteFunc(context, favoriteState, tower), onTap: () { widget.analyticsHelper.logEvent( name: widgetEngagement, @@ -88,7 +87,6 @@ class _TowersState extends State { towerId: tower.id, analyticsHelper: widget.analyticsHelper, ), - ), ); }, diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index e3ce793..ce652cb 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -1,3 +1,4 @@ +import 'package:btd6wiki/utilities/utils.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '/models/base_model.dart'; @@ -37,9 +38,8 @@ class BloonsGrid extends StatelessWidget { return Consumer( builder: (context, favoriteState, child) { return InkWell( - onLongPress: () { - favoriteState.toggleFavorite(bloon); - }, + onLongPress: () => + toggleFavoriteFunc(context, favoriteState, bloon), onTap: () { analyticsHelper.logEvent( name: widgetEngagement, diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index 9c6fa21..f97d7d2 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -1,3 +1,4 @@ +import 'package:btd6wiki/utilities/utils.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/analytics/analytics_constants.dart'; @@ -36,9 +37,8 @@ class BossesGrid extends StatelessWidget { return Consumer( builder: (context, favoriteState, child) { return InkWell( - onLongPress: () { - favoriteState.toggleFavorite(boss); - }, + onLongPress: () => + toggleFavoriteFunc(context, favoriteState, boss), onTap: () { analyticsHelper.logEvent( name: widgetEngagement, diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index a59576e..6e7a76c 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -15,6 +15,8 @@ const int kMapsIndex = 3; const String kFavorite = 'favorite'; +const Duration snackBarDuration = Duration(milliseconds: 850); + const List capTitles = [ 'Towers', 'Heroes', diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 9ccd435..6415e60 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,3 +1,4 @@ +import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; import '/analytics/analytics_constants.dart'; @@ -95,6 +96,18 @@ void navigateToPage(BuildContext context, var item, ); } +void toggleFavoriteFunc( + BuildContext context, FavoriteState favoriteState, var item) { + String msg = favoriteState.toggleFavorite(item); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: snackBarDuration, + ), + ); +} + String formatBigNumber(int number) { if (number < 1000) { return number.toString(); From 9f9d7f182f82d3fd290663578d4e3ded3bf4a6dd Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 17:12:20 +0200 Subject: [PATCH 19/32] added multi select for favorites --- lib/main.dart | 43 ++++++++++++------- lib/presentation/screens/hero/heroes.dart | 36 +++++++++------- lib/presentation/screens/maps/maps.dart | 34 ++++++++------- lib/presentation/screens/tower/towers.dart | 36 +++++++++------- .../widgets/bloons/bloons_grid.dart | 36 +++++++++------- .../widgets/bloons/bosses_grid.dart | 36 +++++++++------- lib/utilities/favorite_state.dart | 8 ++++ 7 files changed, 135 insertions(+), 94 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 815e7ac..742d4ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -196,24 +196,37 @@ class _MyHomePageState extends State { ); }, ), - IconButton( - onPressed: () async { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => FavoriteScreen( - analyticsHelper: analyticsHelper, - ), + Consumer( + builder: (context, favoriteState, child) { + IconData favIcon = + favoriteState.multiSelect ? Icons.add_task_sharp : Icons.star; + return GestureDetector( + onLongPress: () { + favoriteState.toggleMultiSelect(); + }, + child: IconButton( + onPressed: () { + if (!favoriteState.multiSelect) { + analyticsHelper.logScreenView( + screenClass: kFavoritesClass, + screenName: kFavoritesClass, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => FavoriteScreen( + analyticsHelper: analyticsHelper, + ), + ), + ); + } else { + favoriteState.toggleMultiSelect(); + } + }, + icon: Icon(favIcon), ), ); }, - icon: const Icon(Icons.star), - ), - IconButton( - onPressed: () async { - await Hive.deleteFromDisk(); - }, - icon: const Icon(Icons.remove), ), ], ), diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index 4ecd00e..36e3745 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -71,23 +71,27 @@ class _HeroesState extends State { onLongPress: () => toggleFavoriteFunc(context, favoriteState, hero), onTap: () { - widget.analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kHeroPagesClass, - 'widget': listTile, - 'value': hero.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleHero( - heroId: hero.id, - analyticsHelper: widget.analyticsHelper, + if (!favoriteState.multiSelect) { + widget.analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kHeroPagesClass, + 'widget': listTile, + 'value': hero.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleHero( + heroId: hero.id, + analyticsHelper: widget.analyticsHelper, + ), ), - ), - ); + ); + } else { + toggleFavoriteFunc(context, favoriteState, hero); + } }, child: Stack( children: [ diff --git a/lib/presentation/screens/maps/maps.dart b/lib/presentation/screens/maps/maps.dart index 52f2c74..cfdd11f 100644 --- a/lib/presentation/screens/maps/maps.dart +++ b/lib/presentation/screens/maps/maps.dart @@ -79,22 +79,26 @@ class _MapsState extends State { onLongPress: () => toggleFavoriteFunc(context, favoriteState, map), onTap: () { - widget.analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kMapPagesClass, - 'widget': map.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleMap( - analyticsHelper: widget.analyticsHelper, - mapId: map.id, + if (!favoriteState.multiSelect) { + widget.analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kMapPagesClass, + 'widget': map.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleMap( + analyticsHelper: widget.analyticsHelper, + mapId: map.id, + ), ), - ), - ); + ); + } else { + toggleFavoriteFunc(context, favoriteState, map); + } }, child: MapCard(singleMap: map), ), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 68aeb60..1c3eb06 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -72,23 +72,27 @@ class _TowersState extends State { onLongPress: () => toggleFavoriteFunc(context, favoriteState, tower), onTap: () { - widget.analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kTowerPagesClass, - 'widget': listTile, - 'value': tower.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleTower( - towerId: tower.id, - analyticsHelper: widget.analyticsHelper, + if (!favoriteState.multiSelect) { + widget.analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kTowerPagesClass, + 'widget': listTile, + 'value': tower.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleTower( + towerId: tower.id, + analyticsHelper: widget.analyticsHelper, + ), ), - ), - ); + ); + } else { + toggleFavoriteFunc(context, favoriteState, tower); + } }, child: Stack( alignment: AlignmentDirectional.topEnd, diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index ce652cb..dff7f78 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -41,23 +41,27 @@ class BloonsGrid extends StatelessWidget { onLongPress: () => toggleFavoriteFunc(context, favoriteState, bloon), onTap: () { - analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kBloonPagesClass, - 'widget': listTile, - 'value': bloon.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => SingleBloon( - analyticsHelper: analyticsHelper, - bloonId: bloon.id, + if (!favoriteState.multiSelect) { + analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kBloonPagesClass, + 'widget': listTile, + 'value': bloon.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => SingleBloon( + analyticsHelper: analyticsHelper, + bloonId: bloon.id, + ), ), - ), - ); + ); + } else { + toggleFavoriteFunc(context, favoriteState, bloon); + } }, child: Card( margin: const EdgeInsets.symmetric( diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index f97d7d2..c9baafc 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -40,23 +40,27 @@ class BossesGrid extends StatelessWidget { onLongPress: () => toggleFavoriteFunc(context, favoriteState, boss), onTap: () { - analyticsHelper.logEvent( - name: widgetEngagement, - parameters: { - 'screen': kBossPagesClass, - 'widget': listTile, - 'value': boss.id, - }, - ); - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => BossBloon( - analyticsHelper: analyticsHelper, - bossId: boss.id, + if (!favoriteState.multiSelect) { + analyticsHelper.logEvent( + name: widgetEngagement, + parameters: { + 'screen': kBossPagesClass, + 'widget': listTile, + 'value': boss.id, + }, + ); + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => BossBloon( + analyticsHelper: analyticsHelper, + bossId: boss.id, + ), ), - ), - ); + ); + } else { + toggleFavoriteFunc(context, favoriteState, boss); + } }, child: Card( child: Center( diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 0a722f7..b3ff78e 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -6,11 +6,14 @@ import '/utilities/constants.dart'; class FavoriteState extends ChangeNotifier { late Box> _favoriteBox; + bool _multiSelect = false; + FavoriteState() { _favoriteBox = Hive.box>(kFavorite); } Box> get favoriteBox => _favoriteBox; + bool get multiSelect => _multiSelect; List getListOfType(String type) { if (_favoriteBox.containsKey(type)) { @@ -20,6 +23,11 @@ class FavoriteState extends ChangeNotifier { return []; } + void toggleMultiSelect() { + _multiSelect = !_multiSelect; + notifyListeners(); + } + String toggleFavorite(var item) { bool addedToFavorites = false; FavoriteModel favItem = _createFavoriteItem(item); From c8e1d20de8bc6c7294a58d062b6ba480eb69e522 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 18:10:44 +0200 Subject: [PATCH 20/32] moved toggleFavoriteFunc to state mgmt, added remove func to fav screen --- .../screens/bloon/boss_bloon.dart | 4 +- .../screens/bloon/single_bloon.dart | 4 +- lib/presentation/screens/hero/heroes.dart | 7 +- .../screens/hero/single_hero.dart | 2 +- lib/presentation/screens/maps/maps.dart | 7 +- lib/presentation/screens/maps/single_map.dart | 4 +- .../screens/misc/favorite_screen.dart | 23 +++- .../screens/tower/single_tower.dart | 4 +- lib/presentation/screens/tower/towers.dart | 7 +- .../widgets/bloons/bloons_grid.dart | 7 +- .../widgets/bloons/bosses_grid.dart | 7 +- .../widgets/misc/orderable_grid.dart | 127 +++++++----------- lib/utilities/favorite_state.dart | 13 ++ lib/utilities/utils.dart | 73 ++++++++-- 14 files changed, 167 insertions(+), 122 deletions(-) diff --git a/lib/presentation/screens/bloon/boss_bloon.dart b/lib/presentation/screens/bloon/boss_bloon.dart index 56d607f..9380071 100644 --- a/lib/presentation/screens/bloon/boss_bloon.dart +++ b/lib/presentation/screens/bloon/boss_bloon.dart @@ -68,8 +68,8 @@ class _BossBloonState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () => - toggleFavoriteFunc(context, favoriteState, boss), + onPressed: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, boss), icon: favoriteState.isFavorite(boss.type, boss.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/bloon/single_bloon.dart b/lib/presentation/screens/bloon/single_bloon.dart index 1df1601..e689bc3 100644 --- a/lib/presentation/screens/bloon/single_bloon.dart +++ b/lib/presentation/screens/bloon/single_bloon.dart @@ -58,8 +58,8 @@ class _SingleBloonState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () => - toggleFavoriteFunc(context, favoriteState, bloon), + onPressed: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, bloon), icon: favoriteState.isFavorite(bloon.type, bloon.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index 36e3745..3701df4 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -68,8 +68,8 @@ class _HeroesState extends State { return InkWell( borderRadius: BorderRadius.circular(20), - onLongPress: () => - toggleFavoriteFunc(context, favoriteState, hero), + onLongPress: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, hero), onTap: () { if (!favoriteState.multiSelect) { widget.analyticsHelper.logEvent( @@ -90,7 +90,8 @@ class _HeroesState extends State { ), ); } else { - toggleFavoriteFunc(context, favoriteState, hero); + favoriteState.toggleFavoriteFunc( + context, favoriteState, hero); } }, child: Stack( diff --git a/lib/presentation/screens/hero/single_hero.dart b/lib/presentation/screens/hero/single_hero.dart index 61239b2..cda1952 100644 --- a/lib/presentation/screens/hero/single_hero.dart +++ b/lib/presentation/screens/hero/single_hero.dart @@ -107,7 +107,7 @@ class _SingleHeroState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () => toggleFavoriteFunc( + onPressed: () => favoriteState.toggleFavoriteFunc( context, favoriteState, singleHero), icon: favoriteState.isFavorite( singleHero.type, singleHero.id) diff --git a/lib/presentation/screens/maps/maps.dart b/lib/presentation/screens/maps/maps.dart index cfdd11f..c558a9b 100644 --- a/lib/presentation/screens/maps/maps.dart +++ b/lib/presentation/screens/maps/maps.dart @@ -76,8 +76,8 @@ class _MapsState extends State { return Padding( padding: const EdgeInsets.all(5.0), child: GestureDetector( - onLongPress: () => - toggleFavoriteFunc(context, favoriteState, map), + onLongPress: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, map), onTap: () { if (!favoriteState.multiSelect) { widget.analyticsHelper.logEvent( @@ -97,7 +97,8 @@ class _MapsState extends State { ), ); } else { - toggleFavoriteFunc(context, favoriteState, map); + favoriteState.toggleFavoriteFunc( + context, favoriteState, map); } }, child: MapCard(singleMap: map), diff --git a/lib/presentation/screens/maps/single_map.dart b/lib/presentation/screens/maps/single_map.dart index b051b8b..5fe9dd3 100644 --- a/lib/presentation/screens/maps/single_map.dart +++ b/lib/presentation/screens/maps/single_map.dart @@ -58,8 +58,8 @@ class _SingleMapState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () => - toggleFavoriteFunc(context, favoriteState, map), + onPressed: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, map), icon: favoriteState.isFavorite(map.type, map.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index 9cff94c..f48ab0e 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -32,14 +32,23 @@ class _FavoriteScreenState extends State { return Scaffold( appBar: AppBar( title: const Text('Favorites'), + actions: [ + Consumer( + builder: (context, favoriteState, child) { + return IconButton( + onPressed: () { + favoriteState.toggleMultiSelect(); + }, + icon: Icon( + !favoriteState.multiSelect ? Icons.delete : Icons.close), + ); + }, + ), + ], ), - body: Consumer( - builder: (context, favoriteState, child) { - return ListView( - shrinkWrap: true, - children: generatedChildren, - ); - }, + body: ListView( + shrinkWrap: true, + children: generatedChildren, ), ); } diff --git a/lib/presentation/screens/tower/single_tower.dart b/lib/presentation/screens/tower/single_tower.dart index fd44cd1..ffbe011 100644 --- a/lib/presentation/screens/tower/single_tower.dart +++ b/lib/presentation/screens/tower/single_tower.dart @@ -76,8 +76,8 @@ class _SingleTowerState extends State { Consumer( builder: (context, favoriteState, child) { return IconButton( - onPressed: () => - toggleFavoriteFunc(context, favoriteState, tower), + onPressed: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, tower), icon: favoriteState.isFavorite(tower.type, tower.id) ? const Icon(Icons.star) : const Icon(Icons.star_border_outlined), diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 1c3eb06..fd2c07f 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -69,8 +69,8 @@ class _TowersState extends State { return InkWell( borderRadius: BorderRadius.circular(20), - onLongPress: () => - toggleFavoriteFunc(context, favoriteState, tower), + onLongPress: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, tower), onTap: () { if (!favoriteState.multiSelect) { widget.analyticsHelper.logEvent( @@ -91,7 +91,8 @@ class _TowersState extends State { ), ); } else { - toggleFavoriteFunc(context, favoriteState, tower); + favoriteState.toggleFavoriteFunc( + context, favoriteState, tower); } }, child: Stack( diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index dff7f78..13e9ada 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -38,8 +38,8 @@ class BloonsGrid extends StatelessWidget { return Consumer( builder: (context, favoriteState, child) { return InkWell( - onLongPress: () => - toggleFavoriteFunc(context, favoriteState, bloon), + onLongPress: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, bloon), onTap: () { if (!favoriteState.multiSelect) { analyticsHelper.logEvent( @@ -60,7 +60,8 @@ class BloonsGrid extends StatelessWidget { ), ); } else { - toggleFavoriteFunc(context, favoriteState, bloon); + favoriteState.toggleFavoriteFunc( + context, favoriteState, bloon); } }, child: Card( diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index c9baafc..45b44a9 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -37,8 +37,8 @@ class BossesGrid extends StatelessWidget { return Consumer( builder: (context, favoriteState, child) { return InkWell( - onLongPress: () => - toggleFavoriteFunc(context, favoriteState, boss), + onLongPress: () => favoriteState.toggleFavoriteFunc( + context, favoriteState, boss), onTap: () { if (!favoriteState.multiSelect) { analyticsHelper.logEvent( @@ -59,7 +59,8 @@ class BossesGrid extends StatelessWidget { ), ); } else { - toggleFavoriteFunc(context, favoriteState, boss); + favoriteState.toggleFavoriteFunc( + context, favoriteState, boss); } }, child: Card( diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index a75005f..c11150f 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -1,3 +1,5 @@ +import 'package:btd6wiki/utilities/constants.dart'; +import 'package:btd6wiki/utilities/strings.dart'; import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; import 'package:provider/provider.dart'; @@ -30,87 +32,54 @@ class _OrderableGridState extends State { final _scrollController = ScrollController(); @override Widget build(BuildContext context) { - final generatedChildren = List.generate( - widget.favoriteItems.length, - (index) { - FavoriteModel favItem = widget.favoriteItems.elementAt(index); - return InkWell( - key: Key(favItem.id), - onTap: () { - navigateToPage( - context, - favItem, - widget.analyticsHelper, - kFavoritesClass, - card, - ); - }, - child: Card( - child: Padding( - padding: const EdgeInsets.all(8), - child: Column( - mainAxisSize: MainAxisSize.min, - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - flex: 3, - child: Image( - image: AssetImage( - assetImagePath(widget.typeName, favItem.image)), - ), - ), - Flexible( - flex: 1, - child: Center( - child: Text( - favItem.name, - textAlign: TextAlign.center, - )), - ), - ], - ), + return Consumer( + builder: (context, favoriteState, child) { + List generatedChildren = generateGridChildren( + widget.favoriteItems, widget.analyticsHelper, widget.typeName); + if (generatedChildren.isNotEmpty) { + return Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + children: [ + Text( + capitalizeEveryWord(widget.typeName), + style: bigTitleStyle, + ), + ReorderableBuilder( + scrollController: _scrollController, + onReorder: (List orderUpdateEntities) { + for (final orderUpdateEntity in orderUpdateEntities) { + final favItem = widget.favoriteItems + .removeAt(orderUpdateEntity.oldIndex); + widget.favoriteItems + .insert(orderUpdateEntity.newIndex, favItem); + } + favoriteState.updateIndexes( + widget.typeName, widget.favoriteItems); + }, + builder: (children) { + return GridView( + key: widget.gridKey, + controller: _scrollController, + shrinkWrap: true, + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( + mainAxisSpacing: 15, + crossAxisSpacing: 10, + crossAxisCount: 3, + childAspectRatio: 0.70, + ), + children: children, + ); + }, + children: generatedChildren, + ), + ], ), - ), - ); + ); + } + return Container(); }, ); - - return Padding( - padding: const EdgeInsets.all(8.0), - child: Column( - children: [ - Text(widget.typeName), - ReorderableBuilder( - scrollController: _scrollController, - onReorder: (List orderUpdateEntities) { - for (final orderUpdateEntity in orderUpdateEntities) { - final favItem = - widget.favoriteItems.removeAt(orderUpdateEntity.oldIndex); - widget.favoriteItems - .insert(orderUpdateEntity.newIndex, favItem); - } - Provider.of(context, listen: false) - .updateIndexes(widget.typeName, widget.favoriteItems); - }, - builder: (children) { - return GridView( - key: widget.gridKey, - controller: _scrollController, - shrinkWrap: true, - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - mainAxisSpacing: 15, - crossAxisSpacing: 10, - crossAxisCount: 3, - childAspectRatio: 0.70, - ), - children: children, - ); - }, - children: generatedChildren, - ), - ], - ), - ); } } diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index b3ff78e..7f53622 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -28,6 +28,19 @@ class FavoriteState extends ChangeNotifier { notifyListeners(); } + void toggleFavoriteFunc( + BuildContext context, FavoriteState favoriteState, var item) { + String msg = favoriteState.toggleFavorite(item); + ScaffoldMessenger.of(context).removeCurrentSnackBar(); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Center(child: Text(msg)), + duration: snackBarDuration, + ), + ); + notifyListeners(); + } + String toggleFavorite(var item) { bool addedToFavorites = false; FavoriteModel favItem = _createFavoriteItem(item); diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 6415e60..836f1da 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,4 +1,6 @@ +import 'package:btd6wiki/hive/favorite_model.dart'; import 'package:btd6wiki/utilities/favorite_state.dart'; +import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; import '/analytics/analytics_constants.dart'; @@ -96,18 +98,6 @@ void navigateToPage(BuildContext context, var item, ); } -void toggleFavoriteFunc( - BuildContext context, FavoriteState favoriteState, var item) { - String msg = favoriteState.toggleFavorite(item); - ScaffoldMessenger.of(context).removeCurrentSnackBar(); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Center(child: Text(msg)), - duration: snackBarDuration, - ), - ); -} - String formatBigNumber(int number) { if (number < 1000) { return number.toString(); @@ -120,6 +110,65 @@ String formatBigNumber(int number) { } } +List generateGridChildren(List favoriteItems, + AnalyticsHelper analyticsHelper, String typeName) { + return List.generate( + favoriteItems.length, + (index) { + FavoriteModel favItem = favoriteItems.elementAt(index); + return Consumer( + key: Key(favItem.id), + builder: (context, favoriteState, child) { + return InkWell( + onTap: () { + if (!favoriteState.multiSelect) { + navigateToPage( + context, + favItem, + analyticsHelper, + kFavoritesClass, + card, + ); + } else { + favoriteState.toggleFavoriteFunc( + context, favoriteState, favItem); + favoriteItems.removeWhere((item) => item.id == favItem.id); + } + }, + child: Card( + child: Padding( + padding: const EdgeInsets.all(8), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + flex: 3, + child: Image( + image: + AssetImage(assetImagePath(typeName, favItem.image)), + ), + ), + Flexible( + flex: 1, + child: Center( + child: Text( + favItem.name, + textAlign: TextAlign.center, + )), + ), + ], + ), + ), + ), + ); + }, + ); + }, + ); +} + String getPathKeyFromIndex(int index) { switch (index) { case 0: From d702467cdf2fb7ac1c85ef315351444ba71cc77a Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 18:20:28 +0200 Subject: [PATCH 21/32] import cleanup --- lib/presentation/screens/bloon/boss_bloon.dart | 5 ++--- lib/presentation/screens/bloon/single_bloon.dart | 4 ++-- lib/presentation/screens/hero/single_hero.dart | 6 +++--- lib/presentation/screens/maps/single_map.dart | 3 +-- lib/presentation/screens/tower/single_tower.dart | 4 ++-- lib/presentation/widgets/bloons/bloons_grid.dart | 1 - lib/presentation/widgets/bloons/bosses_grid.dart | 1 - lib/presentation/widgets/misc/orderable_grid.dart | 6 ++---- lib/utilities/utils.dart | 4 ++-- 9 files changed, 14 insertions(+), 20 deletions(-) diff --git a/lib/presentation/screens/bloon/boss_bloon.dart b/lib/presentation/screens/bloon/boss_bloon.dart index 9380071..31f1c2f 100644 --- a/lib/presentation/screens/bloon/boss_bloon.dart +++ b/lib/presentation/screens/bloon/boss_bloon.dart @@ -1,6 +1,4 @@ import 'dart:convert'; -import 'package:btd6wiki/utilities/favorite_state.dart'; -import 'package:btd6wiki/utilities/utils.dart'; import 'package:provider/provider.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import 'package:carousel_slider/carousel_slider.dart'; @@ -8,9 +6,10 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/bloons/boss/boss_health_class.dart'; import '/models/bloons/boss/boss_bloon.dart'; -import '../../widgets/bloons/bloon_aid_widget.dart'; +import '/presentation/widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; diff --git a/lib/presentation/screens/bloon/single_bloon.dart b/lib/presentation/screens/bloon/single_bloon.dart index e689bc3..e33cb12 100644 --- a/lib/presentation/screens/bloon/single_bloon.dart +++ b/lib/presentation/screens/bloon/single_bloon.dart @@ -1,12 +1,12 @@ import 'dart:convert'; -import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '/models/bloons/bloon/bloon.dart'; -import '../../widgets/bloons/bloon_aid_widget.dart'; +import '/presentation/widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; import '/utilities/utils.dart'; diff --git a/lib/presentation/screens/hero/single_hero.dart b/lib/presentation/screens/hero/single_hero.dart index cda1952..f293bde 100644 --- a/lib/presentation/screens/hero/single_hero.dart +++ b/lib/presentation/screens/hero/single_hero.dart @@ -1,5 +1,4 @@ import 'dart:convert'; -import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; @@ -7,10 +6,11 @@ import 'package:provider/provider.dart'; import 'package:smooth_page_indicator/smooth_page_indicator.dart'; import '/models/towers/common/upgrade_info_class.dart'; import '/models/towers/hero/hero.dart'; -import '../../widgets/heroes/hero_stats.dart'; -import '../../widgets/heroes/hero_level.dart'; +import '/presentation/widgets/heroes/hero_stats.dart'; +import '/presentation/widgets/heroes/hero_level.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; import '/utilities/utils.dart'; diff --git a/lib/presentation/screens/maps/single_map.dart b/lib/presentation/screens/maps/single_map.dart index 5fe9dd3..2048ec5 100644 --- a/lib/presentation/screens/maps/single_map.dart +++ b/lib/presentation/screens/maps/single_map.dart @@ -1,12 +1,11 @@ import 'dart:convert'; -import 'package:btd6wiki/utilities/favorite_state.dart'; -import 'package:btd6wiki/utilities/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '/models/maps/map.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; diff --git a/lib/presentation/screens/tower/single_tower.dart b/lib/presentation/screens/tower/single_tower.dart index ffbe011..9b0d951 100644 --- a/lib/presentation/screens/tower/single_tower.dart +++ b/lib/presentation/screens/tower/single_tower.dart @@ -1,12 +1,12 @@ import 'dart:convert'; -import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:provider/provider.dart'; import '/models/towers/tower/tower.dart'; -import '../../widgets/towers/path.dart'; +import '/presentation/widgets/towers/path.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; +import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; import '/utilities/constants.dart'; import '/utilities/utils.dart'; diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index 13e9ada..0cecc15 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -1,4 +1,3 @@ -import 'package:btd6wiki/utilities/utils.dart'; import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '/models/base_model.dart'; diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index 45b44a9..82ab6fc 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -1,4 +1,3 @@ -import 'package:btd6wiki/utilities/utils.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/analytics/analytics_constants.dart'; diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index c11150f..b378391 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -1,13 +1,11 @@ -import 'package:btd6wiki/utilities/constants.dart'; -import 'package:btd6wiki/utilities/strings.dart'; import 'package:flutter_reorderable_grid_view/entities/order_update_entity.dart'; import 'package:flutter_reorderable_grid_view/widgets/widgets.dart'; import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; -import '/hive/favorite_model.dart'; -import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; +import '/utilities/constants.dart'; +import '/utilities/strings.dart'; import '/utilities/utils.dart'; class OrderableGrid extends StatefulWidget { diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index 836f1da..ea7ce29 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -1,8 +1,7 @@ -import 'package:btd6wiki/hive/favorite_model.dart'; -import 'package:btd6wiki/utilities/favorite_state.dart'; import 'package:provider/provider.dart'; import 'package:url_launcher/url_launcher.dart'; import 'package:flutter/material.dart'; +import '/hive/favorite_model.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/models/bloons/common/relative_class.dart'; @@ -17,6 +16,7 @@ import '/presentation/screens/bloon/single_bloon.dart'; import '/presentation/screens/bloon/boss_bloon.dart'; import '/presentation/screens/hero/single_hero.dart'; import '/presentation/screens/maps/single_map.dart'; +import '/utilities/favorite_state.dart'; import 'layout_presets.dart'; import 'images_url.dart'; import 'constants.dart'; From 10f84dc469f1eab3bedb42d691e9a37f4dc0d6cd Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 18:26:02 +0200 Subject: [PATCH 22/32] add single remove func to fav screen and changed snackbar duration and dismiss dir --- lib/utilities/constants.dart | 2 +- lib/utilities/favorite_state.dart | 1 + lib/utilities/utils.dart | 4 ++++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 6e7a76c..58c3dc9 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -15,7 +15,7 @@ const int kMapsIndex = 3; const String kFavorite = 'favorite'; -const Duration snackBarDuration = Duration(milliseconds: 850); +const Duration snackBarDuration = Duration(seconds: 2); const List capTitles = [ 'Towers', diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 7f53622..314ba1a 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -36,6 +36,7 @@ class FavoriteState extends ChangeNotifier { SnackBar( content: Center(child: Text(msg)), duration: snackBarDuration, + dismissDirection: DismissDirection.horizontal, ), ); notifyListeners(); diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index ea7ce29..e891d13 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -120,6 +120,10 @@ List generateGridChildren(List favoriteItems, key: Key(favItem.id), builder: (context, favoriteState, child) { return InkWell( + onLongPress: () { + favoriteState.toggleFavoriteFunc(context, favoriteState, favItem); + favoriteItems.removeWhere((item) => item.id == favItem.id); + }, onTap: () { if (!favoriteState.multiSelect) { navigateToPage( From 230ae5495e18c5ec3815f22c9196a85c71487c6d Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 19:15:10 +0200 Subject: [PATCH 23/32] added favorites to layout presets --- lib/main.dart | 3 +- .../screens/misc/favorite_screen.dart | 4 +- .../widgets/misc/orderable_grid.dart | 17 +++--- lib/utilities/constants.dart | 6 ++ lib/utilities/layout_presets.dart | 55 ++++++++++++++++--- lib/utilities/utils.dart | 21 ++++--- 6 files changed, 82 insertions(+), 24 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 742d4ac..94f9889 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -129,7 +129,8 @@ class _MyHomePageState extends State { appBar: AppBar( title: Consumer( builder: (context, globalState, child) { - return Text(globalState.currentTitle); + // return Text(globalState.currentTitle); + return Text(MediaQuery.of(context).size.width.toString()); }, ), actions: [ diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index f48ab0e..c154d06 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -31,7 +31,9 @@ class _FavoriteScreenState extends State { ); return Scaffold( appBar: AppBar( - title: const Text('Favorites'), + // title: const Text('Favorites'), + title: Text(MediaQuery.of(context).size.width.toString()), + actions: [ Consumer( builder: (context, favoriteState, child) { diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index b378391..1c402ce 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -30,10 +30,16 @@ class _OrderableGridState extends State { final _scrollController = ScrollController(); @override Widget build(BuildContext context) { + final constraintsValues = getPreset( + MediaQuery.of(context).size, + ); return Consumer( builder: (context, favoriteState, child) { List generatedChildren = generateGridChildren( - widget.favoriteItems, widget.analyticsHelper, widget.typeName); + widget.favoriteItems, + widget.analyticsHelper, + widget.typeName, + constraintsValues); if (generatedChildren.isNotEmpty) { return Padding( padding: const EdgeInsets.all(8.0), @@ -60,12 +66,9 @@ class _OrderableGridState extends State { key: widget.gridKey, controller: _scrollController, shrinkWrap: true, - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - mainAxisSpacing: 15, - crossAxisSpacing: 10, - crossAxisCount: 3, - childAspectRatio: 0.70, + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: constraintsValues[favItemCrossCount], + childAspectRatio: constraintsValues[favItemAspectRatio], ), children: children, ); diff --git a/lib/utilities/constants.dart b/lib/utilities/constants.dart index 58c3dc9..70e75b2 100644 --- a/lib/utilities/constants.dart +++ b/lib/utilities/constants.dart @@ -205,3 +205,9 @@ const String mapCrossCount = 'mapCrossAxisCount'; const String mapAspectRatio = 'mapChildAspectRatio'; const String mapTitleStyle = 'mapTitleStyle'; const String mapSubtitleStyle = 'mapSubtitleStyle'; + +const String favItemCrossCount = 'favItemCrossCount'; +const String favItemAspectRatio = 'favItemAspectRatio'; +const String favItemSubtitleStyle = 'favItemSubtitleStyle'; +const String favItemImageFlex = 'favItemImageFlex'; +const String favItemTextFlex = 'favItemTextFlex'; diff --git a/lib/utilities/layout_presets.dart b/lib/utilities/layout_presets.dart index ac5fd59..7c8a508 100644 --- a/lib/utilities/layout_presets.dart +++ b/lib/utilities/layout_presets.dart @@ -28,6 +28,12 @@ Map presetUS = { // maps mapCrossCount: 1, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 2, + favItemAspectRatio: 0.6, + favItemImageFlex: 5, + favItemTextFlex: 2, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.0), }; Map presetXS = { // towers @@ -37,7 +43,6 @@ Map presetXS = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 13.0), towerSubtitleRows: 2, towerImageWidth: 55.0, - // heroes heroCrossCount: 1, heroAspectRatio: 3.5, @@ -58,6 +63,12 @@ Map presetXS = { // maps mapCrossCount: 1, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 3, + favItemAspectRatio: 0.60, + favItemImageFlex: 9, + favItemTextFlex: 4, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.0), }; Map presetSM = { // towers @@ -67,7 +78,6 @@ Map presetSM = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.0), towerSubtitleRows: 2, towerImageWidth: 65.0, - // heroes heroCrossCount: 1, heroAspectRatio: 3.5, @@ -88,6 +98,12 @@ Map presetSM = { // maps mapCrossCount: 1, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 3, + favItemAspectRatio: 0.65, + favItemImageFlex: 7, + favItemTextFlex: 3, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 16.5), }; Map presetMD = { // towers @@ -97,7 +113,6 @@ Map presetMD = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.5), towerSubtitleRows: 3, towerImageWidth: 70.0, - // heroes heroCrossCount: 1, heroAspectRatio: 3.5, @@ -118,6 +133,12 @@ Map presetMD = { // maps mapCrossCount: 2, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 3, + favItemAspectRatio: 0.65, + favItemImageFlex: 7, + favItemTextFlex: 3, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 16.5), }; Map presetLG = { // towers @@ -127,7 +148,6 @@ Map presetLG = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 15), towerSubtitleRows: 2, towerImageWidth: 90.0, - // heroes heroCrossCount: 1, heroAspectRatio: 4.3, @@ -148,6 +168,12 @@ Map presetLG = { // maps mapCrossCount: 2, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 4, + favItemAspectRatio: 0.62, + favItemImageFlex: 7, + favItemTextFlex: 3, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 15.5), }; Map presetXL = { // towers @@ -157,7 +183,6 @@ Map presetXL = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.0), towerSubtitleRows: 2, towerImageWidth: 50.0, - // heroes heroCrossCount: 2, heroAspectRatio: 3.0, @@ -178,6 +203,12 @@ Map presetXL = { // maps mapCrossCount: 2, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 5, + favItemAspectRatio: 0.62, + favItemImageFlex: 7, + favItemTextFlex: 3, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 15.5), }; Map presetXXL = { // towers @@ -187,7 +218,6 @@ Map presetXXL = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.0), towerSubtitleRows: 2, towerImageWidth: 65.0, - // heroes heroCrossCount: 2, heroAspectRatio: 3.5, @@ -208,6 +238,12 @@ Map presetXXL = { // maps mapCrossCount: 2, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 6, + favItemAspectRatio: 0.60, + favItemImageFlex: 7, + favItemTextFlex: 4, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 15.0), }; Map presetXXXL = { // towers @@ -217,7 +253,6 @@ Map presetXXXL = { towerSubtitleStyle: subtitleStyle.copyWith(fontSize: 14.5), towerSubtitleRows: 3, towerImageWidth: 90.0, - // heroes heroCrossCount: 3, heroAspectRatio: 2.5, @@ -238,4 +273,10 @@ Map presetXXXL = { // maps mapCrossCount: 3, mapAspectRatio: 1.3, + // favorites + favItemCrossCount: 6, + favItemAspectRatio: 0.60, + favItemImageFlex: 7, + favItemTextFlex: 3, + favItemSubtitleStyle: subtitleStyle.copyWith(fontSize: 15.0), }; diff --git a/lib/utilities/utils.dart b/lib/utilities/utils.dart index e891d13..d607778 100644 --- a/lib/utilities/utils.dart +++ b/lib/utilities/utils.dart @@ -110,8 +110,11 @@ String formatBigNumber(int number) { } } -List generateGridChildren(List favoriteItems, - AnalyticsHelper analyticsHelper, String typeName) { +List generateGridChildren( + List favoriteItems, + AnalyticsHelper analyticsHelper, + String typeName, + Map constraintsValues) { return List.generate( favoriteItems.length, (index) { @@ -148,19 +151,21 @@ List generateGridChildren(List favoriteItems, crossAxisAlignment: CrossAxisAlignment.center, children: [ Expanded( - flex: 3, + flex: constraintsValues[favItemImageFlex], child: Image( image: AssetImage(assetImagePath(typeName, favItem.image)), ), ), Flexible( - flex: 1, + flex: constraintsValues[favItemTextFlex], child: Center( - child: Text( - favItem.name, - textAlign: TextAlign.center, - )), + child: Text( + favItem.name, + textAlign: TextAlign.center, + style: constraintsValues[favItemSubtitleStyle], + ), + ), ), ], ), From f9daacf726974673627d7cc1795df6933968c78a Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 19:28:40 +0200 Subject: [PATCH 24/32] fixed bloons visuals for small screens --- lib/main.dart | 3 +-- lib/presentation/screens/misc/favorite_screen.dart | 4 +--- lib/presentation/widgets/bloons/bloons_grid.dart | 1 + lib/utilities/layout_presets.dart | 12 ++++++------ 4 files changed, 9 insertions(+), 11 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 94f9889..742d4ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -129,8 +129,7 @@ class _MyHomePageState extends State { appBar: AppBar( title: Consumer( builder: (context, globalState, child) { - // return Text(globalState.currentTitle); - return Text(MediaQuery.of(context).size.width.toString()); + return Text(globalState.currentTitle); }, ), actions: [ diff --git a/lib/presentation/screens/misc/favorite_screen.dart b/lib/presentation/screens/misc/favorite_screen.dart index c154d06..f48ab0e 100644 --- a/lib/presentation/screens/misc/favorite_screen.dart +++ b/lib/presentation/screens/misc/favorite_screen.dart @@ -31,9 +31,7 @@ class _FavoriteScreenState extends State { ); return Scaffold( appBar: AppBar( - // title: const Text('Favorites'), - title: Text(MediaQuery.of(context).size.width.toString()), - + title: const Text('Favorites'), actions: [ Consumer( builder: (context, favoriteState, child) { diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index 0cecc15..c80a208 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -71,6 +71,7 @@ class BloonsGrid extends StatelessWidget { child: Center( child: ListTile( titleAlignment: ListTileTitleAlignment.center, + contentPadding: const EdgeInsets.symmetric(horizontal: 8.5), leading: ImageOutliner( imageName: bloon.image, imagePath: bloonImage(bloon.image), diff --git a/lib/utilities/layout_presets.dart b/lib/utilities/layout_presets.dart index 7c8a508..6855f32 100644 --- a/lib/utilities/layout_presets.dart +++ b/lib/utilities/layout_presets.dart @@ -17,10 +17,10 @@ Map presetUS = { skinCrossCount: 1, skinAspectRatio: 1.0, // bloons - bloonCrossCount: 1, - bloonAspectRatio: 5.5, + bloonCrossCount: 2, + bloonAspectRatio: 3.0, bloonTitleStyle: smallTitleStyle.copyWith(fontSize: 12.0), - bloonImageWidth: 28.0, + bloonImageWidth: 18.5, // bosses bossCrossCount: 1, bossAspectRatio: 4.3, @@ -53,9 +53,9 @@ Map presetXS = { skinAspectRatio: 1.0, // bloons bloonCrossCount: 2, - bloonAspectRatio: 2.7, - bloonTitleStyle: smallTitleStyle.copyWith(fontSize: 15.0), - bloonImageWidth: 28.0, + bloonAspectRatio: 3.0, + bloonTitleStyle: smallTitleStyle.copyWith(fontSize: 13.0), + bloonImageWidth: 18.5, // bosses bossCrossCount: 1, bossAspectRatio: 4.3, From b284cdd3fc5952033294d9d1ad25b42267ca3d63 Mon Sep 17 00:00:00 2001 From: Shai <45182218+namelessto@users.noreply.github.com> Date: Sat, 10 Feb 2024 19:29:59 +0200 Subject: [PATCH 25/32] Update lib/presentation/screens/bloon/minion_bloon.dart Co-authored-by: Asaf Hadad --- lib/presentation/screens/bloon/minion_bloon.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/screens/bloon/minion_bloon.dart b/lib/presentation/screens/bloon/minion_bloon.dart index 6e1f9db..2dc5173 100644 --- a/lib/presentation/screens/bloon/minion_bloon.dart +++ b/lib/presentation/screens/bloon/minion_bloon.dart @@ -4,7 +4,7 @@ import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/bloons/boss/minion_bloon.dart'; -import '../../widgets/bloons/bloon_aid_widget.dart'; +import '/widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; From 84cf3b6bce16199a8d6338da73d63e88a0ef499b Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 20:25:57 +0200 Subject: [PATCH 26/32] fixed draggable cards and removed unnecessary field --- lib/hive/favorite_model.dart | 5 +---- lib/hive/favorite_model.g.dart | 7 ++----- lib/hive/favorite_model_adapter.dart | 6 ++++-- lib/presentation/widgets/misc/orderable_grid.dart | 1 + lib/utilities/favorite_state.dart | 1 - 5 files changed, 8 insertions(+), 12 deletions(-) diff --git a/lib/hive/favorite_model.dart b/lib/hive/favorite_model.dart index e84db2a..18fe035 100644 --- a/lib/hive/favorite_model.dart +++ b/lib/hive/favorite_model.dart @@ -16,8 +16,5 @@ class FavoriteModel extends HiveObject { @HiveField(3) late final String type; - @HiveField(4) - late int itemIndex; - - FavoriteModel(this.id, this.name, this.image, this.type, this.itemIndex); + FavoriteModel(this.id, this.name, this.image, this.type); } diff --git a/lib/hive/favorite_model.g.dart b/lib/hive/favorite_model.g.dart index b3929d1..a930c81 100644 --- a/lib/hive/favorite_model.g.dart +++ b/lib/hive/favorite_model.g.dart @@ -21,14 +21,13 @@ class FavoriteModelAdapter extends TypeAdapter { fields[1] as String, fields[2] as String, fields[3] as String, - fields[4] as int, ); } @override void write(BinaryWriter writer, FavoriteModel obj) { writer - ..writeByte(5) + ..writeByte(4) ..writeByte(0) ..write(obj.id) ..writeByte(1) @@ -36,9 +35,7 @@ class FavoriteModelAdapter extends TypeAdapter { ..writeByte(2) ..write(obj.image) ..writeByte(3) - ..write(obj.type) - ..writeByte(4) - ..write(obj.itemIndex); + ..write(obj.type); } @override diff --git a/lib/hive/favorite_model_adapter.dart b/lib/hive/favorite_model_adapter.dart index 53a2967..aea2597 100644 --- a/lib/hive/favorite_model_adapter.dart +++ b/lib/hive/favorite_model_adapter.dart @@ -8,11 +8,14 @@ class FavoriteModelBoxAdapter extends TypeAdapter { @override FavoriteModel read(BinaryReader reader) { return FavoriteModel( + // id reader.readString(), + // name reader.readString(), + // image reader.readString(), + // type reader.readString(), - reader.readInt(), ); } @@ -22,6 +25,5 @@ class FavoriteModelBoxAdapter extends TypeAdapter { writer.writeString(obj.name); writer.writeString(obj.image); writer.writeString(obj.type); - writer.writeInt(obj.itemIndex); } } diff --git a/lib/presentation/widgets/misc/orderable_grid.dart b/lib/presentation/widgets/misc/orderable_grid.dart index 1c402ce..a11bfed 100644 --- a/lib/presentation/widgets/misc/orderable_grid.dart +++ b/lib/presentation/widgets/misc/orderable_grid.dart @@ -50,6 +50,7 @@ class _OrderableGridState extends State { style: bigTitleStyle, ), ReorderableBuilder( + enableLongPress: false, scrollController: _scrollController, onReorder: (List orderUpdateEntities) { for (final orderUpdateEntity in orderUpdateEntities) { diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index 314ba1a..e49c6f8 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -91,7 +91,6 @@ class FavoriteState extends ChangeNotifier { item.name, item.image, item.type, - _getLastIndexOfType(item.type), ); } From aa5226a2882ee2ef8a109052852e4dc41e746a6f Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 20:28:35 +0200 Subject: [PATCH 27/32] fixed import --- lib/presentation/screens/bloon/minion_bloon.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/presentation/screens/bloon/minion_bloon.dart b/lib/presentation/screens/bloon/minion_bloon.dart index 2dc5173..3962701 100644 --- a/lib/presentation/screens/bloon/minion_bloon.dart +++ b/lib/presentation/screens/bloon/minion_bloon.dart @@ -4,7 +4,7 @@ import 'package:carousel_slider/carousel_slider.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import '/models/bloons/boss/minion_bloon.dart'; -import '/widgets/bloons/bloon_aid_widget.dart'; +import '/presentation/widgets/bloons/bloon_aid_widget.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/images_url.dart'; From 9675b08eb9c3a2e6035872ef6b947735ef017bc3 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 20:31:17 +0200 Subject: [PATCH 28/32] moved common widgets to common folder --- lib/main.dart | 2 +- lib/presentation/screens/hero/heroes.dart | 2 +- lib/presentation/screens/tower/towers.dart | 2 +- lib/presentation/widgets/bloons/bloons_grid.dart | 2 +- lib/presentation/widgets/bloons/bosses_grid.dart | 2 +- lib/presentation/widgets/{misc => common}/image_outline.dart | 0 lib/presentation/widgets/{misc => common}/loader.dart | 0 7 files changed, 5 insertions(+), 5 deletions(-) rename lib/presentation/widgets/{misc => common}/image_outline.dart (100%) rename lib/presentation/widgets/{misc => common}/loader.dart (100%) diff --git a/lib/main.dart b/lib/main.dart index 742d4ac..bcd14b3 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,7 +16,7 @@ import '/presentation/screens/tower/towers.dart'; import '/presentation/screens/bloon/bloons.dart'; import '/presentation/screens/hero/heroes.dart'; import '/presentation/screens/maps/maps.dart'; -import '/presentation/widgets/misc/loader.dart'; +import 'presentation/widgets/common/loader.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index 3701df4..17d08e8 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -2,7 +2,7 @@ import 'package:provider/provider.dart'; import 'package:flutter/material.dart'; import '/models/base/base_hero.dart'; import '/presentation/widgets/misc/search_widget.dart'; -import '/presentation/widgets/misc/image_outline.dart'; +import '/presentation/widgets/common/image_outline.dart'; import '/presentation/screens/hero/single_hero.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index fd2c07f..e087ee7 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import '/models/base/base_tower.dart'; import '/presentation/screens/tower/single_tower.dart'; import '/presentation/widgets/misc/search_widget.dart'; -import '/presentation/widgets/misc/image_outline.dart'; +import '/presentation/widgets/common/image_outline.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/utilities/favorite_state.dart'; diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index c80a208..e5e59c7 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import '/models/base_model.dart'; -import '/presentation/widgets/misc/image_outline.dart'; +import '/presentation/widgets/common/image_outline.dart'; import '/presentation/screens/bloon/single_bloon.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; diff --git a/lib/presentation/widgets/bloons/bosses_grid.dart b/lib/presentation/widgets/bloons/bosses_grid.dart index 82ab6fc..25b9528 100644 --- a/lib/presentation/widgets/bloons/bosses_grid.dart +++ b/lib/presentation/widgets/bloons/bosses_grid.dart @@ -3,7 +3,7 @@ import 'package:flutter/material.dart'; import '/analytics/analytics_constants.dart'; import '/analytics/analytics.dart'; import '/models/base_model.dart'; -import '/presentation/widgets/misc/image_outline.dart'; +import '/presentation/widgets/common/image_outline.dart'; import '/presentation/screens/bloon/boss_bloon.dart'; import '/utilities/favorite_state.dart'; import '/utilities/images_url.dart'; diff --git a/lib/presentation/widgets/misc/image_outline.dart b/lib/presentation/widgets/common/image_outline.dart similarity index 100% rename from lib/presentation/widgets/misc/image_outline.dart rename to lib/presentation/widgets/common/image_outline.dart diff --git a/lib/presentation/widgets/misc/loader.dart b/lib/presentation/widgets/common/loader.dart similarity index 100% rename from lib/presentation/widgets/misc/loader.dart rename to lib/presentation/widgets/common/loader.dart From 5fe79e43efa08fe52b1a480a8d89835fa6a5370c Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 21:23:54 +0200 Subject: [PATCH 29/32] visual fixes for listtiles in main pages --- lib/presentation/screens/hero/heroes.dart | 59 ++++++++--------- lib/presentation/screens/tower/towers.dart | 63 ++++++++----------- .../widgets/bloons/bloons_grid.dart | 41 +++++++----- lib/utilities/layout_presets.dart | 4 +- 4 files changed, 77 insertions(+), 90 deletions(-) diff --git a/lib/presentation/screens/hero/heroes.dart b/lib/presentation/screens/hero/heroes.dart index 17d08e8..67dbcee 100644 --- a/lib/presentation/screens/hero/heroes.dart +++ b/lib/presentation/screens/hero/heroes.dart @@ -94,41 +94,34 @@ class _HeroesState extends State { context, favoriteState, hero); } }, - child: Stack( - children: [ - Card( - margin: const EdgeInsets.symmetric( - horizontal: 13, vertical: 8), - child: Center( - child: ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8), - horizontalTitleGap: 8, - leading: ImageOutliner( - imageName: hero.image, - imagePath: heroImage(hero.image), - ), - title: Text( - hero.name, - style: constraintsValues[heroTitleStyle], - ), - subtitle: Text( - hero.inGameDesc, - overflow: TextOverflow.ellipsis, - style: constraintsValues[heroSubtitleStyle], - maxLines: constraintsValues[heroSubtitleRows], - ), - ), + child: Card( + margin: const EdgeInsets.symmetric( + horizontal: 13, vertical: 8), + child: Center( + child: ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 8), + horizontalTitleGap: 8, + leading: ImageOutliner( + imageName: hero.image, + imagePath: heroImage(hero.image), ), + title: Text( + hero.name, + style: constraintsValues[heroTitleStyle], + ), + subtitle: Text( + hero.inGameDesc, + overflow: TextOverflow.ellipsis, + style: constraintsValues[heroSubtitleStyle], + maxLines: constraintsValues[heroSubtitleRows], + ), + trailing: + favoriteState.isFavorite(hero.type, hero.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), ), - Positioned( - top: 17, - right: 25, - child: favoriteState.isFavorite(hero.type, hero.id) - ? const Icon(Icons.star) - : const Icon(Icons.star_border_outlined), - ), - ], + ), ), ); }, diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index e087ee7..4ff9010 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -95,46 +95,33 @@ class _TowersState extends State { context, favoriteState, tower); } }, - child: Stack( - alignment: AlignmentDirectional.topEnd, - children: [ - Card( - margin: const EdgeInsets.symmetric( - horizontal: 13, vertical: 8), - child: Center( - child: ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8), - horizontalTitleGap: 8, - minVerticalPadding: -4, - leading: ImageOutliner( - imageName: tower.image, - imagePath: towerImage(tower.image), - width: constraintsValues[towerImageWidth], - ), - title: Text( - tower.name, - style: constraintsValues[towerTitleStyle], - ), - subtitle: Text( - tower.inGameDesc, - overflow: TextOverflow.ellipsis, - maxLines: - constraintsValues[towerSubtitleRows], - style: constraintsValues[towerSubtitleStyle], - ), - ), - ), + child: Card( + margin: const EdgeInsets.symmetric( + horizontal: 13, vertical: 8), + child: ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 8), + horizontalTitleGap: 8, + leading: ImageOutliner( + imageName: tower.image, + imagePath: towerImage(tower.image), + width: constraintsValues[towerImageWidth], + ), + title: Text( + tower.name, + style: constraintsValues[towerTitleStyle], ), - Positioned( - top: 17, - right: 25, - child: - favoriteState.isFavorite(tower.type, tower.id) - ? const Icon(Icons.star) - : const Icon(Icons.star_border_outlined), + subtitle: Text( + tower.inGameDesc, + overflow: TextOverflow.ellipsis, + maxLines: constraintsValues[towerSubtitleRows], + style: constraintsValues[towerSubtitleStyle], ), - ], + trailing: + favoriteState.isFavorite(tower.type, tower.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), + ), ), ); }, diff --git a/lib/presentation/widgets/bloons/bloons_grid.dart b/lib/presentation/widgets/bloons/bloons_grid.dart index e5e59c7..4f80d0c 100644 --- a/lib/presentation/widgets/bloons/bloons_grid.dart +++ b/lib/presentation/widgets/bloons/bloons_grid.dart @@ -37,6 +37,7 @@ class BloonsGrid extends StatelessWidget { return Consumer( builder: (context, favoriteState, child) { return InkWell( + borderRadius: BorderRadius.circular(20), onLongPress: () => favoriteState.toggleFavoriteFunc( context, favoriteState, bloon), onTap: () { @@ -68,23 +69,29 @@ class BloonsGrid extends StatelessWidget { vertical: 3, horizontal: 7, ), - child: Center( - child: ListTile( - titleAlignment: ListTileTitleAlignment.center, - contentPadding: const EdgeInsets.symmetric(horizontal: 8.5), - leading: ImageOutliner( - imageName: bloon.image, - imagePath: bloonImage(bloon.image), - width: constraintsValues[bloonImageWidth], - ), - title: Text( - bloon.name, - maxLines: 1, - style: constraintsValues[bloonTitleStyle], - ), - trailing: favoriteState.isFavorite(bloon.type, bloon.id) - ? const Icon(Icons.star) - : const Icon(Icons.star_border_outlined), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + ImageOutliner( + imageName: bloon.image, + imagePath: bloonImage(bloon.image), + width: constraintsValues[bloonImageWidth], + ), + Center( + child: Text( + bloon.name, + style: constraintsValues[bloonTitleStyle], + ), + ), + Icon( + favoriteState.isFavorite(bloon.type, bloon.id) + ? Icons.star + : Icons.star_border_outlined, + ), + ], ), ), ), diff --git a/lib/utilities/layout_presets.dart b/lib/utilities/layout_presets.dart index 6855f32..f66948f 100644 --- a/lib/utilities/layout_presets.dart +++ b/lib/utilities/layout_presets.dart @@ -20,7 +20,7 @@ Map presetUS = { bloonCrossCount: 2, bloonAspectRatio: 3.0, bloonTitleStyle: smallTitleStyle.copyWith(fontSize: 12.0), - bloonImageWidth: 18.5, + bloonImageWidth: 26.0, // bosses bossCrossCount: 1, bossAspectRatio: 4.3, @@ -55,7 +55,7 @@ Map presetXS = { bloonCrossCount: 2, bloonAspectRatio: 3.0, bloonTitleStyle: smallTitleStyle.copyWith(fontSize: 13.0), - bloonImageWidth: 18.5, + bloonImageWidth: 26.0, // bosses bossCrossCount: 1, bossAspectRatio: 4.3, From fcaaffa59df28f7dc3b1b8da14f99de085668d58 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 21:38:24 +0200 Subject: [PATCH 30/32] center --- lib/presentation/screens/tower/towers.dart | 46 +++++++++++----------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/lib/presentation/screens/tower/towers.dart b/lib/presentation/screens/tower/towers.dart index 4ff9010..744c480 100644 --- a/lib/presentation/screens/tower/towers.dart +++ b/lib/presentation/screens/tower/towers.dart @@ -98,29 +98,31 @@ class _TowersState extends State { child: Card( margin: const EdgeInsets.symmetric( horizontal: 13, vertical: 8), - child: ListTile( - contentPadding: - const EdgeInsets.symmetric(horizontal: 8), - horizontalTitleGap: 8, - leading: ImageOutliner( - imageName: tower.image, - imagePath: towerImage(tower.image), - width: constraintsValues[towerImageWidth], - ), - title: Text( - tower.name, - style: constraintsValues[towerTitleStyle], - ), - subtitle: Text( - tower.inGameDesc, - overflow: TextOverflow.ellipsis, - maxLines: constraintsValues[towerSubtitleRows], - style: constraintsValues[towerSubtitleStyle], + child: Center( + child: ListTile( + contentPadding: + const EdgeInsets.symmetric(horizontal: 8), + horizontalTitleGap: 8, + leading: ImageOutliner( + imageName: tower.image, + imagePath: towerImage(tower.image), + width: constraintsValues[towerImageWidth], + ), + title: Text( + tower.name, + style: constraintsValues[towerTitleStyle], + ), + subtitle: Text( + tower.inGameDesc, + overflow: TextOverflow.ellipsis, + maxLines: constraintsValues[towerSubtitleRows], + style: constraintsValues[towerSubtitleStyle], + ), + trailing: + favoriteState.isFavorite(tower.type, tower.id) + ? const Icon(Icons.star) + : const Icon(Icons.star_border_outlined), ), - trailing: - favoriteState.isFavorite(tower.type, tower.id) - ? const Icon(Icons.star) - : const Icon(Icons.star_border_outlined), ), ), ); From 5c72d7b3f7ffd58917ffb9956acb2c25e38cd783 Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 21:41:30 +0200 Subject: [PATCH 31/32] added the d --- lib/utilities/favorite_state.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utilities/favorite_state.dart b/lib/utilities/favorite_state.dart index e49c6f8..c6e3803 100644 --- a/lib/utilities/favorite_state.dart +++ b/lib/utilities/favorite_state.dart @@ -62,7 +62,7 @@ class FavoriteState extends ChangeNotifier { _favoriteBox.put(favItem.type, typeList); } notifyListeners(); - return addedToFavorites ? 'Added to favorites!' : 'Remove from favorites.'; + return addedToFavorites ? 'Added to favorites!' : 'Removed from favorites.'; } bool isFavorite(String type, String id) { From ad584e1b9a3c206a4f590ac3be93df7fc0c5384e Mon Sep 17 00:00:00 2001 From: Shai Date: Sat, 10 Feb 2024 22:01:43 +0200 Subject: [PATCH 32/32] updated version --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 13b2331..f0cec73 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -17,7 +17,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # In Windows, build-name is used as the major, minor, and patch parts # of the product and file versions while build-number is used as the build suffix. -version: 1.0.17+19 +version: 1.0.17+20 environment: sdk: ">=2.18.5 <4.0.0"