Skip to content
This repository has been archived by the owner on Oct 19, 2022. It is now read-only.

Commit

Permalink
OT-717: Unreadable Status Bar
Browse files Browse the repository at this point in the history
Fixes #449

BUGFIX
* Fixes a bug that happens on switching between Light and Dark mode, which results in an unreadable system status bar

ADDITIONS & CHANGES
* Adds a new `ThemeKey` enum value `system`
* Changes setting for Light/Dark mode in user profile by removing the switch
* Adds a new screen for switching application appearance to `Light`/`Dark` or `System`
* Refactors all `ThemeKey` enum values from UPPERCASE to lowercase
* Adds `vibrateLight` method for haptic feedback when user changes appearance
* Cleans up code

ADDITIONAL NOTES
* Adds `activeColor` setting to all used `Switch.adaptive` widgets with the value of `CustomTheme.of(context).accent`, because on iOS they had the default green color which doesn't fit our application color theme.
* Adds `Preference` class with just two static methods `set({@required value, @required String forKey})` and `value({@required String forKey})` for convenience and better readability
* Adds static getter/setter on `Preference` class for easier handling of preference values (NOTE: Should be discussed if we adopt this system overall)
  So instead of calling:
  ```
   setPreference(preferenceAppThemeKey, ThemeKey.light.toString());
  ```
  we can call:
  ```
  Preference.themeKey = ThemeKey.light.toString();
  ```
  • Loading branch information
Frank Gregor committed Apr 4, 2020
1 parent 75c5934 commit 1769858
Show file tree
Hide file tree
Showing 19 changed files with 467 additions and 58 deletions.
19 changes: 11 additions & 8 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ void main() {
),
],
child: CustomTheme(
initialThemeKey: ThemeKey.LIGHT,
initialThemeKey: ThemeKey.light,
child: OxCoiApp(),
),
),
Expand All @@ -104,20 +104,23 @@ class OxCoiApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var customTheme = CustomTheme.of(context);
return MaterialApp(
theme: ThemeData(
final themeData = ThemeData(
brightness: customTheme.brightness,
backgroundColor: customTheme.background,
scaffoldBackgroundColor: customTheme.background,
toggleableActiveColor: customTheme.accent,
accentColor: customTheme.accent,
primaryIconTheme: Theme.of(context).primaryIconTheme.copyWith(
color: customTheme.onSurface,
),
color: customTheme.onSurface,
),
primaryTextTheme: Theme.of(context).primaryTextTheme.apply(
bodyColor: customTheme.onSurface,
),
),
bodyColor: customTheme.onSurface,
),
);

