BF: [iOS11] "Smart [colors] Invert" renders badly in the app

https://github.com/vector-im/riot-ios/issues/1524

- the app does its own dark theme and prevents the OS from automatically revert the colors in the app
- there are 3 choices on iOS11 for the Riot theme: "auto", "light", "dark". "auto" uses the system settings
This commit is contained in:
manuroe 2017-09-21 15:29:46 +02:00
parent ff4786d7df
commit 819f407ae1
8 changed files with 151 additions and 53 deletions

View file

@ -516,6 +516,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN
[self refreshLocalContacts]; [self refreshLocalContacts];
_isAppForeground = YES; _isAppForeground = YES;
if (@available(iOS 11.0, *))
{
// Riot has its own dark theme. Prevent iOS from applying its one
[[UIApplication sharedApplication] keyWindow].accessibilityIgnoresInvertColors = YES;
}
[self handleLaunchAnimation]; [self handleLaunchAnimation];
} }

View file

@ -416,8 +416,6 @@
"auth_email_not_found" = "Fehler beim Senden der E-Mail: Die E-Mail-Adresse wurde nicht gefunden"; "auth_email_not_found" = "Fehler beim Senden der E-Mail: Die E-Mail-Adresse wurde nicht gefunden";
"settings_user_interface" = "BENUTZEROBERFLÄCHE"; "settings_user_interface" = "BENUTZEROBERFLÄCHE";
"settings_ui_language" = "Sprache"; "settings_ui_language" = "Sprache";
"settings_ui_light_theme" = "Helles Design";
"settings_ui_dark_theme" = "Dunkles Design";
// Events formatter // Events formatter
"event_formatter_member_updates" = "%tu Änderungen der Mitgliedschaft"; "event_formatter_member_updates" = "%tu Änderungen der Mitgliedschaft";
"contacts_user_directory_section" = "NUTZER VERZEICHNIS"; "contacts_user_directory_section" = "NUTZER VERZEICHNIS";

View file

@ -340,8 +340,12 @@
//"settings_call_invitations" = "Call invitations"; //"settings_call_invitations" = "Call invitations";
"settings_ui_language" = "Language"; "settings_ui_language" = "Language";
"settings_ui_light_theme" = "Light theme"; "settings_ui_theme" = "Theme";
"settings_ui_dark_theme" = "Dark theme"; "settings_ui_theme_auto" = "Auto";
"settings_ui_theme_light" = "Light";
"settings_ui_theme_dark" = "Dark";
"settings_ui_theme_picker_title" = "Select a theme";
"settings_ui_theme_picker_message" = "\"Auto\" uses your device \"Invert Colours\" settings";
"settings_unignore_user" = "Show all messages from %@?"; "settings_unignore_user" = "Show all messages from %@?";

View file

@ -417,8 +417,12 @@
"auth_phone_in_use" = "Ce numéro de téléphone est déjà utilisé"; "auth_phone_in_use" = "Ce numéro de téléphone est déjà utilisé";
"auth_email_not_found" = "Échec lors de l'envoi de l'e-mail : Cette adresse e-mail n'a pas pu être trouvée"; "auth_email_not_found" = "Échec lors de l'envoi de l'e-mail : Cette adresse e-mail n'a pas pu être trouvée";
"settings_ui_language" = "Langue"; "settings_ui_language" = "Langue";
"settings_ui_light_theme" = "Thème clair"; "settings_ui_theme" = "Thème";
"settings_ui_dark_theme" = "Thème sombre"; "settings_ui_theme_auto" = "Auto";
"settings_ui_theme_light" = "Clair";
"settings_ui_theme_dark" = "Sombre";
"settings_ui_theme_picker_title" = "Selectionnez un thème";
"settings_ui_theme_picker_message" = "\"Auto\" utilise le paramètre \"Inverser les couleurs\" de votre appareil";
"collapse" = "réduire"; "collapse" = "réduire";
"auth_untrusted_id_server" = "Le serveur d'identité n'est pas fiable"; "auth_untrusted_id_server" = "Le serveur d'identité n'est pas fiable";
"settings_user_interface" = "INTERFACE UTILISATEUR"; "settings_user_interface" = "INTERFACE UTILISATEUR";

View file

