ML-108 First exposure metering seems to be wrong (#163)

* use latest `camera_android_camerax`

* fixed trailing commas

* moved ci/cd to 3.13.9

* removed focus & exposure fix

* fixed camera not being initialized on Android

* removed unused import
This commit is contained in:
Vadim 2024-04-06 19:14:37 +02:00 committed by GitHub
parent 2128e7c2e9
commit bfd0bfe531
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 31 additions and 52 deletions

View file

@ -113,7 +113,7 @@ jobs:
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.10.0" flutter-version: "3.13.9"
- name: Prepare flutter project - name: Prepare flutter project
run: | run: |

View file

@ -108,7 +108,7 @@ jobs:
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.10.0" flutter-version: "3.13.9"
- name: Prepare flutter project - name: Prepare flutter project
run: | run: |

View file

@ -42,7 +42,7 @@ jobs:
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.10.0" flutter-version: "3.13.9"
- name: Prepare flutter project - name: Prepare flutter project
run: | run: |

View file

@ -31,7 +31,7 @@ jobs:
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.10.0" flutter-version: "3.13.9"
- name: Prepare app - name: Prepare app
run: | run: |

View file

@ -34,7 +34,7 @@ Without further delay behold my new Lightmeter app inspired by Material You (a.k
### 1. Install Flutter ### 1. Install Flutter
To build this app you need to install Flutter 3.10.0 stable. [How to install](https://docs.flutter.dev/get-started/install). To build this app you need to install Flutter 3.13.9 stable. [How to install](https://docs.flutter.dev/get-started/install).
### 2. Project setup ### 2. Project setup

View file

@ -27,7 +27,7 @@ class MockIAPProductsProviderState extends State<MockIAPProductsProvider> {
IAPProduct( IAPProduct(
storeId: IAPProductType.paidFeatures.storeId, storeId: IAPProductType.paidFeatures.storeId,
status: _purchased ? IAPProductStatus.purchased : IAPProductStatus.purchasable, status: _purchased ? IAPProductStatus.purchased : IAPProductStatus.purchasable,
) ),
]), ]),
child: widget.child, child: widget.child,
); );

View file

@ -23,7 +23,7 @@ extension MeteringScreenLayoutConfigJson on MeteringScreenLayoutConfig {
return <MeteringScreenLayoutFeature, bool>{ return <MeteringScreenLayoutFeature, bool>{
for (final f in MeteringScreenLayoutFeature.values) for (final f in MeteringScreenLayoutFeature.values)
f: (data[migratedIndex(f).toString()] ?? data[f.name]) as bool? ?? true f: (data[migratedIndex(f).toString()] ?? data[f.name]) as bool? ?? true,
}; };
} }

View file