return MaterialApp(
theme: themeData,
themeMode: customTheme.brightness == Brightness.light ? ThemeMode.light : ThemeMode.dark,
localizationsDelegates: getLocalizationsDelegates(),
supportedLocales: L10n.supportedLocales,
localeResolutionCallback: (deviceLocale, supportedLocales) {
Expand Down
4 changes: 2 additions & 2 deletions lib/src/brandable/brandable_icon.dart
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ enum IconSource {
retry,
checkedCircle,
circle,
darkMode,
appearance,
qr,
signature,
serverSetting,
Expand Down Expand Up @@ -173,7 +173,7 @@ const iconData = {
IconSource.retry: Icons.autorenew,
IconSource.checkedCircle: Icons.check_circle,
IconSource.circle: Icons.radio_button_unchecked,
IconSource.darkMode: Icons.brightness_2,
IconSource.appearance: Icons.palette,
IconSource.qr: Icons.filter_center_focus,
IconSource.signature: Icons.gesture,
IconSource.serverSetting: Icons.router,
Expand Down
2 changes: 1 addition & 1 deletion lib/src/brandable/branded_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ class BrandedTheme {
final Color chatIcon = Colors.lightBlue[800];
final Color signatureIcon = Colors.blue[600];
final Color serverSettingsIcon = Colors.indigo[600];
final Color darkModeIcon = Colors.deepPurple[500];
final Color appearanceIcon = Colors.deepPurple[500];
final Color dataProtectionIcon = Colors.purple[400];
final Color blockIcon = Colors.pink[500];
final Color encryptionIcon = Colors.red[600];
Expand Down
79 changes: 57 additions & 22 deletions lib/src/brandable/custom_theme.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,14 @@
*/

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:ox_coi/src/platform/preferences.dart';

import 'branded_theme.dart';
import 'package:ox_coi/src/brandable/branded_theme.dart';

enum ThemeKey {
LIGHT,
DARK,
system,
light,
dark,
}

class CustomerThemes {
Expand Down Expand Up @@ -93,12 +94,13 @@ class CustomerThemes {

static BrandedTheme getThemeFromKey(ThemeKey themeKey) {
switch (themeKey) {
case ThemeKey.LIGHT:
case ThemeKey.light:
return lightTheme;
case ThemeKey.DARK:
case ThemeKey.dark:
return darkTheme;
default:
return lightTheme;
final brightness = WidgetsBinding.instance.window.platformBrightness;
return brightness == Brightness.light ? lightTheme : darkTheme;
}
}
}
Expand All @@ -122,11 +124,7 @@ class CustomTheme extends StatefulWidget {
final Widget child;
final ThemeKey initialThemeKey;

const CustomTheme({
Key key,
this.initialThemeKey,
@required this.child,
}) : super(key: key);
const CustomTheme({Key key, this.initialThemeKey, @required this.child}) : super(key: key);

@override
CustomThemeState createState() => new CustomThemeState();
Expand All @@ -140,6 +138,24 @@ class CustomTheme extends StatefulWidget {
_CustomTheme inherited = (context.dependOnInheritedWidgetOfExactType<_CustomTheme>());
return inherited.data;
}

static ThemeKey getThemeKeyFor({@required String name}) {
if (name == ThemeKey.system.toString()) {
return ThemeKey.system;
} else if (name == ThemeKey.light.toString()) {
return ThemeKey.light;
} else {
return ThemeKey.dark;
}
}

static ThemeKey get systemThemeKey {
final brightness = WidgetsBinding.instance.window.platformBrightness;
if (brightness == Brightness.light) {
return ThemeKey.light;
}
return ThemeKey.dark;
}
}

class CustomThemeState extends State<CustomTheme> with WidgetsBindingObserver {
Expand Down Expand Up @@ -169,23 +185,42 @@ class CustomThemeState extends State<CustomTheme> with WidgetsBindingObserver {
_checkSavedTheme();
}

void _checkSavedTheme() async{
var newThemeKey;
String savedThemeKey = await getPreference(preferenceAppThemeKey);
if(savedThemeKey == null){
final Brightness brightness = WidgetsBinding.instance.window.platformBrightness;
newThemeKey = brightness == Brightness.light ? ThemeKey.LIGHT : ThemeKey.DARK;
}else{
newThemeKey = savedThemeKey.compareTo(ThemeKey.LIGHT.toString()) == 0 ? ThemeKey.LIGHT : ThemeKey.DARK;
void _checkSavedTheme() async {
var savedThemeKeyString = await Preference.themeKey;

ThemeKey savedThemeKey;
if (savedThemeKeyString == null) {
savedThemeKey = ThemeKey.system;
savedThemeKeyString = savedThemeKey.toString();
Preference.themeKey = savedThemeKeyString;
}

ThemeKey newThemeKey;
if (savedThemeKey == ThemeKey.system) {
final platformBrightness = WidgetsBinding.instance.window.platformBrightness;
newThemeKey = platformBrightness == Brightness.light ? ThemeKey.light : ThemeKey.dark;
} else {
newThemeKey = CustomTheme.getThemeKeyFor(name: savedThemeKeyString);
}
changeTheme(newThemeKey);

changeTheme(themeKey: newThemeKey, preservePreference: true);
}

void changeTheme(ThemeKey themeKey) {
void changeTheme({@required ThemeKey themeKey, bool preservePreference = false}) async {
setState(() {
_actualThemeKey = themeKey;
_theme = CustomerThemes.getThemeFromKey(themeKey);
});

if (!preservePreference) {
Preference.themeKey = themeKey.toString();
}

SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
statusBarColor: CustomerThemes.getThemeFromKey(themeKey).background, // Android only
statusBarIconBrightness: themeKey == ThemeKey.dark ? Brightness.light : Brightness.dark, // Android only
statusBarBrightness: themeKey == ThemeKey.dark ? Brightness.dark : Brightness.light // iOS only
));
}

@override
Expand Down
8 changes: 7 additions & 1 deletion lib/src/l10n/l.dart
Original file line number Diff line number Diff line change
Expand Up @@ -429,14 +429,20 @@ class L {
static final settingItemChatTitle = _translationKey("Chat");
static final settingItemSignatureTitle = _translationKey("Email signature");
static final settingItemServerSettingsTitle = _translationKey("Server settings");
static final settingItemDarkModeTitle = _translationKey("Dark mode");
static final settingItemDataProtectionTitle = _translationKey("Data protection");
static final settingItemBlockedTitle = _translationKey("Blocked contacts");
static final settingItemEncryptionTitle = _translationKey("Encryption");
static final settingItemAboutTitle = _translationKey("About");
static final settingItemFeedbackTitle = _translationKey("Feedback");
static final settingItemBugReportTitle = _translationKey("Report a bug");

static final settingsAppearanceTitle = _translationKey("Appearance");
static final settingsAppearanceSystemTitle = _translationKey("System");
static final settingsAppearanceDarkTitle = _translationKey("Dark");
static final settingsAppearanceLightTitle = _translationKey("Light");
static final settingsAppearanceDescritpion = _translationKey("Here you can choose your favorite theme. If you choose '%s', the theme may change automatically. This depends on whether you have selected 'Automatic' in the system preferences or not.");
static final settingsAppearanceSystemThemeDescription = _translationKey("Current System theme is: %s");

static List<String> _translationKey(String key, [String pluralKey]) {
String logging = "Registered localization key: '$key'";
if (!pluralKey.isNullOrEmpty()) {
Expand Down
1 change: 1 addition & 0 deletions lib/src/navigation/navigatable.dart
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ enum Type {
settingsKeyTransferDoneDialog,
settingsAutocryptImport,
settingsNotifications,
settingsAppearance,
splash,
share,
showQr,
Expand Down
5 changes: 4 additions & 1 deletion lib/src/navigation/navigation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ import 'package:ox_coi/src/navigation/navigatable.dart';
import 'package:ox_coi/src/settings/settings.dart';
import 'package:ox_coi/src/settings/settings_about.dart';
import 'package:ox_coi/src/settings/settings_anti_mobbing.dart';
import 'package:ox_coi/src/settings/settings_appearance.dart';
import 'package:ox_coi/src/settings/settings_chat.dart';
import 'package:ox_coi/src/settings/settings_debug.dart';
import 'package:ox_coi/src/settings/settings_notifications.dart';
import 'package:ox_coi/src/settings/settings_encryption.dart';
import 'package:ox_coi/src/settings/settings_notifications.dart';
import 'package:ox_coi/src/user/user_account_settings.dart';

class Navigation {
Expand All @@ -70,6 +71,7 @@ class Navigation {
static const String settingsAbout = '/settings/about';
static const String settingsChat = '/settings/chat';
static const String settingsAntiMobbing = '/settings/antiMobbing';
static const String settingsAppearance = '/settings/appearance';
static const String settingsNotifications = '/settings/notifications';
static const String settingsAntiMobbingList = '/settings/antiMobbingList';
static const String settingsDebug = '/settings/debug';
Expand All @@ -86,6 +88,7 @@ class Navigation {
settingsChat: (context) => SettingsChat(),
settingsAntiMobbing: (context) => SettingsAntiMobbing(),
settingsAntiMobbingList: (context) => AntiMobbingList(),
settingsAppearance: (context) => SettingsAppearance(),
settingsNotifications: (context) => SettingsNotifications(),
settingsDebug: (context) => SettingsDebug(),
chatCreate: (context) => ChatCreate(),
Expand Down
18 changes: 17 additions & 1 deletion lib/src/platform/preferences.dart
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
* for more details.
*/

import 'package:flutter/cupertino.dart';
import 'package:shared_preferences/shared_preferences.dart';

const preferenceSystemContactsImportShown = "preferenceSystemContactsImportShown";
Expand All @@ -54,7 +55,6 @@ const preferenceNotificationsPushStatus = "preferenceNotificationsPushStatus";
const preferenceAppState = "preferenceAppState";
const preferenceInviteServiceUrl = "preferenceInviteServiceUrl";
const preferenceHasAuthenticationError = "preferenceHasAuthenticationError";
const preferenceAppThemeKey = "preferenceAppThemeKey";

const preferenceNotificationsAuth = "preferenceNotificationsAuth"; // Unused
const preferenceNotificationsP256dhPublic = "preferenceNotificationsP256dhPublic"; // Unused
Expand Down Expand Up @@ -96,4 +96,20 @@ Future<void> removePreference(String key) async {
Future<void> clearPreferences() async {
SharedPreferences sharedPreferences = await getSharedPreferences();
await sharedPreferences.clear();
}

class Preference {

static const _themeKey = "themeKey";
static Future<String> get themeKey async => await value(forKey: _themeKey);
static set themeKey(String value) => set(value: value, forKey: _themeKey);

static set({@required value, @required String forKey}) async {
await setPreference(forKey, value);
}

static value({@required String forKey}) async {
return await getPreference(forKey);
}

}
7 changes: 6 additions & 1 deletion lib/src/settings/settings_anti_mobbing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:ox_coi/src/brandable/brandable_icon.dart';
import 'package:ox_coi/src/brandable/custom_theme.dart';
import 'package:ox_coi/src/l10n/l.dart';
import 'package:ox_coi/src/l10n/l10n.dart';
import 'package:ox_coi/src/navigation/navigatable.dart';
Expand Down Expand Up @@ -93,7 +94,11 @@ class _SettingsAntiMobbingState extends State<SettingsAntiMobbing> {
contentPadding: EdgeInsets.symmetric(vertical: listItemPadding, horizontal: listItemPadding),
title: Text(L10n.get(L.settingAntiMobbing)),
subtitle: Text(L10n.get(L.settingAntiMobbingText)),
trailing: Switch.adaptive(value: state.antiMobbingActive, onChanged: (value) => _changeAntiMobbingSetting()),
trailing: Switch.adaptive(
value: state.antiMobbingActive,
onChanged: (value) => _changeAntiMobbingSetting(),
activeColor: CustomTheme.of(context).accent,
),
),
Visibility(
visible: state.antiMobbingActive,
Expand Down
Loading

0 comments on commit 1769858

Please sign in to comment.