@ -440,8 +440,6 @@
"contacts_user_directory_offline_section" = "GEBRUIKERSADRESBOEK (offline)"; "contacts_user_directory_offline_section" = "GEBRUIKERSADRESBOEK (offline)";
"settings_user_interface" = "GEBRUIKERSINTERFACE"; "settings_user_interface" = "GEBRUIKERSINTERFACE";
"settings_ui_language" = "Taal"; "settings_ui_language" = "Taal";
"settings_ui_light_theme" = "Lichte thema";
"settings_ui_dark_theme" = "Donkere thema";
// Read Receipts // Read Receipts
"read_receipts_list" = "Leesbewijzen Lijst"; "read_receipts_list" = "Leesbewijzen Lijst";
"receipt_status_read" = "Lees: "; "receipt_status_read" = "Lees: ";

View file

@ -262,8 +262,6 @@
"settings_global_settings_info" = "Глобальные настройки уведомлений доступны в вашем %@ веб-клиенте"; "settings_global_settings_info" = "Глобальные настройки уведомлений доступны в вашем %@ веб-клиенте";
"settings_on_denied_notification" = "Уведомления для %@ запрещены, пожалуйста, разрешите их в настройках вашего устройства"; "settings_on_denied_notification" = "Уведомления для %@ запрещены, пожалуйста, разрешите их в настройках вашего устройства";
"settings_ui_language" = "Язык"; "settings_ui_language" = "Язык";
"settings_ui_light_theme" = "Светлая тема";
"settings_ui_dark_theme" = "Темная тема";
"settings_unignore_user" = "Показать все сообщения от %@?"; "settings_unignore_user" = "Показать все сообщения от %@?";
"settings_labs_e2e_encryption" = "Сквозное шифрование"; "settings_labs_e2e_encryption" = "Сквозное шифрование";
"settings_labs_e2e_encryption_prompt_message" = "Чтобы завершить настройку шифрования, вы должны войти в систему еще раз."; "settings_labs_e2e_encryption_prompt_message" = "Чтобы завершить настройку шифрования, вы должны войти в систему еще раз.";

View file

