Upgrade project to the latest stable Flutter version (#201)

* fixed fvm path typo

* Update pubspec.yaml

* version control pubspec.lock

* fixed ios build

* deleted `ExpandableSectionList`

* removed redundant default cases

* avoided async gaps

* replaced deprecated color value getter

* `WillPopScope` -> `PopScope`

* removed theme deprecations

* replaced text scale deprecation

* updated goldens

* updated flutter version across workflows

* [android] migrated to the new gradle

* upgraded dependencies

* [android] fixed build

* [ios] fixed build

* updated config

* allow release notes to fail

* updated stub pubspec

* [android] use java 17

* [ios] enable flutterfire

* added firebase.json to secrets

* typo

* update color utils

* use exact versions

* reverted color utils

* updated goldens
This commit is contained in:
Vadim 2025-01-20 19:32:57 +01:00 committed by GitHub
parent fd97fc7fef
commit fb58b6cd9f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
56 changed files with 1857 additions and 528 deletions

3
.fvmrc Normal file
View file

@ -0,0 +1,3 @@
{
"flutter": "3.27.1"
}

View file

@ -90,7 +90,7 @@ jobs:
- uses: actions/setup-java@v3 - uses: actions/setup-java@v3
with: with:
distribution: "zulu" distribution: "zulu"
java-version: "11" java-version: "17"
- name: Restore Android keystore .jsk and .properties files - name: Restore Android keystore .jsk and .properties files
run: | run: |
@ -100,8 +100,10 @@ jobs:
- name: Restore google-services.json - name: Restore google-services.json
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.GOOGLE_SERVICES_JSON_ANDROID }}" "android/app/google-services.json" run: bash .github/scripts/restore_from_base64.sh "${{ secrets.GOOGLE_SERVICES_JSON_ANDROID }}" "android/app/google-services.json"
- name: Restore firebase_options.dart - name: Setup Firebase
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_OPTIONS }}" "lib/firebase_options.dart" run: |
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"
- name: Restore constants.dart - name: Restore constants.dart
env: env:
@ -112,6 +114,7 @@ jobs:
run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }} run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }}
- name: Download release notes - name: Download release notes
continue-on-error: true
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
with: with:
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }} name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
@ -121,7 +124,7 @@ jobs:
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.13.9" flutter-version: "3.27.1"
- name: Prepare flutter project - name: Prepare flutter project
run: | run: |

View file

@ -45,7 +45,7 @@ env:
jobs: jobs:
build: build:
name: Build .ipa name: Build .ipa
runs-on: macos-13 runs-on: macos-latest
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- uses: actions/checkout@v3 - uses: actions/checkout@v3
@ -92,11 +92,11 @@ jobs:
- name: Restore ExportOptions.plist - name: Restore ExportOptions.plist
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.APP_STORE_EXPORT_OPTIONS }}" "ios/Runner/ExportOptions.plist" run: bash .github/scripts/restore_from_base64.sh "${{ secrets.APP_STORE_EXPORT_OPTIONS }}" "ios/Runner/ExportOptions.plist"
- name: Restore firebase_app_id_file.json - name: Setup Firebase
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_APP_ID_FILE }}" "ios/firebase_app_id_file.json" run: |
bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_APP_ID_FILE }}" "ios/firebase_app_id_file.json"
- name: Restore firebase_options.dart bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_OPTIONS }}" "lib/firebase_options.dart"
run: 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"
- name: Restore constants.dart - name: Restore constants.dart
env: env:
@ -107,6 +107,7 @@ jobs:
run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }} run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }}
- name: Download release notes - name: Download release notes
continue-on-error: true
uses: actions/download-artifact@v3 uses: actions/download-artifact@v3
with: with:
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }} name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
@ -116,13 +117,14 @@ jobs:
uses: subosito/flutter-action@v2 uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.13.9" flutter-version: "3.27.1"
- name: Prepare flutter project - name: Prepare flutter project
run: | run: |
flutter --version flutter --version
flutter pub get flutter pub get
flutter pub run intl_utils:generate flutter pub run intl_utils:generate
dart pub global activate flutterfire_cli
- name: Build .ipa - name: Build .ipa
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.13.9" flutter-version: "3.27.1"
- name: Prepare flutter project - name: Prepare flutter project
run: | run: |

View file

@ -27,11 +27,12 @@ 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_JSON }}" "firebase.json"
- uses: subosito/flutter-action@v2 - uses: subosito/flutter-action@v2
with: with:
channel: "stable" channel: "stable"
flutter-version: "3.13.9" flutter-version: "3.27.1"
- name: Prepare app - name: Prepare app
run: | run: |
@ -39,6 +40,7 @@ jobs:
flutter pub get flutter pub get
flutter pub run intl_utils:generate flutter pub run intl_utils:generate
flutter analyze lib --fatal-infos flutter analyze lib --fatal-infos
dart pub global activate flutterfire_cli
- name: Launch iOS simulator - name: Launch iOS simulator
uses: futureware-tech/simulator-action@v3 uses: futureware-tech/simulator-action@v3

5
.gitignore vendored
View file

