Merge 1b86b717ee
into fd97fc7fef
2
.github/workflows/build_apk.yml
vendored
|
@ -121,7 +121,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: |
|
||||
|
|
2
.github/workflows/build_ipa.yml
vendored
|
@ -116,7 +116,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: |
|
||||
|
|
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: |
|
||||
|
|
2
.github/workflows/run_integration_tests.yml
vendored
|
@ -31,7 +31,7 @@ jobs:
|
|||
- uses: subosito/flutter-action@v2
|
||||
with:
|
||||
channel: "stable"
|
||||
flutter-version: "3.13.9"
|
||||
flutter-version: "3.27.1"
|
||||
|
||||
- name: Prepare app
|
||||
run: |
|
||||
|
|
1
.gitignore
vendored
|
@ -48,7 +48,6 @@ app.*.map.json
|
|||
/ios/build/
|
||||
/ios/Runner.xcodeproj/project.pbxproj
|
||||
|
||||
pubspec.lock
|
||||
/ios/Podfile.lock
|
||||
|
||||
.fvm/
|
||||
|
|
2
.vscode/settings.json
vendored
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"task.slowProviderWarning": true,
|
||||
"dart.flutterSdkPath": "fvm",
|
||||
"dart.flutterSdkPath": ".fvm/flutter_sdk",
|
||||
"search.exclude": {
|
||||
"**/.fvm": true
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -21,6 +21,6 @@
|
|||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>11.0</string>
|
||||
<string>12.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
10
ios/Podfile
|
@ -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,7 @@
|
|||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
45F53C083F2EA48EF231DA16 /* [CP] Embed Pods Frameworks */,
|
||||
FF00F85CE432774850A0EDB7 /* [firebase_crashlytics] Crashlytics Upload Symbols */,
|
||||
08127035D2CDEEEBA66FCDBB /* [CP] Copy Pods Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
|
@ -171,7 +172,7 @@
|
|||
97C146E61CF9000F007C117D /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 1300;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
97C146ED1CF9000F007C117D = {
|
||||
|
@ -214,6 +215,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;
|
||||
|
@ -292,11 +310,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 +323,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 +400,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 +415,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 +485,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 +534,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 +551,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 +581,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 +654,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 +668,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 +733,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 +750,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 +814,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 +829,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,
|
||||
|
|
|
@ -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,7 +25,15 @@ class WriteEmailListTile extends StatelessWidget {
|
|||
mailToUrl,
|
||||
mode: LaunchMode.externalApplication,
|
||||
);
|
||||
} else {
|
||||
} else if (mounted) {
|
||||
_showSnackBar();
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _showSnackBar() async {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(S.of(context).youDontHaveMailApp),
|
||||
|
@ -29,15 +42,13 @@ class WriteEmailListTile extends StatelessWidget {
|
|||
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;
|
||||
}
|
||||
}
|
1541
pubspec.lock
Normal file
46
pubspec.yaml
|
@ -7,27 +7,26 @@ 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.2.5
|
||||
camera: ^0.11.0+2
|
||||
clipboard: 0.1.3
|
||||
collection: any
|
||||
dynamic_color: 1.7.0
|
||||
exif: 3.1.4
|
||||
exif: ^3.3.0
|
||||
firebase_analytics: 10.6.2
|
||||
firebase_core: 2.20.0
|
||||
firebase_crashlytics: 3.4.2
|
||||
firebase_remote_config: 4.3.2
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_bloc: 8.1.3
|
||||
flutter_bloc: ^8.1.6
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
flutter_native_splash: 2.3.5
|
||||
intl: 0.18.1
|
||||
intl_utils: 2.8.2
|
||||
flutter_native_splash: ^2.4.4
|
||||
intl: ^0.19.0
|
||||
intl_utils: ^2.8.7
|
||||
light_sensor: 3.0.0
|
||||
m3_lightmeter_iap:
|
||||
git:
|
||||
|
@ -39,29 +38,30 @@ dependencies:
|
|||
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
|
||||
permission_handler: ^11.3.1
|
||||
platform: ^3.1.5
|
||||
shared_preferences: 2.2.0
|
||||
url_launcher: 6.1.12
|
||||
url_launcher:
|
||||
url_launcher_ios: ^6.3.2
|
||||
uuid: 3.0.7
|
||||
vibration: 1.8.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: ^9.1.7
|
||||
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: ^4.0.4
|
||||
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 |