Unified the app's color palette & icons (#176)

* unified scaffold background color

* unified components elevation

* use filled tonal icon buttons

* aligned slider colors with guidelines

* removed unused `CloseButton`

* migrated to outlined icons

* moved timer list tile to the top of the section

* updated goldens

* migrated to the latest material utils

* reaplced `SchemeTonalSpot` with `SchemeRainbow`

* fixed ruler slider ticks color

* update goldens

* fixed tests

* fixed scheme mapping and returned to `SchemeTonalSpot`
This commit is contained in:
Vadim 2024-05-20 17:08:37 +02:00 committed by GitHub
parent 5c27f726c5
commit 8c016e548b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
55 changed files with 176 additions and 188 deletions

View file

@ -7,6 +7,11 @@ class Dimens {
static const double borderRadiusL = 24; static const double borderRadiusL = 24;
static const double borderRadiusXL = 32; static const double borderRadiusXL = 32;
static const double elevationLevel0 = 0;
static const double elevationLevel1 = 1;
static const double elevationLevel2 = 3;
static const double elevationLevel3 = 6;
static const double grid4 = 4; static const double grid4 = 4;
static const double grid8 = 8; static const double grid8 = 8;
static const double grid16 = 16; static const double grid16 = 16;

View file

@ -29,14 +29,16 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
primaryColor: primaryColor, primaryColor: primaryColor,
colorScheme: scheme, colorScheme: scheme,
appBarTheme: AppBarTheme( appBarTheme: AppBarTheme(
elevation: 4, elevation: Dimens.elevationLevel0,
scrolledUnderElevation: Dimens.elevationLevel2,
color: scheme.surface, color: scheme.surface,
foregroundColor: scheme.onBackground,
surfaceTintColor: scheme.surfaceTint, surfaceTintColor: scheme.surfaceTint,
), ),
cardTheme: CardTheme( cardTheme: CardTheme(
clipBehavior: Clip.antiAlias, clipBehavior: Clip.antiAlias,
color: scheme.surface, color: scheme.surface,
elevation: 4, elevation: Dimens.elevationLevel1,
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
shadowColor: Colors.transparent, shadowColor: Colors.transparent,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(Dimens.borderRadiusL)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(Dimens.borderRadiusL)),
@ -46,7 +48,7 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
dialogTheme: DialogTheme( dialogTheme: DialogTheme(
backgroundColor: scheme.surface, backgroundColor: scheme.surface,
surfaceTintColor: scheme.surfaceTint, surfaceTintColor: scheme.surfaceTint,
elevation: 6, elevation: Dimens.elevationLevel3,
), ),
dividerColor: scheme.outlineVariant, dividerColor: scheme.outlineVariant,
dividerTheme: DividerThemeData( dividerTheme: DividerThemeData(
@ -71,15 +73,19 @@ ThemeData themeFrom(Color primaryColor, Brightness brightness) {
} }
ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) { ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
final scheme = brightness == Brightness.light ? Scheme.light(primaryColor.value) : Scheme.dark(primaryColor.value); final scheme = SchemeTonalSpot(
sourceColorHct: Hct.fromInt(primaryColor.value),
isDark: brightness == Brightness.dark,
contrastLevel: 0.0,
);
return ColorScheme( return ColorScheme(
brightness: brightness, brightness: brightness,
background: Color(scheme.background), background: Color(scheme.background),
error: Color(scheme.error),
errorContainer: Color(scheme.errorContainer),
onBackground: Color(scheme.onBackground), onBackground: Color(scheme.onBackground),
error: Color(scheme.error),
onError: Color(scheme.onError), onError: Color(scheme.onError),
errorContainer: Color(scheme.errorContainer),
onErrorContainer: Color(scheme.onErrorContainer), onErrorContainer: Color(scheme.onErrorContainer),
primary: Color(scheme.primary), primary: Color(scheme.primary),
onPrimary: Color(scheme.onPrimary), onPrimary: Color(scheme.onPrimary),
@ -87,17 +93,30 @@ ColorScheme _colorSchemeFromColor(Color primaryColor, Brightness brightness) {
onPrimaryContainer: Color(scheme.onPrimaryContainer), onPrimaryContainer: Color(scheme.onPrimaryContainer),
secondary: Color(scheme.secondary), secondary: Color(scheme.secondary),
onSecondary: Color(scheme.onSecondary), onSecondary: Color(scheme.onSecondary),
surface: Color.alphaBlend( secondaryContainer: Color(scheme.secondaryContainer),
Color(scheme.primary).withOpacity(0.05), onSecondaryContainer: Color(scheme.onSecondaryContainer),
Color(scheme.background), tertiary: Color(scheme.tertiary),
), onTertiary: Color(scheme.onTertiary),
tertiaryContainer: Color(scheme.tertiaryContainer),
onTertiaryContainer: Color(scheme.onTertiaryContainer),
surface: Color(scheme.surface),
onSurface: Color(scheme.onSurface), onSurface: Color(scheme.onSurface),
surfaceVariant: Color.alphaBlend( surfaceVariant: Color(scheme.surfaceVariant),
Color(scheme.primary).withOpacity(0.5),
Color(scheme.background),
),
onSurfaceVariant: Color(scheme.onSurfaceVariant), onSurfaceVariant: Color(scheme.onSurfaceVariant),
outline: Color(scheme.outline), outline: Color(scheme.outline),
outlineVariant: Color(scheme.outlineVariant), outlineVariant: Color(scheme.outlineVariant),
surfaceTint: Color(scheme.surfaceTint),
shadow: Color(scheme.shadow),
scrim: Color(scheme.scrim),
); );
} }
extension ElevatedSurfaceTheme on ColorScheme {
Color _surfaceWithElevation(double elevation) {
return ElevationOverlay.applySurfaceTint(surface, surfaceTint, elevation);
}
Color get surfaceElevated1 => _surfaceWithElevation(Dimens.elevationLevel1);
Color get surfaceElevated2 => _surfaceWithElevation(Dimens.elevationLevel2);
Color get surfaceElevated3 => _surfaceWithElevation(Dimens.elevationLevel3);
}

View file

@ -28,12 +28,12 @@ class MeteringBottomControls extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BottomControlsBar( return BottomControlsBar(
left: onSwitchEvSourceType != null left: onSwitchEvSourceType != null
? IconButton( ? IconButton.filledTonal(
onPressed: onSwitchEvSourceType, onPressed: onSwitchEvSourceType,
icon: Icon( icon: Icon(
UserPreferencesProvider.evSourceTypeOf(context) != EvSourceType.camera UserPreferencesProvider.evSourceTypeOf(context) != EvSourceType.camera
? Icons.camera_rear ? Icons.camera_rear_outlined
: Icons.wb_incandescent, : Icons.wb_incandescent_outlined,
), ),
tooltip: UserPreferencesProvider.evSourceTypeOf(context) != EvSourceType.camera tooltip: UserPreferencesProvider.evSourceTypeOf(context) != EvSourceType.camera
? S.of(context).tooltipUseCamera ? S.of(context).tooltipUseCamera
@ -46,9 +46,9 @@ class MeteringBottomControls extends StatelessWidget {
onPressed: onMeasure, onPressed: onMeasure,
child: ev != null ? _EvValueText(ev: ev!, ev100: ev100!) : null, child: ev != null ? _EvValueText(ev: ev!, ev100: ev100!) : null,
), ),
right: IconButton( right: IconButton.filledTonal(
onPressed: onSettings, onPressed: onSettings,
icon: const Icon(Icons.settings), icon: const Icon(Icons.settings_outlined),
tooltip: S.of(context).tooltipOpenSettings, tooltip: S.of(context).tooltipOpenSettings,
), ),
); );

View file

@ -21,7 +21,7 @@ class ExposureOffsetSlider extends StatelessWidget {
range: range, range: range,
value: value, value: value,
onChanged: onChanged, onChanged: onChanged,
icon: Icons.light_mode, icon: Icons.light_mode_outlined,
defaultValue: 0, defaultValue: 0,
rulerValueAdapter: (value) => value.toStringSignedAsFixed(0), rulerValueAdapter: (value) => value.toStringSignedAsFixed(0),
valueAdapter: (value) => S.of(context).evValue(value.toStringSignedAsFixed(1)), valueAdapter: (value) => S.of(context).evValue(value.toStringSignedAsFixed(1)),

View file

@ -32,7 +32,7 @@ class _ZoomSliderState extends State<ZoomSlider> {
range: widget.range, range: widget.range,
value: widget.value, value: widget.value,
onChanged: widget.onChanged, onChanged: widget.onChanged,
icon: Icons.search, icon: Icons.search_outlined,
defaultValue: EquipmentProfiles.selectedOf(context).lensZoom, defaultValue: EquipmentProfiles.selectedOf(context).lensZoom,
rulerValueAdapter: (value) => value.toStringAsFixed(0), rulerValueAdapter: (value) => value.toStringAsFixed(0),
valueAdapter: (value) => value.toZoom(), valueAdapter: (value) => value.toZoom(),

View file

@ -20,15 +20,12 @@ class CameraControlsPlaceholder extends StatelessWidget {
children: [ children: [
IconButton( IconButton(
onPressed: onReset, onPressed: onReset,
icon: Icon(error == CameraErrorType.permissionNotGranted ? Icons.settings : Icons.sync), icon: Icon(error == CameraErrorType.permissionNotGranted ? Icons.settings_outlined : Icons.sync_outlined),
), ),
const SizedBox(height: Dimens.grid8), const SizedBox(height: Dimens.grid8),
Text( Text(
error.toStringLocalized(context), error.toStringLocalized(context),
style: Theme.of(context) style: Theme.of(context).textTheme.bodyMedium?.copyWith(color: Theme.of(context).colorScheme.onBackground),
.textTheme
.bodyMedium
?.copyWith(color: Theme.of(context).colorScheme.onBackground),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],

View file

@ -12,7 +12,7 @@ class CameraViewPlaceholder extends StatelessWidget {
return Card( return Card(
color: error != null ? null : Colors.black, color: error != null ? null : Colors.black,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(Dimens.borderRadiusM)), shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(Dimens.borderRadiusM)),
child: Center(child: error != null ? const Icon(Icons.no_photography) : null), child: Center(child: error != null ? const Icon(Icons.no_photography_outlined) : null),
); );
} }
} }

View file

@ -19,7 +19,7 @@ class ExposurePairsList extends StatelessWidget {
duration: Dimens.switchDuration, duration: Dimens.switchDuration,
child: exposurePairs.isEmpty child: exposurePairs.isEmpty
? IconPlaceholder( ? IconPlaceholder(
icon: Icons.not_interested, icon: Icons.not_interested_outlined,
text: S.of(context).noExposurePairs, text: S.of(context).noExposurePairs,
) )
: Stack( : Stack(

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/res/theme.dart';
import 'package:lightmeter/screens/metering/components/shared/metering_top_bar/shape_top_bar_metering.dart'; import 'package:lightmeter/screens/metering/components/shared/metering_top_bar/shape_top_bar_metering.dart';
import 'package:lightmeter/screens/metering/components/shared/readings_container/widget_container_readings.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/widget_container_readings.dart';
@ -19,7 +20,7 @@ class MeteringTopBar extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CustomPaint( return CustomPaint(
painter: MeteringTopBarShape( painter: MeteringTopBarShape(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surfaceElevated1,
appendixWidth: MediaQuery.of(context).size.width / 2 - Dimens.grid8 / 2 + Dimens.paddingM, appendixWidth: MediaQuery.of(context).size.width / 2 - Dimens.grid8 / 2 + Dimens.paddingM,
appendixHeight: appendixHeight, appendixHeight: appendixHeight,
), ),

View file

@ -11,7 +11,7 @@ class EquipmentProfilePicker extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedDialogPicker<EquipmentProfile>( return AnimatedDialogPicker<EquipmentProfile>(
icon: Icons.camera, icon: Icons.camera_outlined,
title: S.of(context).equipmentProfile, title: S.of(context).equipmentProfile,
selectedValue: EquipmentProfiles.selectedOf(context), selectedValue: EquipmentProfiles.selectedOf(context),
values: EquipmentProfiles.of(context), values: EquipmentProfiles.of(context),

View file

@ -13,7 +13,7 @@ class FilmPicker extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedDialogPicker<Film>( return AnimatedDialogPicker<Film>(
icon: Icons.camera_roll, icon: Icons.camera_roll_outlined,
title: S.of(context).film, title: S.of(context).film,
subtitle: S.of(context).filmReciprocityHint, subtitle: S.of(context).filmReciprocityHint,
selectedValue: Films.selectedOf(context), selectedValue: Films.selectedOf(context),
@ -23,17 +23,14 @@ class FilmPicker extends StatelessWidget {
closedChild: ReadingValueContainer.singleValue( closedChild: ReadingValueContainer.singleValue(
value: ReadingValue( value: ReadingValue(
label: _label(context), label: _label(context),
value: Films.selectedOf(context).name.isEmpty value: Films.selectedOf(context).name.isEmpty ? S.of(context).none : Films.selectedOf(context).name,
? S.of(context).none
: Films.selectedOf(context).name,
), ),
), ),
); );
} }
String _label(BuildContext context) { String _label(BuildContext context) {
if (Films.selectedOf(context) == const Film.other() || if (Films.selectedOf(context) == const Film.other() || Films.selectedOf(context).iso == selectedIso.value) {
Films.selectedOf(context).iso == selectedIso.value) {
return S.of(context).film; return S.of(context).film;
} }

View file

@ -18,16 +18,15 @@ class IsoValuePicker extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedDialogPicker<IsoValue>( return AnimatedDialogPicker<IsoValue>(
icon: Icons.iso, icon: Icons.iso_outlined,
title: S.of(context).iso, title: S.of(context).iso,
subtitle: S.of(context).filmSpeed, subtitle: S.of(context).filmSpeed,
selectedValue: selectedValue, selectedValue: selectedValue,
values: values, values: values,
itemTitleBuilder: (_, value) => Text(value.value.toString()), itemTitleBuilder: (_, value) => Text(value.value.toString()),
// using ascending order, because increase in film speed rises EV // using ascending order, because increase in film speed rises EV
itemTrailingBuilder: (selected, value) => value.value != selected.value itemTrailingBuilder: (selected, value) =>
? Text(S.of(context).evValue(selected.toStringDifference(value))) value.value != selected.value ? Text(S.of(context).evValue(selected.toStringDifference(value))) : null,
: null,
onChanged: onChanged, onChanged: onChanged,
closedChild: ReadingValueContainer.singleValue( closedChild: ReadingValueContainer.singleValue(
value: ReadingValue( value: ReadingValue(

View file

@ -18,7 +18,7 @@ class NdValuePicker extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedDialogPicker<NdValue>( return AnimatedDialogPicker<NdValue>(
icon: Icons.filter_b_and_w, icon: Icons.filter_b_and_w_outlined,
title: S.of(context).nd, title: S.of(context).nd,
subtitle: S.of(context).ndFilterFactor, subtitle: S.of(context).ndFilterFactor,
selectedValue: selectedValue, selectedValue: selectedValue,

View file

@ -47,31 +47,31 @@ class ReadingValueContainer extends StatelessWidget implements AnimatedDialogClo
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ClipRRect( return DecoratedBox(
borderRadius: BorderRadius.circular(Dimens.borderRadiusM), decoration: BoxDecoration(
child: ColoredBox( borderRadius: BorderRadius.circular(Dimens.borderRadiusM),
color: backgroundColor(context), color: backgroundColor(context),
child: Padding( ),
padding: const EdgeInsets.all(Dimens.paddingM), child: Padding(
child: Stack( padding: const EdgeInsets.all(Dimens.paddingM),
children: [ child: Stack(
if (locked) children: [
Positioned( if (locked)
top: 0, Positioned(
right: 0, top: 0,
child: Icon( right: 0,
Icons.lock, child: Icon(
size: Theme.of(context).textTheme.labelMedium!.fontSize, Icons.lock_outlined,
color: Theme.of(context).colorScheme.onPrimaryContainer, size: Theme.of(context).textTheme.labelMedium!.fontSize,
), color: Theme.of(context).colorScheme.onPrimaryContainer,
), ),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: _items,
), ),
], Column(
), crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: _items,
),
],
), ),
), ),
); );

View file

@ -24,7 +24,6 @@ class MeteringScreen extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return _InheritedListeners( return _InheritedListeners(
child: Scaffold( child: Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
body: Column( body: Column(
children: [ children: [
Expanded( Expanded(

View file

@ -9,7 +9,7 @@ class ReportIssueListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.bug_report), leading: const Icon(Icons.bug_report_outlined),
title: Text(S.of(context).reportIssue), title: Text(S.of(context).reportIssue),
onTap: () { onTap: () {
launchUrl( launchUrl(

View file

@ -8,7 +8,7 @@ class RestorePurchasesListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.restore), leading: const Icon(Icons.restore_outlined),
title: Text(S.of(context).restorePurchases), title: Text(S.of(context).restorePurchases),
onTap: IAPProductsProvider.of(context).restorePurchases, onTap: IAPProductsProvider.of(context).restorePurchases,
); );

View file

@ -9,7 +9,7 @@ class SourceCodeListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.code), leading: const Icon(Icons.code_outlined),
title: Text(S.of(context).sourceCode), title: Text(S.of(context).sourceCode),
onTap: () { onTap: () {
launchUrl( launchUrl(

View file

@ -10,7 +10,7 @@ class WriteEmailListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.email), leading: const Icon(Icons.email_outlined),
title: Text(S.of(context).writeEmail), title: Text(S.of(context).writeEmail),
onTap: () { onTap: () {
final mailToUrl = Uri.parse('mailto:$contactEmail?subject=M3 Lightmeter'); final mailToUrl = Uri.parse('mailto:$contactEmail?subject=M3 Lightmeter');

View file

@ -12,7 +12,7 @@ class CaffeineListTile extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<CaffeineListTileBloc, bool>( return BlocBuilder<CaffeineListTileBloc, bool>(
builder: (context, state) => SwitchListTile( builder: (context, state) => SwitchListTile(
secondary: const Icon(Icons.screen_lock_portrait), secondary: const Icon(Icons.screen_lock_portrait_outlined),
title: Text(S.of(context).keepScreenOn), title: Text(S.of(context).keepScreenOn),
value: state, value: state,
onChanged: context.read<CaffeineListTileBloc>().onCaffeineChanged, onChanged: context.read<CaffeineListTileBloc>().onCaffeineChanged,

View file

@ -12,7 +12,7 @@ class HapticsListTile extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<HapticsListTileBloc, bool>( return BlocBuilder<HapticsListTileBloc, bool>(
builder: (context, state) => SwitchListTile( builder: (context, state) => SwitchListTile(
secondary: const Icon(Icons.vibration), secondary: const Icon(Icons.vibration_outlined),
title: Text(S.of(context).haptics), title: Text(S.of(context).haptics),
value: state, value: state,
onChanged: context.read<HapticsListTileBloc>().onHapticsChanged, onChanged: context.read<HapticsListTileBloc>().onHapticsChanged,

View file

@ -10,14 +10,14 @@ class LanguageListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.language), leading: const Icon(Icons.language_outlined),
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: () {
showDialog<SupportedLocale>( showDialog<SupportedLocale>(
context: context, context: context,
builder: (_) => DialogPicker<SupportedLocale>( builder: (_) => DialogPicker<SupportedLocale>(
icon: Icons.language, icon: Icons.language_outlined,
title: S.of(context).chooseLanguage, title: S.of(context).chooseLanguage,
selectedValue: UserPreferencesProvider.localeOf(context), selectedValue: UserPreferencesProvider.localeOf(context),
values: SupportedLocale.values, values: SupportedLocale.values,

View file

@ -11,7 +11,7 @@ class VolumeActionsListTile extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocBuilder<VolumeActionsListTileBloc, bool>( return BlocBuilder<VolumeActionsListTileBloc, bool>(
builder: (context, state) => SwitchListTile( builder: (context, state) => SwitchListTile(
secondary: const Icon(Icons.volume_up), secondary: const Icon(Icons.volume_up_outlined),
title: Text(S.of(context).volumeKeysAction), title: Text(S.of(context).volumeKeysAction),
value: state, value: state,
onChanged: context.read<VolumeActionsListTileBloc>().onVolumeActionChanged, onChanged: context.read<VolumeActionsListTileBloc>().onVolumeActionChanged,

View file

@ -17,9 +17,9 @@ class GeneralSettingsSection extends StatelessWidget {
return SettingsSection( return SettingsSection(
title: S.of(context).general, title: S.of(context).general,
children: [ children: [
const TimerListTileProvider(),
const CaffeineListTileProvider(), const CaffeineListTileProvider(),
const HapticsListTileProvider(), const HapticsListTileProvider(),
const TimerListTileProvider(),
if (Platform.isAndroid) const VolumeActionsListTileProvider(), if (Platform.isAndroid) const VolumeActionsListTileProvider(),
const LanguageListTile(), const LanguageListTile(),
], ],

View file

@ -12,7 +12,7 @@ class BuyProListTile extends StatelessWidget {
final status = IAPProducts.productOf(context, IAPProductType.paidFeatures)?.status; final status = IAPProducts.productOf(context, IAPProductType.paidFeatures)?.status;
final isPending = status == IAPProductStatus.purchased || status == null; final isPending = status == IAPProductStatus.purchased || status == null;
return ListTile( return ListTile(
leading: const Icon(Icons.star), leading: const Icon(Icons.star_outlined),
title: Text(S.of(context).unlockProFeatures), title: Text(S.of(context).unlockProFeatures),
onTap: !isPending onTap: !isPending
? () { ? () {

View file

@ -16,7 +16,7 @@ class CalibrationDialog extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
final bool hasLightSensor = ServicesProvider.of(context).environment.hasLightSensor; final bool hasLightSensor = ServicesProvider.of(context).environment.hasLightSensor;
return AlertDialog( return AlertDialog(
icon: const Icon(Icons.settings_brightness), icon: const Icon(Icons.settings_brightness_outlined),
titlePadding: Dimens.dialogIconTitlePadding, titlePadding: Dimens.dialogIconTitlePadding,
title: Text(S.of(context).calibration), title: Text(S.of(context).calibration),
contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL), contentPadding: const EdgeInsets.symmetric(horizontal: Dimens.paddingL),
@ -25,38 +25,27 @@ class CalibrationDialog extends StatelessWidget {
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Text( Text(
hasLightSensor hasLightSensor ? S.of(context).calibrationMessage : S.of(context).calibrationMessageCameraOnly,
? S.of(context).calibrationMessage
: S.of(context).calibrationMessageCameraOnly,
), ),
const SizedBox(height: Dimens.grid16), const SizedBox(height: Dimens.grid16),
BlocBuilder<CalibrationDialogBloc, CalibrationDialogState>( BlocBuilder<CalibrationDialogBloc, CalibrationDialogState>(
buildWhen: (previous, current) => buildWhen: (previous, current) => previous.cameraEvCalibration != current.cameraEvCalibration,
previous.cameraEvCalibration != current.cameraEvCalibration,
builder: (context, state) => _CalibrationUnit( builder: (context, state) => _CalibrationUnit(
title: S.of(context).camera, title: S.of(context).camera,
value: state.cameraEvCalibration, value: state.cameraEvCalibration,
onChanged: (value) => context onChanged: (value) => context.read<CalibrationDialogBloc>().add(CameraEvCalibrationChangedEvent(value)),
.read<CalibrationDialogBloc>() onReset: () => context.read<CalibrationDialogBloc>().add(const CameraEvCalibrationResetEvent()),
.add(CameraEvCalibrationChangedEvent(value)),
onReset: () => context
.read<CalibrationDialogBloc>()
.add(const CameraEvCalibrationResetEvent()),
), ),
), ),
if (hasLightSensor) if (hasLightSensor)
BlocBuilder<CalibrationDialogBloc, CalibrationDialogState>( BlocBuilder<CalibrationDialogBloc, CalibrationDialogState>(
buildWhen: (previous, current) => buildWhen: (previous, current) => previous.lightSensorEvCalibration != current.lightSensorEvCalibration,
previous.lightSensorEvCalibration != current.lightSensorEvCalibration,
builder: (context, state) => _CalibrationUnit( builder: (context, state) => _CalibrationUnit(
title: S.of(context).lightSensor, title: S.of(context).lightSensor,
value: state.lightSensorEvCalibration, value: state.lightSensorEvCalibration,
onChanged: (value) => context onChanged: (value) =>
.read<CalibrationDialogBloc>() context.read<CalibrationDialogBloc>().add(LightSensorEvCalibrationChangedEvent(value)),
.add(LightSensorEvCalibrationChangedEvent(value)), onReset: () => context.read<CalibrationDialogBloc>().add(const LightSensorEvCalibrationResetEvent()),
onReset: () => context
.read<CalibrationDialogBloc>()
.add(const LightSensorEvCalibrationResetEvent()),
), ),
), ),
], ],
@ -116,7 +105,7 @@ class _CalibrationUnit extends StatelessWidget {
), ),
IconButton( IconButton(
onPressed: onReset, onPressed: onReset,
icon: const Icon(Icons.sync), icon: const Icon(Icons.sync_outlined),
tooltip: S.of(context).tooltipResetToZero, tooltip: S.of(context).tooltipResetToZero,
), ),
], ],

View file

@ -9,7 +9,7 @@ class CalibrationListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.settings_brightness), leading: const Icon(Icons.settings_brightness_outlined),
title: Text(S.of(context).calibration), title: Text(S.of(context).calibration),
onTap: () { onTap: () {
showDialog<double>( showDialog<double>(

View file

@ -11,13 +11,13 @@ class CameraFeaturesListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return IAPListTile( return IAPListTile(
leading: const Icon(Icons.camera_alt), leading: const Icon(Icons.camera_alt_outlined),
title: Text(S.of(context).cameraFeatures), title: Text(S.of(context).cameraFeatures),
onTap: () { onTap: () {
showDialog( showDialog(
context: context, context: context,
builder: (_) => DialogSwitch<CameraFeature>( builder: (_) => DialogSwitch<CameraFeature>(
icon: Icons.layers_outlined, icon: Icons.camera_alt_outlined,
title: S.of(context).cameraFeatures, title: S.of(context).cameraFeatures,
values: UserPreferencesProvider.cameraConfigOf(context), values: UserPreferencesProvider.cameraConfigOf(context),
titleAdapter: (context, feature) { titleAdapter: (context, feature) {

View file

@ -171,7 +171,7 @@ class _AnimatedNameLeading extends AnimatedWidget {
return Padding( return Padding(
padding: EdgeInsets.only(right: _progress.value * Dimens.grid8), padding: EdgeInsets.only(right: _progress.value * Dimens.grid8),
child: Icon( child: Icon(
Icons.edit, Icons.edit_outlined,
size: _progress.value * Dimens.grid24, size: _progress.value * Dimens.grid24,
), ),
); );
@ -194,7 +194,7 @@ class _AnimatedArrowButton extends AnimatedWidget {
onPressed: onPressed, onPressed: onPressed,
icon: Transform.rotate( icon: Transform.rotate(
angle: _progress.value * pi, angle: _progress.value * pi,
child: const Icon(Icons.keyboard_arrow_down), child: const Icon(Icons.keyboard_arrow_down_outlined),
), ),
tooltip: _progress.value == 0 ? S.of(context).tooltipExpand : S.of(context).tooltipCollapse, tooltip: _progress.value == 0 ? S.of(context).tooltipExpand : S.of(context).tooltipCollapse,
); );
@ -239,7 +239,7 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
child: Column( child: Column(
children: [ children: [
FilterListTile<IsoValue>( FilterListTile<IsoValue>(
icon: Icons.iso, icon: Icons.iso_outlined,
title: S.of(context).isoValues, title: S.of(context).isoValues,
description: S.of(context).isoValuesFilterDescription, description: S.of(context).isoValuesFilterDescription,
values: IsoValue.values, values: IsoValue.values,
@ -247,7 +247,7 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
onChanged: onIsoValuesSelecred, onChanged: onIsoValuesSelecred,
), ),
FilterListTile<NdValue>( FilterListTile<NdValue>(
icon: Icons.filter_b_and_w, icon: Icons.filter_b_and_w_outlined,
title: S.of(context).ndFilters, title: S.of(context).ndFilters,
description: S.of(context).ndFiltersFilterDescription, description: S.of(context).ndFiltersFilterDescription,
values: NdValue.values, values: NdValue.values,
@ -255,7 +255,7 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
onChanged: onNdValuesSelected, onChanged: onNdValuesSelected,
), ),
RangePickerListTile<ApertureValue>( RangePickerListTile<ApertureValue>(
icon: Icons.camera, icon: Icons.camera_outlined,
title: S.of(context).apertureValues, title: S.of(context).apertureValues,
description: S.of(context).apertureValuesFilterDescription, description: S.of(context).apertureValuesFilterDescription,
values: ApertureValue.values, values: ApertureValue.values,
@ -263,7 +263,7 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
onChanged: onApertureValuesSelected, onChanged: onApertureValuesSelected,
), ),
RangePickerListTile<ShutterSpeedValue>( RangePickerListTile<ShutterSpeedValue>(
icon: Icons.shutter_speed, icon: Icons.shutter_speed_outlined,
title: S.of(context).shutterSpeedValues, title: S.of(context).shutterSpeedValues,
description: S.of(context).shutterSpeedValuesFilterDescription, description: S.of(context).shutterSpeedValuesFilterDescription,
values: ShutterSpeedValue.values, values: ShutterSpeedValue.values,
@ -275,7 +275,7 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
value.value == 1 ? S.of(context).shutterSpeedManual : value.toString(), value.value == 1 ? S.of(context).shutterSpeedManual : value.toString(),
), ),
SliderPickerListTile( SliderPickerListTile(
icon: Icons.zoom_in, icon: Icons.zoom_in_outlined,
title: S.of(context).lensZoom, title: S.of(context).lensZoom,
description: S.of(context).lensZoomDescription, description: S.of(context).lensZoomDescription,
value: equipmentData.lensZoom, value: equipmentData.lensZoom,
@ -291,12 +291,12 @@ class _AnimatedEquipmentListTiles extends AnimatedWidget {
children: [ children: [
IconButton( IconButton(
onPressed: onCopy, onPressed: onCopy,
icon: const Icon(Icons.copy), icon: const Icon(Icons.copy_outlined),
tooltip: S.of(context).tooltipCopy, tooltip: S.of(context).tooltipCopy,
), ),
IconButton( IconButton(
onPressed: onDelete, onPressed: onDelete,
icon: const Icon(Icons.delete), icon: const Icon(Icons.delete_outlined),
tooltip: S.of(context).tooltipDelete, tooltip: S.of(context).tooltipDelete,
), ),
], ],

View file

@ -23,7 +23,7 @@ class _EquipmentProfileNameDialogState extends State<EquipmentProfileNameDialog>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
icon: const Icon(Icons.edit), icon: const Icon(Icons.edit_outlined),
titlePadding: Dimens.dialogIconTitlePadding, titlePadding: Dimens.dialogIconTitlePadding,
title: Text(S.of(context).equipmentProfileName), title: Text(S.of(context).equipmentProfileName),
content: TextField( content: TextField(

View file

@ -32,7 +32,7 @@ class _EquipmentProfilesScreenState extends State<EquipmentProfilesScreen> {
appBarActions: [ appBarActions: [
IconButton( IconButton(
onPressed: _addProfile, onPressed: _addProfile,
icon: const Icon(Icons.add), icon: const Icon(Icons.add_outlined),
tooltip: S.of(context).tooltipAdd, tooltip: S.of(context).tooltipAdd,
), ),
], ],
@ -150,7 +150,7 @@ class _EquipmentProfilesListPlaceholder extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.all(Dimens.paddingL), padding: const EdgeInsets.all(Dimens.paddingL),
child: IconPlaceholder( child: IconPlaceholder(
icon: Icons.add, icon: Icons.add_outlined,
text: S.of(context).tapToAdd, text: S.of(context).tapToAdd,
), ),
), ),

View file

@ -10,7 +10,7 @@ class EquipmentProfilesListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return IAPListTile( return IAPListTile(
leading: const Icon(Icons.camera), leading: const Icon(Icons.camera_outlined),
title: Text(S.of(context).equipmentProfiles), title: Text(S.of(context).equipmentProfiles),
onTap: () { onTap: () {
Navigator.of(context).push<EquipmentProfile>( Navigator.of(context).push<EquipmentProfile>(

View file

@ -11,13 +11,13 @@ class FilmsListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return IAPListTile( return IAPListTile(
leading: const Icon(Icons.camera_roll), leading: const Icon(Icons.camera_roll_outlined),
title: Text(S.of(context).filmsInUse), title: Text(S.of(context).filmsInUse),
onTap: () { onTap: () {
showDialog<List<Film>>( showDialog<List<Film>>(
context: context, context: context,
builder: (_) => DialogFilter<Film>( builder: (_) => DialogFilter<Film>(
icon: const Icon(Icons.camera_roll), icon: const Icon(Icons.camera_roll_outlined),
title: S.of(context).filmsInUse, title: S.of(context).filmsInUse,
description: S.of(context).filmsInUseDescription, description: S.of(context).filmsInUseDescription,
values: Films.of(context).sublist(1), values: Films.of(context).sublist(1),

View file

@ -10,14 +10,14 @@ class StopTypeListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.straighten), leading: const Icon(Icons.straighten_outlined),
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: () {
showDialog<StopType>( showDialog<StopType>(
context: context, context: context,
builder: (_) => DialogPicker<StopType>( builder: (_) => DialogPicker<StopType>(
icon: Icons.straighten, icon: Icons.straighten_outlined,
title: S.of(context).showFractionalStops, title: S.of(context).showFractionalStops,
selectedValue: UserPreferencesProvider.stopTypeOf(context), selectedValue: UserPreferencesProvider.stopTypeOf(context),
values: StopType.values, values: StopType.values,

View file

@ -13,7 +13,7 @@ class ShowEv100ListTile extends StatelessWidget {
return Disable( return Disable(
disable: !context.isPro, disable: !context.isPro,
child: SwitchListTile( child: SwitchListTile(
secondary: const Icon(Icons.adjust), secondary: const Icon(Icons.adjust_outlined),
title: Text(S.of(context).showEv100), title: Text(S.of(context).showEv100),
value: context.isPro && UserPreferencesProvider.showEv100Of(context), value: context.isPro && UserPreferencesProvider.showEv100Of(context),
onChanged: (_) => UserPreferencesProvider.of(context).toggleShowEv100(), onChanged: (_) => UserPreferencesProvider.of(context).toggleShowEv100(),

View file

@ -109,7 +109,7 @@ class _DialogFilterState<T> extends State<DialogFilter<T>> {
width: 40, width: 40,
child: IconButton( child: IconButton(
padding: EdgeInsets.zero, padding: EdgeInsets.zero,
icon: Icon(_hasAnyUnselected ? Icons.select_all : Icons.deselect), icon: Icon(_hasAnyUnselected ? Icons.select_all_outlined : Icons.deselect_outlined),
onPressed: _toggleAll, onPressed: _toggleAll,
tooltip: _hasAnyUnselected ? S.of(context).tooltipSelectAll : S.of(context).tooltipDesecelectAll, tooltip: _hasAnyUnselected ? S.of(context).tooltipSelectAll : S.of(context).tooltipDesecelectAll,
), ),

View file

@ -10,7 +10,7 @@ class DynamicColorListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return SwitchListTile( return SwitchListTile(
secondary: const Icon(Icons.colorize), secondary: const Icon(Icons.colorize_outlined),
title: Text(S.of(context).dynamicColor), title: Text(S.of(context).dynamicColor),
value: UserPreferencesProvider.dynamicColorStateOf(context) == DynamicColorState.enabled, value: UserPreferencesProvider.dynamicColorStateOf(context) == DynamicColorState.enabled,
onChanged: UserPreferencesProvider.of(context).enableDynamicColor, onChanged: UserPreferencesProvider.of(context).enableDynamicColor,

View file

@ -24,7 +24,7 @@ class _PrimaryColorDialogPickerState extends State<PrimaryColorDialogPicker> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AlertDialog( return AlertDialog(
icon: const Icon(Icons.palette), icon: const Icon(Icons.palette_outlined),
titlePadding: Dimens.dialogIconTitlePadding, titlePadding: Dimens.dialogIconTitlePadding,
title: Text(S.of(context).choosePrimaryColor), title: Text(S.of(context).choosePrimaryColor),
content: SizedBox( content: SizedBox(
@ -124,7 +124,7 @@ class _SelectableColorItemState extends State<_SelectableColorItem> {
duration: Dimens.durationS, duration: Dimens.durationS,
child: widget.selected child: widget.selected
? Icon( ? Icon(
Icons.check, Icons.check_outlined,
color: ThemeData.estimateBrightnessForColor(widget.color) == Brightness.light color: ThemeData.estimateBrightnessForColor(widget.color) == Brightness.light
? Colors.black ? Colors.black
: Colors.white, : Colors.white,

View file

@ -13,13 +13,13 @@ class PrimaryColorListTile extends StatelessWidget {
if (UserPreferencesProvider.dynamicColorStateOf(context) == DynamicColorState.enabled) { if (UserPreferencesProvider.dynamicColorStateOf(context) == DynamicColorState.enabled) {
return Disable( return Disable(
child: ListTile( child: ListTile(
leading: const Icon(Icons.palette), leading: const Icon(Icons.palette_outlined),
title: Text(S.of(context).primaryColor), title: Text(S.of(context).primaryColor),
), ),
); );
} }
return ListTile( return ListTile(
leading: const Icon(Icons.palette), leading: const Icon(Icons.palette_outlined),
title: Text(S.of(context).primaryColor), title: Text(S.of(context).primaryColor),
onTap: () { onTap: () {
showDialog<Color>( showDialog<Color>(

View file

@ -10,14 +10,14 @@ class ThemeTypeListTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: const Icon(Icons.brightness_6), leading: const Icon(Icons.brightness_6_outlined),
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: () {
showDialog<ThemeType>( showDialog<ThemeType>(
context: context, context: context,
builder: (_) => DialogPicker<ThemeType>( builder: (_) => DialogPicker<ThemeType>(
icon: Icons.brightness_6, icon: Icons.brightness_6_outlined,
title: S.of(context).chooseTheme, title: S.of(context).chooseTheme,
selectedValue: UserPreferencesProvider.themeTypeOf(context), selectedValue: UserPreferencesProvider.themeTypeOf(context),
values: ThemeType.values, values: ThemeType.values,

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/res/theme.dart';
class BottomControlsBar extends StatelessWidget { class BottomControlsBar extends StatelessWidget {
final Widget center; final Widget center;
@ -15,40 +16,27 @@ class BottomControlsBar extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final scheme = Theme.of(context).colorScheme; return ClipRRect(
return IconButtonTheme( borderRadius: const BorderRadius.only(
data: IconButtonThemeData( topLeft: Radius.circular(Dimens.borderRadiusL),
style: ButtonStyle( topRight: Radius.circular(Dimens.borderRadiusL),
backgroundColor: MaterialStatePropertyAll(scheme.surface),
elevation: const MaterialStatePropertyAll(4),
iconColor: MaterialStatePropertyAll(scheme.onSurface),
shadowColor: const MaterialStatePropertyAll(Colors.transparent),
surfaceTintColor: MaterialStatePropertyAll(scheme.surfaceTint),
fixedSize: const MaterialStatePropertyAll(Size(Dimens.grid48, Dimens.grid48)),
),
), ),
child: ClipRRect( child: ColoredBox(
borderRadius: const BorderRadius.only( color: Theme.of(context).colorScheme.surfaceElevated1,
topLeft: Radius.circular(Dimens.borderRadiusL), child: SafeArea(
topRight: Radius.circular(Dimens.borderRadiusL), top: false,
), child: Padding(
child: ColoredBox( padding: const EdgeInsets.symmetric(vertical: Dimens.paddingL),
color: Theme.of(context).colorScheme.surface, child: Row(
child: SafeArea( mainAxisAlignment: MainAxisAlignment.spaceEvenly,
top: false, children: [
child: Padding( if (left != null) Expanded(child: Center(child: left)) else const Spacer(),
padding: const EdgeInsets.symmetric(vertical: Dimens.paddingL), SizedBox.fromSize(
child: Row( size: const Size.square(Dimens.grid72),
mainAxisAlignment: MainAxisAlignment.spaceEvenly, child: center,
children: [ ),
if (left != null) Expanded(child: Center(child: left)) else const Spacer(), if (right != null) Expanded(child: Center(child: right)) else const Spacer(),
SizedBox.fromSize( ],
size: const Size.square(Dimens.grid72),
child: center,
),
if (right != null) Expanded(child: Center(child: right)) else const Spacer(),
],
),
), ),
), ),
), ),

View file

@ -1,15 +0,0 @@
import 'package:flutter/material.dart';
import 'package:lightmeter/generated/l10n.dart';
class CloseButton extends StatelessWidget {
const CloseButton({super.key});
@override
Widget build(BuildContext context) {
return IconButton(
onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.close),
tooltip: S.of(context).tooltipClose,
);
}
}

View file

@ -24,7 +24,7 @@ class ProFeaturesDialog extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return TransparentDialog( return TransparentDialog(
icon: Icons.star, icon: Icons.star_outlined,
title: S.of(context).proFeatures, title: S.of(context).proFeatures,
scrollableContent: false, scrollableContent: false,
content: Flexible( content: Flexible(

View file

@ -30,7 +30,7 @@ class RulerSlider extends StatelessWidget {
children: [ children: [
Text( Text(
valueAdapter(value), valueAdapter(value),
style: Theme.of(context).textTheme.labelLarge, style: Theme.of(context).textTheme.labelLarge!.copyWith(color: Theme.of(context).colorScheme.onBackground),
), ),
const SizedBox(height: Dimens.grid4), const SizedBox(height: Dimens.grid4),
Expanded( Expanded(
@ -53,7 +53,7 @@ class RulerSlider extends StatelessWidget {
), ),
), ),
IconButton( IconButton(
icon: const Icon(Icons.sync), icon: const Icon(Icons.sync_outlined),
onPressed: value != defaultValue ? () => onChanged(defaultValue) : null, onPressed: value != defaultValue ? () => onChanged(defaultValue) : null,
tooltip: S.of(context).tooltipResetToZero, tooltip: S.of(context).tooltipResetToZero,
), ),
@ -78,6 +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;
return LayoutBuilder( return LayoutBuilder(
builder: (context, constraints) { builder: (context, constraints) {
final bool showAllMainTicks = final bool showAllMainTicks =
@ -103,11 +104,11 @@ class _Ruler extends StatelessWidget {
if (showValue) if (showValue)
Text( Text(
rulerValueAdapter(index / 2 + min), rulerValueAdapter(index / 2 + min),
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall!.copyWith(color: itemsColor),
), ),
const SizedBox(width: Dimens.grid4), const SizedBox(width: Dimens.grid4),
ColoredBox( ColoredBox(
color: Theme.of(context).colorScheme.onBackground, color: itemsColor,
child: SizedBox( child: SizedBox(
height: 1, height: 1,
width: isMainTick ? Dimens.grid8 : Dimens.grid4, width: isMainTick ? Dimens.grid8 : Dimens.grid4,

View file

@ -42,7 +42,7 @@ class SliverScreen extends StatelessWidget {
if (Navigator.of(context).canPop()) if (Navigator.of(context).canPop())
IconButton( IconButton(
onPressed: Navigator.of(context).pop, onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.close), icon: const Icon(Icons.close_outlined),
tooltip: S.of(context).tooltipClose, tooltip: S.of(context).tooltipClose,
), ),
], ],

View file

@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/generated/l10n.dart'; 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/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart'; import 'package:lightmeter/screens/metering/components/shared/readings_container/components/shared/reading_value_container/widget_container_reading_value.dart';
import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart'; import 'package:m3_lightmeter_resources/m3_lightmeter_resources.dart';
@ -21,7 +22,7 @@ class TimerMeteringConfig extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Container( return Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface, color: Theme.of(context).colorScheme.surfaceElevated1,
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
bottomLeft: Radius.circular(Dimens.borderRadiusL), bottomLeft: Radius.circular(Dimens.borderRadiusL),
bottomRight: Radius.circular(Dimens.borderRadiusL), bottomRight: Radius.circular(Dimens.borderRadiusL),

View file

@ -16,7 +16,7 @@ class TimerTimeline extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return CustomPaint( return CustomPaint(
painter: _TimelinePainter( painter: _TimelinePainter(
backgroundColor: Theme.of(context).colorScheme.surface, backgroundColor: Theme.of(context).colorScheme.primaryContainer,
progressColor: Theme.of(context).colorScheme.primary, progressColor: Theme.of(context).colorScheme.primary,
progress: progress, progress: progress,
), ),

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:lightmeter/data/models/exposure_pair.dart'; import 'package:lightmeter/data/models/exposure_pair.dart';
import 'package:lightmeter/generated/l10n.dart';
import 'package:lightmeter/res/dimens.dart'; import 'package:lightmeter/res/dimens.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/shared/bottom_controls_bar/widget_bottom_controls_bar.dart'; import 'package:lightmeter/screens/shared/bottom_controls_bar/widget_bottom_controls_bar.dart';
@ -66,7 +67,6 @@ class TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
listenWhen: (previous, current) => previous.runtimeType != current.runtimeType, listenWhen: (previous, current) => previous.runtimeType != current.runtimeType,
listener: (context, state) => _updateAnimations(state), listener: (context, state) => _updateAnimations(state),
child: Scaffold( child: Scaffold(
backgroundColor: Theme.of(context).colorScheme.background,
body: Center( body: Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
@ -95,7 +95,7 @@ class TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
), ),
const Spacer(), const Spacer(),
BottomControlsBar( BottomControlsBar(
left: IconButton( left: IconButton.filledTonal(
onPressed: () { onPressed: () {
context.read<TimerBloc>().add(const ResetTimerEvent()); context.read<TimerBloc>().add(const ResetTimerEvent());
}, },
@ -118,7 +118,11 @@ class TimerScreenState extends State<TimerScreen> with TickerProviderStateMixin
), ),
), ),
), ),
right: const CloseButton(), right: IconButton.filledTonal(
onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.close),
tooltip: S.of(context).tooltipClose,
),
), ),
], ],
), ),

View file

@ -12,7 +12,7 @@ dependencies:
camera: 0.10.5+2 camera: 0.10.5+2
camera_android_camerax: 0.6.1+1 camera_android_camerax: 0.6.1+1
clipboard: 0.1.3 clipboard: 0.1.3
dynamic_color: 1.6.6 dynamic_color: 1.7.0
exif: 3.1.4 exif: 3.1.4
firebase_analytics: 10.6.2 firebase_analytics: 10.6.2
firebase_core: 2.20.0 firebase_core: 2.20.0
@ -58,6 +58,9 @@ dev_dependencies:
mocktail: 0.3.0 mocktail: 0.3.0
test: 1.24.3 test: 1.24.3
dependency_overrides:
material_color_utilities: 0.11.1
flutter: flutter:
uses-material-design: true uses-material-design: true
assets: assets:

View file

@ -47,7 +47,7 @@ void main() {
await pumpApplication(tester); await pumpApplication(tester);
expectReadingValueContainerText(S.current.equipmentProfile); expectReadingValueContainerText(S.current.equipmentProfile);
await tester.openAnimatedPicker<EquipmentProfilePicker>(); await tester.openAnimatedPicker<EquipmentProfilePicker>();
expect(find.byIcon(Icons.camera), findsOneWidget); expect(find.byIcon(Icons.camera_outlined), findsOneWidget);
expectDialogPickerText<EquipmentProfile>(S.current.equipmentProfile); expectDialogPickerText<EquipmentProfile>(S.current.equipmentProfile);
}, },
); );

View file

@ -38,7 +38,7 @@ void main() {
await pumpApplication(tester); await pumpApplication(tester);
expectReadingValueContainerText(S.current.iso); expectReadingValueContainerText(S.current.iso);
await tester.openAnimatedPicker<IsoValuePicker>(); await tester.openAnimatedPicker<IsoValuePicker>();
expect(find.byIcon(Icons.iso), findsOneWidget); expect(find.byIcon(Icons.iso_outlined), findsOneWidget);
expectDialogPickerText<IsoValue>(S.current.iso); expectDialogPickerText<IsoValue>(S.current.iso);
expectDialogPickerText<IsoValue>(S.current.filmSpeed); expectDialogPickerText<IsoValue>(S.current.filmSpeed);
}, },

View file

@ -38,7 +38,7 @@ void main() {
await pumpApplication(tester); await pumpApplication(tester);
expectReadingValueContainerText(S.current.nd); expectReadingValueContainerText(S.current.nd);
await tester.openAnimatedPicker<NdValuePicker>(); await tester.openAnimatedPicker<NdValuePicker>();
expect(find.byIcon(Icons.filter_b_and_w), findsOneWidget); expect(find.byIcon(Icons.filter_b_and_w_outlined), findsOneWidget);
expectDialogPickerText<NdValue>(S.current.nd); expectDialogPickerText<NdValue>(S.current.nd);
expectDialogPickerText<NdValue>(S.current.ndFilterFactor); expectDialogPickerText<NdValue>(S.current.ndFilterFactor);
}, },

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 496 KiB

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 854 KiB

After

Width:  |  Height:  |  Size: 858 KiB