@ -5,9 +5,11 @@
*.swp *.swp
.DS_Store .DS_Store
.atom/ .atom/
.build/
.buildlog/ .buildlog/
.history .history
.svn/ .svn/
.swiftpm/
migrate_working_dir/ migrate_working_dir/
# IntelliJ related # IntelliJ related
@ -48,7 +50,6 @@ app.*.map.json
/ios/build/ /ios/build/
/ios/Runner.xcodeproj/project.pbxproj /ios/Runner.xcodeproj/project.pbxproj
pubspec.lock
/ios/Podfile.lock /ios/Podfile.lock
.fvm/ .fvm/
@ -64,3 +65,5 @@ coverage/
test/coverage_helper_test.dart test/coverage_helper_test.dart
**/failures/*.png **/failures/*.png
screenshots/generated/raw/ screenshots/generated/raw/
firebase.json

View file

@ -1,6 +1,6 @@
{ {
"task.slowProviderWarning": true, "task.slowProviderWarning": true,
"dart.flutterSdkPath": "fvm", "dart.flutterSdkPath": ".fvm/flutter_sdk",
"search.exclude": { "search.exclude": {
"**/.fvm": true "**/.fvm": true
}, },
@ -10,7 +10,7 @@
"dart.lineLength": 120, "dart.lineLength": 120,
"[dart]": { "[dart]": {
"editor.rulers": [ "editor.rulers": [
120, 120
], ],
"editor.selectionHighlight": true, "editor.selectionHighlight": true,
"editor.suggest.snippetsPreventQuickSuggestions": false, "editor.suggest.snippetsPreventQuickSuggestions": false,
@ -21,5 +21,5 @@
"dart.doNotFormat": [ "dart.doNotFormat": [
"**/generated/**", "**/generated/**",
"lib/data/**" "lib/data/**"
], ]
} }

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.13.9 stable. [How to install](https://docs.flutter.dev/get-started/install). To build this app you need to install Flutter 3.27.1 stable. [How to install](https://docs.flutter.dev/get-started/install).
### 2. Project setup ### 2. Project setup

View file

@ -1,3 +1,11 @@
plugins {
id 'com.android.application'
id 'kotlin-android'
id "dev.flutter.flutter-gradle-plugin"
id "com.google.gms.google-services"
id "com.google.firebase.crashlytics"
}
def localProperties = new Properties() def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties') def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) { if (localPropertiesFile.exists()) {
@ -6,11 +14,6 @@ if (localPropertiesFile.exists()) {
} }
} }
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode') def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = '1' flutterVersionCode = '1'
@ -27,15 +30,9 @@ if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile)) keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
} }
apply plugin: 'com.android.application'
apply plugin: 'com.google.gms.google-services'
apply plugin: 'com.google.firebase.crashlytics'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android { android {
compileSdkVersion 34 compileSdkVersion 34
ndkVersion flutter.ndkVersion ndkVersion "27.0.12077973"
compileOptions { compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8 sourceCompatibility JavaVersion.VERSION_1_8
@ -43,7 +40,7 @@ android {
} }
kotlinOptions { kotlinOptions {
jvmTarget = '1.8' jvmTarget = JavaVersion.VERSION_1_8
} }
sourceSets { sourceSets {
@ -51,7 +48,7 @@ android {
} }
defaultConfig { defaultConfig {
minSdkVersion 21 minSdkVersion 23
targetSdkVersion 34 targetSdkVersion 34
ndk { ndk {
debugSymbolLevel 'FULL' debugSymbolLevel 'FULL'
@ -101,6 +98,7 @@ android {
} }
} }
} }
namespace 'com.vodemn.lightmeter'
} }
flutter { flutter {
@ -108,7 +106,6 @@ flutter {
} }
dependencies { dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "com.android.billingclient:billing-ktx:6.0.0" implementation "com.android.billingclient:billing-ktx:6.0.0"
implementation "com.google.firebase:firebase-analytics:17.4.1" implementation "com.google.firebase:firebase-analytics:17.4.1"
} }

View file

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="com.vodemn.lightmeter">
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.

View file

@ -1,6 +1,5 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools">
package="com.vodemn.lightmeter">
<application <application
android:label="@string/app_name" android:label="@string/app_name"

View file

@ -1,5 +1,4 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android" <manifest xmlns:android="http://schemas.android.com/apk/res/android">
package="com.vodemn.lightmeter">
<!-- The INTERNET permission is required for development. Specifically, <!-- The INTERNET permission is required for development. Specifically,
the Flutter tool needs it to communicate with the running application the Flutter tool needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.

View file

