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
3
.fvmrc
Normal file
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"flutter": "3.27.1"
|
||||
}
|
11
.github/workflows/build_apk.yml
vendored
|
@ -90,7 +90,7 @@ jobs:
|
|||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: "zulu"
|
||||
java-version: "11"
|
||||
java-version: "17"
|
||||
|
||||
- name: Restore Android keystore .jsk and .properties files
|
||||
run: |
|
||||
|
@ -100,8 +100,10 @@ jobs:
|
|||
- name: Restore 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
|
||||
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_OPTIONS }}" "lib/firebase_options.dart"
|
||||
- name: Setup Firebase
|
||||
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
|
||||
env:
|
||||
|
@ -112,6 +114,7 @@ jobs:
|
|||
run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Download release notes
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||
|
@ -121,7 +124,7 @@ jobs:
|
|||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version: "3.13.9"
|
||||
flutter-version: "3.27.1"
|
||||
|
||||
- name: Prepare flutter project
|
||||
run: |
|
||||
|
|
16
.github/workflows/build_ipa.yml
vendored
|
@ -45,7 +45,7 @@ env:
|
|||
jobs:
|
||||
build:
|
||||
name: Build .ipa
|
||||
runs-on: macos-13
|
||||
runs-on: macos-latest
|
||||
timeout-minutes: 60
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
@ -92,11 +92,11 @@ jobs:
|
|||
- name: Restore 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
|
||||
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_APP_ID_FILE }}" "ios/firebase_app_id_file.json"
|
||||
|
||||
- name: Restore firebase_options.dart
|
||||
run: bash .github/scripts/restore_from_base64.sh "${{ secrets.FIREBASE_OPTIONS }}" "lib/firebase_options.dart"
|
||||
- name: Setup Firebase
|
||||
run: |
|
||||
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"
|
||||
|
||||
- name: Restore constants.dart
|
||||
env:
|
||||
|
@ -107,6 +107,7 @@ jobs:
|
|||
run: bash ./.github/scripts/increment_build_number.sh ${{ github.event.inputs.version }}
|
||||
|
||||
- name: Download release notes
|
||||
continue-on-error: true
|
||||
uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: ${{ env.RELEASE_NOTES_ARTIFACT_NAME }}
|
||||
|
@ -116,13 +117,14 @@ jobs:
|
|||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version: "3.13.9"
|
||||
flutter-version: "3.27.1"
|
||||
|
||||
- name: Prepare flutter project
|
||||
run: |
|
||||
flutter --version
|
||||
flutter pub get
|
||||
flutter pub run intl_utils:generate
|
||||
dart pub global activate flutterfire_cli
|
||||
|
||||
- name: Build .ipa
|
||||
run: |
|
||||
|
|
2
.github/workflows/pr_check.yml
vendored
|
@ -42,7 +42,7 @@ jobs:
|
|||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version: "3.13.9"
|
||||
flutter-version: "3.27.1"
|
||||
|
||||
- name: Prepare flutter project
|
||||
run: |
|
||||
|
|
4
.github/workflows/run_integration_tests.yml
vendored
|
@ -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.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_JSON }}" "firebase.json"
|
||||
|
||||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version: "3.13.9"
|
||||
flutter-version: "3.27.1"
|
||||
|
||||
- name: Prepare app
|
||||
run: |
|
||||
|
@ -39,6 +40,7 @@ jobs:
|
|||
flutter pub get
|
||||
flutter pub run intl_utils:generate
|
||||
flutter analyze lib --fatal-infos
|
||||
dart pub global activate flutterfire_cli
|
||||
|
||||
- name: Launch iOS simulator
|
||||
uses: futureware-tech/simulator-action@v3
|
||||
|
|
7
.gitignore
vendored
|
@ -5,9 +5,11 @@
|
|||
*.swp
|
||||
.DS_Store
|
||||
.atom/
|
||||
.build/
|
||||
.buildlog/
|
||||
.history
|
||||
.svn/
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
# IntelliJ related
|
||||
|
@ -48,7 +50,6 @@ app.*.map.json
|
|||
/ios/build/
|
||||
/ios/Runner.xcodeproj/project.pbxproj
|
||||
|
||||
pubspec.lock
|
||||
/ios/Podfile.lock
|
||||
|
||||
.fvm/
|
||||
|
@ -63,4 +64,6 @@ ios/Runner/GoogleService-Info.plist
|
|||
coverage/
|
||||
test/coverage_helper_test.dart
|
||||
**/failures/*.png
|
||||
screenshots/generated/raw/
|
||||
screenshots/generated/raw/
|
||||
|
||||
firebase.json
|
44
.vscode/settings.json
vendored
|
@ -1,25 +1,25 @@
|
|||
{
|
||||
"task.slowProviderWarning": true,
|
||||
"dart.flutterSdkPath": "fvm",
|
||||
"search.exclude": {
|
||||
"**/.fvm": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/.fvm": true
|
||||
},
|
||||
"dart.lineLength": 120,
|
||||
"[dart]": {
|
||||
"editor.rulers": [
|
||||
120,
|
||||
],
|
||||
"editor.selectionHighlight": true,
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||
"editor.suggestSelection": "first",
|
||||
"editor.tabCompletion": "onlySnippets",
|
||||
"editor.wordBasedSuggestions": "off"
|
||||
},
|
||||
"dart.doNotFormat": [
|
||||
"**/generated/**",
|
||||
"lib/data/**"
|
||||
"task.slowProviderWarning": true,
|
||||
"dart.flutterSdkPath": ".fvm/flutter_sdk",
|
||||
"search.exclude": {
|
||||
"**/.fvm": true
|
||||
},
|
||||
"files.watcherExclude": {
|
||||
"**/.fvm": true
|
||||
},
|
||||
"dart.lineLength": 120,
|
||||
"[dart]": {
|
||||
"editor.rulers": [
|
||||
120
|
||||
],
|
||||
"editor.selectionHighlight": true,
|
||||
"editor.suggest.snippetsPreventQuickSuggestions": false,
|
||||
"editor.suggestSelection": "first",
|
||||
"editor.tabCompletion": "onlySnippets",
|
||||
"editor.wordBasedSuggestions": "off"
|
||||
},
|
||||
"dart.doNotFormat": [
|
||||
"**/generated/**",
|
||||
"lib/data/**"
|
||||
]
|
||||
}
|
|
@ -34,7 +34,7 @@ Without further delay behold my new Lightmeter app inspired by Material You (a.k
|
|||
|
||||
### 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
|
||||
|
||||
|
|
|
@ -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 localPropertiesFile = rootProject.file('local.properties')
|
||||
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')
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = '1'
|
||||
|
@ -27,15 +30,9 @@ if (keystorePropertiesFile.exists()) {
|
|||
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 {
|
||||
compileSdkVersion 34
|
||||
ndkVersion flutter.ndkVersion
|
||||
ndkVersion "27.0.12077973"
|
||||
|
||||
compileOptions {
|
||||
sourceCompatibility JavaVersion.VERSION_1_8
|
||||
|
@ -43,7 +40,7 @@ android {
|
|||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = '1.8'
|
||||
jvmTarget = JavaVersion.VERSION_1_8
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
|
@ -51,7 +48,7 @@ android {
|
|||
}
|
||||
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
minSdkVersion 23
|
||||
targetSdkVersion 34
|
||||
ndk {
|
||||
debugSymbolLevel 'FULL'
|
||||
|
@ -101,6 +98,7 @@ android {
|
|||
}
|
||||
}
|
||||
}
|
||||
namespace 'com.vodemn.lightmeter'
|
||||
}
|
||||
|
||||
flutter {
|
||||
|
@ -108,7 +106,6 @@ flutter {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
|
||||
implementation "com.android.billingclient:billing-ktx:6.0.0"
|
||||
implementation "com.google.firebase:firebase-analytics:17.4.1"
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.vodemn.lightmeter">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
package="com.vodemn.lightmeter">
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<application
|
||||
android:label="@string/app_name"
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.vodemn.lightmeter">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<!-- The INTERNET permission is required for development. Specifically,
|
||||
the Flutter tool needs it to communicate with the running application
|
||||
to allow setting breakpoints, to provide hot reload, etc.
|
||||
|
|
|
@ -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 {
|
||||
repositories {
|
||||
google()
|
||||
|
|
|
@ -1,3 +1,6 @@
|
|||
org.gradle.jvmargs=-Xmx1536M
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
android.defaults.buildfeatures.buildconfig=true
|
||||
android.nonTransitiveRClass=false
|
||||
android.nonFinalResIds=false
|
||||
|
|
|
@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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
|
||||
|
|
|
@ -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")
|
||||
def properties = new Properties()
|
||||
includeBuild("$flutterSdkPath/packages/flutter_tools/gradle")
|
||||
|
||||
assert localPropertiesFile.exists()
|
||||
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
|
||||
repositories {
|
||||
google()
|
||||
mavenCentral()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
|
||||
plugins {
|
||||
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||
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"
|
|
@ -13,7 +13,7 @@ dependencies:
|
|||
git:
|
||||
url: "https://github.com/vodemn/m3_lightmeter_resources"
|
||||
ref: v2.1.0
|
||||
shared_preferences: 2.2.0
|
||||
shared_preferences:
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>11.0</string>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
12
ios/Podfile
|
@ -1,5 +1,5 @@
|
|||
# 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.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
@ -36,6 +36,16 @@ end
|
|||
|
||||
post_install do |installer|
|
||||
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)
|
||||
|
||||
target.build_configurations.each do |config|
|
||||
|
|
|
@ -155,6 +155,8 @@
|
|||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
45F53C083F2EA48EF231DA16 /* [CP] Embed Pods Frameworks */,
|
||||
FF00F85CE432774850A0EDB7 /* [firebase_crashlytics] Crashlytics Upload Symbols */,
|
||||
08127035D2CDEEEBA66FCDBB /* [CP] Copy Pods Resources */,
|
||||
6F6C086A620B15784F8BE312 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -171,7 +173,7 @@
|
|||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
|
@ -214,6 +216,23 @@
|
|||
/* End PBXResourcesBuildPhase 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 */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@ -269,6 +288,24 @@
|
|||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
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 */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
@ -292,11 +329,11 @@
|
|||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"\"${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/Info.plist\"",
|
||||
"\"$(TARGET_BUILD_DIR)/$(EXECUTABLE_PATH)\"",
|
||||
"\"$(PROJECT_DIR)/firebase_app_id_file.json\"",
|
||||
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}",
|
||||
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${PRODUCT_NAME}",
|
||||
"${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Info.plist",
|
||||
"$(BUILT_PRODUCTS_DIR)/$(UNLOCALIZED_RESOURCES_FOLDER_PATH)/GoogleService-Info.plist",
|
||||
"$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)",
|
||||
);
|
||||
name = "[firebase_crashlytics] Crashlytics Upload Symbols";
|
||||
outputFileListPaths = (
|
||||
|
@ -305,7 +342,7 @@
|
|||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
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 */
|
||||
|
||||
|
@ -382,7 +419,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -397,6 +434,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod";
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
@ -466,7 +504,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -515,7 +553,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -532,6 +570,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod";
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
@ -561,6 +600,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-prod";
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
|
@ -633,7 +673,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
|
@ -647,6 +687,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev";
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
@ -711,7 +752,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -728,6 +769,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev";
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
@ -791,7 +833,7 @@
|
|||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 11.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
@ -806,6 +848,7 @@
|
|||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = "AppIcon-dev";
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = NO;
|
||||
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import UIKit
|
||||
import Flutter
|
||||
|
||||
@UIApplicationMain
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
|
|
|
@ -44,7 +44,7 @@ class Application extends StatelessWidget {
|
|||
],
|
||||
supportedLocales: S.delegate.supportedLocales,
|
||||
builder: (context, child) => MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
|
||||
data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
|
||||
child: child!,
|
||||
),
|
||||
initialRoute: NavigationRoutes.meteringScreen.name,
|
||||
|
|
|
@ -22,7 +22,7 @@ class LightmeterAnalytics {
|
|||
|
||||
Future<void> logEvent(
|
||||
String eventName, {
|
||||
Map<String, dynamic>? parameters,
|
||||
Map<String, Object>? parameters,
|
||||
}) async {
|
||||
if (!kReleaseMode) {
|
||||
log('<LightmeterAnalytics> logEvent: $eventName / $parameters');
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
abstract class ILightmeterAnalyticsApi {
|
||||
Future<void> logEvent(
|
||||
String eventName, {
|
||||
Map<String, dynamic>? parameters,
|
||||
Map<String, Object>? parameters,
|
||||
});
|
||||
|
||||
Future<void> logCrash(
|
||||
|
|
|
@ -10,7 +10,7 @@ class LightmeterAnalyticsFirebase implements ILightmeterAnalyticsApi {
|
|||
@override
|
||||
Future<void> logEvent(
|
||||
String eventName, {
|
||||
Map<String, dynamic>? parameters,
|
||||
Map<String, Object>? parameters,
|
||||
}) async {
|
||||
try {
|
||||
await FirebaseAnalytics.instance.logEvent(
|
||||
|
|
|
@ -8,7 +8,7 @@ typedef MeteringScreenLayoutConfig = Map<MeteringScreenLayoutFeature, bool>;
|
|||
|
||||
extension MeteringScreenLayoutConfigJson on MeteringScreenLayoutConfig {
|
||||
static MeteringScreenLayoutConfig fromJson(Map<String, dynamic> data) {
|
||||
int? migratedIndex(MeteringScreenLayoutFeature feature) {
|
||||
int migratedIndex(MeteringScreenLayoutFeature feature) {
|
||||
switch (feature) {
|
||||
case MeteringScreenLayoutFeature.extremeExposurePairs:
|
||||
return 0;
|
||||
|
@ -16,8 +16,6 @@ extension MeteringScreenLayoutConfigJson on MeteringScreenLayoutConfig {
|
|||
return 1;
|
||||
case MeteringScreenLayoutFeature.equipmentProfiles:
|
||||
return 3;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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/theme_type.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:shared_preferences/shared_preferences.dart';
|
||||
|
||||
|
@ -155,7 +156,7 @@ class UserPreferencesService {
|
|||
set themeType(ThemeType value) => _sharedPreferences.setInt(themeTypeKey, value.index);
|
||||
|
||||
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;
|
||||
set dynamicColor(bool value) => _sharedPreferences.setBool(dynamicColorKey, value);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:lightmeter/res/dimens.dart';
|
||||
import 'package:lightmeter/utils/color_to_int.dart';
|
||||
import 'package:material_color_utilities/material_color_utilities.dart';
|
||||
|
||||
const primaryColorsList = [
|
||||
|
@ -32,7 +33,7 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
|
|||
elevation: Dimens.elevationLevel0,
|
||||
scrolledUnderElevation: Dimens.elevationLevel2,
|
||||
color: scheme.surface,
|
||||
foregroundColor: scheme.onBackground,
|
||||
foregroundColor: scheme.onSurface,
|
||||
surfaceTintColor: scheme.surfaceTint,
|
||||
),
|
||||
cardTheme: CardTheme(
|
||||
|
@ -75,15 +76,13 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
|
|||
|
||||
ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
|
||||
final scheme = SchemeTonalSpot(
|
||||
sourceColorHct: Hct.fromInt(primaryColor.value),
|
||||
sourceColorHct: Hct.fromInt(primaryColor.toInt()),
|
||||
isDark: brightness == Brightness.dark,
|
||||
contrastLevel: 0.0,
|
||||
);
|
||||
|
||||
return ColorScheme(
|
||||
brightness: brightness,
|
||||
background: Color(scheme.background),
|
||||
onBackground: Color(scheme.onBackground),
|
||||
error: Color(scheme.error),
|
||||
onError: Color(scheme.onError),
|
||||
errorContainer: Color(scheme.errorContainer),
|
||||
|
@ -102,7 +101,7 @@ ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
|
|||
onTertiaryContainer: Color(scheme.onTertiaryContainer),
|
||||
surface: Color(scheme.surface),
|
||||
onSurface: Color(scheme.onSurface),
|
||||
surfaceVariant: Color(scheme.surfaceVariant),
|
||||
surfaceContainerHighest: Color(scheme.surfaceContainerHighest),
|
||||
onSurfaceVariant: Color(scheme.onSurfaceVariant),
|
||||
outline: Color(scheme.outline),
|
||||
outlineVariant: Color(scheme.outlineVariant),
|
||||
|
|
|
@ -91,7 +91,6 @@ class CameraContainerBloc extends EvSourceBlocBase<CameraContainerEvent, CameraC
|
|||
case communication_states.SettingsClosedState():
|
||||
_settingsOpened = false;
|
||||
add(const InitializeEvent());
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ class CameraControlsPlaceholder extends StatelessWidget {
|
|||
const SizedBox(height: Dimens.grid8),
|
||||
Text(
|
||||
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,
|
||||
),
|
||||
],
|
||||
|
|
|
@ -62,14 +62,14 @@ class _Title<T extends PhotographyStopValue> extends StatelessWidget {
|
|||
value.toString(),
|
||||
stepGranularity: 0.5,
|
||||
minFontSize: 10,
|
||||
style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onBackground),
|
||||
style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onSurface),
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 1,
|
||||
)
|
||||
: Text(
|
||||
value.toString(),
|
||||
style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onBackground),
|
||||
style: labelTextStyle(context).copyWith(color: Theme.of(context).colorScheme.onSurface),
|
||||
softWrap: false,
|
||||
overflow: TextOverflow.fade,
|
||||
maxLines: 1,
|
||||
|
@ -97,7 +97,7 @@ class _Tick extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ColoredBox(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
child: SizedBox(
|
||||
height: 1,
|
||||
width: _length,
|
||||
|
|
|
@ -78,7 +78,7 @@ class ExposurePairsList extends StatelessWidget {
|
|||
? constraints.maxHeight / 2
|
||||
: constraints.maxHeight,
|
||||
child: ColoredBox(
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
child: const SizedBox(width: 1),
|
||||
),
|
||||
),
|
||||
|
|
|
@ -178,8 +178,8 @@ class AnimatedDialogState extends State<AnimatedDialog> with SingleTickerProvide
|
|||
opaque: false,
|
||||
transitionDuration: Duration.zero,
|
||||
reverseTransitionDuration: Duration.zero,
|
||||
pageBuilder: (_, __, ___) => WillPopScope(
|
||||
onWillPop: () => _animateReverse().then((value) => true),
|
||||
pageBuilder: (_, __, ___) => PopScope(
|
||||
onPopInvokedWithResult: (_, __) => _animateReverse().then((value) => true),
|
||||
child: _AnimatedOverlay(
|
||||
controller: _animationController,
|
||||
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 {
|
||||
|
|
|
@ -69,9 +69,14 @@ class MeteringScreen extends StatelessWidget {
|
|||
}
|
||||
|
||||
void pushNamed(BuildContext context, String routeName, {Object? arguments}) {
|
||||
context.read<MeteringBloc>().add(const ScreenOnTopOpenedEvent());
|
||||
Navigator.pushNamed(context, routeName, arguments: arguments).then((_) {
|
||||
context.read<MeteringBloc>().add(const ScreenOnTopClosedEvent());
|
||||
final bloc = context.read<MeteringBloc>();
|
||||
bloc.add(const ScreenOnTopOpenedEvent());
|
||||
Navigator.pushNamed(
|
||||
context,
|
||||
routeName,
|
||||
arguments: arguments,
|
||||
).then((_) {
|
||||
bloc.add(const ScreenOnTopClosedEvent());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,9 +4,14 @@ import 'package:lightmeter/constants.dart';
|
|||
import 'package:lightmeter/generated/l10n.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class WriteEmailListTile extends StatelessWidget {
|
||||
class WriteEmailListTile extends StatefulWidget {
|
||||
const WriteEmailListTile({super.key});
|
||||
|
||||
@override
|
||||
State<WriteEmailListTile> createState() => _WriteEmailListTileState();
|
||||
}
|
||||
|
||||
class _WriteEmailListTileState extends State<WriteEmailListTile> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
|
@ -20,24 +25,30 @@ class WriteEmailListTile extends StatelessWidget {
|
|||
mailToUrl,
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(S.of(context).youDontHaveMailApp),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
action: SnackBarAction(
|
||||
label: S.of(context).copyEmail,
|
||||
onPressed: () {
|
||||
FlutterClipboard.copy(contactEmail).then((_) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
} else if (mounted) {
|
||||
_showSnackBar();
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showSnackBar() async {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(S.of(context).youDontHaveMailApp),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
action: SnackBarAction(
|
||||
label: S.of(context).copyEmail,
|
||||
onPressed: () {
|
||||
FlutterClipboard.copy(contactEmail).then((_) {
|
||||
if (mounted) {
|
||||
ScaffoldMessenger.of(context).clearSnackBars();
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ class LanguageListTile extends StatelessWidget {
|
|||
title: Text(S.of(context).language),
|
||||
trailing: Text(UserPreferencesProvider.localeOf(context).localizedName),
|
||||
onTap: () {
|
||||
final prefs = UserPreferencesProvider.of(context);
|
||||
showDialog<SupportedLocale>(
|
||||
context: context,
|
||||
builder: (_) => DialogPicker<SupportedLocale>(
|
||||
|
@ -21,11 +22,11 @@ class LanguageListTile extends StatelessWidget {
|
|||
title: S.of(context).chooseLanguage,
|
||||
selectedValue: UserPreferencesProvider.localeOf(context),
|
||||
values: SupportedLocale.values,
|
||||
titleAdapter: (context, value) => value.localizedName,
|
||||
titleAdapter: (_, value) => value.localizedName,
|
||||
),
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
UserPreferencesProvider.of(context).setLocale(value);
|
||||
prefs.setLocale(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -14,6 +14,7 @@ class StopTypeListTile extends StatelessWidget {
|
|||
title: Text(S.of(context).fractionalStops),
|
||||
trailing: Text(_typeToString(context, UserPreferencesProvider.stopTypeOf(context))),
|
||||
onTap: () {
|
||||
final prefs = UserPreferencesProvider.of(context);
|
||||
showDialog<StopType>(
|
||||
context: context,
|
||||
builder: (_) => DialogPicker<StopType>(
|
||||
|
@ -25,7 +26,7 @@ class StopTypeListTile extends StatelessWidget {
|
|||
),
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
UserPreferencesProvider.of(context).setStopType(value);
|
||||
prefs.setStopType(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -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),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@ import 'package:lightmeter/generated/l10n.dart';
|
|||
import 'package:lightmeter/res/dimens.dart';
|
||||
import 'package:lightmeter/res/theme.dart';
|
||||
import 'package:lightmeter/screens/shared/filled_circle/widget_circle_filled.dart';
|
||||
import 'package:lightmeter/utils/color_to_int.dart';
|
||||
|
||||
class PrimaryColorDialogPicker extends StatefulWidget {
|
||||
const PrimaryColorDialogPicker({super.key});
|
||||
|
@ -45,7 +46,7 @@ class _PrimaryColorDialogPickerState extends State<PrimaryColorDialogPicker> {
|
|||
padding: EdgeInsets.only(left: index == 0 ? 0 : Dimens.paddingS),
|
||||
child: _SelectableColorItem(
|
||||
color: color,
|
||||
selected: color.value == _selected.value,
|
||||
selected: color.toInt() == _selected.toInt(),
|
||||
onTap: () {
|
||||
setState(() {
|
||||
_selected = color;
|
||||
|
|
|
@ -22,12 +22,13 @@ class PrimaryColorListTile extends StatelessWidget {
|
|||
leading: const Icon(Icons.palette_outlined),
|
||||
title: Text(S.of(context).primaryColor),
|
||||
onTap: () {
|
||||
final prefs = UserPreferencesProvider.of(context);
|
||||
showDialog<Color>(
|
||||
context: context,
|
||||
builder: (_) => const PrimaryColorDialogPicker(),
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
UserPreferencesProvider.of(context).setPrimaryColor(value);
|
||||
prefs.setPrimaryColor(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -14,6 +14,7 @@ class ThemeTypeListTile extends StatelessWidget {
|
|||
title: Text(S.of(context).theme),
|
||||
trailing: Text(_typeToString(context, UserPreferencesProvider.themeTypeOf(context))),
|
||||
onTap: () {
|
||||
final prefs = UserPreferencesProvider.of(context);
|
||||
showDialog<ThemeType>(
|
||||
context: context,
|
||||
builder: (_) => DialogPicker<ThemeType>(
|
||||
|
@ -25,7 +26,7 @@ class ThemeTypeListTile extends StatelessWidget {
|
|||
),
|
||||
).then((value) {
|
||||
if (value != null) {
|
||||
UserPreferencesProvider.of(context).setThemeType(value);
|
||||
prefs.setThemeType(value);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -120,7 +120,7 @@ class _Slider extends StatelessWidget {
|
|||
width: handleDistance + trackThickness,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(trackThickness / 2),
|
||||
child: ColoredBox(color: Theme.of(context).colorScheme.surfaceVariant),
|
||||
child: ColoredBox(color: Theme.of(context).colorScheme.surfaceContainerHighest),
|
||||
),
|
||||
),
|
||||
AnimatedPositioned.fromRect(
|
||||
|
|
|
@ -20,15 +20,12 @@ class IconPlaceholder extends StatelessWidget {
|
|||
children: [
|
||||
Icon(
|
||||
icon,
|
||||
color: Theme.of(context).colorScheme.onBackground,
|
||||
color: Theme.of(context).colorScheme.onSurface,
|
||||
),
|
||||
const SizedBox(height: Dimens.grid8),
|
||||
Text(
|
||||
text,
|
||||
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,
|
||||
),
|
||||
],
|
||||
|
|
|
@ -21,10 +21,11 @@ class ReleaseNotesFlow extends StatelessWidget {
|
|||
child: BlocListener<ReleaseNotesBloc, ReleaseNotesState>(
|
||||
listener: (context, state) {
|
||||
if (state is ShowReleaseNotesDialogState) {
|
||||
final bloc = context.read<ReleaseNotesBloc>();
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (_) => ReleaseNotesDialog(version: state.version),
|
||||
).then((_) => context.read<ReleaseNotesBloc>().setChangelogVersion());
|
||||
).then((_) => bloc.setChangelogVersion());
|
||||
}
|
||||
},
|
||||
child: child,
|
||||
|
|
|
@ -30,7 +30,7 @@ class RulerSlider extends StatelessWidget {
|
|||
children: [
|
||||
Text(
|
||||
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),
|
||||
Expanded(
|
||||
|
@ -78,7 +78,7 @@ class _Ruler extends StatelessWidget {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final mainTicksFontSize = Theme.of(context).textTheme.bodySmall!.fontSize!;
|
||||
final itemsColor = Theme.of(context).colorScheme.onBackground;
|
||||
final itemsColor = Theme.of(context).colorScheme.onSurface;
|
||||
return LayoutBuilder(
|
||||
builder: (context, constraints) {
|
||||
final bool showAllMainTicks =
|
||||
|
|
12
lib/utils/color_to_int.dart
Normal 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
66
pubspec.yaml
|
@ -7,61 +7,61 @@ environment:
|
|||
sdk: ">=3.0.0 <4.0.0"
|
||||
|
||||
dependencies:
|
||||
app_settings: 4.2.0
|
||||
app_settings: 5.1.1
|
||||
auto_size_text: 3.0.0
|
||||
bloc_concurrency: 0.2.2
|
||||
camera: 0.10.5+2
|
||||
camera_android_camerax: 0.6.1+1
|
||||
bloc_concurrency: 0.3.0
|
||||
camera: 0.11.0+2
|
||||
clipboard: 0.1.3
|
||||
collection: any
|
||||
dynamic_color: 1.7.0
|
||||
exif: 3.1.4
|
||||
firebase_analytics: 10.6.2
|
||||
firebase_core: 2.20.0
|
||||
firebase_crashlytics: 3.4.2
|
||||
firebase_remote_config: 4.3.2
|
||||
exif: 3.3.0
|
||||
firebase_analytics: 11.4.0
|
||||
firebase_core: 3.10.0
|
||||
firebase_crashlytics: 4.3.0
|
||||
firebase_remote_config: 5.3.0
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_bloc: 8.1.3
|
||||
flutter_bloc: 9.0.0
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_native_splash: 2.3.5
|
||||
intl: 0.18.1
|
||||
intl_utils: 2.8.2
|
||||
light_sensor: 3.0.0
|
||||
flutter_native_splash: 2.4.4
|
||||
intl: 0.19.0
|
||||
intl_utils: 2.8.7
|
||||
light_sensor: 3.0.1
|
||||
m3_lightmeter_iap:
|
||||
git:
|
||||
url: "https://github.com/vodemn/m3_lightmeter_iap"
|
||||
ref: v2.1.0
|
||||
ref: v2.1.1
|
||||
m3_lightmeter_resources:
|
||||
git:
|
||||
url: "https://github.com/vodemn/m3_lightmeter_resources"
|
||||
ref: v2.1.0
|
||||
material_color_utilities: 0.5.0
|
||||
package_info_plus: 4.2.0
|
||||
permission_handler: 10.4.3
|
||||
platform: 3.1.0
|
||||
shared_preferences: 2.2.0
|
||||
url_launcher: 6.1.12
|
||||
uuid: 3.0.7
|
||||
vibration: 1.8.1
|
||||
material_color_utilities: 0.12.0
|
||||
package_info_plus: 8.1.3
|
||||
permission_handler: 11.3.1
|
||||
platform: 3.1.5
|
||||
shared_preferences: 2.3.5
|
||||
url_launcher:
|
||||
url_launcher_ios: 6.3.2
|
||||
uuid: 4.5.1
|
||||
vibration: 2.0.1
|
||||
|
||||
dev_dependencies:
|
||||
args: 2.5.0
|
||||
bloc_test: 9.1.3
|
||||
build_runner: 2.4.6
|
||||
args: 2.6.0
|
||||
bloc_test: 10.0.0
|
||||
build_runner: 2.4.14
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
golden_toolkit: 0.15.0
|
||||
google_fonts: 3.0.1
|
||||
image: 4.1.7
|
||||
google_fonts: 6.2.1
|
||||
image: 4.3.0
|
||||
integration_test:
|
||||
sdk: flutter
|
||||
lint: 2.1.2
|
||||
logging: 1.2.0
|
||||
meta: 1.9.1
|
||||
mocktail: 0.3.0
|
||||
test: 1.24.3
|
||||
lint: 2.3.0
|
||||
logging: 1.3.0
|
||||
meta: 1.15.0
|
||||
mocktail: 1.0.4
|
||||
test: 1.25.8
|
||||
|
||||
dependency_overrides:
|
||||
material_color_utilities: 0.11.1
|
||||
|
|
|
@ -22,6 +22,7 @@ import 'package:lightmeter/screens/metering/screen_metering.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/timer/screen_timer.dart';
|
||||
import 'package:lightmeter/utils/color_to_int.dart';
|
||||
import 'package:lightmeter/utils/platform_utils.dart';
|
||||
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
@ -77,7 +78,7 @@ void main() {
|
|||
|
||||
/// Theme settings
|
||||
UserPreferencesService.themeTypeKey: theme.index,
|
||||
UserPreferencesService.primaryColorKey: color.value,
|
||||
UserPreferencesService.primaryColorKey: color.toInt(),
|
||||
UserPreferencesService.dynamicColorKey: false,
|
||||
|
||||
UserPreferencesService.seenChangelogVersionKey: await const PlatformUtils().version,
|
||||
|
@ -190,7 +191,7 @@ extension on WidgetTester {
|
|||
name: name,
|
||||
deviceName: const String.fromEnvironment('deviceName'),
|
||||
platformFolder: _platformFolder,
|
||||
backgroundColor: backgroundColor.value.toRadixString(16),
|
||||
backgroundColor: backgroundColor.toInt().toRadixString(16),
|
||||
isDark: theme.brightness == Brightness.dark,
|
||||
).toString(),
|
||||
);
|
||||
|
|
|
@ -47,7 +47,7 @@ class WidgetTestApplicationMock extends StatelessWidget {
|
|||
],
|
||||
supportedLocales: S.delegate.supportedLocales,
|
||||
builder: (context, child) => MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
|
||||
data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
|
||||
child: child!,
|
||||
),
|
||||
home: Scaffold(body: child),
|
||||
|
@ -124,7 +124,7 @@ class _GoldenTestApplicationMockState extends State<GoldenTestApplicationMock> {
|
|||
],
|
||||
supportedLocales: S.delegate.supportedLocales,
|
||||
builder: (context, child) => MediaQuery(
|
||||
data: MediaQuery.of(context).copyWith(textScaleFactor: 1.0),
|
||||
data: MediaQuery.of(context).copyWith(textScaler: TextScaler.noScaling),
|
||||
child: child!,
|
||||
),
|
||||
home: widget.child,
|
||||
|
|
Before Width: | Height: | Size: 301 KiB After Width: | Height: | Size: 301 KiB |
Before Width: | Height: | Size: 1.6 MiB After Width: | Height: | Size: 1.5 MiB |
Before Width: | Height: | Size: 494 KiB After Width: | Height: | Size: 498 KiB |
Before Width: | Height: | Size: 858 KiB After Width: | Height: | Size: 863 KiB |