@ -50,7 +50,6 @@ class DefaultFirebaseOptions {
static const FirebaseOptions android = FirebaseOptions( static const FirebaseOptions android = FirebaseOptions(
apiKey: '', apiKey: '',
appId: '',
messagingSenderId: '', messagingSenderId: '',
projectId: '', projectId: '',
storageBucket: '', storageBucket: '',

View file

@ -4,7 +4,6 @@ import 'dart:io';
import 'dart:math' as math; import 'dart:math' as math;
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
@ -217,15 +216,9 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
Future<double?> _takePhoto() async { Future<double?> _takePhoto() async {
try { try {
// https://github.com/flutter/flutter/issues/84957#issuecomment-1661155095
await _cameraController!.setFocusMode(FocusMode.locked);
await _cameraController!.setExposureMode(ExposureMode.locked);
final file = await _cameraController!.takePicture(); final file = await _cameraController!.takePicture();
await _cameraController!.setFocusMode(FocusMode.auto);
await _cameraController!.setExposureMode(ExposureMode.auto);
final bytes = await file.readAsBytes(); final bytes = await file.readAsBytes();
Directory(file.path).deleteSync(recursive: true); Directory(file.path).deleteSync(recursive: true);
return await evFromImage(bytes); return await evFromImage(bytes);
} catch (e, stackTrace) { } catch (e, stackTrace) {
_analytics.logCrash(e, stackTrace); _analytics.logCrash(e, stackTrace);
@ -257,18 +250,6 @@ class _WidgetsBindingObserver with WidgetsBindingObserver {
/// Revoking camera permissions results in app being killed both on Android and iOS /// Revoking camera permissions results in app being killed both on Android and iOS
@override @override
void didChangeAppLifecycleState(AppLifecycleState state) { void didChangeAppLifecycleState(AppLifecycleState state) {
switch (defaultTargetPlatform) {
/// On Android opening a dialog results in [AppLifecycleState.inactive]
case TargetPlatform.android:
if (_prevState == AppLifecycleState.inactive && state == AppLifecycleState.resumed) {
return;
}
_prevState = state;
onLifecycleStateChanged(state);
/// When coming from the app's settings iOS fires paused -> inactive -> resumed state which falls into this condition.
/// So the inactive state is skipped.
case TargetPlatform.iOS:
if (state == AppLifecycleState.inactive) { if (state == AppLifecycleState.inactive) {
return; return;
} }
@ -276,7 +257,5 @@ class _WidgetsBindingObserver with WidgetsBindingObserver {
_prevState = state; _prevState = state;
onLifecycleStateChanged(state); onLifecycleStateChanged(state);
} }
default:
}
} }
} }

View file

@ -117,7 +117,7 @@ class _CameraPreviewBuilderState extends State<_CameraPreviewBuilder> {
context, context,
CameraFeature.spotMetering, CameraFeature.spotMetering,
)) ))
CameraSpotDetector(onSpotTap: widget.onSpotTap) CameraSpotDetector(onSpotTap: widget.onSpotTap),
], ],
], ],
) )

View file

@ -97,7 +97,7 @@ class CameraContainer extends StatelessWidget {
), ),
], ],
), ),
) ),
], ],
); );
} }

View file

@ -42,7 +42,7 @@ class MeteringTopBar extends StatelessWidget {
child: preview, child: preview,
), ),
), ),
] ],
], ],
), ),
), ),

View file

@ -92,7 +92,7 @@ class _ReadingValueBuilder extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
softWrap: false, softWrap: false,
), ),
) ),
], ],
); );
} }

View file

@ -120,7 +120,7 @@ class _CalibrationUnit extends StatelessWidget {
tooltip: S.of(context).tooltipResetToZero, tooltip: S.of(context).tooltipResetToZero,
), ),
], ],
) ),
], ],
); );
} }

View file

@ -41,7 +41,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
SliverFillRemaining( SliverFillRemaining(
hasScrollBody: false, hasScrollBody: false,
child: _EquipmentProfilesListPlaceholder(onTap: _addProfile), child: _EquipmentProfilesListPlaceholder(onTap: _addProfile),
) ),
] ]
: [ : [
SliverList( SliverList(

View file

@ -135,7 +135,7 @@ class _DialogFilterState<T> extends State<DialogFilter<T>> {
), ),
], ],
), ),
) ),
], ],
), ),
), ),

View file