@ -1,18 +1,3 @@
buildscript {
ext.kotlin_version = '1.8.21'
repositories {
google()
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.4.2'
classpath 'com.google.gms:google-services:4.3.15'
classpath 'com.google.firebase:firebase-crashlytics-gradle:2.8.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
allprojects { allprojects {
repositories { repositories {
google() google()

View file

@ -1,3 +1,6 @@
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
android.defaults.buildfeatures.buildconfig=true
android.nonTransitiveRClass=false
android.nonFinalResIds=false

View file

@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-all.zip

View file

@ -1,11 +1,27 @@
include ':app' pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}()
def localPropertiesFile = new File(rootProject.projectDir, "local.properties") includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
def properties = new Properties()
assert localPropertiesFile.exists() repositories {
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) } google()
mavenCentral()
gradlePluginPortal()
}
}
def flutterSdkPath = properties.getProperty("flutter.sdk") plugins {
assert flutterSdkPath != null, "flutter.sdk not set in local.properties" id "dev.flutter.flutter-plugin-loader" version "1.0.0"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle" id "com.android.application" version '8.7.3' apply false
id "org.jetbrains.kotlin.android" version "1.8.21" apply false
id "com.google.gms.google-services" version "4.4.0" apply false
id "com.google.firebase.crashlytics" version "2.9.9" apply false
}
include ":app"

View file

@ -13,7 +13,7 @@ dependencies:
git: git:
url: "https://github.com/vodemn/m3_lightmeter_resources" url: "https://github.com/vodemn/m3_lightmeter_resources"
ref: v2.1.0 ref: v2.1.0
shared_preferences: 2.2.0 shared_preferences:
dev_dependencies: dev_dependencies:
flutter_test: flutter_test:

View file

@ -21,6 +21,6 @@
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0</string> <string>1.0</string>
<key>MinimumOSVersion</key> <key>MinimumOSVersion</key>
<string>11.0</string> <string>12.0</string>
</dict> </dict>
</plist> </plist>

View file

@ -1,5 +1,5 @@
# Uncomment this line to define a global platform for your project # Uncomment this line to define a global platform for your project
platform :ios, '12.0' platform :ios, '13.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency. # CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true' ENV['COCOAPODS_DISABLE_STATS'] = 'true'
@ -36,6 +36,16 @@ end
post_install do |installer| post_install do |installer|
installer.pods_project.targets.each do |target| installer.pods_project.targets.each do |target|
if target.name == 'BoringSSL-GRPC'
target.source_build_phase.files.each do |file|
if file.settings && file.settings['COMPILER_FLAGS']
flags = file.settings['COMPILER_FLAGS'].split
flags.reject! { |flag| flag == '-GCC_WARN_INHIBIT_ALL_WARNINGS' }
file.settings['COMPILER_FLAGS'] = flags.join(' ')
end
end
end
flutter_additional_ios_build_settings(target) flutter_additional_ios_build_settings(target)
target.build_configurations.each do |config| target.build_configurations.each do |config|

View file

@ -155,6 +155,8 @@
3B06AD1E1E4923F5004D2608 /* Thin Binary */, 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
45F53C083F2EA48EF231DA16 /* [CP] Embed Pods Frameworks */, 45F53C083F2EA48EF231DA16 /* [CP] Embed Pods Frameworks */,
FF00F85CE432774850A0EDB7 /* [firebase_crashlytics] Crashlytics Upload Symbols */, FF00F85CE432774850A0EDB7 /* [firebase_crashlytics] Crashlytics Upload Symbols */,
08127035D2CDEEEBA66FCDBB /* [CP] Copy Pods Resources */,
6F6C086A620B15784F8BE312 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
); );
buildRules = ( buildRules = (
); );
@ -171,7 +173,7 @@
97C146E61CF9000F007C117D /* Project object */ = { 97C146E61CF9000F007C117D /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 1300; LastUpgradeCheck = 1510;
ORGANIZATIONNAME = ""; ORGANIZATIONNAME = "";
TargetAttributes = { TargetAttributes = {
97C146ED1CF9000F007C117D = { 97C146ED1CF9000F007C117D = {
@ -214,6 +216,23 @@
/* End PBXResourcesBuildPhase section */ /* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */
08127035D2CDEEEBA66FCDBB /* [CP] Copy Pods Resources */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
);
name = "[CP] Copy Pods Resources";
outputFileListPaths = (
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
showEnvVarsInLog = 0;
};
385E047940E442D45ED68E6E /* [CP] Check Pods Manifest.lock */ = { 385E047940E442D45ED68E6E /* [CP] Check Pods Manifest.lock */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
@ -269,6 +288,24 @@
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
showEnvVarsInLog = 0; showEnvVarsInLog = 0;
}; };
6F6C086A620B15784F8BE312 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "\n#!/bin/bash\nPATH=\"${PATH}:$FLUTTER_ROOT/bin:$HOME/.pub-cache/bin\"\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --platform=ios --apple-project-path=\"${SRCROOT}\" --env-platform-name=\"${PLATFORM_NAME}\" --env-configuration=\"${CONFIGURATION}\" --env-project-dir=\"${PROJECT_DIR}\" --env-built-products-dir=\"${BUILT_PRODUCTS_DIR}\" --env-dwarf-dsym-folder-path=\"${DWARF_DSYM_FOLDER_PATH}\" --env-dwarf-dsym-file-name=\"${DWARF_DSYM_FILE_NAME}\" --env-infoplist-path=\"${INFOPLIST_PATH}\" --default-config=default\n";
};
9740EEB61CF901F6004384FC /* Run Script */ = { 9740EEB61CF901F6004384FC /* Run Script */ = {
isa = PBXShellScriptBuildPhase; isa = PBXShellScriptBuildPhase;
alwaysOutOfDate = 1; alwaysOutOfDate = 1;
@ -292,11 +329,11 @@
inputFileListPaths = ( inputFileListPaths = (
); );
inputPaths = ( inputPaths = (
"\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}\"", "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}",
"\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/\"", "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${PRODUCT_NAME}",
"\"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist\"", "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist",
"\"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)\"", "$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/GoogleService-Info.plist",
"\"$(PROJECT_DIR)/firebase_app_id_file.json\"", "$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)",
); );
name = "[firebase_crashlytics] Crashlytics Upload Symbols"; name = "[firebase_crashlytics] Crashlytics Upload Symbols";
outputFileListPaths = ( outputFileListPaths = (
@ -305,7 +342,7 @@
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh; shellPath = /bin/sh;
shellScript = "\"$PODS_ROOT/FirebaseCrashlytics/upload-symbols\" --flutter-project \"$PROJECT_DIR/firebase_app_id_file.json\" "; shellScript = "\"${PODS_ROOT}/FirebaseCrashlytics/upload-symbols\" -gsp \"${PROJECT_DIR}/Runner/GoogleService-Info.plist\" -p ios \"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}\"\n";
}; };
/* End PBXShellScriptBuildPhase section */ /* End PBXShellScriptBuildPhase section */
@ -382,7 +419,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -397,6 +434,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -466,7 +504,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -515,7 +553,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -532,6 +570,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -561,6 +600,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution"; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
@ -633,7 +673,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = YES; MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos; SDKROOT = iphoneos;
@ -647,6 +687,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -711,7 +752,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -728,6 +769,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
@ -791,7 +833,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 11.0; IPHONEOS_DEPLOYMENT_TARGET = 12.0;
MTL_ENABLE_DEBUG_INFO = NO; MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos; SDKROOT = iphoneos;
SUPPORTED_PLATFORMS = iphoneos; SUPPORTED_PLATFORMS = iphoneos;
@ -806,6 +848,7 @@
buildSettings = { buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev"; ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev";
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO; ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;

View file

@ -1,7 +1,7 @@
import UIKit import UIKit
import Flutter import Flutter
@UIApplicationMain @main
@objc class AppDelegate: FlutterAppDelegate { @objc class AppDelegate: FlutterAppDelegate {
override func application( override func application(
_ application: UIApplication, _ application: UIApplication,

View file

@ -44,7 +44,7 @@ class Application extends StatelessWidget {
], ],
supportedLocales: S.delegate.supportedLocales, supportedLocales: S.delegate.supportedLocales,
builder: (context, child) => MediaQuery( builder: (context, child) => MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
child: child!, child: child!,
), ),
initialRoute: NavigationRoutes.meteringScreen.name, initialRoute: NavigationRoutes.meteringScreen.name,

View file

@ -22,7 +22,7 @@ class LightmeterAnalytics {
Future<void> logEvent( Future<void> logEvent(
String eventName, { String eventName, {
Map<String, dynamic>? parameters, Map<String, Object>? parameters,
}) async { }) async {
if (!kReleaseMode) { if (!kReleaseMode) {
log('<LightmeterAnalytics> logEvent: $eventName / $parameters'); log('<LightmeterAnalytics> logEvent: $eventName / $parameters');

View file

@ -1,7 +1,7 @@
abstract class ILightmeterAnalyticsApi { abstract class ILightmeterAnalyticsApi {
Future<void> logEvent( Future<void> logEvent(
String eventName, { String eventName, {
Map<String, dynamic>? parameters, Map<String, Object>? parameters,
}); });
Future<void> logCrash( Future<void> logCrash(

View file

@ -10,7 +10,7 @@ class LightmeterAnalyticsFirebase implements ILightmeterAnalyticsApi {
@override @override
Future<void> logEvent( Future<void> logEvent(
String eventName, { String eventName, {
Map<String, dynamic>? parameters, Map<String, Object>? parameters,
}) async { }) async {
try { try {
await FirebaseAnalytics.instance.logEvent( await FirebaseAnalytics.instance.logEvent(

View file

@ -8,7 +8,7 @@ typedef MeteringScreenLayoutConfig = Map<MeteringScreenLayoutFeature, bool>;
extension MeteringScreenLayoutConfigJson on MeteringScreenLayoutConfig { extension MeteringScreenLayoutConfigJson on MeteringScreenLayoutConfig {
static MeteringScreenLayoutConfig fromJson(Map<String, dynamic> data) { static MeteringScreenLayoutConfig fromJson(Map<String, dynamic> data) {
int? migratedIndex(MeteringScreenLayoutFeature feature) { int migratedIndex(MeteringScreenLayoutFeature feature) {
switch (feature) { switch (feature) {
case MeteringScreenLayoutFeature.extremeExposurePairs: case MeteringScreenLayoutFeature.extremeExposurePairs:
return 0; return 0;
@ -16,8 +16,6 @@ extension MeteringScreenLayoutConfigJson on MeteringScreenLayoutConfig {
return 1; return 1;
case MeteringScreenLayoutFeature.equipmentProfiles: case MeteringScreenLayoutFeature.equipmentProfiles:
return 3; return 3;
default:
return null;
} }
} }

View file

@ -7,6 +7,7 @@ import 'package:lightmeter/data/models/metering_screen_layout_config.dart';
import 'package:lightmeter/data/models/supported_locale.dart'; import 'package:lightmeter/data/models/supported_locale.dart';
import 'package:lightmeter/data/models/theme_type.dart'; import 'package:lightmeter/data/models/theme_type.dart';
import 'package:lightmeter/data/models/volume_action.dart'; import 'package:lightmeter/data/models/volume_action.dart';
import 'package:lightmeter/utils/color_to_int.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -155,7 +156,7 @@ class UserPreferencesService {
set themeType(ThemeType value) => _sharedPreferences.setInt(themeTypeKey, value.index); set themeType(ThemeType value) => _sharedPreferences.setInt(themeTypeKey, value.index);
Color get primaryColor => Color(_sharedPreferences.getInt(primaryColorKey) ?? 0xff2196f3); Color get primaryColor => Color(_sharedPreferences.getInt(primaryColorKey) ?? 0xff2196f3);
set primaryColor(Color value) => _sharedPreferences.setInt(primaryColorKey, value.value); set primaryColor(Color value) => _sharedPreferences.setInt(primaryColorKey, value.toInt());
bool get dynamicColor => _sharedPreferences.getBool(dynamicColorKey) ?? false; bool get dynamicColor => _sharedPreferences.getBool(dynamicColorKey) ?? false;
set dynamicColor(bool value) => _sharedPreferences.setBool(dynamicColorKey, value); set dynamicColor(bool value) => _sharedPreferences.setBool(dynamicColorKey, value);

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/utils/color_to_int.dart';
import 'package:material_color_utilities/material_color_utilities.dart'; import 'package:material_color_utilities/material_color_utilities.dart';
const primaryColorsList = [ const primaryColorsList = [
@ -32,7 +33,7 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
elevation: Dimens.elevationLevel0, elevation: Dimens.elevationLevel0,
scrolledUnderElevation: Dimens.elevationLevel2, scrolledUnderElevation: Dimens.elevationLevel2,
color: scheme.surface, color: scheme.surface,
foregroundColor: scheme.onBackground, foregroundColor: scheme.onSurface,
surfaceTintColor: scheme.surfaceTint, surfaceTintColor: scheme.surfaceTint,
), ),
cardTheme: CardTheme( cardTheme: CardTheme(
@ -75,15 +76,13 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) { ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
final scheme = SchemeTonalSpot( final scheme = SchemeTonalSpot(
sourceColorHct: Hct.fromInt(primaryColor.value), sourceColorHct: Hct.fromInt(primaryColor.toInt()),
isDark: brightness == Brightness.dark, isDark: brightness == Brightness.dark,
contrastLevel: 0.0, contrastLevel: 0.0,
); );
return ColorScheme( return ColorScheme(
brightness: brightness, brightness: brightness,
background: Color(scheme.background),
onBackground: Color(scheme.onBackground),
error: Color(scheme.error), error: Color(scheme.error),
onError: Color(scheme.onError), onError: Color(scheme.onError),
errorContainer: Color(scheme.errorContainer), errorContainer: Color(scheme.errorContainer),
@ -102,7 +101,7 @@ ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
onTertiaryContainer: Color(scheme.onTertiaryContainer), onTertiaryContainer: Color(scheme.onTertiaryContainer),
surface: Color(scheme.surface), surface: Color(scheme.surface),
onSurface: Color(scheme.onSurface), onSurface: Color(scheme.onSurface),
surfaceVariant: Color(scheme.surfaceVariant), surfaceContainerHighest: Color(scheme.surfaceContainerHighest),
onSurfaceVariant: Color(scheme.onSurfaceVariant), onSurfaceVariant: Color(scheme.onSurfaceVariant),
outline: Color(scheme.outline), outline: Color(scheme.outline),
outlineVariant: Color(scheme.outlineVariant), outlineVariant: Color(scheme.outlineVariant),

View file

@ -91,7 +91,6 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
case communication_states.SettingsClosedState(): case communication_states.SettingsClosedState():
_settingsOpened = false; _settingsOpened = false;
add(const InitializeEvent()); add(const InitializeEvent());
default:
} }
} }

View file

@ -25,7 +25,7 @@ class CameraControlsPlaceholder extends StatelessWidget {
const SizedBox(height: Dimens.grid8), const SizedBox(height: Dimens.grid8),
Text( Text(
error.toStringLocalized(context), error.toStringLocalized(context),
style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: Theme.of(context).colorScheme.onBackground), style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: Theme.of(context).colorScheme.onSurface),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],

View file

@ -62,14 +62,14 @@ class _Title<T extends PhotographyStopValue> extends StatelessWidget {
value.toString(), value.toString(),
stepGranularity: 0.5, stepGranularity: 0.5,
minFontSize: 10, minFontSize: 10,
style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onBackground), style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onSurface),
softWrap: false, softWrap: false,
overflow: TextOverflow.fade, overflow: TextOverflow.fade,
maxLines: 1, maxLines: 1,
) )
: Text( : Text(
value.toString(), value.toString(),
style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onBackground), style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onSurface),
softWrap: false, softWrap: false,
overflow: TextOverflow.fade, overflow: TextOverflow.fade,
maxLines: 1, maxLines: 1,
@ -97,7 +97,7 @@ class _Tick extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ColoredBox( return ColoredBox(
color: Theme.of(context).colorScheme.onBackground, color: Theme.of(context).colorScheme.onSurface,
child: SizedBox( child: SizedBox(
height: 1, height: 1,
width: _length, width: _length,

View file

@ -78,7 +78,7 @@ class ExposurePairsList extends StatelessWidget {
? constraints.maxHeight / 2 ? constraints.maxHeight / 2
: constraints.maxHeight, : constraints.maxHeight,
child: ColoredBox( child: ColoredBox(
color: Theme.of(context).colorScheme.onBackground, color: Theme.of(context).colorScheme.onSurface,
child: const SizedBox(width: 1), child: const SizedBox(width: 1),
), ),
), ),

View file

@ -178,8 +178,8 @@ class AnimatedDialogState extends State<AnimatedDialog> with SingleTickerProvide
opaque: false, opaque: false,
transitionDuration: Duration.zero, transitionDuration: Duration.zero,
reverseTransitionDuration: Duration.zero, reverseTransitionDuration: Duration.zero,
pageBuilder: (_, __, ___) => WillPopScope( pageBuilder: (_, __, ___) => PopScope(
onWillPop: () => _animateReverse().then((value) => true), onPopInvokedWithResult: (_, __) => _animateReverse().then((value) => true),
child: _AnimatedOverlay( child: _AnimatedOverlay(
controller: _animationController, controller: _animationController,
barrierColorAnimation: _barrierColorAnimation, barrierColorAnimation: _barrierColorAnimation,
@ -221,7 +221,13 @@ class AnimatedDialogState extends State<AnimatedDialog> with SingleTickerProvide
}); });
} }
Future<void> close() => _animateReverse().then((_) => Navigator.of(context).pop()); Future<void> close() {
return _animateReverse().then((_) {
if (mounted) {
Navigator.of(context).pop();
}
});
}
} }
class _AnimatedOverlay extends StatelessWidget { class _AnimatedOverlay extends StatelessWidget {

View file

@ -69,9 +69,14 @@ class MeteringScreen extends StatelessWidget {
} }
void pushNamed(BuildContext context, String routeName, {Object? arguments}) { void pushNamed(BuildContext context, String routeName, {Object? arguments}) {
context.read<MeteringBloc>().add(const ScreenOnTopOpenedEvent()); final bloc = context.read<MeteringBloc>();
Navigator.pushNamed(context, routeName, arguments: arguments).then((_) { bloc.add(const ScreenOnTopOpenedEvent());
context.read<MeteringBloc>().add(const ScreenOnTopClosedEvent()); Navigator.pushNamed(
context,
routeName,
arguments: arguments,
).then((_) {
bloc.add(const ScreenOnTopClosedEvent());
}); });
} }
} }

View file

@ -4,9 +4,14 @@ import 'package:lightmeter/constants.dart';
import 'package:lightmeter/generated/l10n.dart'; import 'package:lightmeter/generated/l10n.dart';
import 'package:url_launcher/url_launcher.dart'; import 'package:url_launcher/url_launcher.dart';
class WriteEmailListTile extends StatelessWidget { class WriteEmailListTile extends StatefulWidget {
const WriteEmailListTile({super.key}); const WriteEmailListTile({super.key});
@override
State<WriteEmailListTile> createState() => _WriteEmailListTileState();
}
class _WriteEmailListTileState extends State<WriteEmailListTile> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
@ -20,7 +25,15 @@ class WriteEmailListTile extends StatelessWidget {
mailToUrl, mailToUrl,
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
} else { } else if (mounted) {
_showSnackBar();
}
});
},
);
}
Future<void> _showSnackBar() async {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text(S.of(context).youDontHaveMailApp), content: Text(S.of(context).youDontHaveMailApp),
@ -29,15 +42,13 @@ class WriteEmailListTile extends StatelessWidget {
label: S.of(context).copyEmail, label: S.of(context).copyEmail,
onPressed: () { onPressed: () {
FlutterClipboard.copy(contactEmail).then((_) { FlutterClipboard.copy(contactEmail).then((_) {
if (mounted) {
ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).clearSnackBars();
});
},
),
),
);
} }
}); });
}, },
),
),
); );
} }
} }

View file

@ -14,6 +14,7 @@ class LanguageListTile extends StatelessWidget {
title: Text(S.of(context).language), title: Text(S.of(context).language),
trailing: Text(UserPreferencesProvider.localeOf(context).localizedName), trailing: Text(UserPreferencesProvider.localeOf(context).localizedName),
onTap: () { onTap: () {
final prefs = UserPreferencesProvider.of(context);
showDialog<SupportedLocale>( showDialog<SupportedLocale>(
context: context, context: context,
builder: (_) => DialogPicker<SupportedLocale>( builder: (_) => DialogPicker<SupportedLocale>(
@ -21,11 +22,11 @@ class LanguageListTile extends StatelessWidget {
title: S.of(context).chooseLanguage, title: S.of(context).chooseLanguage,
selectedValue: UserPreferencesProvider.localeOf(context), selectedValue: UserPreferencesProvider.localeOf(context),
values: SupportedLocale.values, values: SupportedLocale.values,
titleAdapter: (context, value) => value.localizedName, titleAdapter: (_, value) => value.localizedName,
), ),
).then((value) { ).then((value) {
if (value != null) { if (value != null) {
UserPreferencesProvider.of(context).setLocale(value); prefs.setLocale(value);
} }
}); });
}, },

View file

@ -14,6 +14,7 @@ class StopTypeListTile extends StatelessWidget {
title: Text(S.of(context).fractionalStops), title: Text(S.of(context).fractionalStops),
trailing: Text(_typeToString(context, UserPreferencesProvider.stopTypeOf(context))), trailing: Text(_typeToString(context, UserPreferencesProvider.stopTypeOf(context))),
onTap: () { onTap: () {
final prefs = UserPreferencesProvider.of(context);
showDialog<StopType>( showDialog<StopType>(
context: context, context: context,
builder: (_) => DialogPicker<StopType>( builder: (_) => DialogPicker<StopType>(
@ -25,7 +26,7 @@ class StopTypeListTile extends StatelessWidget {
), ),
).then((value) { ).then((value) {
if (value != null) { if (value != null) {
UserPreferencesProvider.of(context).setStopType(value); prefs.setStopType(value);
} }
}); });
}, },

View file

@ -1,56 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart';
class ExpandableSectionNameDialog extends StatefulWidget {
final String title;
final String hint;
final String initialValue;
const ExpandableSectionNameDialog({
this.initialValue = '',
required this.title,
required this.hint,
super.key,
});
@override
State<ExpandableSectionNameDialog> createState() => _ExpandableSectionNameDialogState();
}
class _ExpandableSectionNameDialogState extends State<ExpandableSectionNameDialog> {
late final _nameController = TextEditingController(text: widget.initialValue);
@override
void dispose() {
_nameController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AlertDialog(
icon: const Icon(Icons.edit_outlined),
titlePadding: Dimens.dialogIconTitlePadding,
title: Text(widget.title),
content: TextField(
autofocus: true,
controller: _nameController,
decoration: InputDecoration(hintText: widget.hint),
),
actions: [
TextButton(
onPressed: Navigator.of(context).pop,
child: Text(S.of(context).cancel),
),
ValueListenableBuilder(
valueListenable: _nameController,
builder: (_, value, __) => TextButton(
onPressed: value.text.isNotEmpty ? () => Navigator.of(context).pop(value.text) : null,
child: Text(S.of(context).save),
),
),
],
);
}
}

View file

@ -1,184 +0,0 @@
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart';
class ExpandableSectionListItem extends StatefulWidget {
final String title;
final VoidCallback onTitleTap;
final VoidCallback onExpand;
final List<IconButton> actions;
final List<Widget> children;
const ExpandableSectionListItem({
required this.title,
required this.onTitleTap,
required this.onExpand,
required this.actions,
required this.children,
super.key,
});
static ExpandableSectionListItemState of(BuildContext context) {
return context.findAncestorStateOfType<ExpandableSectionListItemState>()!;
}
@override
State<ExpandableSectionListItem> createState() => ExpandableSectionListItemState();
}
class ExpandableSectionListItemState extends State<ExpandableSectionListItem> with TickerProviderStateMixin {
late final AnimationController _controller = AnimationController(
duration: Dimens.durationM,
vsync: this,
);
bool get _expanded => _controller.isCompleted;
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingM),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
title: Row(
children: [
_AnimatedNameLeading(controller: _controller),
const SizedBox(width: Dimens.grid8),
Flexible(
child: Text(
widget.title,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
),
],
),
trailing: _AnimatedArrowButton(
controller: _controller,
onPressed: () => _expanded ? collapse() : expand(),
),
onTap: () => _expanded ? widget.onTitleTap() : expand(),
),
_AnimatedContent(
controller: _controller,
actions: widget.actions,
children: widget.children,
),
],
),
),
);
}
void expand() {
widget.onExpand();
_controller.forward();
SchedulerBinding.instance.addPostFrameCallback((_) {
Future.delayed(_controller.duration!).then((_) {
Scrollable.ensureVisible(
context,
alignmentPolicy: ScrollPositionAlignmentPolicy.keepVisibleAtEnd,
duration: _controller.duration!,
);
});
});
}
void collapse() {
_controller.reverse();
}
}
class _AnimatedNameLeading extends AnimatedWidget {
const _AnimatedNameLeading({required AnimationController controller}) : super(listenable: controller);
Animation<double> get _progress => listenable as Animation<double>;
@override
Widget build(BuildContext context) {
return Padding(
padding: EdgeInsets.only(right: _progress.value * Dimens.grid8),
child: Icon(
Icons.edit_outlined,
size: _progress.value * Dimens.grid24,
),
);
}
}
class _AnimatedArrowButton extends AnimatedWidget {
final VoidCallback onPressed;
const _AnimatedArrowButton({
required AnimationController controller,
required this.onPressed,
}) : super(listenable: controller);
Animation<double> get _progress => listenable as Animation<double>;
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: onPressed,
icon: Transform.rotate(
angle: _progress.value * pi,
child: const Icon(Icons.keyboard_arrow_down_outlined),
),
tooltip: _progress.value == 0 ? S.of(context).tooltipExpand : S.of(context).tooltipCollapse,
);
}
}
class _AnimatedContent extends AnimatedWidget {
final List<IconButton> actions;
final List<Widget> children;
const _AnimatedContent({
required AnimationController controller,
required this.actions,
required this.children,
}) : super(listenable: controller);
Animation<double> get _progress => listenable as Animation<double>;
@override
Widget build(BuildContext context) {
return SizedOverflowBox(
alignment: Alignment.topCenter,
size: Size(
double.maxFinite,
_progress.value * Dimens.grid56 * (children.length + 1),
),
// https://github.com/gskinnerTeam/flutter-folio/pull/62
child: Opacity(
opacity: _progress.value,
child: Column(
children: [
...children,
ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingM),
trailing: Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.min,
children: actions,
),
),
],
),
),
);
}
}

