diff --git a/app/lib/cubits/settings.dart b/app/lib/cubits/settings.dart index e214407ee211..5574f4337e16 100644 --- a/app/lib/cubits/settings.dart +++ b/app/lib/cubits/settings.dart @@ -370,6 +370,7 @@ class ButterflySettings with _$ButterflySettings { @Default([]) List recentColors, @Default([]) List flags, @Default(false) bool spreadPages, + @Default(false) bool highContrast, }) = _ButterflySettings; factory ButterflySettings.fromPrefs( @@ -445,6 +446,8 @@ class ButterflySettings with _$ButterflySettings { recentColors: prefs.getStringList('recent_colors')?.map(int.parse).toList() ?? [], flags: prefs.getStringList('flags') ?? [], + spreadPages: prefs.getBool('spread_pages') ?? false, + highContrast: prefs.getBool('high_contrast') ?? false, ); } @@ -502,6 +505,8 @@ class ButterflySettings with _$ButterflySettings { await prefs.setStringList( 'recent_colors', recentColors.map((e) => e.toString()).toList()); await prefs.setStringList('flags', flags); + await prefs.setBool('spread_pages', spreadPages); + await prefs.setBool('high_contrast', highContrast); } ExternalStorage? getRemote(String? identifier) { @@ -975,4 +980,11 @@ class SettingsCubit extends Cubit { } Future resetSpreadPages() => changeSpreadPages(true); + + Future changeHighContrast(bool value) { + emit(state.copyWith(highContrast: value)); + return save(); + } + + Future resetHighContrast() => changeHighContrast(false); } diff --git a/app/lib/cubits/settings.freezed.dart b/app/lib/cubits/settings.freezed.dart index 93ada68f65cc..254bdb41446d 100644 --- a/app/lib/cubits/settings.freezed.dart +++ b/app/lib/cubits/settings.freezed.dart @@ -439,7 +439,7 @@ class _$DavRemoteStorageImpl extends DavRemoteStorage } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$DavRemoteStorageImpl && @@ -868,7 +868,7 @@ class _$LocalStorageImpl extends LocalStorage with DiagnosticableTreeMixin { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$LocalStorageImpl && @@ -1301,7 +1301,7 @@ class _$InputConfigurationImpl extends _InputConfiguration } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$InputConfigurationImpl && @@ -1413,6 +1413,7 @@ mixin _$ButterflySettings { List get recentColors => throw _privateConstructorUsedError; List get flags => throw _privateConstructorUsedError; bool get spreadPages => throw _privateConstructorUsedError; + bool get highContrast => throw _privateConstructorUsedError; @JsonKey(ignore: true) $ButterflySettingsCopyWith get copyWith => @@ -1462,7 +1463,8 @@ abstract class $ButterflySettingsCopyWith<$Res> { PlatformTheme platformTheme, List recentColors, List flags, - bool spreadPages}); + bool spreadPages, + bool highContrast}); $InputConfigurationCopyWith<$Res> get inputConfiguration; } @@ -1517,6 +1519,7 @@ class _$ButterflySettingsCopyWithImpl<$Res, $Val extends ButterflySettings> Object? recentColors = null, Object? flags = null, Object? spreadPages = null, + Object? highContrast = null, }) { return _then(_value.copyWith( theme: null == theme @@ -1667,6 +1670,10 @@ class _$ButterflySettingsCopyWithImpl<$Res, $Val extends ButterflySettings> ? _value.spreadPages : spreadPages // ignore: cast_nullable_to_non_nullable as bool, + highContrast: null == highContrast + ? _value.highContrast + : highContrast // ignore: cast_nullable_to_non_nullable + as bool, ) as $Val); } @@ -1725,7 +1732,8 @@ abstract class _$$ButterflySettingsImplCopyWith<$Res> PlatformTheme platformTheme, List recentColors, List flags, - bool spreadPages}); + bool spreadPages, + bool highContrast}); @override $InputConfigurationCopyWith<$Res> get inputConfiguration; @@ -1779,6 +1787,7 @@ class __$$ButterflySettingsImplCopyWithImpl<$Res> Object? recentColors = null, Object? flags = null, Object? spreadPages = null, + Object? highContrast = null, }) { return _then(_$ButterflySettingsImpl( theme: null == theme @@ -1929,6 +1938,10 @@ class __$$ButterflySettingsImplCopyWithImpl<$Res> ? _value.spreadPages : spreadPages // ignore: cast_nullable_to_non_nullable as bool, + highContrast: null == highContrast + ? _value.highContrast + : highContrast // ignore: cast_nullable_to_non_nullable + as bool, )); } } @@ -1974,7 +1987,8 @@ class _$ButterflySettingsImpl extends _ButterflySettings this.platformTheme = PlatformTheme.system, final List recentColors = const [], final List flags = const [], - this.spreadPages = false}) + this.spreadPages = false, + this.highContrast = false}) : _history = history, _connections = connections, _starred = starred, @@ -2121,10 +2135,13 @@ class _$ButterflySettingsImpl extends _ButterflySettings @override @JsonKey() final bool spreadPages; + @override + @JsonKey() + final bool highContrast; @override String toString({DiagnosticLevel minLevel = DiagnosticLevel.info}) { - return 'ButterflySettings(theme: $theme, density: $density, localeTag: $localeTag, documentPath: $documentPath, touchSensitivity: $touchSensitivity, mouseSensitivity: $mouseSensitivity, penSensitivity: $penSensitivity, selectSensitivity: $selectSensitivity, penOnlyInput: $penOnlyInput, inputGestures: $inputGestures, design: $design, bannerVisibility: $bannerVisibility, history: $history, navigatorEnabled: $navigatorEnabled, zoomEnabled: $zoomEnabled, lastVersion: $lastVersion, connections: $connections, defaultRemote: $defaultRemote, nativeTitleBar: $nativeTitleBar, startInFullScreen: $startInFullScreen, navigationRail: $navigationRail, fullScreen: $fullScreen, syncMode: $syncMode, inputConfiguration: $inputConfiguration, fallbackPack: $fallbackPack, starred: $starred, defaultTemplate: $defaultTemplate, navigatorPage: $navigatorPage, toolbarPosition: $toolbarPosition, sortBy: $sortBy, sortOrder: $sortOrder, imageScale: $imageScale, pdfQuality: $pdfQuality, platformTheme: $platformTheme, recentColors: $recentColors, flags: $flags, spreadPages: $spreadPages)'; + return 'ButterflySettings(theme: $theme, density: $density, localeTag: $localeTag, documentPath: $documentPath, touchSensitivity: $touchSensitivity, mouseSensitivity: $mouseSensitivity, penSensitivity: $penSensitivity, selectSensitivity: $selectSensitivity, penOnlyInput: $penOnlyInput, inputGestures: $inputGestures, design: $design, bannerVisibility: $bannerVisibility, history: $history, navigatorEnabled: $navigatorEnabled, zoomEnabled: $zoomEnabled, lastVersion: $lastVersion, connections: $connections, defaultRemote: $defaultRemote, nativeTitleBar: $nativeTitleBar, startInFullScreen: $startInFullScreen, navigationRail: $navigationRail, fullScreen: $fullScreen, syncMode: $syncMode, inputConfiguration: $inputConfiguration, fallbackPack: $fallbackPack, starred: $starred, defaultTemplate: $defaultTemplate, navigatorPage: $navigatorPage, toolbarPosition: $toolbarPosition, sortBy: $sortBy, sortOrder: $sortOrder, imageScale: $imageScale, pdfQuality: $pdfQuality, platformTheme: $platformTheme, recentColors: $recentColors, flags: $flags, spreadPages: $spreadPages, highContrast: $highContrast)'; } @override @@ -2168,11 +2185,12 @@ class _$ButterflySettingsImpl extends _ButterflySettings ..add(DiagnosticsProperty('platformTheme', platformTheme)) ..add(DiagnosticsProperty('recentColors', recentColors)) ..add(DiagnosticsProperty('flags', flags)) - ..add(DiagnosticsProperty('spreadPages', spreadPages)); + ..add(DiagnosticsProperty('spreadPages', spreadPages)) + ..add(DiagnosticsProperty('highContrast', highContrast)); } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$ButterflySettingsImpl && @@ -2242,7 +2260,9 @@ class _$ButterflySettingsImpl extends _ButterflySettings .equals(other._recentColors, _recentColors) && const DeepCollectionEquality().equals(other._flags, _flags) && (identical(other.spreadPages, spreadPages) || - other.spreadPages == spreadPages)); + other.spreadPages == spreadPages) && + (identical(other.highContrast, highContrast) || + other.highContrast == highContrast)); } @override @@ -2284,7 +2304,8 @@ class _$ButterflySettingsImpl extends _ButterflySettings platformTheme, const DeepCollectionEquality().hash(_recentColors), const DeepCollectionEquality().hash(_flags), - spreadPages + spreadPages, + highContrast ]); @JsonKey(ignore: true) @@ -2333,7 +2354,8 @@ abstract class _ButterflySettings extends ButterflySettings { final PlatformTheme platformTheme, final List recentColors, final List flags, - final bool spreadPages}) = _$ButterflySettingsImpl; + final bool spreadPages, + final bool highContrast}) = _$ButterflySettingsImpl; const _ButterflySettings._() : super._(); @override @@ -2411,6 +2433,8 @@ abstract class _ButterflySettings extends ButterflySettings { @override bool get spreadPages; @override + bool get highContrast; + @override @JsonKey(ignore: true) _$$ButterflySettingsImplCopyWith<_$ButterflySettingsImpl> get copyWith => throw _privateConstructorUsedError; diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 337b1b87bbde..ee1397b7e73e 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -581,5 +581,6 @@ } }, "continueAnyway": "Continue anyway", - "zoomControl": "Zoom control" + "zoomControl": "Zoom control", + "highContrast": "High contrast" } diff --git a/app/lib/main.dart b/app/lib/main.dart index 2e6ed477b9ca..a62c9c8bad41 100644 --- a/app/lib/main.dart +++ b/app/lib/main.dart @@ -351,7 +351,8 @@ class ButterflyApp extends StatelessWidget { previous.theme != current.theme || previous.localeTag != current.localeTag || previous.design != current.design || - previous.density != current.density, + previous.density != current.density || + previous.highContrast != current.highContrast, builder: (context, state) => MaterialApp.router( locale: state.locale, title: applicationName, @@ -371,10 +372,10 @@ class ButterflyApp extends StatelessWidget { }, supportedLocales: getLocales(), themeMode: state.theme, - theme: getThemeData( - state.design, false, state.density.toFlutter(), lightDynamic), - darkTheme: getThemeData( - state.design, true, state.density.toFlutter(), darkDynamic), + theme: getThemeData(state.design, false, + state.density.toFlutter(), lightDynamic, state.highContrast), + darkTheme: getThemeData(state.design, true, + state.density.toFlutter(), darkDynamic, state.highContrast), )); } diff --git a/app/lib/models/label.freezed.dart b/app/lib/models/label.freezed.dart index 45c97c98b96a..2d53106938c0 100644 --- a/app/lib/models/label.freezed.dart +++ b/app/lib/models/label.freezed.dart @@ -327,7 +327,7 @@ class _$TextContextImpl extends TextContext { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$TextContextImpl && @@ -616,7 +616,7 @@ class _$MarkdownContextImpl extends MarkdownContext { } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$MarkdownContextImpl && diff --git a/app/lib/services/network.freezed.dart b/app/lib/services/network.freezed.dart index 8f52a949081e..29b8496ee641 100644 --- a/app/lib/services/network.freezed.dart +++ b/app/lib/services/network.freezed.dart @@ -132,7 +132,7 @@ class _$NetworkingInitMessageImpl } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$NetworkingInitMessageImpl && @@ -311,7 +311,7 @@ class _$NetworkingUserImpl } @override - bool operator ==(dynamic other) { + bool operator ==(Object other) { return identical(this, other) || (other.runtimeType == runtimeType && other is _$NetworkingUserImpl && diff --git a/app/lib/settings/personalization.dart b/app/lib/settings/personalization.dart index 8742f624c66c..8190172b457c 100644 --- a/app/lib/settings/personalization.dart +++ b/app/lib/settings/personalization.dart @@ -103,6 +103,16 @@ class PersonalizationSettingsPage extends StatelessWidget { Text(_getDensityName(context, state.density)), onTap: () => _openDensityModal(context), ), + SwitchListTile( + secondary: + const PhosphorIcon(PhosphorIconsLight.circleHalf), + title: + Text(AppLocalizations.of(context).highContrast), + value: state.highContrast, + onChanged: (value) => context + .read() + .changeHighContrast(value), + ), ]), ), ), diff --git a/app/lib/theme.dart b/app/lib/theme.dart index 354642a76a47..cd63d505283a 100644 --- a/app/lib/theme.dart +++ b/app/lib/theme.dart @@ -15,7 +15,9 @@ const kClassicThemeData = FlexSchemeData( name: '', description: '', light: kClassicTheme, dark: kClassicTheme); ThemeData getThemeData(String name, bool dark, - [VisualDensity? density, ColorScheme? overridden]) { + [VisualDensity? density, + ColorScheme? overridden, + bool highContrast = false]) { final color = getFlexThemeColor(name, dark); final override = overridden != null && name.isEmpty; ThemeData theme; @@ -27,6 +29,7 @@ ThemeData getThemeData(String name, bool dark, appBarElevation: 2, fontFamily: 'Comfortaa', visualDensity: density, + darkIsTrueBlack: highContrast, ); } else { theme = FlexThemeData.light( @@ -36,6 +39,7 @@ ThemeData getThemeData(String name, bool dark, appBarElevation: 0.5, fontFamily: 'Comfortaa', visualDensity: density, + lightIsWhite: highContrast, ); } return theme.copyWith( diff --git a/fastlane/metadata/android/en-US/changelogs/86.txt b/fastlane/metadata/android/en-US/changelogs/86.txt index 1a8e4a312f12..d4ea55d94bb9 100644 --- a/fastlane/metadata/android/en-US/changelogs/86.txt +++ b/fastlane/metadata/android/en-US/changelogs/86.txt @@ -1,7 +1,9 @@ +* Add high contrast mode ([#564](https://github.com/LinwoodDev/Butterfly/issues/564)) * Add support for multi character input languages ([#539](https://github.com/LinwoodDev/Butterfly/issues/539)) * Add scale to label toolbar * Add scale to label selection view * Add markdown element selection view * Fix moving data directory ([#562](https://github.com/LinwoodDev/Butterfly/issues/562)) * Fix various issues with the label tool -* Fix display icon \ No newline at end of file +* Fix display icon +* Fix spread pages settings not being saved \ No newline at end of file