@ -112,8 +112,10 @@ UIColor *kRiotDesignSearchBarTintColor = nil;
// Observe user interface theme change. // Observe user interface theme change.
[[NSUserDefaults standardUserDefaults] addObserver:[RiotDesignValues sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil]; [[NSUserDefaults standardUserDefaults] addObserver:[RiotDesignValues sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil];
[[RiotDesignValues sharedInstance] userInterfaceThemeDidChange]; [[RiotDesignValues sharedInstance] userInterfaceThemeDidChange];
}
// Observe "Invert Colours" settings changes (available since iOS 11)
[[NSNotificationCenter defaultCenter] addObserver:[RiotDesignValues sharedInstance] selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{ {
@ -123,10 +125,25 @@ UIColor *kRiotDesignSearchBarTintColor = nil;
} }
} }
- (void)accessibilityInvertColorsStatusDidChange
{
// Refresh the theme only for "auto"
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
if (!theme || [theme isEqualToString:@"auto"])
{
[self userInterfaceThemeDidChange];
}
}
- (void)userInterfaceThemeDidChange - (void)userInterfaceThemeDidChange
{ {
// Retrieve the current selected theme ("light" if none). // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11).
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"]; NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
if (!theme || [theme isEqualToString:@"auto"])
{
theme = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light";
}
// Currently only 2 themes is supported // Currently only 2 themes is supported
if ([theme isEqualToString:@"dark"]) if ([theme isEqualToString:@"dark"])

View file

@ -1695,36 +1695,39 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
} }
else if (row == USER_INTERFACE_THEME_INDEX) else if (row == USER_INTERFACE_THEME_INDEX)
{ {
uiThemeCell = [tableView dequeueReusableCellWithIdentifier:[TableViewCellWithCheckBoxes defaultReuseIdentifier] forIndexPath:indexPath]; cell = [tableView dequeueReusableCellWithIdentifier:kSettingsViewControllerPhoneBookCountryCellId];
if (!cell)
uiThemeCell.mainContainerLeadingConstraint.constant = uiThemeCell.separatorInset.left;
uiThemeCell.checkBoxesNumber = 2;
uiThemeCell.allowsMultipleSelection = NO;
uiThemeCell.delegate = self;
NSArray *labels = uiThemeCell.labels;
UILabel *label;
label = labels[0];
label.textColor = kRiotPrimaryTextColor;
label.text = NSLocalizedStringFromTable(@"settings_ui_light_theme", @"Vector", nil);
label = labels[1];
label.textColor = kRiotPrimaryTextColor;
label.text = NSLocalizedStringFromTable(@"settings_ui_dark_theme", @"Vector", nil);
NSString *selectedTheme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
if (selectedTheme && [selectedTheme isEqualToString:@"dark"])
{ {
[uiThemeCell setCheckBoxValue:YES atIndex:1]; cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kSettingsViewControllerPhoneBookCountryCellId];
} }
else
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
if (!theme)
{ {
// Consider the light theme by default. if (@available(iOS 11.0, *))
[uiThemeCell setCheckBoxValue:YES atIndex:0]; {
// "auto" is used the default value from iOS 11
theme = @"auto";
}
else
{
// Use "light" for older version
theme = @"light";
}
} }
cell = uiThemeCell; theme = [NSString stringWithFormat:@"settings_ui_theme_%@", theme];
NSString *i18nTheme = NSLocalizedStringFromTable(theme,
@"Vector",
nil);
cell.textLabel.textColor = kRiotPrimaryTextColor;
cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_theme", @"Vector", nil);
cell.detailTextLabel.text = i18nTheme;
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
cell.selectionStyle = UITableViewCellSelectionStyleDefault;
} }
} }
else if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX) else if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX)
@ -2270,6 +2273,10 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
languagePickerViewController.delegate = self; languagePickerViewController.delegate = self;
[self pushViewController:languagePickerViewController]; [self pushViewController:languagePickerViewController];
} }
else if (row == USER_INTERFACE_THEME_INDEX)
{
[self showThemePicker];
}
} }
else if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX) else if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX)
{ {
@ -3430,6 +3437,87 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
} }
} }
- (void)showThemePicker
{
__weak typeof(self) weakSelf = self;
__block UIAlertAction *autoAction, *lightAction, *darkAction;
NSString *themePickerMessage;
void (^actionBlock)(UIAlertAction *action) = ^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
NSString *newTheme;
if (action == autoAction)
{
newTheme = @"auto";
}
else if (action == lightAction)
{
newTheme = @"light";
}
else if (action == darkAction)
{
newTheme = @"dark";
}
NSString *theme = [[NSUserDefaults standardUserDefaults] stringForKey:@"userInterfaceTheme"];
if (newTheme && ![newTheme isEqualToString:theme])
{
// Clear fake Riot Avatars based on the previous theme.
[AvatarGenerator clear];
// The user wants to select this theme
[[NSUserDefaults standardUserDefaults] setObject:newTheme forKey:@"userInterfaceTheme"];
[[NSUserDefaults standardUserDefaults] synchronize];
[self.tableView reloadData];
}
}
};
if (@available(iOS 11.0, *))
{
// Show "auto" only from iOS 11
autoAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_auto", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:actionBlock];
// Explain what is "auto"
themePickerMessage = NSLocalizedStringFromTable(@"settings_ui_theme_picker_message", @"Vector", nil);
}
lightAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_light", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:actionBlock];
darkAction = [UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_dark", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:actionBlock];
// Ask the user the kind of the call: voice or video?
UIAlertController *themePicker = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"settings_ui_theme_picker_title", @"Vector", nil)
message:themePickerMessage
preferredStyle:UIAlertControllerStyleActionSheet];
if (autoAction)
{
[themePicker addAction:autoAction];
}
[themePicker addAction:lightAction];
[themePicker addAction:darkAction];
// Cancel button
[themePicker addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleDefault
handler:nil]];
[self presentViewController:themePicker animated:YES completion:nil];
}
#pragma mark - MediaPickerViewController Delegate #pragma mark - MediaPickerViewController Delegate
- (void)dismissMediaPicker - (void)dismissMediaPicker
@ -3773,21 +3861,6 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)();
- (void)tableViewCellWithCheckBoxes:(TableViewCellWithCheckBoxes *)tableViewCellWithCheckBoxes didTapOnCheckBoxAtIndex:(NSUInteger)index - (void)tableViewCellWithCheckBoxes:(TableViewCellWithCheckBoxes *)tableViewCellWithCheckBoxes didTapOnCheckBoxAtIndex:(NSUInteger)index
{ {
if (tableViewCellWithCheckBoxes == uiThemeCell)
{
NSString *theme = (index == 0) ? @"light" : @"dark";
BOOL isCurrentlySelected = [uiThemeCell checkBoxValueAtIndex:index];
if (!isCurrentlySelected)
{
// Clear fake Riot Avatars based on the previous theme.
[AvatarGenerator clear];
// The user wants to select this theme
[[NSUserDefaults standardUserDefaults] setObject:theme forKey:@"userInterfaceTheme"];
[[NSUserDefaults standardUserDefaults] synchronize];
}
}
} }
@end @end