From e5ddc185b2cf3e40b33b3f27233eed83c0556311 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 21 Jul 2017 10:55:21 +0200 Subject: [PATCH 1/4] Settings: Add app language settings --- Riot.xcodeproj/project.pbxproj | 6 ++ Riot/Assets/en.lproj/Vector.strings | 1 + .../LanguagePickerViewController.h | 21 +++++++ .../LanguagePickerViewController.m | 54 +++++++++++++++++ Riot/ViewController/SettingsViewController.h | 2 +- Riot/ViewController/SettingsViewController.m | 58 ++++++++++++++++++- 6 files changed, 138 insertions(+), 4 deletions(-) create mode 100644 Riot/ViewController/LanguagePickerViewController.h create mode 100644 Riot/ViewController/LanguagePickerViewController.m diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 8764ae962..ac5bd0b55 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -14,6 +14,7 @@ 3205ED851E97725E003D65FA /* DirectoryServerTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3205ED831E97725E003D65FA /* DirectoryServerTableViewCell.xib */; }; 321082B21F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 321082B01F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.m */; }; 321082B31F0E9F41002E0091 /* RoomMembershipCollapsedBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 321082B11F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.xib */; }; + 32185B311F20FA2B00752141 /* LanguagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 32185B301F20FA2B00752141 /* LanguagePickerViewController.m */; }; 322806A01F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3228069E1F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.m */; }; 322806A11F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3228069F1F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.xib */; }; 32471CDC1F1373A100BDF50A /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 32471CDA1F1373A100BDF50A /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m */; }; @@ -499,6 +500,8 @@ 321082AF1F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMembershipCollapsedBubbleCell.h; sourceTree = ""; }; 321082B01F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMembershipCollapsedBubbleCell.m; sourceTree = ""; }; 321082B11F0E9F40002E0091 /* RoomMembershipCollapsedBubbleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomMembershipCollapsedBubbleCell.xib; sourceTree = ""; }; + 32185B2F1F20FA2B00752141 /* LanguagePickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LanguagePickerViewController.h; sourceTree = ""; }; + 32185B301F20FA2B00752141 /* LanguagePickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LanguagePickerViewController.m; sourceTree = ""; }; 3228069D1F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomMembershipExpandedBubbleCell.h; sourceTree = ""; }; 3228069E1F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomMembershipExpandedBubbleCell.m; sourceTree = ""; }; 3228069F1F0F64C4008C53D7 /* RoomMembershipExpandedBubbleCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = RoomMembershipExpandedBubbleCell.xib; sourceTree = ""; }; @@ -1599,6 +1602,8 @@ F083BC2F1E7009EC00A9B29C /* HomeMessagesSearchViewController.m */, F083BC301E7009EC00A9B29C /* HomeViewController.h */, F083BC311E7009EC00A9B29C /* HomeViewController.m */, + 32185B2F1F20FA2B00752141 /* LanguagePickerViewController.h */, + 32185B301F20FA2B00752141 /* LanguagePickerViewController.m */, F083BC321E7009EC00A9B29C /* MediaAlbumContentViewController.h */, F083BC331E7009EC00A9B29C /* MediaAlbumContentViewController.m */, F083BC341E7009EC00A9B29C /* MediaAlbumContentViewController.xib */, @@ -2565,6 +2570,7 @@ F083BE7E1E7009ED00A9B29C /* InviteRecentTableViewCell.m in Sources */, F083BE3C1E7009ED00A9B29C /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */, F083BE211E7009ED00A9B29C /* RoomSearchViewController.m in Sources */, + 32185B311F20FA2B00752141 /* LanguagePickerViewController.m in Sources */, F083BE3E1E7009ED00A9B29C /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */, F083BE071E7009ED00A9B29C /* AttachmentsViewController.m in Sources */, F083BE051E7009ED00A9B29C /* RiotDesignValues.m in Sources */, diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index c137f8e6c..aedca653b 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -329,6 +329,7 @@ //"settings_join_leave_rooms" = "When people join or leave rooms"; //"settings_call_invitations" = "Call invitations"; +"settings_ui_language" = "Language"; "settings_ui_light_theme" = "Light theme"; "settings_ui_dark_theme" = "Dark theme"; diff --git a/Riot/ViewController/LanguagePickerViewController.h b/Riot/ViewController/LanguagePickerViewController.h new file mode 100644 index 000000000..0e65d0494 --- /dev/null +++ b/Riot/ViewController/LanguagePickerViewController.h @@ -0,0 +1,21 @@ +/* + Copyright 2017 Vector Creations Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import + +@interface LanguagePickerViewController : MXKLanguagePickerViewController + +@end diff --git a/Riot/ViewController/LanguagePickerViewController.m b/Riot/ViewController/LanguagePickerViewController.m new file mode 100644 index 000000000..dfa4ec293 --- /dev/null +++ b/Riot/ViewController/LanguagePickerViewController.m @@ -0,0 +1,54 @@ +/* + Copyright 2017 Vector Creations Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +#import "LanguagePickerViewController.h" + +#import "AppDelegate.h" + +@implementation LanguagePickerViewController + +- (void)finalizeInit +{ + [super finalizeInit]; + + // Setup `MXKViewControllerHandling` properties + self.defaultBarTintColor = kRiotNavBarTintColor; + self.enableBarTintColorStatusChange = NO; + self.rageShakeManager = [RageShakeManager sharedManager]; +} + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Hide line separators of empty cells + self.tableView.tableFooterView = [[UIView alloc] init]; +} + +- (void)viewWillAppear:(BOOL)animated +{ + [super viewWillAppear:animated]; + + // Screen tracking (via Google Analytics) + id tracker = [[GAI sharedInstance] defaultTracker]; + if (tracker) + { + [tracker set:kGAIScreenName value:@"CountryPicker"]; + [tracker send:[[GAIDictionaryBuilder createScreenView] build]]; + } +} + +@end diff --git a/Riot/ViewController/SettingsViewController.h b/Riot/ViewController/SettingsViewController.h index f4c06b888..6713cb94d 100644 --- a/Riot/ViewController/SettingsViewController.h +++ b/Riot/ViewController/SettingsViewController.h @@ -21,7 +21,7 @@ #import "MediaPickerViewController.h" #import "TableViewCellWithCheckBoxes.h" -@interface SettingsViewController : MXKTableViewController +@interface SettingsViewController : MXKTableViewController @end diff --git a/Riot/ViewController/SettingsViewController.m b/Riot/ViewController/SettingsViewController.m index a1f8da2d5..5b09b69f6 100644 --- a/Riot/ViewController/SettingsViewController.m +++ b/Riot/ViewController/SettingsViewController.m @@ -29,6 +29,7 @@ #import "BugReportViewController.h" #import "CountryPickerViewController.h" +#import "LanguagePickerViewController.h" #import "TableViewCellWithPhoneNumberTextField.h" #import "NBPhoneNumberUtil.h" @@ -71,7 +72,8 @@ enum enum { - USER_INTERFACE_THEME_INDEX = 0, + USER_INTERFACE_LANGUAGE_INDEX = 0, + USER_INTERFACE_THEME_INDEX, USER_INTERFACE_COUNT }; @@ -1565,7 +1567,26 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); } else if (section == SETTINGS_SECTION_USER_INTERFACE_INDEX) { - if (row == USER_INTERFACE_THEME_INDEX) + if (row == USER_INTERFACE_LANGUAGE_INDEX) + { + cell = [tableView dequeueReusableCellWithIdentifier:kSettingsViewControllerPhoneBookCountryCellId]; + if (!cell) + { + cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:kSettingsViewControllerPhoneBookCountryCellId]; + } + + NSString *language = [NSBundle mxk_language]; + NSString *languageDescription = language ? [MXKLanguagePickerViewController languageDescription:language] : [MXKLanguagePickerViewController languageDescription:[MXKLanguagePickerViewController defaultLanguage]]; + + cell.textLabel.textColor = kRiotTextColorBlack; + + cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_language", @"Vector", nil); + cell.detailTextLabel.text = languageDescription; + + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.selectionStyle = UITableViewCellSelectionStyleDefault; + } + else if (row == USER_INTERFACE_THEME_INDEX) { uiThemeCell = [tableView dequeueReusableCellWithIdentifier:[TableViewCellWithCheckBoxes defaultReuseIdentifier] forIndexPath:indexPath]; @@ -2057,7 +2078,18 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); NSInteger section = indexPath.section; NSInteger row = indexPath.row; - if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX) + if (section == SETTINGS_SECTION_USER_INTERFACE_INDEX) + { + if (row == USER_INTERFACE_LANGUAGE_INDEX) + { + // Display the language picker + LanguagePickerViewController *languagePickerViewController = [LanguagePickerViewController languagePickerViewController]; + languagePickerViewController.selectedLanguage = [NSBundle mxk_language]; + languagePickerViewController.delegate = self; + [self pushViewController:languagePickerViewController]; + } + } + else if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX) { MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; @@ -3481,6 +3513,26 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); [countryPickerViewController withdrawViewControllerAnimated:YES completion:nil]; } +#pragma mark - MXKCountryPickerViewControllerDelegate + +- (void)languagePickerViewController:(MXKLanguagePickerViewController *)languagePickerViewController didSelectLangugage:(NSString *)language +{ + [languagePickerViewController withdrawViewControllerAnimated:YES completion:nil]; + + if (![language isEqualToString:[NSBundle mxk_language]]) + { + [NSBundle mxk_setLanguage:language]; + + // Do a full sync to recompute room summaries + // TODO: resetting room summaries and room data sources should be enough + [self startActivityIndicator]; + dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ + + [[AppDelegate theDelegate] reloadMatrixSessions:YES]; + }); + } +} + #pragma mark - TableViewCellWithCheckBoxesDelegate - (void)tableViewCellWithCheckBoxes:(TableViewCellWithCheckBoxes *)tableViewCellWithCheckBoxes didTapOnCheckBoxAtIndex:(NSUInteger)index From 68b5083a5251083d6f96485b208426a49a377b28 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 21 Jul 2017 11:08:33 +0200 Subject: [PATCH 2/4] Language settings: Store it in NSUserDefaults (@"appLanguage") --- Riot/AppDelegate.m | 7 ++++++- Riot/ViewController/BugReportViewController.m | 1 + Riot/ViewController/SettingsViewController.m | 4 ++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index ee993eec6..5a033cba6 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -291,7 +291,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN NSLog(@"MatrixSDK version: %@", MatrixSDKVersion); NSLog(@"Build: %@\n", build); NSLog(@"------------------------------\n"); - + + // Set up runtime language and fallback + NSString *langage = [[NSUserDefaults standardUserDefaults] objectForKey:@"appLanguage"];; + [NSBundle mxk_setLanguage:langage]; + [NSBundle mxk_setFallbackLanguage:@"en"]; + // Define the navigation bar text color [[UINavigationBar appearance] setTintColor:kRiotColorGreen]; diff --git a/Riot/ViewController/BugReportViewController.m b/Riot/ViewController/BugReportViewController.m index b9087d541..76613b993 100644 --- a/Riot/ViewController/BugReportViewController.m +++ b/Riot/ViewController/BugReportViewController.m @@ -238,6 +238,7 @@ userInfo[@"locale"] = [NSLocale preferredLanguages][0]; userInfo[@"app_language"] = [[NSBundle mainBundle] preferredLocalizations][0]; + //TODO bugReportRestClient.others = userInfo; diff --git a/Riot/ViewController/SettingsViewController.m b/Riot/ViewController/SettingsViewController.m index 5b09b69f6..77a86d47f 100644 --- a/Riot/ViewController/SettingsViewController.m +++ b/Riot/ViewController/SettingsViewController.m @@ -3523,6 +3523,10 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); { [NSBundle mxk_setLanguage:language]; + // Store user settings + [[NSUserDefaults standardUserDefaults] setObject:language forKey:@"appLanguage"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + // Do a full sync to recompute room summaries // TODO: resetting room summaries and room data sources should be enough [self startActivityIndicator]; From 3847beda8fa571c3b3148704ccea749cf4de56b6 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 21 Jul 2017 12:06:10 +0200 Subject: [PATCH 3/4] Language settings: Reload data softly after language change --- Riot/ViewController/SettingsViewController.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/ViewController/SettingsViewController.m b/Riot/ViewController/SettingsViewController.m index 77a86d47f..72ac1313f 100644 --- a/Riot/ViewController/SettingsViewController.m +++ b/Riot/ViewController/SettingsViewController.m @@ -3519,7 +3519,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); { [languagePickerViewController withdrawViewControllerAnimated:YES completion:nil]; - if (![language isEqualToString:[NSBundle mxk_language]]) + if (![language isEqualToString:[NSBundle mxk_language]] + || (language == nil && [NSBundle mxk_language])) { [NSBundle mxk_setLanguage:language]; @@ -3527,12 +3528,11 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); [[NSUserDefaults standardUserDefaults] setObject:language forKey:@"appLanguage"]; [[NSUserDefaults standardUserDefaults] synchronize]; - // Do a full sync to recompute room summaries - // TODO: resetting room summaries and room data sources should be enough + // Do a full sync to recompute matrix data (rooms data sources and summaries) [self startActivityIndicator]; dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 0.3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ - [[AppDelegate theDelegate] reloadMatrixSessions:YES]; + [[AppDelegate theDelegate] reloadMatrixSessions:NO]; }); } } From 1c0476f0ef8211c60558a7903dfbc3f4842b5c2f Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 21 Jul 2017 15:09:23 +0200 Subject: [PATCH 4/4] Language settings: Report it in the bug report --- Riot/ViewController/BugReportViewController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/ViewController/BugReportViewController.m b/Riot/ViewController/BugReportViewController.m index 76613b993..fb38f491e 100644 --- a/Riot/ViewController/BugReportViewController.m +++ b/Riot/ViewController/BugReportViewController.m @@ -237,8 +237,8 @@ } userInfo[@"locale"] = [NSLocale preferredLanguages][0]; - userInfo[@"app_language"] = [[NSBundle mainBundle] preferredLocalizations][0]; - //TODO + userInfo[@"default_app_language"] = [[NSBundle mainBundle] preferredLocalizations][0]; // The language chosen by the OS + userInfo[@"app_language"] = [NSBundle mxk_language] ? [NSBundle mxk_language] : userInfo[@"default_app_language"]; // The language chosen by the user bugReportRestClient.others = userInfo;