View file

@ -1,95 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/screens/settings/components/shared/expandable_section_list/components/expandable_section_list_item/widget_expandable_section_list_item.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
typedef _WidgetBuilder<W, T extends Identifiable> = W Function(BuildContext context, T value);
class ExpandableSectionList<T extends Identifiable> extends StatefulWidget {
final List<T> values;
final VoidCallback onSectionTitleTap;
final _WidgetBuilder<List<Widget>, T> contentBuilder;
final _WidgetBuilder<List<IconButton>, T> actionsBuilder;
const ExpandableSectionList({
required this.values,
required this.onSectionTitleTap,
required this.contentBuilder,
required this.actionsBuilder,
super.key,
});
@override
State<ExpandableSectionList> createState() => _ExpandableSectionListState<T>();
}
class _ExpandableSectionListState<T extends Identifiable> extends State<ExpandableSectionList<T>> {
final Map<String, GlobalKey<ExpandableSectionListItemState>> keysMap = {};
@override
void didChangeDependencies() {
super.didChangeDependencies();
_updateProfilesKeys();
}
@override
Widget build(BuildContext context) {
return SliverList(
delegate: SliverChildBuilderDelegate(
(context, index) {
final item = widget.values[index];
return Padding(
padding: EdgeInsets.fromLTRB(
Dimens.paddingM,
index == 0 ? Dimens.paddingM : 0,
Dimens.paddingM,
Dimens.paddingM,
),
child: ExpandableSectionListItem(
key: keysMap[item.id],
title: item.name,
onTitleTap: widget.onSectionTitleTap,
onExpand: () => _keepExpandedAt(index),
actions: widget.actionsBuilder(context, item),
children: widget.contentBuilder(context, item),
),
);
},
childCount: widget.values.length,
),
);
}
void _keepExpandedAt(int index) {
keysMap.values.toList().getRange(0, index).forEach((element) {
element.currentState?.collapse();
});
keysMap.values.toList().getRange(index + 1, keysMap.length).forEach((element) {
element.currentState?.collapse();
});
}
void _updateProfilesKeys() {
if (widget.values.length > keysMap.length) {
// item added
final List<String> idsToAdd = [];
for (final item in widget.values) {
if (!keysMap.keys.contains(item.id)) idsToAdd.add(item.id);
}
for (final id in idsToAdd) {
keysMap[id] = GlobalKey<ExpandableSectionListItemState>(debugLabel: id);
}
idsToAdd.clear();
} else if (widget.values.length < keysMap.length) {
// item deleted
final List<String> idsToDelete = [];
for (final id in keysMap.keys) {
if (!widget.values.any((p) => p.id == id)) idsToDelete.add(id);
}
idsToDelete.forEach(keysMap.remove);
idsToDelete.clear();
} else {
// item updated, no need to updated keys
}
}
}

