mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2024-11-21 15:00:40 +00:00
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:
parent
2128e7c2e9
commit
bfd0bfe531
23 changed files with 31 additions and 52 deletions
2
.github/workflows/build_apk.yml
vendored
2
.github/workflows/build_apk.yml
vendored
|
@ -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: |
|
||||||
|
|
2
.github/workflows/build_ipa.yml
vendored
2
.github/workflows/build_ipa.yml
vendored
|
@ -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: |
|
||||||
|
|
2
.github/workflows/pr_check.yml
vendored
2
.github/workflows/pr_check.yml
vendored
|
@ -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: |
|
||||||
|
|
2
.github/workflows/run_integration_tests.yml
vendored
2
.github/workflows/run_integration_tests.yml
vendored
|
@ -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: |
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
);
|
);
|
||||||
|
|
|
@ -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,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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: '',
|
||||||
|
|
|
@ -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:
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,7 +117,7 @@ class _CameraPreviewBuilderState extends State<_CameraPreviewBuilder> {
|
||||||
context,
|
context,
|
||||||
CameraFeature.spotMetering,
|
CameraFeature.spotMetering,
|
||||||
))
|
))
|
||||||
CameraSpotDetector(onSpotTap: widget.onSpotTap)
|
CameraSpotDetector(onSpotTap: widget.onSpotTap),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
|
@ -97,7 +97,7 @@ class CameraContainer extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class MeteringTopBar extends StatelessWidget {
|
||||||
child: preview,
|
child: preview,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
]
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -92,7 +92,7 @@ class _ReadingValueBuilder extends StatelessWidget {
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
softWrap: false,
|
softWrap: false,
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ class _CalibrationUnit extends StatelessWidget {
|
||||||
tooltip: S.of(context).tooltipResetToZero,
|
tooltip: S.of(context).tooltipResetToZero,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -135,7 +135,7 @@ class _DialogFilterState<T> extends State<DialogFilter<T>> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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}'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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');
|
||||||
|
|
Loading…
Reference in a new issue