mirror of
https://github.com/vodemn/m3_lightmeter.git
synced 2025-07-04 13:10:42 +00:00
Compare commits
12 commits
c40bcf51f5
...
2a7dad2c38
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2a7dad2c38 | ||
![]() |
2ee4d3ef53 | ||
![]() |
9a2ef35eed | ||
![]() |
cd752aaf89 | ||
![]() |
b614af9a97 | ||
![]() |
85b84000ae | ||
![]() |
43989e5e5f | ||
![]() |
8ecab836a3 | ||
![]() |
2439f7bfff | ||
![]() |
bccd68f1ff | ||
![]() |
5e8f66d75c | ||
![]() |
75dc9aaf13 |
13 changed files with 147 additions and 170 deletions
4
.github/workflows/build_apk.yml
vendored
4
.github/workflows/build_apk.yml
vendored
|
@ -115,7 +115,7 @@ jobs:
|
||||||
|
|
||||||
- name: Download release notes
|
- name: Download release notes
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||||
path: ${{ env.RELEASE_NOTES_PATH }}
|
path: ${{ env.RELEASE_NOTES_PATH }}
|
||||||
|
@ -136,7 +136,7 @@ jobs:
|
||||||
run: flutter build ${{ inputs.binary-type }} $BUILD_ARGS
|
run: flutter build ${{ inputs.binary-type }} $BUILD_ARGS
|
||||||
|
|
||||||
- name: Upload ${{ inputs.binary-type }} to artifacts
|
- name: Upload ${{ inputs.binary-type }} to artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: m3_lightmeter_${{ inputs.binary-type }}
|
name: m3_lightmeter_${{ inputs.binary-type }}
|
||||||
path: ${{ inputs.binary-type == 'apk' && env.BUILD_APK_PATH || env.BUILD_AAB_PATH }}
|
path: ${{ inputs.binary-type == 'apk' && env.BUILD_APK_PATH || env.BUILD_AAB_PATH }}
|
||||||
|
|
4
.github/workflows/build_ipa.yml
vendored
4
.github/workflows/build_ipa.yml
vendored
|
@ -108,7 +108,7 @@ jobs:
|
||||||
|
|
||||||
- name: Download release notes
|
- name: Download release notes
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||||
path: ${{ env.RELEASE_NOTES_PATH }}
|
path: ${{ env.RELEASE_NOTES_PATH }}
|
||||||
|
@ -135,7 +135,7 @@ jobs:
|
||||||
--export-options-plist=ios/Runner/ExportOptions.plist
|
--export-options-plist=ios/Runner/ExportOptions.plist
|
||||||
|
|
||||||
- name: Upload artifact
|
- name: Upload artifact
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: m3_lightmeter_ipa
|
name: m3_lightmeter_ipa
|
||||||
path: build/ios/ipa/lightmeter.ipa
|
path: build/ios/ipa/lightmeter.ipa
|
||||||
|
|
40
.github/workflows/create_release.yml
vendored
40
.github/workflows/create_release.yml
vendored
|
@ -27,6 +27,16 @@ on:
|
||||||
required: true
|
required: true
|
||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
|
deploy-ios:
|
||||||
|
description: "Publish to App Store"
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
deploy-android:
|
||||||
|
description: "Publish to Google Play"
|
||||||
|
required: true
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
release-track:
|
release-track:
|
||||||
description: "Release track"
|
description: "Release track"
|
||||||
type: choice
|
type: choice
|
||||||
|
@ -59,7 +69,7 @@ jobs:
|
||||||
echo ${{ inputs.release-notes }} > ${{ env.RELEASE_NOTES_FILE }}
|
echo ${{ inputs.release-notes }} > ${{ env.RELEASE_NOTES_FILE }}
|
||||||
perl -i -pe 's/\s{1}(-{1})/\n$1/g' ${{ env.RELEASE_NOTES_FILE }}
|
perl -i -pe 's/\s{1}(-{1})/\n$1/g' ${{ env.RELEASE_NOTES_FILE }}
|
||||||
- name: Upload merged_native_libs.zip to artifacts
|
- name: Upload merged_native_libs.zip to artifacts
|
||||||
uses: actions/upload-artifact@v3
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||||
path: ${{ env.RELEASE_NOTES_FILE }}
|
path: ${{ env.RELEASE_NOTES_FILE }}
|
||||||
|
@ -67,7 +77,7 @@ jobs:
|
||||||
build-android:
|
build-android:
|
||||||
name: Build Android
|
name: Build Android
|
||||||
needs: [generate-release-notes]
|
needs: [generate-release-notes]
|
||||||
if: ${{ always() && !failure() && !cancelled() }}
|
if: ${{ always() && !failure() && !cancelled() && inputs.deploy-android }}
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
binary-type: [apk, appbundle]
|
binary-type: [apk, appbundle]
|
||||||
|
@ -82,7 +92,7 @@ jobs:
|
||||||
build-ios:
|
build-ios:
|
||||||
name: Build iOS
|
name: Build iOS
|
||||||
needs: [generate-release-notes]
|
needs: [generate-release-notes]
|
||||||
if: ${{ always() && !failure() && !cancelled() }}
|
if: ${{ always() && !failure() && !cancelled() && inputs.deploy-ios }}
|
||||||
uses: ./.github/workflows/build_ipa.yml
|
uses: ./.github/workflows/build_ipa.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
with:
|
with:
|
||||||
|
@ -92,7 +102,7 @@ jobs:
|
||||||
create-github-release:
|
create-github-release:
|
||||||
name: Create Github release
|
name: Create Github release
|
||||||
needs: [build-android, build-ios]
|
needs: [build-android, build-ios]
|
||||||
if: ${{ always() && !failure() && !cancelled() }}
|
if: ${{ always() && !cancelled() && inputs.deploy-android}}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
|
@ -102,24 +112,24 @@ jobs:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Download apk
|
- name: Download apk
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: m3_lightmeter_apk
|
name: m3_lightmeter_apk
|
||||||
|
|
||||||
- name: Increment build number & replace version number
|
|
||||||
run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }}
|
|
||||||
|
|
||||||
- name: Download release notes
|
- name: Download release notes
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||||
path: ${{ env.RELEASE_NOTES_PATH }}
|
path: ${{ env.RELEASE_NOTES_PATH }}
|
||||||
|
|
||||||
|
- name: Increment build number & replace version number
|
||||||
|
run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }}
|
||||||
|
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
run: |
|
run: |
|
||||||
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
git config --local user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
git config --local user.name "github-actions[bot]"
|
git config --local user.name "github-actions[bot]"
|
||||||
git add -A
|
git add --all -- ":!app-prod-release.apk"
|
||||||
git commit -m "Release v${{ inputs.version }}"
|
git commit -m "Release v${{ inputs.version }}"
|
||||||
|
|
||||||
- name: Push to main
|
- name: Push to main
|
||||||
|
@ -143,7 +153,7 @@ jobs:
|
||||||
create-google-play-release:
|
create-google-play-release:
|
||||||
name: Create Google Play release
|
name: Create Google Play release
|
||||||
needs: [build-android, build-ios]
|
needs: [build-android, build-ios]
|
||||||
if: ${{ always() && !failure() && !cancelled() }}
|
if: ${{ always() && !failure() && !cancelled() && inputs.deploy-android }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
@ -151,7 +161,7 @@ jobs:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Download app bundle
|
- name: Download app bundle
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: m3_lightmeter_appbundle
|
name: m3_lightmeter_appbundle
|
||||||
|
|
||||||
|
@ -161,7 +171,7 @@ jobs:
|
||||||
(cd base/lib && zip -r "$OLDPWD/merged_native_libs.zip" .)
|
(cd base/lib && zip -r "$OLDPWD/merged_native_libs.zip" .)
|
||||||
|
|
||||||
- name: Download release notes
|
- name: Download release notes
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||||
|
|
||||||
|
@ -195,7 +205,7 @@ jobs:
|
||||||
upload-to-app-store:
|
upload-to-app-store:
|
||||||
name: Upload to App Store
|
name: Upload to App Store
|
||||||
needs: [build-android, build-ios]
|
needs: [build-android, build-ios]
|
||||||
if: ${{ always() && !failure() && !cancelled() }}
|
if: ${{ always() && !failure() && !cancelled() && inputs.deploy-ios }}
|
||||||
runs-on: macos-13
|
runs-on: macos-13
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v3
|
||||||
|
@ -203,7 +213,7 @@ jobs:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
|
||||||
- name: Download ipa
|
- name: Download ipa
|
||||||
uses: actions/download-artifact@v3
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: m3_lightmeter_ipa
|
name: m3_lightmeter_ipa
|
||||||
|
|
||||||
|
|
65
.github/workflows/pr_check.yml
vendored
65
.github/workflows/pr_check.yml
vendored
|
@ -36,8 +36,10 @@ jobs:
|
||||||
if: steps.fetch-iap.conclusion != 'success'
|
if: steps.fetch-iap.conclusion != 'success'
|
||||||
run: bash ./.github/scripts/stub_iap.sh
|
run: bash ./.github/scripts/stub_iap.sh
|
||||||
|
|
||||||
- name: Restore constants.dart
|
- name: Restore secrets
|
||||||
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.CONSTANTS }}" "lib/constants.dart"
|
run: |
|
||||||
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.CONSTANTS }}" "lib/constants.dart"
|
||||||
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_OPTIONS }}" "lib/firebase_options.dart"
|
||||||
|
|
||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
|
@ -64,3 +66,62 @@ jobs:
|
||||||
bash ./.github/scripts/stub_iap.sh
|
bash ./.github/scripts/stub_iap.sh
|
||||||
flutter pub get
|
flutter pub get
|
||||||
flutter analyze lib --fatal-infos
|
flutter analyze lib --fatal-infos
|
||||||
|
|
||||||
|
platform-changes:
|
||||||
|
name: Checks for platform changes
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
android-changed: ${{ steps.platform-changes.outputs.android-changed }}
|
||||||
|
ios-changed: ${{ steps.platform-changes.outputs.ios-changed }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- id: platform-changes
|
||||||
|
uses: dorny/paths-filter@v2
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
android-changed:
|
||||||
|
- 'android/**'
|
||||||
|
- 'pubspec.yaml'
|
||||||
|
ios-changed:
|
||||||
|
- 'ios/**'
|
||||||
|
- 'pubspec.yaml'
|
||||||
|
|
||||||
|
build-android:
|
||||||
|
name: Build Android
|
||||||
|
needs: platform-changes
|
||||||
|
if: needs.platform-changes.outputs.android-changed == 'true'
|
||||||
|
uses: ./.github/workflows/build_apk.yml
|
||||||
|
secrets: inherit
|
||||||
|
with:
|
||||||
|
binary-type: apk
|
||||||
|
flavor: prod
|
||||||
|
stage-backend: false
|
||||||
|
version: "1.0.0"
|
||||||
|
|
||||||
|
build-ios:
|
||||||
|
name: Build iOS
|
||||||
|
needs: platform-changes
|
||||||
|
if: needs.platform-changes.outputs.ios-changed == 'true'
|
||||||
|
uses: ./.github/workflows/build_ipa.yml
|
||||||
|
secrets: inherit
|
||||||
|
with:
|
||||||
|
stage-backend: false
|
||||||
|
version: "1.0.0"
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
name: Cleanup
|
||||||
|
if: ${{ always() }}
|
||||||
|
needs: [build-android, build-ios]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Delete release artifacts
|
||||||
|
uses: geekyeggo/delete-artifact@v2
|
||||||
|
with:
|
||||||
|
failOnError: false
|
||||||
|
name: |
|
||||||
|
m3_lightmeter_apk
|
||||||
|
m3_lightmeter_appbundle
|
||||||
|
m3_lightmeter_ipa
|
||||||
|
|
3
.github/workflows/run_integration_tests.yml
vendored
3
.github/workflows/run_integration_tests.yml
vendored
|
@ -27,8 +27,9 @@ jobs:
|
||||||
bash .github/scripts/restore_from_base64.sh "${{ secrets.CONSTANTS }}" "lib/constants.dart"
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.CONSTANTS }}" "lib/constants.dart"
|
||||||
bash .github/scripts/restore_from_base64.sh "${{ secrets.GOOGLE_SERVICES_JSON_IOS }}" "ios/Runner/GoogleService-Info.plist"
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.GOOGLE_SERVICES_JSON_IOS }}" "ios/Runner/GoogleService-Info.plist"
|
||||||
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_APP_ID_FILE }}" "ios/firebase_app_id_file.json"
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_APP_ID_FILE }}" "ios/firebase_app_id_file.json"
|
||||||
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_OPTIONS }}" "lib/firebase_options.dart"
|
||||||
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_JSON }}" "firebase.json"
|
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_JSON }}" "firebase.json"
|
||||||
|
|
||||||
- uses: subosito/flutter-action@v2
|
- uses: subosito/flutter-action@v2
|
||||||
with:
|
with:
|
||||||
channel: "stable"
|
channel: "stable"
|
||||||
|
|
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -58,8 +58,8 @@ keystore.properties
|
||||||
android/app/google-services.json
|
android/app/google-services.json
|
||||||
ios/firebase_app_id_file.json
|
ios/firebase_app_id_file.json
|
||||||
ios/Runner/GoogleService-Info.plist
|
ios/Runner/GoogleService-Info.plist
|
||||||
/lib/firebase_options.dart
|
lib/firebase_options.dart
|
||||||
/lib/constants.dart
|
lib/constants.dart
|
||||||
|
|
||||||
coverage/
|
coverage/
|
||||||
test/coverage_helper_test.dart
|
test/coverage_helper_test.dart
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx2048M
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
||||||
android.defaults.buildfeatures.buildconfig=true
|
android.defaults.buildfeatures.buildconfig=true
|
||||||
|
|
1
assets/release_notes/release_notes_en_1.0.1.md
Normal file
1
assets/release_notes/release_notes_en_1.0.1.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
- Performance improvements and bug fixes.
|
|
@ -1,67 +0,0 @@
|
||||||
// File generated by FlutterFire CLI.
|
|
||||||
// ignore_for_file: lines_longer_than_80_chars, avoid_classes_with_only_static_members
|
|
||||||
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
|
|
||||||
import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb, TargetPlatform;
|
|
||||||
|
|
||||||
/// Default [FirebaseOptions] for use with your Firebase apps.
|
|
||||||
///
|
|
||||||
/// Example:
|
|
||||||
/// ```dart
|
|
||||||
/// import 'firebase_options.dart';
|
|
||||||
/// // ...
|
|
||||||
/// await Firebase.initializeApp(
|
|
||||||
/// options: DefaultFirebaseOptions.currentPlatform,
|
|
||||||
/// );
|
|
||||||
/// ```
|
|
||||||
class DefaultFirebaseOptions {
|
|
||||||
static FirebaseOptions get currentPlatform {
|
|
||||||
if (kIsWeb) {
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for web - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
switch (defaultTargetPlatform) {
|
|
||||||
case TargetPlatform.android:
|
|
||||||
return android;
|
|
||||||
case TargetPlatform.iOS:
|
|
||||||
return ios;
|
|
||||||
case TargetPlatform.macOS:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for macos - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
case TargetPlatform.windows:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for windows - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
case TargetPlatform.linux:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions have not been configured for linux - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
default:
|
|
||||||
throw UnsupportedError(
|
|
||||||
'DefaultFirebaseOptions are not supported for this platform.',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const FirebaseOptions android = FirebaseOptions(
|
|
||||||
apiKey: '',
|
|
||||||
messagingSenderId: '',
|
|
||||||
projectId: '',
|
|
||||||
storageBucket: '',
|
|
||||||
);
|
|
||||||
|
|
||||||
static const FirebaseOptions ios = FirebaseOptions(
|
|
||||||
apiKey: '',
|
|
||||||
appId: '',
|
|
||||||
messagingSenderId: '',
|
|
||||||
projectId: '',
|
|
||||||
storageBucket: '',
|
|
||||||
iosClientId: '',
|
|
||||||
iosBundleId: '',
|
|
||||||
);
|
|
||||||
}
|
|
|
@ -132,6 +132,7 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
|
||||||
|
|
||||||
await _cameraController!.initialize();
|
await _cameraController!.initialize();
|
||||||
await _cameraController!.setFlashMode(FlashMode.off);
|
await _cameraController!.setFlashMode(FlashMode.off);
|
||||||
|
await _cameraController!.lockCaptureOrientation(DeviceOrientation.portraitUp);
|
||||||
|
|
||||||
_zoomRange = await Future.wait<double>([
|
_zoomRange = await Future.wait<double>([
|
||||||
_cameraController!.getMinZoomLevel(),
|
_cameraController!.getMinZoomLevel(),
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
import 'package:camera/camera.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
|
|
||||||
class CameraView extends StatelessWidget {
|
|
||||||
final CameraController controller;
|
|
||||||
|
|
||||||
const CameraView({required this.controller, super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final value = controller.value;
|
|
||||||
return ValueListenableBuilder<CameraValue>(
|
|
||||||
valueListenable: controller,
|
|
||||||
builder: (_, __, Widget? child) => AspectRatio(
|
|
||||||
aspectRatio: _isLandscape(value) ? value.aspectRatio : (1 / value.aspectRatio),
|
|
||||||
child: Stack(
|
|
||||||
children: [
|
|
||||||
RotatedBox(
|
|
||||||
quarterTurns: _getQuarterTurns(value),
|
|
||||||
child: controller.buildPreview(),
|
|
||||||
),
|
|
||||||
child ?? const SizedBox(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool _isLandscape(CameraValue value) {
|
|
||||||
return <DeviceOrientation>[DeviceOrientation.landscapeLeft, DeviceOrientation.landscapeRight]
|
|
||||||
.contains(_getApplicableOrientation(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
int _getQuarterTurns(CameraValue value) {
|
|
||||||
final Map<DeviceOrientation, int> turns = <DeviceOrientation, int>{
|
|
||||||
DeviceOrientation.portraitUp: 0,
|
|
||||||
DeviceOrientation.landscapeRight: 1,
|
|
||||||
DeviceOrientation.portraitDown: 2,
|
|
||||||
DeviceOrientation.landscapeLeft: 3,
|
|
||||||
};
|
|
||||||
return turns[_getApplicableOrientation(value)]!;
|
|
||||||
}
|
|
||||||
|
|
||||||
DeviceOrientation _getApplicableOrientation(CameraValue value) {
|
|
||||||
return value.isRecordingVideo
|
|
||||||
? value.recordingOrientation!
|
|
||||||
: (value.previewPauseOrientation ?? value.lockedCaptureOrientation ?? value.deviceOrientation);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,18 +1,17 @@
|
||||||
import 'package:camera/camera.dart';
|
import 'package:camera/camera.dart' as camera;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:lightmeter/data/models/camera_feature.dart';
|
import 'package:lightmeter/data/models/camera_feature.dart';
|
||||||
import 'package:lightmeter/platform_config.dart';
|
import 'package:lightmeter/platform_config.dart';
|
||||||
import 'package:lightmeter/providers/user_preferences_provider.dart';
|
import 'package:lightmeter/providers/user_preferences_provider.dart';
|
||||||
import 'package:lightmeter/res/dimens.dart';
|
import 'package:lightmeter/res/dimens.dart';
|
||||||
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_spot_detector/widget_camera_spot_detector.dart';
|
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_spot_detector/widget_camera_spot_detector.dart';
|
||||||
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view/widget_camera_view.dart';
|
|
||||||
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view_placeholder/widget_placeholder_camera_view.dart';
|
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/camera_view_placeholder/widget_placeholder_camera_view.dart';
|
||||||
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/histogram/widget_histogram.dart';
|
import 'package:lightmeter/screens/metering/components/camera_container/components/camera_preview/components/histogram/widget_histogram.dart';
|
||||||
import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart';
|
import 'package:lightmeter/screens/metering/components/camera_container/models/camera_error_type.dart';
|
||||||
import 'package:lightmeter/utils/context_utils.dart';
|
import 'package:lightmeter/utils/context_utils.dart';
|
||||||
|
|
||||||
class CameraPreview extends StatefulWidget {
|
class CameraPreview extends StatefulWidget {
|
||||||
final CameraController? controller;
|
final camera.CameraController? controller;
|
||||||
final CameraErrorType? error;
|
final CameraErrorType? error;
|
||||||
final ValueChanged<Offset?> onSpotTap;
|
final ValueChanged<Offset?> onSpotTap;
|
||||||
|
|
||||||
|
@ -53,7 +52,7 @@ class _CameraPreviewState extends State<CameraPreview> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CameraPreviewBuilder extends StatefulWidget {
|
class _CameraPreviewBuilder extends StatefulWidget {
|
||||||
final CameraController controller;
|
final camera.CameraController controller;
|
||||||
final ValueChanged<Offset?> onSpotTap;
|
final ValueChanged<Offset?> onSpotTap;
|
||||||
|
|
||||||
const _CameraPreviewBuilder({
|
const _CameraPreviewBuilder({
|
||||||
|
@ -97,29 +96,15 @@ class _CameraPreviewBuilderState extends State<_CameraPreviewBuilder> {
|
||||||
}
|
}
|
||||||
return ValueListenableBuilder<bool>(
|
return ValueListenableBuilder<bool>(
|
||||||
valueListenable: _initializedNotifier,
|
valueListenable: _initializedNotifier,
|
||||||
builder: (context, value, child) => value
|
builder: (context, value, _) => value
|
||||||
? Stack(
|
? camera.CameraPreview(
|
||||||
alignment: Alignment.bottomCenter,
|
widget.controller,
|
||||||
children: [
|
child: context.isPro
|
||||||
CameraView(controller: widget.controller),
|
? _ProFeaturesOverlay(
|
||||||
if (context.isPro) ...[
|
controller: widget.controller,
|
||||||
if (UserPreferencesProvider.cameraFeatureOf(
|
onSpotTap: widget.onSpotTap,
|
||||||
context,
|
)
|
||||||
CameraFeature.histogram,
|
: const SizedBox.shrink(),
|
||||||
))
|
|
||||||
Positioned(
|
|
||||||
left: Dimens.grid8,
|
|
||||||
right: Dimens.grid8,
|
|
||||||
bottom: Dimens.grid16,
|
|
||||||
child: CameraHistogram(controller: widget.controller),
|
|
||||||
),
|
|
||||||
if (UserPreferencesProvider.cameraFeatureOf(
|
|
||||||
context,
|
|
||||||
CameraFeature.spotMetering,
|
|
||||||
))
|
|
||||||
CameraSpotDetector(onSpotTap: widget.onSpotTap),
|
|
||||||
],
|
|
||||||
],
|
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
);
|
);
|
||||||
|
@ -129,3 +114,38 @@ class _CameraPreviewBuilderState extends State<_CameraPreviewBuilder> {
|
||||||
_initializedNotifier.value = widget.controller.value.isInitialized;
|
_initializedNotifier.value = widget.controller.value.isInitialized;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _ProFeaturesOverlay extends StatelessWidget {
|
||||||
|
final camera.CameraController controller;
|
||||||
|
final ValueChanged<Offset?> onSpotTap;
|
||||||
|
|
||||||
|
const _ProFeaturesOverlay({
|
||||||
|
required this.controller,
|
||||||
|
required this.onSpotTap,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final bool hasHistogram = UserPreferencesProvider.cameraFeatureOf(
|
||||||
|
context,
|
||||||
|
CameraFeature.histogram,
|
||||||
|
);
|
||||||
|
final bool hasSpotMetering = UserPreferencesProvider.cameraFeatureOf(
|
||||||
|
context,
|
||||||
|
CameraFeature.histogram,
|
||||||
|
);
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.bottomCenter,
|
||||||
|
children: [
|
||||||
|
if (hasHistogram)
|
||||||
|
Positioned(
|
||||||
|
left: Dimens.grid8,
|
||||||
|
right: Dimens.grid8,
|
||||||
|
bottom: Dimens.grid16,
|
||||||
|
child: CameraHistogram(controller: controller),
|
||||||
|
),
|
||||||
|
if (hasSpotMetering) CameraSpotDetector(onSpotTap: onSpotTap),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
name: lightmeter
|
name: lightmeter
|
||||||
description: Lightmeter app inspired by Material 3 design system.
|
description: Lightmeter app inspired by Material 3 design system.
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.0.0+55
|
version: 1.0.1+56
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=3.0.0 <4.0.0"
|
sdk: ">=3.0.0 <4.0.0"
|
||||||
|
|
Loading…
Reference in a new issue