From f39177919ce9d7b2ce8f65da22b0640b8e5cc102 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Sat, 2 Sep 2023 22:29:35 +0200 Subject: [PATCH 1/3] Equipment profiles issues (#112) * Fixed equipment profiles sections collapsing * Fixed range picker dialog * Refined equipment profiles sections handling --- .../widget_dialog_picker_range.dart | 4 +- .../widget_container_equipment_profile.dart | 11 ++- .../screen_equipment_profile.dart | 96 ++++++++++++------- 3 files changed, 70 insertions(+), 41 deletions(-) diff --git a/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/components/dialog_range_picker/widget_dialog_picker_range.dart b/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/components/dialog_range_picker/widget_dialog_picker_range.dart index 24f684a..cc3f4ca 100644 --- a/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/components/dialog_range_picker/widget_dialog_picker_range.dart +++ b/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/components/equipment_profile_container/components/equipment_list_tiles/components/dialog_range_picker/widget_dialog_picker_range.dart @@ -68,8 +68,8 @@ class _DialogRangePickerState extends State widget.onExpand(); _controller.forward(); SchedulerBinding.instance.addPostFrameCallback((_) { - Scrollable.ensureVisible( - context, - alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd, - ); + Future.delayed(_controller.duration!).then((_) { + Scrollable.ensureVisible( + context, + alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd, + duration: _controller.duration!, + ); + }); }); } diff --git a/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/screen_equipment_profile.dart b/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/screen_equipment_profile.dart index 0168608..5307145 100644 --- a/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/screen_equipment_profile.dart +++ b/lib/screens/settings/components/metering/components/equipment_profiles/components/equipment_profile_screen/screen_equipment_profile.dart @@ -17,17 +17,13 @@ class EquipmentProfilesScreen extends StatefulWidget { } class _EquipmentProfilesScreenState extends State { - static const maxProfiles = 5 + 1; // replace with a constant from iap - - late List> profileContainersKeys = []; - int get profilesCount => EquipmentProfiles.of(context).length; + final Map> keysMap = {}; + int get profilesCount => keysMap.length; @override void didChangeDependencies() { super.didChangeDependencies(); - profileContainersKeys = EquipmentProfiles.of(context) - .map((e) => GlobalKey(debugLabel: e.id)) - .toList(); + _updateProfilesKeys(); } @override @@ -35,11 +31,10 @@ class _EquipmentProfilesScreenState extends State { return SliverScreen( title: S.of(context).equipmentProfiles, appBarActions: [ - if (profilesCount < maxProfiles) - IconButton( - onPressed: _addProfile, - icon: const Icon(Icons.add), - ), + IconButton( + onPressed: _addProfile, + icon: const Icon(Icons.add), + ), IconButton( onPressed: Navigator.of(context).pop, icon: const Icon(Icons.close), @@ -55,24 +50,30 @@ class _EquipmentProfilesScreenState extends State { : [ SliverList( delegate: SliverChildBuilderDelegate( - (context, index) => index > 0 // skip default - ? Padding( - padding: EdgeInsets.fromLTRB( - Dimens.paddingM, - index == 0 ? Dimens.paddingM : 0, - Dimens.paddingM, - Dimens.paddingM, - ), - child: EquipmentProfileContainer( - key: profileContainersKeys[index], - data: EquipmentProfiles.of(context)[index], - onExpand: () => _keepExpandedAt(index), - onUpdate: (profileData) => _updateProfileAt(profileData, index), - onDelete: () => _removeProfileAt(index), - ), - ) - : const SizedBox.shrink(), - childCount: profilesCount, + (context, index) { + if (index == 0) { + // skip default profile + return const SizedBox.shrink(); + } + + final profile = EquipmentProfiles.of(context)[index]; + return Padding( + padding: EdgeInsets.fromLTRB( + Dimens.paddingM, + index == 0 ? Dimens.paddingM : 0, + Dimens.paddingM, + Dimens.paddingM, + ), + child: EquipmentProfileContainer( + key: keysMap[profile.id], + data: profile, + onExpand: () => _keepExpandedAt(index), + onUpdate: _updateProfileAt, + onDelete: () => _removeProfileAt(profile), + ), + ); + }, + childCount: EquipmentProfiles.of(context).length, ), ), SliverToBoxAdapter(child: SizedBox(height: MediaQuery.paddingOf(context).bottom)), @@ -91,22 +92,47 @@ class _EquipmentProfilesScreenState extends State { }); } - void _updateProfileAt(EquipmentProfile data, int index) { + void _updateProfileAt(EquipmentProfile data) { EquipmentProfileProvider.of(context).updateProdile(data); } - void _removeProfileAt(int index) { - EquipmentProfileProvider.of(context).deleteProfile(EquipmentProfiles.of(context)[index]); + void _removeProfileAt(EquipmentProfile data) { + EquipmentProfileProvider.of(context).deleteProfile(data); } void _keepExpandedAt(int index) { - profileContainersKeys.getRange(0, index).forEach((element) { + keysMap.values.toList().getRange(0, index).forEach((element) { element.currentState?.collapse(); }); - profileContainersKeys.getRange(index + 1, profilesCount).forEach((element) { + keysMap.values.toList().getRange(index + 1, profilesCount).forEach((element) { element.currentState?.collapse(); }); } + + void _updateProfilesKeys() { + final profiles = EquipmentProfiles.of(context); + if (profiles.length > keysMap.length) { + // profile added + final List idsToAdd = []; + for (final profile in profiles) { + if (!keysMap.keys.contains(profile.id)) idsToAdd.add(profile.id); + } + for (final id in idsToAdd) { + keysMap[id] = GlobalKey(debugLabel: id); + } + idsToAdd.clear(); + } else if (profiles.length < keysMap.length) { + // profile deleted + final List idsToDelete = []; + for (final id in keysMap.keys) { + if (!profiles.any((p) => p.id == id)) idsToDelete.add(id); + } + idsToDelete.forEach(keysMap.remove); + idsToDelete.clear(); + } else { + // profile updated, no need to updated keys + } + } } class _EquipmentProfilesListPlaceholder extends StatelessWidget { From 429c0a53a21438f061555d22e00f2b9ac489d59f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 2 Sep 2023 21:13:17 +0000 Subject: [PATCH 2/3] Version bump --- pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.yaml b/pubspec.yaml index 0a2bfb6..97beb09 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: lightmeter description: Lightmeter app inspired by Material 3 design system. publish_to: "none" -version: 0.13.2+38 +version: 0.14.0+39 environment: sdk: ">=3.0.0 <4.0.0" From 4201d36abb202787691121ea48b3dbb38cde2e09 Mon Sep 17 00:00:00 2001 From: Vadim <44135514+vodemn@users.noreply.github.com> Date: Sun, 3 Sep 2023 13:06:30 +0200 Subject: [PATCH 3/3] Refined launch options --- .gitignore | 2 +- .vscode/launch.json | 66 ++++++++++++++++++++++++++++++------------- README.md | 11 ++++++-- lib/firebase.dart | 22 ++++++++++----- lib/main_prod.dart | 8 +----- lib/main_release.dart | 10 +++++++ 6 files changed, 82 insertions(+), 37 deletions(-) create mode 100644 lib/main_release.dart diff --git a/.gitignore b/.gitignore index ee0aebd..3fd9832 100644 --- a/.gitignore +++ b/.gitignore @@ -57,6 +57,6 @@ keystore.properties android/app/google-services.json ios/firebase_app_id_file.json ios/Runner/GoogleService-Info.plist -lib/firebase_options.dart +/lib/firebase_options.dart coverage/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 6cbc2bc..40dbfac 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,9 +5,10 @@ "version": "0.2.0", "configurations": [ { - "name": "dev (android)", + "name": "dev-debug (android)", "request": "launch", "type": "dart", + "flutterMode": "debug", "args": [ "--flavor", "dev", @@ -17,9 +18,49 @@ "program": "${workspaceFolder}/lib/main_dev.dart", }, { - "name": "dev (ios)", + "name": "dev-profile (android)", "request": "launch", "type": "dart", + "flutterMode": "profile", + "args": [ + "--flavor", + "dev", + "--dart-define", + "cameraPreviewAspectRatio=240/320", + ], + "program": "${workspaceFolder}/lib/main_dev.dart", + }, + { + "name": "prod-debug (android)", + "request": "launch", + "type": "dart", + "flutterMode": "debug", + "args": [ + "--flavor", + "prod", + "--dart-define", + "cameraPreviewAspectRatio=240/320", + ], + "program": "${workspaceFolder}/lib/main_release.dart", + }, + { + "name": "prod-profile (android)", + "request": "launch", + "type": "dart", + "flutterMode": "profile", + "args": [ + "--flavor", + "prod", + "--dart-define", + "cameraPreviewAspectRatio=240/320", + ], + "program": "${workspaceFolder}/lib/main_release.dart", + }, + { + "name": "dev-debug (ios)", + "request": "launch", + "type": "dart", + "flutterMode": "debug", "args": [ "--flavor", "dev", @@ -29,30 +70,17 @@ "program": "${workspaceFolder}/lib/main_dev.dart", }, { - "name": "prod (android)", + "name": "dev-profile (ios)", "request": "launch", - //"flutterMode": "release", + "flutterMode": "profile", "type": "dart", "args": [ "--flavor", - "prod", - "--dart-define", - "cameraPreviewAspectRatio=240/320", - ], - "program": "${workspaceFolder}/lib/main_prod.dart", - }, - { - "name": "prod (ios)", - "request": "launch", - //"flutterMode": "release", - "type": "dart", - "args": [ - "--flavor", - "prod", + "dev", "--dart-define", "cameraPreviewAspectRatio=3/4", ], - "program": "${workspaceFolder}/lib/main_prod.dart", + "program": "${workspaceFolder}/lib/main_dev.dart", }, ], } \ No newline at end of file diff --git a/README.md b/README.md index c4af94a..08e5780 100644 --- a/README.md +++ b/README.md @@ -60,13 +60,18 @@ flutter pub get flutter pub run intl_utils:generate ``` -### 4. Build (Android) +### 4. Build + +#### Android You can build an apk by running the following command from the root of the repository: ```console -flutter build apk --release --flavor $FLAVOR --dart-define cameraPreviewAspectRatio=240/320 -t lib/main_$FLAVOR.dart +flutter build apk --release --flavor dev --dart-define cameraPreviewAspectRatio=240/320 -t lib/main_dev.dart ``` -Just replace `$FLAVOR` with `dev` or `prod`. + +### iOS + +TBD # Contribution diff --git a/lib/firebase.dart b/lib/firebase.dart index f75ae90..0a0e6b0 100644 --- a/lib/firebase.dart +++ b/lib/firebase.dart @@ -1,14 +1,22 @@ +import 'dart:developer'; + import 'package:firebase_core/firebase_core.dart'; import 'package:firebase_crashlytics/firebase_crashlytics.dart'; import 'package:flutter/foundation.dart'; import 'package:lightmeter/firebase_options.dart'; -Future initializeFirebase() async { - await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); - FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError; - PlatformDispatcher.instance.onError = (error, stack) { - FirebaseCrashlytics.instance.recordError(error, stack, fatal: true); - return true; - }; +Future initializeFirebase({required bool handleErrors}) async { + try { + await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform); + if (handleErrors) { + FlutterError.onError = FirebaseCrashlytics.instance.recordFlutterFatalError; + PlatformDispatcher.instance.onError = (error, stack) { + FirebaseCrashlytics.instance.recordError(error, stack, fatal: true); + return true; + }; + } + } catch (e) { + log(e.toString()); + } } diff --git a/lib/main_prod.dart b/lib/main_prod.dart index fc1700a..2ccc397 100644 --- a/lib/main_prod.dart +++ b/lib/main_prod.dart @@ -1,5 +1,3 @@ -import 'dart:developer'; - import 'package:flutter/material.dart'; import 'package:lightmeter/application.dart'; import 'package:lightmeter/environment.dart'; @@ -7,10 +5,6 @@ import 'package:lightmeter/firebase.dart'; Future main() async { WidgetsFlutterBinding.ensureInitialized(); - try { - await initializeFirebase(); - } catch (e) { - log(e.toString()); - } + await initializeFirebase(handleErrors: true); runApp(const Application(Environment.prod())); } diff --git a/lib/main_release.dart b/lib/main_release.dart new file mode 100644 index 0000000..b87dff8 --- /dev/null +++ b/lib/main_release.dart @@ -0,0 +1,10 @@ +import 'package:flutter/material.dart'; +import 'package:lightmeter/application.dart'; +import 'package:lightmeter/environment.dart'; +import 'package:lightmeter/firebase.dart'; + +Future main() async { + WidgetsFlutterBinding.ensureInitialized(); + await initializeFirebase(handleErrors: false); + runApp(const Application(Environment.prod())); +}