This commit is contained in:
Vadim 2025-01-06 14:34:47 +00:00 committed by GitHub
commit 5264dd7cfa
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 1711 additions and 437 deletions

View file

@ -121,7 +121,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

@ -116,7 +116,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

@ -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

@ -31,7 +31,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 app - name: Prepare app
run: | run: |

1
.gitignore vendored
View file

@ -48,7 +48,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/

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
}, },

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

@ -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

@ -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,7 @@
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 */,
); );
buildRules = ( buildRules = (
); );
@ -171,7 +172,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 +215,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;
@ -292,11 +310,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 +323,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 +400,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 +415,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 +485,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 +534,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 +551,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 +581,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 +654,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 +668,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 +733,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 +750,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 +814,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 +829,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

@ -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,24 +25,30 @@ class WriteEmailListTile extends StatelessWidget {
mailToUrl, mailToUrl,
mode: LaunchMode.externalApplication, mode: LaunchMode.externalApplication,
); );
} else { } else if (mounted) {
ScaffoldMessenger.of(context).showSnackBar( _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();
});
},
),
),
);
} }
}); });
}, },
); );
} }
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();
}
});
},
),
),
);
}
} }

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;
}
}

1541
pubspec.lock Normal file

File diff suppressed because it is too large Load diff

View file

@ -7,27 +7,26 @@ 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.2.5
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: 10.6.2
firebase_core: 2.20.0 firebase_core: 2.20.0
firebase_crashlytics: 3.4.2 firebase_crashlytics: 3.4.2
firebase_remote_config: 4.3.2 firebase_remote_config: 4.3.2
flutter: flutter:
sdk: flutter sdk: flutter
flutter_bloc: 8.1.3 flutter_bloc: ^8.1.6
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.0
m3_lightmeter_iap: m3_lightmeter_iap:
git: git:
@ -39,29 +38,30 @@ dependencies:
ref: v2.1.0 ref: v2.1.0
material_color_utilities: 0.5.0 material_color_utilities: 0.5.0
package_info_plus: 4.2.0 package_info_plus: 4.2.0
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.2.0
url_launcher: 6.1.12 url_launcher:
url_launcher_ios: ^6.3.2
uuid: 3.0.7 uuid: 3.0.7
vibration: 1.8.1 vibration: ^2.0.1
dev_dependencies: dev_dependencies:
args: 2.5.0 args: ^2.6.0
bloc_test: 9.1.3 bloc_test: ^9.1.7
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: ^4.0.4
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