View file

@ -3,6 +3,7 @@ import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.dart';
import 'package:lightmeter/res/theme.dart'; import 'package:lightmeter/res/theme.dart';
import 'package:lightmeter/screens/shared/filled_circle/widget_circle_filled.dart'; import 'package:lightmeter/screens/shared/filled_circle/widget_circle_filled.dart';
import 'package:lightmeter/utils/color_to_int.dart';
class PrimaryColorDialogPicker extends StatefulWidget { class PrimaryColorDialogPicker extends StatefulWidget {
const PrimaryColorDialogPicker({super.key}); const PrimaryColorDialogPicker({super.key});
@ -45,7 +46,7 @@ class _PrimaryColorDialogPickerState extends State<PrimaryColorDialogPicker> {
padding: EdgeInsets.only(left: index == 0 ? 0 : Dimens.paddingS), padding: EdgeInsets.only(left: index == 0 ? 0 : Dimens.paddingS),
child: _SelectableColorItem( child: _SelectableColorItem(
color: color, color: color,
selected: color.value == _selected.value, selected: color.toInt() == _selected.toInt(),
onTap: () { onTap: () {
setState(() { setState(() {
_selected = color; _selected = color;

View file

@ -22,12 +22,13 @@ class PrimaryColorListTile extends StatelessWidget {
leading: const Icon(Icons.palette_outlined), leading: const Icon(Icons.palette_outlined),
title: Text(S.of(context).primaryColor), title: Text(S.of(context).primaryColor),
onTap: () { onTap: () {
final prefs = UserPreferencesProvider.of(context);
showDialog<Color>( showDialog<Color>(
context: context, context: context,
builder: (_) => const PrimaryColorDialogPicker(), builder: (_) => const PrimaryColorDialogPicker(),
).then((value) { ).then((value) {
if (value != null) { if (value != null) {
UserPreferencesProvider.of(context).setPrimaryColor(value); prefs.setPrimaryColor(value);
} }
}); });
}, },

View file

@ -14,6 +14,7 @@ class ThemeTypeListTile extends StatelessWidget {
title: Text(S.of(context).theme), title: Text(S.of(context).theme),
trailing: Text(_typeToString(context, UserPreferencesProvider.themeTypeOf(context))), trailing: Text(_typeToString(context, UserPreferencesProvider.themeTypeOf(context))),
onTap: () { onTap: () {
final prefs = UserPreferencesProvider.of(context);
showDialog<ThemeType>( showDialog<ThemeType>(
context: context, context: context,
builder: (_) => DialogPicker<ThemeType>( builder: (_) => DialogPicker<ThemeType>(
@ -25,7 +26,7 @@ class ThemeTypeListTile extends StatelessWidget {
), ),
).then((value) { ).then((value) {
if (value != null) { if (value != null) {
UserPreferencesProvider.of(context).setThemeType(value); prefs.setThemeType(value);
} }
}); });
}, },

View file

@ -120,7 +120,7 @@ class _Slider extends StatelessWidget {
width: handleDistance + trackThickness, width: handleDistance + trackThickness,
child: ClipRRect( child: ClipRRect(
borderRadius: BorderRadius.circular(trackThickness / 2), borderRadius: BorderRadius.circular(trackThickness / 2),
child: ColoredBox(color: Theme.of(context).colorScheme.surfaceVariant), child: ColoredBox(color: Theme.of(context).colorScheme.surfaceContainerHighest),
), ),
), ),
AnimatedPositioned.fromRect( AnimatedPositioned.fromRect(

View file

@ -20,15 +20,12 @@ class IconPlaceholder extends StatelessWidget {
children: [ children: [
Icon( Icon(
icon, icon,
color: Theme.of(context).colorScheme.onBackground, color: Theme.of(context).colorScheme.onSurface,
), ),
const SizedBox(height: Dimens.grid8), const SizedBox(height: Dimens.grid8),
Text( Text(
text, text,
style: Theme.of(context) style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: Theme.of(context).colorScheme.onSurface),
.textTheme
.bodyMedium
?.copyWith(color: Theme.of(context).colorScheme.onBackground),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],

View file

@ -21,10 +21,11 @@ class ReleaseNotesFlow extends StatelessWidget {
child: BlocListener<ReleaseNotesBloc, ReleaseNotesState>( child: BlocListener<ReleaseNotesBloc, ReleaseNotesState>(
listener: (context, state) { listener: (context, state) {
if (state is ShowReleaseNotesDialogState) { if (state is ShowReleaseNotesDialogState) {
final bloc = context.read<ReleaseNotesBloc>();
showDialog( showDialog(
context: context, context: context,
builder: (_) => ReleaseNotesDialog(version: state.version), builder: (_) => ReleaseNotesDialog(version: state.version),
).then((_) => context.read<ReleaseNotesBloc>().setChangelogVersion()); ).then((_) => bloc.setChangelogVersion());
} }
}, },
child: child, child: child,

View file

@ -30,7 +30,7 @@ class RulerSlider extends StatelessWidget {
children: [ children: [
Text( Text(
valueAdapter(value), valueAdapter(value),
style: Theme.of(context).textTheme.labelLarge!.copyWith(color: Theme.of(context).colorScheme.onBackground), style: Theme.of(context).textTheme.labelLarge!.copyWith(color: Theme.of(context).colorScheme.onSurface),
), ),
const SizedBox(height: Dimens.grid4), const SizedBox(height: Dimens.grid4),
Expanded( Expanded(
@ -78,7 +78,7 @@ class _Ruler extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final mainTicksFontSize = Theme.of(context).textTheme.bodySmall!.fontSize!; final mainTicksFontSize = Theme.of(context).textTheme.bodySmall!.fontSize!;
final itemsColor = Theme.of(context).colorScheme.onBackground; final itemsColor = Theme.of(context).colorScheme.onSurface;
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final bool showAllMainTicks = final bool showAllMainTicks =

View file

@ -0,0 +1,12 @@
import 'dart:ui';
extension ColorToInt on Color {
int toInt() {
final a = (this.a * 255).round();
final r = (this.r * 255).round();
final g = (this.g * 255).round();
final b = (this.b * 255).round();
return (a << 24) | (r << 16) | (g << 8) | b;
}
}

1565
pubspec.lock Normal file

File diff suppressed because it is too large Load diff

View file

@ -7,61 +7,61 @@ environment:
sdk: ">=3.0.0 <4.0.0" sdk: ">=3.0.0 <4.0.0"
dependencies: dependencies:
app_settings: 4.2.0 app_settings: 5.1.1
auto_size_text: 3.0.0 auto_size_text: 3.0.0
bloc_concurrency: 0.2.2 bloc_concurrency: 0.3.0
camera: 0.10.5+2 camera: 0.11.0+2
camera_android_camerax: 0.6.1+1
clipboard: 0.1.3 clipboard: 0.1.3
collection: any collection: any
dynamic_color: 1.7.0 dynamic_color: 1.7.0
exif: 3.1.4 exif: 3.3.0
firebase_analytics: 10.6.2 firebase_analytics: 11.4.0
firebase_core: 2.20.0 firebase_core: 3.10.0
firebase_crashlytics: 3.4.2 firebase_crashlytics: 4.3.0
firebase_remote_config: 4.3.2 firebase_remote_config: 5.3.0
flutter: flutter:
sdk: flutter sdk: flutter
flutter_bloc: 8.1.3 flutter_bloc: 9.0.0
flutter_localizations: flutter_localizations:
sdk: flutter sdk: flutter
flutter_native_splash: 2.3.5 flutter_native_splash: 2.4.4
intl: 0.18.1 intl: 0.19.0
intl_utils: 2.8.2 intl_utils: 2.8.7
light_sensor: 3.0.0 light_sensor: 3.0.1
m3_lightmeter_iap: m3_lightmeter_iap:
git: git:
url: "https://github.com/vodemn/m3_lightmeter_iap" url: "https://github.com/vodemn/m3_lightmeter_iap"
ref: v2.1.0 ref: v2.1.1
m3_lightmeter_resources: m3_lightmeter_resources:
git: git:
url: "https://github.com/vodemn/m3_lightmeter_resources" url: "https://github.com/vodemn/m3_lightmeter_resources"
ref: v2.1.0 ref: v2.1.0
material_color_utilities: 0.5.0 material_color_utilities: 0.12.0
package_info_plus: 4.2.0 package_info_plus: 8.1.3
permission_handler: 10.4.3 permission_handler: 11.3.1
platform: 3.1.0 platform: 3.1.5
shared_preferences: 2.2.0 shared_preferences: 2.3.5
url_launcher: 6.1.12 url_launcher:
uuid: 3.0.7 url_launcher_ios: 6.3.2
vibration: 1.8.1 uuid: 4.5.1
vibration: 2.0.1
dev_dependencies: dev_dependencies:
args: 2.5.0 args: 2.6.0
bloc_test: 9.1.3 bloc_test: 10.0.0
build_runner: 2.4.6 build_runner: 2.4.14
flutter_test: flutter_test:
sdk: flutter sdk: flutter
golden_toolkit: 0.15.0 golden_toolkit: 0.15.0
google_fonts: 3.0.1 google_fonts: 6.2.1
image: 4.1.7 image: 4.3.0
integration_test: integration_test:
sdk: flutter sdk: flutter
lint: 2.1.2 lint: 2.3.0
logging: 1.2.0 logging: 1.3.0
meta: 1.9.1 meta: 1.15.0
mocktail: 0.3.0 mocktail: 1.0.4
test: 1.24.3 test: 1.25.8
dependency_overrides: dependency_overrides:
material_color_utilities: 0.11.1 material_color_utilities: 0.11.1

View file

@ -22,6 +22,7 @@ import 'package:lightmeter/screens/metering/screen_metering.dart';
import 'package:lightmeter/screens/settings/screen_settings.dart'; import 'package:lightmeter/screens/settings/screen_settings.dart';
import 'package:lightmeter/screens/shared/animated_circular_button/widget_button_circular_animated.dart'; import 'package:lightmeter/screens/shared/animated_circular_button/widget_button_circular_animated.dart';
import 'package:lightmeter/screens/timer/screen_timer.dart'; import 'package:lightmeter/screens/timer/screen_timer.dart';
import 'package:lightmeter/utils/color_to_int.dart';
import 'package:lightmeter/utils/platform_utils.dart'; import 'package:lightmeter/utils/platform_utils.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -77,7 +78,7 @@ void main() {
/// Theme settings /// Theme settings
UserPreferencesService.themeTypeKey: theme.index, UserPreferencesService.themeTypeKey: theme.index,
UserPreferencesService.primaryColorKey: color.value, UserPreferencesService.primaryColorKey: color.toInt(),
UserPreferencesService.dynamicColorKey: false, UserPreferencesService.dynamicColorKey: false,
UserPreferencesService.seenChangelogVersionKey: await const PlatformUtils().version, UserPreferencesService.seenChangelogVersionKey: await const PlatformUtils().version,
@ -190,7 +191,7 @@ extension on WidgetTester {
name: name, name: name,
deviceName: const String.fromEnvironment('deviceName'), deviceName: const String.fromEnvironment('deviceName'),
platformFolder: _platformFolder, platformFolder: _platformFolder,
backgroundColor: backgroundColor.value.toRadixString(16), backgroundColor: backgroundColor.toInt().toRadixString(16),
isDark: theme.brightness == Brightness.dark, isDark: theme.brightness == Brightness.dark,
).toString(), ).toString(),
); );

View file

@ -47,7 +47,7 @@ class WidgetTestApplicationMock extends StatelessWidget {
], ],
supportedLocales: S.delegate.supportedLocales, supportedLocales: S.delegate.supportedLocales,
builder: (context, child) => MediaQuery( builder: (context, child) => MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
child: child!, child: child!,
), ),
home: Scaffold(body: child), home: Scaffold(body: child),
@ -124,7 +124,7 @@ class _GoldenTestApplicationMockState extends State<GoldenTestApplicationMock> {
], ],
supportedLocales: S.delegate.supportedLocales, supportedLocales: S.delegate.supportedLocales,
builder: (context, child) => MediaQuery( builder: (context, child) => MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0), data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
child: child!, child: child!,
), ),
home: widget.child, home: widget.child,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 301 KiB

After

Width:  |  Height:  |  Size: 301 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 494 KiB

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 858 KiB

After

Width:  |  Height:  |  Size: 863 KiB