@ -51,7 +51,7 @@ class _DialogSwitchState<T> extends State<DialogSwitch<T>> {
padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL), padding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL),
child: Text(widget.description!), child: Text(widget.description!),
), ),
const SizedBox(height: Dimens.grid16) const SizedBox(height: Dimens.grid16),
], ],
ListView( ListView(
shrinkWrap: true, shrinkWrap: true,

View file

@ -10,6 +10,7 @@ dependencies:
app_settings: 4.2.0 app_settings: 4.2.0
bloc_concurrency: 0.2.2 bloc_concurrency: 0.2.2
camera: 0.10.5+2 camera: 0.10.5+2
camera_android_camerax: 0.6.1+1
clipboard: 0.1.3 clipboard: 0.1.3
dynamic_color: 1.6.6 dynamic_color: 1.6.6
exif: 3.1.4 exif: 3.1.4
@ -22,7 +23,7 @@ dependencies:
flutter_bloc: 8.1.3 flutter_bloc: 8.1.3
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
intl: 0.18.0 intl: 0.18.1
intl_utils: 2.8.2 intl_utils: 2.8.2
light_sensor: 3.0.0 light_sensor: 3.0.0
m3_lightmeter_iap: m3_lightmeter_iap:
@ -33,7 +34,7 @@ dependencies:
git: git:
url: "https://github.com/vodemn/m3_lightmeter_resources" url: "https://github.com/vodemn/m3_lightmeter_resources"
ref: main ref: main
material_color_utilities: 0.2.0 material_color_utilities: 0.5.0
package_info_plus: 4.0.2 package_info_plus: 4.0.2
permission_handler: 10.4.3 permission_handler: 10.4.3
platform: 3.1.0 platform: 3.1.0
@ -54,7 +55,7 @@ dev_dependencies:
lint: 2.1.2 lint: 2.1.2
meta: 1.9.1 meta: 1.9.1
mocktail: 0.3.0 mocktail: 0.3.0
test: 1.24.1 test: 1.24.3
flutter: flutter:
uses-material-design: true uses-material-design: true

View file

@ -26,7 +26,7 @@ void main() {
IAPProduct( IAPProduct(
storeId: IAPProductType.paidFeatures.storeId, storeId: IAPProductType.paidFeatures.storeId,
status: productStatus, status: productStatus,
) ),
], ],
child: FilmsProvider( child: FilmsProvider(
storageService: mockIAPStorageService, storageService: mockIAPStorageService,

View file

@ -317,7 +317,7 @@ void main() {
onPressed: () => UserPreferencesProvider.of(context).setThemeType(ThemeType.dark), onPressed: () => UserPreferencesProvider.of(context).setThemeType(ThemeType.dark),
child: Text('${UserPreferencesProvider.themeTypeOf(context)}'), child: Text('${UserPreferencesProvider.themeTypeOf(context)}'),
), ),
Text('${Theme.of(context).colorScheme.brightness}') Text('${Theme.of(context).colorScheme.brightness}'),
], ],
), ),
); );
@ -344,7 +344,7 @@ void main() {
onPressed: () => UserPreferencesProvider.of(context).setThemeType(ThemeType.systemDefault), onPressed: () => UserPreferencesProvider.of(context).setThemeType(ThemeType.systemDefault),
child: Text('${UserPreferencesProvider.themeTypeOf(context)}'), child: Text('${UserPreferencesProvider.themeTypeOf(context)}'),
), ),
Text('${Theme.of(context).colorScheme.brightness}') Text('${Theme.of(context).colorScheme.brightness}'),
], ],
), ),
); );

View file

@ -28,7 +28,7 @@ void main() {
IAPProduct( IAPProduct(
storeId: IAPProductType.paidFeatures.storeId, storeId: IAPProductType.paidFeatures.storeId,
status: IAPProductStatus.purchased, status: IAPProductStatus.purchased,
) ),
], ],
child: EquipmentProfileProvider( child: EquipmentProfileProvider(
storageService: mockIAPStorageService, storageService: mockIAPStorageService,

View file

@ -27,7 +27,7 @@ void main() {
IAPProduct( IAPProduct(
storeId: IAPProductType.paidFeatures.storeId, storeId: IAPProductType.paidFeatures.storeId,
status: IAPProductStatus.purchased, status: IAPProductStatus.purchased,
) ),
], ],
child: FilmsProvider( child: FilmsProvider(
storageService: mockIAPStorageService, storageService: mockIAPStorageService,

View file

@ -26,7 +26,7 @@ Future<void> grantCameraPermission() async {
'pm', 'pm',
'grant', 'grant',
'com.vodemn.lightmeter.dev', 'com.vodemn.lightmeter.dev',
'android.permission.CAMERA' 'android.permission.CAMERA',
]); ]);
} catch (e) { } catch (e) {
log('Error occured: $e'); log('Error occured: $e');