From d9c36476f1016d517f1f34ca7c6bbf2144f915b2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 29 Nov 2018 14:09:12 +0100 Subject: [PATCH 001/244] Reskin: Store color values provided in zeplin --- Riot.xcodeproj/project.pbxproj | 26 +++++++++ Riot/Constants/Colors/ColorValues.swift | 57 +++++++++++++++++++ Riot/Constants/Colors/DarkColorValues.swift | 50 ++++++++++++++++ .../Constants/Colors/DefaultColorValues.swift | 50 ++++++++++++++++ 4 files changed, 183 insertions(+) create mode 100644 Riot/Constants/Colors/ColorValues.swift create mode 100644 Riot/Constants/Colors/DarkColorValues.swift create mode 100644 Riot/Constants/Colors/DefaultColorValues.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index d98c83e20..6cc675aad 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -10,6 +10,12 @@ 24CBEC591F0EAD310093EABB /* RiotShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BBE81E7009EC00A9B29C /* MXRoom+Riot.m */; }; 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BC111E7009EC00A9B29C /* AvatarGenerator.m */; }; + 3223D9C021B00615000321C1 /* ColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* ColorValues.swift */; }; + 3223D9C121B00615000321C1 /* DefaultColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */; }; + 3223D9C321B0065A000321C1 /* DarkColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkColorValues.swift */; }; + 3223D9C421B0077D000321C1 /* ColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* ColorValues.swift */; }; + 3223D9C521B00781000321C1 /* DarkColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkColorValues.swift */; }; + 3223D9C621B00788000321C1 /* DefaultColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */; }; 3233F7461F3497E2006ACA81 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; }; 3233F7471F3497E2006ACA81 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3284A35120A07C210044F922 /* postMessageAPI.js in Resources */ = {isa = PBXBuildFile; fileRef = 3284A35020A07C210044F922 /* postMessageAPI.js */; }; @@ -380,6 +386,9 @@ 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = RiotShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 2510A69B4A681C1FEC36E848 /* Pods_RiotPods_Riot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_Riot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 319CD7C67A47A3D35959E18F /* Pods-RiotPods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.release.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.release.xcconfig"; sourceTree = ""; }; + 3223D9BE21B00615000321C1 /* ColorValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorValues.swift; sourceTree = ""; }; + 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultColorValues.swift; sourceTree = ""; }; + 3223D9C221B0065A000321C1 /* DarkColorValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkColorValues.swift; sourceTree = ""; }; 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = ""; }; 3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = ""; }; 3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; @@ -968,6 +977,16 @@ path = RiotShareExtension; sourceTree = ""; }; + 3223D9BD21B00615000321C1 /* Colors */ = { + isa = PBXGroup; + children = ( + 3223D9BE21B00615000321C1 /* ColorValues.swift */, + 3223D9C221B0065A000321C1 /* DarkColorValues.swift */, + 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */, + ); + path = Colors; + sourceTree = ""; + }; 3233F7291F31F3B4006ACA81 /* libs */ = { isa = PBXGroup; children = ( @@ -1142,6 +1161,7 @@ B16932A620F3A6FA00746532 /* Constants */ = { isa = PBXGroup; children = ( + 3223D9BD21B00615000321C1 /* Colors */, B16932AA20F3A7B000746532 /* RiotDesignValues.h */, B16932AB20F3A7B000746532 /* RiotDesignValues.m */, ); @@ -2949,13 +2969,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 3223D9C621B00788000321C1 /* DefaultColorValues.swift in Sources */, B169328420F38BE300746532 /* SegmentedViewController.m in Sources */, + 3223D9C521B00781000321C1 /* DarkColorValues.swift in Sources */, B16932AD20F3A7B100746532 /* RiotDesignValues.m in Sources */, B1664BCA20F4E67600808783 /* ShareViewController.m in Sources */, B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */, 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */, B1664BCF20F4E67600808783 /* ShareExtensionManager.m in Sources */, 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */, + 3223D9C421B0077D000321C1 /* ColorValues.swift in Sources */, B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */, F0A8955F1F7D1FEA00BD6C2A /* MXRoomSummary+Riot.m in Sources */, B169328320F38AE600746532 /* RiotSettings.swift in Sources */, @@ -3081,6 +3104,7 @@ B1B5572620EE6C4D00210D55 /* RoomFilesSearchViewController.m in Sources */, B1B5583120EF66BA00210D55 /* RoomIdOrAliasTableViewCell.m in Sources */, F083BDFA1E7009ED00A9B29C /* RoomPreviewData.m in Sources */, + 3223D9C321B0065A000321C1 /* DarkColorValues.swift in Sources */, B1B557B420EF5AEF00210D55 /* EventDetailsView.m in Sources */, B1B5577E20EE84BF00210D55 /* IncomingCallView.m in Sources */, B1B5578F20EF568D00210D55 /* GroupTableViewCell.m in Sources */, @@ -3106,6 +3130,7 @@ B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, B1B558CF20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B5575120EE6C4D00210D55 /* AuthenticationViewController.m in Sources */, + 3223D9C121B00615000321C1 /* DefaultColorValues.swift in Sources */, B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */, B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */, B1B5575A20EE6C4D00210D55 /* UnifiedSearchViewController.m in Sources */, @@ -3140,6 +3165,7 @@ B1B558EE20EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.m in Sources */, B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, + 3223D9C021B00615000321C1 /* ColorValues.swift in Sources */, B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, diff --git a/Riot/Constants/Colors/ColorValues.swift b/Riot/Constants/Colors/ColorValues.swift new file mode 100644 index 000000000..56e19c16b --- /dev/null +++ b/Riot/Constants/Colors/ColorValues.swift @@ -0,0 +1,57 @@ +/* + Copyright 2018 New Vector 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 UIKit + +/// Provide color constant values defined by the designer +/// https://app.zeplin.io/project/5b857c64b1747a2c472290da/screen/5bf2cc89a4a6973f47883c6e +@objc protocol ColorValues { + + var background: UIColor { get } + var base: UIColor { get } + + var searchBackground: UIColor { get } + var searchText: UIColor { get } + + var headerBackground: UIColor { get } + var headerBorder: UIColor { get } + var headerTextPrimary: UIColor { get } + var headerTextSecondary: UIColor { get } + + var textPrimary: UIColor { get } + var textSecondary: UIColor { get } + + var accent: UIColor { get } + var unreadRoomIndent: UIColor { get } + + var notificationUnread: UIColor { get } + var notificationMention: UIColor { get } + + var avatarColor1: UIColor { get } + var avatarColor2: UIColor { get } + var avatarColor3: UIColor { get } +} + +extension UIColor { + convenience init(rgb: UInt) { + self.init( + red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgb & 0x0000FF) / 255.0, + alpha: CGFloat(1.0) + ) + } +} diff --git a/Riot/Constants/Colors/DarkColorValues.swift b/Riot/Constants/Colors/DarkColorValues.swift new file mode 100644 index 000000000..cae9b7cc6 --- /dev/null +++ b/Riot/Constants/Colors/DarkColorValues.swift @@ -0,0 +1,50 @@ +/* + Copyright 2018 New Vector 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 Foundation +import UIKit + +/// Color constants for the dart theme +@objcMembers +final class DarkColorValues: NSObject, ColorValues { + + static let shared = DarkColorValues() + + let background: UIColor = UIColor(rgb: 0x212224) + + let base: UIColor = UIColor(rgb: 0x292E37) + + let searchBackground: UIColor = UIColor(rgb: 0x3E434B) + let searchText: UIColor = UIColor(rgb: 0xACB3C2) + + let headerBackground: UIColor = UIColor(rgb: 0x303540) + let headerBorder: UIColor = UIColor(rgb: 0x2E2F31) + let headerTextPrimary: UIColor = UIColor(rgb: 0x96A1B7) + let headerTextSecondary: UIColor = UIColor(rgb: 0xC8C8CD) + + let textPrimary: UIColor = UIColor(rgb: 0xFFFFFF) + let textSecondary: UIColor = UIColor(rgb: 0xD8D8D8) + + let accent: UIColor = UIColor(rgb: 0x7AC9A1) + let unreadRoomIndent: UIColor = UIColor(rgb: 0x2E3648) + + let notificationUnread: UIColor = UIColor(rgb: 0x7AC9A1) + let notificationMention: UIColor = UIColor(rgb: 0x3F4147) + + let avatarColor1: UIColor = UIColor(rgb: 0x7AC9A1) + let avatarColor2: UIColor = UIColor(rgb: 0x1E7DDC) + let avatarColor3: UIColor = UIColor(rgb: 0x76DDD7) +} diff --git a/Riot/Constants/Colors/DefaultColorValues.swift b/Riot/Constants/Colors/DefaultColorValues.swift new file mode 100644 index 000000000..2d82bdf65 --- /dev/null +++ b/Riot/Constants/Colors/DefaultColorValues.swift @@ -0,0 +1,50 @@ +/* + Copyright 2018 New Vector 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 Foundation +import UIKit + +/// Color constants for the default theme +@objcMembers +final class DefaultColorValues: NSObject, ColorValues { + + static let shared = DefaultColorValues() + + let background: UIColor = UIColor(rgb: 0xFFFFFF) + + let base: UIColor = UIColor(rgb: 0x2E3648) + + let searchBackground: UIColor = UIColor(rgb: 0xFFFFFF) + let searchText: UIColor = UIColor(rgb: 0xACB3C2) + + let headerBackground: UIColor = UIColor(rgb: 0xF1F5F8) + let headerBorder: UIColor = UIColor(rgb: 0xEAEEF2) + let headerTextPrimary: UIColor = UIColor(rgb: 0x96A1B7) + let headerTextSecondary: UIColor = UIColor(rgb: 0xC8C8CD) + + let textPrimary: UIColor = UIColor(rgb: 0x383838) + let textSecondary: UIColor = UIColor(rgb: 0x9E9E9E) + + let accent: UIColor = UIColor(rgb: 0x7AC9A1) + let unreadRoomIndent: UIColor = UIColor(rgb: 0x2E3648) + + let notificationUnread: UIColor = UIColor(rgb: 0x7AC9A1) + let notificationMention: UIColor = UIColor(rgb: 0xF56679) + + let avatarColor1: UIColor = UIColor(rgb: 0x7AC9A1) + let avatarColor2: UIColor = UIColor(rgb: 0x1E7DDC) + let avatarColor3: UIColor = UIColor(rgb: 0x76DDD7) +} From 5475057f7edb0caf4bf8be6f5761c2acbdd875b5 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 29 Nov 2018 16:05:07 +0100 Subject: [PATCH 002/244] Reskin: Add some missing colors in the design palette --- Riot/Constants/Colors/ColorValues.swift | 3 +++ Riot/Constants/Colors/DarkColorValues.swift | 2 ++ Riot/Constants/Colors/DefaultColorValues.swift | 2 ++ 3 files changed, 7 insertions(+) diff --git a/Riot/Constants/Colors/ColorValues.swift b/Riot/Constants/Colors/ColorValues.swift index 56e19c16b..472e7daa8 100644 --- a/Riot/Constants/Colors/ColorValues.swift +++ b/Riot/Constants/Colors/ColorValues.swift @@ -23,6 +23,9 @@ import UIKit var background: UIColor { get } var base: UIColor { get } + var baseTextPrimary: UIColor { get } + var baseTextSecondary: UIColor { get } + var searchBackground: UIColor { get } var searchText: UIColor { get } diff --git a/Riot/Constants/Colors/DarkColorValues.swift b/Riot/Constants/Colors/DarkColorValues.swift index cae9b7cc6..033e90d50 100644 --- a/Riot/Constants/Colors/DarkColorValues.swift +++ b/Riot/Constants/Colors/DarkColorValues.swift @@ -26,6 +26,8 @@ final class DarkColorValues: NSObject, ColorValues { let background: UIColor = UIColor(rgb: 0x212224) let base: UIColor = UIColor(rgb: 0x292E37) + let baseTextPrimary: UIColor = UIColor(rgb: 0xFFFFFF) + let baseTextSecondary: UIColor = UIColor(rgb: 0xFFFFFF) let searchBackground: UIColor = UIColor(rgb: 0x3E434B) let searchText: UIColor = UIColor(rgb: 0xACB3C2) diff --git a/Riot/Constants/Colors/DefaultColorValues.swift b/Riot/Constants/Colors/DefaultColorValues.swift index 2d82bdf65..2e5361160 100644 --- a/Riot/Constants/Colors/DefaultColorValues.swift +++ b/Riot/Constants/Colors/DefaultColorValues.swift @@ -26,6 +26,8 @@ final class DefaultColorValues: NSObject, ColorValues { let background: UIColor = UIColor(rgb: 0xFFFFFF) let base: UIColor = UIColor(rgb: 0x2E3648) + let baseTextPrimary: UIColor = UIColor(rgb: 0xFFFFFF) + let baseTextSecondary: UIColor = UIColor(rgb: 0xFFFFFF) let searchBackground: UIColor = UIColor(rgb: 0xFFFFFF) let searchText: UIColor = UIColor(rgb: 0xACB3C2) From 145086bd8d7abc92aaa105841eb6150546cabce1 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 29 Nov 2018 16:06:38 +0100 Subject: [PATCH 003/244] Reskin: RiotDesignValues: Make use of the new ColorValues --- Riot/Constants/RiotDesignValues.h | 15 ++- Riot/Constants/RiotDesignValues.m | 101 ++++++++---------- .../DeactivateAccountViewController.m | 2 +- 3 files changed, 56 insertions(+), 62 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 35c4d05c8..213eec44c 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -39,7 +39,7 @@ extern UIColor *kRiotSecondaryTextColor; //subtitle, sending messages color. extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. extern UIColor *kRiotTopicTextColor; extern UIColor *kRiotSelectedBgColor; // nil is used to keep the default color. -extern UIColor *kRiotAuxiliaryColor; // kRiotColorSilver by default. +extern UIColor *kRiotAuxiliaryColor; extern UIColor *kRiotOverlayColor; // fading behind dialog modals. This color includes the transparency value. extern UIColor *kRiotKeyboardColor; @@ -47,7 +47,6 @@ extern UIColor *kRiotKeyboardColor; extern UIColor *kRiotColorGreen; extern UIColor *kRiotColorLightGreen; extern UIColor *kRiotColorLightOrange; -extern UIColor *kRiotColorSilver; extern UIColor *kRiotColorPinkRed; extern UIColor *kRiotColorRed; extern UIColor *kRiotColorIndigo; @@ -60,9 +59,15 @@ extern NSInteger const kRiotRoomModeratorLevel; extern NSInteger const kRiotRoomAdminLevel; #pragma mark - Riot bar style -extern UIStatusBarStyle kRiotDesignStatusBarStyle; -extern UIBarStyle kRiotDesignSearchBarStyle; -extern UIColor *kRiotDesignSearchBarTintColor; +extern UIStatusBarStyle kRiotDesignStatusBarStyle; +extern UIColor *kRiotDesignNavigationBarTintColor; +extern UIColor *kRiotDesignNavigationBarBarTintColor; +extern NSDictionary *kRiotDesignNavigationBarTitleTextAttributes; +extern BOOL kRiotDesignNavigationBarTranslucent; + +extern UIBarStyle kRiotDesignSearchBarStyle; +extern UIColor *kRiotDesignSearchBarTintColor; +extern UIColor *kRiotDesignSearchBarBarTintColor; extern UIKeyboardAppearance kRiotKeyboard; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index a6d4ce672..2e2dfe154 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -41,7 +41,6 @@ UIColor *kRiotKeyboardColor; UIColor *kRiotColorGreen; UIColor *kRiotColorLightGreen; UIColor *kRiotColorLightOrange; -UIColor *kRiotColorSilver; UIColor *kRiotColorPinkRed; UIColor *kRiotColorRed; UIColor *kRiotColorIndigo; @@ -50,27 +49,21 @@ UIColor *kRiotColorBlue; UIColor *kRiotColorCuriousBlue; // Riot Background Colors -UIColor *kRiotBgColorWhite; -UIColor *kRiotBgColorBlack; -UIColor *kRiotBgColorOLEDBlack; -UIColor *kRiotColorLightGrey; -UIColor *kRiotColorLightBlack; -UIColor *kRiotColorLightKeyboard; -UIColor *kRiotColorDarkKeyboard; - -// Riot Text Colors -UIColor *kRiotTextColorBlack; -UIColor *kRiotTextColorDarkGray; -UIColor *kRiotTextColorGray; -UIColor *kRiotTextColorWhite; -UIColor *kRiotTextColorDarkWhite; +UIColor *kRiotColorLightKeyboard; // TO REMOVE +UIColor *kRiotColorDarkKeyboard; // TO REMOVE NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; -UIStatusBarStyle kRiotDesignStatusBarStyle = UIStatusBarStyleDefault; +UIStatusBarStyle kRiotDesignStatusBarStyle = UIStatusBarStyleDefault; +UIColor *kRiotDesignNavigationBarTintColor; +UIColor *kRiotDesignNavigationBarBarTintColor; +NSDictionary *kRiotDesignNavigationBarTitleTextAttributes; +BOOL kRiotDesignNavigationBarTranslucent = YES; + UIBarStyle kRiotDesignSearchBarStyle = UIBarStyleDefault; UIColor *kRiotDesignSearchBarTintColor = nil; +UIColor *kRiotDesignSearchBarBarTintColor = nil; UIKeyboardAppearance kRiotKeyboard; @@ -96,7 +89,6 @@ UIKeyboardAppearance kRiotKeyboard; // Colors as defined by the design kRiotColorGreen = UIColorFromRGB(0x62CE9C); - kRiotColorSilver = UIColorFromRGB(0xC7C7CC); kRiotColorPinkRed = UIColorFromRGB(0xFF0064); kRiotColorRed = UIColorFromRGB(0xFF4444); kRiotColorIndigo = UIColorFromRGB(0xBD79CC); @@ -104,22 +96,9 @@ UIKeyboardAppearance kRiotKeyboard; kRiotColorBlue = UIColorFromRGB(0x81BDDB); kRiotColorCuriousBlue = UIColorFromRGB(0x2A9EDB); - kRiotBgColorWhite = [UIColor whiteColor]; - kRiotBgColorBlack = UIColorFromRGB(0x2D2D2D); - kRiotBgColorOLEDBlack = [UIColor blackColor]; - - kRiotColorLightGrey = UIColorFromRGB(0xF2F2F2); - kRiotColorLightBlack = UIColorFromRGB(0x353535); - kRiotColorLightKeyboard = UIColorFromRGB(0xE7E7E7); kRiotColorDarkKeyboard = UIColorFromRGB(0x7E7E7E); - kRiotTextColorBlack = UIColorFromRGB(0x3C3C3C); - kRiotTextColorDarkGray = UIColorFromRGB(0x4A4A4A); - kRiotTextColorGray = UIColorFromRGB(0x9D9D9D); - kRiotTextColorWhite = UIColorFromRGB(0xDDDDDD); - kRiotTextColorDarkWhite = UIColorFromRGB(0xD9D9D9); - // Colors copied from Vector web kRiotColorLightGreen = UIColorFromRGB(0x50e2c2); kRiotColorLightOrange = UIColorFromRGB(0xf4c371); @@ -159,23 +138,21 @@ UIKeyboardAppearance kRiotKeyboard; { theme = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; } + + + id colorValues; if ([theme isEqualToString:@"dark"]) { // Set dark theme colors - kRiotPrimaryBgColor = kRiotBgColorBlack; - kRiotSecondaryBgColor = kRiotColorLightBlack; - kRiotPrimaryTextColor = kRiotTextColorWhite; - kRiotSecondaryTextColor = kRiotTextColorGray; + colorValues = DarkColorValues.shared; + kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; - kRiotTopicTextColor = kRiotTextColorDarkWhite; kRiotSelectedBgColor = [UIColor blackColor]; kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; kRiotDesignSearchBarStyle = UIBarStyleBlack; - kRiotDesignSearchBarTintColor = kRiotColorGreen; - - kRiotAuxiliaryColor = kRiotTextColorGray; + kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; kRiotKeyboardColor = kRiotColorDarkKeyboard; @@ -184,20 +161,16 @@ UIKeyboardAppearance kRiotKeyboard; } else if ([theme isEqualToString:@"black"]) { + // TODO: Use dark theme colors for the moment + colorValues = DarkColorValues.shared; + // Set black theme colors - kRiotPrimaryBgColor = kRiotBgColorOLEDBlack; - kRiotSecondaryBgColor = kRiotColorLightBlack; - kRiotPrimaryTextColor = kRiotTextColorWhite; - kRiotSecondaryTextColor = kRiotTextColorGray; kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; - kRiotTopicTextColor = kRiotTextColorDarkWhite; kRiotSelectedBgColor = [UIColor blackColor]; kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; kRiotDesignSearchBarStyle = UIBarStyleBlack; - kRiotDesignSearchBarTintColor = kRiotColorGreen; - - kRiotAuxiliaryColor = kRiotTextColorGray; + kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; kRiotKeyboardColor = kRiotColorDarkKeyboard; @@ -207,26 +180,42 @@ UIKeyboardAppearance kRiotKeyboard; else { // Set light theme colors by default. - kRiotPrimaryBgColor = kRiotBgColorWhite; - kRiotSecondaryBgColor = kRiotColorLightGrey; - kRiotPrimaryTextColor = kRiotTextColorBlack; - kRiotSecondaryTextColor = kRiotTextColorGray; + colorValues = DefaultColorValues.shared; + kRiotPlaceholderTextColor = nil; // Use default 70% gray color. - kRiotTopicTextColor = kRiotTextColorDarkGray; kRiotSelectedBgColor = nil; // Use the default selection color. - kRiotDesignStatusBarStyle = UIStatusBarStyleDefault; - kRiotDesignSearchBarStyle = UIBarStyleDefault; - kRiotDesignSearchBarTintColor = nil; // Default tint color. + kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; + kRiotDesignNavigationBarTranslucent = NO; - kRiotAuxiliaryColor = kRiotColorSilver; + kRiotDesignSearchBarStyle = UIBarStyleDefault; + kRiotOverlayColor = [UIColor colorWithWhite:0.7 alpha:0.5]; kRiotKeyboardColor = kRiotColorLightKeyboard; [UITextField appearance].keyboardAppearance = UIKeyboardAppearanceLight; kRiotKeyboard = UIKeyboardAppearanceLight; } - + + // Apply theme color constants + kRiotPrimaryBgColor = colorValues.background; + kRiotSecondaryBgColor = colorValues.headerBackground; + kRiotPrimaryTextColor = colorValues.textPrimary; + kRiotSecondaryTextColor = colorValues.textSecondary; + + kRiotDesignNavigationBarBarTintColor = colorValues.base; + kRiotDesignNavigationBarTintColor = colorValues.baseTextPrimary; + kRiotDesignNavigationBarTitleTextAttributes = @{ + NSForegroundColorAttributeName: colorValues.baseTextPrimary + }; + + kRiotDesignSearchBarBarTintColor = colorValues.headerBackground; + kRiotDesignSearchBarTintColor = colorValues.searchText; + + kRiotTopicTextColor = colorValues.baseTextSecondary; + kRiotAuxiliaryColor = colorValues.headerTextSecondary; + + [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; } diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index dfbd4f8ca..7688c58df 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -167,7 +167,7 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.layer.masksToBounds = YES; self.deactivateAcccountButton.backgroundColor = kRiotColorGreen; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; - [self.deactivateAcccountButton setTitleColor:kRiotColorSilver forState:UIControlStateDisabled]; + [self.deactivateAcccountButton setTitleColor:kRiotAuxiliaryColor forState:UIControlStateDisabled]; } - (void)setupDeactivateAccountInfosLabel From 00e19fe259e93047cd09458fa858471f11a07566 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 29 Nov 2018 17:31:41 +0100 Subject: [PATCH 004/244] Reskin: Use the new [RiotDesignValues applyStyleOnNavigationBar:] method everywhere Note that we do not change anymore the bar tint color when changing tabs. This is alwasy the same. --- Riot/Constants/RiotDesignValues.h | 11 ++++++ Riot/Constants/RiotDesignValues.m | 8 +++++ .../AuthenticationViewController.m | 9 +++-- .../Authentication/Views/AuthInputsView.m | 13 +------ .../BugReport/BugReportViewController.m | 4 +-- Riot/Modules/Call/CallViewController.m | 18 +++------- .../Common/Recents/RecentsViewController.m | 5 +-- .../SegmentedViewController.m | 4 +-- .../WebViewController/WebViewViewController.m | 5 ++- .../Communities/GroupsViewController.m | 13 ++----- .../Home/GroupHomeViewController.m | 4 +-- .../Members/GroupParticipantsViewController.m | 4 +-- .../Rooms/GroupRoomsViewController.m | 4 +-- .../TabDetail/GroupDetailsViewController.m | 36 ------------------- .../Contacts/ContactsTableViewController.m | 4 +-- .../Details/ContactDetailsViewController.m | 4 +-- .../Favorites/FavouritesViewController.m | 13 ------- .../Files/HomeFilesSearchViewController.m | 4 +-- .../HomeMessagesSearchViewController.m | 4 +-- .../Rooms/DirectoryViewController.m | 4 +-- Riot/Modules/Home/HomeViewController.m | 4 ++- .../Library/MediaAlbumContentViewController.m | 4 +-- .../MediaPicker/MediaPickerViewController.m | 4 +-- Riot/Modules/People/PeopleViewController.m | 14 -------- .../Attachements/AttachmentsViewController.m | 6 ++-- .../Room/Files/RoomFilesViewController.m | 4 +-- .../Detail/RoomMemberDetailsViewController.m | 4 +-- .../Members/RoomParticipantsViewController.m | 4 +-- .../ReadReceiptsViewController.m | 4 +-- Riot/Modules/Room/RoomViewController.m | 4 +-- .../Files/RoomFilesSearchViewController.m | 4 +-- .../RoomMessagesSearchViewController.m | 4 +-- .../Settings/RoomSettingsViewController.m | 4 +-- .../DirectoryServerPickerViewController.m | 4 +-- .../DeactivateAccountViewController.m | 4 +-- .../Language/LanguagePickerViewController.m | 4 +-- .../CountryPickerViewController.m | 4 +-- .../Modules/Settings/SettingsViewController.m | 4 +-- Riot/Modules/TabBar/MasterTabBarController.m | 2 ++ .../UserDevices/UsersDevicesViewController.m | 4 +-- 40 files changed, 94 insertions(+), 167 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 213eec44c..fbfc4b6b2 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -17,6 +17,8 @@ #import +NS_ASSUME_NONNULL_BEGIN + /** Posted when the user interface theme has been changed. */ @@ -76,4 +78,13 @@ extern UIKeyboardAppearance kRiotKeyboard; */ @interface RiotDesignValues : NSObject +/** + Apply the current style on a navigation bar. + + @param navigationBar the navigation bar to customise. + */ ++ (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar; + @end + +NS_ASSUME_NONNULL_END diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 2e2dfe154..9ac01e009 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -219,4 +219,12 @@ UIKeyboardAppearance kRiotKeyboard; [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; } ++ (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar +{ + navigationBar.tintColor = kRiotDesignNavigationBarTintColor; + navigationBar.titleTextAttributes = kRiotDesignNavigationBarTitleTextAttributes; + navigationBar.barTintColor = kRiotDesignNavigationBarBarTintColor; + navigationBar.translucent = kRiotDesignNavigationBarTranslucent; +} + @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index eb8c29a81..cbbfee5bd 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -130,9 +130,10 @@ - (void)userInterfaceThemeDidChange { + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.view.backgroundColor = kRiotSecondaryBgColor; - - self.navigationBar.barTintColor = kRiotSecondaryBgColor; + self.authenticationScrollView.backgroundColor = kRiotPrimaryBgColor; self.authFallbackContentView.backgroundColor = kRiotPrimaryBgColor; @@ -173,9 +174,7 @@ self.identityServerTextField.textColor = kRiotPrimaryTextColor; self.identityServerLabel.textColor = kRiotSecondaryTextColor; - - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + self.activityIndicator.backgroundColor = kRiotOverlayColor; [self.authInputsView customizeViewRendering]; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 0cf9f87a7..908062c9a 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -1139,18 +1139,7 @@ phoneNumberPickerNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - phoneNumberPickerNavigationController.navigationBar.barTintColor = kRiotPrimaryBgColor; - NSDictionary *titleTextAttributes = phoneNumberPickerNavigationController.navigationBar.titleTextAttributes; - if (titleTextAttributes) - { - NSMutableDictionary *textAttributes = [NSMutableDictionary dictionaryWithDictionary:titleTextAttributes]; - textAttributes[NSForegroundColorAttributeName] = kRiotPrimaryTextColor; - phoneNumberPickerNavigationController.navigationBar.titleTextAttributes = textAttributes; - } - else if (kRiotPrimaryTextColor) - { - phoneNumberPickerNavigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: kRiotPrimaryTextColor}; - } + [RiotDesignValues applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; [phoneNumberPickerNavigationController pushViewController:phoneNumberCountryPicker animated:NO]; diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 689d2cb73..09890a4d9 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -137,8 +137,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.overlayView.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index b88a3e32b..e8af90b4a 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -97,8 +97,8 @@ - (void)userInterfaceThemeDidChange { - self.view.backgroundColor = kRiotPrimaryBgColor; - self.defaultBarTintColor = kRiotSecondaryBgColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.barTitleColor = kRiotPrimaryTextColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; @@ -282,19 +282,9 @@ UINavigationController *usersDevicesNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors + [RiotDesignValues applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; usersDevicesNavigationController.navigationBar.barTintColor = kRiotPrimaryBgColor; - NSDictionary *titleTextAttributes = usersDevicesNavigationController.navigationBar.titleTextAttributes; - if (titleTextAttributes) - { - NSMutableDictionary *textAttributes = [NSMutableDictionary dictionaryWithDictionary:titleTextAttributes]; - textAttributes[NSForegroundColorAttributeName] = kRiotPrimaryTextColor; - usersDevicesNavigationController.navigationBar.titleTextAttributes = textAttributes; - } - else if (kRiotPrimaryTextColor) - { - usersDevicesNavigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: kRiotPrimaryTextColor}; - } - + [usersDevicesNavigationController pushViewController:usersDevicesViewController animated:NO]; [self presentViewController:usersDevicesNavigationController animated:YES completion:nil]; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index f0f54f16a..0c1b23bc3 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -158,8 +158,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Use the primary bg color for the recents table view in plain style. @@ -169,6 +169,7 @@ tableSearchBar.barStyle = self.recentsSearchBar.barStyle = kRiotDesignSearchBarStyle; tableSearchBar.tintColor = self.recentsSearchBar.tintColor = kRiotDesignSearchBarTintColor; + tableSearchBar.barTintColor = self.recentsSearchBar.barTintColor = kRiotDesignSearchBarBarTintColor; if (self.recentsTableView.dataSource) { diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index c4d5d4d12..53bce17b3 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -172,8 +172,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.view.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index 67c5e69e5..446bc19ff 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -51,9 +51,8 @@ - (void)userInterfaceThemeDidChange { - self.view.backgroundColor = kRiotPrimaryBgColor; - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; webView.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 04d1209a6..86fdf7a0e 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -115,8 +115,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Use the primary bg color for the recents table view in plain style. @@ -203,8 +203,6 @@ }]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_groups", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorBlue; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorBlue; } - (void)viewWillDisappear:(BOOL)animated @@ -219,13 +217,6 @@ [[NSNotificationCenter defaultCenter] removeObserver:kAppDelegateDidTapStatusBarNotificationObserver]; kAppDelegateDidTapStatusBarNotificationObserver = nil; } - - if ([AppDelegate theDelegate].masterTabBarController.tabBar.tintColor == kRiotColorBlue && ![AppDelegate theDelegate].masterTabBarController.selectedGroup) - { - // Restore default tintColor - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorGreen; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorGreen; - } } - (void)viewDidAppear:(BOOL)animated diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 247b49521..f37f2d457 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -112,8 +112,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.view.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index ef7ba2360..269e3f6a6 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -144,8 +144,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; [self refreshSearchBarItemsColor:_searchBarView]; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index dfaaf1243..465be0516 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -125,8 +125,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; [self refreshSearchBarItemsColor:_searchBarView]; diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m index 08bf19492..45f24d431 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m @@ -143,42 +143,6 @@ [super viewWillDisappear:animated]; } -- (void)viewDidLayoutSubviews -{ - [super viewDidLayoutSubviews]; - - // Customize the navigation bar tint color - self.navigationController.navigationBar.tintColor = kRiotColorBlue; - - // Consider the case where the view controller is embedded inside a collapsed split view controller. - if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) - { - UINavigationController *mainNavigationController = self.splitViewController.viewControllers.firstObject; - mainNavigationController.navigationBar.tintColor = kRiotColorBlue; - } -} - -- (void)destroy -{ - // Restore the default tintColor of the main navigation controller. - if (self.navigationController.navigationBar.tintColor == kRiotColorBlue) - { - self.navigationController.navigationBar.tintColor = kRiotColorGreen; - } - - // Check whether the current view controller is embedded inside a collapsed split view controller. - if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) - { - UINavigationController *mainNavigationController = self.splitViewController.viewControllers.firstObject; - if (mainNavigationController.navigationBar.tintColor == kRiotColorBlue) - { - mainNavigationController.navigationBar.tintColor = kRiotColorGreen; - } - } - - [super destroy]; -} - - (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession { _group = group; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index c5f199fd5..a03a99932 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -103,8 +103,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 3c40ccb57..4d02b2a9b 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -230,8 +230,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.headerView.backgroundColor = kRiotSecondaryBgColor; diff --git a/Riot/Modules/Favorites/FavouritesViewController.m b/Riot/Modules/Favorites/FavouritesViewController.m index a5352cb8a..5edd70483 100644 --- a/Riot/Modules/Favorites/FavouritesViewController.m +++ b/Riot/Modules/Favorites/FavouritesViewController.m @@ -55,8 +55,6 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_favourites", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorIndigo; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorIndigo; if (recentsDataSource) { @@ -66,17 +64,6 @@ } } -- (void)viewWillDisappear:(BOOL)animated -{ - [super viewWillDisappear:animated]; - - if ([AppDelegate theDelegate].masterTabBarController.tabBar.tintColor == kRiotColorIndigo) - { - // Restore default tintColor - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorGreen; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorGreen; - } -} - (void)dealloc { diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 6cf51a715..01c7fa0bb 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -70,8 +70,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index d239acbc6..4c866d55b 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -77,8 +77,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index 90bb1bfd5..1f0a74083 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -70,8 +70,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 8c261b545..0834959a0 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -80,7 +80,9 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_home", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorGreen; + + [RiotDesignValues applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorGreen; if (recentsDataSource) diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index 4ed3f011f..de547b17c 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -111,9 +111,9 @@ - (void)userInterfaceThemeDidChange { + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.assetsCollectionView.backgroundColor = kRiotPrimaryBgColor; - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; } diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index f0f30b847..6cc167150 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -181,8 +181,8 @@ static void *RecordingContext = &RecordingContext; - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.cameraVideoCaptureProgressView.progressColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/People/PeopleViewController.m b/Riot/Modules/People/PeopleViewController.m index f2fb57b10..f6f3a09d9 100644 --- a/Riot/Modules/People/PeopleViewController.m +++ b/Riot/Modules/People/PeopleViewController.m @@ -108,8 +108,6 @@ } [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_people", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorOrange; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorOrange; if (recentsDataSource) { @@ -119,18 +117,6 @@ } } -- (void)viewWillDisappear:(BOOL)animated -{ - [super viewWillDisappear:animated]; - - if ([AppDelegate theDelegate].masterTabBarController.tabBar.tintColor == kRiotColorOrange) - { - // Restore default tintColor - [AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar.tintColor = kRiotColorGreen; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorGreen; - } -} - #pragma mark - - (void)displayList:(MXKRecentsDataSource *)listDataSource diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 72f2dd5b0..28a255cdf 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -58,13 +58,11 @@ - (void)userInterfaceThemeDidChange { + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.view.backgroundColor = kRiotPrimaryBgColor; - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.navigationBar.tintColor = kRiotSecondaryBgColor; - self.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName: kRiotPrimaryTextColor}; self.backButton.tintColor = kRiotColorGreen; } diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 53319ec57..143c032d2 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -109,8 +109,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 5b88317b3..ec2db69ed 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -217,8 +217,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.memberHeaderView.backgroundColor = kRiotSecondaryBgColor; diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 3a3fefa6a..4afe79ee7 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -156,8 +156,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; [self refreshSearchBarItemsColor:_searchBarView]; diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 09ffafd0c..10dc58161 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -93,8 +93,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.overlayView.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index fea0b3ca0..3babbddf9 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -418,8 +418,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Prepare jump to last unread banner diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index a710dc8cb..582e4dd97 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -71,8 +71,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index f152865d4..4f3f3af11 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -72,8 +72,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index d76cd73ef..e50287c28 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -265,8 +265,8 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index a7450b622..ecb97c2b5 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -119,8 +119,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 7688c58df..051d4dc33 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -122,8 +122,8 @@ static CGFloat const kTextFontSize = 15.0; - (void)userInterfaceThemeDidChange { - self.view.backgroundColor = kRiotPrimaryBgColor; - self.defaultBarTintColor = kRiotSecondaryBgColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; } diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index ef3ac56d8..f42289a2f 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -68,8 +68,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.searchBar.barStyle = kRiotDesignSearchBarStyle; diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 1c0a2fa40..a4fec5670 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -71,8 +71,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; self.searchBar.barStyle = kRiotDesignSearchBarStyle; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 04acf5dc6..96ce50c34 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -334,8 +334,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 1190e2ee6..6434c6664 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -114,6 +114,8 @@ - (void)userInterfaceThemeDidChange { + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.tabBar.tintColor = kRiotColorGreen; self.tabBar.barTintColor = kRiotSecondaryBgColor; diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index b2847f6ac..70692e8a3 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -81,8 +81,8 @@ - (void)userInterfaceThemeDidChange { - self.defaultBarTintColor = kRiotSecondaryBgColor; - self.barTitleColor = kRiotPrimaryTextColor; + [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. From 42b089c4982f21ea0cc7baa2367e3c3d7d957916 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 29 Nov 2018 17:47:42 +0100 Subject: [PATCH 005/244] Reskin: Factorise *RoomTitleViews and apply them kRiotDesignNavigationBarBarTintColor as background color to mimic the nav bar color --- .../Title/Expanded/ExpandedRoomTitleView.m | 12 --------- .../Title/Preview/PreviewRoomTitleView.m | 21 +++------------- Riot/Modules/Room/Views/Title/RoomTitleView.m | 8 +++--- .../Views/Title/Simple/SimpleRoomTitleView.m | 25 ------------------- 4 files changed, 9 insertions(+), 57 deletions(-) diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index f8ef4bc72..c72ff7e19 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -38,7 +38,6 @@ { [super customizeViewRendering]; - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? kRiotPrimaryTextColor : kRiotSecondaryTextColor); self.roomTopic.textColor = kRiotTopicTextColor; self.roomMembers.textColor = kRiotColorGreen; } @@ -51,17 +50,6 @@ { [self.mxRoom.summary setRoomAvatarImageIn:self.roomAvatar]; - self.displayNameTextField.text = self.mxRoom.summary.displayname; - if (!self.displayNameTextField.text.length) - { - self.displayNameTextField.text = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; - self.displayNameTextField.textColor = kRiotSecondaryTextColor; - } - else - { - self.displayNameTextField.textColor = kRiotPrimaryTextColor; - } - self.roomTopic.text = [MXTools stripNewlineCharacters:self.mxRoom.summary.topic]; // Compute active members count diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index d1c155736..ac1f7e5c7 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -61,11 +61,10 @@ -(void)customizeViewRendering { [super customizeViewRendering]; - - self.backgroundColor = kRiotPrimaryBgColor; - self.mainHeaderBackground.backgroundColor = kRiotSecondaryBgColor; - - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? kRiotPrimaryTextColor : kRiotSecondaryTextColor); + + // Use same color as navigation bar + self.mainHeaderBackground.backgroundColor = kRiotDesignNavigationBarBarTintColor; + self.roomTopic.textColor = kRiotTopicTextColor; @@ -173,18 +172,6 @@ { [self.mxRoom.summary setRoomAvatarImageIn:self.roomAvatar]; - // The user is here invited to join a room (This invitation has been received from server sync) - self.displayNameTextField.text = self.mxRoom.summary.displayname; - if (!self.displayNameTextField.text.length) - { - self.displayNameTextField.text = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; - self.displayNameTextField.textColor = kRiotSecondaryTextColor; - } - else - { - self.displayNameTextField.textColor = kRiotPrimaryTextColor; - } - // Display room topic self.roomTopic.text = [MXTools stripNewlineCharacters:self.mxRoom.summary.topic]; diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index ba8bfc421..a766629a5 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -132,8 +132,10 @@ -(void)customizeViewRendering { [super customizeViewRendering]; - - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? kRiotPrimaryTextColor : kRiotSecondaryTextColor); + + // Use same color as navigation bar + self.backgroundColor = kRiotDesignNavigationBarBarTintColor; + self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? kRiotDesignNavigationBarTintColor : kRiotSecondaryTextColor); } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -162,7 +164,7 @@ } else { - self.displayNameTextField.textColor = kRiotPrimaryTextColor; + self.displayNameTextField.textColor = kRiotDesignNavigationBarTintColor; } } } diff --git a/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m b/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m index bffc71c54..c6446edd3 100644 --- a/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m @@ -87,30 +87,5 @@ } } --(void)customizeViewRendering -{ - [super customizeViewRendering]; - - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? kRiotPrimaryTextColor : kRiotSecondaryTextColor); -} - -- (void)refreshDisplay -{ - [super refreshDisplay]; - - if (self.mxRoom) - { - self.displayNameTextField.text = self.mxRoom.summary.displayname; - if (!self.displayNameTextField.text.length) - { - self.displayNameTextField.text = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; - self.displayNameTextField.textColor = kRiotSecondaryTextColor; - } - else - { - self.displayNameTextField.textColor = kRiotPrimaryTextColor; - } - } -} @end From 21745aa5baa817e4f0f3d4cf17eb2ee043bb54e6 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 30 Nov 2018 15:26:41 +0100 Subject: [PATCH 006/244] Reskin: RiotDesignValues: Expose the current style color constants. --- Riot/Constants/RiotDesignValues.h | 7 +++++ Riot/Constants/RiotDesignValues.m | 43 ++++++++++++++++++++++++------- 2 files changed, 40 insertions(+), 10 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index fbfc4b6b2..84f2522f9 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -17,6 +17,8 @@ #import +@protocol ColorValues; + NS_ASSUME_NONNULL_BEGIN /** @@ -78,6 +80,11 @@ extern UIKeyboardAppearance kRiotKeyboard; */ @interface RiotDesignValues : NSObject +/** + The current style color constants. + */ ++ (id)colorValues; + /** Apply the current style on a navigation bar. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 9ac01e009..96a45d789 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -139,14 +139,9 @@ UIKeyboardAppearance kRiotKeyboard; theme = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; } - - id colorValues; - if ([theme isEqualToString:@"dark"]) { // Set dark theme colors - colorValues = DarkColorValues.shared; - kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; kRiotSelectedBgColor = [UIColor blackColor]; @@ -161,9 +156,6 @@ UIKeyboardAppearance kRiotKeyboard; } else if ([theme isEqualToString:@"black"]) { - // TODO: Use dark theme colors for the moment - colorValues = DarkColorValues.shared; - // Set black theme colors kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; kRiotSelectedBgColor = [UIColor blackColor]; @@ -180,8 +172,6 @@ UIKeyboardAppearance kRiotKeyboard; else { // Set light theme colors by default. - colorValues = DefaultColorValues.shared; - kRiotPlaceholderTextColor = nil; // Use default 70% gray color. kRiotSelectedBgColor = nil; // Use the default selection color. @@ -198,6 +188,8 @@ UIKeyboardAppearance kRiotKeyboard; } // Apply theme color constants + id colorValues = [RiotDesignValues colorValues]; + kRiotPrimaryBgColor = colorValues.background; kRiotSecondaryBgColor = colorValues.headerBackground; kRiotPrimaryTextColor = colorValues.textPrimary; @@ -219,6 +211,37 @@ UIKeyboardAppearance kRiotKeyboard; [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; } ++ (id)colorValues +{ + id colorValues; + + // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). + NSString *theme = RiotSettings.shared.userInterfaceTheme; + + if (!theme || [theme isEqualToString:@"auto"]) + { + theme = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; + } + + if ([theme isEqualToString:@"dark"]) + { + // Set dark theme colors + colorValues = DarkColorValues.shared; + } + else if ([theme isEqualToString:@"black"]) + { + // TODO: Use dark theme colors for the moment + colorValues = DarkColorValues.shared; + } + else + { + // Set light theme colors by default. + colorValues = DefaultColorValues.shared; + } + + return colorValues; +} + + (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar { navigationBar.tintColor = kRiotDesignNavigationBarTintColor; From d6d64ff43d567c014ae149ec34c5eda76f4cf22c Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 30 Nov 2018 15:27:13 +0100 Subject: [PATCH 007/244] Reskin: Use current style color constants for section headers --- .../Modules/Common/Recents/DataSources/RecentsDataSource.m | 6 +++--- Riot/Modules/Communities/GroupsViewController.m | 5 +++-- Riot/Modules/Contacts/DataSources/ContactsDataSource.m | 7 ++++--- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 03d6c7e0b..8eecdab3f 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -415,10 +415,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : kRiotAuxiliaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondary, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -426,7 +426,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 86fdf7a0e..d9a5bb0d9 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -20,6 +20,7 @@ #import "GroupInviteTableViewCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface GroupsViewController () { @@ -460,9 +461,9 @@ { NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName: kRiotPrimaryTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextPrimary}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName: kRiotAuxiliaryColor}]]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextSecondary}]]; sectionHeader.mxkLabel.attributedText = mutableSectionTitle; } diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index b0ac22827..3289a3f09 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -18,6 +18,7 @@ #import "ContactTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #define CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE 0x01 #define CONTACTSDATASOURCE_USERDIRECTORY_BITWISE 0x02 @@ -741,10 +742,10 @@ NSString *roomCount = [NSString stringWithFormat:roomCountFormat, count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : kRiotAuxiliaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondary, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -752,7 +753,7 @@ else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } From 56cd67857c50de82c8023596883f610750665f3f Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 30 Nov 2018 15:56:10 +0100 Subject: [PATCH 008/244] Reskin:Create [RiotDesignValues applyStyleOnSearchBar:] and use it --- Riot/Categories/UIViewController+RiotSearch.m | 3 +-- Riot/Constants/RiotDesignValues.h | 7 +++++++ Riot/Constants/RiotDesignValues.m | 9 +++++++++ Riot/Modules/Common/Recents/RecentsViewController.m | 9 ++++----- Riot/Modules/Communities/GroupsViewController.m | 6 +++--- .../Members/GroupParticipantsViewController.m | 3 ++- .../Modules/Communities/Rooms/GroupRoomsViewController.m | 3 ++- .../Room/Members/RoomParticipantsViewController.m | 3 ++- .../Settings/Language/LanguagePickerViewController.m | 3 +-- .../Settings/PhoneCountry/CountryPickerViewController.m | 3 +-- Riot/Modules/StartChat/StartChatViewController.m | 3 ++- 11 files changed, 34 insertions(+), 18 deletions(-) diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index becfd114c..006979c1d 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -94,8 +94,7 @@ self.searchBar.text = @""; // Customize search bar - self.searchBar.barStyle = kRiotDesignSearchBarStyle; - self.searchBar.tintColor = kRiotDesignSearchBarTintColor; + [RiotDesignValues applyStyleOnSearchBar:self.searchBar]; // Remove navigation buttons self.navigationItem.hidesBackButton = YES; diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 84f2522f9..1df300965 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -92,6 +92,13 @@ extern UIKeyboardAppearance kRiotKeyboard; */ + (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar; +/** + Apply the current style on a search bar. + + @param searchBar the search bar to customise. + */ ++ (void)applyStyleOnSearchBar:(UISearchBar *)searchBar; + @end NS_ASSUME_NONNULL_END diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 96a45d789..b635f0009 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -250,4 +250,13 @@ UIKeyboardAppearance kRiotKeyboard; navigationBar.translucent = kRiotDesignNavigationBarTranslucent; } ++ (void)applyStyleOnSearchBar:(UISearchBar *)searchBar +{ + searchBar.barStyle = kRiotDesignSearchBarStyle; + searchBar.tintColor = kRiotDesignSearchBarTintColor; + searchBar.barTintColor = kRiotDesignSearchBarBarTintColor; + searchBar.layer.borderWidth = 1; + searchBar.layer.borderColor = RiotDesignValues.colorValues.headerBorder.CGColor; +} + @end diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 0c1b23bc3..fb25ab1d1 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -166,11 +166,10 @@ self.recentsTableView.backgroundColor = kRiotPrimaryBgColor; topview.backgroundColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; - - tableSearchBar.barStyle = self.recentsSearchBar.barStyle = kRiotDesignSearchBarStyle; - tableSearchBar.tintColor = self.recentsSearchBar.tintColor = kRiotDesignSearchBarTintColor; - tableSearchBar.barTintColor = self.recentsSearchBar.barTintColor = kRiotDesignSearchBarBarTintColor; - + + [RiotDesignValues applyStyleOnSearchBar:tableSearchBar]; + [RiotDesignValues applyStyleOnSearchBar:self.recentsSearchBar]; + if (self.recentsTableView.dataSource) { // Force table refresh diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index d9a5bb0d9..a247da74f 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -124,9 +124,9 @@ self.groupsTableView.backgroundColor = kRiotPrimaryBgColor; topview.backgroundColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; - - tableSearchBar.barStyle = self.groupsSearchBar.barStyle = kRiotDesignSearchBarStyle; - tableSearchBar.tintColor = self.groupsSearchBar.tintColor = kRiotDesignSearchBarTintColor; + + [RiotDesignValues applyStyleOnSearchBar:tableSearchBar]; + [RiotDesignValues applyStyleOnSearchBar:self.groupsSearchBar]; if (self.groupsTableView.dataSource) { diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 269e3f6a6..3bc270687 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -17,6 +17,7 @@ #import "GroupParticipantsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "Contact.h" #import "ContactTableViewCell.h" @@ -150,7 +151,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = kRiotAuxiliaryColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 465be0516..33956bf0e 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -17,6 +17,7 @@ #import "GroupRoomsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "GroupRoomTableViewCell.h" @@ -131,7 +132,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = kRiotAuxiliaryColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 4afe79ee7..f05a99897 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -20,6 +20,7 @@ #import "RoomMemberDetailsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "Contact.h" @@ -162,7 +163,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = kRiotAuxiliaryColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index f42289a2f..6361142fd 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -72,8 +72,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.searchBar.barStyle = kRiotDesignSearchBarStyle; - self.searchBar.tintColor = kRiotDesignSearchBarTintColor; + [RiotDesignValues applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. self.tableView.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index a4fec5670..1fb5c59df 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -75,8 +75,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.searchBar.barStyle = kRiotDesignSearchBarStyle; - self.searchBar.tintColor = kRiotDesignSearchBarTintColor; + [RiotDesignValues applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. self.tableView.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index d55a50f60..54c18a313 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -18,6 +18,7 @@ #import "StartChatViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface StartChatViewController () { @@ -148,7 +149,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = kRiotAuxiliaryColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; // Check the table view style to select its bg color. self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); From 477361e47406672db47dea02d9a631eaafd8e100 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 30 Nov 2018 16:17:12 +0100 Subject: [PATCH 009/244] Reskin: New avatar bg colors when no room avatar --- Riot/Constants/Colors/ColorValues.swift | 4 +--- Riot/Constants/Colors/DarkColorValues.swift | 7 ++++--- Riot/Constants/Colors/DefaultColorValues.swift | 7 ++++--- Riot/Constants/RiotDesignValues.h | 4 ---- Riot/Constants/RiotDesignValues.m | 10 ---------- Riot/Utils/AvatarGenerator.m | 11 +++++++---- 6 files changed, 16 insertions(+), 27 deletions(-) diff --git a/Riot/Constants/Colors/ColorValues.swift b/Riot/Constants/Colors/ColorValues.swift index 472e7daa8..09d4fc7f7 100644 --- a/Riot/Constants/Colors/ColorValues.swift +++ b/Riot/Constants/Colors/ColorValues.swift @@ -43,9 +43,7 @@ import UIKit var notificationUnread: UIColor { get } var notificationMention: UIColor { get } - var avatarColor1: UIColor { get } - var avatarColor2: UIColor { get } - var avatarColor3: UIColor { get } + var avatars: [UIColor] { get } } extension UIColor { diff --git a/Riot/Constants/Colors/DarkColorValues.swift b/Riot/Constants/Colors/DarkColorValues.swift index 033e90d50..a2522ea10 100644 --- a/Riot/Constants/Colors/DarkColorValues.swift +++ b/Riot/Constants/Colors/DarkColorValues.swift @@ -46,7 +46,8 @@ final class DarkColorValues: NSObject, ColorValues { let notificationUnread: UIColor = UIColor(rgb: 0x7AC9A1) let notificationMention: UIColor = UIColor(rgb: 0x3F4147) - let avatarColor1: UIColor = UIColor(rgb: 0x7AC9A1) - let avatarColor2: UIColor = UIColor(rgb: 0x1E7DDC) - let avatarColor3: UIColor = UIColor(rgb: 0x76DDD7) + let avatars: [UIColor] = [ + UIColor(rgb: 0x7AC9A1), + UIColor(rgb: 0x1E7DDC), + UIColor(rgb: 0x76DDD7)] } diff --git a/Riot/Constants/Colors/DefaultColorValues.swift b/Riot/Constants/Colors/DefaultColorValues.swift index 2e5361160..ed90ae7b6 100644 --- a/Riot/Constants/Colors/DefaultColorValues.swift +++ b/Riot/Constants/Colors/DefaultColorValues.swift @@ -46,7 +46,8 @@ final class DefaultColorValues: NSObject, ColorValues { let notificationUnread: UIColor = UIColor(rgb: 0x7AC9A1) let notificationMention: UIColor = UIColor(rgb: 0xF56679) - let avatarColor1: UIColor = UIColor(rgb: 0x7AC9A1) - let avatarColor2: UIColor = UIColor(rgb: 0x1E7DDC) - let avatarColor3: UIColor = UIColor(rgb: 0x76DDD7) + let avatars: [UIColor] = [ + UIColor(rgb: 0x7AC9A1), + UIColor(rgb: 0x1E7DDC), + UIColor(rgb: 0x76DDD7)] } diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 1df300965..9cace93c5 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -49,12 +49,8 @@ extern UIColor *kRiotKeyboardColor; #pragma mark - Riot Colors extern UIColor *kRiotColorGreen; -extern UIColor *kRiotColorLightGreen; -extern UIColor *kRiotColorLightOrange; extern UIColor *kRiotColorPinkRed; extern UIColor *kRiotColorRed; -extern UIColor *kRiotColorIndigo; -extern UIColor *kRiotColorOrange; extern UIColor *kRiotColorBlue; extern UIColor *kRiotColorCuriousBlue; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index b635f0009..b75e7ceae 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -39,12 +39,8 @@ UIColor *kRiotKeyboardColor; // Riot Colors UIColor *kRiotColorGreen; -UIColor *kRiotColorLightGreen; -UIColor *kRiotColorLightOrange; UIColor *kRiotColorPinkRed; UIColor *kRiotColorRed; -UIColor *kRiotColorIndigo; -UIColor *kRiotColorOrange; UIColor *kRiotColorBlue; UIColor *kRiotColorCuriousBlue; @@ -91,18 +87,12 @@ UIKeyboardAppearance kRiotKeyboard; kRiotColorGreen = UIColorFromRGB(0x62CE9C); kRiotColorPinkRed = UIColorFromRGB(0xFF0064); kRiotColorRed = UIColorFromRGB(0xFF4444); - kRiotColorIndigo = UIColorFromRGB(0xBD79CC); - kRiotColorOrange = UIColorFromRGB(0xF8A15F); kRiotColorBlue = UIColorFromRGB(0x81BDDB); kRiotColorCuriousBlue = UIColorFromRGB(0x2A9EDB); kRiotColorLightKeyboard = UIColorFromRGB(0xE7E7E7); kRiotColorDarkKeyboard = UIColorFromRGB(0x7E7E7E); - // Colors copied from Vector web - kRiotColorLightGreen = UIColorFromRGB(0x50e2c2); - kRiotColorLightOrange = UIColorFromRGB(0xf4c371); - // Observe user interface theme change. [[NSUserDefaults standardUserDefaults] addObserver:[RiotDesignValues sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil]; [[RiotDesignValues sharedInstance] userInterfaceThemeDidChange]; diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index 3d8bcd1eb..d8fbb18fb 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -19,6 +19,12 @@ #import "RiotDesignValues.h" +#ifdef IS_SHARE_EXTENSION +#import "RiotShareExtension-Swift.h" +#else +#import "Riot-Swift.h" +#endif + @implementation AvatarGenerator static NSMutableDictionary *imageByKeyDict = nil; @@ -33,10 +39,7 @@ static UILabel* backgroundLabel = nil; { if (!colorsList) { - colorsList = [[NSMutableArray alloc] init]; - [colorsList addObject:kRiotColorGreen]; - [colorsList addObject:kRiotColorLightGreen]; - [colorsList addObject:kRiotColorLightOrange]; + colorsList = RiotDesignValues.colorValues.avatars; } } From ba51d3630fc18770d1b0ce23f1e787af35097c45 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 30 Nov 2018 16:36:34 +0100 Subject: [PATCH 010/244] Reskin: Change the 2 notifications colors --- .../Common/Recents/Views/RecentTableViewCell.m | 3 ++- .../Communities/Views/GroupInviteTableViewCell.m | 3 ++- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 5 +++-- .../Modules/People/Views/InviteRecentTableViewCell.m | 3 ++- Riot/Modules/Room/RoomViewController.m | 4 ++-- Riot/Modules/TabBar/MasterTabBarController.m | 12 +++++++++--- Riot/Utils/EventFormatter.m | 3 ++- 7 files changed, 22 insertions(+), 11 deletions(-) diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 48c15da08..3cdd4b5a7 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -22,6 +22,7 @@ #import "MXEvent.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -108,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? kRiotColorPinkRed : kRiotColorGreen; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 351d5f086..adb08767a 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -17,6 +17,7 @@ #import "GroupInviteTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #pragma mark - Constant definitions @@ -57,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = kRiotColorBlue; self.rightButton.backgroundColor = kRiotColorBlue; - self.noticeBadgeView.backgroundColor = kRiotColorPinkRed; + self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMention; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 17519e728..1e1752d04 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -19,6 +19,7 @@ #import "AvatarGenerator.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -125,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? kRiotColorPinkRed : kRiotColorGreen; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -146,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = kRiotColorPinkRed; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.colorValues.notificationMention; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index a942bf7f5..a830d8eca 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -22,6 +22,7 @@ #import "MXEvent.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #pragma mark - Constant definitions @@ -62,7 +63,7 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell self.leftButton.backgroundColor = kRiotColorGreen; self.rightButton.backgroundColor = kRiotColorGreen; - self.noticeBadgeView.backgroundColor = kRiotColorPinkRed; + self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMention; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 3babbddf9..33872fac3 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4219,11 +4219,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = kRiotColorPinkRed; + missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationMention; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = kRiotColorGreen; + missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationUnread; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 6434c6664..6f49d6219 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -796,11 +796,17 @@ - (void)refreshTabBarBadges { // Use a middle dot to signal missed notif in favourites - [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? kRiotColorPinkRed : kRiotColorGreen)]; + [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) + onTabBarItem:TABBAR_FAVOURITES_INDEX + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread)]; // Update the badge on People and Rooms tabs - [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? kRiotColorPinkRed : kRiotColorGreen)]; - [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? kRiotColorPinkRed : kRiotColorGreen)]; + [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount + onTabBarItem:TABBAR_PEOPLE_INDEX + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread)]; + [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount + onTabBarItem:TABBAR_ROOMS_INDEX + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 33cf6d1b3..f161d22da 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -18,6 +18,7 @@ #import "EventFormatter.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "WidgetManager.h" @@ -219,7 +220,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.defaultTextColor = kRiotPrimaryTextColor; self.subTitleTextColor = kRiotSecondaryTextColor; self.prefixTextColor = kRiotSecondaryTextColor; - self.bingTextColor = kRiotColorPinkRed; + self.bingTextColor = RiotDesignValues.colorValues.notificationMention; self.encryptingTextColor = kRiotColorGreen; self.sendingTextColor = kRiotSecondaryTextColor; self.errorTextColor = kRiotColorRed; From 6ad603a6ca62d153ac6bbb1367f61dc4c2659c08 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 30 Nov 2018 17:10:28 +0100 Subject: [PATCH 011/244] Reskin: Kill kRiotColorGreen and use RiotDesignValues.colorValues.accent instead --- Riot/AppDelegate.m | 4 ++-- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m | 3 ++- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 2 -- .../Authentication/AuthenticationViewController.m | 7 ++++--- .../Views/ForgotPasswordInputsView.m | 3 ++- Riot/Modules/BugReport/BugReportViewController.m | 7 ++++--- Riot/Modules/Call/CallViewController.m | 3 ++- Riot/Modules/Call/Views/IncomingCallView.m | 3 ++- .../Common/Recents/Views/RecentTableViewCell.m | 2 +- .../SegmentedViewController.h | 2 +- .../SegmentedViewController.m | 8 +++++++- .../Details/ContactDetailsViewController.m | 3 ++- .../Contacts/Details/Views/RoomTableViewCell.m | 4 +++- .../Modules/Contacts/Views/ContactTableViewCell.m | 5 +++-- Riot/Modules/EncryptionInfo/EncryptionInfoView.m | 9 +++++---- .../DataSources/HomeMessagesSearchDataSource.m | 3 ++- .../MessagesSearchResultAttachmentBubbleCell.m | 3 ++- .../Views/MessagesSearchResultTextMsgBubbleCell.m | 3 ++- Riot/Modules/Home/HomeViewController.m | 3 ++- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 2 +- .../People/Views/InviteRecentTableViewCell.m | 4 ++-- .../Room/Attachements/AttachmentsViewController.m | 3 ++- Riot/Modules/Room/DataSources/RoomDataSource.m | 3 ++- .../Detail/RoomMemberDetailsViewController.m | 3 ++- .../Room/Members/RoomParticipantsViewController.m | 10 +++++----- .../ReadReceiptsViewController.m | 3 ++- .../Search/DataSources/RoomSearchDataSource.m | 3 ++- .../Room/Settings/RoomSettingsViewController.m | 15 ++++++++------- .../RoomIncomingAttachmentBubbleCell.m | 3 ++- ...omingAttachmentWithPaginationTitleBubbleCell.m | 7 ++++--- ...ncomingAttachmentWithoutSenderInfoBubbleCell.m | 3 ++- .../BubbleCells/RoomIncomingTextMsgBubbleCell.m | 3 ++- ...IncomingTextMsgWithPaginationTitleBubbleCell.m | 7 ++++--- ...thPaginationTitleWithoutSenderNameBubbleCell.m | 3 ++- ...omIncomingTextMsgWithoutSenderInfoBubbleCell.m | 3 ++- ...omIncomingTextMsgWithoutSenderNameBubbleCell.m | 3 ++- .../Views/BubbleCells/RoomMembershipBubbleCell.m | 3 ++- .../RoomMembershipCollapsedBubbleCell.m | 3 ++- ...ershipCollapsedWithPaginationTitleBubbleCell.m | 5 +++-- .../RoomMembershipExpandedBubbleCell.m | 3 ++- ...bershipExpandedWithPaginationTitleBubbleCell.m | 5 +++-- .../RoomMembershipWithPaginationTitleBubbleCell.m | 5 +++-- .../RoomOutgoingAttachmentBubbleCell.m | 3 ++- ...goingAttachmentWithPaginationTitleBubbleCell.m | 7 ++++--- ...utgoingAttachmentWithoutSenderInfoBubbleCell.m | 3 ++- .../BubbleCells/RoomOutgoingTextMsgBubbleCell.m | 3 ++- ...OutgoingTextMsgWithPaginationTitleBubbleCell.m | 5 +++-- ...omOutgoingTextMsgWithoutSenderInfoBubbleCell.m | 3 ++- Riot/Modules/Room/Views/Event/EventDetailsView.m | 5 +++-- .../InputToolbar/DisabledRoomInputToolbarView.m | 3 ++- .../Views/InputToolbar/RoomInputToolbarView.m | 7 ++++--- .../Views/Title/Expanded/ExpandedRoomTitleView.m | 3 ++- .../Views/Title/Preview/PreviewRoomTitleView.m | 7 ++++--- .../DeactivateAccountViewController.m | 3 ++- Riot/Modules/Settings/SettingsViewController.m | 14 +++++++------- Riot/Modules/Settings/Views/DeviceView.m | 7 ++++--- Riot/Modules/StartChat/StartChatViewController.m | 10 +++++----- Riot/Modules/TabBar/MasterTabBarController.m | 2 +- .../UserDevices/Views/DeviceTableViewCell.m | 6 ++++-- Riot/Utils/EventFormatter.m | 2 +- .../Share/Listing/RoomsListViewController.m | 8 +++++++- 62 files changed, 170 insertions(+), 111 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 5ffa69a5a..4f8c89b8d 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -422,7 +422,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [NSBundle mxk_setFallbackLanguage:@"en"]; // Define the navigation bar text color - [[UINavigationBar appearance] setTintColor:kRiotColorGreen]; + [[UINavigationBar appearance] setTintColor:RiotDesignValues.colorValues.accent]; // Customize the localized string table [NSBundle mxk_customizeLocalizedStringTableName:@"Vector"]; @@ -3541,7 +3541,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN _callStatusBarButton.titleLabel.font = [UIFont boldSystemFontOfSize:17]; } - [_callStatusBarButton setBackgroundColor:kRiotColorGreen]; + [_callStatusBarButton setBackgroundColor:RiotDesignValues.colorValues.accent]; [_callStatusBarButton addTarget:self action:@selector(onCallStatusBarButtonPressed) forControlEvents:UIControlEventTouchUpInside]; // Place button into the new window diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index dabdb7af2..5e03dd91e 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -20,6 +20,7 @@ #import "RoomBubbleCellData.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import @@ -208,7 +209,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT markPosY, VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH, markHeight)]; - markerView.backgroundColor = kRiotColorGreen; + markerView.backgroundColor = RiotDesignValues.colorValues.accent; [markerView setTranslatesAutoresizingMaskIntoConstraints:NO]; markerView.accessibilityIdentifier = @"markerView"; diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 9cace93c5..f1887a86c 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -48,7 +48,6 @@ extern UIColor *kRiotOverlayColor; // fading behind dialog modals. This color in extern UIColor *kRiotKeyboardColor; #pragma mark - Riot Colors -extern UIColor *kRiotColorGreen; extern UIColor *kRiotColorPinkRed; extern UIColor *kRiotColorRed; extern UIColor *kRiotColorBlue; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index b75e7ceae..5b18e38cf 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -38,7 +38,6 @@ UIColor *kRiotOverlayColor; UIColor *kRiotKeyboardColor; // Riot Colors -UIColor *kRiotColorGreen; UIColor *kRiotColorPinkRed; UIColor *kRiotColorRed; UIColor *kRiotColorBlue; @@ -84,7 +83,6 @@ UIKeyboardAppearance kRiotKeyboard; // Load colors at the app load time for the life of the app // Colors as defined by the design - kRiotColorGreen = UIColorFromRGB(0x62CE9C); kRiotColorPinkRed = UIColorFromRGB(0xFF0064); kRiotColorRed = UIColorFromRGB(0xFF4444); kRiotColorBlue = UIColorFromRGB(0x81BDDB); diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index cbbfee5bd..369f08fa2 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -18,6 +18,7 @@ #import "AuthenticationViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "AuthInputsView.h" #import "ForgotPasswordInputsView.h" @@ -153,14 +154,14 @@ } } - self.submitButton.backgroundColor = kRiotColorGreen; - self.skipButton.backgroundColor = kRiotColorGreen; + self.submitButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.skipButton.backgroundColor = RiotDesignValues.colorValues.accent; self.noFlowLabel.textColor = kRiotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(0, forgotPasswordTitle.length)]; - [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:kRiotColorGreen range:NSMakeRange(0, forgotPasswordTitle.length)]; + [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.colorValues.accent range:NSMakeRange(0, forgotPasswordTitle.length)]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; [self updateForgotPwdButtonVisibility]; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 653598d3a..a57385370 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -19,6 +19,7 @@ #import "MXHTTPOperation.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @interface ForgotPasswordInputsView () @@ -114,7 +115,7 @@ [self.nextStepButton.layer setCornerRadius:5]; self.nextStepButton.clipsToBounds = YES; - self.nextStepButton.backgroundColor = kRiotColorGreen; + self.nextStepButton.backgroundColor = RiotDesignValues.colorValues.accent; if (kRiotPlaceholderTextColor) { diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 09890a4d9..1559dba0e 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -17,6 +17,7 @@ #import "BugReportViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "GBDeviceInfo_iOS.h" @@ -153,13 +154,13 @@ self.sendingLabel.textColor = kRiotPrimaryTextColor; self.descriptionLabel.textColor = kRiotPrimaryTextColor; self.bugReportDescriptionTextView.textColor = kRiotPrimaryTextColor; - self.bugReportDescriptionTextView.tintColor = kRiotColorGreen; + self.bugReportDescriptionTextView.tintColor = RiotDesignValues.colorValues.accent; self.logsDescriptionLabel.textColor = kRiotPrimaryTextColor; self.sendLogsLabel.textColor = kRiotPrimaryTextColor; self.sendScreenshotLabel.textColor = kRiotPrimaryTextColor; - self.sendButton.tintColor = kRiotColorGreen; - self.cancelButton.tintColor = kRiotColorGreen; + self.sendButton.tintColor = RiotDesignValues.colorValues.accent; + self.cancelButton.tintColor = RiotDesignValues.colorValues.accent; _bugReportDescriptionTextView.layer.borderColor = kRiotSecondaryBgColor.CGColor; } diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index e8af90b4a..3138aeea8 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -19,6 +19,7 @@ #import "CallViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "AvatarGenerator.h" @@ -105,7 +106,7 @@ self.callerNameLabel.textColor = kRiotPrimaryTextColor; self.callStatusLabel.textColor = kRiotTopicTextColor; - self.localPreviewContainerView.layer.borderColor = kRiotColorGreen.CGColor; + self.localPreviewContainerView.layer.borderColor = RiotDesignValues.colorValues.accent.CGColor; self.localPreviewContainerView.layer.borderWidth = 2; self.localPreviewContainerView.layer.cornerRadius = 5; self.localPreviewContainerView.clipsToBounds = YES; diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index d956cecce..34696dedb 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -22,6 +22,7 @@ #import "CircleButton.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" static const CGFloat kAvatarSize = 100.0; static const CGFloat kButtonSize = 80.0; @@ -86,7 +87,7 @@ static const CGFloat kButtonSize = 80.0; self.callInfoLabel.text = callInfo; self.callInfoLabel.textAlignment = NSTextAlignmentCenter; - UIColor *answerButtonBorderColor = kRiotColorGreen; + UIColor *answerButtonBorderColor = RiotDesignValues.colorValues.accent; self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"] borderColor:answerButtonBorderColor]; diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 3cdd4b5a7..199357bbe 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -54,7 +54,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.accent.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h index a0a340863..6259922bf 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h @@ -38,7 +38,7 @@ limitations under the License. @property (nonatomic) NSUInteger selectedIndex; /** - The tint color for the section header (kRiotColorGreen by default). + The tint color for the section header (RiotDesignValues.colorValues.accent by default). */ @property (nonatomic) UIColor *sectionHeaderTintColor; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 53bce17b3..8aa3635bd 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -19,6 +19,12 @@ #import "RiotDesignValues.h" +#ifdef IS_SHARE_EXTENSION +#import "RiotShareExtension-Swift.h" +#else +#import "Riot-Swift.h" +#endif + @interface SegmentedViewController () { // Tell whether the segmented view is appeared (see viewWillAppear/viewWillDisappear). @@ -130,7 +136,7 @@ // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; - self.sectionHeaderTintColor = kRiotColorGreen; + self.sectionHeaderTintColor = RiotDesignValues.colorValues.accent; } - (void)viewDidLoad diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 4d02b2a9b..39e5e20a7 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -19,6 +19,7 @@ #import "ContactDetailsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "RoomMemberTitleView.h" @@ -236,7 +237,7 @@ self.headerView.backgroundColor = kRiotSecondaryBgColor; self.contactNameLabel.textColor = kRiotPrimaryTextColor; - self.contactStatusLabel.textColor = kRiotColorGreen; + self.contactStatusLabel.textColor = RiotDesignValues.colorValues.accent; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index 394d2b3e9..13310c1ea 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -18,6 +18,8 @@ #import "RoomTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" + #import "MXRoomSummary+Riot.h" #pragma mark - Defines & Constants @@ -36,7 +38,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.titleLabel.textColor = kRiotPrimaryTextColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.accent.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index 1259162ed..ad33219f9 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -20,6 +20,7 @@ #import #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "AvatarGenerator.h" #import "Tools.h" @@ -222,11 +223,11 @@ } else if ((!contact.isMatrixContact && contact.phoneNumbers.count && !contact.emailAddresses.count)) { - image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:kRiotColorGreen]; + image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:RiotDesignValues.colorValues.accent]; } else { - image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:kRiotColorGreen]; + image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:RiotDesignValues.colorValues.accent]; } } diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index fdc6143c7..c493fe692 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -18,6 +18,7 @@ #import "EncryptionInfoView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation EncryptionInfoView @@ -30,10 +31,10 @@ self.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.defaultTextColor = kRiotPrimaryTextColor; - self.cancelButton.tintColor = kRiotColorGreen; - self.verifyButton.tintColor = kRiotColorGreen; - self.blockButton.tintColor = kRiotColorGreen; - self.confirmVerifyButton.tintColor = kRiotColorGreen; + self.cancelButton.tintColor = RiotDesignValues.colorValues.accent; + self.verifyButton.tintColor = RiotDesignValues.colorValues.accent; + self.blockButton.tintColor = RiotDesignValues.colorValues.accent; + self.confirmVerifyButton.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 83bf82ed4..c3e083f51 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -23,6 +23,7 @@ #import "RoomBubbleCellData.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @@ -65,7 +66,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:kRiotColorGreen andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.accent andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index 1cf9379ea..b6406ef28 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -18,6 +18,7 @@ #import "MessagesSearchResultAttachmentBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation MessagesSearchResultAttachmentBubbleCell @@ -29,7 +30,7 @@ self.roomNameLabel.textColor = kRiotSecondaryTextColor; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index 8359cc26e..42ecdd21b 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -18,6 +18,7 @@ #import "MessagesSearchResultTextMsgBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation MessagesSearchResultTextMsgBubbleCell @@ -29,7 +30,7 @@ self.roomNameLabel.textColor = kRiotSecondaryTextColor; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 0834959a0..f571702ec 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -18,6 +18,7 @@ #import "HomeViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "RecentsDataSource.h" @@ -83,7 +84,7 @@ [RiotDesignValues applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorGreen; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.accent; if (recentsDataSource) { diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 1e1752d04..d7151daf8 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -72,7 +72,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(kRiotColorGreen.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.accent.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index a830d8eca..0f752aac7 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -60,8 +60,8 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell { [super customizeTableViewCellRendering]; - self.leftButton.backgroundColor = kRiotColorGreen; - self.rightButton.backgroundColor = kRiotColorGreen; + self.leftButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.rightButton.backgroundColor = RiotDesignValues.colorValues.accent; self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMention; } diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 28a255cdf..4de12a032 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -18,6 +18,7 @@ #import "AttachmentsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface AttachmentsViewController () { @@ -63,7 +64,7 @@ self.view.backgroundColor = kRiotPrimaryBgColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.backButton.tintColor = kRiotColorGreen; + self.backButton.tintColor = RiotDesignValues.colorValues.accent; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 24a60e6fd..093805a56 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -23,6 +23,7 @@ #import "MXKRoomBubbleTableViewCell+Riot.h" #import "AvatarGenerator.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXRoom+Riot.h" @@ -385,7 +386,7 @@ if ([component.event.eventId isEqualToString:self.room.accountData.readMarkerEventId]) { bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - 2, bubbleCell.bubbleOverlayContainer.frame.size.width, 2)]; - bubbleCell.readMarkerView.backgroundColor = kRiotColorGreen; + bubbleCell.readMarkerView.backgroundColor = RiotDesignValues.colorValues.accent; // Hide by default the marker, it will be shown and animated when the cell will be rendered. bubbleCell.readMarkerView.hidden = YES; bubbleCell.readMarkerView.tag = index; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index ec2db69ed..025b4b4e0 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -19,6 +19,7 @@ #import "RoomMemberDetailsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "RoomMemberTitleView.h" @@ -223,7 +224,7 @@ self.memberHeaderView.backgroundColor = kRiotSecondaryBgColor; self.roomMemberNameLabel.textColor = kRiotPrimaryTextColor; - self.roomMemberStatusLabel.textColor = kRiotColorGreen; + self.roomMemberStatusLabel.textColor = RiotDesignValues.colorValues.accent; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index f05a99897..39ce8a7ac 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -1685,8 +1685,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = kRiotColorGreen; - searchBar.tintColor = kRiotColorGreen; + searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.accent; + searchBar.tintColor = RiotDesignValues.colorValues.accent; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -1697,7 +1697,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = kRiotColorGreen; + leftImageView.tintColor = RiotDesignValues.colorValues.accent; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -1708,8 +1708,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: kRiotColorGreen, - NSForegroundColorAttributeName: kRiotColorGreen}]; + NSUnderlineColorAttributeName: RiotDesignValues.colorValues.accent, + NSForegroundColorAttributeName: RiotDesignValues.colorValues.accent}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 10dc58161..d44282fb3 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -20,6 +20,7 @@ #import "RageShakeManager.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @interface ReadReceiptsViewController () { @@ -106,7 +107,7 @@ // Check the table view style to select its bg color. self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); - self.closeButton.tintColor = kRiotColorGreen; + self.closeButton.tintColor = RiotDesignValues.colorValues.accent; if (self.receiptsTableView.dataSource) { diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 94503a882..9c3177495 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -20,6 +20,7 @@ #import "RoomBubbleCellData.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @@ -68,7 +69,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:kRiotColorGreen andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.accent andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index e50287c28..9d3ff7e13 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -29,6 +29,7 @@ #import "MXRoomSummary+Riot.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "RoomMemberDetailsViewController.h" @@ -2212,7 +2213,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView.text = mxRoomState.topic; } - topicTextView.tintColor = kRiotColorGreen; + topicTextView.tintColor = RiotDesignValues.colorValues.accent; topicTextView.font = [UIFont systemFontOfSize:15]; topicTextView.bounces = NO; topicTextView.delegate = self; @@ -2241,7 +2242,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti nameTextField = roomNameCell.mxkTextField; - nameTextField.tintColor = kRiotColorGreen; + nameTextField.tintColor = RiotDesignValues.colorValues.accent; nameTextField.font = [UIFont systemFontOfSize:17]; nameTextField.borderStyle = UITextBorderStyleNone; nameTextField.textAlignment = NSTextAlignmentRight; @@ -2319,7 +2320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [leaveCell.mxkButton setTitle:title forState:UIControlStateNormal]; [leaveCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [leaveCell.mxkButton setTintColor:kRiotColorGreen]; + [leaveCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; leaveCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [leaveCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2508,7 +2509,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressTextField.text = currentValue; addAddressTextField.textColor = kRiotSecondaryTextColor; - addAddressTextField.tintColor = kRiotColorGreen; + addAddressTextField.tintColor = RiotDesignValues.colorValues.accent; addAddressTextField.font = [UIFont systemFontOfSize:17]; addAddressTextField.borderStyle = UITextBorderStyleNone; addAddressTextField.textAlignment = NSTextAlignmentLeft; @@ -2599,7 +2600,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addGroupTextField.text = currentValue; addGroupTextField.textColor = kRiotSecondaryTextColor; - addGroupTextField.tintColor = kRiotColorGreen; + addGroupTextField.tintColor = RiotDesignValues.colorValues.accent; addGroupTextField.font = [UIFont systemFontOfSize:17]; addGroupTextField.borderStyle = UITextBorderStyleNone; addGroupTextField.textAlignment = NSTextAlignmentLeft; @@ -2671,7 +2672,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti MXKTableViewCellWithLabelAndSwitch *roomBlacklistUnverifiedDevicesCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; [roomBlacklistUnverifiedDevicesCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevice:) forControlEvents:UIControlEventValueChanged]; - roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = kRiotColorGreen; + roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; roomBlacklistUnverifiedDevicesCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_blacklist_unverified_devices", @"Vector", nil); @@ -2802,7 +2803,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.mxkLabel.textColor = kRiotPrimaryTextColor; - cell.mxkSwitch.onTintColor = kRiotColorGreen; + cell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged]; // Reset the stored `directoryVisibilitySwitch` if the corresponding cell is reused. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index f390f2146..8cad6d47e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingAttachmentBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingAttachmentBubbleCell @@ -26,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index d405bf245..09e0fed2c 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingAttachmentWithPaginationTitleBubbleCell @@ -27,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; - self.messageTextView.tintColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m index d3e984383..839f52114 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingAttachmentWithoutSenderInfoBubbleCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index 0a09a63ca..48751e1a6 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingTextMsgBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingTextMsgBubbleCell @@ -26,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index 6f85dded9..272a75b40 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithPaginationTitleBubbleCell @@ -27,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; - self.messageTextView.tintColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index 02085a8b0..816e9cce8 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m index 7a2544891..ed8f43876 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithoutSenderInfoBubbleCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m index 2be960f3d..a6a280204 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithoutSenderNameBubbleCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m index 5073402c3..a10e24b86 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m @@ -17,6 +17,7 @@ #import "RoomMembershipBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -40,7 +41,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)prepareForReuse diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m index 0c6bd06e4..364dadbe6 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomMembershipCollapsedBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -29,7 +30,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m index bf9c0c1ff..5dfa22cec 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m @@ -17,6 +17,7 @@ #import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -26,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index 7803ec5db..d49a31ad4 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -17,6 +17,7 @@ #import "RoomMembershipExpandedBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -39,7 +40,7 @@ NSString *const kRoomMembershipExpandedBubbleCellTapOnCollapseButton = @"kRoomMe self.separatorView.backgroundColor = kRiotSecondaryBgColor; - [self.collapseButton setTintColor:kRiotColorGreen]; + [self.collapseButton setTintColor:RiotDesignValues.colorValues.accent]; self.collapseButton.titleLabel.font = [UIFont systemFontOfSize:14]; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m index 7efc5030c..fe40ec063 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m @@ -17,6 +17,7 @@ #import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -26,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m index 7c281d3e4..1f7299953 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m @@ -17,6 +17,7 @@ #import "RoomMembershipWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -26,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index d5e7d5cfa..e4400fbc0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomOutgoingAttachmentBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomOutgoingAttachmentBubbleCell @@ -26,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index 9ec7644e1..b34265b70 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomOutgoingAttachmentWithPaginationTitleBubbleCell @@ -27,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; - self.messageTextView.tintColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m index a106baa47..f2488d5a4 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index 9446e5bb2..7b4df7b14 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomOutgoingTextMsgBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomOutgoingTextMsgBubbleCell @@ -26,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m index ff4957f6d..2be9207b1 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomOutgoingTextMsgWithPaginationTitleBubbleCell @@ -25,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = kRiotColorGreen; - self.paginationSeparatorView.backgroundColor = kRiotColorGreen; + self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m index 1a3b829b1..31bb7ce23 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomOutgoingTextMsgWithoutSenderInfoBubbleCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotColorGreen; + self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 17f7b2178..88dc29b8c 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -17,6 +17,7 @@ #import "EventDetailsView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation EventDetailsView @@ -27,8 +28,8 @@ self.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.textView.textColor = kRiotPrimaryTextColor; - self.redactButton.tintColor = kRiotColorGreen; - self.closeButton.tintColor = kRiotColorGreen; + self.redactButton.tintColor = RiotDesignValues.colorValues.accent; + self.closeButton.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 0ed84f45e..26d191372 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -17,6 +17,7 @@ #import "DisabledRoomInputToolbarView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation DisabledRoomInputToolbarView @@ -51,7 +52,7 @@ self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; self.disabledReasonTextView.textColor = kRiotPrimaryTextColor; - self.disabledReasonTextView.tintColor = kRiotColorGreen; + self.disabledReasonTextView.tintColor = RiotDesignValues.colorValues.accent; self.disabledReasonTextView.editable = NO; self.disabledReasonTextView.scrollEnabled = NO; } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index feae0f022..f3a55839d 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -18,6 +18,7 @@ #import "RoomInputToolbarView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "GBDeviceInfo_iOS.h" @@ -71,8 +72,8 @@ self.rightInputToolbarButton.hidden = YES; - [self.rightInputToolbarButton setTitleColor:kRiotColorGreen forState:UIControlStateNormal]; - [self.rightInputToolbarButton setTitleColor:kRiotColorGreen forState:UIControlStateHighlighted]; + [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.accent forState:UIControlStateNormal]; + [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.accent forState:UIControlStateHighlighted]; self.isEncryptionEnabled = _isEncryptionEnabled; } @@ -95,7 +96,7 @@ growingTextView.font = [UIFont systemFontOfSize:15]; growingTextView.textColor = kRiotPrimaryTextColor; - growingTextView.tintColor = kRiotColorGreen; + growingTextView.tintColor = RiotDesignValues.colorValues.accent; growingTextView.internalTextView.keyboardAppearance = kRiotKeyboard; } diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index c72ff7e19..a0324cf31 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -18,6 +18,7 @@ #import "ExpandedRoomTitleView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -39,7 +40,7 @@ [super customizeViewRendering]; self.roomTopic.textColor = kRiotTopicTextColor; - self.roomMembers.textColor = kRiotColorGreen; + self.roomMembers.textColor = RiotDesignValues.colorValues.accent; } - (void)refreshDisplay diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index ac1f7e5c7..119850c9c 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -19,6 +19,7 @@ #import "PreviewRoomTitleView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -68,7 +69,7 @@ self.roomTopic.textColor = kRiotTopicTextColor; - self.roomMembers.textColor = kRiotColorGreen; + self.roomMembers.textColor = RiotDesignValues.colorValues.accent; self.previewLabel.textColor = kRiotTopicTextColor; self.previewLabel.numberOfLines = 0; @@ -80,11 +81,11 @@ [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; - self.leftButton.backgroundColor = kRiotColorGreen; + self.leftButton.backgroundColor = RiotDesignValues.colorValues.accent; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - self.rightButton.backgroundColor = kRiotColorGreen; + self.rightButton.backgroundColor = RiotDesignValues.colorValues.accent; } - (void)refreshDisplay diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 051d4dc33..20b9219ac 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -17,6 +17,7 @@ #import "DeactivateAccountViewController.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "AppDelegate.h" #pragma mark - Defines & Constants @@ -165,7 +166,7 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; self.deactivateAcccountButton.layer.masksToBounds = YES; - self.deactivateAcccountButton.backgroundColor = kRiotColorGreen; + self.deactivateAcccountButton.backgroundColor = RiotDesignValues.colorValues.accent; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; [self.deactivateAcccountButton setTitleColor:kRiotAuxiliaryColor forState:UIControlStateDisabled]; } diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 96ce50c34..4b01f53a9 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1404,7 +1404,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); [signOutCell.mxkButton setTitle:title forState:UIControlStateNormal]; [signOutCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [signOutCell.mxkButton setTintColor:kRiotColorGreen]; + [signOutCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; signOutCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [signOutCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1559,7 +1559,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); newEmailTextField = newEmailCell.mxkTextField; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:kRiotColorGreen]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.accent]; newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; } @@ -1652,7 +1652,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); newPhoneNumberCell = newPhoneCell; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:kRiotColorGreen]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.accent]; newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; cell = newPhoneCell; @@ -1998,7 +1998,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_mark_all_as_read", @"Vector", nil); [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [markAllBtnCell.mxkButton setTintColor:kRiotColorGreen]; + [markAllBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; markAllBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [markAllBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2023,7 +2023,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_clear_cache", @"Vector", nil); [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [clearCacheBtnCell.mxkButton setTintColor:kRiotColorGreen]; + [clearCacheBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; clearCacheBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [clearCacheBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2048,7 +2048,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_report_bug", @"Vector", nil); [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [reportBugBtnCell.mxkButton setTintColor:kRiotColorGreen]; + [reportBugBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; reportBugBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [reportBugBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2186,7 +2186,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_crypto_export", @"Vector", nil); [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [exportKeysBtnCell.mxkButton setTintColor:kRiotColorGreen]; + [exportKeysBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; exportKeysBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [exportKeysBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 27ba9245b..47d74d3c6 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -18,6 +18,7 @@ #import "DeviceView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation DeviceView @@ -30,9 +31,9 @@ self.containerView.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.defaultTextColor = kRiotPrimaryTextColor; - self.cancelButton.tintColor = kRiotColorGreen; - self.deleteButton.tintColor = kRiotColorGreen; - self.renameButton.tintColor = kRiotColorGreen; + self.cancelButton.tintColor = RiotDesignValues.colorValues.accent; + self.deleteButton.tintColor = RiotDesignValues.colorValues.accent; + self.renameButton.tintColor = RiotDesignValues.colorValues.accent; } @end diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 54c18a313..e7b08578e 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -621,8 +621,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = kRiotColorGreen; - searchBar.tintColor = kRiotColorGreen; + searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.accent; + searchBar.tintColor = RiotDesignValues.colorValues.accent; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -633,7 +633,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = kRiotColorGreen; + leftImageView.tintColor = RiotDesignValues.colorValues.accent; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -646,8 +646,8 @@ { searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: kRiotColorGreen, - NSForegroundColorAttributeName: kRiotColorGreen}]; + NSUnderlineColorAttributeName: RiotDesignValues.colorValues.accent, + NSForegroundColorAttributeName: RiotDesignValues.colorValues.accent}]; } } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 6f49d6219..aa4c0ba30 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -116,7 +116,7 @@ { [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.tabBar.tintColor = kRiotColorGreen; + self.tabBar.tintColor = RiotDesignValues.colorValues.accent; self.tabBar.barTintColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 267c5a6bb..0678fbc42 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -18,6 +18,8 @@ #import "DeviceTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" + #import "MXRoom+Riot.h" #define DEVICE_TABLEVIEW_ROW_CELL_HEIGHT_WITHOUT_LABEL_HEIGHT 59 @@ -34,11 +36,11 @@ [self.verifyButton.layer setCornerRadius:5]; self.verifyButton.clipsToBounds = YES; - self.verifyButton.backgroundColor = kRiotColorGreen; + self.verifyButton.backgroundColor = RiotDesignValues.colorValues.accent; [self.blockButton.layer setCornerRadius:5]; self.blockButton.clipsToBounds = YES; - self.blockButton.backgroundColor = kRiotColorGreen; + self.blockButton.backgroundColor = RiotDesignValues.colorValues.accent; } - (void)render:(MXDeviceInfo *)deviceInfo diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index f161d22da..1fb0c86d5 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -221,7 +221,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.subTitleTextColor = kRiotSecondaryTextColor; self.prefixTextColor = kRiotSecondaryTextColor; self.bingTextColor = RiotDesignValues.colorValues.notificationMention; - self.encryptingTextColor = kRiotColorGreen; + self.encryptingTextColor = RiotDesignValues.colorValues.accent; self.sendingTextColor = kRiotSecondaryTextColor; self.errorTextColor = kRiotColorRed; diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m index 9c3f126d7..ce5e67b8c 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m @@ -22,6 +22,12 @@ #import "RiotDesignValues.h" #import +#ifdef IS_SHARE_EXTENSION +#import "RiotShareExtension-Swift.h" +#else +#import "Riot-Swift.h" +#endif + @interface RoomsListViewController () @property (nonatomic) MXKPieChartHUD *hudView; @@ -90,7 +96,7 @@ self.recentsSearchBar.searchBarStyle = UISearchBarStyleMinimal; self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); - self.recentsSearchBar.tintColor = kRiotColorGreen; + self.recentsSearchBar.tintColor = RiotDesignValues.colorValues.accent; _tableSearchBar.tintColor = self.recentsSearchBar.tintColor; } From cc050e6da083bd5fc01a68fd102eb2362e57fff2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 3 Dec 2018 17:14:32 +0100 Subject: [PATCH 012/244] Reskin: Paint icons with RiotDesignValues.colorValues.accent when possible --- Riot/Modules/Call/CallViewController.m | 3 ++- .../GlobalSearch/Views/RoomIdOrAliasTableViewCell.m | 4 +++- .../Detail/RoomMemberDetailsViewController.m | 3 ++- Riot/Modules/Room/RoomViewController.m | 3 ++- .../Views/Title/Expanded/ExpandedRoomTitleView.h | 5 ++++- .../Views/Title/Expanded/ExpandedRoomTitleView.m | 12 ++++++++++++ .../Views/Title/Expanded/ExpandedRoomTitleView.xib | 13 +++++++------ .../Room/Views/Title/Preview/PreviewRoomTitleView.m | 3 ++- Riot/Modules/Room/Views/Title/RoomTitleView.m | 4 ++++ .../Views/DirectoryServerTableViewCell.m | 4 +++- 10 files changed, 41 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 3138aeea8..0eb1c252e 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -349,7 +349,8 @@ return [AvatarGenerator generateAvatarForMatrixItem:self.mxCall.room.roomId withDisplayName:self.mxCall.room.summary.displayname size:self.callerImageViewWidthConstraint.constant andFontSize:fontSize]; } - return [UIImage imageNamed:@"placeholder"]; + return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + withColor:RiotDesignValues.colorValues.accent]; } - (void)setMxCall:(MXCall *)call diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index bc52e06df..0bd2245eb 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -19,6 +19,7 @@ #import "AvatarGenerator.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomIdOrAliasTableViewCell @@ -48,7 +49,8 @@ } else { - self.avatarImageView.image = [UIImage imageNamed:@"placeholder"]; + self.avatarImageView.image = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + withColor:RiotDesignValues.colorValues.accent]; } self.titleLabel.text = roomIdOrAlias; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 025b4b4e0..dab8e2693 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -358,7 +358,8 @@ return [AvatarGenerator generateAvatarForMatrixItem:self.mxRoomMember.userId withDisplayName:self.mxRoomMember.displayname]; } - return [UIImage imageNamed:@"placeholder"]; + return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + withColor:RiotDesignValues.colorValues.accent]; } - (void)updateMemberInfo diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 33872fac3..db00913df 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1741,7 +1741,8 @@ } else { - previewHeader.roomAvatarPlaceholder = [UIImage imageNamed:@"placeholder"]; + previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + withColor:RiotDesignValues.colorValues.accent]; } } diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.h b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.h index 47073ca77..ff6a1b40d 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.h +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.h @@ -27,4 +27,7 @@ @property (weak, nonatomic) IBOutlet UIView *bottomBorderView; -@end \ No newline at end of file +@property (weak, nonatomic) IBOutlet UIImageView *membersListIcon; +@property (weak, nonatomic) IBOutlet UIImageView *addParticipantIcon; + +@end diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index a0324cf31..33e7fb630 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -35,6 +35,18 @@ [super awakeFromNib]; } +- (void)layoutSubviews +{ + [super layoutSubviews]; + + self.membersListIcon.image = [MXKTools paintImage:self.membersListIcon.image + withColor:RiotDesignValues.colorValues.accent]; + + // TODO: paintImage does not work here because addParticipantIcon has 2 colors +// self.addParticipantIcon.image = [MXKTools paintImage:self.addParticipantIcon.image +// withColor:RiotDesignValues.colorValues.accent]; +} + -(void)customizeViewRendering { [super customizeViewRendering]; diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.xib b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.xib index 2c15d26ca..353189cdd 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.xib +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.xib @@ -1,12 +1,11 @@ - + - - + @@ -38,7 +37,7 @@ - + @@ -62,7 +61,7 @@ - + @@ -143,9 +142,11 @@ + + @@ -157,7 +158,7 @@ - + diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 119850c9c..3fce53189 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -102,7 +102,8 @@ andImageOrientation:UIImageOrientationUp toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop - previewImage:[UIImage imageNamed:@"placeholder"] + previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + withColor:RiotDesignValues.colorValues.accent] mediaManager:self.mxRoom.mxSession.mediaManager]; } else diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index a766629a5..b9f253e09 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -18,6 +18,7 @@ #import "RoomTitleView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomTitleView @@ -70,6 +71,9 @@ - (void)layoutSubviews { [super layoutSubviews]; + + self.roomDetailsIconImageView.image = [MXKTools paintImage:self.roomDetailsIconImageView.image + withColor:RiotDesignValues.colorValues.accent]; if (self.superview) { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 617b0b400..2d5505660 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -19,6 +19,7 @@ #import "AvatarGenerator.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation DirectoryServerTableViewCell @@ -62,7 +63,8 @@ [self.iconImageView setImageURI:iconURL withType:nil andImageOrientation:UIImageOrientationUp - previewImage:[UIImage imageNamed:@"placeholder"] + previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + withColor:RiotDesignValues.colorValues.accent] mediaManager:cellData.mediaManager]; } else From 00aa0575f9af7a25e31a269d199d4c84646396bc Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 3 Dec 2018 18:02:02 +0100 Subject: [PATCH 013/244] Reskin: Apply RiotDesignValues.colorValues.accent on swith buttons --- Riot/Modules/Settings/SettingsViewController.m | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 4b01f53a9..188e63f31 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1695,6 +1695,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_push_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.isPushKitNotificationActive; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePushNotifications:) forControlEvents:UIControlEventTouchUpInside]; @@ -1706,9 +1707,11 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_show_decrypted_content", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.showDecryptedContentInNotifications; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = account.isPushKitNotificationActive; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleShowDecodedContent:) forControlEvents:UIControlEventTouchUpInside]; + cell = labelAndSwitchCell; } else if (row == NOTIFICATION_SETTINGS_GLOBAL_SETTINGS_INDEX) @@ -1730,6 +1733,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_missed_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithMissedNotif:) forControlEvents:UIControlEventTouchUpInside]; @@ -1740,7 +1744,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_unread", @"Vector", nil); - labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome; + labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithUnread:) forControlEvents:UIControlEventTouchUpInside]; @@ -1754,6 +1759,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside]; @@ -1858,6 +1864,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.numberOfLines = 0; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_contacts_discover_matrix_users", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].syncLocalContacts; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLocalContactsSync:) forControlEvents:UIControlEventTouchUpInside]; @@ -1966,6 +1973,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); sendCrashReportCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_send_crash_report", @"Vector", nil); sendCrashReportCell.mxkSwitch.on = RiotSettings.shared.enableCrashReport; + sendCrashReportCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; sendCrashReportCell.mxkSwitch.enabled = YES; [sendCrashReportCell.mxkSwitch addTarget:self action:@selector(toggleSendCrashReport:) forControlEvents:UIControlEventTouchUpInside]; @@ -1977,6 +1985,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); enableRageShakeCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_rageshake", @"Vector", nil); enableRageShakeCell.mxkSwitch.on = RiotSettings.shared.enableRageShake; + enableRageShakeCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; enableRageShakeCell.mxkSwitch.enabled = YES; [enableRageShakeCell.mxkSwitch addTarget:self action:@selector(toggleEnableRageShake:) forControlEvents:UIControlEventTouchUpInside]; @@ -2068,6 +2077,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; labelAndSwitchCell.mxkSwitch.on = account.mxSession.syncWithLazyLoadOfRoomMembers; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleSyncWithLazyLoadOfRoomMembers:) forControlEvents:UIControlEventTouchUpInside]; @@ -2079,6 +2089,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_create_conference_with_jitsi", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.createConferenceCallsWithJitsi; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleJitsiForConference:) forControlEvents:UIControlEventTouchUpInside]; @@ -2092,6 +2103,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_e2e_encryption", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = (nil != session.crypto); + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLabsEndToEndEncryption:) forControlEvents:UIControlEventTouchUpInside]; @@ -2165,6 +2177,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_crypto_blacklist_unverified_devices", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.mxSession.crypto.globalBlacklistUnverifiedDevices; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevices:) forControlEvents:UIControlEventTouchUpInside]; From a04dfd94746b6fc0d2e7c8739c9a280d0715935e Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 21 Dec 2018 11:41:43 +0100 Subject: [PATCH 014/244] Reskin: New TermsView screen --- Riot/Modules/Authentication/Views/TermsView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index 443b9486e..b422b53e2 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -80,7 +80,7 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie } func customizeViewRendering() { - acceptButton.backgroundColor = kRiotColorGreen + acceptButton.backgroundColor = RiotDesignValues.colorValues().accent } From e6862e0d15b71b51a41e0a172c8dfc82e904f53d Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 28 Dec 2018 09:16:24 +0100 Subject: [PATCH 015/244] reskin: Fix display of expanded header in Room VC --- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 6 +++--- Riot/Modules/Room/RoomViewController.m | 6 ++++++ 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index f1887a86c..a04497567 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -62,7 +62,6 @@ extern UIStatusBarStyle kRiotDesignStatusBarStyle; extern UIColor *kRiotDesignNavigationBarTintColor; extern UIColor *kRiotDesignNavigationBarBarTintColor; extern NSDictionary *kRiotDesignNavigationBarTitleTextAttributes; -extern BOOL kRiotDesignNavigationBarTranslucent; extern UIBarStyle kRiotDesignSearchBarStyle; extern UIColor *kRiotDesignSearchBarTintColor; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 5b18e38cf..8286018df 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -54,7 +54,6 @@ UIStatusBarStyle kRiotDesignStatusBarStyle = UIStatusBarStyleDefault; UIColor *kRiotDesignNavigationBarTintColor; UIColor *kRiotDesignNavigationBarBarTintColor; NSDictionary *kRiotDesignNavigationBarTitleTextAttributes; -BOOL kRiotDesignNavigationBarTranslucent = YES; UIBarStyle kRiotDesignSearchBarStyle = UIBarStyleDefault; UIColor *kRiotDesignSearchBarTintColor = nil; @@ -164,7 +163,6 @@ UIKeyboardAppearance kRiotKeyboard; kRiotSelectedBgColor = nil; // Use the default selection color. kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; - kRiotDesignNavigationBarTranslucent = NO; kRiotDesignSearchBarStyle = UIBarStyleDefault; @@ -235,7 +233,9 @@ UIKeyboardAppearance kRiotKeyboard; navigationBar.tintColor = kRiotDesignNavigationBarTintColor; navigationBar.titleTextAttributes = kRiotDesignNavigationBarTitleTextAttributes; navigationBar.barTintColor = kRiotDesignNavigationBarBarTintColor; - navigationBar.translucent = kRiotDesignNavigationBarTranslucent; + + // The navigation bar needs to be opaque so that its background color is the expected one + navigationBar.translucent = NO; } + (void)applyStyleOnSearchBar:(UISearchBar *)searchBar diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index db00913df..0b6fba85c 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1483,6 +1483,12 @@ - (void)showExpandedHeader:(BOOL)isVisible { + // Use a transparent navigation bar when displaying the expanded header + // Retrieve the main navigation controller if the current view controller + // is embedded inside a split view controlle + self.navigationController.navigationBar.translucent = isVisible; + self.mxk_mainNavigationController.navigationBar.translucent = isVisible; + if (self.expandedHeaderContainer.isHidden == isVisible) { // Check conditions before making the expanded room header visible. From 0a0279e8b6070f66eb33f38169cf6498a5bc0557 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 28 Dec 2018 17:52:45 +0100 Subject: [PATCH 016/244] reskin: Improve a bit RoomVC expanded header display RoomVC is displayed in another UINavigationController. Its bar can be translucent. Then, we just need to make sure that the main UINavigationController navigationBar is translucent when displaying the expanded header. Note: there is a UI glitch when navigating back when the expanded header is displayed but that bug existed before (in v0.7.8) --- Riot/Modules/Room/RoomViewController.m | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 0b6fba85c..03668a848 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -419,6 +419,7 @@ - (void)userInterfaceThemeDidChange { [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.navigationController.navigationBar.translucent = YES; self.activityIndicator.backgroundColor = kRiotOverlayColor; @@ -1483,12 +1484,6 @@ - (void)showExpandedHeader:(BOOL)isVisible { - // Use a transparent navigation bar when displaying the expanded header - // Retrieve the main navigation controller if the current view controller - // is embedded inside a split view controlle - self.navigationController.navigationBar.translucent = isVisible; - self.mxk_mainNavigationController.navigationBar.translucent = isVisible; - if (self.expandedHeaderContainer.isHidden == isVisible) { // Check conditions before making the expanded room header visible. @@ -1549,6 +1544,7 @@ // Report shadow image [mainNavigationController.navigationBar setShadowImage:shadowImage]; [mainNavigationController.navigationBar setBackgroundImage:shadowImage forBarMetrics:UIBarMetricsDefault]; + mainNavigationController.navigationBar.translucent = isVisible; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ From 571c5630a6dcfd40dec577fc260081def08de05d Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 28 Dec 2018 17:54:19 +0100 Subject: [PATCH 017/244] reskin: Fix display of RoomMemberDetailsVC header. Apply the same logic as in RoomVC in the previous commit --- .../Room/Members/Detail/RoomMemberDetailsViewController.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index dab8e2693..73fb8bfd6 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -219,10 +219,11 @@ - (void)userInterfaceThemeDidChange { [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + self.navigationController.navigationBar.translucent = YES; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.memberHeaderView.backgroundColor = kRiotSecondaryBgColor; + self.memberHeaderView.backgroundColor = kRiotDesignNavigationBarBarTintColor; self.roomMemberNameLabel.textColor = kRiotPrimaryTextColor; self.roomMemberStatusLabel.textColor = RiotDesignValues.colorValues.accent; @@ -473,6 +474,9 @@ [mainNavigationController.navigationBar setShadowImage:nil]; [mainNavigationController.navigationBar setBackgroundImage:nil forBarMetrics:UIBarMetricsDefault]; } + + // Main Navigation bar opacity must follow + mainNavigationController.navigationBar.translucent = isHidden; } #pragma mark - TableView data source From 401e4b3a0a4f33c9cde50d7e5bce29d345ca90e1 Mon Sep 17 00:00:00 2001 From: daniel tygel Date: Sun, 17 Jun 2018 17:19:18 +0000 Subject: [PATCH 018/244] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (4 of 4 strings) Translation: Riot iOS/Riot iOS (Dialogs) Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios-dialogs/pt_BR/ --- Riot/Assets/pt_BR.lproj/InfoPlist.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/pt_BR.lproj/InfoPlist.strings b/Riot/Assets/pt_BR.lproj/InfoPlist.strings index da30fcefa..60e4b10f3 100644 --- a/Riot/Assets/pt_BR.lproj/InfoPlist.strings +++ b/Riot/Assets/pt_BR.lproj/InfoPlist.strings @@ -2,4 +2,4 @@ "NSCameraUsageDescription" = "A câmera será usada para tomar fotos e vídeos, e também para a realização de chamadas de vídeo."; "NSPhotoLibraryUsageDescription" = "A galeria de fotos é usada para o envio de fotos e vídeos."; "NSMicrophoneUsageDescription" = "O microfone é usado para gravar vídeos e fazer chamadas, tanto de áudio como de vídeo."; -"NSContactsUsageDescription" = "O cadernos de contatos é usado para fazer busca de usuárias/os no Riot a partir do e-mail ou do número de telefone."; +"NSContactsUsageDescription" = "Para mostrar a você quais de seus contatos já estão usando o Riot ou o Matrix, podemos enviar os endereços de e-mail e números de telefone em seu catálogo de endereços para o Matrix Identity Server. A New Vector não armazena esses dados ou usa-os para qualquer outra finalidade. Para mais informações, consulte a página da política de privacidade nas configurações do aplicativo."; From 9f34103150124aef360658e4b981f57c65534437 Mon Sep 17 00:00:00 2001 From: Paulo Miranda Date: Fri, 4 Jan 2019 00:39:01 +0000 Subject: [PATCH 019/244] Translated using Weblate (Portuguese (Brazil)) Currently translated at 33.0% (172 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/pt_BR/ --- Riot/Assets/pt_BR.lproj/Vector.strings | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index 32eea684f..f8df570ca 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -158,4 +158,27 @@ "room_creation_title" = "Nova Sala"; "room_creation_account" = "Conta"; // Room recents -"room_recents_directory_section" = "LISTA PÚBLICA DE SALAS"; +"room_recents_directory_section" = "DIRETÓRIO DE SALAS"; +"directory_search_results_title" = "Procurar nos resultados do diretório"; +"directory_search_fail" = "Falha ao buscar dados"; +"auth_accept_policies" = "Por favor, revise e aceite as políticas deste homeserver:"; +"room_recents_server_notice_section" = "ALERTAS DO SISTEMA"; +"room_participants_remove_third_party_invite_msg" = "Remover convite de terceiros ainda não é suportado até que a API exista"; +"room_participants_invite_prompt_title" = "Confirmação"; +"room_participants_invite_prompt_msg" = "Tem certeza de que deseja convidar %@ para este chat?"; +"room_participants_filter_room_members" = "Filtrar membros da sala"; +"room_participants_invite_another_user" = "Pesquisar / convidar por ID do usuário, nome ou e-mail"; +"room_participants_invite_malformed_id_title" = "Erro no Convite"; +"room_participants_invited_section" = "CONVIDADO"; +"room_participants_online" = "Online"; +"room_participants_offline" = "Offline"; +"room_participants_unknown" = "Desconhecido"; +"room_participants_idle" = "Ocioso"; +"room_participants_now" = "agora"; +"room_participants_ago" = "atrás"; +"room_participants_action_section_admin_tools" = "Ferramentas Administrativas"; +"room_participants_action_section_direct_chats" = "bate-papos diretos"; +"room_participants_action_section_devices" = "Dispositivos"; +"room_participants_action_section_other" = "Outros"; +"room_participants_action_invite" = "Convidar"; +"room_participants_action_leave" = "Deixar esta sala"; From 03a5f8755249565474088f77656678f917761e13 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Sun, 6 Jan 2019 22:22:14 -0600 Subject: [PATCH 020/244] Use white scroll bar in dark and black themes Signed-off-by: Aaron Raimist --- Riot.xcodeproj/project.pbxproj | 2 ++ Riot/Constants/RiotDesignValues.m | 12 ++++++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 16dcad2ef..07198bac1 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -2413,6 +2413,7 @@ ); path = Riot; sourceTree = ""; + usesTabs = 0; }; F083BB0E1E7009EC00A9B29C /* Assets */ = { isa = PBXGroup; @@ -2513,6 +2514,7 @@ A237FB70534FB8ADA0D7CFEE /* Pods */, ); sourceTree = ""; + usesTabs = 0; }; F094A9A31B78D8F000B1FBBF /* Products */ = { isa = PBXGroup; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index a6d4ce672..2b5b1debb 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -73,6 +73,7 @@ UIBarStyle kRiotDesignSearchBarStyle = UIBarStyleDefault; UIColor *kRiotDesignSearchBarTintColor = nil; UIKeyboardAppearance kRiotKeyboard; +UIScrollViewIndicatorStyle kRiotScrollBarStyle; @implementation RiotDesignValues @@ -179,8 +180,8 @@ UIKeyboardAppearance kRiotKeyboard; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; kRiotKeyboardColor = kRiotColorDarkKeyboard; - [UITextField appearance].keyboardAppearance = UIKeyboardAppearanceDark; kRiotKeyboard = UIKeyboardAppearanceDark; + kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } else if ([theme isEqualToString:@"black"]) { @@ -201,8 +202,8 @@ UIKeyboardAppearance kRiotKeyboard; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; kRiotKeyboardColor = kRiotColorDarkKeyboard; - [UITextField appearance].keyboardAppearance = UIKeyboardAppearanceDark; kRiotKeyboard = UIKeyboardAppearanceDark; + kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } else { @@ -222,11 +223,14 @@ UIKeyboardAppearance kRiotKeyboard; kRiotAuxiliaryColor = kRiotColorSilver; kRiotOverlayColor = [UIColor colorWithWhite:0.7 alpha:0.5]; kRiotKeyboardColor = kRiotColorLightKeyboard; - - [UITextField appearance].keyboardAppearance = UIKeyboardAppearanceLight; + kRiotKeyboard = UIKeyboardAppearanceLight; + kRiotScrollBarStyle = UIScrollViewIndicatorStyleDefault; } + [UITextField appearance].keyboardAppearance = kRiotKeyboard; + [UIScrollView appearance].indicatorStyle = kRiotScrollBarStyle; + [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; } From a940ecc50696758091d8c70c89a17e3fcc8806fc Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Sun, 6 Jan 2019 22:39:33 -0600 Subject: [PATCH 021/244] Add changelog Signed-off-by: Aaron Raimist --- CHANGES.rst | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index cadc8d154..1e4b68663 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,9 @@ +Changes in 0.7.x (2019-xx-xx) +=============================================== + +Bug fix: + * Use white scroll bar on dark themes (#2158) + Changes in 0.7.10 (2019-01-04) =============================================== @@ -8,10 +14,10 @@ Changes in 0.7.9 (2019-01-04) =============================================== Improvements: -* Upgrade MatrixKit version (v0.9.2). + * Upgrade MatrixKit version (v0.9.2). Bug fix: -* Registration: email or phone number is no more skippable (#2140). + * Registration: email or phone number is no more skippable (#2140). Changes in 0.7.8 (2018-12-12) =============================================== From 2839a24058042d5d20d97c4296d399aadc26c482 Mon Sep 17 00:00:00 2001 From: fridtjof <2780577+fridtjof@users.noreply.github.com> Date: Tue, 8 Jan 2019 00:24:11 +0100 Subject: [PATCH 022/244] make use of Obj-C's modern syntax for literals and subscripting --- Riot/AppDelegate.m | 14 +- .../MXKRoomBubbleTableViewCell+Riot.m | 2 +- Riot/Categories/MXRoom+Riot.m | 2 +- Riot/Managers/Analytics/Analytics.m | 2 +- .../AuthenticationViewController.m | 4 +- .../Authentication/Views/AuthInputsView.m | 4 +- Riot/Modules/Call/CallViewController.m | 2 +- .../Recents/DataSources/RecentsDataSource.m | 20 +- .../Common/Recents/RecentsViewController.m | 2 +- .../SegmentedViewController.m | 14 +- .../Members/GroupParticipantsViewController.m | 15 +- .../Contacts/DataSources/ContactsDataSource.m | 8 +- .../Details/ContactDetailsViewController.m | 2 +- Riot/Modules/Home/HomeViewController.m | 2 +- .../MediaPicker/MediaPickerViewController.m | 6 +- .../Room/CellData/RoomBubbleCellData.m | 4 +- .../Detail/RoomMemberDetailsViewController.m | 4 +- .../Members/RoomParticipantsViewController.m | 17 +- Riot/Modules/Room/RoomViewController.m | 18 +- .../Settings/RoomSettingsViewController.m | 186 +++++++++--------- .../Modules/Settings/SettingsViewController.m | 32 +-- .../StartChat/StartChatViewController.m | 6 +- Riot/Modules/TabBar/MasterTabBarController.m | 12 +- Riot/Utils/AvatarGenerator.m | 8 +- .../Managers/ShareExtensionManager.m | 2 +- .../Modules/Share/ShareViewController.m | 2 +- SiriIntents/IntentHandler.m | 2 +- 27 files changed, 195 insertions(+), 197 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index e49b0ed7b..e5c96e866 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -389,7 +389,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN NSLog(@"[AppDelegate] didFinishLaunchingWithOptions: isProtectedDataAvailable: %@", @([application isProtectedDataAvailable])); // Log app information - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; NSString* appVersion = [AppDelegate theDelegate].appVersion; NSString* build = [AppDelegate theDelegate].build; @@ -437,7 +437,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UISplitViewController *splitViewController = (UISplitViewController *)self.window.rootViewController; splitViewController.delegate = self; - _masterNavigationController = [splitViewController.viewControllers objectAtIndex:0]; + _masterNavigationController = splitViewController.viewControllers[0]; _masterTabBarController = _masterNavigationController.viewControllers.firstObject; // Force the background color of the fake view controller displayed when there is no details. @@ -1080,7 +1080,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UIMutableUserNotificationCategory* quickReplyCategory = [[UIMutableUserNotificationCategory alloc] init]; quickReplyCategory.identifier = @"QUICK_REPLY"; - [quickReplyCategory setActions:[NSArray arrayWithObjects:quickReply, nil] forContext:UIUserNotificationActionContextDefault]; + [quickReplyCategory setActions:@[quickReply] forContext:UIUserNotificationActionContextDefault]; [notificationCategories addObject:quickReplyCategory]; } @@ -1144,7 +1144,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN else { [manager roomDataSourceForRoom:roomId create:YES onComplete:^(MXKRoomDataSource *roomDataSource) { - NSString* responseText = [responseInfo objectForKey:UIUserNotificationActionResponseTypedTextKey]; + NSString* responseText = responseInfo[UIUserNotificationActionResponseTypedTextKey]; if (responseText != nil && responseText.length != 0) { NSLog(@"[AppDelegate][Push] handleActionWithIdentifier: sending message to room: %@", roomId); @@ -2144,10 +2144,10 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN for (NSString *keyValue in [fragments[1] componentsSeparatedByString:@"&"]) { // Get the parameter name - NSString *key = [[keyValue componentsSeparatedByString:@"="] objectAtIndex:0]; + NSString *key = [keyValue componentsSeparatedByString:@"="][0]; // Get the parameter value - NSString *value = [[keyValue componentsSeparatedByString:@"="] objectAtIndex:1]; + NSString *value = [keyValue componentsSeparatedByString:@"="][1]; if (value.length) { value = [value stringByReplacingOccurrencesOfString:@"+" withString:@" "]; @@ -3777,7 +3777,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN callerDisplayname = event.sender; } - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; NSString *message = [NSString stringWithFormat:NSLocalizedStringFromTable(@"no_voip", @"Vector", nil), callerDisplayname, appDisplayName]; diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index dabdb7af2..a0a916211 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -315,7 +315,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT - (void)setBlurred:(BOOL)blurred { - objc_setAssociatedObject(self, @selector(blurred), [NSNumber numberWithBool:blurred], OBJC_ASSOCIATION_RETAIN_NONATOMIC); + objc_setAssociatedObject(self, @selector(blurred), @(blurred), OBJC_ASSOCIATION_RETAIN_NONATOMIC); if (blurred) { diff --git a/Riot/Categories/MXRoom+Riot.m b/Riot/Categories/MXRoom+Riot.m index fc2533508..cc43e075a 100644 --- a/Riot/Categories/MXRoom+Riot.m +++ b/Riot/Categories/MXRoom+Riot.m @@ -32,7 +32,7 @@ if (self.accountData.tags && self.accountData.tags.count) { - oldTag = [self.accountData.tags.allKeys objectAtIndex:0]; + oldTag = self.accountData.tags.allKeys[0]; } // support only kMXRoomTagFavourite or kMXRoomTagLowPriority tags by now diff --git a/Riot/Managers/Analytics/Analytics.m b/Riot/Managers/Analytics/Analytics.m index a87b29315..552e9e0ab 100644 --- a/Riot/Managers/Analytics/Analytics.m +++ b/Riot/Managers/Analytics/Analytics.m @@ -103,7 +103,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure"; - (void)trackScreen:(NSString *)screenName { // Use the same pattern as Android - NSString *appName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; NSString *appVersion = [AppDelegate theDelegate].appVersion; [[PiwikTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName] diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index cd16fe9d5..5aad8e64d 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -158,7 +158,7 @@ self.noFlowLabel.textColor = kRiotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; - [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:[NSNumber numberWithInteger:NSUnderlineStyleSingle] range:NSMakeRange(0, forgotPasswordTitle.length)]; + [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:kRiotColorGreen range:NSMakeRange(0, forgotPasswordTitle.length)]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; @@ -290,7 +290,7 @@ if (!countryCode) { // If none, consider the preferred locale - NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]]; + NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[NSBundle mainBundle] preferredLocalizations][0]]; if ([local respondsToSelector:@selector(countryCode)]) { countryCode = local.countryCode; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 9aa81ff8f..c35376819 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -1292,11 +1292,11 @@ // Retrieve the site key NSString *siteKey; - id recaptchaParams = [currentSession.params objectForKey:kMXLoginFlowTypeRecaptcha]; + id recaptchaParams = currentSession.params[kMXLoginFlowTypeRecaptcha]; if (recaptchaParams && [recaptchaParams isKindOfClass:NSDictionary.class]) { NSDictionary *recaptchaParamsDict = (NSDictionary*)recaptchaParams; - siteKey = [recaptchaParamsDict objectForKey:@"public_key"]; + siteKey = recaptchaParamsDict[@"public_key"]; } // Retrieve the REST client from delegate diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index b88a3e32b..5a9f710d4 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -127,7 +127,7 @@ CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; - gradientMaskLayer.colors = [NSArray arrayWithObjects:(__bridge id)opaqueWhiteColor, (__bridge id)transparentWhiteColor, nil]; + gradientMaskLayer.colors = @[(__bridge id) opaqueWhiteColor, (__bridge id) transparentWhiteColor]; gradientMaskLayer.bounds = CGRectMake(0, 0, self.callContainerView.frame.size.width, self.callContainerView.frame.size.height + 20); gradientMaskLayer.anchorPoint = CGPointZero; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index e228e2039..f7341486a 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -156,7 +156,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // sanity check if (matrixSession.myUser && matrixSession.myUser.userId) { - id roomTagListener = [roomTagsListenerByUserId objectForKey:matrixSession.myUser.userId]; + id roomTagListener = roomTagsListenerByUserId[matrixSession.myUser.userId]; if (roomTagListener) { @@ -204,7 +204,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou }]; - [roomTagsListenerByUserId setObject:roomTagsListener forKey:dataSource.mxSession.myUser.userId]; + roomTagsListenerByUserId[dataSource.mxSession.myUser.userId] = roomTagsListener; } } } @@ -891,42 +891,42 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { if (cellDataIndex < favoriteCellDataArray.count) { - cellData = [favoriteCellDataArray objectAtIndex:cellDataIndex]; + cellData = favoriteCellDataArray[cellDataIndex]; } } else if (tableSection == peopleSection) { if (cellDataIndex < peopleCellDataArray.count) { - cellData = [peopleCellDataArray objectAtIndex:cellDataIndex]; + cellData = peopleCellDataArray[cellDataIndex]; } } else if (tableSection== conversationSection) { if (cellDataIndex < conversationCellDataArray.count) { - cellData = [conversationCellDataArray objectAtIndex:cellDataIndex]; + cellData = conversationCellDataArray[cellDataIndex]; } } else if (tableSection == lowPrioritySection) { if (cellDataIndex < lowPriorityCellDataArray.count) { - cellData = [lowPriorityCellDataArray objectAtIndex:cellDataIndex]; + cellData = lowPriorityCellDataArray[cellDataIndex]; } } else if (tableSection == serverNoticeSection) { if (cellDataIndex < serverNoticeCellDataArray.count) { - cellData = [serverNoticeCellDataArray objectAtIndex:cellDataIndex]; + cellData = serverNoticeCellDataArray[cellDataIndex]; } } else if (tableSection == invitesSection) { if (cellDataIndex < invitesCellDataArray.count) { - cellData = [invitesCellDataArray objectAtIndex:cellDataIndex]; + cellData = invitesCellDataArray[cellDataIndex]; } } @@ -983,7 +983,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { for (int index = 0; index < cellDataArray.count; index++) { - id cellDataStoring = [cellDataArray objectAtIndex:index]; + id cellDataStoring = cellDataArray[index]; if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession)) { @@ -1114,7 +1114,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (displayedRecentsDataSourceArray.count > 0) { // FIXME manage multi accounts - MXKSessionRecentsDataSource *recentsDataSource = [displayedRecentsDataSourceArray objectAtIndex:0]; + MXKSessionRecentsDataSource *recentsDataSource = displayedRecentsDataSourceArray[0]; MXSession* session = recentsDataSource.mxSession; NSInteger count = recentsDataSource.numberOfCells; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index f0f54f16a..8e3d8da43 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -893,7 +893,7 @@ NSArray* tags = room.accountData.tags.allValues; if (tags.count) { - currentTag = [tags objectAtIndex:0]; + currentTag = tags[0]; } } diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index c4d5d4d12..d539f6ffa 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -243,7 +243,7 @@ // create programmatically each label UILabel *label = [[UILabel alloc] init]; - label.text = [sectionTitles objectAtIndex:index]; + label.text = sectionTitles[index]; label.font = [UIFont systemFontOfSize:17]; label.textAlignment = NSTextAlignmentCenter; label.textColor = _sectionHeaderTintColor; @@ -263,7 +263,7 @@ leftConstraint = [NSLayoutConstraint constraintWithItem:label attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual - toItem:[labels objectAtIndex:(index-1)] + toItem:labels[index - 1] attribute:NSLayoutAttributeTrailing multiplier:1.0 constant:0]; @@ -339,7 +339,7 @@ leftMarkerViewConstraint = [NSLayoutConstraint constraintWithItem:selectedMarkerView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual - toItem:[sectionLabels objectAtIndex:_selectedIndex] + toItem:sectionLabels[_selectedIndex] attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; @@ -386,7 +386,7 @@ if (index != NSNotFound) { - UILabel* label = [sectionLabels objectAtIndex:index]; + UILabel* label = sectionLabels[index]; label.font = [UIFont systemFontOfSize:17]; } @@ -398,7 +398,7 @@ [NSLayoutConstraint deactivateConstraints:@[displayedVCTopConstraint, displayedVCLeftConstraint, displayedVCWidthConstraint, displayedVCHeightConstraint]]; } - UILabel* label = [sectionLabels objectAtIndex:_selectedIndex]; + UILabel* label = sectionLabels[_selectedIndex]; label.font = [UIFont boldSystemFontOfSize:17]; // update the marker view position @@ -407,7 +407,7 @@ leftMarkerViewConstraint = [NSLayoutConstraint constraintWithItem:selectedMarkerView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual - toItem:[sectionLabels objectAtIndex:_selectedIndex] + toItem:sectionLabels[_selectedIndex] attribute:NSLayoutAttributeLeading multiplier:1.0 constant:0]; @@ -415,7 +415,7 @@ [NSLayoutConstraint activateConstraints:@[leftMarkerViewConstraint]]; // Set the new selected view controller - _selectedViewController = [viewControllers objectAtIndex:_selectedIndex]; + _selectedViewController = viewControllers[_selectedIndex]; // Make iOS invoke selectedViewController viewWillAppear when the segmented view is already visible if (isViewAppeared) diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index ef7ba2360..da5f29271 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -161,7 +161,7 @@ [kRiotPrimaryBgColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; - tableViewMaskLayer.colors = [NSArray arrayWithObjects:(__bridge id)transparentWhiteColor, (__bridge id)transparentWhiteColor, (__bridge id)opaqueWhiteColor, nil]; + tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; if (self.tableView.dataSource) { @@ -450,13 +450,12 @@ CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; - tableViewMaskLayer.colors = [NSArray arrayWithObjects:(__bridge id)transparentWhiteColor, (__bridge id)transparentWhiteColor, (__bridge id)opaqueWhiteColor, nil]; + tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; // display a gradient to the rencents bottom (20% of the bottom of the screen) - tableViewMaskLayer.locations = [NSArray arrayWithObjects: - [NSNumber numberWithFloat:0], - [NSNumber numberWithFloat:0.85], - [NSNumber numberWithFloat:1.0], nil]; + tableViewMaskLayer.locations = @[@0.0F, + @0.85F, + @1.0F]; tableViewMaskLayer.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); tableViewMaskLayer.anchorPoint = CGPointZero; @@ -540,11 +539,11 @@ // List all the participants matrix user id to ignore them during the contacts search. for (Contact *contact in actualParticipants) { - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxGroupUser.userId]; + contactsDataSource.ignoredContactsByMatrixId[contact.mxGroupUser.userId] = contact; } for (Contact *contact in invitedParticipants) { - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxGroupUser.userId]; + contactsDataSource.ignoredContactsByMatrixId[contact.mxGroupUser.userId] = contact; } [contactsPickerViewController showSearch:YES]; diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index b0ac22827..b78d14dd4 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -375,7 +375,7 @@ NSArray *identifiers = contact.matrixIdentifiers; if (identifiers.count) { - if ([_ignoredContactsByMatrixId objectForKey:identifiers.firstObject]) + if (_ignoredContactsByMatrixId[identifiers.firstObject]) { [unfilteredLocalContacts removeObjectAtIndex:index]; continue; @@ -396,7 +396,7 @@ MXKEmail *email = emails.firstObject; // Trick: ignore @facebook.com email addresses from the results - facebook have discontinued that service... - if ([_ignoredContactsByEmail objectForKey:email.emailAddress] || [email.emailAddress hasSuffix:@"@facebook.com"]) + if (_ignoredContactsByEmail[email.emailAddress] || [email.emailAddress hasSuffix:@"@facebook.com"]) { [unfilteredLocalContacts removeObjectAtIndex:index]; continue; @@ -434,7 +434,7 @@ { for (NSString *userId in identifiers) { - if ([_ignoredContactsByMatrixId objectForKey:userId] == nil) + if (_ignoredContactsByMatrixId[userId] == nil) { MXKContact *splitContact = [[MXKContact alloc] initMatrixContactWithDisplayName:contact.displayName andMatrixID:userId]; [unfilteredMatrixContacts addObject:splitContact]; @@ -444,7 +444,7 @@ else if (identifiers.count) { NSString *userId = identifiers.firstObject; - if ([_ignoredContactsByMatrixId objectForKey:userId] == nil) + if (_ignoredContactsByMatrixId[userId] == nil) { [unfilteredMatrixContacts addObject:contact]; } diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 3c40ccb57..3e264ba2c 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -727,7 +727,7 @@ if (indexPath.row < actionsArray.count) { - NSNumber *actionNumber = [actionsArray objectAtIndex:indexPath.row]; + NSNumber *actionNumber = actionsArray[indexPath.row]; NSString *title = [self actionButtonTitle:actionNumber.unsignedIntegerValue]; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 8c261b545..65d69eeb5 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -301,7 +301,7 @@ NSArray* tags = room.accountData.tags.allValues; if (tags.count) { - currentTag = [tags objectAtIndex:0]; + currentTag = tags[0]; } } diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index f0f30b847..ae3ceb3ba 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -306,7 +306,7 @@ static void *RecordingContext = &RecordingContext; - (void)checkDeviceAuthorizationStatus { - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; [MXKTools checkAccessForMediaType:AVMediaTypeVideo manualChangeMessage:[NSString stringWithFormat:NSLocalizedStringFromTable(@"camera_access_not_granted", @"Vector", nil), appDisplayName] @@ -1324,7 +1324,7 @@ static void *RecordingContext = &RecordingContext; - (void)caughtAVRuntimeError:(NSNotification*)note { - NSError *error = [[note userInfo] objectForKey:AVCaptureSessionErrorKey]; + NSError *error = [note userInfo][AVCaptureSessionErrorKey]; NSLog(@"[MediaPickerVC] AV Session Error: %@", error); dispatch_async(dispatch_get_main_queue(), ^{ @@ -1838,7 +1838,7 @@ static void *RecordingContext = &RecordingContext; { if (validationView) { - validationView.image = [[notification userInfo] objectForKey:MPMoviePlayerThumbnailImageKey]; + validationView.image = [notification userInfo][MPMoviePlayerThumbnailImageKey]; [validationView bringSubviewToFront:videoPlayerControl]; // Now, there is a thumbnail, show the video control diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 55aa3051e..81cbef55f 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -275,7 +275,7 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil; for (; index < bubbleComponents.count; index++) { // Compute the vertical position for next component - component = [bubbleComponents objectAtIndex:index]; + component = bubbleComponents[index]; component.position = CGPointMake(0, positionY); @@ -316,7 +316,7 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil; for (index++; index < bubbleComponents.count; index++) { // Compute the vertical position for next component - component = [bubbleComponents objectAtIndex:index]; + component = bubbleComponents[index]; if (component.attributedTextMessage) { diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 5b88317b3..3a9827614 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -754,11 +754,11 @@ NSNumber *actionNumber; if (indexPath.section == adminToolsIndex && indexPath.row < adminActionsArray.count) { - actionNumber = [adminActionsArray objectAtIndex:indexPath.row]; + actionNumber = adminActionsArray[indexPath.row]; } else if (indexPath.section == otherActionsIndex && indexPath.row < otherActionsArray.count) { - actionNumber = [otherActionsArray objectAtIndex:indexPath.row]; + actionNumber = otherActionsArray[indexPath.row]; } if (actionNumber) diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 3a3fefa6a..0712a7169 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -173,7 +173,7 @@ [kRiotPrimaryBgColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; - tableViewMaskLayer.colors = [NSArray arrayWithObjects:(__bridge id)transparentWhiteColor, (__bridge id)transparentWhiteColor, (__bridge id)opaqueWhiteColor, nil]; + tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; if (self.tableView.dataSource) { @@ -581,13 +581,12 @@ CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; - tableViewMaskLayer.colors = [NSArray arrayWithObjects:(__bridge id)transparentWhiteColor, (__bridge id)transparentWhiteColor, (__bridge id)opaqueWhiteColor, nil]; + tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; // display a gradient to the rencents bottom (20% of the bottom of the screen) - tableViewMaskLayer.locations = [NSArray arrayWithObjects: - [NSNumber numberWithFloat:0], - [NSNumber numberWithFloat:0.85], - [NSNumber numberWithFloat:1.0], nil]; + tableViewMaskLayer.locations = @[@0.0F, + @0.85F, + @1.0F]; tableViewMaskLayer.bounds = CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height); tableViewMaskLayer.anchorPoint = CGPointZero; @@ -671,18 +670,18 @@ // List all the participants matrix user id to ignore them during the contacts search. for (Contact *contact in actualParticipants) { - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxMember.userId]; + contactsDataSource.ignoredContactsByMatrixId[contact.mxMember.userId] = contact; } for (Contact *contact in invitedParticipants) { if (contact.mxMember) { - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:contact.mxMember.userId]; + contactsDataSource.ignoredContactsByMatrixId[contact.mxMember.userId] = contact; } } if (userParticipant) { - [contactsDataSource.ignoredContactsByMatrixId setObject:userParticipant forKey:userParticipant.mxMember.userId]; + contactsDataSource.ignoredContactsByMatrixId[userParticipant.mxMember.userId] = userParticipant; } [contactsPickerViewController showSearch:YES]; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index fea0b3ca0..09fdb31a0 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -2233,7 +2233,7 @@ [self cancelEventSelection]; - NSArray *activityItems = [NSArray arrayWithObjects:selectedComponent.textMessage, nil]; + NSArray *activityItems = @[selectedComponent.textMessage]; UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; @@ -2974,7 +2974,7 @@ { // Create the contact related to this member MXKContact *contact = [[MXKContact alloc] initMatrixContactWithDisplayName:mxMember.displayname andMatrixID:mxMember.userId]; - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:mxMember.userId]; + contactsDataSource.ignoredContactsByMatrixId[mxMember.userId] = contact; } } @@ -3080,7 +3080,7 @@ { __weak __typeof(self) weakSelf = self; - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; // Check app permissions first [MXKTools checkAccessForCall:video @@ -3400,7 +3400,7 @@ [super scrollViewWillBeginDragging:scrollView]; } - if (self.expandedHeaderContainer.isHidden == NO) + if (!self.expandedHeaderContainer.isHidden) { // Store here the position of the first touch down event UIPanGestureRecognizer *panGestureRecognizer = scrollView.panGestureRecognizer; @@ -3728,7 +3728,7 @@ // keeps the only the first two users for(int i = 0; i < MIN(count, 2); i++) { - NSString* name = [currentTypingUsers objectAtIndex:i]; + NSString* name = currentTypingUsers[i]; MXRoomMember* member = [self.roomDataSource.roomState.members memberWithUserId:name]; @@ -3750,15 +3750,15 @@ } else if (1 == names.count) { - text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_one_user_is_typing", @"Vector", nil), [names objectAtIndex:0]]; + text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_one_user_is_typing", @"Vector", nil), names[0]]; } else if (2 == names.count) { - text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_two_users_are_typing", @"Vector", nil), [names objectAtIndex:0], [names objectAtIndex:1]]; + text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_two_users_are_typing", @"Vector", nil), names[0], names[1]]; } else { - text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_many_users_are_typing", @"Vector", nil), [names objectAtIndex:0], [names objectAtIndex:1]]; + text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_many_users_are_typing", @"Vector", nil), names[0], names[1]]; } [((RoomActivitiesView*) self.activitiesView) displayTypingNotification:text]; @@ -3985,7 +3985,7 @@ NSLog(@"[RoomVC] onOngoingConferenceCallPressed (jitsi)"); __weak __typeof(self) weakSelf = self; - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; // Check app permissions first [MXKTools checkAccessForCall:video diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index e3fcf752a..565d656dc 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -713,9 +713,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti NSString *currentCanonicalAlias = mxRoomState.canonicalAlias; NSString *canonicalAlias; - if ([updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]) + if (updatedItemsDict[kRoomSettingsCanonicalAliasKey]) { - canonicalAlias = [updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]; + canonicalAlias = updatedItemsDict[kRoomSettingsCanonicalAliasKey]; } else { @@ -849,7 +849,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti if (directoryVisibilitySwitch) { // Check a potential user's change before the end of the request - MXRoomDirectoryVisibility modifiedDirectoryVisibility = [updatedItemsDict objectForKey:kRoomSettingsDirectoryKey]; + MXRoomDirectoryVisibility modifiedDirectoryVisibility = updatedItemsDict[kRoomSettingsDirectoryKey]; if (modifiedDirectoryVisibility) { if ([modifiedDirectoryVisibility isEqualToString:directoryVisibility]) @@ -882,7 +882,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Refresh here the related communities list. [relatedGroups removeAllObjects]; [relatedGroups addObjectsFromArray:mxRoomState.relatedGroups]; - NSArray *removedCommunities = [updatedItemsDict objectForKey:kRoomSettingsRemovedRelatedGroupKey]; + NSArray *removedCommunities = updatedItemsDict[kRoomSettingsRemovedRelatedGroupKey]; if (removedCommunities.count) { for (NSUInteger index = 0; index < relatedGroups.count;) @@ -900,7 +900,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } } } - NSArray *communities = [updatedItemsDict objectForKey:kRoomSettingsNewRelatedGroupKey]; + NSArray *communities = updatedItemsDict[kRoomSettingsNewRelatedGroupKey]; if (communities) { [relatedGroups addObjectsFromArray:communities]; @@ -947,7 +947,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Check whether the topic has been actually changed if ((topic || currentTopic) && ([topic isEqualToString:currentTopic] == NO)) { - [updatedItemsDict setObject:(topic ? topic : @"") forKey:kRoomSettingsTopicKey]; + updatedItemsDict[kRoomSettingsTopicKey] = topic ? topic : @""; } else { @@ -1098,7 +1098,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Check whether the name has been actually changed if ((displayName || currentName) && ([displayName isEqualToString:currentName] == NO)) { - [updatedItemsDict setObject:(displayName ? displayName : @"") forKey:kRoomSettingsNameKey]; + updatedItemsDict[kRoomSettingsNameKey] = displayName ? displayName : @""; } else { @@ -1187,10 +1187,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // check if there is some updates related to room state if (mxRoomState) { - if ([updatedItemsDict objectForKey:kRoomSettingsAvatarKey]) + if (updatedItemsDict[kRoomSettingsAvatarKey]) { // Retrieve the current picture and make sure its orientation is up - UIImage *updatedPicture = [MXKTools forceImageOrientationUp:[updatedItemsDict objectForKey:kRoomSettingsAvatarKey]]; + UIImage *updatedPicture = [MXKTools forceImageOrientationUp:updatedItemsDict[kRoomSettingsAvatarKey]]; // Upload picture uploader = [MXMediaManager prepareUploaderWithMatrixSession:mxRoom.mxSession initialRange:0 andRange:1.0]; @@ -1204,7 +1204,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti self->uploader = nil; [self->updatedItemsDict removeObjectForKey:kRoomSettingsAvatarKey]; - [self->updatedItemsDict setObject:url forKey:kRoomSettingsAvatarURLKey]; + self->updatedItemsDict[kRoomSettingsAvatarURLKey] = url; [self onSave:nil]; } @@ -1236,7 +1236,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti return; } - NSString* photoUrl = [updatedItemsDict objectForKey:kRoomSettingsAvatarURLKey]; + NSString* photoUrl = updatedItemsDict[kRoomSettingsAvatarURLKey]; if (photoUrl) { pendingOperation = [mxRoom setAvatar:photoUrl success:^{ @@ -1278,7 +1278,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // has a new room name - NSString* roomName = [updatedItemsDict objectForKey:kRoomSettingsNameKey]; + NSString* roomName = updatedItemsDict[kRoomSettingsNameKey]; if (roomName) { pendingOperation = [mxRoom setName:roomName success:^{ @@ -1320,7 +1320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // has a new room topic - NSString* roomTopic = [updatedItemsDict objectForKey:kRoomSettingsTopicKey]; + NSString* roomTopic = updatedItemsDict[kRoomSettingsTopicKey]; if (roomTopic) { pendingOperation = [mxRoom setTopic:roomTopic success:^{ @@ -1362,7 +1362,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Room guest access - MXRoomGuestAccess guestAccess = [updatedItemsDict objectForKey:kRoomSettingsGuestAccessKey]; + MXRoomGuestAccess guestAccess = updatedItemsDict[kRoomSettingsGuestAccessKey]; if (guestAccess) { pendingOperation = [mxRoom setGuestAccess:guestAccess success:^{ @@ -1404,7 +1404,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Room join rule - MXRoomJoinRule joinRule = [updatedItemsDict objectForKey:kRoomSettingsJoinRuleKey]; + MXRoomJoinRule joinRule = updatedItemsDict[kRoomSettingsJoinRuleKey]; if (joinRule) { pendingOperation = [mxRoom setJoinRule:joinRule success:^{ @@ -1446,7 +1446,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // History visibility - MXRoomHistoryVisibility visibility = [updatedItemsDict objectForKey:kRoomSettingsHistoryVisibilityKey]; + MXRoomHistoryVisibility visibility = updatedItemsDict[kRoomSettingsHistoryVisibilityKey]; if (visibility) { pendingOperation = [mxRoom setHistoryVisibility:visibility success:^{ @@ -1488,7 +1488,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Room addresses - NSMutableArray *aliases = [updatedItemsDict objectForKey:kRoomSettingsNewAliasesKey]; + NSMutableArray *aliases = updatedItemsDict[kRoomSettingsNewAliasesKey]; if (aliases.count) { NSString *roomAlias = aliases.firstObject; @@ -1504,7 +1504,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti if (aliases.count > 1) { [aliases removeObjectAtIndex:0]; - [self->updatedItemsDict setObject:aliases forKey:kRoomSettingsNewAliasesKey]; + self->updatedItemsDict[kRoomSettingsNewAliasesKey] = aliases; } else { @@ -1541,7 +1541,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti return; } - aliases = [updatedItemsDict objectForKey:kRoomSettingsRemovedAliasesKey]; + aliases = updatedItemsDict[kRoomSettingsRemovedAliasesKey]; if (aliases.count) { NSString *roomAlias = aliases.firstObject; @@ -1557,7 +1557,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti if (aliases.count > 1) { [aliases removeObjectAtIndex:0]; - [self->updatedItemsDict setObject:aliases forKey:kRoomSettingsRemovedAliasesKey]; + self->updatedItemsDict[kRoomSettingsRemovedAliasesKey] = aliases; } else { @@ -1594,7 +1594,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti return; } - NSString* canonicalAlias = [updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]; + NSString* canonicalAlias = updatedItemsDict[kRoomSettingsCanonicalAliasKey]; if (canonicalAlias) { pendingOperation = [mxRoom setCanonicalAlias:canonicalAlias success:^{ @@ -1636,7 +1636,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Related groups - if ([updatedItemsDict objectForKey:kRoomSettingsNewRelatedGroupKey] || [updatedItemsDict objectForKey:kRoomSettingsRemovedRelatedGroupKey]) + if (updatedItemsDict[kRoomSettingsNewRelatedGroupKey] || updatedItemsDict[kRoomSettingsRemovedRelatedGroupKey]) { [self refreshRelatedGroups]; @@ -1683,7 +1683,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Update here other room settings - NSString *roomTag = [updatedItemsDict objectForKey:kRoomSettingsTagKey]; + NSString *roomTag = updatedItemsDict[kRoomSettingsTagKey]; if (roomTag) { if (!roomTag.length) @@ -1706,9 +1706,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti return; } - if ([updatedItemsDict objectForKey:kRoomSettingsMuteNotifKey]) + if (updatedItemsDict[kRoomSettingsMuteNotifKey]) { - if (((NSNumber*)[updatedItemsDict objectForKey:kRoomSettingsMuteNotifKey]).boolValue) + if (((NSNumber*) updatedItemsDict[kRoomSettingsMuteNotifKey]).boolValue) { [mxRoom mentionsOnly:^{ @@ -1739,9 +1739,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti return; } - if ([updatedItemsDict objectForKey:kRoomSettingsDirectChatKey]) + if (updatedItemsDict[kRoomSettingsDirectChatKey]) { - pendingOperation = [mxRoom setIsDirect:((NSNumber*)[updatedItemsDict objectForKey:kRoomSettingsDirectChatKey]).boolValue withUserId:nil success:^{ + pendingOperation = [mxRoom setIsDirect:((NSNumber*) updatedItemsDict[kRoomSettingsDirectChatKey]).boolValue withUserId:nil success:^{ if (weakSelf) { @@ -1752,7 +1752,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [self onSave:nil]; } - } failure:^(NSError *error) { + } failure:^(NSError *error) { NSLog(@"[RoomSettingsViewController] Altering DMness failed"); @@ -1779,7 +1779,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Room directory visibility - MXRoomDirectoryVisibility directoryVisibility = [updatedItemsDict objectForKey:kRoomSettingsDirectoryKey]; + MXRoomDirectoryVisibility directoryVisibility = updatedItemsDict[kRoomSettingsDirectoryKey]; if (directoryVisibility) { [mxRoom setDirectoryVisibility:directoryVisibility success:^{ @@ -1820,7 +1820,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Room encryption - if ([updatedItemsDict objectForKey:kRoomSettingsEncryptionKey]) + if (updatedItemsDict[kRoomSettingsEncryptionKey]) { pendingOperation = [mxRoom enableEncryptionWithAlgorithm:kMXCryptoMegolmAlgorithm success:^{ @@ -1862,7 +1862,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } // Room settings on blacklist unverified devices - if ([updatedItemsDict objectForKey:kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) + if (updatedItemsDict[kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) { BOOL blacklistUnverifiedDevices = [((NSNumber*)updatedItemsDict[kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) boolValue]; [mxRoom.mxSession.crypto setBlacklistUnverifiedDevicesInRoom:mxRoom.roomId blacklist:blacklistUnverifiedDevices]; @@ -1884,7 +1884,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [roomAddresses removeAllObjects]; localAddressesCount = 0; - NSArray *removedAliases = [updatedItemsDict objectForKey:kRoomSettingsRemovedAliasesKey]; + NSArray *removedAliases = updatedItemsDict[kRoomSettingsRemovedAliasesKey]; NSArray *aliases = mxRoomState.aliases; if (aliases) @@ -1908,7 +1908,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } } - aliases = [updatedItemsDict objectForKey:kRoomSettingsNewAliasesKey]; + aliases = updatedItemsDict[kRoomSettingsNewAliasesKey]; for (NSString *alias in aliases) { // Add this new alias to local addresses @@ -1938,7 +1938,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti count = ROOM_SETTINGS_ROOM_ACCESS_SECTION_ROW_SUB_COUNT; // Check whether a room address is required for the current join rule - NSString *joinRule = [updatedItemsDict objectForKey:kRoomSettingsJoinRuleKey]; + NSString *joinRule = updatedItemsDict[kRoomSettingsJoinRuleKey]; if (!joinRule) { // Use the actual values if no change is pending. @@ -2126,9 +2126,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomNotifCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_mute_notifs", @"Vector", nil); - if ([updatedItemsDict objectForKey:kRoomSettingsMuteNotifKey]) + if (updatedItemsDict[kRoomSettingsMuteNotifKey]) { - roomNotifCell.mxkSwitch.on = ((NSNumber*)[updatedItemsDict objectForKey:kRoomSettingsMuteNotifKey]).boolValue; + roomNotifCell.mxkSwitch.on = ((NSNumber*) updatedItemsDict[kRoomSettingsMuteNotifKey]).boolValue; } else { @@ -2145,9 +2145,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomDirectChat.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_direct_chat", @"Vector", nil); - if ([updatedItemsDict objectForKey:kRoomSettingsDirectChatKey]) + if (updatedItemsDict[kRoomSettingsDirectChatKey]) { - roomDirectChat.mxkSwitch.on = ((NSNumber*)[updatedItemsDict objectForKey:kRoomSettingsDirectChatKey]).boolValue; + roomDirectChat.mxkSwitch.on = ((NSNumber*) updatedItemsDict[kRoomSettingsDirectChatKey]).boolValue; } else { @@ -2179,9 +2179,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomPhotoCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_photo", @"Vector", nil); roomPhotoCell.mxkLabel.textColor = kRiotPrimaryTextColor; - if ([updatedItemsDict objectForKey:kRoomSettingsAvatarKey]) + if (updatedItemsDict[kRoomSettingsAvatarKey]) { - roomPhotoCell.mxkImageView.image = (UIImage*)[updatedItemsDict objectForKey:kRoomSettingsAvatarKey]; + roomPhotoCell.mxkImageView.image = (UIImage*) updatedItemsDict[kRoomSettingsAvatarKey]; } else { @@ -2203,9 +2203,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView = roomTopicCell.textView; - if ([updatedItemsDict objectForKey:kRoomSettingsTopicKey]) + if (updatedItemsDict[kRoomSettingsTopicKey]) { - topicTextView.text = (NSString*)[updatedItemsDict objectForKey:kRoomSettingsTopicKey]; + topicTextView.text = (NSString*) updatedItemsDict[kRoomSettingsTopicKey]; } else { @@ -2247,9 +2247,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti nameTextField.textAlignment = NSTextAlignmentRight; nameTextField.delegate = self; - if ([updatedItemsDict objectForKey:kRoomSettingsNameKey]) + if (updatedItemsDict[kRoomSettingsNameKey]) { - nameTextField.text = (NSString*)[updatedItemsDict objectForKey:kRoomSettingsNameKey]; + nameTextField.text = (NSString*) updatedItemsDict[kRoomSettingsNameKey]; } else { @@ -2285,9 +2285,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti label.textColor = kRiotPrimaryTextColor; label.text = NSLocalizedStringFromTable(@"room_details_low_priority_tag", @"Vector", nil); - if ([updatedItemsDict objectForKey:kRoomSettingsTagKey]) + if (updatedItemsDict[kRoomSettingsTagKey]) { - NSString *roomTag = [updatedItemsDict objectForKey:kRoomSettingsTagKey]; + NSString *roomTag = updatedItemsDict[kRoomSettingsTagKey]; if ([roomTag isEqualToString:kMXRoomTagFavourite]) { [roomTagCell setCheckBoxValue:YES atIndex:0]; @@ -2338,9 +2338,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [directoryToggleCell.mxkSwitch addTarget:self action:@selector(toggleDirectoryVisibility:) forControlEvents:UIControlEventValueChanged]; - if ([updatedItemsDict objectForKey:kRoomSettingsDirectoryKey]) + if (updatedItemsDict[kRoomSettingsDirectoryKey]) { - directoryToggleCell.mxkSwitch.on = ((NSNumber*)[updatedItemsDict objectForKey:kRoomSettingsDirectoryKey]).boolValue; + directoryToggleCell.mxkSwitch.on = ((NSNumber*) updatedItemsDict[kRoomSettingsDirectoryKey]).boolValue; } else { @@ -2375,8 +2375,8 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomAccessCell.checkBoxLeadingConstraint.constant = roomAccessCell.separatorInset.left; // Retrieve the potential updated values for joinRule and guestAccess - NSString *joinRule = [updatedItemsDict objectForKey:kRoomSettingsJoinRuleKey]; - NSString *guestAccess = [updatedItemsDict objectForKey:kRoomSettingsGuestAccessKey]; + NSString *joinRule = updatedItemsDict[kRoomSettingsJoinRuleKey]; + NSString *guestAccess = updatedItemsDict[kRoomSettingsGuestAccessKey]; // Use the actual values if no change is pending if (!joinRule) @@ -2427,7 +2427,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti historyVisibilityCell.checkBoxLeadingConstraint.constant = historyVisibilityCell.separatorInset.left; // Retrieve first the potential updated value for history visibility - NSString *visibility = [updatedItemsDict objectForKey:kRoomSettingsHistoryVisibilityKey]; + NSString *visibility = updatedItemsDict[kRoomSettingsHistoryVisibilityKey]; // Use the actual value if no change is pending if (!visibility) @@ -2442,7 +2442,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti historyVisibilityCell.enabled = ([visibility isEqualToString:kMXRoomHistoryVisibilityWorldReadable]); - [historyVisibilityTickCells setObject:historyVisibilityCell forKey:kMXRoomHistoryVisibilityWorldReadable]; + historyVisibilityTickCells[kMXRoomHistoryVisibilityWorldReadable] = historyVisibilityCell; } else if (indexPath.row == ROOM_SETTINGS_HISTORY_VISIBILITY_SECTION_ROW_MEMBERS_ONLY) { @@ -2451,7 +2451,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti historyVisibilityCell.enabled = ([visibility isEqualToString:kMXRoomHistoryVisibilityShared]); - [historyVisibilityTickCells setObject:historyVisibilityCell forKey:kMXRoomHistoryVisibilityShared]; + historyVisibilityTickCells[kMXRoomHistoryVisibilityShared] = historyVisibilityCell; } else if (indexPath.row == ROOM_SETTINGS_HISTORY_VISIBILITY_SECTION_ROW_MEMBERS_ONLY_SINCE_INVITED) { @@ -2460,7 +2460,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti historyVisibilityCell.enabled = ([visibility isEqualToString:kMXRoomHistoryVisibilityInvited]); - [historyVisibilityTickCells setObject:historyVisibilityCell forKey:kMXRoomHistoryVisibilityInvited]; + historyVisibilityTickCells[kMXRoomHistoryVisibilityInvited] = historyVisibilityCell; } else if (indexPath.row == ROOM_SETTINGS_HISTORY_VISIBILITY_SECTION_ROW_MEMBERS_ONLY_SINCE_JOINED) { @@ -2469,7 +2469,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti historyVisibilityCell.enabled = ([visibility isEqualToString:kMXRoomHistoryVisibilityJoined]); - [historyVisibilityTickCells setObject:historyVisibilityCell forKey:kMXRoomHistoryVisibilityJoined]; + historyVisibilityTickCells[kMXRoomHistoryVisibilityJoined] = historyVisibilityCell; } // Check whether the user can change this option @@ -2544,9 +2544,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti NSString *alias = roomAddresses[row]; NSString *canonicalAlias; - if ([updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]) + if (updatedItemsDict[kRoomSettingsCanonicalAliasKey]) { - canonicalAlias = [updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]; + canonicalAlias = updatedItemsDict[kRoomSettingsCanonicalAliasKey]; } else { @@ -2690,7 +2690,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { roomBlacklistUnverifiedDevicesCell.mxkSwitch.enabled = YES; - if ([updatedItemsDict objectForKey:kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) + if (updatedItemsDict[kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) { blacklistUnverifiedDevices = [((NSNumber*)updatedItemsDict[kRoomSettingsEncryptionBlacklistUnverifiedDevicesKey]) boolValue]; } @@ -2737,7 +2737,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomEncryptionCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_enable_e2e_encryption", @"Vector", nil); - roomEncryptionCell.mxkSwitch.on = ([updatedItemsDict objectForKey:kRoomSettingsEncryptionKey] != nil); + roomEncryptionCell.mxkSwitch.on = (updatedItemsDict[kRoomSettingsEncryptionKey] != nil); cell = roomEncryptionCell; } @@ -2886,7 +2886,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:kMXRoomJoinRuleInvite forKey:kRoomSettingsJoinRuleKey]; + updatedItemsDict[kRoomSettingsJoinRuleKey] = kMXRoomJoinRuleInvite; // Update guest access to allow guest on invitation. // Note: if guest_access is "forbidden" here, guests cannot join this room even if explicitly invited. @@ -2896,7 +2896,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:kMXRoomGuestAccessCanJoin forKey:kRoomSettingsGuestAccessKey]; + updatedItemsDict[kRoomSettingsGuestAccessKey] = kMXRoomGuestAccessCanJoin; } } @@ -2929,7 +2929,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:kMXRoomJoinRulePublic forKey:kRoomSettingsJoinRuleKey]; + updatedItemsDict[kRoomSettingsJoinRuleKey] = kMXRoomJoinRulePublic; } if ([mxRoomState.guestAccess isEqualToString:kMXRoomGuestAccessForbidden]) @@ -2938,7 +2938,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:kMXRoomGuestAccessForbidden forKey:kRoomSettingsGuestAccessKey]; + updatedItemsDict[kRoomSettingsGuestAccessKey] = kMXRoomGuestAccessForbidden; } } @@ -2971,7 +2971,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:kMXRoomJoinRulePublic forKey:kRoomSettingsJoinRuleKey]; + updatedItemsDict[kRoomSettingsJoinRuleKey] = kMXRoomJoinRulePublic; } if ([mxRoomState.guestAccess isEqualToString:kMXRoomGuestAccessCanJoin]) @@ -2980,7 +2980,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:kMXRoomGuestAccessCanJoin forKey:kRoomSettingsGuestAccessKey]; + updatedItemsDict[kRoomSettingsGuestAccessKey] = kMXRoomGuestAccessCanJoin; } } @@ -3201,7 +3201,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:historyVisibility forKey:kRoomSettingsHistoryVisibilityKey]; + updatedItemsDict[kRoomSettingsHistoryVisibilityKey] = historyVisibility; } [self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0); @@ -3259,7 +3259,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Remove the canonical address if (self->mxRoomState.canonicalAlias.length) { - [self->updatedItemsDict setObject:@"" forKey:kRoomSettingsCanonicalAliasKey]; + self->updatedItemsDict[kRoomSettingsCanonicalAliasKey] = @""; } else { @@ -3305,7 +3305,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { [self getNavigationItem].rightBarButtonItem.enabled = YES; - [updatedItemsDict setObject:image forKey:kRoomSettingsAvatarKey]; + updatedItemsDict[kRoomSettingsAvatarKey] = image; [self refreshRoomSettings]; } @@ -3401,7 +3401,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:[NSNumber numberWithBool:theSwitch.on] forKey:kRoomSettingsMuteNotifKey]; + updatedItemsDict[kRoomSettingsMuteNotifKey] = @(theSwitch.on); } [self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0); @@ -3415,7 +3415,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:[NSNumber numberWithBool:theSwitch.on] forKey:kRoomSettingsDirectChatKey]; + updatedItemsDict[kRoomSettingsDirectChatKey] = @(theSwitch.on); } [self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0); @@ -3458,7 +3458,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti typeof(self) self = weakSelf; self->currentAlert = nil; - [self->updatedItemsDict setObject:@(YES) forKey:kRoomSettingsEncryptionKey]; + self->updatedItemsDict[kRoomSettingsEncryptionKey] = @(YES); [self getNavigationItem].rightBarButtonItem.enabled = self->updatedItemsDict.count; } @@ -3504,12 +3504,12 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:visibility forKey:kRoomSettingsDirectoryKey]; + updatedItemsDict[kRoomSettingsDirectoryKey] = visibility; } } else { - [updatedItemsDict setObject:visibility forKey:kRoomSettingsDirectoryKey]; + updatedItemsDict[kRoomSettingsDirectoryKey] = visibility; } [self getNavigationItem].rightBarButtonItem.enabled = (updatedItemsDict.count != 0); @@ -3526,7 +3526,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:alias forKey:kRoomSettingsCanonicalAliasKey]; + updatedItemsDict[kRoomSettingsCanonicalAliasKey] = alias; } NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:ROOM_SETTINGS_ROOM_ADDRESSES_SECTION_INDEX]; @@ -3559,9 +3559,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { NSString *canonicalAlias; - if ([updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]) + if (updatedItemsDict[kRoomSettingsCanonicalAliasKey]) { - canonicalAlias = [updatedItemsDict objectForKey:kRoomSettingsCanonicalAliasKey]; + canonicalAlias = updatedItemsDict[kRoomSettingsCanonicalAliasKey]; } else { @@ -3582,7 +3582,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti else { // Check whether the alias has just been added - NSMutableArray *addedAlias = [updatedItemsDict objectForKey:kRoomSettingsNewAliasesKey]; + NSMutableArray *addedAlias = updatedItemsDict[kRoomSettingsNewAliasesKey]; if (addedAlias && [addedAlias indexOfObject:roomAlias] != NSNotFound) { [addedAlias removeObject:roomAlias]; @@ -3594,11 +3594,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - NSMutableArray *removedAlias = [updatedItemsDict objectForKey:kRoomSettingsRemovedAliasesKey]; + NSMutableArray *removedAlias = updatedItemsDict[kRoomSettingsRemovedAliasesKey]; if (!removedAlias) { removedAlias = [NSMutableArray array]; - [updatedItemsDict setObject:removedAlias forKey:kRoomSettingsRemovedAliasesKey]; + updatedItemsDict[kRoomSettingsRemovedAliasesKey] = removedAlias; } [removedAlias addObject:roomAlias]; @@ -3622,7 +3622,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)removeCommunity:(NSString*)groupId { // Check whether the alias has just been added - NSMutableArray *addedGroup = [updatedItemsDict objectForKey:kRoomSettingsNewRelatedGroupKey]; + NSMutableArray *addedGroup = updatedItemsDict[kRoomSettingsNewRelatedGroupKey]; if (addedGroup && [addedGroup indexOfObject:groupId] != NSNotFound) { [addedGroup removeObject:groupId]; @@ -3634,11 +3634,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - NSMutableArray *removedGroup = [updatedItemsDict objectForKey:kRoomSettingsRemovedRelatedGroupKey]; + NSMutableArray *removedGroup = updatedItemsDict[kRoomSettingsRemovedRelatedGroupKey]; if (!removedGroup) { removedGroup = [NSMutableArray array]; - [updatedItemsDict setObject:removedGroup forKey:kRoomSettingsRemovedRelatedGroupKey]; + updatedItemsDict[kRoomSettingsRemovedRelatedGroupKey] = removedGroup; } [removedGroup addObject:groupId]; @@ -3656,7 +3656,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti if ([MXTools isMatrixRoomAlias:roomAlias]) { // Check whether this alias has just been deleted - NSMutableArray *removedAlias = [updatedItemsDict objectForKey:kRoomSettingsRemovedAliasesKey]; + NSMutableArray *removedAlias = updatedItemsDict[kRoomSettingsRemovedAliasesKey]; if (removedAlias && [removedAlias indexOfObject:roomAlias] != NSNotFound) { [removedAlias removeObject:roomAlias]; @@ -3669,11 +3669,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Check whether this alias is not already defined for this room else if ([roomAddresses indexOfObject:roomAlias] == NSNotFound) { - NSMutableArray *addedAlias = [updatedItemsDict objectForKey:kRoomSettingsNewAliasesKey]; + NSMutableArray *addedAlias = updatedItemsDict[kRoomSettingsNewAliasesKey]; if (!addedAlias) { addedAlias = [NSMutableArray array]; - [updatedItemsDict setObject:addedAlias forKey:kRoomSettingsNewAliasesKey]; + updatedItemsDict[kRoomSettingsNewAliasesKey] = addedAlias; } [addedAlias addObject:roomAlias]; @@ -3693,7 +3693,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:roomAlias forKey:kRoomSettingsCanonicalAliasKey]; + updatedItemsDict[kRoomSettingsCanonicalAliasKey] = roomAlias; } if (missingAddressWarningIndex != -1) @@ -3746,7 +3746,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti if ([MXTools isMatrixGroupIdentifier:groupId]) { // Check whether this group has just been deleted - NSMutableArray *removedGroups = [updatedItemsDict objectForKey:kRoomSettingsRemovedRelatedGroupKey]; + NSMutableArray *removedGroups = updatedItemsDict[kRoomSettingsRemovedRelatedGroupKey]; if (removedGroups && [removedGroups indexOfObject:groupId] != NSNotFound) { [removedGroups removeObject:groupId]; @@ -3759,11 +3759,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Check whether this alias is not already defined for this room else if ([relatedGroups indexOfObject:groupId] == NSNotFound) { - NSMutableArray *addedGroup = [updatedItemsDict objectForKey:kRoomSettingsNewRelatedGroupKey]; + NSMutableArray *addedGroup = updatedItemsDict[kRoomSettingsNewRelatedGroupKey]; if (!addedGroup) { addedGroup = [NSMutableArray array]; - [updatedItemsDict setObject:addedGroup forKey:kRoomSettingsNewRelatedGroupKey]; + updatedItemsDict[kRoomSettingsNewRelatedGroupKey] = addedGroup; } [addedGroup addObject:groupId]; @@ -3819,7 +3819,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { // The user wants to unselect this tag // Retrieve the current change on room tag (if any) - NSString *updatedRoomTag = [updatedItemsDict objectForKey:kRoomSettingsTagKey]; + NSString *updatedRoomTag = updatedItemsDict[kRoomSettingsTagKey]; // Check the actual tag on mxRoom if (mxRoom.accountData.tags[tappedRoomTag]) @@ -3827,7 +3827,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // The actual tag must be updated, check whether another tag is already set if (!updatedRoomTag) { - [updatedItemsDict setObject:@"" forKey:kRoomSettingsTagKey]; + updatedItemsDict[kRoomSettingsTagKey] = @""; } } else if (updatedRoomTag && [updatedRoomTag isEqualToString:tappedRoomTag]) @@ -3835,7 +3835,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // Cancel the updated tag, but take into account the cancellation of another tag when 'tappedRoomTag' was selected. if (mxRoom.accountData.tags.count) { - [updatedItemsDict setObject:@"" forKey:kRoomSettingsTagKey]; + updatedItemsDict[kRoomSettingsTagKey] = @""; } else { @@ -3856,7 +3856,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } else { - [updatedItemsDict setObject:tappedRoomTag forKey:kRoomSettingsTagKey]; + updatedItemsDict[kRoomSettingsTagKey] = tappedRoomTag; } // Select the tapped tag diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index cd55bd79f..37441f08c 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1224,7 +1224,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { if ([AppDelegate theDelegate].mxSessions.count > 0) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; count = session.ignoredUsers.count; } else @@ -1383,7 +1383,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); return cell; } - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; if (section == SETTINGS_SECTION_SIGN_OUT_INDEX) @@ -1626,7 +1626,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); if (!countryCode) { // If none, consider the preferred locale - NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]]; + NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[NSBundle mainBundle] preferredLocalizations][0]]; if ([local respondsToSelector:@selector(countryCode)]) { countryCode = local.countryCode; @@ -1715,7 +1715,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { MXKTableViewCell *globalInfoCell = [self getDefaultTableViewCell:tableView]; - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; globalInfoCell.textLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"settings_global_settings_info", @"Vector", nil), appDisplayName]; globalInfoCell.textLabel.numberOfLines = 0; @@ -1872,7 +1872,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); } NSString* countryCode = [[MXKAppSettings standardAppSettings] phonebookCountryCode]; - NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[[NSBundle mainBundle] preferredLocalizations] objectAtIndex:0]]; + NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[NSBundle mainBundle] preferredLocalizations][0]]; NSString *countryName = [local displayNameForKey:NSLocaleCountryCode value:countryCode]; cell.textLabel.textColor = kRiotPrimaryTextColor; @@ -2086,7 +2086,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); } else if (row == LABS_CRYPTO_INDEX) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; @@ -2252,7 +2252,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Check whether this section is visible if ([AppDelegate theDelegate].mxSessions.count > 0) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; if (session.ignoredUsers.count) { return NSLocalizedStringFromTable(@"settings_ignored_users", @"Vector", nil); @@ -2379,7 +2379,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { if ([AppDelegate theDelegate].mxSessions.count > 0) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; if (session.ignoredUsers.count == 0) { // Hide this section @@ -2411,7 +2411,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { if ([AppDelegate theDelegate].mxSessions.count > 0) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; if (session.ignoredUsers.count == 0) { // Hide this section @@ -2492,7 +2492,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); } else if (section == SETTINGS_SECTION_IGNORED_USERS_INDEX) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; NSString *ignoredUserId; if (indexPath.row < session.ignoredUsers.count) @@ -2517,7 +2517,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); typeof(self) self = weakSelf; self->currentAlert = nil; - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; // Remove the member from the ignored user list [self startActivityIndicator]; @@ -2794,7 +2794,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); __weak typeof(self) weakSelf = self; - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; currentAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:NSLocalizedStringFromTable(@"settings_on_denied_notification", @"Vector", nil), appDisplayName] message:nil preferredStyle:UIAlertControllerStyleAlert]; @@ -3048,7 +3048,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { [self startActivityIndicator]; - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; [session enableCrypto:switchButton.isOn success:^{ // When disabling crypto, reset the current device id as it cannot be reused. @@ -3478,7 +3478,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Dismiss the keyboard [newEmailTextField resignFirstResponder]; - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; MXK3PID *new3PID = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumEmail andAddress:newEmailTextField.text]; [new3PID requestValidationTokenWithMatrixRestClient:session.matrixRestClient isDuringRegistration:NO nextLink:nil success:^{ @@ -3569,7 +3569,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Dismiss the keyboard [newPhoneNumberCell.mxkTextField resignFirstResponder]; - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; NSString *e164 = [[NBPhoneNumberUtil sharedInstance] format:newPhoneNumber numberFormat:NBEPhoneNumberFormatE164 error:nil]; NSString *msisdn; @@ -3635,7 +3635,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { if ([AppDelegate theDelegate].mxSessions.count > 0) { - MXSession* session = [[AppDelegate theDelegate].mxSessions objectAtIndex:0]; + MXSession* session = [AppDelegate theDelegate].mxSessions[0]; MXMyUser* myUser = session.myUser; BOOL saveButtonEnabled = (nil != newAvatarImage); diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index d55a50f60..939d8f3cc 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -257,7 +257,7 @@ if (identifiers.count) { // Here the contact can only have one identifier - [contactsDataSource.ignoredContactsByMatrixId setObject:contact forKey:identifiers.firstObject]; + contactsDataSource.ignoredContactsByMatrixId[identifiers.firstObject] = contact; } else { @@ -266,7 +266,7 @@ { // Here the contact can only have one email MXKEmail *email = emails.firstObject; - [contactsDataSource.ignoredContactsByEmail setObject:contact forKey:email.emailAddress]; + contactsDataSource.ignoredContactsByEmail[email.emailAddress] = contact; } } isMultiUseNameByDisplayName[contact.displayName] = (isMultiUseNameByDisplayName[contact.displayName] ? @(YES) : @(NO)); @@ -274,7 +274,7 @@ if (userContact) { - [contactsDataSource.ignoredContactsByMatrixId setObject:userContact forKey:self.mainSession.myUser.userId]; + contactsDataSource.ignoredContactsByMatrixId[self.mainSession.myUser.userId] = userContact; } } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 1190e2ee6..ef16cd49a 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -74,11 +74,11 @@ // Do any additional setup after loading the view, typically from a nib. // Retrieve the all view controllers - _homeViewController = [self.viewControllers objectAtIndex:TABBAR_HOME_INDEX]; - _favouritesViewController = [self.viewControllers objectAtIndex:TABBAR_FAVOURITES_INDEX]; - _peopleViewController = [self.viewControllers objectAtIndex:TABBAR_PEOPLE_INDEX]; - _roomsViewController = [self.viewControllers objectAtIndex:TABBAR_ROOMS_INDEX]; - _groupsViewController = [self.viewControllers objectAtIndex:TABBAR_GROUPS_INDEX]; + _homeViewController = self.viewControllers[TABBAR_HOME_INDEX]; + _favouritesViewController = self.viewControllers[TABBAR_FAVOURITES_INDEX]; + _peopleViewController = self.viewControllers[TABBAR_PEOPLE_INDEX]; + _roomsViewController = self.viewControllers[TABBAR_ROOMS_INDEX]; + _groupsViewController = self.viewControllers[TABBAR_GROUPS_INDEX]; // Set the accessibility labels for all buttons #1842 [_settingsBarButtonItem setAccessibilityLabel:NSLocalizedStringFromTable(@"settings_title", @"Vector", nil)]; @@ -864,7 +864,7 @@ [currentAlert dismissViewControllerAnimated:NO completion:nil]; - NSString *appDisplayName = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleDisplayName"]; + NSString *appDisplayName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; currentAlert = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:NSLocalizedStringFromTable(@"google_analytics_use_prompt", @"Vector", nil), appDisplayName] message:nil preferredStyle:UIAlertControllerStyleAlert]; diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index 3d8bcd1eb..8cfc959f6 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -164,12 +164,12 @@ static UILabel* backgroundLabel = nil; imageByKeyDict = [[NSMutableDictionary alloc] init]; } - UIImage* image = [imageByKeyDict objectForKey:key]; + UIImage* image = imageByKeyDict[key]; if (!image) { - image = [AvatarGenerator imageFromText:firstChar withBackgroundColor:[colorsList objectAtIndex:colorIndex]]; - [imageByKeyDict setObject:image forKey:key]; + image = [AvatarGenerator imageFromText:firstChar withBackgroundColor:colorsList[colorIndex]]; + imageByKeyDict[key] = image; } return image; @@ -190,7 +190,7 @@ static UILabel* backgroundLabel = nil; NSString* firstChar = [AvatarGenerator firstChar:(displayname ? displayname : itemId)]; NSUInteger colorIndex = [AvatarGenerator colorIndexForText:itemId]; - return [AvatarGenerator imageFromText:firstChar withBackgroundColor:[colorsList objectAtIndex:colorIndex] size:size andFontSize:fontSize]; + return [AvatarGenerator imageFromText:firstChar withBackgroundColor:colorsList[colorIndex] size:size andFontSize:fontSize]; } + (void)clear diff --git a/RiotShareExtension/Managers/ShareExtensionManager.m b/RiotShareExtension/Managers/ShareExtensionManager.m index 182a9481c..27927a0c8 100644 --- a/RiotShareExtension/Managers/ShareExtensionManager.m +++ b/RiotShareExtension/Managers/ShareExtensionManager.m @@ -837,7 +837,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) - (void)setIsLoaded:(BOOL)isLoaded { - NSNumber *number = [NSNumber numberWithBool:isLoaded]; + NSNumber *number = @(isLoaded); objc_setAssociatedObject(self, @selector(isLoaded), number, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } diff --git a/RiotShareExtension/Modules/Share/ShareViewController.m b/RiotShareExtension/Modules/Share/ShareViewController.m index 6f6b785f7..5d8aa81fd 100644 --- a/RiotShareExtension/Modules/Share/ShareViewController.m +++ b/RiotShareExtension/Modules/Share/ShareViewController.m @@ -102,7 +102,7 @@ else { NSDictionary *infoDictionary = [NSBundle mainBundle].infoDictionary; - NSString *bundleDisplayName = [infoDictionary objectForKey:@"CFBundleDisplayName"]; + NSString *bundleDisplayName = infoDictionary[@"CFBundleDisplayName"]; self.tittleLabel.text = bundleDisplayName; [self configureFallbackViewController]; } diff --git a/SiriIntents/IntentHandler.m b/SiriIntents/IntentHandler.m index 3a657cb69..9d32a284b 100644 --- a/SiriIntents/IntentHandler.m +++ b/SiriIntents/IntentHandler.m @@ -330,7 +330,7 @@ if (userRoomSummaries) [userRoomSummaries addObject:summary]; else - roomSummaries[diretUserId] = [NSMutableArray arrayWithObject:summary]; + roomSummaries[diretUserId] = [@[summary] mutableCopy]; } } From 8d18316cb6e22dcfaf58f37945c7c86ef46d16c4 Mon Sep 17 00:00:00 2001 From: Fridtjof Mund <2780577+fridtjof@users.noreply.github.com> Date: Tue, 8 Jan 2019 00:29:30 +0100 Subject: [PATCH 023/244] Update CHANGES.rst --- CHANGES.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index ab116afcd..cbfb2944d 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,7 +2,8 @@ Changes in 0.7.10 (2019-01-04) =============================================== Improvements: -* Fix almost all the warnings caused by -Wstrict-prototypes, thanks to @fridtjof (PR #2155). + * Fix almost all the warnings caused by -Wstrict-prototypes, thanks to @fridtjof (PR #2155). + * Use modern literals and array/dictionary syntax where possible (PR #2160). Bug fix: * Share extension: Fix screenshot sharing (#2022). Improve image sharing performance to avoid out of memory crash. From ad5c446ba115c4c3b1a6d63aa9fb818fcc7dda4d Mon Sep 17 00:00:00 2001 From: Juho Ylikorpi Date: Tue, 8 Jan 2019 22:05:23 +0000 Subject: [PATCH 024/244] Added translation using Weblate (Finnish) --- Riot/Assets/fi.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) create mode 100644 Riot/Assets/fi.lproj/Vector.strings diff --git a/Riot/Assets/fi.lproj/Vector.strings b/Riot/Assets/fi.lproj/Vector.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Riot/Assets/fi.lproj/Vector.strings @@ -0,0 +1 @@ + From 04dc416077bfa23c3278bcc8b1957a44b8ae5499 Mon Sep 17 00:00:00 2001 From: Juho Ylikorpi Date: Tue, 8 Jan 2019 22:10:11 +0000 Subject: [PATCH 025/244] Added translation using Weblate (Finnish) --- Riot/Assets/fi.lproj/InfoPlist.strings | 1 + 1 file changed, 1 insertion(+) create mode 100644 Riot/Assets/fi.lproj/InfoPlist.strings diff --git a/Riot/Assets/fi.lproj/InfoPlist.strings b/Riot/Assets/fi.lproj/InfoPlist.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Riot/Assets/fi.lproj/InfoPlist.strings @@ -0,0 +1 @@ + From 43b4b311e1a81ce1aa8e917b84172810a1910312 Mon Sep 17 00:00:00 2001 From: Juho Ylikorpi Date: Tue, 8 Jan 2019 22:10:59 +0000 Subject: [PATCH 026/244] Added translation using Weblate (Finnish) --- Riot/Assets/fi.lproj/Localizable.strings | 1 + 1 file changed, 1 insertion(+) create mode 100644 Riot/Assets/fi.lproj/Localizable.strings diff --git a/Riot/Assets/fi.lproj/Localizable.strings b/Riot/Assets/fi.lproj/Localizable.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Riot/Assets/fi.lproj/Localizable.strings @@ -0,0 +1 @@ + From 71dd59016aae2699cfdd227025226d3891a36715 Mon Sep 17 00:00:00 2001 From: Juho Ylikorpi Date: Tue, 8 Jan 2019 22:16:20 +0000 Subject: [PATCH 027/244] Translated using Weblate (Finnish) Currently translated at 100.0% (4 of 4 strings) Translation: Riot iOS/Riot iOS (Dialogs) Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios-dialogs/fi/ --- Riot/Assets/fi.lproj/InfoPlist.strings | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/fi.lproj/InfoPlist.strings b/Riot/Assets/fi.lproj/InfoPlist.strings index 8b1378917..51988aa6f 100644 --- a/Riot/Assets/fi.lproj/InfoPlist.strings +++ b/Riot/Assets/fi.lproj/InfoPlist.strings @@ -1 +1,5 @@ - +// Permissions usage explanations +"NSCameraUsageDescription" = "Kameralla otetaan kuvia ja videota sekä soitetaan videopuheluita."; +"NSPhotoLibraryUsageDescription" = "Kuvakirjastoa käytetään kuvien ja videoiden lähetykseen."; +"NSMicrophoneUsageDescription" = "Mikrofonia käytetään puheluissa."; +"NSContactsUsageDescription" = "Jotta Riot ja Matrix yhteyshenkilösi voidaan näyttää, tulee sähköpostosoitteesi ja puhelinnumerosi lähettää identiteettipalvelimelle. New Vector ei tallenna tietoja. Tarvittaessa saat lisätietoja sovelluksen asetussivulta."; From 34cfac5399616cd55491641e8cc638b5e6cab38b Mon Sep 17 00:00:00 2001 From: fridtjof <2780577+fridtjof@users.noreply.github.com> Date: Wed, 9 Jan 2019 17:50:42 +0100 Subject: [PATCH 028/244] Allocate less objects --- SiriIntents/IntentHandler.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SiriIntents/IntentHandler.m b/SiriIntents/IntentHandler.m index 9d32a284b..3a657cb69 100644 --- a/SiriIntents/IntentHandler.m +++ b/SiriIntents/IntentHandler.m @@ -330,7 +330,7 @@ if (userRoomSummaries) [userRoomSummaries addObject:summary]; else - roomSummaries[diretUserId] = [@[summary] mutableCopy]; + roomSummaries[diretUserId] = [NSMutableArray arrayWithObject:summary]; } } From c89d54869b999f577695cbfcecf4db1cde9ff48b Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 14:47:58 +0100 Subject: [PATCH 029/244] reskin: Fix header display of room preview --- Riot/Modules/Room/RoomViewController.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 089e21e0c..b1147cd72 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1628,6 +1628,14 @@ } self.previewHeaderContainer.hidden = NO; + + // Consider the main navigation controller if the current view controller is embedded inside a split view controller. + UINavigationController *mainNavigationController = self.navigationController; + if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) + { + mainNavigationController = self.splitViewController.viewControllers.firstObject; + } + mainNavigationController.navigationBar.translucent = isVisible; // Finalize preview header display according to the screen orientation [self refreshPreviewHeader:UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])]; From 8fb45b1ebbd9ae14a6dbe2ac2c179134bd5a3448 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 15:12:24 +0100 Subject: [PATCH 030/244] reskin: Put back riot colors in the main tab bar icons --- Riot/Constants/RiotDesignValues.h | 2 ++ Riot/Constants/RiotDesignValues.m | 4 ++++ Riot/Modules/Communities/GroupsViewController.m | 1 + Riot/Modules/Favorites/FavouritesViewController.m | 2 +- Riot/Modules/People/PeopleViewController.m | 1 + Riot/Modules/Rooms/RoomsViewController.m | 3 +++ 6 files changed, 12 insertions(+), 1 deletion(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index a04497567..ba1ded424 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -52,6 +52,8 @@ extern UIColor *kRiotColorPinkRed; extern UIColor *kRiotColorRed; extern UIColor *kRiotColorBlue; extern UIColor *kRiotColorCuriousBlue; +extern UIColor *kRiotColorIndigo; +extern UIColor *kRiotColorOrange; #pragma mark - Riot Standard Room Member Power Level extern NSInteger const kRiotRoomModeratorLevel; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 0821e6d22..af81ce331 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -42,6 +42,8 @@ UIColor *kRiotColorPinkRed; UIColor *kRiotColorRed; UIColor *kRiotColorBlue; UIColor *kRiotColorCuriousBlue; +UIColor *kRiotColorIndigo; +UIColor *kRiotColorOrange; // Riot Background Colors UIColor *kRiotColorLightKeyboard; // TO REMOVE @@ -87,6 +89,8 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotColorRed = UIColorFromRGB(0xFF4444); kRiotColorBlue = UIColorFromRGB(0x81BDDB); kRiotColorCuriousBlue = UIColorFromRGB(0x2A9EDB); + kRiotColorIndigo = UIColorFromRGB(0xBD79CC); + kRiotColorOrange = UIColorFromRGB(0xF8A15F); kRiotColorLightKeyboard = UIColorFromRGB(0xE7E7E7); kRiotColorDarkKeyboard = UIColorFromRGB(0x7E7E7E); diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index a247da74f..ff71514bb 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -204,6 +204,7 @@ }]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_groups", @"Vector", nil); + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorBlue; } - (void)viewWillDisappear:(BOOL)animated diff --git a/Riot/Modules/Favorites/FavouritesViewController.m b/Riot/Modules/Favorites/FavouritesViewController.m index 5edd70483..a45af8da0 100644 --- a/Riot/Modules/Favorites/FavouritesViewController.m +++ b/Riot/Modules/Favorites/FavouritesViewController.m @@ -55,6 +55,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_favourites", @"Vector", nil); + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorIndigo; if (recentsDataSource) { @@ -64,7 +65,6 @@ } } - - (void)dealloc { diff --git a/Riot/Modules/People/PeopleViewController.m b/Riot/Modules/People/PeopleViewController.m index f6f3a09d9..914fc6744 100644 --- a/Riot/Modules/People/PeopleViewController.m +++ b/Riot/Modules/People/PeopleViewController.m @@ -108,6 +108,7 @@ } [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_people", @"Vector", nil); + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorOrange; if (recentsDataSource) { diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 64b6c121f..5d01c3115 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -22,6 +22,8 @@ #import "DirectoryServerPickerViewController.h" +#import "Riot-Swift.h" + @interface RoomsViewController () { RecentsDataSource *recentsDataSource; @@ -62,6 +64,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil); + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.accent; if ([self.dataSource isKindOfClass:RecentsDataSource.class]) { From 845775d794df68f062c9e67f86e2196974f3bcd6 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 15:23:22 +0100 Subject: [PATCH 031/244] reskin: ColorValues: suffix UIColor properties names with "Color" --- Riot/AppDelegate.m | 4 +- .../MXKRoomBubbleTableViewCell+Riot.m | 2 +- Riot/Constants/Colors/ColorValues.swift | 37 +++++++++--------- Riot/Constants/Colors/DarkColorValues.swift | 34 ++++++++--------- .../Constants/Colors/DefaultColorValues.swift | 34 ++++++++--------- Riot/Constants/RiotDesignValues.m | 24 ++++++------ .../AuthenticationViewController.m | 6 +-- .../Views/ForgotPasswordInputsView.m | 2 +- .../Authentication/Views/TermsView.swift | 2 +- .../BugReport/BugReportViewController.m | 6 +-- Riot/Modules/Call/CallViewController.m | 4 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../Recents/DataSources/RecentsDataSource.m | 6 +-- .../Recents/Views/RecentTableViewCell.m | 4 +- .../SegmentedViewController.m | 2 +- .../Communities/GroupsViewController.m | 4 +- .../Members/GroupParticipantsViewController.m | 2 +- .../Rooms/GroupRoomsViewController.m | 2 +- .../Views/GroupInviteTableViewCell.m | 2 +- .../Contacts/DataSources/ContactsDataSource.m | 6 +-- .../Details/ContactDetailsViewController.m | 2 +- .../Details/Views/RoomTableViewCell.m | 2 +- .../Contacts/Views/ContactTableViewCell.m | 4 +- .../EncryptionInfo/EncryptionInfoView.m | 8 ++-- .../HomeMessagesSearchDataSource.m | 2 +- ...MessagesSearchResultAttachmentBubbleCell.m | 2 +- .../MessagesSearchResultTextMsgBubbleCell.m | 2 +- .../Views/RoomIdOrAliasTableViewCell.m | 2 +- Riot/Modules/Home/HomeViewController.m | 2 +- .../Home/Views/RoomCollectionViewCell.m | 6 +-- .../People/Views/InviteRecentTableViewCell.m | 6 +-- .../Attachements/AttachmentsViewController.m | 2 +- .../Modules/Room/DataSources/RoomDataSource.m | 2 +- .../Detail/RoomMemberDetailsViewController.m | 4 +- .../Members/RoomParticipantsViewController.m | 12 +++--- .../ReadReceiptsViewController.m | 2 +- Riot/Modules/Room/RoomViewController.m | 6 +-- .../Search/DataSources/RoomSearchDataSource.m | 2 +- .../Settings/RoomSettingsViewController.m | 14 +++---- .../RoomIncomingAttachmentBubbleCell.m | 2 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 6 +-- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../RoomIncomingTextMsgBubbleCell.m | 2 +- ...mingTextMsgWithPaginationTitleBubbleCell.m | 6 +-- ...ginationTitleWithoutSenderNameBubbleCell.m | 2 +- ...comingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- ...comingTextMsgWithoutSenderNameBubbleCell.m | 2 +- .../BubbleCells/RoomMembershipBubbleCell.m | 2 +- .../RoomMembershipCollapsedBubbleCell.m | 2 +- ...ipCollapsedWithPaginationTitleBubbleCell.m | 4 +- .../RoomMembershipExpandedBubbleCell.m | 2 +- ...hipExpandedWithPaginationTitleBubbleCell.m | 4 +- ...mMembershipWithPaginationTitleBubbleCell.m | 4 +- .../RoomOutgoingAttachmentBubbleCell.m | 2 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 6 +-- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../RoomOutgoingTextMsgBubbleCell.m | 2 +- ...oingTextMsgWithPaginationTitleBubbleCell.m | 4 +- ...tgoingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- .../Room/Views/Event/EventDetailsView.m | 4 +- .../DisabledRoomInputToolbarView.m | 2 +- .../Views/InputToolbar/RoomInputToolbarView.m | 6 +-- .../Title/Expanded/ExpandedRoomTitleView.m | 4 +- .../Title/Preview/PreviewRoomTitleView.m | 8 ++-- Riot/Modules/Room/Views/Title/RoomTitleView.m | 2 +- .../Views/DirectoryServerTableViewCell.m | 2 +- Riot/Modules/Rooms/RoomsViewController.m | 2 +- .../DeactivateAccountViewController.m | 2 +- .../Modules/Settings/SettingsViewController.m | 38 +++++++++---------- Riot/Modules/Settings/Views/DeviceView.m | 6 +-- .../StartChat/StartChatViewController.m | 12 +++--- Riot/Modules/TabBar/MasterTabBarController.m | 8 ++-- .../UserDevices/Views/DeviceTableViewCell.m | 4 +- Riot/Utils/AvatarGenerator.m | 2 +- Riot/Utils/EventFormatter.m | 4 +- .../Share/Listing/RoomsListViewController.m | 2 +- 76 files changed, 218 insertions(+), 217 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 992813cf6..4ad9ddb69 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -422,7 +422,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [NSBundle mxk_setFallbackLanguage:@"en"]; // Define the navigation bar text color - [[UINavigationBar appearance] setTintColor:RiotDesignValues.colorValues.accent]; + [[UINavigationBar appearance] setTintColor:RiotDesignValues.colorValues.tintColor]; // Customize the localized string table [NSBundle mxk_customizeLocalizedStringTableName:@"Vector"]; @@ -3542,7 +3542,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN _callStatusBarButton.titleLabel.font = [UIFont boldSystemFontOfSize:17]; } - [_callStatusBarButton setBackgroundColor:RiotDesignValues.colorValues.accent]; + [_callStatusBarButton setBackgroundColor:RiotDesignValues.colorValues.tintColor]; [_callStatusBarButton addTarget:self action:@selector(onCallStatusBarButtonPressed) forControlEvents:UIControlEventTouchUpInside]; // Place button into the new window diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index f60e94e6b..c0273351f 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -209,7 +209,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT markPosY, VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH, markHeight)]; - markerView.backgroundColor = RiotDesignValues.colorValues.accent; + markerView.backgroundColor = RiotDesignValues.colorValues.tintColor; [markerView setTranslatesAutoresizingMaskIntoConstraints:NO]; markerView.accessibilityIdentifier = @"markerView"; diff --git a/Riot/Constants/Colors/ColorValues.swift b/Riot/Constants/Colors/ColorValues.swift index 09d4fc7f7..b23f35cbc 100644 --- a/Riot/Constants/Colors/ColorValues.swift +++ b/Riot/Constants/Colors/ColorValues.swift @@ -20,30 +20,31 @@ import UIKit /// https://app.zeplin.io/project/5b857c64b1747a2c472290da/screen/5bf2cc89a4a6973f47883c6e @objc protocol ColorValues { - var background: UIColor { get } - var base: UIColor { get } + var backgroundColor: UIColor { get } + var baseColor: UIColor { get } - var baseTextPrimary: UIColor { get } - var baseTextSecondary: UIColor { get } + var baseTextPrimaryColor: UIColor { get } + var baseTextSecondaryColor: UIColor { get } - var searchBackground: UIColor { get } - var searchText: UIColor { get } + var searchBackgroundColor: UIColor { get } + var searchTextColor: UIColor { get } - var headerBackground: UIColor { get } - var headerBorder: UIColor { get } - var headerTextPrimary: UIColor { get } - var headerTextSecondary: UIColor { get } + var headerBackgroundColor: UIColor { get } + var headerBorderColor: UIColor { get } + var headerTextPrimaryColor: UIColor { get } + var headerTextSecondaryColor: UIColor { get } - var textPrimary: UIColor { get } - var textSecondary: UIColor { get } + var textPrimaryColor: UIColor { get } + var textSecondaryColor: UIColor { get } - var accent: UIColor { get } - var unreadRoomIndent: UIColor { get } - - var notificationUnread: UIColor { get } - var notificationMention: UIColor { get } + var tintColor: UIColor { get } - var avatars: [UIColor] { get } + var unreadRoomIndentColor: UIColor { get } + + var notificationUnreadColor: UIColor { get } + var notificationMentionColor: UIColor { get } + + var avatarColors: [UIColor] { get } } extension UIColor { diff --git a/Riot/Constants/Colors/DarkColorValues.swift b/Riot/Constants/Colors/DarkColorValues.swift index a2522ea10..c4c420c75 100644 --- a/Riot/Constants/Colors/DarkColorValues.swift +++ b/Riot/Constants/Colors/DarkColorValues.swift @@ -23,30 +23,30 @@ final class DarkColorValues: NSObject, ColorValues { static let shared = DarkColorValues() - let background: UIColor = UIColor(rgb: 0x212224) + let backgroundColor: UIColor = UIColor(rgb: 0x212224) - let base: UIColor = UIColor(rgb: 0x292E37) - let baseTextPrimary: UIColor = UIColor(rgb: 0xFFFFFF) - let baseTextSecondary: UIColor = UIColor(rgb: 0xFFFFFF) + let baseColor: UIColor = UIColor(rgb: 0x292E37) + let baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + let baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let searchBackground: UIColor = UIColor(rgb: 0x3E434B) - let searchText: UIColor = UIColor(rgb: 0xACB3C2) + let searchBackgroundColor: UIColor = UIColor(rgb: 0x3E434B) + let searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) - let headerBackground: UIColor = UIColor(rgb: 0x303540) - let headerBorder: UIColor = UIColor(rgb: 0x2E2F31) - let headerTextPrimary: UIColor = UIColor(rgb: 0x96A1B7) - let headerTextSecondary: UIColor = UIColor(rgb: 0xC8C8CD) + let headerBackgroundColor: UIColor = UIColor(rgb: 0x303540) + let headerBorderColor: UIColor = UIColor(rgb: 0x2E2F31) + let headerTextPrimaryColor: UIColor = UIColor(rgb: 0x96A1B7) + let headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) - let textPrimary: UIColor = UIColor(rgb: 0xFFFFFF) - let textSecondary: UIColor = UIColor(rgb: 0xD8D8D8) + let textPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + let textSecondaryColor: UIColor = UIColor(rgb: 0xD8D8D8) - let accent: UIColor = UIColor(rgb: 0x7AC9A1) - let unreadRoomIndent: UIColor = UIColor(rgb: 0x2E3648) + let tintColor: UIColor = UIColor(rgb: 0x7AC9A1) + let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - let notificationUnread: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationMention: UIColor = UIColor(rgb: 0x3F4147) + let notificationUnreadColor: UIColor = UIColor(rgb: 0x7AC9A1) + let notificationMentionColor: UIColor = UIColor(rgb: 0x3F4147) - let avatars: [UIColor] = [ + let avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] diff --git a/Riot/Constants/Colors/DefaultColorValues.swift b/Riot/Constants/Colors/DefaultColorValues.swift index ed90ae7b6..840bcc584 100644 --- a/Riot/Constants/Colors/DefaultColorValues.swift +++ b/Riot/Constants/Colors/DefaultColorValues.swift @@ -23,30 +23,30 @@ final class DefaultColorValues: NSObject, ColorValues { static let shared = DefaultColorValues() - let background: UIColor = UIColor(rgb: 0xFFFFFF) + let backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) - let base: UIColor = UIColor(rgb: 0x2E3648) - let baseTextPrimary: UIColor = UIColor(rgb: 0xFFFFFF) - let baseTextSecondary: UIColor = UIColor(rgb: 0xFFFFFF) + let baseColor: UIColor = UIColor(rgb: 0x2E3648) + let baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + let baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let searchBackground: UIColor = UIColor(rgb: 0xFFFFFF) - let searchText: UIColor = UIColor(rgb: 0xACB3C2) + let searchBackgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) + let searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) - let headerBackground: UIColor = UIColor(rgb: 0xF1F5F8) - let headerBorder: UIColor = UIColor(rgb: 0xEAEEF2) - let headerTextPrimary: UIColor = UIColor(rgb: 0x96A1B7) - let headerTextSecondary: UIColor = UIColor(rgb: 0xC8C8CD) + let headerBackgroundColor: UIColor = UIColor(rgb: 0xF1F5F8) + let headerBorderColor: UIColor = UIColor(rgb: 0xEAEEF2) + let headerTextPrimaryColor: UIColor = UIColor(rgb: 0x96A1B7) + let headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) - let textPrimary: UIColor = UIColor(rgb: 0x383838) - let textSecondary: UIColor = UIColor(rgb: 0x9E9E9E) + let textPrimaryColor: UIColor = UIColor(rgb: 0x383838) + let textSecondaryColor: UIColor = UIColor(rgb: 0x9E9E9E) - let accent: UIColor = UIColor(rgb: 0x7AC9A1) - let unreadRoomIndent: UIColor = UIColor(rgb: 0x2E3648) + let tintColor: UIColor = UIColor(rgb: 0x7AC9A1) + let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - let notificationUnread: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationMention: UIColor = UIColor(rgb: 0xF56679) + let notificationUnreadColor: UIColor = UIColor(rgb: 0x7AC9A1) + let notificationMentionColor: UIColor = UIColor(rgb: 0xF56679) - let avatars: [UIColor] = [ + let avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index af81ce331..56833fbea 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -181,22 +181,22 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Apply theme color constants id colorValues = [RiotDesignValues colorValues]; - kRiotPrimaryBgColor = colorValues.background; - kRiotSecondaryBgColor = colorValues.headerBackground; - kRiotPrimaryTextColor = colorValues.textPrimary; - kRiotSecondaryTextColor = colorValues.textSecondary; + kRiotPrimaryBgColor = colorValues.backgroundColor; + kRiotSecondaryBgColor = colorValues.headerBackgroundColor; + kRiotPrimaryTextColor = colorValues.textPrimaryColor; + kRiotSecondaryTextColor = colorValues.textSecondaryColor; - kRiotDesignNavigationBarBarTintColor = colorValues.base; - kRiotDesignNavigationBarTintColor = colorValues.baseTextPrimary; + kRiotDesignNavigationBarBarTintColor = colorValues.baseColor; + kRiotDesignNavigationBarTintColor = colorValues.baseTextPrimaryColor; kRiotDesignNavigationBarTitleTextAttributes = @{ - NSForegroundColorAttributeName: colorValues.baseTextPrimary + NSForegroundColorAttributeName: colorValues.baseTextPrimaryColor }; - kRiotDesignSearchBarBarTintColor = colorValues.headerBackground; - kRiotDesignSearchBarTintColor = colorValues.searchText; + kRiotDesignSearchBarBarTintColor = colorValues.headerBackgroundColor; + kRiotDesignSearchBarTintColor = colorValues.searchTextColor; - kRiotTopicTextColor = colorValues.baseTextSecondary; - kRiotAuxiliaryColor = colorValues.headerTextSecondary; + kRiotTopicTextColor = colorValues.baseTextSecondaryColor; + kRiotAuxiliaryColor = colorValues.headerTextSecondaryColor; [UIScrollView appearance].indicatorStyle = kRiotScrollBarStyle; @@ -250,7 +250,7 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; searchBar.tintColor = kRiotDesignSearchBarTintColor; searchBar.barTintColor = kRiotDesignSearchBarBarTintColor; searchBar.layer.borderWidth = 1; - searchBar.layer.borderColor = RiotDesignValues.colorValues.headerBorder.CGColor; + searchBar.layer.borderColor = RiotDesignValues.colorValues.headerBorderColor.CGColor; } @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index f1c765f38..292b1e58c 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -154,14 +154,14 @@ } } - self.submitButton.backgroundColor = RiotDesignValues.colorValues.accent; - self.skipButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.submitButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.skipButton.backgroundColor = RiotDesignValues.colorValues.tintColor; self.noFlowLabel.textColor = kRiotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; - [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.colorValues.accent range:NSMakeRange(0, forgotPasswordTitle.length)]; + [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.colorValues.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; [self updateForgotPwdButtonVisibility]; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index a57385370..07f7a7e1d 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -115,7 +115,7 @@ [self.nextStepButton.layer setCornerRadius:5]; self.nextStepButton.clipsToBounds = YES; - self.nextStepButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.nextStepButton.backgroundColor = RiotDesignValues.colorValues.tintColor; if (kRiotPlaceholderTextColor) { diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index b422b53e2..fdd1670e9 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -80,7 +80,7 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie } func customizeViewRendering() { - acceptButton.backgroundColor = RiotDesignValues.colorValues().accent + acceptButton.backgroundColor = RiotDesignValues.colorValues().tintColor } diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 1559dba0e..c829c965c 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -154,13 +154,13 @@ self.sendingLabel.textColor = kRiotPrimaryTextColor; self.descriptionLabel.textColor = kRiotPrimaryTextColor; self.bugReportDescriptionTextView.textColor = kRiotPrimaryTextColor; - self.bugReportDescriptionTextView.tintColor = RiotDesignValues.colorValues.accent; + self.bugReportDescriptionTextView.tintColor = RiotDesignValues.colorValues.tintColor; self.logsDescriptionLabel.textColor = kRiotPrimaryTextColor; self.sendLogsLabel.textColor = kRiotPrimaryTextColor; self.sendScreenshotLabel.textColor = kRiotPrimaryTextColor; - self.sendButton.tintColor = RiotDesignValues.colorValues.accent; - self.cancelButton.tintColor = RiotDesignValues.colorValues.accent; + self.sendButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.cancelButton.tintColor = RiotDesignValues.colorValues.tintColor; _bugReportDescriptionTextView.layer.borderColor = kRiotSecondaryBgColor.CGColor; } diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 12cf122da..e75585353 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -106,7 +106,7 @@ self.callerNameLabel.textColor = kRiotPrimaryTextColor; self.callStatusLabel.textColor = kRiotTopicTextColor; - self.localPreviewContainerView.layer.borderColor = RiotDesignValues.colorValues.accent.CGColor; + self.localPreviewContainerView.layer.borderColor = RiotDesignValues.colorValues.tintColor.CGColor; self.localPreviewContainerView.layer.borderWidth = 2; self.localPreviewContainerView.layer.cornerRadius = 5; self.localPreviewContainerView.clipsToBounds = YES; @@ -350,7 +350,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.accent]; + withColor:RiotDesignValues.colorValues.tintColor]; } - (void)setMxCall:(MXCall *)call diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 34696dedb..db5bd9613 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -87,7 +87,7 @@ static const CGFloat kButtonSize = 80.0; self.callInfoLabel.text = callInfo; self.callInfoLabel.textAlignment = NSTextAlignmentCenter; - UIColor *answerButtonBorderColor = RiotDesignValues.colorValues.accent; + UIColor *answerButtonBorderColor = RiotDesignValues.colorValues.tintColor; self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"] borderColor:answerButtonBorderColor]; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 91c551f26..31919cd05 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -415,10 +415,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondary, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -426,7 +426,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 199357bbe..38ce18a3d 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -54,7 +54,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.accent.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -109,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index d598f7b5d..dfdeacb1b 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -136,7 +136,7 @@ // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; - self.sectionHeaderTintColor = RiotDesignValues.colorValues.accent; + self.sectionHeaderTintColor = RiotDesignValues.colorValues.tintColor; } - (void)viewDidLoad diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index ff71514bb..23d5168c9 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -462,9 +462,9 @@ { NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextPrimary}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextPrimaryColor}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextSecondary}]]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextSecondaryColor}]]; sectionHeader.mxkLabel.attributedText = mutableSectionTitle; } diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 54554e4d3..e70e7ea21 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -151,7 +151,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 33956bf0e..24ec9f1be 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -132,7 +132,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index adb08767a..41b5f02a7 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -58,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = kRiotColorBlue; self.rightButton.backgroundColor = kRiotColorBlue; - self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMention; + self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 11ff1027a..bcf3385fd 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -742,10 +742,10 @@ NSString *roomCount = [NSString stringWithFormat:roomCountFormat, count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondary, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -753,7 +753,7 @@ else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimary, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 8debc1999..b88011958 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -237,7 +237,7 @@ self.headerView.backgroundColor = kRiotSecondaryBgColor; self.contactNameLabel.textColor = kRiotPrimaryTextColor; - self.contactStatusLabel.textColor = RiotDesignValues.colorValues.accent; + self.contactStatusLabel.textColor = RiotDesignValues.colorValues.tintColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index 13310c1ea..2d2c6d1a8 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -38,7 +38,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.titleLabel.textColor = kRiotPrimaryTextColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.accent.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index ad33219f9..f2e4cb0f2 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -223,11 +223,11 @@ } else if ((!contact.isMatrixContact && contact.phoneNumbers.count && !contact.emailAddresses.count)) { - image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:RiotDesignValues.colorValues.accent]; + image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:RiotDesignValues.colorValues.tintColor]; } else { - image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:RiotDesignValues.colorValues.accent]; + image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:RiotDesignValues.colorValues.tintColor]; } } diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index c493fe692..31ebbd3ce 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -31,10 +31,10 @@ self.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.defaultTextColor = kRiotPrimaryTextColor; - self.cancelButton.tintColor = RiotDesignValues.colorValues.accent; - self.verifyButton.tintColor = RiotDesignValues.colorValues.accent; - self.blockButton.tintColor = RiotDesignValues.colorValues.accent; - self.confirmVerifyButton.tintColor = RiotDesignValues.colorValues.accent; + self.cancelButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.verifyButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.blockButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.confirmVerifyButton.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index c3e083f51..2698f17fb 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -66,7 +66,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.accent andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index b6406ef28..bac583c42 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -30,7 +30,7 @@ self.roomNameLabel.textColor = kRiotSecondaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index 42ecdd21b..d155f7850 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -30,7 +30,7 @@ self.roomNameLabel.textColor = kRiotSecondaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index 0bd2245eb..5347c6fa6 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -50,7 +50,7 @@ else { self.avatarImageView.image = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.accent]; + withColor:RiotDesignValues.colorValues.tintColor]; } self.titleLabel.text = roomIdOrAlias; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index d28bcd99e..810159529 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -84,7 +84,7 @@ [RiotDesignValues applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.accent; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.tintColor; if (recentsDataSource) { diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index d7151daf8..61c5c0e40 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -72,7 +72,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.accent.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -126,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -147,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.colorValues.notificationMention; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index 0f752aac7..6870a419d 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -60,10 +60,10 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell { [super customizeTableViewCellRendering]; - self.leftButton.backgroundColor = RiotDesignValues.colorValues.accent; - self.rightButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.leftButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.rightButton.backgroundColor = RiotDesignValues.colorValues.tintColor; - self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMention; + self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 4de12a032..e9f972901 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -64,7 +64,7 @@ self.view.backgroundColor = kRiotPrimaryBgColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.backButton.tintColor = RiotDesignValues.colorValues.accent; + self.backButton.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 093805a56..7ce867da0 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -386,7 +386,7 @@ if ([component.event.eventId isEqualToString:self.room.accountData.readMarkerEventId]) { bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - 2, bubbleCell.bubbleOverlayContainer.frame.size.width, 2)]; - bubbleCell.readMarkerView.backgroundColor = RiotDesignValues.colorValues.accent; + bubbleCell.readMarkerView.backgroundColor = RiotDesignValues.colorValues.tintColor; // Hide by default the marker, it will be shown and animated when the cell will be rendered. bubbleCell.readMarkerView.hidden = YES; bubbleCell.readMarkerView.tag = index; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index f8aa8b716..d2c218553 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -225,7 +225,7 @@ self.memberHeaderView.backgroundColor = kRiotDesignNavigationBarBarTintColor; self.roomMemberNameLabel.textColor = kRiotPrimaryTextColor; - self.roomMemberStatusLabel.textColor = RiotDesignValues.colorValues.accent; + self.roomMemberStatusLabel.textColor = RiotDesignValues.colorValues.tintColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); @@ -360,7 +360,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.accent]; + withColor:RiotDesignValues.colorValues.tintColor]; } - (void)updateMemberInfo diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 795430f1b..b021f35a2 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -163,7 +163,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); @@ -1684,8 +1684,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.accent; - searchBar.tintColor = RiotDesignValues.colorValues.accent; + searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.tintColor; + searchBar.tintColor = RiotDesignValues.colorValues.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -1696,7 +1696,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = RiotDesignValues.colorValues.accent; + leftImageView.tintColor = RiotDesignValues.colorValues.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -1707,8 +1707,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: RiotDesignValues.colorValues.accent, - NSForegroundColorAttributeName: RiotDesignValues.colorValues.accent}]; + NSUnderlineColorAttributeName: RiotDesignValues.colorValues.tintColor, + NSForegroundColorAttributeName: RiotDesignValues.colorValues.tintColor}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index d44282fb3..1ce819780 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -107,7 +107,7 @@ // Check the table view style to select its bg color. self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); - self.closeButton.tintColor = RiotDesignValues.colorValues.accent; + self.closeButton.tintColor = RiotDesignValues.colorValues.tintColor; if (self.receiptsTableView.dataSource) { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index b1147cd72..a1a3c7f47 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1752,7 +1752,7 @@ else { previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.accent]; + withColor:RiotDesignValues.colorValues.tintColor]; } } @@ -4230,11 +4230,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationMention; + missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationUnread; + missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationUnreadColor; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 9c3177495..339624776 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -69,7 +69,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.accent andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index a1bc63092..ac8dd2759 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2213,7 +2213,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView.text = mxRoomState.topic; } - topicTextView.tintColor = RiotDesignValues.colorValues.accent; + topicTextView.tintColor = RiotDesignValues.colorValues.tintColor; topicTextView.font = [UIFont systemFontOfSize:15]; topicTextView.bounces = NO; topicTextView.delegate = self; @@ -2242,7 +2242,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti nameTextField = roomNameCell.mxkTextField; - nameTextField.tintColor = RiotDesignValues.colorValues.accent; + nameTextField.tintColor = RiotDesignValues.colorValues.tintColor; nameTextField.font = [UIFont systemFontOfSize:17]; nameTextField.borderStyle = UITextBorderStyleNone; nameTextField.textAlignment = NSTextAlignmentRight; @@ -2320,7 +2320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [leaveCell.mxkButton setTitle:title forState:UIControlStateNormal]; [leaveCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [leaveCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; + [leaveCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; leaveCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [leaveCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2509,7 +2509,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressTextField.text = currentValue; addAddressTextField.textColor = kRiotSecondaryTextColor; - addAddressTextField.tintColor = RiotDesignValues.colorValues.accent; + addAddressTextField.tintColor = RiotDesignValues.colorValues.tintColor; addAddressTextField.font = [UIFont systemFontOfSize:17]; addAddressTextField.borderStyle = UITextBorderStyleNone; addAddressTextField.textAlignment = NSTextAlignmentLeft; @@ -2600,7 +2600,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addGroupTextField.text = currentValue; addGroupTextField.textColor = kRiotSecondaryTextColor; - addGroupTextField.tintColor = RiotDesignValues.colorValues.accent; + addGroupTextField.tintColor = RiotDesignValues.colorValues.tintColor; addGroupTextField.font = [UIFont systemFontOfSize:17]; addGroupTextField.borderStyle = UITextBorderStyleNone; addGroupTextField.textAlignment = NSTextAlignmentLeft; @@ -2672,7 +2672,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti MXKTableViewCellWithLabelAndSwitch *roomBlacklistUnverifiedDevicesCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; [roomBlacklistUnverifiedDevicesCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevice:) forControlEvents:UIControlEventValueChanged]; - roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; roomBlacklistUnverifiedDevicesCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_blacklist_unverified_devices", @"Vector", nil); @@ -2803,7 +2803,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.mxkLabel.textColor = kRiotPrimaryTextColor; - cell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + cell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged]; // Reset the stored `directoryVisibilitySwitch` if the corresponding cell is reused. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index 8cad6d47e..a1a529000 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index 09e0fed2c..e254550a0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -28,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m index 839f52114..7628004b2 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index 48751e1a6..47ac451f9 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index 272a75b40..76cf9cc08 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -28,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index 816e9cce8..d344cc2a7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m index ed8f43876..d58db9dd7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m index a6a280204..c538335dc 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m index a10e24b86..cc1da021b 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m @@ -41,7 +41,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)prepareForReuse diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m index 364dadbe6..32194ae9d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m @@ -30,7 +30,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m index 5dfa22cec..31bfa1cf0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index d49a31ad4..c28fd41a7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -40,7 +40,7 @@ NSString *const kRoomMembershipExpandedBubbleCellTapOnCollapseButton = @"kRoomMe self.separatorView.backgroundColor = kRiotSecondaryBgColor; - [self.collapseButton setTintColor:RiotDesignValues.colorValues.accent]; + [self.collapseButton setTintColor:RiotDesignValues.colorValues.tintColor]; self.collapseButton.titleLabel.font = [UIFont systemFontOfSize:14]; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m index fe40ec063..cf43c8501 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m index 1f7299953..2b165e8ba 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index e4400fbc0..4aa88ddfa 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index b34265b70..126331862 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -28,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m index f2488d5a4..fb4286cbc 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index 7b4df7b14..cf23e9c73 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m index 2be9207b1..482512cce 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.accent; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.accent; + self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m index 31bb7ce23..2f0cf9460 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.accent; + self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 88dc29b8c..1bb4fdb49 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -28,8 +28,8 @@ self.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.textView.textColor = kRiotPrimaryTextColor; - self.redactButton.tintColor = RiotDesignValues.colorValues.accent; - self.closeButton.tintColor = RiotDesignValues.colorValues.accent; + self.redactButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.closeButton.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 26d191372..85bbf7142 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -52,7 +52,7 @@ self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; self.disabledReasonTextView.textColor = kRiotPrimaryTextColor; - self.disabledReasonTextView.tintColor = RiotDesignValues.colorValues.accent; + self.disabledReasonTextView.tintColor = RiotDesignValues.colorValues.tintColor; self.disabledReasonTextView.editable = NO; self.disabledReasonTextView.scrollEnabled = NO; } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index f3a55839d..38ad66303 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -72,8 +72,8 @@ self.rightInputToolbarButton.hidden = YES; - [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.accent forState:UIControlStateNormal]; - [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.accent forState:UIControlStateHighlighted]; + [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.tintColor forState:UIControlStateNormal]; + [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.tintColor forState:UIControlStateHighlighted]; self.isEncryptionEnabled = _isEncryptionEnabled; } @@ -96,7 +96,7 @@ growingTextView.font = [UIFont systemFontOfSize:15]; growingTextView.textColor = kRiotPrimaryTextColor; - growingTextView.tintColor = RiotDesignValues.colorValues.accent; + growingTextView.tintColor = RiotDesignValues.colorValues.tintColor; growingTextView.internalTextView.keyboardAppearance = kRiotKeyboard; } diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index 33e7fb630..292a6b939 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -40,7 +40,7 @@ [super layoutSubviews]; self.membersListIcon.image = [MXKTools paintImage:self.membersListIcon.image - withColor:RiotDesignValues.colorValues.accent]; + withColor:RiotDesignValues.colorValues.tintColor]; // TODO: paintImage does not work here because addParticipantIcon has 2 colors // self.addParticipantIcon.image = [MXKTools paintImage:self.addParticipantIcon.image @@ -52,7 +52,7 @@ [super customizeViewRendering]; self.roomTopic.textColor = kRiotTopicTextColor; - self.roomMembers.textColor = RiotDesignValues.colorValues.accent; + self.roomMembers.textColor = RiotDesignValues.colorValues.tintColor; } - (void)refreshDisplay diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 3fce53189..518ebcaee 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -69,7 +69,7 @@ self.roomTopic.textColor = kRiotTopicTextColor; - self.roomMembers.textColor = RiotDesignValues.colorValues.accent; + self.roomMembers.textColor = RiotDesignValues.colorValues.tintColor; self.previewLabel.textColor = kRiotTopicTextColor; self.previewLabel.numberOfLines = 0; @@ -81,11 +81,11 @@ [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; - self.leftButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.leftButton.backgroundColor = RiotDesignValues.colorValues.tintColor; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - self.rightButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.rightButton.backgroundColor = RiotDesignValues.colorValues.tintColor; } - (void)refreshDisplay @@ -103,7 +103,7 @@ toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.accent] + withColor:RiotDesignValues.colorValues.tintColor] mediaManager:self.mxRoom.mxSession.mediaManager]; } else diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index b9f253e09..0a8cf2bea 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -73,7 +73,7 @@ [super layoutSubviews]; self.roomDetailsIconImageView.image = [MXKTools paintImage:self.roomDetailsIconImageView.image - withColor:RiotDesignValues.colorValues.accent]; + withColor:RiotDesignValues.colorValues.tintColor]; if (self.superview) { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 2d5505660..97d406ed9 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -64,7 +64,7 @@ withType:nil andImageOrientation:UIImageOrientationUp previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.accent] + withColor:RiotDesignValues.colorValues.tintColor] mediaManager:cellData.mediaManager]; } else diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 5d01c3115..b3456a174 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -64,7 +64,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.accent; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.tintColor; if ([self.dataSource isKindOfClass:RecentsDataSource.class]) { diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 20b9219ac..cd9fb0204 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -166,7 +166,7 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; self.deactivateAcccountButton.layer.masksToBounds = YES; - self.deactivateAcccountButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.deactivateAcccountButton.backgroundColor = RiotDesignValues.colorValues.tintColor; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; [self.deactivateAcccountButton setTitleColor:kRiotAuxiliaryColor forState:UIControlStateDisabled]; } diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index ec2256601..9c182183c 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1404,7 +1404,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); [signOutCell.mxkButton setTitle:title forState:UIControlStateNormal]; [signOutCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [signOutCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; + [signOutCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; signOutCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [signOutCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1559,7 +1559,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newEmailTextField = newEmailCell.mxkTextField; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.accent]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.tintColor]; newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; } @@ -1652,7 +1652,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newPhoneNumberCell = newPhoneCell; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.accent]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.tintColor]; newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; cell = newPhoneCell; @@ -1695,7 +1695,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_push_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.isPushKitNotificationActive; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePushNotifications:) forControlEvents:UIControlEventTouchUpInside]; @@ -1707,7 +1707,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_show_decrypted_content", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.showDecryptedContentInNotifications; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = account.isPushKitNotificationActive; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleShowDecodedContent:) forControlEvents:UIControlEventTouchUpInside]; @@ -1733,7 +1733,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_missed_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithMissedNotif:) forControlEvents:UIControlEventTouchUpInside]; @@ -1745,7 +1745,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_unread", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithUnread:) forControlEvents:UIControlEventTouchUpInside]; @@ -1759,7 +1759,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside]; @@ -1864,7 +1864,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.numberOfLines = 0; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_contacts_discover_matrix_users", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].syncLocalContacts; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLocalContactsSync:) forControlEvents:UIControlEventTouchUpInside]; @@ -1973,7 +1973,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); sendCrashReportCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_send_crash_report", @"Vector", nil); sendCrashReportCell.mxkSwitch.on = RiotSettings.shared.enableCrashReport; - sendCrashReportCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + sendCrashReportCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; sendCrashReportCell.mxkSwitch.enabled = YES; [sendCrashReportCell.mxkSwitch addTarget:self action:@selector(toggleSendCrashReport:) forControlEvents:UIControlEventTouchUpInside]; @@ -1985,7 +1985,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); enableRageShakeCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_rageshake", @"Vector", nil); enableRageShakeCell.mxkSwitch.on = RiotSettings.shared.enableRageShake; - enableRageShakeCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + enableRageShakeCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; enableRageShakeCell.mxkSwitch.enabled = YES; [enableRageShakeCell.mxkSwitch addTarget:self action:@selector(toggleEnableRageShake:) forControlEvents:UIControlEventTouchUpInside]; @@ -2007,7 +2007,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_mark_all_as_read", @"Vector", nil); [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [markAllBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; + [markAllBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; markAllBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [markAllBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2032,7 +2032,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_clear_cache", @"Vector", nil); [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [clearCacheBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; + [clearCacheBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; clearCacheBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [clearCacheBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2057,7 +2057,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_report_bug", @"Vector", nil); [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [reportBugBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; + [reportBugBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; reportBugBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [reportBugBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2077,7 +2077,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; labelAndSwitchCell.mxkSwitch.on = account.mxSession.syncWithLazyLoadOfRoomMembers; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleSyncWithLazyLoadOfRoomMembers:) forControlEvents:UIControlEventTouchUpInside]; @@ -2089,7 +2089,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_create_conference_with_jitsi", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.createConferenceCallsWithJitsi; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleJitsiForConference:) forControlEvents:UIControlEventTouchUpInside]; @@ -2103,7 +2103,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_e2e_encryption", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = (nil != session.crypto); - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLabsEndToEndEncryption:) forControlEvents:UIControlEventTouchUpInside]; @@ -2177,7 +2177,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_crypto_blacklist_unverified_devices", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.mxSession.crypto.globalBlacklistUnverifiedDevices; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.accent; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevices:) forControlEvents:UIControlEventTouchUpInside]; @@ -2199,7 +2199,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_crypto_export", @"Vector", nil); [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [exportKeysBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.accent]; + [exportKeysBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; exportKeysBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [exportKeysBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 47d74d3c6..4545ef02f 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -31,9 +31,9 @@ self.containerView.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.defaultTextColor = kRiotPrimaryTextColor; - self.cancelButton.tintColor = RiotDesignValues.colorValues.accent; - self.deleteButton.tintColor = RiotDesignValues.colorValues.accent; - self.renameButton.tintColor = RiotDesignValues.colorValues.accent; + self.cancelButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.deleteButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.renameButton.tintColor = RiotDesignValues.colorValues.tintColor; } @end diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 0c822a958..f9c22e975 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -149,7 +149,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorder; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; // Check the table view style to select its bg color. self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); @@ -621,8 +621,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.accent; - searchBar.tintColor = RiotDesignValues.colorValues.accent; + searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.tintColor; + searchBar.tintColor = RiotDesignValues.colorValues.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -633,7 +633,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = RiotDesignValues.colorValues.accent; + leftImageView.tintColor = RiotDesignValues.colorValues.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -646,8 +646,8 @@ { searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: RiotDesignValues.colorValues.accent, - NSForegroundColorAttributeName: RiotDesignValues.colorValues.accent}]; + NSUnderlineColorAttributeName: RiotDesignValues.colorValues.tintColor, + NSForegroundColorAttributeName: RiotDesignValues.colorValues.tintColor}]; } } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index c695ba3d7..9391cc0e5 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -116,7 +116,7 @@ { [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.tabBar.tintColor = RiotDesignValues.colorValues.accent; + self.tabBar.tintColor = RiotDesignValues.colorValues.tintColor; self.tabBar.barTintColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; @@ -798,15 +798,15 @@ // Use a middle dot to signal missed notif in favourites [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX - withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread)]; + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor)]; // Update the badge on People and Rooms tabs [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX - withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread)]; + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor)]; [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX - withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? RiotDesignValues.colorValues.notificationMention : RiotDesignValues.colorValues.notificationUnread)]; + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 0678fbc42..269f4eac1 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -36,11 +36,11 @@ [self.verifyButton.layer setCornerRadius:5]; self.verifyButton.clipsToBounds = YES; - self.verifyButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.verifyButton.backgroundColor = RiotDesignValues.colorValues.tintColor; [self.blockButton.layer setCornerRadius:5]; self.blockButton.clipsToBounds = YES; - self.blockButton.backgroundColor = RiotDesignValues.colorValues.accent; + self.blockButton.backgroundColor = RiotDesignValues.colorValues.tintColor; } - (void)render:(MXDeviceInfo *)deviceInfo diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index 0885ef5a0..dd559682d 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -39,7 +39,7 @@ static UILabel* backgroundLabel = nil; { if (!colorsList) { - colorsList = RiotDesignValues.colorValues.avatars; + colorsList = RiotDesignValues.colorValues.avatarColors; } } diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 1fb0c86d5..fe2fa731e 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -220,8 +220,8 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.defaultTextColor = kRiotPrimaryTextColor; self.subTitleTextColor = kRiotSecondaryTextColor; self.prefixTextColor = kRiotSecondaryTextColor; - self.bingTextColor = RiotDesignValues.colorValues.notificationMention; - self.encryptingTextColor = RiotDesignValues.colorValues.accent; + self.bingTextColor = RiotDesignValues.colorValues.notificationMentionColor; + self.encryptingTextColor = RiotDesignValues.colorValues.tintColor; self.sendingTextColor = kRiotSecondaryTextColor; self.errorTextColor = kRiotColorRed; diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m index ce5e67b8c..a27048d17 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m @@ -96,7 +96,7 @@ self.recentsSearchBar.searchBarStyle = UISearchBarStyleMinimal; self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); - self.recentsSearchBar.tintColor = RiotDesignValues.colorValues.accent; + self.recentsSearchBar.tintColor = RiotDesignValues.colorValues.tintColor; _tableSearchBar.tintColor = self.recentsSearchBar.tintColor; } From c702350171cb6512e92e10f32d2634677d7390a2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 15:32:59 +0100 Subject: [PATCH 032/244] reskin: rename ColorValues to Theme --- Riot.xcodeproj/project.pbxproj | 36 ++++++------ Riot/AppDelegate.m | 4 +- .../MXKRoomBubbleTableViewCell+Riot.m | 2 +- ...{DarkColorValues.swift => DarkTheme.swift} | 4 +- ...ltColorValues.swift => DefaultTheme.swift} | 4 +- .../Colors/{ColorValues.swift => Theme.swift} | 2 +- Riot/Constants/RiotDesignValues.h | 6 +- Riot/Constants/RiotDesignValues.m | 58 +++++++++---------- .../AuthenticationViewController.m | 6 +- .../Views/ForgotPasswordInputsView.m | 2 +- .../Authentication/Views/TermsView.swift | 2 +- .../BugReport/BugReportViewController.m | 6 +- Riot/Modules/Call/CallViewController.m | 4 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../Recents/DataSources/RecentsDataSource.m | 6 +- .../Recents/Views/RecentTableViewCell.m | 4 +- .../SegmentedViewController.h | 2 +- .../SegmentedViewController.m | 2 +- .../Communities/GroupsViewController.m | 4 +- .../Members/GroupParticipantsViewController.m | 2 +- .../Rooms/GroupRoomsViewController.m | 2 +- .../Views/GroupInviteTableViewCell.m | 2 +- .../Contacts/DataSources/ContactsDataSource.m | 6 +- .../Details/ContactDetailsViewController.m | 2 +- .../Details/Views/RoomTableViewCell.m | 2 +- .../Contacts/Views/ContactTableViewCell.m | 4 +- .../EncryptionInfo/EncryptionInfoView.m | 8 +-- .../HomeMessagesSearchDataSource.m | 2 +- ...MessagesSearchResultAttachmentBubbleCell.m | 2 +- .../MessagesSearchResultTextMsgBubbleCell.m | 2 +- .../Views/RoomIdOrAliasTableViewCell.m | 2 +- Riot/Modules/Home/HomeViewController.m | 2 +- .../Home/Views/RoomCollectionViewCell.m | 6 +- .../People/Views/InviteRecentTableViewCell.m | 6 +- .../Attachements/AttachmentsViewController.m | 2 +- .../Modules/Room/DataSources/RoomDataSource.m | 2 +- .../Detail/RoomMemberDetailsViewController.m | 4 +- .../Members/RoomParticipantsViewController.m | 12 ++-- .../ReadReceiptsViewController.m | 2 +- Riot/Modules/Room/RoomViewController.m | 6 +- .../Search/DataSources/RoomSearchDataSource.m | 2 +- .../Settings/RoomSettingsViewController.m | 14 ++--- .../RoomIncomingAttachmentBubbleCell.m | 2 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 6 +- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../RoomIncomingTextMsgBubbleCell.m | 2 +- ...mingTextMsgWithPaginationTitleBubbleCell.m | 6 +- ...ginationTitleWithoutSenderNameBubbleCell.m | 2 +- ...comingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- ...comingTextMsgWithoutSenderNameBubbleCell.m | 2 +- .../BubbleCells/RoomMembershipBubbleCell.m | 2 +- .../RoomMembershipCollapsedBubbleCell.m | 2 +- ...ipCollapsedWithPaginationTitleBubbleCell.m | 4 +- .../RoomMembershipExpandedBubbleCell.m | 2 +- ...hipExpandedWithPaginationTitleBubbleCell.m | 4 +- ...mMembershipWithPaginationTitleBubbleCell.m | 4 +- .../RoomOutgoingAttachmentBubbleCell.m | 2 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 6 +- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../RoomOutgoingTextMsgBubbleCell.m | 2 +- ...oingTextMsgWithPaginationTitleBubbleCell.m | 4 +- ...tgoingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- .../Room/Views/Event/EventDetailsView.m | 4 +- .../DisabledRoomInputToolbarView.m | 2 +- .../Views/InputToolbar/RoomInputToolbarView.m | 6 +- .../Title/Expanded/ExpandedRoomTitleView.m | 6 +- .../Title/Preview/PreviewRoomTitleView.m | 8 +-- Riot/Modules/Room/Views/Title/RoomTitleView.m | 2 +- .../Views/DirectoryServerTableViewCell.m | 2 +- Riot/Modules/Rooms/RoomsViewController.m | 2 +- .../DeactivateAccountViewController.m | 2 +- .../Modules/Settings/SettingsViewController.m | 38 ++++++------ Riot/Modules/Settings/Views/DeviceView.m | 6 +- .../StartChat/StartChatViewController.m | 12 ++-- Riot/Modules/TabBar/MasterTabBarController.m | 8 +-- .../UserDevices/Views/DeviceTableViewCell.m | 4 +- Riot/Utils/AvatarGenerator.m | 2 +- Riot/Utils/EventFormatter.m | 4 +- .../Share/Listing/RoomsListViewController.m | 2 +- 79 files changed, 210 insertions(+), 210 deletions(-) rename Riot/Constants/Colors/{DarkColorValues.swift => DarkTheme.swift} (94%) rename Riot/Constants/Colors/{DefaultColorValues.swift => DefaultTheme.swift} (94%) rename Riot/Constants/Colors/{ColorValues.swift => Theme.swift} (98%) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 99c422a95..8962111f1 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -10,12 +10,12 @@ 24CBEC591F0EAD310093EABB /* RiotShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BBE81E7009EC00A9B29C /* MXRoom+Riot.m */; }; 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BC111E7009EC00A9B29C /* AvatarGenerator.m */; }; - 3223D9C021B00615000321C1 /* ColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* ColorValues.swift */; }; - 3223D9C121B00615000321C1 /* DefaultColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */; }; - 3223D9C321B0065A000321C1 /* DarkColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkColorValues.swift */; }; - 3223D9C421B0077D000321C1 /* ColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* ColorValues.swift */; }; - 3223D9C521B00781000321C1 /* DarkColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkColorValues.swift */; }; - 3223D9C621B00788000321C1 /* DefaultColorValues.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */; }; + 3223D9C021B00615000321C1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* Theme.swift */; }; + 3223D9C121B00615000321C1 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultTheme.swift */; }; + 3223D9C321B0065A000321C1 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkTheme.swift */; }; + 3223D9C421B0077D000321C1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* Theme.swift */; }; + 3223D9C521B00781000321C1 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkTheme.swift */; }; + 3223D9C621B00788000321C1 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultTheme.swift */; }; 3233F7461F3497E2006ACA81 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; }; 3233F7471F3497E2006ACA81 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3275FD8B21A5A2C500B9C13D /* TermsView.swift */; }; @@ -388,9 +388,9 @@ 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = RiotShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 2510A69B4A681C1FEC36E848 /* Pods_RiotPods_Riot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_Riot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 319CD7C67A47A3D35959E18F /* Pods-RiotPods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.release.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.release.xcconfig"; sourceTree = ""; }; - 3223D9BE21B00615000321C1 /* ColorValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ColorValues.swift; sourceTree = ""; }; - 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultColorValues.swift; sourceTree = ""; }; - 3223D9C221B0065A000321C1 /* DarkColorValues.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkColorValues.swift; sourceTree = ""; }; + 3223D9BE21B00615000321C1 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + 3223D9BF21B00615000321C1 /* DefaultTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultTheme.swift; sourceTree = ""; }; + 3223D9C221B0065A000321C1 /* DarkTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkTheme.swift; sourceTree = ""; }; 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = ""; }; 3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = ""; }; 3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; @@ -984,9 +984,9 @@ 3223D9BD21B00615000321C1 /* Colors */ = { isa = PBXGroup; children = ( - 3223D9BE21B00615000321C1 /* ColorValues.swift */, - 3223D9C221B0065A000321C1 /* DarkColorValues.swift */, - 3223D9BF21B00615000321C1 /* DefaultColorValues.swift */, + 3223D9BE21B00615000321C1 /* Theme.swift */, + 3223D9C221B0065A000321C1 /* DarkTheme.swift */, + 3223D9BF21B00615000321C1 /* DefaultTheme.swift */, ); path = Colors; sourceTree = ""; @@ -2980,16 +2980,16 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3223D9C621B00788000321C1 /* DefaultColorValues.swift in Sources */, + 3223D9C621B00788000321C1 /* DefaultTheme.swift in Sources */, B169328420F38BE300746532 /* SegmentedViewController.m in Sources */, - 3223D9C521B00781000321C1 /* DarkColorValues.swift in Sources */, + 3223D9C521B00781000321C1 /* DarkTheme.swift in Sources */, B16932AD20F3A7B100746532 /* RiotDesignValues.m in Sources */, B1664BCA20F4E67600808783 /* ShareViewController.m in Sources */, B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */, 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */, B1664BCF20F4E67600808783 /* ShareExtensionManager.m in Sources */, 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */, - 3223D9C421B0077D000321C1 /* ColorValues.swift in Sources */, + 3223D9C421B0077D000321C1 /* Theme.swift in Sources */, B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */, F0A8955F1F7D1FEA00BD6C2A /* MXRoomSummary+Riot.m in Sources */, B169328320F38AE600746532 /* RiotSettings.swift in Sources */, @@ -3116,7 +3116,7 @@ B1B5572620EE6C4D00210D55 /* RoomFilesSearchViewController.m in Sources */, B1B5583120EF66BA00210D55 /* RoomIdOrAliasTableViewCell.m in Sources */, F083BDFA1E7009ED00A9B29C /* RoomPreviewData.m in Sources */, - 3223D9C321B0065A000321C1 /* DarkColorValues.swift in Sources */, + 3223D9C321B0065A000321C1 /* DarkTheme.swift in Sources */, B1B557B420EF5AEF00210D55 /* EventDetailsView.m in Sources */, B1B5577E20EE84BF00210D55 /* IncomingCallView.m in Sources */, B1B5578F20EF568D00210D55 /* GroupTableViewCell.m in Sources */, @@ -3142,7 +3142,7 @@ B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, B1B558CF20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B5575120EE6C4D00210D55 /* AuthenticationViewController.m in Sources */, - 3223D9C121B00615000321C1 /* DefaultColorValues.swift in Sources */, + 3223D9C121B00615000321C1 /* DefaultTheme.swift in Sources */, B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */, B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */, B1B5575A20EE6C4D00210D55 /* UnifiedSearchViewController.m in Sources */, @@ -3177,7 +3177,7 @@ B1B558EE20EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.m in Sources */, B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, - 3223D9C021B00615000321C1 /* ColorValues.swift in Sources */, + 3223D9C021B00615000321C1 /* Theme.swift in Sources */, B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 4ad9ddb69..082135202 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -422,7 +422,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [NSBundle mxk_setFallbackLanguage:@"en"]; // Define the navigation bar text color - [[UINavigationBar appearance] setTintColor:RiotDesignValues.colorValues.tintColor]; + [[UINavigationBar appearance] setTintColor:RiotDesignValues.theme.tintColor]; // Customize the localized string table [NSBundle mxk_customizeLocalizedStringTableName:@"Vector"]; @@ -3542,7 +3542,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN _callStatusBarButton.titleLabel.font = [UIFont boldSystemFontOfSize:17]; } - [_callStatusBarButton setBackgroundColor:RiotDesignValues.colorValues.tintColor]; + [_callStatusBarButton setBackgroundColor:RiotDesignValues.theme.tintColor]; [_callStatusBarButton addTarget:self action:@selector(onCallStatusBarButtonPressed) forControlEvents:UIControlEventTouchUpInside]; // Place button into the new window diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index c0273351f..39c495f7c 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -209,7 +209,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT markPosY, VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH, markHeight)]; - markerView.backgroundColor = RiotDesignValues.colorValues.tintColor; + markerView.backgroundColor = RiotDesignValues.theme.tintColor; [markerView setTranslatesAutoresizingMaskIntoConstraints:NO]; markerView.accessibilityIdentifier = @"markerView"; diff --git a/Riot/Constants/Colors/DarkColorValues.swift b/Riot/Constants/Colors/DarkTheme.swift similarity index 94% rename from Riot/Constants/Colors/DarkColorValues.swift rename to Riot/Constants/Colors/DarkTheme.swift index c4c420c75..aff625b9c 100644 --- a/Riot/Constants/Colors/DarkColorValues.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -19,9 +19,9 @@ import UIKit /// Color constants for the dart theme @objcMembers -final class DarkColorValues: NSObject, ColorValues { +final class DarkTheme: NSObject, Theme { - static let shared = DarkColorValues() + static let shared = DarkTheme() let backgroundColor: UIColor = UIColor(rgb: 0x212224) diff --git a/Riot/Constants/Colors/DefaultColorValues.swift b/Riot/Constants/Colors/DefaultTheme.swift similarity index 94% rename from Riot/Constants/Colors/DefaultColorValues.swift rename to Riot/Constants/Colors/DefaultTheme.swift index 840bcc584..e13081bc6 100644 --- a/Riot/Constants/Colors/DefaultColorValues.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -19,9 +19,9 @@ import UIKit /// Color constants for the default theme @objcMembers -final class DefaultColorValues: NSObject, ColorValues { +final class DefaultTheme: NSObject, Theme { - static let shared = DefaultColorValues() + static let shared = DefaultTheme() let backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) diff --git a/Riot/Constants/Colors/ColorValues.swift b/Riot/Constants/Colors/Theme.swift similarity index 98% rename from Riot/Constants/Colors/ColorValues.swift rename to Riot/Constants/Colors/Theme.swift index b23f35cbc..7d8a9321f 100644 --- a/Riot/Constants/Colors/ColorValues.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -18,7 +18,7 @@ import UIKit /// Provide color constant values defined by the designer /// https://app.zeplin.io/project/5b857c64b1747a2c472290da/screen/5bf2cc89a4a6973f47883c6e -@objc protocol ColorValues { +@objc protocol Theme { var backgroundColor: UIColor { get } var baseColor: UIColor { get } diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index ba1ded424..586925ac9 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -17,7 +17,7 @@ #import -@protocol ColorValues; +@protocol Theme; NS_ASSUME_NONNULL_BEGIN @@ -77,9 +77,9 @@ extern UIKeyboardAppearance kRiotKeyboard; @interface RiotDesignValues : NSObject /** - The current style color constants. + The current theme. */ -+ (id)colorValues; ++ (id)theme; /** Apply the current style on a navigation bar. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 56833fbea..1113eff1f 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -124,14 +124,14 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; - (void)userInterfaceThemeDidChange { // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). - NSString *theme = RiotSettings.shared.userInterfaceTheme; + NSString *themeId = RiotSettings.shared.userInterfaceTheme; - if (!theme || [theme isEqualToString:@"auto"]) + if (!themeId || [themeId isEqualToString:@"auto"]) { - theme = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; + themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; } - if ([theme isEqualToString:@"dark"]) + if ([themeId isEqualToString:@"dark"]) { // Set dark theme colors kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; @@ -146,7 +146,7 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotKeyboard = UIKeyboardAppearanceDark; kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } - else if ([theme isEqualToString:@"black"]) + else if ([themeId isEqualToString:@"black"]) { // Set black theme colors kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; @@ -179,59 +179,59 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; } // Apply theme color constants - id colorValues = [RiotDesignValues colorValues]; + id theme = [RiotDesignValues theme]; - kRiotPrimaryBgColor = colorValues.backgroundColor; - kRiotSecondaryBgColor = colorValues.headerBackgroundColor; - kRiotPrimaryTextColor = colorValues.textPrimaryColor; - kRiotSecondaryTextColor = colorValues.textSecondaryColor; + kRiotPrimaryBgColor = theme.backgroundColor; + kRiotSecondaryBgColor = theme.headerBackgroundColor; + kRiotPrimaryTextColor = theme.textPrimaryColor; + kRiotSecondaryTextColor = theme.textSecondaryColor; - kRiotDesignNavigationBarBarTintColor = colorValues.baseColor; - kRiotDesignNavigationBarTintColor = colorValues.baseTextPrimaryColor; + kRiotDesignNavigationBarBarTintColor = theme.baseColor; + kRiotDesignNavigationBarTintColor = theme.baseTextPrimaryColor; kRiotDesignNavigationBarTitleTextAttributes = @{ - NSForegroundColorAttributeName: colorValues.baseTextPrimaryColor + NSForegroundColorAttributeName: theme.baseTextPrimaryColor }; - kRiotDesignSearchBarBarTintColor = colorValues.headerBackgroundColor; - kRiotDesignSearchBarTintColor = colorValues.searchTextColor; + kRiotDesignSearchBarBarTintColor = theme.headerBackgroundColor; + kRiotDesignSearchBarTintColor = theme.searchTextColor; - kRiotTopicTextColor = colorValues.baseTextSecondaryColor; - kRiotAuxiliaryColor = colorValues.headerTextSecondaryColor; + kRiotTopicTextColor = theme.baseTextSecondaryColor; + kRiotAuxiliaryColor = theme.headerTextSecondaryColor; [UIScrollView appearance].indicatorStyle = kRiotScrollBarStyle; [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; } -+ (id)colorValues ++ (id)theme { - id colorValues; + id theme; // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). - NSString *theme = RiotSettings.shared.userInterfaceTheme; + NSString *themeId = RiotSettings.shared.userInterfaceTheme; - if (!theme || [theme isEqualToString:@"auto"]) + if (!themeId || [themeId isEqualToString:@"auto"]) { - theme = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; + themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; } - if ([theme isEqualToString:@"dark"]) + if ([themeId isEqualToString:@"dark"]) { // Set dark theme colors - colorValues = DarkColorValues.shared; + theme = DarkTheme.shared; } - else if ([theme isEqualToString:@"black"]) + else if ([themeId isEqualToString:@"black"]) { // TODO: Use dark theme colors for the moment - colorValues = DarkColorValues.shared; + theme = DarkTheme.shared; } else { // Set light theme colors by default. - colorValues = DefaultColorValues.shared; + theme = DefaultTheme.shared; } - return colorValues; + return theme; } + (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar @@ -250,7 +250,7 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; searchBar.tintColor = kRiotDesignSearchBarTintColor; searchBar.barTintColor = kRiotDesignSearchBarBarTintColor; searchBar.layer.borderWidth = 1; - searchBar.layer.borderColor = RiotDesignValues.colorValues.headerBorderColor.CGColor; + searchBar.layer.borderColor = RiotDesignValues.theme.headerBorderColor.CGColor; } @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 292b1e58c..89f01b049 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -154,14 +154,14 @@ } } - self.submitButton.backgroundColor = RiotDesignValues.colorValues.tintColor; - self.skipButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.submitButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.skipButton.backgroundColor = RiotDesignValues.theme.tintColor; self.noFlowLabel.textColor = kRiotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; - [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.colorValues.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; + [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; [self updateForgotPwdButtonVisibility]; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 07f7a7e1d..2b15b4b58 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -115,7 +115,7 @@ [self.nextStepButton.layer setCornerRadius:5]; self.nextStepButton.clipsToBounds = YES; - self.nextStepButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.nextStepButton.backgroundColor = RiotDesignValues.theme.tintColor; if (kRiotPlaceholderTextColor) { diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index fdd1670e9..228e3c22e 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -80,7 +80,7 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie } func customizeViewRendering() { - acceptButton.backgroundColor = RiotDesignValues.colorValues().tintColor + acceptButton.backgroundColor = RiotDesignValues.theme().tintColor } diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index c829c965c..01f5c1379 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -154,13 +154,13 @@ self.sendingLabel.textColor = kRiotPrimaryTextColor; self.descriptionLabel.textColor = kRiotPrimaryTextColor; self.bugReportDescriptionTextView.textColor = kRiotPrimaryTextColor; - self.bugReportDescriptionTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.bugReportDescriptionTextView.tintColor = RiotDesignValues.theme.tintColor; self.logsDescriptionLabel.textColor = kRiotPrimaryTextColor; self.sendLogsLabel.textColor = kRiotPrimaryTextColor; self.sendScreenshotLabel.textColor = kRiotPrimaryTextColor; - self.sendButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.cancelButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.sendButton.tintColor = RiotDesignValues.theme.tintColor; + self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; _bugReportDescriptionTextView.layer.borderColor = kRiotSecondaryBgColor.CGColor; } diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index e75585353..b2cea64d1 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -106,7 +106,7 @@ self.callerNameLabel.textColor = kRiotPrimaryTextColor; self.callStatusLabel.textColor = kRiotTopicTextColor; - self.localPreviewContainerView.layer.borderColor = RiotDesignValues.colorValues.tintColor.CGColor; + self.localPreviewContainerView.layer.borderColor = RiotDesignValues.theme.tintColor.CGColor; self.localPreviewContainerView.layer.borderWidth = 2; self.localPreviewContainerView.layer.cornerRadius = 5; self.localPreviewContainerView.clipsToBounds = YES; @@ -350,7 +350,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.tintColor]; + withColor:RiotDesignValues.theme.tintColor]; } - (void)setMxCall:(MXCall *)call diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index db5bd9613..0c248c8a0 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -87,7 +87,7 @@ static const CGFloat kButtonSize = 80.0; self.callInfoLabel.text = callInfo; self.callInfoLabel.textAlignment = NSTextAlignmentCenter; - UIColor *answerButtonBorderColor = RiotDesignValues.colorValues.tintColor; + UIColor *answerButtonBorderColor = RiotDesignValues.theme.tintColor; self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"] borderColor:answerButtonBorderColor]; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 31919cd05..687d13fde 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -415,10 +415,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -426,7 +426,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 38ce18a3d..03700075c 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -54,7 +54,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -109,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h index 6259922bf..76192d5af 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h @@ -38,7 +38,7 @@ limitations under the License. @property (nonatomic) NSUInteger selectedIndex; /** - The tint color for the section header (RiotDesignValues.colorValues.accent by default). + The tint color for the section header (RiotDesignValues.theme.accent by default). */ @property (nonatomic) UIColor *sectionHeaderTintColor; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index dfdeacb1b..6a6381a06 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -136,7 +136,7 @@ // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; - self.sectionHeaderTintColor = RiotDesignValues.colorValues.tintColor; + self.sectionHeaderTintColor = RiotDesignValues.theme.tintColor; } - (void)viewDidLoad diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 23d5168c9..d583c8ef0 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -462,9 +462,9 @@ { NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextPrimaryColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.headerTextPrimaryColor}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.colorValues.headerTextSecondaryColor}]]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.headerTextSecondaryColor}]]; sectionHeader.mxkLabel.attributedText = mutableSectionTitle; } diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index e70e7ea21..105962477 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -151,7 +151,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 24ec9f1be..5b9e9f058 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -132,7 +132,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 41b5f02a7..15726aa98 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -58,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = kRiotColorBlue; self.rightButton.backgroundColor = kRiotColorBlue; - self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; + self.noticeBadgeView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index bcf3385fd..4fd7a8a34 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -742,10 +742,10 @@ NSString *roomCount = [NSString stringWithFormat:roomCountFormat, count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextSecondaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -753,7 +753,7 @@ else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.colorValues.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index b88011958..c53cc6a79 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -237,7 +237,7 @@ self.headerView.backgroundColor = kRiotSecondaryBgColor; self.contactNameLabel.textColor = kRiotPrimaryTextColor; - self.contactStatusLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.contactStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index 2d2c6d1a8..37c535486 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -38,7 +38,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.titleLabel.textColor = kRiotPrimaryTextColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index f2e4cb0f2..5e10b43c1 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -223,11 +223,11 @@ } else if ((!contact.isMatrixContact && contact.phoneNumbers.count && !contact.emailAddresses.count)) { - image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:RiotDesignValues.colorValues.tintColor]; + image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:RiotDesignValues.theme.tintColor]; } else { - image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:RiotDesignValues.colorValues.tintColor]; + image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:RiotDesignValues.theme.tintColor]; } } diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index 31ebbd3ce..b4adb1dce 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -31,10 +31,10 @@ self.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.defaultTextColor = kRiotPrimaryTextColor; - self.cancelButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.verifyButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.blockButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.confirmVerifyButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; + self.verifyButton.tintColor = RiotDesignValues.theme.tintColor; + self.blockButton.tintColor = RiotDesignValues.theme.tintColor; + self.confirmVerifyButton.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 2698f17fb..0d159cb36 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -66,7 +66,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.theme.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index bac583c42..9d1a4aa76 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -30,7 +30,7 @@ self.roomNameLabel.textColor = kRiotSecondaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index d155f7850..d718c2781 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -30,7 +30,7 @@ self.roomNameLabel.textColor = kRiotSecondaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index 5347c6fa6..e65fce10b 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -50,7 +50,7 @@ else { self.avatarImageView.image = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.tintColor]; + withColor:RiotDesignValues.theme.tintColor]; } self.titleLabel.text = roomIdOrAlias; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 810159529..9c84f9987 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -84,7 +84,7 @@ [RiotDesignValues applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.tintColor; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.theme.tintColor; if (recentsDataSource) { diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 61c5c0e40..0b74b465b 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -72,7 +72,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.colorValues.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -126,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -147,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index 6870a419d..c688d6894 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -60,10 +60,10 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell { [super customizeTableViewCellRendering]; - self.leftButton.backgroundColor = RiotDesignValues.colorValues.tintColor; - self.rightButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.leftButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.rightButton.backgroundColor = RiotDesignValues.theme.tintColor; - self.noticeBadgeView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; + self.noticeBadgeView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index e9f972901..678029e87 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -64,7 +64,7 @@ self.view.backgroundColor = kRiotPrimaryBgColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.backButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.backButton.tintColor = RiotDesignValues.theme.tintColor; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 7ce867da0..fdb0fd9be 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -386,7 +386,7 @@ if ([component.event.eventId isEqualToString:self.room.accountData.readMarkerEventId]) { bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - 2, bubbleCell.bubbleOverlayContainer.frame.size.width, 2)]; - bubbleCell.readMarkerView.backgroundColor = RiotDesignValues.colorValues.tintColor; + bubbleCell.readMarkerView.backgroundColor = RiotDesignValues.theme.tintColor; // Hide by default the marker, it will be shown and animated when the cell will be rendered. bubbleCell.readMarkerView.hidden = YES; bubbleCell.readMarkerView.tag = index; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index d2c218553..4be847828 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -225,7 +225,7 @@ self.memberHeaderView.backgroundColor = kRiotDesignNavigationBarBarTintColor; self.roomMemberNameLabel.textColor = kRiotPrimaryTextColor; - self.roomMemberStatusLabel.textColor = RiotDesignValues.colorValues.tintColor; + self.roomMemberStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); @@ -360,7 +360,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.tintColor]; + withColor:RiotDesignValues.theme.tintColor]; } - (void)updateMemberInfo diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index b021f35a2..8d6e91909 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -163,7 +163,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); @@ -1684,8 +1684,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.tintColor; - searchBar.tintColor = RiotDesignValues.colorValues.tintColor; + searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.theme.tintColor; + searchBar.tintColor = RiotDesignValues.theme.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -1696,7 +1696,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = RiotDesignValues.colorValues.tintColor; + leftImageView.tintColor = RiotDesignValues.theme.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -1707,8 +1707,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: RiotDesignValues.colorValues.tintColor, - NSForegroundColorAttributeName: RiotDesignValues.colorValues.tintColor}]; + NSUnderlineColorAttributeName: RiotDesignValues.theme.tintColor, + NSForegroundColorAttributeName: RiotDesignValues.theme.tintColor}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 1ce819780..a8fab5dfe 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -107,7 +107,7 @@ // Check the table view style to select its bg color. self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); - self.closeButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.closeButton.tintColor = RiotDesignValues.theme.tintColor; if (self.receiptsTableView.dataSource) { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index a1a3c7f47..529ffe310 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1752,7 +1752,7 @@ else { previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.tintColor]; + withColor:RiotDesignValues.theme.tintColor]; } } @@ -4230,11 +4230,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationMentionColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.colorValues.notificationUnreadColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.theme.notificationUnreadColor; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 339624776..046d9b70f 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -69,7 +69,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.colorValues.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.theme.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index ac8dd2759..8183d0404 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2213,7 +2213,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView.text = mxRoomState.topic; } - topicTextView.tintColor = RiotDesignValues.colorValues.tintColor; + topicTextView.tintColor = RiotDesignValues.theme.tintColor; topicTextView.font = [UIFont systemFontOfSize:15]; topicTextView.bounces = NO; topicTextView.delegate = self; @@ -2242,7 +2242,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti nameTextField = roomNameCell.mxkTextField; - nameTextField.tintColor = RiotDesignValues.colorValues.tintColor; + nameTextField.tintColor = RiotDesignValues.theme.tintColor; nameTextField.font = [UIFont systemFontOfSize:17]; nameTextField.borderStyle = UITextBorderStyleNone; nameTextField.textAlignment = NSTextAlignmentRight; @@ -2320,7 +2320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [leaveCell.mxkButton setTitle:title forState:UIControlStateNormal]; [leaveCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [leaveCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [leaveCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; leaveCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [leaveCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2509,7 +2509,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressTextField.text = currentValue; addAddressTextField.textColor = kRiotSecondaryTextColor; - addAddressTextField.tintColor = RiotDesignValues.colorValues.tintColor; + addAddressTextField.tintColor = RiotDesignValues.theme.tintColor; addAddressTextField.font = [UIFont systemFontOfSize:17]; addAddressTextField.borderStyle = UITextBorderStyleNone; addAddressTextField.textAlignment = NSTextAlignmentLeft; @@ -2600,7 +2600,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addGroupTextField.text = currentValue; addGroupTextField.textColor = kRiotSecondaryTextColor; - addGroupTextField.tintColor = RiotDesignValues.colorValues.tintColor; + addGroupTextField.tintColor = RiotDesignValues.theme.tintColor; addGroupTextField.font = [UIFont systemFontOfSize:17]; addGroupTextField.borderStyle = UITextBorderStyleNone; addGroupTextField.textAlignment = NSTextAlignmentLeft; @@ -2672,7 +2672,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti MXKTableViewCellWithLabelAndSwitch *roomBlacklistUnverifiedDevicesCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; [roomBlacklistUnverifiedDevicesCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevice:) forControlEvents:UIControlEventValueChanged]; - roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; roomBlacklistUnverifiedDevicesCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_blacklist_unverified_devices", @"Vector", nil); @@ -2803,7 +2803,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.mxkLabel.textColor = kRiotPrimaryTextColor; - cell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + cell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged]; // Reset the stored `directoryVisibilitySwitch` if the corresponding cell is reused. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index a1a529000..26f82538e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index e254550a0..c44b53c11 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -28,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m index 7628004b2..effc143f1 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index 47ac451f9..0a18ab22a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index 76cf9cc08..b098875da 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -28,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index d344cc2a7..ed1dcf9ce 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m index d58db9dd7..bcf756e00 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m index c538335dc..c35e92c4f 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m index cc1da021b..3536b961d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m @@ -41,7 +41,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)prepareForReuse diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m index 32194ae9d..b9ec9456d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m @@ -30,7 +30,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m index 31bfa1cf0..193a47787 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index c28fd41a7..df6953d8e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -40,7 +40,7 @@ NSString *const kRoomMembershipExpandedBubbleCellTapOnCollapseButton = @"kRoomMe self.separatorView.backgroundColor = kRiotSecondaryBgColor; - [self.collapseButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [self.collapseButton setTintColor:RiotDesignValues.theme.tintColor]; self.collapseButton.titleLabel.font = [UIFont systemFontOfSize:14]; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m index cf43c8501..3b5115d82 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m index 2b165e8ba..fd77e5da7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index 4aa88ddfa..e277347ea 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index 126331862..259adac7e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -28,9 +28,9 @@ self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m index fb4286cbc..7992756b8 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index cf23e9c73..633cba7e7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.userNameLabel.textColor = kRiotPrimaryTextColor; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m index 482512cce..55dff40d6 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.colorValues.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; + self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m index 2f0cf9460..9c65559ec 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 1bb4fdb49..3b981204d 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -28,8 +28,8 @@ self.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.textView.textColor = kRiotPrimaryTextColor; - self.redactButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.closeButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.redactButton.tintColor = RiotDesignValues.theme.tintColor; + self.closeButton.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 85bbf7142..39c727156 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -52,7 +52,7 @@ self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; self.disabledReasonTextView.textColor = kRiotPrimaryTextColor; - self.disabledReasonTextView.tintColor = RiotDesignValues.colorValues.tintColor; + self.disabledReasonTextView.tintColor = RiotDesignValues.theme.tintColor; self.disabledReasonTextView.editable = NO; self.disabledReasonTextView.scrollEnabled = NO; } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 38ad66303..4df829bb4 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -72,8 +72,8 @@ self.rightInputToolbarButton.hidden = YES; - [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.tintColor forState:UIControlStateNormal]; - [self.rightInputToolbarButton setTitleColor:RiotDesignValues.colorValues.tintColor forState:UIControlStateHighlighted]; + [self.rightInputToolbarButton setTitleColor:RiotDesignValues.theme.tintColor forState:UIControlStateNormal]; + [self.rightInputToolbarButton setTitleColor:RiotDesignValues.theme.tintColor forState:UIControlStateHighlighted]; self.isEncryptionEnabled = _isEncryptionEnabled; } @@ -96,7 +96,7 @@ growingTextView.font = [UIFont systemFontOfSize:15]; growingTextView.textColor = kRiotPrimaryTextColor; - growingTextView.tintColor = RiotDesignValues.colorValues.tintColor; + growingTextView.tintColor = RiotDesignValues.theme.tintColor; growingTextView.internalTextView.keyboardAppearance = kRiotKeyboard; } diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index 292a6b939..734a93c50 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -40,11 +40,11 @@ [super layoutSubviews]; self.membersListIcon.image = [MXKTools paintImage:self.membersListIcon.image - withColor:RiotDesignValues.colorValues.tintColor]; + withColor:RiotDesignValues.theme.tintColor]; // TODO: paintImage does not work here because addParticipantIcon has 2 colors // self.addParticipantIcon.image = [MXKTools paintImage:self.addParticipantIcon.image -// withColor:RiotDesignValues.colorValues.accent]; +// withColor:RiotDesignValues.theme.accent]; } -(void)customizeViewRendering @@ -52,7 +52,7 @@ [super customizeViewRendering]; self.roomTopic.textColor = kRiotTopicTextColor; - self.roomMembers.textColor = RiotDesignValues.colorValues.tintColor; + self.roomMembers.textColor = RiotDesignValues.theme.tintColor; } - (void)refreshDisplay diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 518ebcaee..bf751f1b6 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -69,7 +69,7 @@ self.roomTopic.textColor = kRiotTopicTextColor; - self.roomMembers.textColor = RiotDesignValues.colorValues.tintColor; + self.roomMembers.textColor = RiotDesignValues.theme.tintColor; self.previewLabel.textColor = kRiotTopicTextColor; self.previewLabel.numberOfLines = 0; @@ -81,11 +81,11 @@ [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; - self.leftButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.leftButton.backgroundColor = RiotDesignValues.theme.tintColor; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - self.rightButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.rightButton.backgroundColor = RiotDesignValues.theme.tintColor; } - (void)refreshDisplay @@ -103,7 +103,7 @@ toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.tintColor] + withColor:RiotDesignValues.theme.tintColor] mediaManager:self.mxRoom.mxSession.mediaManager]; } else diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 0a8cf2bea..40456474e 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -73,7 +73,7 @@ [super layoutSubviews]; self.roomDetailsIconImageView.image = [MXKTools paintImage:self.roomDetailsIconImageView.image - withColor:RiotDesignValues.colorValues.tintColor]; + withColor:RiotDesignValues.theme.tintColor]; if (self.superview) { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 97d406ed9..675c5b4d2 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -64,7 +64,7 @@ withType:nil andImageOrientation:UIImageOrientationUp previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.colorValues.tintColor] + withColor:RiotDesignValues.theme.tintColor] mediaManager:cellData.mediaManager]; } else diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index b3456a174..9e5a9e7f3 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -64,7 +64,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.colorValues.tintColor; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.theme.tintColor; if ([self.dataSource isKindOfClass:RecentsDataSource.class]) { diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index cd9fb0204..ed9451721 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -166,7 +166,7 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; self.deactivateAcccountButton.layer.masksToBounds = YES; - self.deactivateAcccountButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.deactivateAcccountButton.backgroundColor = RiotDesignValues.theme.tintColor; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; [self.deactivateAcccountButton setTitleColor:kRiotAuxiliaryColor forState:UIControlStateDisabled]; } diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 9c182183c..e965e52f1 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1404,7 +1404,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); [signOutCell.mxkButton setTitle:title forState:UIControlStateNormal]; [signOutCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [signOutCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [signOutCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; signOutCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [signOutCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1559,7 +1559,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newEmailTextField = newEmailCell.mxkTextField; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.tintColor]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.theme.tintColor]; newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; } @@ -1652,7 +1652,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newPhoneNumberCell = newPhoneCell; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.colorValues.tintColor]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.theme.tintColor]; newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; cell = newPhoneCell; @@ -1695,7 +1695,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_push_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.isPushKitNotificationActive; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePushNotifications:) forControlEvents:UIControlEventTouchUpInside]; @@ -1707,7 +1707,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_show_decrypted_content", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.showDecryptedContentInNotifications; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = account.isPushKitNotificationActive; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleShowDecodedContent:) forControlEvents:UIControlEventTouchUpInside]; @@ -1733,7 +1733,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_missed_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithMissedNotif:) forControlEvents:UIControlEventTouchUpInside]; @@ -1745,7 +1745,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_unread", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithUnread:) forControlEvents:UIControlEventTouchUpInside]; @@ -1759,7 +1759,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside]; @@ -1864,7 +1864,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.numberOfLines = 0; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_contacts_discover_matrix_users", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].syncLocalContacts; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLocalContactsSync:) forControlEvents:UIControlEventTouchUpInside]; @@ -1973,7 +1973,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); sendCrashReportCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_send_crash_report", @"Vector", nil); sendCrashReportCell.mxkSwitch.on = RiotSettings.shared.enableCrashReport; - sendCrashReportCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + sendCrashReportCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; sendCrashReportCell.mxkSwitch.enabled = YES; [sendCrashReportCell.mxkSwitch addTarget:self action:@selector(toggleSendCrashReport:) forControlEvents:UIControlEventTouchUpInside]; @@ -1985,7 +1985,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); enableRageShakeCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_rageshake", @"Vector", nil); enableRageShakeCell.mxkSwitch.on = RiotSettings.shared.enableRageShake; - enableRageShakeCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + enableRageShakeCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; enableRageShakeCell.mxkSwitch.enabled = YES; [enableRageShakeCell.mxkSwitch addTarget:self action:@selector(toggleEnableRageShake:) forControlEvents:UIControlEventTouchUpInside]; @@ -2007,7 +2007,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_mark_all_as_read", @"Vector", nil); [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [markAllBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [markAllBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; markAllBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [markAllBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2032,7 +2032,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_clear_cache", @"Vector", nil); [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [clearCacheBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [clearCacheBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; clearCacheBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [clearCacheBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2057,7 +2057,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_report_bug", @"Vector", nil); [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [reportBugBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [reportBugBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; reportBugBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [reportBugBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2077,7 +2077,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; labelAndSwitchCell.mxkSwitch.on = account.mxSession.syncWithLazyLoadOfRoomMembers; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleSyncWithLazyLoadOfRoomMembers:) forControlEvents:UIControlEventTouchUpInside]; @@ -2089,7 +2089,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_create_conference_with_jitsi", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.createConferenceCallsWithJitsi; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleJitsiForConference:) forControlEvents:UIControlEventTouchUpInside]; @@ -2103,7 +2103,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_e2e_encryption", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = (nil != session.crypto); - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLabsEndToEndEncryption:) forControlEvents:UIControlEventTouchUpInside]; @@ -2177,7 +2177,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_crypto_blacklist_unverified_devices", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.mxSession.crypto.globalBlacklistUnverifiedDevices; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.colorValues.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevices:) forControlEvents:UIControlEventTouchUpInside]; @@ -2199,7 +2199,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_crypto_export", @"Vector", nil); [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [exportKeysBtnCell.mxkButton setTintColor:RiotDesignValues.colorValues.tintColor]; + [exportKeysBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; exportKeysBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [exportKeysBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 4545ef02f..2726bcf63 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -31,9 +31,9 @@ self.containerView.backgroundColor = kRiotSecondaryBgColor; self.textView.backgroundColor = kRiotPrimaryBgColor; self.defaultTextColor = kRiotPrimaryTextColor; - self.cancelButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.deleteButton.tintColor = RiotDesignValues.colorValues.tintColor; - self.renameButton.tintColor = RiotDesignValues.colorValues.tintColor; + self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; + self.deleteButton.tintColor = RiotDesignValues.theme.tintColor; + self.renameButton.tintColor = RiotDesignValues.theme.tintColor; } @end diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index f9c22e975..15864e485 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -149,7 +149,7 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.colorValues.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); @@ -621,8 +621,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.colorValues.tintColor; - searchBar.tintColor = RiotDesignValues.colorValues.tintColor; + searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.theme.tintColor; + searchBar.tintColor = RiotDesignValues.theme.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -633,7 +633,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = RiotDesignValues.colorValues.tintColor; + leftImageView.tintColor = RiotDesignValues.theme.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -646,8 +646,8 @@ { searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: RiotDesignValues.colorValues.tintColor, - NSForegroundColorAttributeName: RiotDesignValues.colorValues.tintColor}]; + NSUnderlineColorAttributeName: RiotDesignValues.theme.tintColor, + NSForegroundColorAttributeName: RiotDesignValues.theme.tintColor}]; } } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 9391cc0e5..d608eab79 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -116,7 +116,7 @@ { [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.tabBar.tintColor = RiotDesignValues.colorValues.tintColor; + self.tabBar.tintColor = RiotDesignValues.theme.tintColor; self.tabBar.barTintColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; @@ -798,15 +798,15 @@ // Use a middle dot to signal missed notif in favourites [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX - withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor)]; // Update the badge on People and Rooms tabs [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX - withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor)]; [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX - withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? RiotDesignValues.colorValues.notificationMentionColor : RiotDesignValues.colorValues.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 269f4eac1..bf79becc5 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -36,11 +36,11 @@ [self.verifyButton.layer setCornerRadius:5]; self.verifyButton.clipsToBounds = YES; - self.verifyButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.verifyButton.backgroundColor = RiotDesignValues.theme.tintColor; [self.blockButton.layer setCornerRadius:5]; self.blockButton.clipsToBounds = YES; - self.blockButton.backgroundColor = RiotDesignValues.colorValues.tintColor; + self.blockButton.backgroundColor = RiotDesignValues.theme.tintColor; } - (void)render:(MXDeviceInfo *)deviceInfo diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index dd559682d..aa18ab526 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -39,7 +39,7 @@ static UILabel* backgroundLabel = nil; { if (!colorsList) { - colorsList = RiotDesignValues.colorValues.avatarColors; + colorsList = RiotDesignValues.theme.avatarColors; } } diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index fe2fa731e..02003526b 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -220,8 +220,8 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.defaultTextColor = kRiotPrimaryTextColor; self.subTitleTextColor = kRiotSecondaryTextColor; self.prefixTextColor = kRiotSecondaryTextColor; - self.bingTextColor = RiotDesignValues.colorValues.notificationMentionColor; - self.encryptingTextColor = RiotDesignValues.colorValues.tintColor; + self.bingTextColor = RiotDesignValues.theme.notificationMentionColor; + self.encryptingTextColor = RiotDesignValues.theme.tintColor; self.sendingTextColor = kRiotSecondaryTextColor; self.errorTextColor = kRiotColorRed; diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m index a27048d17..1a80aad7a 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m @@ -96,7 +96,7 @@ self.recentsSearchBar.searchBarStyle = UISearchBarStyleMinimal; self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); - self.recentsSearchBar.tintColor = RiotDesignValues.colorValues.tintColor; + self.recentsSearchBar.tintColor = RiotDesignValues.theme.tintColor; _tableSearchBar.tintColor = self.recentsSearchBar.tintColor; } From 3bacf204d5a99d25f544e3e346154222535c8776 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 16:35:34 +0100 Subject: [PATCH 033/244] reskin: Delegate navigation and search bars styling to theme --- Riot/Categories/UIViewController+RiotSearch.m | 3 ++- Riot/Constants/Colors/DarkTheme.swift | 20 +++++++++++++++++++ Riot/Constants/Colors/DefaultTheme.swift | 19 ++++++++++++++++++ Riot/Constants/Colors/Theme.swift | 12 +++++++++++ Riot/Constants/RiotDesignValues.h | 14 ------------- Riot/Constants/RiotDesignValues.m | 19 ------------------ .../AuthenticationViewController.m | 2 +- .../Authentication/Views/AuthInputsView.m | 2 +- .../BugReport/BugReportViewController.m | 2 +- Riot/Modules/Call/CallViewController.m | 4 ++-- .../Common/Recents/RecentsViewController.m | 7 ++++--- .../SegmentedViewController.m | 2 +- .../WebViewController/WebViewViewController.m | 3 ++- .../Communities/GroupsViewController.m | 6 +++--- .../Home/GroupHomeViewController.m | 3 ++- .../Members/GroupParticipantsViewController.m | 2 +- .../Rooms/GroupRoomsViewController.m | 2 +- .../Contacts/ContactsTableViewController.m | 3 ++- .../Details/ContactDetailsViewController.m | 2 +- .../Files/HomeFilesSearchViewController.m | 3 ++- .../HomeMessagesSearchViewController.m | 3 ++- .../Rooms/DirectoryViewController.m | 3 ++- Riot/Modules/Home/HomeViewController.m | 2 +- .../Library/MediaAlbumContentViewController.m | 4 +++- .../MediaPicker/MediaPickerViewController.m | 3 ++- .../Attachements/AttachmentsViewController.m | 2 +- .../Room/Files/RoomFilesViewController.m | 3 ++- .../Detail/RoomMemberDetailsViewController.m | 2 +- .../Members/RoomParticipantsViewController.m | 2 +- .../ReadReceiptsViewController.m | 2 +- Riot/Modules/Room/RoomViewController.m | 2 +- .../Files/RoomFilesSearchViewController.m | 3 ++- .../RoomMessagesSearchViewController.m | 3 ++- .../Settings/RoomSettingsViewController.m | 2 +- .../DirectoryServerPickerViewController.m | 3 ++- .../DeactivateAccountViewController.m | 2 +- .../Language/LanguagePickerViewController.m | 5 +++-- .../CountryPickerViewController.m | 5 +++-- .../Modules/Settings/SettingsViewController.m | 2 +- Riot/Modules/TabBar/MasterTabBarController.m | 2 +- .../UserDevices/UsersDevicesViewController.m | 3 ++- 41 files changed, 112 insertions(+), 76 deletions(-) diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index 006979c1d..32da56edf 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -20,6 +20,7 @@ #import #import "RiotDesignValues.h" +#import "Riot-Swift.h" /** `UIViewControllerRiotSearchInternals` is the internal single point storage for the search feature. @@ -94,7 +95,7 @@ self.searchBar.text = @""; // Customize search bar - [RiotDesignValues applyStyleOnSearchBar:self.searchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; // Remove navigation buttons self.navigationItem.hidesBackButton = YES; diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index aff625b9c..08164c08f 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -50,4 +50,24 @@ final class DarkTheme: NSObject, Theme { UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] + + + func applyStyle(onNavigationBar navigationBar: UINavigationBar) { + navigationBar.tintColor = self.baseTextPrimaryColor; + navigationBar.titleTextAttributes = [ + NSAttributedStringKey.foregroundColor: self.baseTextPrimaryColor + ] + navigationBar.barTintColor = self.baseColor; + + // The navigation bar needs to be opaque so that its background color is the expected one + navigationBar.isTranslucent = false; + } + + func applyStyle(onSearchBar searchBar: UISearchBar) { + searchBar.barStyle = .black + searchBar.tintColor = self.searchTextColor; + searchBar.barTintColor = self.headerBackgroundColor; + searchBar.layer.borderWidth = 1; + searchBar.layer.borderColor = self.headerBorderColor.cgColor; + } } diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index e13081bc6..e916917f0 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -50,4 +50,23 @@ final class DefaultTheme: NSObject, Theme { UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] + + func applyStyle(onNavigationBar navigationBar: UINavigationBar) { + navigationBar.tintColor = self.baseTextPrimaryColor; + navigationBar.titleTextAttributes = [ + NSAttributedStringKey.foregroundColor: self.baseTextPrimaryColor + ] + navigationBar.barTintColor = self.baseColor; + + // The navigation bar needs to be opaque so that its background color is the expected one + navigationBar.isTranslucent = false; + } + + func applyStyle(onSearchBar searchBar: UISearchBar) { + searchBar.barStyle = .default + searchBar.tintColor = self.searchTextColor; + searchBar.barTintColor = self.headerBackgroundColor; + searchBar.layer.borderWidth = 1; + searchBar.layer.borderColor = self.headerBorderColor.cgColor; + } } diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index 7d8a9321f..cfb6e8c7e 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -45,8 +45,20 @@ import UIKit var notificationMentionColor: UIColor { get } var avatarColors: [UIColor] { get } + + /// Apply the theme on a navigation bar + /// + /// - Parameter navigationBar: the navigation bar to customise. + func applyStyle(onNavigationBar: UINavigationBar) + + /// Apply the theme on a search bar. + /// + /// - Parameter searchBar: the search bar to customise. + func applyStyle(onSearchBar: UISearchBar) } + +/// TODO: to move extension UIColor { convenience init(rgb: UInt) { self.init( diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 586925ac9..b242f8662 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -81,20 +81,6 @@ extern UIKeyboardAppearance kRiotKeyboard; */ + (id)theme; -/** - Apply the current style on a navigation bar. - - @param navigationBar the navigation bar to customise. - */ -+ (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar; - -/** - Apply the current style on a search bar. - - @param searchBar the search bar to customise. - */ -+ (void)applyStyleOnSearchBar:(UISearchBar *)searchBar; - @end NS_ASSUME_NONNULL_END diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 1113eff1f..e75f913b3 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -234,23 +234,4 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; return theme; } -+ (void)applyStyleOnNavigationBar:(UINavigationBar *)navigationBar -{ - navigationBar.tintColor = kRiotDesignNavigationBarTintColor; - navigationBar.titleTextAttributes = kRiotDesignNavigationBarTitleTextAttributes; - navigationBar.barTintColor = kRiotDesignNavigationBarBarTintColor; - - // The navigation bar needs to be opaque so that its background color is the expected one - navigationBar.translucent = NO; -} - -+ (void)applyStyleOnSearchBar:(UISearchBar *)searchBar -{ - searchBar.barStyle = kRiotDesignSearchBarStyle; - searchBar.tintColor = kRiotDesignSearchBarTintColor; - searchBar.barTintColor = kRiotDesignSearchBarBarTintColor; - searchBar.layer.borderWidth = 1; - searchBar.layer.borderColor = RiotDesignValues.theme.headerBorderColor.CGColor; -} - @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 89f01b049..a2edaad4a 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -131,7 +131,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.view.backgroundColor = kRiotSecondaryBgColor; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index cfba5e511..e801b1e26 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -1149,7 +1149,7 @@ phoneNumberPickerNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - [RiotDesignValues applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; [phoneNumberPickerNavigationController pushViewController:phoneNumberCountryPicker animated:NO]; diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 01f5c1379..5f5a84af0 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -138,7 +138,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index b2cea64d1..da3a648a9 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -98,7 +98,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.barTitleColor = kRiotPrimaryTextColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; @@ -283,7 +283,7 @@ UINavigationController *usersDevicesNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - [RiotDesignValues applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; usersDevicesNavigationController.navigationBar.barTintColor = kRiotPrimaryBgColor; [usersDevicesNavigationController pushViewController:usersDevicesViewController animated:NO]; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 3a721d92d..aa341b452 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -33,6 +33,7 @@ #import "RoomIdOrAliasTableViewCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface RecentsViewController () { @@ -158,7 +159,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; @@ -167,8 +168,8 @@ topview.backgroundColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; - [RiotDesignValues applyStyleOnSearchBar:tableSearchBar]; - [RiotDesignValues applyStyleOnSearchBar:self.recentsSearchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:self.recentsSearchBar]; if (self.recentsTableView.dataSource) { diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 6a6381a06..780742130 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -178,7 +178,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index 446bc19ff..fd8184b00 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -16,6 +16,7 @@ #import "WebViewViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface WebViewViewController () { @@ -51,7 +52,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index d583c8ef0..4ba5406f3 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -116,7 +116,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; @@ -125,8 +125,8 @@ topview.backgroundColor = kRiotSecondaryBgColor; self.view.backgroundColor = kRiotPrimaryBgColor; - [RiotDesignValues applyStyleOnSearchBar:tableSearchBar]; - [RiotDesignValues applyStyleOnSearchBar:self.groupsSearchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:self.groupsSearchBar]; if (self.groupsTableView.dataSource) { diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index f37f2d457..c30cb8846 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -18,6 +18,7 @@ #import "GroupHomeViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "RiotDesignValues.h" #import "Tools.h" @@ -112,7 +113,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 105962477..bedfda86f 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -145,7 +145,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 5b9e9f058..214678672 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -126,7 +126,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index a03a99932..697b30250 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -20,6 +20,7 @@ #import "UIViewController+RiotSearch.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #define CONTACTS_TABLEVC_LOCALCONTACTS_BITWISE 0x01 #define CONTACTS_TABLEVC_USERDIRECTORY_BITWISE 0x02 @@ -103,7 +104,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index c53cc6a79..c6cda14e9 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -231,7 +231,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 01c7fa0bb..02ca050b1 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -18,6 +18,7 @@ #import "HomeFilesSearchViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "HomeViewController.h" @@ -70,7 +71,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index 4c866d55b..c8da434ca 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -18,6 +18,7 @@ #import "HomeMessagesSearchViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "HomeViewController.h" @@ -77,7 +78,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index 1f0a74083..d59633588 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -20,6 +20,7 @@ #import "PublicRoomsDirectoryDataSource.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface DirectoryViewController () { @@ -70,7 +71,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 9c84f9987..b1cfe2673 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -82,7 +82,7 @@ [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_home", @"Vector", nil); - [RiotDesignValues applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index de547b17c..750f92532 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -21,6 +21,8 @@ #import +#import "Riot-Swift.h" + @interface MediaAlbumContentViewController () { /** @@ -111,7 +113,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.assetsCollectionView.backgroundColor = kRiotPrimaryBgColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index d4950ce8f..1df3e6c79 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -18,6 +18,7 @@ #import "MediaPickerViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import @@ -181,7 +182,7 @@ static void *RecordingContext = &RecordingContext; - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 678029e87..242bbb21a 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -59,7 +59,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.view.backgroundColor = kRiotPrimaryBgColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 143c032d2..f51d94fcf 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -20,6 +20,7 @@ #import "FilesSearchTableViewCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "AttachmentsViewController.h" @@ -109,7 +110,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 4be847828..1ab01ec6a 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -218,7 +218,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 8d6e91909..c13d4ab6b 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -157,7 +157,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index a8fab5dfe..7686bd5cc 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -94,7 +94,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 529ffe310..89715d07a 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -418,7 +418,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index 582e4dd97..8929a9a18 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -25,6 +25,7 @@ #import "FilesSearchTableViewCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface RoomFilesSearchViewController () { @@ -71,7 +72,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index 4f3f3af11..47cbcd431 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -27,6 +27,7 @@ #import "RoomIncomingTextMsgBubbleCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface RoomMessagesSearchViewController () { @@ -72,7 +73,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 8183d0404..9df65078e 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -266,7 +266,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index ecb97c2b5..36a0fdbaf 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -19,6 +19,7 @@ #import "DirectoryServerDetailTableViewCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface DirectoryServerPickerViewController () { @@ -119,7 +120,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index ed9451721..a7db11c09 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -123,7 +123,7 @@ static CGFloat const kTextFontSize = 15.0; - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; } diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index 6361142fd..2e904998f 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -17,6 +17,7 @@ #import "LanguagePickerViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface LanguagePickerViewController () { @@ -68,11 +69,11 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; - [RiotDesignValues applyStyleOnSearchBar:self.searchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. self.tableView.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 1fb5c59df..add706c81 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -17,6 +17,7 @@ #import "CountryPickerViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface CountryPickerViewController () { @@ -71,11 +72,11 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; - [RiotDesignValues applyStyleOnSearchBar:self.searchBar]; + [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. self.tableView.backgroundColor = kRiotPrimaryBgColor; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index e965e52f1..7a58501b8 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -334,7 +334,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index d608eab79..5156c9213 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -114,7 +114,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.tabBar.tintColor = RiotDesignValues.theme.tintColor; self.tabBar.barTintColor = kRiotSecondaryBgColor; diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 70692e8a3..1c8b575cb 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -18,6 +18,7 @@ #import "UsersDevicesViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface UsersDevicesViewController () { @@ -81,7 +82,7 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.activityIndicator.backgroundColor = kRiotOverlayColor; From 7b40258d050d8a9c2a2384b7977db702d868a0a9 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 17:08:32 +0100 Subject: [PATCH 034/244] reskin: remove bar style ivars from RiotDesignValues --- Riot/Constants/Colors/DarkTheme.swift | 1 + Riot/Constants/Colors/DefaultTheme.swift | 2 ++ Riot/Constants/Colors/Theme.swift | 2 ++ Riot/Constants/RiotDesignValues.h | 10 ------- Riot/Constants/RiotDesignValues.m | 28 ------------------- .../AuthenticationViewController.m | 2 +- .../BugReport/BugReportViewController.m | 2 +- .../Common/Recents/RecentsViewController.m | 2 +- .../SegmentedViewController.m | 2 +- .../WebViewController/WebViewViewController.m | 2 +- .../Communities/GroupsViewController.m | 2 +- .../Home/GroupHomeViewController.m | 2 +- .../Members/GroupParticipantsViewController.m | 2 +- .../Rooms/GroupRoomsViewController.m | 2 +- .../TabDetail/GroupDetailsViewController.m | 3 +- .../Contacts/ContactsTableViewController.m | 2 +- .../Details/ContactDetailsViewController.m | 2 +- .../Files/HomeFilesSearchViewController.m | 2 +- .../HomeMessagesSearchViewController.m | 2 +- .../Rooms/DirectoryViewController.m | 2 +- .../Library/MediaAlbumContentViewController.m | 2 +- .../MediaPicker/MediaPickerViewController.m | 2 +- .../Room/Files/RoomFilesViewController.m | 2 +- .../Detail/RoomMemberDetailsViewController.m | 4 +-- .../Members/RoomParticipantsViewController.m | 2 +- .../ReadReceiptsViewController.m | 2 +- Riot/Modules/Room/RoomViewController.m | 2 +- .../Files/RoomFilesSearchViewController.m | 2 +- .../RoomMessagesSearchViewController.m | 2 +- .../Settings/RoomSettingsViewController.m | 2 +- .../Title/Preview/PreviewRoomTitleView.m | 2 +- Riot/Modules/Room/Views/Title/RoomTitleView.m | 6 ++-- .../DirectoryServerPickerViewController.m | 2 +- .../DeactivateAccountViewController.m | 2 +- .../Language/LanguagePickerViewController.m | 2 +- .../CountryPickerViewController.m | 2 +- .../Modules/Settings/SettingsViewController.m | 2 +- .../StartChat/StartChatViewController.m | 2 +- Riot/Modules/TabBar/MasterTabBarController.m | 2 +- .../UserDevices/UsersDevicesViewController.m | 2 +- 40 files changed, 44 insertions(+), 76 deletions(-) diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index 08164c08f..747418af6 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -51,6 +51,7 @@ final class DarkTheme: NSObject, Theme { UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] + let statusBarStyle: UIStatusBarStyle = .lightContent func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index e916917f0..f8e97cc9b 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -51,6 +51,8 @@ final class DefaultTheme: NSObject, Theme { UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] + let statusBarStyle: UIStatusBarStyle = .lightContent + func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; navigationBar.titleTextAttributes = [ diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index cfb6e8c7e..866e8d13e 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -46,6 +46,8 @@ import UIKit var avatarColors: [UIColor] { get } + var statusBarStyle: UIStatusBarStyle { get } + /// Apply the theme on a navigation bar /// /// - Parameter navigationBar: the navigation bar to customise. diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index b242f8662..f7e25c681 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -59,16 +59,6 @@ extern UIColor *kRiotColorOrange; extern NSInteger const kRiotRoomModeratorLevel; extern NSInteger const kRiotRoomAdminLevel; -#pragma mark - Riot bar style -extern UIStatusBarStyle kRiotDesignStatusBarStyle; -extern UIColor *kRiotDesignNavigationBarTintColor; -extern UIColor *kRiotDesignNavigationBarBarTintColor; -extern NSDictionary *kRiotDesignNavigationBarTitleTextAttributes; - -extern UIBarStyle kRiotDesignSearchBarStyle; -extern UIColor *kRiotDesignSearchBarTintColor; -extern UIColor *kRiotDesignSearchBarBarTintColor; - extern UIKeyboardAppearance kRiotKeyboard; /** diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index e75f913b3..285f4872f 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -52,15 +52,6 @@ UIColor *kRiotColorDarkKeyboard; // TO REMOVE NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; -UIStatusBarStyle kRiotDesignStatusBarStyle = UIStatusBarStyleDefault; -UIColor *kRiotDesignNavigationBarTintColor; -UIColor *kRiotDesignNavigationBarBarTintColor; -NSDictionary *kRiotDesignNavigationBarTitleTextAttributes; - -UIBarStyle kRiotDesignSearchBarStyle = UIBarStyleDefault; -UIColor *kRiotDesignSearchBarTintColor = nil; -UIColor *kRiotDesignSearchBarBarTintColor = nil; - UIKeyboardAppearance kRiotKeyboard; UIScrollViewIndicatorStyle kRiotScrollBarStyle; @@ -136,9 +127,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Set dark theme colors kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; kRiotSelectedBgColor = [UIColor blackColor]; - - kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; - kRiotDesignSearchBarStyle = UIBarStyleBlack; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; kRiotKeyboardColor = kRiotColorDarkKeyboard; @@ -151,9 +139,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Set black theme colors kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; kRiotSelectedBgColor = [UIColor blackColor]; - - kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; - kRiotDesignSearchBarStyle = UIBarStyleBlack; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; kRiotKeyboardColor = kRiotColorDarkKeyboard; @@ -166,10 +151,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Set light theme colors by default. kRiotPlaceholderTextColor = nil; // Use default 70% gray color. kRiotSelectedBgColor = nil; // Use the default selection color. - - kRiotDesignStatusBarStyle = UIStatusBarStyleLightContent; - - kRiotDesignSearchBarStyle = UIBarStyleDefault; kRiotOverlayColor = [UIColor colorWithWhite:0.7 alpha:0.5]; kRiotKeyboardColor = kRiotColorLightKeyboard; @@ -186,15 +167,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotPrimaryTextColor = theme.textPrimaryColor; kRiotSecondaryTextColor = theme.textSecondaryColor; - kRiotDesignNavigationBarBarTintColor = theme.baseColor; - kRiotDesignNavigationBarTintColor = theme.baseTextPrimaryColor; - kRiotDesignNavigationBarTitleTextAttributes = @{ - NSForegroundColorAttributeName: theme.baseTextPrimaryColor - }; - - kRiotDesignSearchBarBarTintColor = theme.headerBackgroundColor; - kRiotDesignSearchBarTintColor = theme.searchTextColor; - kRiotTopicTextColor = theme.baseTextSecondaryColor; kRiotAuxiliaryColor = theme.headerTextSecondaryColor; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index a2edaad4a..4ad6865ae 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -185,7 +185,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 5f5a84af0..87bc824bf 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -167,7 +167,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index aa341b452..ea1d651bb 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -180,7 +180,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 780742130..5baff1cc9 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -187,7 +187,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index fd8184b00..2bf189a44 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -61,7 +61,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 4ba5406f3..6529b08cd 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -137,7 +137,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index c30cb8846..4f1f511a6 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -170,7 +170,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index bedfda86f..31c0fe5fd 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -172,7 +172,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 214678672..68f2578de 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -146,7 +146,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m index 45f24d431..c56b83804 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m @@ -21,6 +21,7 @@ #import "GroupRoomsViewController.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface GroupDetailsViewController () { @@ -121,7 +122,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 697b30250..babeafeac 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -120,7 +120,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)didReceiveMemoryWarning diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index c6cda14e9..3bd61c627 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -251,7 +251,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 02ca050b1..ef84b2644 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -89,7 +89,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index c8da434ca..db81962cf 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -96,7 +96,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index d59633588..870913b56 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -87,7 +87,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index 750f92532..585a3906c 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -121,7 +121,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index 1df3e6c79..eab761580 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -195,7 +195,7 @@ static void *RecordingContext = &RecordingContext; - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index f51d94fcf..7f45ba55d 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -126,7 +126,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 1ab01ec6a..66e946d59 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -223,7 +223,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.memberHeaderView.backgroundColor = kRiotDesignNavigationBarBarTintColor; + self.memberHeaderView.backgroundColor = RiotDesignValues.theme.baseColor; self.roomMemberNameLabel.textColor = kRiotPrimaryTextColor; self.roomMemberStatusLabel.textColor = RiotDesignValues.theme.tintColor; @@ -239,7 +239,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index c13d4ab6b..2ab8a29d9 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -184,7 +184,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 7686bd5cc..1ec666e22 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -118,7 +118,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 89715d07a..8caf471e7 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -447,7 +447,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)didReceiveMemoryWarning diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index 8929a9a18..31949524b 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -90,7 +90,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index 47cbcd431..636824993 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -91,7 +91,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 9df65078e..68ea4914d 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -282,7 +282,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index bf751f1b6..499c08380 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -64,7 +64,7 @@ [super customizeViewRendering]; // Use same color as navigation bar - self.mainHeaderBackground.backgroundColor = kRiotDesignNavigationBarBarTintColor; + self.mainHeaderBackground.backgroundColor = RiotDesignValues.theme.baseColor; self.roomTopic.textColor = kRiotTopicTextColor; diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 40456474e..fbd068589 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -138,8 +138,8 @@ [super customizeViewRendering]; // Use same color as navigation bar - self.backgroundColor = kRiotDesignNavigationBarBarTintColor; - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? kRiotDesignNavigationBarTintColor : kRiotSecondaryTextColor); + self.backgroundColor = RiotDesignValues.theme.baseColor; + self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? RiotDesignValues.theme.baseTextPrimaryColor : kRiotSecondaryTextColor); } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -168,7 +168,7 @@ } else { - self.displayNameTextField.textColor = kRiotDesignNavigationBarTintColor; + self.displayNameTextField.textColor = RiotDesignValues.theme.baseTextPrimaryColor; } } } diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index 36a0fdbaf..af2e847d3 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -136,7 +136,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index a7db11c09..8617b6c02 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -109,7 +109,7 @@ static CGFloat const kTextFontSize = 15.0; - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } #pragma mark - Private diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index 2e904998f..e92d41ee6 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -87,7 +87,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index add706c81..078b41224 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -91,7 +91,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 7a58501b8..2177a21fa 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -350,7 +350,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)didReceiveMemoryWarning diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 15864e485..63be60b60 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -163,7 +163,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 5156c9213..bb81aeaf9 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -126,7 +126,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 1c8b575cb..7e01d9c44 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -98,7 +98,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return kRiotDesignStatusBarStyle; + return RiotDesignValues.theme.statusBarStyle; } - (void)destroy From 0f3cf8ec95012b3a02144bc42448898f84fe0473 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 17:36:36 +0100 Subject: [PATCH 035/244] reskin: Kill RiotDesignValues.kRiotKeyboardColor and replace it by Theme.matrixSearchBackgroundImageTintColor --- Riot/Categories/UIViewController+RiotSearch.m | 2 +- Riot/Constants/Colors/DarkTheme.swift | 2 ++ Riot/Constants/Colors/DefaultTheme.swift | 2 ++ Riot/Constants/Colors/Theme.swift | 12 ++++++++++++ Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 10 ---------- .../GlobalSearch/UnifiedSearchViewController.m | 3 ++- Riot/Modules/Room/Search/RoomSearchViewController.m | 3 ++- 8 files changed, 21 insertions(+), 14 deletions(-) diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index 32da56edf..3845c3072 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -134,7 +134,7 @@ - (void)addBackgroundImageViewToView:(UIView*)view { - UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:kRiotKeyboardColor]; + UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:RiotDesignValues.theme.matrixSearchBackgroundImageTintColor]; UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:searchBgImage]; backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO; diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index 747418af6..08ad427d6 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -53,6 +53,8 @@ final class DarkTheme: NSObject, Theme { let statusBarStyle: UIStatusBarStyle = .lightContent + let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) + func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; navigationBar.titleTextAttributes = [ diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index f8e97cc9b..0ea09155c 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -53,6 +53,8 @@ final class DefaultTheme: NSObject, Theme { let statusBarStyle: UIStatusBarStyle = .lightContent + let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) + func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; navigationBar.titleTextAttributes = [ diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index 866e8d13e..ef4e61987 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -46,8 +46,20 @@ import UIKit var avatarColors: [UIColor] { get } + /// Status bar style to use var statusBarStyle: UIStatusBarStyle { get } + + // MARK: - Colors that have currently few usage and may disappear in a redesign + + + /// Color to tint the search background image + var matrixSearchBackgroundImageTintColor: UIColor { get } + + + // MARK: - Customisation methods + + /// Apply the theme on a navigation bar /// /// - Parameter navigationBar: the navigation bar to customise. diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index f7e25c681..597b1c324 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -45,7 +45,6 @@ extern UIColor *kRiotTopicTextColor; extern UIColor *kRiotSelectedBgColor; // nil is used to keep the default color. extern UIColor *kRiotAuxiliaryColor; extern UIColor *kRiotOverlayColor; // fading behind dialog modals. This color includes the transparency value. -extern UIColor *kRiotKeyboardColor; #pragma mark - Riot Colors extern UIColor *kRiotColorPinkRed; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 285f4872f..ed3fe79a6 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -35,7 +35,6 @@ UIColor *kRiotTopicTextColor; UIColor *kRiotSelectedBgColor; UIColor *kRiotAuxiliaryColor; UIColor *kRiotOverlayColor; -UIColor *kRiotKeyboardColor; // Riot Colors UIColor *kRiotColorPinkRed; @@ -45,9 +44,6 @@ UIColor *kRiotColorCuriousBlue; UIColor *kRiotColorIndigo; UIColor *kRiotColorOrange; -// Riot Background Colors -UIColor *kRiotColorLightKeyboard; // TO REMOVE -UIColor *kRiotColorDarkKeyboard; // TO REMOVE NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; @@ -83,9 +79,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotColorIndigo = UIColorFromRGB(0xBD79CC); kRiotColorOrange = UIColorFromRGB(0xF8A15F); - kRiotColorLightKeyboard = UIColorFromRGB(0xE7E7E7); - kRiotColorDarkKeyboard = UIColorFromRGB(0x7E7E7E); - // Observe user interface theme change. [[NSUserDefaults standardUserDefaults] addObserver:[RiotDesignValues sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil]; [[RiotDesignValues sharedInstance] userInterfaceThemeDidChange]; @@ -129,7 +122,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotSelectedBgColor = [UIColor blackColor]; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; - kRiotKeyboardColor = kRiotColorDarkKeyboard; kRiotKeyboard = UIKeyboardAppearanceDark; kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; @@ -141,7 +133,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotSelectedBgColor = [UIColor blackColor]; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; - kRiotKeyboardColor = kRiotColorDarkKeyboard; kRiotKeyboard = UIKeyboardAppearanceDark; kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; @@ -153,7 +144,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotSelectedBgColor = nil; // Use the default selection color. kRiotOverlayColor = [UIColor colorWithWhite:0.7 alpha:0.5]; - kRiotKeyboardColor = kRiotColorLightKeyboard; kRiotKeyboard = UIKeyboardAppearanceLight; kRiotScrollBarStyle = UIScrollViewIndicatorStyleDefault; diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index 3d6145a67..7725cbbac 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -32,6 +32,7 @@ #import "FilesSearchCellData.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #import "GBDeviceInfo_iOS.h" @@ -114,7 +115,7 @@ UIImageView *backgroundImageView = self.backgroundImageView; if (backgroundImageView) { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:kRiotKeyboardColor]; + UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:RiotDesignValues.theme.matrixSearchBackgroundImageTintColor]; backgroundImageView.image = image; } } diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index 95f1e2015..21b70c2ec 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -23,6 +23,7 @@ #import "FilesSearchCellData.h" #import "AppDelegate.h" +#import "Riot-Swift.h" @interface RoomSearchViewController () { @@ -79,7 +80,7 @@ UIImageView *backgroundImageView = self.backgroundImageView; if (backgroundImageView) { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:kRiotKeyboardColor]; + UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:RiotDesignValues.theme.matrixSearchBackgroundImageTintColor]; backgroundImageView.image = image; } } From 77e6a812762064117224f57c7850fc442bec1bdc Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 17:42:43 +0100 Subject: [PATCH 036/244] reskin: Kill RiotDesignValues.kRiotKeyboard and replace it by Theme.keyboardAppearance --- Riot/Constants/Colors/DarkTheme.swift | 2 ++ Riot/Constants/Colors/DefaultTheme.swift | 2 ++ Riot/Constants/Colors/Theme.swift | 6 ++++++ Riot/Constants/RiotDesignValues.h | 2 -- Riot/Constants/RiotDesignValues.m | 8 ++------ Riot/Modules/BugReport/BugReportViewController.m | 2 +- Riot/Modules/Room/Settings/RoomSettingsViewController.m | 2 +- .../Room/Views/InputToolbar/RoomInputToolbarView.m | 2 +- 8 files changed, 15 insertions(+), 11 deletions(-) diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index 08ad427d6..3ae71a512 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -53,6 +53,8 @@ final class DarkTheme: NSObject, Theme { let statusBarStyle: UIStatusBarStyle = .lightContent + let keyboardAppearance: UIKeyboardAppearance = .dark + let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index 0ea09155c..7ea6013aa 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -53,6 +53,8 @@ final class DefaultTheme: NSObject, Theme { let statusBarStyle: UIStatusBarStyle = .lightContent + let keyboardAppearance: UIKeyboardAppearance = .light + let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index ef4e61987..e7dede486 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -46,9 +46,15 @@ import UIKit var avatarColors: [UIColor] { get } + + // MARK: - Appearance and style + + /// Status bar style to use var statusBarStyle: UIStatusBarStyle { get } + var keyboardAppearance : UIKeyboardAppearance { get } + // MARK: - Colors that have currently few usage and may disappear in a redesign diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 597b1c324..6572faa07 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -58,8 +58,6 @@ extern UIColor *kRiotColorOrange; extern NSInteger const kRiotRoomModeratorLevel; extern NSInteger const kRiotRoomAdminLevel; -extern UIKeyboardAppearance kRiotKeyboard; - /** `RiotDesignValues` class manages the Riot design parameters */ diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index ed3fe79a6..fc5e552f3 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -48,7 +48,6 @@ UIColor *kRiotColorOrange; NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; -UIKeyboardAppearance kRiotKeyboard; UIScrollViewIndicatorStyle kRiotScrollBarStyle; @implementation RiotDesignValues @@ -123,7 +122,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; - kRiotKeyboard = UIKeyboardAppearanceDark; kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } else if ([themeId isEqualToString:@"black"]) @@ -133,8 +131,7 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotSelectedBgColor = [UIColor blackColor]; kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; - - kRiotKeyboard = UIKeyboardAppearanceDark; + kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } else @@ -144,8 +141,7 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotSelectedBgColor = nil; // Use the default selection color. kRiotOverlayColor = [UIColor colorWithWhite:0.7 alpha:0.5]; - - kRiotKeyboard = UIKeyboardAppearanceLight; + kRiotScrollBarStyle = UIScrollViewIndicatorStyleDefault; } diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 87bc824bf..4055796b2 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -148,7 +148,7 @@ self.containerView.backgroundColor = kRiotPrimaryBgColor; self.sendingContainer.backgroundColor = kRiotPrimaryBgColor; - self.bugReportDescriptionTextView.keyboardAppearance = kRiotKeyboard; + self.bugReportDescriptionTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; self.titleLabel.textColor = kRiotPrimaryTextColor; self.sendingLabel.textColor = kRiotPrimaryTextColor; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 68ea4914d..abc30635f 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2222,7 +2222,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView.editable = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomTopic]); topicTextView.textColor = kRiotSecondaryTextColor; - topicTextView.keyboardAppearance = kRiotKeyboard; + topicTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; cell = roomTopicCell; } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 4df829bb4..1b7f21e19 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -98,7 +98,7 @@ growingTextView.textColor = kRiotPrimaryTextColor; growingTextView.tintColor = RiotDesignValues.theme.tintColor; - growingTextView.internalTextView.keyboardAppearance = kRiotKeyboard; + growingTextView.internalTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; } #pragma mark - From dd4e20d3894e05c939f0c0759d95030944a1930e Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 17:50:26 +0100 Subject: [PATCH 037/244] reskin: kill kRiotPrimaryBgColor --- Riot/AppDelegate.m | 12 ++++++------ .../Categories/MXKRoomBubbleTableViewCell+Riot.m | 2 +- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 2 -- .../AuthenticationViewController.m | 4 ++-- Riot/Modules/BugReport/BugReportViewController.m | 4 ++-- Riot/Modules/Call/CallViewController.m | 8 ++++---- Riot/Modules/Call/Views/IncomingCallView.m | 16 ++++++++-------- .../Recents/DataSources/RecentsDataSource.m | 2 +- .../Common/Recents/RecentsViewController.m | 8 ++++---- .../Common/Recents/Views/RecentTableViewCell.m | 2 +- .../SegmentedViewController.m | 2 +- .../WebViewController/WebViewViewController.m | 2 +- Riot/Modules/Communities/GroupsViewController.m | 6 +++--- .../Communities/Home/GroupHomeViewController.m | 2 +- .../Members/GroupParticipantsViewController.m | 10 +++++----- .../Communities/Rooms/GroupRoomsViewController.m | 4 ++-- .../Communities/Views/GroupTableViewCell.m | 3 ++- .../Contacts/ContactsTableViewController.m | 4 ++-- .../Details/ContactDetailsViewController.m | 4 ++-- Riot/Modules/EncryptionInfo/EncryptionInfoView.m | 2 +- .../Files/HomeFilesSearchViewController.m | 6 +++--- .../Files/Views/FilesSearchTableViewCell.m | 3 ++- .../Messages/HomeMessagesSearchViewController.m | 6 +++--- .../GlobalSearch/Rooms/DirectoryViewController.m | 4 ++-- Riot/Modules/Home/HomeViewController.m | 2 +- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 2 +- .../Library/MediaAlbumContentViewController.m | 2 +- .../MediaPicker/MediaPickerViewController.m | 14 +++++++------- .../Attachements/AttachmentsViewController.m | 2 +- .../Modules/Room/Files/RoomFilesViewController.m | 4 ++-- .../Detail/RoomMemberDetailsViewController.m | 4 ++-- .../Members/RoomParticipantsViewController.m | 10 +++++----- .../ReadReceiptsViewController.m | 6 +++--- Riot/Modules/Room/RoomViewController.m | 8 ++++---- .../Search/Files/RoomFilesSearchViewController.m | 6 +++--- .../Messages/RoomMessagesSearchViewController.m | 6 +++--- .../Room/Settings/RoomSettingsViewController.m | 4 ++-- .../Room/Views/Activities/RoomActivitiesView.m | 11 ++++++----- Riot/Modules/Room/Views/Event/EventDetailsView.m | 2 +- .../DirectoryServerPickerViewController.m | 4 ++-- .../Language/LanguagePickerViewController.m | 6 +++--- .../PhoneCountry/CountryPickerViewController.m | 6 +++--- Riot/Modules/Settings/SettingsViewController.m | 4 ++-- Riot/Modules/Settings/Views/DeviceView.m | 2 +- Riot/Modules/StartChat/StartChatViewController.m | 4 ++-- Riot/Modules/TabBar/MasterTabBarController.m | 4 ++-- .../UserDevices/UsersDevicesViewController.m | 4 ++-- Riot/Utils/AvatarGenerator.m | 4 ++-- 49 files changed, 120 insertions(+), 120 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 082135202..c256a8b5a 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -444,8 +444,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UINavigationController *secondNavController = self.secondaryNavigationController; if (secondNavController) { - secondNavController.navigationBar.barTintColor = kRiotPrimaryBgColor; - secondNavController.topViewController.view.backgroundColor = kRiotPrimaryBgColor; + secondNavController.navigationBar.barTintColor = RiotDesignValues.theme.backgroundColor; + secondNavController.topViewController.view.backgroundColor = RiotDesignValues.theme.backgroundColor; } // on IOS 8 iPad devices, force to display the primary and the secondary viewcontroller @@ -835,7 +835,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; UIViewController *emptyDetailsViewController = [storyboard instantiateViewControllerWithIdentifier:@"EmptyDetailsViewControllerStoryboardId"]; - emptyDetailsViewController.view.backgroundColor = kRiotPrimaryBgColor; + emptyDetailsViewController.view.backgroundColor = RiotDesignValues.theme.backgroundColor; splitViewController.viewControllers = @[mainViewController, emptyDetailsViewController]; } @@ -2825,7 +2825,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN if (!launchAnimationContainerView && window) { launchAnimationContainerView = [[UIView alloc] initWithFrame:window.bounds]; - launchAnimationContainerView.backgroundColor = kRiotPrimaryBgColor; + launchAnimationContainerView.backgroundColor = RiotDesignValues.theme.backgroundColor; launchAnimationContainerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [window addSubview:launchAnimationContainerView]; @@ -3531,7 +3531,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [_callStatusBarButton setTitle:buttonTitle forState:UIControlStateNormal]; [_callStatusBarButton setTitle:buttonTitle forState:UIControlStateHighlighted]; - _callStatusBarButton.titleLabel.textColor = kRiotPrimaryBgColor; + _callStatusBarButton.titleLabel.textColor = RiotDesignValues.theme.backgroundColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { @@ -3691,7 +3691,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; UIViewController *emptyDetailsViewController = [storyboard instantiateViewControllerWithIdentifier:@"EmptyDetailsViewControllerStoryboardId"]; - emptyDetailsViewController.view.backgroundColor = kRiotPrimaryBgColor; + emptyDetailsViewController.view.backgroundColor = RiotDesignValues.theme.backgroundColor; return emptyDetailsViewController; } diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 39c495f7c..906932e71 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -321,7 +321,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT if (blurred) { self.bubbleOverlayContainer.hidden = NO; - self.bubbleOverlayContainer.backgroundColor = kRiotPrimaryBgColor; + self.bubbleOverlayContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; self.bubbleOverlayContainer.alpha = 0.8; self.bubbleOverlayContainer.userInteractionEnabled = YES; diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 6572faa07..a2041738d 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -36,7 +36,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; alpha:1.0] #pragma mark - Riot Theme Colors (depends on the selected theme light or dark). -extern UIColor *kRiotPrimaryBgColor; extern UIColor *kRiotSecondaryBgColor; extern UIColor *kRiotPrimaryTextColor; extern UIColor *kRiotSecondaryTextColor; //subtitle, sending messages color. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index fc5e552f3..a7c41ce1d 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -26,7 +26,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; -UIColor *kRiotPrimaryBgColor; UIColor *kRiotSecondaryBgColor; UIColor *kRiotPrimaryTextColor; UIColor *kRiotSecondaryTextColor; @@ -148,7 +147,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Apply theme color constants id theme = [RiotDesignValues theme]; - kRiotPrimaryBgColor = theme.backgroundColor; kRiotSecondaryBgColor = theme.headerBackgroundColor; kRiotPrimaryTextColor = theme.textPrimaryColor; kRiotSecondaryTextColor = theme.textSecondaryColor; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 4ad6865ae..b5e3b2d77 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -135,8 +135,8 @@ self.view.backgroundColor = kRiotSecondaryBgColor; - self.authenticationScrollView.backgroundColor = kRiotPrimaryBgColor; - self.authFallbackContentView.backgroundColor = kRiotPrimaryBgColor; + self.authenticationScrollView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.authFallbackContentView.backgroundColor = RiotDesignValues.theme.backgroundColor; if (kRiotPlaceholderTextColor) { diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 4055796b2..809b9d0c4 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -145,8 +145,8 @@ self.overlayView.backgroundColor = kRiotOverlayColor; self.overlayView.alpha = 1.0; - self.containerView.backgroundColor = kRiotPrimaryBgColor; - self.sendingContainer.backgroundColor = kRiotPrimaryBgColor; + self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.sendingContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; self.bugReportDescriptionTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index da3a648a9..93e3ad985 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -111,7 +111,7 @@ self.localPreviewContainerView.layer.cornerRadius = 5; self.localPreviewContainerView.clipsToBounds = YES; - self.remotePreviewContainerView.backgroundColor = kRiotPrimaryBgColor; + self.remotePreviewContainerView.backgroundColor = RiotDesignValues.theme.backgroundColor; if (gradientMaskLayer) { @@ -121,9 +121,9 @@ // Add a gradient mask programatically at the top of the screen (background of the call information (name, status)) gradientMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the kRiotPrimaryBgColor. + // Consider the grayscale components of the RiotDesignValues.theme.backgroundColor. CGFloat white = 1.0; - [kRiotPrimaryBgColor getWhite:&white alpha:nil]; + [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -284,7 +284,7 @@ // Set Riot navigation bar colors [RiotDesignValues.theme applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; - usersDevicesNavigationController.navigationBar.barTintColor = kRiotPrimaryBgColor; + usersDevicesNavigationController.navigationBar.barTintColor = RiotDesignValues.theme.backgroundColor; [usersDevicesNavigationController pushViewController:usersDevicesViewController animated:NO]; diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 0c248c8a0..82d4552c6 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -57,11 +57,11 @@ static const CGFloat kButtonSize = 80.0; self = [super initWithFrame:CGRectZero]; if (self) { - self.backgroundColor = kRiotPrimaryBgColor; + self.backgroundColor = RiotDesignValues.theme.backgroundColor; self.opaque = YES; self.callerImageView = [[MXKImageView alloc] init]; - self.callerImageView.backgroundColor = kRiotPrimaryBgColor; + self.callerImageView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.callerImageView.clipsToBounds = YES; self.callerImageView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder; self.callerImageView.enableInMemoryCache = YES; @@ -74,14 +74,14 @@ static const CGFloat kButtonSize = 80.0; mediaManager:mediaManager]; self.callerNameLabel = [[UILabel alloc] init]; - self.callerNameLabel.backgroundColor = kRiotPrimaryBgColor; + self.callerNameLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; self.callerNameLabel.textColor = kRiotPrimaryTextColor; self.callerNameLabel.font = [UIFont systemFontOfSize:24.0 weight:UIFontWeightMedium]; self.callerNameLabel.text = callerName; self.callerNameLabel.textAlignment = NSTextAlignmentCenter; self.callInfoLabel = [[UILabel alloc] init]; - self.callInfoLabel.backgroundColor = kRiotPrimaryBgColor; + self.callInfoLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; self.callInfoLabel.textColor = kRiotSecondaryTextColor; self.callInfoLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.callInfoLabel.text = callInfo; @@ -91,11 +91,11 @@ static const CGFloat kButtonSize = 80.0; self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"] borderColor:answerButtonBorderColor]; - self.answerButton.defaultBackgroundColor = kRiotPrimaryBgColor; + self.answerButton.defaultBackgroundColor = RiotDesignValues.theme.backgroundColor; [self.answerButton addTarget:self action:@selector(didTapAnswerButton) forControlEvents:UIControlEventTouchUpInside]; self.answerTitleLabel = [[UILabel alloc] init]; - self.answerTitleLabel.backgroundColor = kRiotPrimaryBgColor; + self.answerTitleLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; self.answerTitleLabel.textColor = answerButtonBorderColor; self.answerTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.answerTitleLabel.text = NSLocalizedStringFromTable(@"accept", @"Vector", nil); @@ -104,11 +104,11 @@ static const CGFloat kButtonSize = 80.0; self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"call_hangup_icon"] borderColor:rejectButtonBorderColor]; - self.rejectButton.defaultBackgroundColor = kRiotPrimaryBgColor; + self.rejectButton.defaultBackgroundColor = RiotDesignValues.theme.backgroundColor; [self.rejectButton addTarget:self action:@selector(didTapRejectButton) forControlEvents:UIControlEventTouchUpInside]; self.rejectTitleLabel = [[UILabel alloc] init]; - self.rejectTitleLabel.backgroundColor = kRiotPrimaryBgColor; + self.rejectTitleLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; self.rejectTitleLabel.textColor = rejectButtonBorderColor; self.rejectTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.rejectTitleLabel.text = NSLocalizedStringFromTable(@"decline", @"Vector", nil); diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 687d13fde..701aa15ab 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -469,7 +469,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (count) { UILabel *missedNotifAndUnreadBadgeLabel = [[UILabel alloc] init]; - missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; + missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; missedNotifAndUnreadBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; if (count > 1000) { diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index ea1d651bb..e9dc36e11 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -164,9 +164,9 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Use the primary bg color for the recents table view in plain style. - self.recentsTableView.backgroundColor = kRiotPrimaryBgColor; + self.recentsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; topview.backgroundColor = kRiotSecondaryBgColor; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; [RiotDesignValues.theme applyStyleOnSearchBar:self.recentsSearchBar]; @@ -1185,7 +1185,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) @@ -1413,7 +1413,7 @@ if (indexPath && [recentsDataSource isDraggableCellAt:indexPath]) { UITableViewCell *cell = [self.recentsTableView cellForRowAtIndexPath:indexPath]; - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // snapshot the cell UIGraphicsBeginImageContextWithOptions(cell.bounds.size, NO, 0); diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 03700075c..866263c7a 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -51,7 +51,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.roomTitle.textColor = kRiotPrimaryTextColor; self.lastEventDescription.textColor = kRiotSecondaryTextColor; self.lastEventDate.textColor = kRiotSecondaryTextColor; - self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; + self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; // Prepare direct room border CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 5baff1cc9..f59ddb601 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -182,7 +182,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index 2bf189a44..1a6669803 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -56,7 +56,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - webView.backgroundColor = kRiotPrimaryBgColor; + webView.backgroundColor = RiotDesignValues.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 6529b08cd..b5b9f4642 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -121,9 +121,9 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Use the primary bg color for the recents table view in plain style. - self.groupsTableView.backgroundColor = kRiotPrimaryBgColor; + self.groupsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; topview.backgroundColor = kRiotSecondaryBgColor; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; [RiotDesignValues.theme applyStyleOnSearchBar:self.groupsSearchBar]; @@ -424,7 +424,7 @@ { [super tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath]; - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 4f1f511a6..3cc1a98c9 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -117,7 +117,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; self.mainHeaderContainer.backgroundColor = kRiotSecondaryBgColor; _groupName.textColor = kRiotPrimaryTextColor; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 31c0fe5fd..c42664234 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -154,12 +154,12 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen CGFloat white = 1.0; - [kRiotPrimaryBgColor getWhite:&white alpha:nil]; + [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; @@ -444,9 +444,9 @@ // Add blur mask programmatically tableViewMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the kRiotPrimaryBgColor. + // Consider the grayscale components of the RiotDesignValues.theme.backgroundColor. CGFloat white = 1.0; - [kRiotPrimaryBgColor getWhite:&white alpha:nil]; + [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -877,7 +877,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 68f2578de..ad78042b6 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -135,7 +135,7 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -487,7 +487,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.m b/Riot/Modules/Communities/Views/GroupTableViewCell.m index 54246f7e8..538afc64d 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.m @@ -17,6 +17,7 @@ #import "GroupTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "MXGroup+Riot.h" @@ -46,7 +47,7 @@ if (self.missedNotifAndUnreadBadgeLabel) { - self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; + self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; } self.groupAvatar.defaultBackgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index babeafeac..00a064d85 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -109,7 +109,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -288,7 +288,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 3bd61c627..0b6c3f714 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -240,7 +240,7 @@ self.contactStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -779,7 +779,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index b4adb1dce..2cb8b2f69 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -29,7 +29,7 @@ [super customizeViewRendering]; self.backgroundColor = kRiotSecondaryBgColor; - self.textView.backgroundColor = kRiotPrimaryBgColor; + self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.defaultTextColor = kRiotPrimaryTextColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; self.verifyButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index ef84b2644..af15ef436 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -76,10 +76,10 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = kRiotPrimaryBgColor; + self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -153,7 +153,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index 29f8ccb5d..1b851f5d0 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -19,6 +19,7 @@ #import "FilesSearchTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation FilesSearchTableViewCell @synthesize delegate, mxkCellData; @@ -75,7 +76,7 @@ if (bubbleData.isAttachmentWithThumbnail) { - self.attachmentImageView.backgroundColor = kRiotPrimaryBgColor; + self.attachmentImageView.backgroundColor = RiotDesignValues.theme.backgroundColor; [self.attachmentImageView setAttachmentThumb:bubbleData.attachment]; } diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index db81962cf..11785ea50 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -83,10 +83,10 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = kRiotPrimaryBgColor; + self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -196,7 +196,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index 870913b56..950d9f664 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -76,7 +76,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -157,7 +157,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index b1cfe2673..6c842f03d 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -416,7 +416,7 @@ } } - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; return cell; } diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 0b74b465b..d8c229060 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -69,7 +69,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; self.roomTitle.textColor = kRiotPrimaryTextColor; self.roomTitle1.textColor = kRiotPrimaryTextColor; self.roomTitle2.textColor = kRiotPrimaryTextColor; - self.missedNotifAndUnreadBadgeLabel.textColor = kRiotPrimaryBgColor; + self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; // Prepare direct room border CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index 585a3906c..094506bbc 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -115,7 +115,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.assetsCollectionView.backgroundColor = kRiotPrimaryBgColor; + self.assetsCollectionView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; } diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index eab761580..7df9fd2cd 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -186,11 +186,11 @@ static void *RecordingContext = &RecordingContext; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.cameraVideoCaptureProgressView.progressColor = kRiotPrimaryBgColor; + self.cameraVideoCaptureProgressView.progressColor = RiotDesignValues.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor clearColor]; - self.userAlbumsTableView.backgroundColor = kRiotPrimaryBgColor; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.userAlbumsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle @@ -343,12 +343,12 @@ static void *RecordingContext = &RecordingContext; if (self.cameraVideoCaptureProgressView.progressColor != [UIColor lightGrayColor]) { self.cameraVideoCaptureProgressView.progressColor = [UIColor lightGrayColor]; - self.cameraVideoCaptureProgressView.unprogressColor = kRiotPrimaryBgColor; + self.cameraVideoCaptureProgressView.unprogressColor = RiotDesignValues.theme.backgroundColor; } } - else if (self.cameraVideoCaptureProgressView.progressColor != kRiotPrimaryBgColor) + else if (self.cameraVideoCaptureProgressView.progressColor != RiotDesignValues.theme.backgroundColor) { - self.cameraVideoCaptureProgressView.progressColor = kRiotPrimaryBgColor; + self.cameraVideoCaptureProgressView.progressColor = RiotDesignValues.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor lightGrayColor]; } @@ -1765,7 +1765,7 @@ static void *RecordingContext = &RecordingContext; - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 242bbb21a..3b189ef60 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -61,7 +61,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; self.backButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 7f45ba55d..b425c5ed8 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -115,7 +115,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) @@ -193,7 +193,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 66e946d59..4b60f87cc 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -228,7 +228,7 @@ self.roomMemberStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -843,7 +843,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 2ab8a29d9..1723e95e2 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -166,12 +166,12 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen CGFloat white = 1.0; - [kRiotPrimaryBgColor getWhite:&white alpha:nil]; + [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; @@ -575,9 +575,9 @@ // Add blur mask programmatically tableViewMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the kRiotPrimaryBgColor. + // Consider the grayscale components of the RiotDesignValues.theme.backgroundColor. CGFloat white = 1.0; - [kRiotPrimaryBgColor getWhite:&white alpha:nil]; + [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -1175,7 +1175,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 1ec666e22..a745f1898 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -102,10 +102,10 @@ self.overlayView.alpha = 1.0; self.titleLabel.textColor = kRiotPrimaryTextColor; - self.containerView.backgroundColor = kRiotPrimaryBgColor; + self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; // Check the table view style to select its bg color. - self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.closeButton.tintColor = RiotDesignValues.theme.tintColor; @@ -240,7 +240,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 8caf471e7..798616a1d 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -424,19 +424,19 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Prepare jump to last unread banner - self.jumpToLastUnreadBannerContainer.backgroundColor = kRiotPrimaryBgColor; + self.jumpToLastUnreadBannerContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: kRiotPrimaryTextColor, NSForegroundColorAttributeName: kRiotPrimaryTextColor}]; self.expandedHeaderContainer.backgroundColor = kRiotSecondaryBgColor; self.previewHeaderContainer.backgroundColor = kRiotSecondaryBgColor; - missedDiscussionsBadgeLabel.textColor = kRiotPrimaryBgColor; + missedDiscussionsBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; missedDiscussionsBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; missedDiscussionsBadgeLabel.backgroundColor = [UIColor clearColor]; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) @@ -3338,7 +3338,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index 31949524b..bf25d0598 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -77,10 +77,10 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = kRiotPrimaryBgColor; + self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -146,7 +146,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index 636824993..a43bb3f94 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -78,10 +78,10 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = kRiotPrimaryBgColor; + self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -173,7 +173,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index abc30635f..2db8b52cb 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -271,7 +271,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -2822,7 +2822,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 586f572af..56af7f992 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -18,6 +18,7 @@ #import "RoomActivitiesView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import @@ -259,12 +260,12 @@ // Display the string in white on pink red NSRange wholeString = NSMakeRange(0, onGoingConferenceCallAttibutedString.length); - [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:kRiotPrimaryBgColor range:wholeString]; + [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.backgroundColor range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:kRiotColorPinkRed range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = onGoingConferenceCallAttibutedString; - self.messageTextView.tintColor = kRiotPrimaryBgColor; + self.messageTextView.tintColor = RiotDesignValues.theme.backgroundColor; self.messageTextView.hidden = NO; self.backgroundColor = kRiotColorPinkRed; @@ -431,13 +432,13 @@ message2 = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_resource_usage_limit_reached_message_2", @"Vector", nil) attributes:@{ NSFontAttributeName: [UIFont boldSystemFontOfSize:fontSize], - NSForegroundColorAttributeName: kRiotPrimaryBgColor + NSForegroundColorAttributeName: RiotDesignValues.theme.backgroundColor }]; } NSDictionary *attributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:fontSize], - NSForegroundColorAttributeName: kRiotPrimaryBgColor + NSForegroundColorAttributeName: RiotDesignValues.theme.backgroundColor }; NSDictionary *messageContact2LinkAttributes; @@ -481,7 +482,7 @@ [attributedText appendAttributedString:messageContact3]; self.messageTextView.attributedText = attributedText; - self.messageTextView.tintColor = kRiotPrimaryBgColor; + self.messageTextView.tintColor = RiotDesignValues.theme.backgroundColor; self.messageTextView.hidden = NO; if (hardLimit) diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 3b981204d..6ef3e4f27 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -26,7 +26,7 @@ [super customizeViewRendering]; self.backgroundColor = kRiotSecondaryBgColor; - self.textView.backgroundColor = kRiotPrimaryBgColor; + self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.textView.textColor = kRiotPrimaryTextColor; self.redactButton.tintColor = RiotDesignValues.theme.tintColor; self.closeButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index af2e847d3..3b60c3825 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -125,7 +125,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -226,7 +226,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index e92d41ee6..fb325864e 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -76,8 +76,8 @@ [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. - self.tableView.backgroundColor = kRiotPrimaryBgColor; - topview.backgroundColor = kRiotPrimaryBgColor; + self.tableView.backgroundColor = RiotDesignValues.theme.backgroundColor; + topview.backgroundColor = RiotDesignValues.theme.backgroundColor; if (self.tableView.dataSource) { @@ -116,7 +116,7 @@ { cell.textLabel.textColor = kRiotPrimaryTextColor; cell.detailTextLabel.textColor = kRiotSecondaryTextColor; - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 078b41224..430eacf0d 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -79,8 +79,8 @@ [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. - self.tableView.backgroundColor = kRiotPrimaryBgColor; - topview.backgroundColor = kRiotPrimaryBgColor; + self.tableView.backgroundColor = RiotDesignValues.theme.backgroundColor; + topview.backgroundColor = RiotDesignValues.theme.backgroundColor; self.searchDisplayController.searchResultsTableView.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -120,7 +120,7 @@ { cell.textLabel.textColor = kRiotPrimaryTextColor; cell.detailTextLabel.textColor = kRiotSecondaryTextColor; - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 2177a21fa..1f466eca0 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -339,7 +339,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -2362,7 +2362,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; if (cell.selectionStyle != UITableViewCellSelectionStyleNone) { diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 2726bcf63..71f5ca407 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -29,7 +29,7 @@ [super customizeViewRendering]; self.containerView.backgroundColor = kRiotSecondaryBgColor; - self.textView.backgroundColor = kRiotPrimaryBgColor; + self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.defaultTextColor = kRiotPrimaryTextColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; self.deleteButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 63be60b60..365f3cbf1 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -152,7 +152,7 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -381,7 +381,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index bb81aeaf9..94460d9de 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -119,7 +119,7 @@ self.tabBar.tintColor = RiotDesignValues.theme.tintColor; self.tabBar.barTintColor = kRiotSecondaryBgColor; - self.view.backgroundColor = kRiotPrimaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; [self setNeedsStatusBarAppearanceUpdate]; } @@ -786,7 +786,7 @@ { _hidden = hidden; - [self.view superview].backgroundColor = kRiotPrimaryBgColor; + [self.view superview].backgroundColor = RiotDesignValues.theme.backgroundColor; self.view.hidden = hidden; self.navigationController.navigationBar.hidden = hidden; } diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 7e01d9c44..d1b05015a 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -87,7 +87,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? kRiotPrimaryBgColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -178,7 +178,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = kRiotPrimaryBgColor; + cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view if (kRiotSelectedBgColor) diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index aa18ab526..67b4d5c4a 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -93,7 +93,7 @@ static UILabel* backgroundLabel = nil; if (!backgroundLabel) { backgroundLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; - backgroundLabel.textColor = kRiotPrimaryBgColor; + backgroundLabel.textColor = RiotDesignValues.theme.backgroundColor; backgroundLabel.textAlignment = NSTextAlignmentCenter; backgroundLabel.font = [UIFont boldSystemFontOfSize:25]; } @@ -123,7 +123,7 @@ static UILabel* backgroundLabel = nil; + (UIImage *)imageFromText:(NSString*)text withBackgroundColor:(UIColor*)color size:(CGFloat)size andFontSize:(CGFloat)fontSize { UILabel *bgLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size, size)]; - bgLabel.textColor = kRiotPrimaryBgColor; + bgLabel.textColor = RiotDesignValues.theme.backgroundColor; bgLabel.textAlignment = NSTextAlignmentCenter; bgLabel.font = [UIFont boldSystemFontOfSize:fontSize]; From 2bdadf5cdac52efd26af05e461ab06d5844a8e5a Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 17:57:17 +0100 Subject: [PATCH 038/244] reskin: kill kRiotSecondaryBgColor --- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 2 -- .../AuthenticationViewController.m | 2 +- Riot/Modules/BugReport/BugReportViewController.m | 2 +- .../Recents/DataSources/RecentsDataSource.m | 2 +- .../Common/Recents/RecentsViewController.m | 16 ++++++++-------- Riot/Modules/Communities/GroupsViewController.m | 6 +++--- .../Communities/Home/GroupHomeViewController.m | 8 ++++---- .../Members/GroupParticipantsViewController.m | 6 +++--- .../Communities/Rooms/GroupRoomsViewController.m | 4 ++-- .../Contacts/ContactsTableViewController.m | 2 +- .../Contacts/DataSources/ContactsDataSource.m | 2 +- .../Details/ContactDetailsViewController.m | 4 ++-- Riot/Modules/EncryptionInfo/EncryptionInfoView.m | 2 +- .../Files/HomeFilesSearchViewController.m | 2 +- .../Messages/HomeMessagesSearchViewController.m | 2 +- .../GlobalSearch/Rooms/DirectoryViewController.m | 2 +- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 2 +- .../Home/Views/TableViewCellWithCollectionView.m | 3 ++- .../Modules/Room/Files/RoomFilesViewController.m | 2 +- .../Detail/RoomMemberDetailsViewController.m | 2 +- .../Members/RoomParticipantsViewController.m | 6 +++--- .../ReadReceiptsViewController.m | 2 +- Riot/Modules/Room/RoomViewController.m | 6 +++--- .../Search/Files/RoomFilesSearchViewController.m | 2 +- .../Messages/RoomMessagesSearchViewController.m | 2 +- .../Room/Settings/RoomSettingsViewController.m | 6 +++--- .../Room/Views/Activities/RoomActivitiesView.m | 2 +- .../RoomMembershipExpandedBubbleCell.m | 2 +- .../BubbleCells/RoomPredecessorBubbleCell.m | 3 ++- .../BubbleCells/RoomSelectedStickerBubbleCell.m | 5 +++-- Riot/Modules/Room/Views/Event/EventDetailsView.m | 2 +- .../Views/Title/Expanded/ExpandedRoomTitleView.m | 2 +- .../Views/Title/Preview/PreviewRoomTitleView.m | 4 ++-- .../DirectoryServerPickerViewController.m | 2 +- Riot/Modules/Settings/SettingsViewController.m | 6 +++--- Riot/Modules/Settings/Views/DeviceView.m | 2 +- Riot/Modules/StartChat/StartChatViewController.m | 4 ++-- Riot/Modules/TabBar/MasterTabBarController.m | 2 +- .../UserDevices/UsersDevicesViewController.m | 2 +- Riot/Utils/EventFormatter.m | 2 +- 41 files changed, 69 insertions(+), 69 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index a2041738d..9416ae1fe 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -36,7 +36,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; alpha:1.0] #pragma mark - Riot Theme Colors (depends on the selected theme light or dark). -extern UIColor *kRiotSecondaryBgColor; extern UIColor *kRiotPrimaryTextColor; extern UIColor *kRiotSecondaryTextColor; //subtitle, sending messages color. extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index a7c41ce1d..bab61734a 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -26,7 +26,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; -UIColor *kRiotSecondaryBgColor; UIColor *kRiotPrimaryTextColor; UIColor *kRiotSecondaryTextColor; UIColor *kRiotPlaceholderTextColor; @@ -147,7 +146,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Apply theme color constants id theme = [RiotDesignValues theme]; - kRiotSecondaryBgColor = theme.headerBackgroundColor; kRiotPrimaryTextColor = theme.textPrimaryColor; kRiotSecondaryTextColor = theme.textSecondaryColor; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index b5e3b2d77..56a18e78e 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -133,7 +133,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.view.backgroundColor = kRiotSecondaryBgColor; + self.view.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.authenticationScrollView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.authFallbackContentView.backgroundColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 809b9d0c4..4cfeb35e2 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -162,7 +162,7 @@ self.sendButton.tintColor = RiotDesignValues.theme.tintColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; - _bugReportDescriptionTextView.layer.borderColor = kRiotSecondaryBgColor.CGColor; + _bugReportDescriptionTextView.layer.borderColor = RiotDesignValues.theme.headerBackgroundColor.CGColor; } - (UIStatusBarStyle)preferredStatusBarStyle diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 701aa15ab..04dd79713 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -516,7 +516,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame { UIView *sectionHeader = [[UIView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = kRiotSecondaryBgColor; + sectionHeader.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; NSInteger sectionBitwise = 0; UIImageView *chevronView; UIView *accessoryView; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index e9dc36e11..2d6c416d1 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -165,7 +165,7 @@ // Use the primary bg color for the recents table view in plain style. self.recentsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - topview.backgroundColor = kRiotSecondaryBgColor; + topview.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; @@ -868,7 +868,7 @@ }]; UIImage *actionIcon = isDirect ? [UIImage imageNamed:@"directChatOff"] : [UIImage imageNamed:@"directChatOn"]; - directAction.backgroundColor = [MXKTools convertImageToPatternColor:isDirect ? @"directChatOff" : @"directChatOn" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + directAction.backgroundColor = [MXKTools convertImageToPatternColor:isDirect ? @"directChatOff" : @"directChatOn" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:directAction atIndex:0]; @@ -882,7 +882,7 @@ }]; actionIcon = isMuted ? [UIImage imageNamed:@"notifications"] : [UIImage imageNamed:@"notificationsOff"]; - muteAction.backgroundColor = [MXKTools convertImageToPatternColor:isMuted ? @"notifications" : @"notificationsOff" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + muteAction.backgroundColor = [MXKTools convertImageToPatternColor:isMuted ? @"notifications" : @"notificationsOff" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:muteAction atIndex:0]; // Favorites management @@ -907,7 +907,7 @@ }]; actionIcon = [UIImage imageNamed:@"favouriteOff"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"favouriteOff" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"favouriteOff" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } else @@ -919,7 +919,7 @@ }]; actionIcon = [UIImage imageNamed:@"favourite"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"favourite" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"favourite" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } @@ -932,7 +932,7 @@ }]; actionIcon = [UIImage imageNamed:@"priorityHigh"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityHigh" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityHigh" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } else @@ -944,7 +944,7 @@ }]; actionIcon = [UIImage imageNamed:@"priorityLow"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityLow" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityLow" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } @@ -955,7 +955,7 @@ }]; actionIcon = [UIImage imageNamed:@"leave"]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"leave" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"leave" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index b5b9f4642..f6eda95e3 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -122,7 +122,7 @@ // Use the primary bg color for the recents table view in plain style. self.groupsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - topview.backgroundColor = kRiotSecondaryBgColor; + topview.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; @@ -452,7 +452,7 @@ if (tableView.numberOfSections > 1) { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; - sectionHeader.mxkContentView.backgroundColor = kRiotSecondaryBgColor; + sectionHeader.mxkContentView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; sectionHeader.mxkLabel.textColor = kRiotPrimaryTextColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; @@ -512,7 +512,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 3cc1a98c9..bcf57b5e4 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -118,7 +118,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.mainHeaderContainer.backgroundColor = kRiotSecondaryBgColor; + self.mainHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; _groupName.textColor = kRiotPrimaryTextColor; @@ -128,7 +128,7 @@ self.inviteLabel.textColor = kRiotTopicTextColor; self.inviteLabel.numberOfLines = 0; - self.separatorView.backgroundColor = kRiotSecondaryBgColor; + self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; @@ -144,7 +144,7 @@ _groupLongDescription.tintColor = kRiotColorBlue; // Update HTML loading options - NSUInteger bgColor = [MXKTools rgbValueWithColor:kRiotSecondaryBgColor]; + NSUInteger bgColor = [MXKTools rgbValueWithColor:RiotDesignValues.theme.headerBackgroundColor]; NSString *defaultCSS = [NSString stringWithFormat:@" \ pre,code { \ background-color: #%06lX; \ @@ -481,7 +481,7 @@ _groupAvatar.layer.cornerRadius = _groupAvatar.frame.size.width / 2; _groupAvatar.clipsToBounds = YES; - _groupAvatar.defaultBackgroundColor = kRiotSecondaryBgColor; + _groupAvatar.defaultBackgroundColor = RiotDesignValues.theme.headerBackgroundColor; } - (void)refreshGroupLongDescription diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index c42664234..fd162ff6c 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -154,7 +154,7 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen @@ -914,7 +914,7 @@ if (section == invitedSection) { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; - sectionHeader.mxkContentView.backgroundColor = kRiotSecondaryBgColor; + sectionHeader.mxkContentView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; sectionHeader.mxkLabel.textColor = kRiotPrimaryTextColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; @@ -985,7 +985,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index ad78042b6..b3b85a664 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -135,7 +135,7 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -588,7 +588,7 @@ // // }]; // -// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; +// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; // [actions insertObject:leaveAction atIndex:0]; // // return actions; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 00a064d85..5d7b0b690 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -109,7 +109,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 4fd7a8a34..3568d4ea6 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -767,7 +767,7 @@ NSInteger sectionBitwise = 0; sectionHeader = [[UIView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = kRiotSecondaryBgColor; + sectionHeader.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; frame.origin.x = 20; frame.origin.y = 5; diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 0b6c3f714..d7150176d 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -235,12 +235,12 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.headerView.backgroundColor = kRiotSecondaryBgColor; + self.headerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.contactNameLabel.textColor = kRiotPrimaryTextColor; self.contactStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index 2cb8b2f69..c9fe44e35 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -28,7 +28,7 @@ { [super customizeViewRendering]; - self.backgroundColor = kRiotSecondaryBgColor; + self.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.defaultTextColor = kRiotPrimaryTextColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index af15ef436..37d4f17f2 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -76,7 +76,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index 11785ea50..4ca9ff535 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -83,7 +83,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index 950d9f664..c29b62396 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -76,7 +76,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index d8c229060..246ce8b70 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -81,7 +81,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; CFRelease(directRoomBorderColor); - self.editionArrowView.backgroundColor = kRiotSecondaryBgColor; + self.editionArrowView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m index f884672b5..ef131331a 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m @@ -16,6 +16,7 @@ #import "TableViewCellWithCollectionView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation TableViewCellWithCollectionView @@ -31,7 +32,7 @@ { [super customizeTableViewCellRendering]; - self.editionView.backgroundColor = kRiotSecondaryBgColor; + self.editionView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; } - (void)prepareForReuse diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index b425c5ed8..07bdce754 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -115,7 +115,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 4b60f87cc..94650209f 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -228,7 +228,7 @@ self.roomMemberStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 1723e95e2..b059a2db0 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -166,7 +166,7 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen @@ -1215,7 +1215,7 @@ if (section == invitedSection) { sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 30)]; - sectionHeader.backgroundColor = kRiotSecondaryBgColor; + sectionHeader.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; CGRect frame = sectionHeader.frame; frame.origin.x = 20; @@ -1327,7 +1327,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index a745f1898..b9ca8da95 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -105,7 +105,7 @@ self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; // Check the table view style to select its bg color. - self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.closeButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 798616a1d..f0d480bde 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -428,15 +428,15 @@ self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: kRiotPrimaryTextColor, NSForegroundColorAttributeName: kRiotPrimaryTextColor}]; - self.expandedHeaderContainer.backgroundColor = kRiotSecondaryBgColor; - self.previewHeaderContainer.backgroundColor = kRiotSecondaryBgColor; + self.expandedHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.previewHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; missedDiscussionsBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; missedDiscussionsBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; missedDiscussionsBadgeLabel.backgroundColor = [UIColor clearColor]; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index bf25d0598..e405965a5 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -77,7 +77,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index a43bb3f94..1d8a281f5 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -78,7 +78,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 2db8b52cb..2a94239b0 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -271,7 +271,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -3117,7 +3117,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti }]; - removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; + removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:removeAction atIndex:0]; } } @@ -3132,7 +3132,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti }]; - removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; + removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:removeAction atIndex:0]; } diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 56af7f992..0477efbd7 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -112,7 +112,7 @@ { [super customizeViewRendering]; - self.separatorView.backgroundColor = kRiotSecondaryBgColor; + self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; if (self.messageLabel.textColor != kRiotColorPinkRed) { self.messageLabel.textColor = kRiotSecondaryTextColor; diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index df6953d8e..e17e76392 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -38,7 +38,7 @@ NSString *const kRoomMembershipExpandedBubbleCellTapOnCollapseButton = @"kRoomMe { [super customizeTableViewCellRendering]; - self.separatorView.backgroundColor = kRiotSecondaryBgColor; + self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; [self.collapseButton setTintColor:RiotDesignValues.theme.tintColor]; self.collapseButton.titleLabel.font = [UIFont systemFontOfSize:14]; diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m index 154709567..674e2e115 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m @@ -18,6 +18,7 @@ #import "RoomPredecessorBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #pragma mark - Defines & Constants @@ -58,7 +59,7 @@ static CGFloat const kCustomBackgroundCornerRadius = 5.0; [super customizeTableViewCellRendering]; self.messageTextView.tintColor = kRiotPrimaryTextColor; - self.customBackgroundView.backgroundColor = kRiotSecondaryBgColor; + self.customBackgroundView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m index 18a757bbb..f6671541d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m @@ -25,6 +25,7 @@ #import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation RoomSelectedStickerBubbleCell @@ -44,8 +45,8 @@ arrowMaskLayer.path = path.CGPath; self.arrowView.layer.mask = arrowMaskLayer; - self.arrowView.backgroundColor = kRiotSecondaryBgColor; - self.descriptionView.backgroundColor = kRiotSecondaryBgColor; + self.arrowView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.descriptionView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; [self.descriptionView.layer setCornerRadius:10]; } diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 6ef3e4f27..64742a570 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -25,7 +25,7 @@ { [super customizeViewRendering]; - self.backgroundColor = kRiotSecondaryBgColor; + self.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.textView.textColor = kRiotPrimaryTextColor; self.redactButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index 734a93c50..af8b036c5 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -131,7 +131,7 @@ self.roomAvatar.layer.cornerRadius = self.roomAvatar.frame.size.width / 2; self.roomAvatar.clipsToBounds = YES; - self.roomAvatar.defaultBackgroundColor = kRiotSecondaryBgColor; + self.roomAvatar.defaultBackgroundColor = RiotDesignValues.theme.headerBackgroundColor; // Force the layout of subviews to update the position of 'bottomBorderView' which is used to define the actual height of the preview container. [self layoutIfNeeded]; diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 499c08380..9049d3cbf 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -77,7 +77,7 @@ self.subNoticeLabel.textColor = kRiotSecondaryTextColor; self.subNoticeLabel.numberOfLines = 0; - self.bottomBorderView.backgroundColor = kRiotSecondaryBgColor; + self.bottomBorderView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; @@ -249,7 +249,7 @@ self.roomAvatar.layer.cornerRadius = self.roomAvatar.frame.size.width / 2; self.roomAvatar.clipsToBounds = YES; - self.roomAvatar.defaultBackgroundColor = kRiotSecondaryBgColor; + self.roomAvatar.defaultBackgroundColor = RiotDesignValues.theme.headerBackgroundColor; // Force the layout of subviews to update the position of 'bottomBorderView' which is used to define the actual height of the preview container. [self layoutIfNeeded]; diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index 3b60c3825..bdf219446 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -125,7 +125,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 1f466eca0..c7e19c688 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -339,7 +339,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -1672,7 +1672,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); else if (row == userSettingsNightModeSepIndex) { UITableViewCell *sepCell = [[UITableViewCell alloc] init]; - sepCell.backgroundColor = kRiotSecondaryBgColor; + sepCell.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; cell = sepCell; } @@ -2473,7 +2473,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_pink" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(50, cellHeight) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_pink" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(50, cellHeight) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } } diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 71f5ca407..8a70e7aa7 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -28,7 +28,7 @@ { [super customizeViewRendering]; - self.containerView.backgroundColor = kRiotSecondaryBgColor; + self.containerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.defaultTextColor = kRiotPrimaryTextColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 365f3cbf1..945de65ce 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -152,7 +152,7 @@ _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -453,7 +453,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:kRiotSecondaryBgColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 94460d9de..c5f1882bd 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -117,7 +117,7 @@ [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.tabBar.tintColor = RiotDesignValues.theme.tintColor; - self.tabBar.barTintColor = kRiotSecondaryBgColor; + self.tabBar.barTintColor = RiotDesignValues.theme.headerBackgroundColor; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index d1b05015a..6d18b145a 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -87,7 +87,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : kRiotSecondaryBgColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 02003526b..7427285de 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -206,7 +206,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; // Use the secondary bg color to set the background color in the default CSS. - NSUInteger bgColor = [MXKTools rgbValueWithColor:kRiotSecondaryBgColor]; + NSUInteger bgColor = [MXKTools rgbValueWithColor:RiotDesignValues.theme.headerBackgroundColor]; self.defaultCSS = [NSString stringWithFormat:@" \ pre,code { \ background-color: #%06lX; \ From 1fe7b85e1621affeeb8ddfbea9b8fb1ae2db0927 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 18:00:45 +0100 Subject: [PATCH 039/244] reskin: kill kRiotPrimaryTextColor --- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 2 -- .../AuthenticationViewController.m | 4 +-- .../Authentication/Views/AuthInputsView.m | 14 ++++----- .../Views/ForgotPasswordInputsView.m | 8 ++--- .../BugReport/BugReportViewController.m | 14 ++++----- Riot/Modules/Call/CallViewController.m | 4 +-- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../Recents/DataSources/RecentsDataSource.m | 2 +- .../Recents/Views/RecentTableViewCell.m | 2 +- .../Communities/GroupsViewController.m | 2 +- .../Home/GroupHomeViewController.m | 2 +- .../Members/GroupParticipantsViewController.m | 2 +- .../Rooms/Views/GroupRoomTableViewCell.m | 3 +- .../Communities/Views/GroupTableViewCell.m | 2 +- .../Contacts/DataSources/ContactsDataSource.m | 2 +- .../Details/ContactDetailsViewController.m | 6 ++-- .../Details/Views/RoomTableViewCell.m | 2 +- .../Contacts/Views/ContactTableViewCell.m | 2 +- .../EncryptionInfo/EncryptionInfoView.m | 2 +- .../Files/Views/FilesSearchTableViewCell.m | 2 +- ...MessagesSearchResultAttachmentBubbleCell.m | 2 +- .../MessagesSearchResultTextMsgBubbleCell.m | 2 +- .../Views/DirectoryRecentTableViewCell.m | 3 +- .../Views/RoomIdOrAliasTableViewCell.m | 2 +- .../Home/Views/RoomCollectionViewCell.m | 6 ++-- .../MediaPicker/Views/MediaAlbumTableCell.m | 3 +- .../Views/PublicRoomTableViewCell.m | 3 +- .../Detail/RoomMemberDetailsViewController.m | 6 ++-- .../Members/RoomParticipantsViewController.m | 2 +- .../ReadReceiptsViewController.m | 4 +-- Riot/Modules/Room/RoomViewController.m | 2 +- .../Settings/RoomSettingsViewController.m | 24 +++++++-------- .../Views/TableViewCellWithCheckBoxAndLabel.m | 3 +- .../TableViewCellWithLabelAndLargeTextView.m | 5 ++-- .../Views/Activities/RoomActivitiesView.m | 4 +-- .../RoomIncomingAttachmentBubbleCell.m | 2 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 2 +- .../RoomIncomingTextMsgBubbleCell.m | 2 +- ...mingTextMsgWithPaginationTitleBubbleCell.m | 2 +- .../RoomOutgoingAttachmentBubbleCell.m | 2 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 2 +- .../RoomOutgoingTextMsgBubbleCell.m | 2 +- .../BubbleCells/RoomPredecessorBubbleCell.m | 2 +- .../Room/Views/Event/EventDetailsView.m | 2 +- .../DisabledRoomInputToolbarView.m | 2 +- .../Views/InputToolbar/RoomInputToolbarView.m | 2 +- .../Views/DirectoryServerTableViewCell.m | 2 +- .../DeactivateAccountViewController.m | 4 +-- .../Language/LanguagePickerViewController.m | 2 +- .../CountryPickerViewController.m | 2 +- .../Modules/Settings/SettingsViewController.m | 30 +++++++++---------- Riot/Modules/Settings/Views/DeviceView.m | 2 +- .../TableViewCellWithPhoneNumberTextField.m | 7 +++-- .../UserDevices/Views/DeviceTableViewCell.m | 2 +- Riot/Utils/EventFormatter.m | 2 +- 56 files changed, 115 insertions(+), 111 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 9416ae1fe..8b639715f 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -36,7 +36,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; alpha:1.0] #pragma mark - Riot Theme Colors (depends on the selected theme light or dark). -extern UIColor *kRiotPrimaryTextColor; extern UIColor *kRiotSecondaryTextColor; //subtitle, sending messages color. extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. extern UIColor *kRiotTopicTextColor; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index bab61734a..418712e49 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -26,7 +26,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; -UIColor *kRiotPrimaryTextColor; UIColor *kRiotSecondaryTextColor; UIColor *kRiotPlaceholderTextColor; UIColor *kRiotTopicTextColor; @@ -146,7 +145,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Apply theme color constants id theme = [RiotDesignValues theme]; - kRiotPrimaryTextColor = theme.textPrimaryColor; kRiotSecondaryTextColor = theme.textSecondaryColor; kRiotTopicTextColor = theme.baseTextSecondaryColor; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 56a18e78e..b1b2fc70b 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -170,10 +170,10 @@ [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateNormal]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateHighlighted]; - self.homeServerTextField.textColor = kRiotPrimaryTextColor; + self.homeServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; self.homeServerLabel.textColor = kRiotSecondaryTextColor; - self.identityServerTextField.textColor = kRiotPrimaryTextColor; + self.identityServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; self.identityServerLabel.textColor = kRiotSecondaryTextColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index e801b1e26..b302dd986 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -103,15 +103,15 @@ { [super customizeViewRendering]; - self.repeatPasswordTextField.textColor = kRiotPrimaryTextColor; - self.userLoginTextField.textColor = kRiotPrimaryTextColor; - self.passWordTextField.textColor = kRiotPrimaryTextColor; + self.repeatPasswordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.userLoginTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.passWordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.emailTextField.textColor = kRiotPrimaryTextColor; - self.phoneTextField.textColor = kRiotPrimaryTextColor; + self.emailTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.phoneTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.isoCountryCodeLabel.textColor = kRiotPrimaryTextColor; - self.callingCodeLabel.textColor = kRiotPrimaryTextColor; + self.isoCountryCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.callingCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.messageLabel.textColor = kRiotSecondaryTextColor; self.messageLabel.numberOfLines = 0; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 2b15b4b58..67c54cf3e 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -105,11 +105,11 @@ { [super customizeViewRendering]; - self.messageLabel.textColor = kRiotPrimaryTextColor; + self.messageLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.emailTextField.textColor = kRiotPrimaryTextColor; - self.passWordTextField.textColor = kRiotPrimaryTextColor; - self.repeatPasswordTextField.textColor = kRiotPrimaryTextColor; + self.emailTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.passWordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.repeatPasswordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; self.messageLabel.numberOfLines = 0; diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 4cfeb35e2..1476d2474 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -150,14 +150,14 @@ self.bugReportDescriptionTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; - self.titleLabel.textColor = kRiotPrimaryTextColor; - self.sendingLabel.textColor = kRiotPrimaryTextColor; - self.descriptionLabel.textColor = kRiotPrimaryTextColor; - self.bugReportDescriptionTextView.textColor = kRiotPrimaryTextColor; + self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.sendingLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.descriptionLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.bugReportDescriptionTextView.textColor = RiotDesignValues.theme.textPrimaryColor; self.bugReportDescriptionTextView.tintColor = RiotDesignValues.theme.tintColor; - self.logsDescriptionLabel.textColor = kRiotPrimaryTextColor; - self.sendLogsLabel.textColor = kRiotPrimaryTextColor; - self.sendScreenshotLabel.textColor = kRiotPrimaryTextColor; + self.logsDescriptionLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.sendLogsLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.sendScreenshotLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.sendButton.tintColor = RiotDesignValues.theme.tintColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 93e3ad985..ca54bbacf 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -100,10 +100,10 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.barTitleColor = kRiotPrimaryTextColor; + self.barTitleColor = RiotDesignValues.theme.textPrimaryColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; - self.callerNameLabel.textColor = kRiotPrimaryTextColor; + self.callerNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.callStatusLabel.textColor = kRiotTopicTextColor; self.localPreviewContainerView.layer.borderColor = RiotDesignValues.theme.tintColor.CGColor; diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 82d4552c6..87cbd4c26 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -75,7 +75,7 @@ static const CGFloat kButtonSize = 80.0; self.callerNameLabel = [[UILabel alloc] init]; self.callerNameLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.callerNameLabel.textColor = kRiotPrimaryTextColor; + self.callerNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.callerNameLabel.font = [UIFont systemFontOfSize:24.0 weight:UIFontWeightMedium]; self.callerNameLabel.text = callerName; self.callerNameLabel.textAlignment = NSTextAlignmentCenter; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 04dd79713..48d86f491 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -754,7 +754,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } // Apply the current UI theme. - networkLabel.textColor = kRiotPrimaryTextColor; + networkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; directoryServerLabel.textColor = kRiotSecondaryTextColor; // Set the current directory server name diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 866263c7a..093a29e16 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -48,7 +48,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeTableViewCellRendering]; - self.roomTitle.textColor = kRiotPrimaryTextColor; + self.roomTitle.textColor = RiotDesignValues.theme.textPrimaryColor; self.lastEventDescription.textColor = kRiotSecondaryTextColor; self.lastEventDate.textColor = kRiotSecondaryTextColor; self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index f6eda95e3..863a7039f 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -453,7 +453,7 @@ { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; sectionHeader.mxkContentView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - sectionHeader.mxkLabel.textColor = kRiotPrimaryTextColor; + sectionHeader.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; NSString* title = [self.dataSource tableView:tableView titleForHeaderInSection:section]; diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index bcf57b5e4..22377578c 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -120,7 +120,7 @@ self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; self.mainHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - _groupName.textColor = kRiotPrimaryTextColor; + _groupName.textColor = RiotDesignValues.theme.textPrimaryColor; _groupDescription.textColor = kRiotTopicTextColor; _groupDescription.numberOfLines = 0; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index fd162ff6c..9c30adbc0 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -915,7 +915,7 @@ { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; sectionHeader.mxkContentView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - sectionHeader.mxkLabel.textColor = kRiotPrimaryTextColor; + sectionHeader.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; sectionHeader.mxkLabel.text = NSLocalizedStringFromTable(@"group_participants_invited_section", @"Vector", nil); diff --git a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m index ea0d153b4..a4adb6d0b 100644 --- a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m +++ b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m @@ -20,6 +20,7 @@ #import "AvatarGenerator.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation GroupRoomTableViewCell @@ -36,7 +37,7 @@ { [super customizeTableViewCellRendering]; - self.roomDisplayName.textColor = kRiotPrimaryTextColor; + self.roomDisplayName.textColor = RiotDesignValues.theme.textPrimaryColor; self.roomTopic.textColor = kRiotSecondaryTextColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.m b/Riot/Modules/Communities/Views/GroupTableViewCell.m index 538afc64d..5742fcaae 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.m @@ -41,7 +41,7 @@ { [super customizeTableViewCellRendering]; - self.groupName.textColor = kRiotPrimaryTextColor; + self.groupName.textColor = RiotDesignValues.theme.textPrimaryColor; self.groupDescription.textColor = kRiotSecondaryTextColor; self.memberCount.textColor = kRiotSecondaryTextColor; diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 3568d4ea6..89701adb3 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -970,7 +970,7 @@ } // Apply UI theme - checkboxLabel.textColor = kRiotPrimaryTextColor; + checkboxLabel.textColor = RiotDesignValues.theme.textPrimaryColor; // Set the right value of the tick box localContactsCheckbox.image = hideNonMatrixEnabledContacts ? [UIImage imageNamed:@"selection_tick"] : [UIImage imageNamed:@"selection_untick"]; diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index d7150176d..450d3ebb4 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -236,7 +236,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; self.headerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.contactNameLabel.textColor = kRiotPrimaryTextColor; + self.contactNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.contactStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. @@ -735,8 +735,8 @@ [cellWithButton.mxkButton setTitle:title forState:UIControlStateNormal]; [cellWithButton.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [cellWithButton.mxkButton setTitleColor:kRiotPrimaryTextColor forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:kRiotPrimaryTextColor forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateHighlighted]; [cellWithButton.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index 37c535486..29c3aed7a 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -35,7 +35,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = kRiotPrimaryTextColor; + self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; // Prepare direct room border CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index 5e10b43c1..784fea296 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -53,7 +53,7 @@ [super customizeTableViewCellRendering]; // apply the vector colours - self.contactDisplayNameLabel.textColor = kRiotPrimaryTextColor; + self.contactDisplayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.contactInformationLabel.textColor = kRiotSecondaryTextColor; // Clear the default background color of a MXKImageView instance diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index c9fe44e35..b3087cea3 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -30,7 +30,7 @@ self.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.defaultTextColor = kRiotPrimaryTextColor; + self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; self.verifyButton.tintColor = RiotDesignValues.theme.tintColor; self.blockButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index 1b851f5d0..f285f4eb5 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -28,7 +28,7 @@ { [super customizeTableViewCellRendering]; - self.title.textColor = kRiotPrimaryTextColor; + self.title.textColor = RiotDesignValues.theme.textPrimaryColor; self.message.textColor = kRiotSecondaryTextColor; diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index 9d1a4aa76..de01419be 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.roomNameLabel.textColor = kRiotSecondaryTextColor; diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index d718c2781..c9012f1eb 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.roomNameLabel.textColor = kRiotSecondaryTextColor; diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m index 81e47d81c..2cc5a6c47 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m @@ -20,6 +20,7 @@ #import "PublicRoomsDirectoryDataSource.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation DirectoryRecentTableViewCell @@ -29,7 +30,7 @@ { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = kRiotPrimaryTextColor; + self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.descriptionLabel.textColor = kRiotSecondaryTextColor; } diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index e65fce10b..c0ca9ce00 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -29,7 +29,7 @@ { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = kRiotPrimaryTextColor; + self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 246ce8b70..53f8b9f1c 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -66,9 +66,9 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeCollectionViewCellRendering]; - self.roomTitle.textColor = kRiotPrimaryTextColor; - self.roomTitle1.textColor = kRiotPrimaryTextColor; - self.roomTitle2.textColor = kRiotPrimaryTextColor; + self.roomTitle.textColor = RiotDesignValues.theme.textPrimaryColor; + self.roomTitle1.textColor = RiotDesignValues.theme.textPrimaryColor; + self.roomTitle2.textColor = RiotDesignValues.theme.textPrimaryColor; self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; // Prepare direct room border diff --git a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m index a728a77b2..6013e520a 100644 --- a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m +++ b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m @@ -18,6 +18,7 @@ #import "MediaAlbumTableCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation MediaAlbumTableCell @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.albumDisplayNameLabel.textColor = kRiotPrimaryTextColor; + self.albumDisplayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.albumCountLabel.textColor = kRiotSecondaryTextColor; } diff --git a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m index a8fbca4cc..4c82f0817 100644 --- a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m +++ b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m @@ -21,6 +21,7 @@ #import "AvatarGenerator.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation PublicRoomTableViewCell @@ -37,7 +38,7 @@ { [super customizeTableViewCellRendering]; - self.roomDisplayName.textColor = kRiotPrimaryTextColor; + self.roomDisplayName.textColor = RiotDesignValues.theme.textPrimaryColor; self.roomTopic.textColor = kRiotSecondaryTextColor; self.memberCount.textColor = kRiotSecondaryTextColor; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 94650209f..5f048513f 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -224,7 +224,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; self.memberHeaderView.backgroundColor = RiotDesignValues.theme.baseColor; - self.roomMemberNameLabel.textColor = kRiotPrimaryTextColor; + self.roomMemberNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.roomMemberStatusLabel.textColor = RiotDesignValues.theme.tintColor; // Check the table view style to select its bg color. @@ -781,8 +781,8 @@ } else { - [cellWithButton.mxkButton setTitleColor:kRiotPrimaryTextColor forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:kRiotPrimaryTextColor forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateHighlighted]; } [cellWithButton.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index b059a2db0..09fbe8195 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -1223,7 +1223,7 @@ frame.size.width = sectionHeader.frame.size.width - 10; frame.size.height -= 10; UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame]; - headerLabel.textColor = kRiotPrimaryTextColor; + headerLabel.textColor = RiotDesignValues.theme.textPrimaryColor; headerLabel.font = [UIFont boldSystemFontOfSize:15.0]; headerLabel.backgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index b9ca8da95..84cdde9fa 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -101,7 +101,7 @@ self.overlayView.backgroundColor = kRiotOverlayColor; self.overlayView.alpha = 1.0; - self.titleLabel.textColor = kRiotPrimaryTextColor; + self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; // Check the table view style to select its bg color. @@ -196,7 +196,7 @@ { MXKReadReceiptTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[MXKReadReceiptTableViewCell defaultReuseIdentifier] forIndexPath:indexPath]; - cell.displayNameLabel.textColor = kRiotPrimaryTextColor; + cell.displayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.receiptDescriptionLabel.textColor = kRiotSecondaryTextColor; if (indexPath.row < self.roomMembers.count) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index f0d480bde..e540570a3 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -425,7 +425,7 @@ // Prepare jump to last unread banner self.jumpToLastUnreadBannerContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: kRiotPrimaryTextColor, NSForegroundColorAttributeName: kRiotPrimaryTextColor}]; + self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: RiotDesignValues.theme.textPrimaryColor, NSForegroundColorAttributeName: RiotDesignValues.theme.textPrimaryColor}]; self.expandedHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 2a94239b0..225793f9e 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2053,7 +2053,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { // Customize label style UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view; - tableViewHeaderFooterView.textLabel.textColor = kRiotPrimaryTextColor; + tableViewHeaderFooterView.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15]; } } @@ -2178,7 +2178,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomPhotoCell.mxkImageView.defaultBackgroundColor = [UIColor clearColor]; roomPhotoCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_photo", @"Vector", nil); - roomPhotoCell.mxkLabel.textColor = kRiotPrimaryTextColor; + roomPhotoCell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; if (updatedItemsDict[kRoomSettingsAvatarKey]) { @@ -2235,7 +2235,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomNameCell.mxkTextFieldTrailingConstraint.constant = 15; roomNameCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_room_name", @"Vector", nil); - roomNameCell.mxkLabel.textColor = kRiotPrimaryTextColor; + roomNameCell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; roomNameCell.accessoryType = UITableViewCellAccessoryNone; roomNameCell.accessoryView = nil; @@ -2280,10 +2280,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti NSArray *labels = roomTagCell.labels; UILabel *label; label = labels[0]; - label.textColor = kRiotPrimaryTextColor; + label.textColor = RiotDesignValues.theme.textPrimaryColor; label.text = NSLocalizedStringFromTable(@"room_details_favourite_tag", @"Vector", nil); label = labels[1]; - label.textColor = kRiotPrimaryTextColor; + label.textColor = RiotDesignValues.theme.textPrimaryColor; label.text = NSLocalizedStringFromTable(@"room_details_low_priority_tag", @"Vector", nil); if (updatedItemsDict[kRoomSettingsTagKey]) @@ -2525,7 +2525,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *addressCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; addressCell.textLabel.font = [UIFont systemFontOfSize:16]; - addressCell.textLabel.textColor = kRiotPrimaryTextColor; + addressCell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; addressCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; addressCell.accessoryView = nil; addressCell.accessoryType = UITableViewCellAccessoryNone; @@ -2616,7 +2616,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *communityCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; communityCell.textLabel.font = [UIFont systemFontOfSize:16]; - communityCell.textLabel.textColor = kRiotPrimaryTextColor; + communityCell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; communityCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; communityCell.accessoryView = nil; communityCell.accessoryType = UITableViewCellAccessoryNone; @@ -2634,7 +2634,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *addressCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; addressCell.textLabel.font = [UIFont systemFontOfSize:16]; - addressCell.textLabel.textColor = kRiotPrimaryTextColor; + addressCell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; addressCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; addressCell.accessoryView = nil; addressCell.accessoryType = UITableViewCellAccessoryNone; @@ -2656,7 +2656,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_room_id", @"Vector", nil); - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.detailTextLabel.font = [UIFont systemFontOfSize:15]; cell.detailTextLabel.text = mxRoomState.roomId; @@ -2719,7 +2719,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_enabled", @"Vector", nil); - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -2753,7 +2753,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_disabled", @"Vector", nil); - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -2801,7 +2801,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.mxkLabelLeadingConstraint.constant = cell.separatorInset.left; cell.mxkSwitchTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = kRiotPrimaryTextColor; + cell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged]; diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m index e93bf1440..3ac1cf733 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m @@ -18,6 +18,7 @@ #import "TableViewCellWithCheckBoxAndLabel.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation TableViewCellWithCheckBoxAndLabel @@ -25,7 +26,7 @@ { [super customizeTableViewCellRendering]; - _label.textColor = kRiotPrimaryTextColor; + _label.textColor = RiotDesignValues.theme.textPrimaryColor; } - (void)setEnabled:(BOOL)enabled diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m index 4260ad0f1..2b2cf6f03 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m @@ -18,6 +18,7 @@ #import "TableViewCellWithLabelAndLargeTextView.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation TableViewCellWithLabelAndLargeTextView @@ -36,8 +37,8 @@ { [super customizeTableViewCellRendering]; - _label.textColor = kRiotPrimaryTextColor; - _textView.textColor = kRiotPrimaryTextColor; + _label.textColor = RiotDesignValues.theme.textPrimaryColor; + _textView.textColor = RiotDesignValues.theme.textPrimaryColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 0477efbd7..acead1d1b 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -356,7 +356,7 @@ [roomReplacementAttributedString appendAttributedString:roomLinkAttributedString]; NSRange wholeStringRange = NSMakeRange(0, roomReplacementAttributedString.length); - [roomReplacementAttributedString addAttribute:NSForegroundColorAttributeName value:kRiotPrimaryTextColor range:wholeStringRange]; + [roomReplacementAttributedString addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.textPrimaryColor range:wholeStringRange]; self.messageTextView.attributedText = roomReplacementAttributedString; } @@ -365,7 +365,7 @@ self.messageTextView.text = NSLocalizedStringFromTable(@"room_replacement_information", @"Vector", nil); } - self.messageTextView.tintColor = kRiotPrimaryTextColor; + self.messageTextView.tintColor = RiotDesignValues.theme.textPrimaryColor; self.messageTextView.hidden = NO; self.messageTextView.backgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index 26f82538e..36d9bb7c7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index c44b53c11..51a5aba56 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index 0a18ab22a..eb3937c37 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index b098875da..384bbc946 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index e277347ea..f0f2dfebe 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index 259adac7e..4a0e72ee9 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index 633cba7e7..04c5d8f01 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = kRiotPrimaryTextColor; + self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m index 674e2e115..7bc995254 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m @@ -58,7 +58,7 @@ static CGFloat const kCustomBackgroundCornerRadius = 5.0; { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = kRiotPrimaryTextColor; + self.messageTextView.tintColor = RiotDesignValues.theme.textPrimaryColor; self.customBackgroundView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; } diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 64742a570..605b636ce 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -27,7 +27,7 @@ self.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.textView.textColor = kRiotPrimaryTextColor; + self.textView.textColor = RiotDesignValues.theme.textPrimaryColor; self.redactButton.tintColor = RiotDesignValues.theme.tintColor; self.closeButton.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 39c727156..ff23658b1 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -51,7 +51,7 @@ self.separatorView.backgroundColor = kRiotAuxiliaryColor; self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; - self.disabledReasonTextView.textColor = kRiotPrimaryTextColor; + self.disabledReasonTextView.textColor = RiotDesignValues.theme.textPrimaryColor; self.disabledReasonTextView.tintColor = RiotDesignValues.theme.tintColor; self.disabledReasonTextView.editable = NO; self.disabledReasonTextView.scrollEnabled = NO; diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 1b7f21e19..ac7f5900a 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -95,7 +95,7 @@ growingTextView.backgroundColor = [UIColor clearColor]; growingTextView.font = [UIFont systemFontOfSize:15]; - growingTextView.textColor = kRiotPrimaryTextColor; + growingTextView.textColor = RiotDesignValues.theme.textPrimaryColor; growingTextView.tintColor = RiotDesignValues.theme.tintColor; growingTextView.internalTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 675c5b4d2..858fbddd0 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -29,7 +29,7 @@ { [super customizeTableViewCellRendering]; - self.descLabel.textColor = kRiotPrimaryTextColor; + self.descLabel.textColor = RiotDesignValues.theme.textPrimaryColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 8617b6c02..837c78a72 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -132,13 +132,13 @@ static CGFloat const kTextFontSize = 15.0; { self.normalStringAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize], - NSForegroundColorAttributeName: kRiotPrimaryTextColor + NSForegroundColorAttributeName: RiotDesignValues.theme.textPrimaryColor }; self.emphasizeStringAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize weight:UIFontWeightBold], - NSForegroundColorAttributeName: kRiotPrimaryTextColor + NSForegroundColorAttributeName: RiotDesignValues.theme.textPrimaryColor }; } diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index fb325864e..908471381 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -114,7 +114,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.detailTextLabel.textColor = kRiotSecondaryTextColor; cell.backgroundColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 430eacf0d..9fb33b786 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -118,7 +118,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.detailTextLabel.textColor = kRiotSecondaryTextColor; cell.backgroundColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index c7e19c688..9a4391abf 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -955,30 +955,30 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Crypto information NSMutableAttributedString *cryptoInformationString = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_name", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:account.device.displayName ? account.device.displayName : @"" - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_id", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:account.device.deviceId ? account.device.deviceId : @"" - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_key", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; NSString *fingerprint = account.mxSession.crypto.deviceEd25519Key; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:fingerprint ? fingerprint : @"" - attributes:@{NSForegroundColorAttributeName : kRiotPrimaryTextColor, + attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:17]}]]; return cryptoInformationString; @@ -1295,7 +1295,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkTextFieldLeadingConstraint.constant = 16; cell.mxkTextFieldTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = kRiotPrimaryTextColor; + cell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.mxkTextField.userInteractionEnabled = YES; cell.mxkTextField.borderStyle = UITextBorderStyleNone; @@ -1322,7 +1322,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkLabelLeadingConstraint.constant = cell.separatorInset.left; cell.mxkSwitchTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = kRiotPrimaryTextColor; + cell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1348,7 +1348,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); } cell.textLabel.accessibilityIdentifier = nil; cell.textLabel.font = [UIFont systemFontOfSize:17]; - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; return cell; } @@ -1357,7 +1357,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { MXKTableViewCellWithTextView *textViewCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier] forIndexPath:indexPath]; - textViewCell.mxkTextView.textColor = kRiotPrimaryTextColor; + textViewCell.mxkTextView.textColor = RiotDesignValues.theme.textPrimaryColor; textViewCell.mxkTextView.font = [UIFont systemFontOfSize:17]; textViewCell.mxkTextView.backgroundColor = [UIColor clearColor]; textViewCell.mxkTextViewLeadingConstraint.constant = tableView.separatorInset.left; @@ -1436,7 +1436,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); profileCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_profile_picture", @"Vector", nil); profileCell.accessibilityIdentifier=@"SettingsVCProfilPictureStaticText"; - profileCell.mxkLabel.textColor = kRiotPrimaryTextColor; + profileCell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; // if the user defines a new avatar if (newAvatarImage) @@ -1796,7 +1796,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language]; languageDescription = [languageDescription capitalizedStringWithLocale:locale]; - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_language", @"Vector", nil); cell.detailTextLabel.text = languageDescription; @@ -1833,7 +1833,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); @"Vector", nil); - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_theme", @"Vector", nil); cell.detailTextLabel.text = i18nTheme; @@ -1882,7 +1882,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[NSBundle mainBundle] preferredLocalizations][0]]; NSString *countryName = [local displayNameForKey:NSLocaleCountryCode value:countryCode]; - cell.textLabel.textColor = kRiotPrimaryTextColor; + cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_contacts_phonebook_country", @"Vector", nil); cell.detailTextLabel.text = countryName; @@ -2334,7 +2334,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { // Customize label style UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view; - tableViewHeaderFooterView.textLabel.textColor = kRiotPrimaryTextColor; + tableViewHeaderFooterView.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15]; } } diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 8a70e7aa7..01fc6c8cf 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -30,7 +30,7 @@ self.containerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.defaultTextColor = kRiotPrimaryTextColor; + self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; self.deleteButton.tintColor = RiotDesignValues.theme.tintColor; self.renameButton.tintColor = RiotDesignValues.theme.tintColor; diff --git a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m index 3f9d7e012..6476e51a9 100644 --- a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m +++ b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m @@ -17,6 +17,7 @@ #import "TableViewCellWithPhoneNumberTextField.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" #import "NBPhoneNumberUtil.h" @@ -26,10 +27,10 @@ { [super customizeTableViewCellRendering]; - self.mxkLabel.textColor = kRiotPrimaryTextColor; - self.mxkTextField.textColor = kRiotPrimaryTextColor; + self.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.mxkTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - _isoCountryCodeLabel.textColor = kRiotPrimaryTextColor; + _isoCountryCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; } - (void)setIsoCountryCode:(NSString *)isoCountryCode diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index bf79becc5..7b3f42e3b 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -32,7 +32,7 @@ { [super customizeTableViewCellRendering]; - self.deviceName.textColor = kRiotPrimaryTextColor; + self.deviceName.textColor = RiotDesignValues.theme.textPrimaryColor; [self.verifyButton.layer setCornerRadius:5]; self.verifyButton.clipsToBounds = YES; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 7427285de..c1d8a65ac 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -217,7 +217,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; font-size: small; \ }", (unsigned long)bgColor]; - self.defaultTextColor = kRiotPrimaryTextColor; + self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; self.subTitleTextColor = kRiotSecondaryTextColor; self.prefixTextColor = kRiotSecondaryTextColor; self.bingTextColor = RiotDesignValues.theme.notificationMentionColor; From 67044e3451e3caba4db12120112e2a135b927df0 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 18:05:21 +0100 Subject: [PATCH 040/244] reskin: kill kRiotSecondaryTextColor --- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m | 4 ++-- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 3 --- .../Authentication/AuthenticationViewController.m | 6 +++--- Riot/Modules/Authentication/Views/AuthInputsView.m | 2 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../Common/Recents/DataSources/RecentsDataSource.m | 4 ++-- .../Modules/Common/Recents/Views/RecentTableViewCell.m | 8 ++++---- .../Modules/Communities/Home/GroupHomeViewController.m | 2 +- .../Members/GroupParticipantsViewController.m | 2 +- .../Communities/Rooms/GroupRoomsViewController.m | 2 +- .../Communities/Rooms/Views/GroupRoomTableViewCell.m | 2 +- Riot/Modules/Communities/Views/GroupTableViewCell.m | 4 ++-- Riot/Modules/Contacts/DataSources/ContactsDataSource.m | 2 +- Riot/Modules/Contacts/Views/ContactTableViewCell.m | 2 +- .../Files/Views/FilesSearchTableViewCell.m | 4 ++-- .../Views/MessagesSearchResultAttachmentBubbleCell.m | 2 +- .../Views/MessagesSearchResultTextMsgBubbleCell.m | 2 +- .../GlobalSearch/Views/DirectoryRecentTableViewCell.m | 2 +- Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m | 2 +- .../DataSources/PublicRoomsDirectoryDataSource.m | 3 ++- .../PublicRoomList/Views/PublicRoomTableViewCell.m | 4 ++-- .../Room/Members/RoomParticipantsViewController.m | 2 +- .../ReadReceiptsDetail/ReadReceiptsViewController.m | 6 +++--- .../Modules/Room/Settings/RoomSettingsViewController.m | 10 +++++----- .../Modules/Room/Views/Activities/RoomActivitiesView.m | 4 ++-- .../Room/Views/Title/Preview/PreviewRoomTitleView.m | 2 +- Riot/Modules/Room/Views/Title/RoomTitleView.m | 4 ++-- .../Views/DirectoryServerDetailTableViewCell.m | 3 ++- .../Settings/Language/LanguagePickerViewController.m | 2 +- .../PhoneCountry/CountryPickerViewController.m | 2 +- Riot/Modules/Settings/SettingsViewController.m | 2 +- Riot/Modules/StartChat/StartChatViewController.m | 2 +- Riot/Utils/EventFormatter.m | 6 +++--- .../Modules/Fallback/FallbackViewController.m | 8 +++++++- 35 files changed, 61 insertions(+), 57 deletions(-) diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 906932e71..f3374a5e3 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -62,7 +62,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT timeLabel.text = [bubbleData.eventFormatter timeStringFromDate:component.date]; timeLabel.textAlignment = NSTextAlignmentRight; - timeLabel.textColor = kRiotSecondaryTextColor; + timeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { timeLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightLight]; @@ -264,7 +264,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT timeLabel.text = [bubbleData.eventFormatter dateStringFromDate:date withTime:NO]; timeLabel.textAlignment = NSTextAlignmentRight; - timeLabel.textColor = kRiotSecondaryTextColor; + timeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { timeLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightLight]; diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 8b639715f..d915937cb 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -36,7 +36,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; alpha:1.0] #pragma mark - Riot Theme Colors (depends on the selected theme light or dark). -extern UIColor *kRiotSecondaryTextColor; //subtitle, sending messages color. extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. extern UIColor *kRiotTopicTextColor; extern UIColor *kRiotSelectedBgColor; // nil is used to keep the default color. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 418712e49..332a582e6 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -26,7 +26,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; -UIColor *kRiotSecondaryTextColor; UIColor *kRiotPlaceholderTextColor; UIColor *kRiotTopicTextColor; UIColor *kRiotSelectedBgColor; @@ -145,8 +144,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Apply theme color constants id theme = [RiotDesignValues theme]; - kRiotSecondaryTextColor = theme.textSecondaryColor; - kRiotTopicTextColor = theme.baseTextSecondaryColor; kRiotAuxiliaryColor = theme.headerTextSecondaryColor; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index b1b2fc70b..62ca41c73 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -166,15 +166,15 @@ [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; [self updateForgotPwdButtonVisibility]; - NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : kRiotSecondaryTextColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}]; + NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textSecondaryColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateNormal]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateHighlighted]; self.homeServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.homeServerLabel.textColor = kRiotSecondaryTextColor; + self.homeServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.identityServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.identityServerLabel.textColor = kRiotSecondaryTextColor; + self.identityServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.activityIndicator.backgroundColor = kRiotOverlayColor; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index b302dd986..62df4a34a 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -113,7 +113,7 @@ self.isoCountryCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.callingCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.messageLabel.textColor = kRiotSecondaryTextColor; + self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.messageLabel.numberOfLines = 0; if (kRiotPlaceholderTextColor) diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 87cbd4c26..56361c33d 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -82,7 +82,7 @@ static const CGFloat kButtonSize = 80.0; self.callInfoLabel = [[UILabel alloc] init]; self.callInfoLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.callInfoLabel.textColor = kRiotSecondaryTextColor; + self.callInfoLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.callInfoLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.callInfoLabel.text = callInfo; self.callInfoLabel.textAlignment = NSTextAlignmentCenter; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 48d86f491..50dd66286 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -755,7 +755,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Apply the current UI theme. networkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - directoryServerLabel.textColor = kRiotSecondaryTextColor; + directoryServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; // Set the current directory server name directoryServerLabel.text = _publicRoomsDirectoryDataSource.directoryServerDisplayname; @@ -846,7 +846,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = kRiotSecondaryTextColor; + tableViewCell.textLabel.textColor = RiotDesignValues.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 093a29e16..09fc2f07f 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -49,8 +49,8 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; [super customizeTableViewCellRendering]; self.roomTitle.textColor = RiotDesignValues.theme.textPrimaryColor; - self.lastEventDescription.textColor = kRiotSecondaryTextColor; - self.lastEventDate.textColor = kRiotSecondaryTextColor; + self.lastEventDescription.textColor = RiotDesignValues.theme.textSecondaryColor; + self.lastEventDate.textColor = RiotDesignValues.theme.textSecondaryColor; self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; // Prepare direct room border @@ -94,7 +94,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { // Force the default text color for the last message (cancel highlighted message color) NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:roomCellData.lastEventAttributedTextMessage]; - [lastEventDescription addAttribute:NSForegroundColorAttributeName value:kRiotSecondaryTextColor range:NSMakeRange(0, lastEventDescription.length)]; + [lastEventDescription addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.textSecondaryColor range:NSMakeRange(0, lastEventDescription.length)]; self.lastEventDescription.attributedText = lastEventDescription; } else @@ -136,7 +136,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; } else { - self.lastEventDate.textColor = kRiotSecondaryTextColor; + self.lastEventDate.textColor = RiotDesignValues.theme.textSecondaryColor; // The room title is not bold anymore if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 22377578c..84443ce62 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -140,7 +140,7 @@ if (_groupLongDescription) { - _groupLongDescription.textColor = kRiotSecondaryTextColor; + _groupLongDescription.textColor = RiotDesignValues.theme.textSecondaryColor; _groupLongDescription.tintColor = kRiotColorBlue; // Update HTML loading options diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 9c30adbc0..59b100273 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -1205,7 +1205,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = kRiotSecondaryTextColor; + searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index b3b85a664..71c9c394d 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -606,7 +606,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = kRiotSecondaryTextColor; + searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m index a4adb6d0b..a30f68051 100644 --- a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m +++ b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m @@ -38,7 +38,7 @@ [super customizeTableViewCellRendering]; self.roomDisplayName.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomTopic.textColor = kRiotSecondaryTextColor; + self.roomTopic.textColor = RiotDesignValues.theme.textSecondaryColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.m b/Riot/Modules/Communities/Views/GroupTableViewCell.m index 5742fcaae..6f22506ca 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.m @@ -42,8 +42,8 @@ [super customizeTableViewCellRendering]; self.groupName.textColor = RiotDesignValues.theme.textPrimaryColor; - self.groupDescription.textColor = kRiotSecondaryTextColor; - self.memberCount.textColor = kRiotSecondaryTextColor; + self.groupDescription.textColor = RiotDesignValues.theme.textSecondaryColor; + self.memberCount.textColor = RiotDesignValues.theme.textSecondaryColor; if (self.missedNotifAndUnreadBadgeLabel) { diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 89701adb3..b20056971 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -595,7 +595,7 @@ if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = kRiotSecondaryTextColor; + tableViewCell.textLabel.textColor = RiotDesignValues.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index 784fea296..eefdc53ad 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -54,7 +54,7 @@ // apply the vector colours self.contactDisplayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.contactInformationLabel.textColor = kRiotSecondaryTextColor; + self.contactInformationLabel.textColor = RiotDesignValues.theme.textSecondaryColor; // Clear the default background color of a MXKImageView instance self.thumbnailView.defaultBackgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index f285f4eb5..0a380c467 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -30,9 +30,9 @@ self.title.textColor = RiotDesignValues.theme.textPrimaryColor; - self.message.textColor = kRiotSecondaryTextColor; + self.message.textColor = RiotDesignValues.theme.textSecondaryColor; - self.date.tintColor = kRiotSecondaryTextColor; + self.date.tintColor = RiotDesignValues.theme.textSecondaryColor; } + (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index de01419be..da3362a0a 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -28,7 +28,7 @@ self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomNameLabel.textColor = kRiotSecondaryTextColor; + self.roomNameLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index c9012f1eb..1b5a067ea 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -28,7 +28,7 @@ self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomNameLabel.textColor = kRiotSecondaryTextColor; + self.roomNameLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m index 2cc5a6c47..816fd7407 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m @@ -31,7 +31,7 @@ [super customizeTableViewCellRendering]; self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.descriptionLabel.textColor = kRiotSecondaryTextColor; + self.descriptionLabel.textColor = RiotDesignValues.theme.textSecondaryColor; } - (void)render:(PublicRoomsDirectoryDataSource *)publicRoomsDirectoryDataSource diff --git a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m index 6013e520a..e6cc0ec11 100644 --- a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m +++ b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m @@ -27,7 +27,7 @@ [super customizeTableViewCellRendering]; self.albumDisplayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.albumCountLabel.textColor = kRiotSecondaryTextColor; + self.albumCountLabel.textColor = RiotDesignValues.theme.textSecondaryColor; } @end diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m index 82fb580a9..f105775a2 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m @@ -20,6 +20,7 @@ #import "PublicRoomTableViewCell.h" #import "AppDelegate.h" +#import "Riot-Swift.h" #pragma mark - Constants definitions @@ -338,7 +339,7 @@ double const kPublicRoomsDirectoryDataExpiration = 10; if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = kRiotSecondaryTextColor; + tableViewCell.textLabel.textColor = RiotDesignValues.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m index 4c82f0817..87686ba7c 100644 --- a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m +++ b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m @@ -39,8 +39,8 @@ [super customizeTableViewCellRendering]; self.roomDisplayName.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomTopic.textColor = kRiotSecondaryTextColor; - self.memberCount.textColor = kRiotSecondaryTextColor; + self.roomTopic.textColor = RiotDesignValues.theme.textSecondaryColor; + self.memberCount.textColor = RiotDesignValues.theme.textSecondaryColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 09fbe8195..b82abf08a 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -1691,7 +1691,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = kRiotSecondaryTextColor; + searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 84cdde9fa..30d362b5f 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -197,7 +197,7 @@ MXKReadReceiptTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[MXKReadReceiptTableViewCell defaultReuseIdentifier] forIndexPath:indexPath]; cell.displayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - cell.receiptDescriptionLabel.textColor = kRiotSecondaryTextColor; + cell.receiptDescriptionLabel.textColor = RiotDesignValues.theme.textSecondaryColor; if (indexPath.row < self.roomMembers.count) { @@ -224,9 +224,9 @@ NSString *receiptReadText = NSLocalizedStringFromTable(@"receipt_status_read", @"Vector", nil); NSString *receiptTimeText = [(MXKEventFormatter*)self.session.roomSummaryUpdateDelegate dateStringFromTimestamp:self.receipts[indexPath.row].ts withTime:YES]; - NSMutableAttributedString *receiptDescription = [[NSMutableAttributedString alloc] initWithString:receiptReadText attributes:@{NSForegroundColorAttributeName : kRiotSecondaryTextColor, NSFontAttributeName : [UIFont boldSystemFontOfSize:15]}]; + NSMutableAttributedString *receiptDescription = [[NSMutableAttributedString alloc] initWithString:receiptReadText attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textSecondaryColor, NSFontAttributeName : [UIFont boldSystemFontOfSize:15]}]; - [receiptDescription appendAttributedString:[[NSAttributedString alloc] initWithString:receiptTimeText attributes:@{NSForegroundColorAttributeName : kRiotSecondaryTextColor, NSFontAttributeName : [UIFont systemFontOfSize:15]}]]; + [receiptDescription appendAttributedString:[[NSAttributedString alloc] initWithString:receiptTimeText attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textSecondaryColor, NSFontAttributeName : [UIFont systemFontOfSize:15]}]]; cell.receiptDescriptionLabel.attributedText = receiptDescription; } diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 225793f9e..cb168feee 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2220,7 +2220,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // disable the edition if the user cannot update it topicTextView.editable = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomTopic]); - topicTextView.textColor = kRiotSecondaryTextColor; + topicTextView.textColor = RiotDesignValues.theme.textSecondaryColor; topicTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; @@ -2259,7 +2259,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // disable the edition if the user cannot update it nameTextField.userInteractionEnabled = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomName]); - nameTextField.textColor = kRiotSecondaryTextColor; + nameTextField.textColor = RiotDesignValues.theme.textSecondaryColor; // Add a "textFieldDidChange" notification method to the text field control. [nameTextField addTarget:self action:@selector(onTextFieldUpdate:) forControlEvents:UIControlEventEditingChanged]; @@ -2507,7 +2507,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } addAddressTextField.userInteractionEnabled = YES; addAddressTextField.text = currentValue; - addAddressTextField.textColor = kRiotSecondaryTextColor; + addAddressTextField.textColor = RiotDesignValues.theme.textSecondaryColor; addAddressTextField.tintColor = RiotDesignValues.theme.tintColor; addAddressTextField.font = [UIFont systemFontOfSize:17]; @@ -2598,7 +2598,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti } addGroupTextField.userInteractionEnabled = YES; addGroupTextField.text = currentValue; - addGroupTextField.textColor = kRiotSecondaryTextColor; + addGroupTextField.textColor = RiotDesignValues.theme.textSecondaryColor; addGroupTextField.tintColor = RiotDesignValues.theme.tintColor; addGroupTextField.font = [UIFont systemFontOfSize:17]; @@ -2660,7 +2660,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.detailTextLabel.font = [UIFont systemFontOfSize:15]; cell.detailTextLabel.text = mxRoomState.roomId; - cell.detailTextLabel.textColor = kRiotSecondaryTextColor; + cell.detailTextLabel.textColor = RiotDesignValues.theme.textSecondaryColor; cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; cell.selectionStyle = UITableViewCellSelectionStyleNone; diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index acead1d1b..9445af2af 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -115,7 +115,7 @@ self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; if (self.messageLabel.textColor != kRiotColorPinkRed) { - self.messageLabel.textColor = kRiotSecondaryTextColor; + self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; } } @@ -535,7 +535,7 @@ [self.messageTextView resignFirstResponder]; self.messageTextView.hidden = YES; - self.messageLabel.textColor = kRiotSecondaryTextColor; + self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; objc_removeAssociatedObjects(self.messageTextView); } diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 9049d3cbf..89326772c 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -74,7 +74,7 @@ self.previewLabel.textColor = kRiotTopicTextColor; self.previewLabel.numberOfLines = 0; - self.subNoticeLabel.textColor = kRiotSecondaryTextColor; + self.subNoticeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.subNoticeLabel.numberOfLines = 0; self.bottomBorderView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index fbd068589..405fa53a6 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -139,7 +139,7 @@ // Use same color as navigation bar self.backgroundColor = RiotDesignValues.theme.baseColor; - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? RiotDesignValues.theme.baseTextPrimaryColor : kRiotSecondaryTextColor); + self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? RiotDesignValues.theme.baseTextPrimaryColor : RiotDesignValues.theme.textSecondaryColor); } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -164,7 +164,7 @@ if (!self.displayNameTextField.text.length) { self.displayNameTextField.text = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; - self.displayNameTextField.textColor = kRiotSecondaryTextColor; + self.displayNameTextField.textColor = RiotDesignValues.theme.textSecondaryColor; } else { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m index da8649181..f3a139de8 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m @@ -17,6 +17,7 @@ #import "DirectoryServerDetailTableViewCell.h" #import "RiotDesignValues.h" +#import "Riot-Swift.h" @implementation DirectoryServerDetailTableViewCell @@ -24,7 +25,7 @@ { [super customizeTableViewCellRendering]; - self.detailDescLabel.textColor = kRiotSecondaryTextColor; + self.detailDescLabel.textColor = RiotDesignValues.theme.textSecondaryColor; } - (void)render:(id)cellData diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index 908471381..09d671eda 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -115,7 +115,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - cell.detailTextLabel.textColor = kRiotSecondaryTextColor; + cell.detailTextLabel.textColor = RiotDesignValues.theme.textSecondaryColor; cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 9fb33b786..5cc119e37 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -119,7 +119,7 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - cell.detailTextLabel.textColor = kRiotSecondaryTextColor; + cell.detailTextLabel.textColor = RiotDesignValues.theme.textSecondaryColor; cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 9a4391abf..edf8db390 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1300,7 +1300,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkTextField.userInteractionEnabled = YES; cell.mxkTextField.borderStyle = UITextBorderStyleNone; cell.mxkTextField.textAlignment = NSTextAlignmentRight; - cell.mxkTextField.textColor = kRiotSecondaryTextColor; + cell.mxkTextField.textColor = RiotDesignValues.theme.textSecondaryColor; cell.mxkTextField.font = [UIFont systemFontOfSize:16]; cell.mxkTextField.placeholder = nil; diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 945de65ce..d9cfb7edf 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -628,7 +628,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = kRiotSecondaryTextColor; + searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index c1d8a65ac..9049e1c1e 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -218,11 +218,11 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; }", (unsigned long)bgColor]; self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; - self.subTitleTextColor = kRiotSecondaryTextColor; - self.prefixTextColor = kRiotSecondaryTextColor; + self.subTitleTextColor = RiotDesignValues.theme.textSecondaryColor; + self.prefixTextColor = RiotDesignValues.theme.textSecondaryColor; self.bingTextColor = RiotDesignValues.theme.notificationMentionColor; self.encryptingTextColor = RiotDesignValues.theme.tintColor; - self.sendingTextColor = kRiotSecondaryTextColor; + self.sendingTextColor = RiotDesignValues.theme.textSecondaryColor; self.errorTextColor = kRiotColorRed; self.defaultTextFont = [UIFont systemFontOfSize:15]; diff --git a/RiotShareExtension/Modules/Fallback/FallbackViewController.m b/RiotShareExtension/Modules/Fallback/FallbackViewController.m index cae2cabce..e10aba785 100644 --- a/RiotShareExtension/Modules/Fallback/FallbackViewController.m +++ b/RiotShareExtension/Modules/Fallback/FallbackViewController.m @@ -17,6 +17,12 @@ #import "FallbackViewController.h" #import "RiotDesignValues.h" +#ifdef IS_SHARE_EXTENSION +#import "RiotShareExtension-Swift.h" +#else +#import "Riot-Swift.h" +#endif + @interface FallbackViewController () @property (weak, nonatomic) IBOutlet UILabel *titleLabel; @@ -29,7 +35,7 @@ { [super viewDidLoad]; - self.titleLabel.textColor = kRiotSecondaryTextColor; + self.titleLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.titleLabel.text = NSLocalizedStringFromTable(@"share_extension_auth_prompt", @"Vector", nil); } From e755b390c744dcaf2fc43ed8c0cac5ed97192af3 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 18:08:10 +0100 Subject: [PATCH 041/244] reskin: kill kRiotTopicTextColor --- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 2 -- Riot/Modules/Call/CallViewController.m | 2 +- Riot/Modules/Communities/Home/GroupHomeViewController.m | 4 ++-- .../Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m | 2 +- Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m | 4 ++-- 6 files changed, 6 insertions(+), 9 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index d915937cb..9f0c8db51 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -37,7 +37,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; #pragma mark - Riot Theme Colors (depends on the selected theme light or dark). extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. -extern UIColor *kRiotTopicTextColor; extern UIColor *kRiotSelectedBgColor; // nil is used to keep the default color. extern UIColor *kRiotAuxiliaryColor; extern UIColor *kRiotOverlayColor; // fading behind dialog modals. This color includes the transparency value. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 332a582e6..b90f8334f 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -27,7 +27,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; UIColor *kRiotPlaceholderTextColor; -UIColor *kRiotTopicTextColor; UIColor *kRiotSelectedBgColor; UIColor *kRiotAuxiliaryColor; UIColor *kRiotOverlayColor; @@ -144,7 +143,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; // Apply theme color constants id theme = [RiotDesignValues theme]; - kRiotTopicTextColor = theme.baseTextSecondaryColor; kRiotAuxiliaryColor = theme.headerTextSecondaryColor; [UIScrollView appearance].indicatorStyle = kRiotScrollBarStyle; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index ca54bbacf..4b247a1a4 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -104,7 +104,7 @@ self.activityIndicator.backgroundColor = kRiotOverlayColor; self.callerNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.callStatusLabel.textColor = kRiotTopicTextColor; + self.callStatusLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; self.localPreviewContainerView.layer.borderColor = RiotDesignValues.theme.tintColor.CGColor; self.localPreviewContainerView.layer.borderWidth = 2; diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 84443ce62..d2a66b5e5 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -122,10 +122,10 @@ _groupName.textColor = RiotDesignValues.theme.textPrimaryColor; - _groupDescription.textColor = kRiotTopicTextColor; + _groupDescription.textColor = RiotDesignValues.theme.baseTextSecondaryColor; _groupDescription.numberOfLines = 0; - self.inviteLabel.textColor = kRiotTopicTextColor; + self.inviteLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; self.inviteLabel.numberOfLines = 0; self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index af8b036c5..944329271 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -51,7 +51,7 @@ { [super customizeViewRendering]; - self.roomTopic.textColor = kRiotTopicTextColor; + self.roomTopic.textColor = RiotDesignValues.theme.baseTextSecondaryColor; self.roomMembers.textColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 89326772c..858f38a26 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -67,11 +67,11 @@ self.mainHeaderBackground.backgroundColor = RiotDesignValues.theme.baseColor; - self.roomTopic.textColor = kRiotTopicTextColor; + self.roomTopic.textColor = RiotDesignValues.theme.baseTextSecondaryColor; self.roomMembers.textColor = RiotDesignValues.theme.tintColor; - self.previewLabel.textColor = kRiotTopicTextColor; + self.previewLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; self.previewLabel.numberOfLines = 0; self.subNoticeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; From e58035b155f017aa928a20d310131031fb0f9915 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 18:10:10 +0100 Subject: [PATCH 042/244] reskin: kill headerTextSecondaryColor --- Riot/Constants/RiotDesignValues.h | 1 - Riot/Constants/RiotDesignValues.m | 6 ------ Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m | 2 +- Riot/Modules/Common/Recents/Views/RecentTableViewCell.m | 2 +- .../Room/Views/InputToolbar/DisabledRoomInputToolbarView.m | 2 +- Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m | 2 +- .../DeactivateAccount/DeactivateAccountViewController.m | 2 +- 7 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index 9f0c8db51..e5d7909eb 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -38,7 +38,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; #pragma mark - Riot Theme Colors (depends on the selected theme light or dark). extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. extern UIColor *kRiotSelectedBgColor; // nil is used to keep the default color. -extern UIColor *kRiotAuxiliaryColor; extern UIColor *kRiotOverlayColor; // fading behind dialog modals. This color includes the transparency value. #pragma mark - Riot Colors diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index b90f8334f..33d4a05fd 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -28,7 +28,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValue UIColor *kRiotPlaceholderTextColor; UIColor *kRiotSelectedBgColor; -UIColor *kRiotAuxiliaryColor; UIColor *kRiotOverlayColor; // Riot Colors @@ -140,11 +139,6 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; kRiotScrollBarStyle = UIScrollViewIndicatorStyleDefault; } - // Apply theme color constants - id theme = [RiotDesignValues theme]; - - kRiotAuxiliaryColor = theme.headerTextSecondaryColor; - [UIScrollView appearance].indicatorStyle = kRiotScrollBarStyle; [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 50dd66286..5a4a57628 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -487,7 +487,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou missedNotifAndUnreadBadgeBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, bgViewWidth, 20)]; [missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10]; - missedNotifAndUnreadBadgeBgView.backgroundColor = kRiotAuxiliaryColor; + missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; [missedNotifAndUnreadBadgeBgView addSubview:missedNotifAndUnreadBadgeLabel]; missedNotifAndUnreadBadgeLabel.center = missedNotifAndUnreadBadgeBgView.center; diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 09fc2f07f..a103bf775 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -121,7 +121,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; } else { - self.missedNotifAndUnreadIndicator.backgroundColor = kRiotAuxiliaryColor; + self.missedNotifAndUnreadIndicator.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; } // Use bold font for the room title diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index ff23658b1..817fd370c 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -48,7 +48,7 @@ // Remove default toolbar background color self.backgroundColor = [UIColor clearColor]; - self.separatorView.backgroundColor = kRiotAuxiliaryColor; + self.separatorView.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; self.disabledReasonTextView.textColor = RiotDesignValues.theme.textPrimaryColor; diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index ac7f5900a..f363c89a9 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -87,7 +87,7 @@ // Remove default toolbar background color self.backgroundColor = [UIColor clearColor]; - self.separatorView.backgroundColor = kRiotAuxiliaryColor; + self.separatorView.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; // Custom the growingTextView display growingTextView.layer.cornerRadius = 0; diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 837c78a72..e926afcf4 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -168,7 +168,7 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.layer.masksToBounds = YES; self.deactivateAcccountButton.backgroundColor = RiotDesignValues.theme.tintColor; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; - [self.deactivateAcccountButton setTitleColor:kRiotAuxiliaryColor forState:UIControlStateDisabled]; + [self.deactivateAcccountButton setTitleColor:RiotDesignValues.theme.headerTextSecondaryColor forState:UIControlStateDisabled]; } - (void)setupDeactivateAccountInfosLabel From e98a26ebb81de4083337530c33756ca983a62cd4 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 18:47:49 +0100 Subject: [PATCH 043/244] reskin: kill last customisable kRiotXColors --- Riot/Constants/Colors/DarkTheme.swift | 6 ++++ Riot/Constants/Colors/DefaultTheme.swift | 8 +++++ Riot/Constants/Colors/Theme.swift | 11 ++++++- Riot/Constants/RiotDesignValues.h | 5 --- Riot/Constants/RiotDesignValues.m | 19 ----------- .../AuthenticationViewController.m | 8 ++--- .../Authentication/Views/AuthInputsView.m | 32 +++++++++---------- .../Views/ForgotPasswordInputsView.m | 10 +++--- .../BugReport/BugReportViewController.m | 4 +-- Riot/Modules/Call/CallViewController.m | 2 +- .../Common/Recents/RecentsViewController.m | 6 ++-- .../SegmentedViewController.m | 2 +- .../WebViewController/WebViewViewController.m | 2 +- .../Communities/GroupsViewController.m | 6 ++-- .../Home/GroupHomeViewController.m | 2 +- .../Members/GroupParticipantsViewController.m | 6 ++-- .../Rooms/GroupRoomsViewController.m | 6 ++-- .../Contacts/ContactsTableViewController.m | 6 ++-- .../Details/ContactDetailsViewController.m | 6 ++-- .../Files/HomeFilesSearchViewController.m | 6 ++-- .../HomeMessagesSearchViewController.m | 6 ++-- .../Rooms/DirectoryViewController.m | 6 ++-- .../Library/MediaAlbumContentViewController.m | 2 +- .../MediaPicker/MediaPickerViewController.m | 6 ++-- .../Attachements/AttachmentsViewController.m | 2 +- .../Room/Files/RoomFilesViewController.m | 6 ++-- .../Detail/RoomMemberDetailsViewController.m | 6 ++-- .../Members/RoomParticipantsViewController.m | 6 ++-- .../ReadReceiptsViewController.m | 8 ++--- Riot/Modules/Room/RoomViewController.m | 6 ++-- .../Files/RoomFilesSearchViewController.m | 6 ++-- .../RoomMessagesSearchViewController.m | 6 ++-- .../Settings/RoomSettingsViewController.m | 14 ++++---- .../DirectoryServerPickerViewController.m | 6 ++-- .../DeactivateAccountViewController.m | 2 +- .../Language/LanguagePickerViewController.m | 6 ++-- .../CountryPickerViewController.m | 6 ++-- .../Modules/Settings/SettingsViewController.m | 10 +++--- .../StartChat/StartChatViewController.m | 4 +-- .../UserDevices/UsersDevicesViewController.m | 6 ++-- 40 files changed, 136 insertions(+), 137 deletions(-) diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index 3ae71a512..18c7b3edc 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -55,6 +55,12 @@ final class DarkTheme: NSObject, Theme { let keyboardAppearance: UIKeyboardAppearance = .dark + let placeholderTextColor: UIColor? = UIColor(white: 1.0, alpha: 0.3) + + let selectedBackgroundColor: UIColor? = UIColor.black + + let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) + let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index 7ea6013aa..b94149347 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -55,6 +55,14 @@ final class DefaultTheme: NSObject, Theme { let keyboardAppearance: UIKeyboardAppearance = .light + // Use default 70% gray color. + var placeholderTextColor: UIColor? + + // Use the default selection color + var selectedBackgroundColor: UIColor? + + let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) + let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index e7dede486..de181bd3a 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -56,9 +56,18 @@ import UIKit var keyboardAppearance : UIKeyboardAppearance { get } - // MARK: - Colors that have currently few usage and may disappear in a redesign + // MARK: - Colors not defined in the design palette + /// nil is used to keep the default color + var placeholderTextColor: UIColor? { get } + + /// nil is used to keep the default color + var selectedBackgroundColor: UIColor? { get } + + /// fading behind dialog modals + var overlayBackgroundColor: UIColor { get } + /// Color to tint the search background image var matrixSearchBackgroundImageTintColor: UIColor { get } diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/RiotDesignValues.h index e5d7909eb..fe0918824 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/RiotDesignValues.h @@ -35,11 +35,6 @@ extern NSString *const kRiotDesignValuesDidChangeThemeNotification; blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ alpha:1.0] -#pragma mark - Riot Theme Colors (depends on the selected theme light or dark). -extern UIColor *kRiotPlaceholderTextColor; // nil is used to keep the default color. -extern UIColor *kRiotSelectedBgColor; // nil is used to keep the default color. -extern UIColor *kRiotOverlayColor; // fading behind dialog modals. This color includes the transparency value. - #pragma mark - Riot Colors extern UIColor *kRiotColorPinkRed; extern UIColor *kRiotColorRed; diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index 33d4a05fd..e4a2deaf1 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -26,10 +26,6 @@ NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; -UIColor *kRiotPlaceholderTextColor; -UIColor *kRiotSelectedBgColor; -UIColor *kRiotOverlayColor; - // Riot Colors UIColor *kRiotColorPinkRed; UIColor *kRiotColorRed; @@ -111,31 +107,16 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; if ([themeId isEqualToString:@"dark"]) { // Set dark theme colors - kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; - kRiotSelectedBgColor = [UIColor blackColor]; - - kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; - kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } else if ([themeId isEqualToString:@"black"]) { // Set black theme colors - kRiotPlaceholderTextColor = [UIColor colorWithWhite:1.0 alpha:0.3]; - kRiotSelectedBgColor = [UIColor blackColor]; - - kRiotOverlayColor = [UIColor colorWithWhite:0.3 alpha:0.5]; - kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; } else { // Set light theme colors by default. - kRiotPlaceholderTextColor = nil; // Use default 70% gray color. - kRiotSelectedBgColor = nil; // Use the default selection color. - - kRiotOverlayColor = [UIColor colorWithWhite:0.7 alpha:0.5]; - kRiotScrollBarStyle = UIScrollViewIndicatorStyleDefault; } diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 62ca41c73..d3c83c199 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -138,19 +138,19 @@ self.authenticationScrollView.backgroundColor = RiotDesignValues.theme.backgroundColor; self.authFallbackContentView.backgroundColor = RiotDesignValues.theme.backgroundColor; - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { if (self.homeServerTextField.placeholder) { self.homeServerTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.homeServerTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } if (self.identityServerTextField.placeholder) { self.identityServerTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.identityServerTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } } @@ -176,7 +176,7 @@ self.identityServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; self.identityServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; [self.authInputsView customizeViewRendering]; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 62df4a34a..7ee5e48de 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -72,7 +72,7 @@ self.repeatPasswordTextField.placeholder = NSLocalizedStringFromTable(@"auth_repeat_password_placeholder", @"Vector", nil); self.passWordTextField.placeholder = NSLocalizedStringFromTable(@"auth_password_placeholder", @"Vector", nil); - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { // Apply placeholder color [self customizeViewRendering]; @@ -116,20 +116,20 @@ self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; self.messageLabel.numberOfLines = 0; - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { if (self.userLoginTextField.placeholder) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.userLoginTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } if (self.repeatPasswordTextField.placeholder) { self.repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.repeatPasswordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } @@ -137,21 +137,21 @@ { self.passWordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.passWordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } if (self.phoneTextField.placeholder) { self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } if (self.emailTextField.placeholder) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } } } @@ -196,14 +196,14 @@ self.messageLabel.text = NSLocalizedStringFromTable(@"or", @"Vector", nil); self.phoneTextField.placeholder = NSLocalizedStringFromTable(@"auth_phone_placeholder", @"Vector", nil); - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.userLoginTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } self.userLoginContainer.hidden = NO; @@ -1025,11 +1025,11 @@ { self.passWordTextField.returnKeyType = UIReturnKeyNext; - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_user_name_placeholder", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } else { @@ -1057,11 +1057,11 @@ self.emailTextField.placeholder = NSLocalizedStringFromTable(@"auth_optional_email_placeholder", @"Vector", nil); } - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } self.emailContainer.hidden = NO; @@ -1085,11 +1085,11 @@ self.phoneTextField.placeholder = NSLocalizedStringFromTable(@"auth_optional_phone_placeholder", @"Vector", nil); } - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } self.phoneContainer.hidden = NO; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 67c54cf3e..a4bb9e550 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -60,7 +60,7 @@ self.passWordTextField.placeholder = NSLocalizedStringFromTable(@"auth_new_password_placeholder", @"Vector", nil); self.repeatPasswordTextField.placeholder = NSLocalizedStringFromTable(@"auth_repeat_new_password_placeholder", @"Vector", nil); - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { // Apply placeholder color [self customizeViewRendering]; @@ -117,25 +117,25 @@ self.nextStepButton.clipsToBounds = YES; self.nextStepButton.backgroundColor = RiotDesignValues.theme.tintColor; - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { if (self.emailTextField.placeholder) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } if (self.passWordTextField.placeholder) { self.passWordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.passWordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } if (self.repeatPasswordTextField.placeholder) { self.repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.repeatPasswordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } } } diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 1476d2474..91fc084b6 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -140,9 +140,9 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; - self.overlayView.backgroundColor = kRiotOverlayColor; + self.overlayView.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.overlayView.alpha = 1.0; self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 4b247a1a4..b8f7e1086 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -101,7 +101,7 @@ [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.barTitleColor = RiotDesignValues.theme.textPrimaryColor; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.callerNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; self.callStatusLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 2d6c416d1..2c182798c 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -161,7 +161,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Use the primary bg color for the recents table view in plain style. self.recentsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; @@ -1188,10 +1188,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index f59ddb601..17921f3b6 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -180,7 +180,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; } diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index 1a6669803..25f900f71 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -54,7 +54,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; webView.backgroundColor = RiotDesignValues.theme.backgroundColor; } diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 863a7039f..7fa81a360 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -118,7 +118,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Use the primary bg color for the recents table view in plain style. self.groupsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; @@ -427,10 +427,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index d2a66b5e5..43c62d7af 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -115,7 +115,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; self.mainHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 59b100273..9b8a39c59 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -147,7 +147,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; @@ -880,10 +880,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 71c9c394d..4958580e6 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -128,7 +128,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; @@ -490,10 +490,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 5d7b0b690..a2e4fe1d5 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -106,7 +106,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -291,10 +291,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 450d3ebb4..3cfd959ec 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -233,7 +233,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.headerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; self.contactNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; @@ -782,10 +782,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 37d4f17f2..defcbab58 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -73,7 +73,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -156,10 +156,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index 4ca9ff535..2249b3031 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -80,7 +80,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -199,10 +199,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index c29b62396..dec10d228 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -73,7 +73,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -160,10 +160,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index 094506bbc..416a20115 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -116,7 +116,7 @@ [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.assetsCollectionView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index 7df9fd2cd..b726a5307 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -184,7 +184,7 @@ static void *RecordingContext = &RecordingContext; { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.cameraVideoCaptureProgressView.progressColor = RiotDesignValues.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor clearColor]; @@ -1768,10 +1768,10 @@ static void *RecordingContext = &RecordingContext; cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 3b189ef60..378fe3ec0 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -62,7 +62,7 @@ [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.backButton.tintColor = RiotDesignValues.theme.tintColor; } diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 07bdce754..61927b015 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -112,7 +112,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -196,10 +196,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 5f048513f..987c9bde3 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -221,7 +221,7 @@ [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.memberHeaderView.backgroundColor = RiotDesignValues.theme.baseColor; self.roomMemberNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; @@ -846,10 +846,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index b82abf08a..106b6f010 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -159,7 +159,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; @@ -1178,10 +1178,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 30d362b5f..585f76522 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -96,9 +96,9 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; - self.overlayView.backgroundColor = kRiotOverlayColor; + self.overlayView.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; self.overlayView.alpha = 1.0; self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; @@ -243,10 +243,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index e540570a3..1c70aebc3 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -421,7 +421,7 @@ [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Prepare jump to last unread banner self.jumpToLastUnreadBannerContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; @@ -3341,10 +3341,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index e405965a5..4d1b60fbb 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -74,7 +74,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -149,10 +149,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index 1d8a281f5..42d6123ec 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -75,7 +75,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -176,10 +176,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index cb168feee..b84ea93d1 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -268,7 +268,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -2499,11 +2499,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressTextField = addAddressCell.mxkTextField; addAddressTextField.placeholder = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_details_new_address_placeholder", @"Vector", nil), self.mainSession.matrixRestClient.homeserverSuffix]; - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { addAddressTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:addAddressTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } addAddressTextField.userInteractionEnabled = YES; addAddressTextField.text = currentValue; @@ -2590,11 +2590,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addGroupTextField = addCommunityCell.mxkTextField; addGroupTextField.placeholder = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_details_new_flair_placeholder", @"Vector", nil), self.mainSession.matrixRestClient.homeserverSuffix]; - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { addGroupTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:addGroupTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } addGroupTextField.userInteractionEnabled = YES; addGroupTextField.text = currentValue; @@ -2825,10 +2825,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index bdf219446..e22454615 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -122,7 +122,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -229,10 +229,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index e926afcf4..13d07cbbc 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -125,7 +125,7 @@ static CGFloat const kTextFontSize = 15.0; { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; } - (void)setupStringAttributes diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index 09d671eda..224fa5a60 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -71,7 +71,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; @@ -119,10 +119,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 5cc119e37..73d26ed7a 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -74,7 +74,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; @@ -123,10 +123,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index edf8db390..9bb49e631 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -336,7 +336,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -1527,11 +1527,11 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { newEmailCell.mxkLabel.text = nil; newEmailCell.mxkTextField.placeholder = NSLocalizedStringFromTable(@"settings_email_address_placeholder", @"Vector", nil); - if (kRiotPlaceholderTextColor) + if (RiotDesignValues.theme.placeholderTextColor) { newEmailCell.mxkTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:newEmailCell.mxkTextField.placeholder - attributes:@{NSForegroundColorAttributeName: kRiotPlaceholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; } newEmailCell.mxkTextField.text = newEmailTextField.text; newEmailCell.mxkTextField.userInteractionEnabled = YES; @@ -2367,10 +2367,10 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); if (cell.selectionStyle != UITableViewCellSelectionStyleNone) { // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index d9cfb7edf..08f4b73c3 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -384,10 +384,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 6d18b145a..7cbd10a38 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -84,7 +84,7 @@ { [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = kRiotOverlayColor; + self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; // Check the table view style to select its bg color. self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); @@ -181,10 +181,10 @@ cell.backgroundColor = RiotDesignValues.theme.backgroundColor; // Update the selected background view - if (kRiotSelectedBgColor) + if (RiotDesignValues.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = kRiotSelectedBgColor; + cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; } else { From 192d04fcbd4e52ee8cbaf80bd1851b7c461f24b1 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 10 Jan 2019 18:53:24 +0100 Subject: [PATCH 044/244] reskin: delegate scrollBarStyle to themes --- Riot/Constants/Colors/DarkTheme.swift | 2 ++ Riot/Constants/Colors/DefaultTheme.swift | 2 ++ Riot/Constants/Colors/Theme.swift | 2 ++ Riot/Constants/RiotDesignValues.m | 28 +----------------------- 4 files changed, 7 insertions(+), 27 deletions(-) diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index 18c7b3edc..a6f830263 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -53,6 +53,8 @@ final class DarkTheme: NSObject, Theme { let statusBarStyle: UIStatusBarStyle = .lightContent + let scrollBarStyle: UIScrollViewIndicatorStyle = .white + let keyboardAppearance: UIKeyboardAppearance = .dark let placeholderTextColor: UIColor? = UIColor(white: 1.0, alpha: 0.3) diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index b94149347..0bc04f5e9 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -53,6 +53,8 @@ final class DefaultTheme: NSObject, Theme { let statusBarStyle: UIStatusBarStyle = .lightContent + let scrollBarStyle: UIScrollViewIndicatorStyle = .default + let keyboardAppearance: UIKeyboardAppearance = .light // Use default 70% gray color. diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index de181bd3a..01812bf07 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -53,6 +53,8 @@ import UIKit /// Status bar style to use var statusBarStyle: UIStatusBarStyle { get } + var scrollBarStyle: UIScrollViewIndicatorStyle { get } + var keyboardAppearance : UIKeyboardAppearance { get } diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/RiotDesignValues.m index e4a2deaf1..14ddb737d 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/RiotDesignValues.m @@ -38,8 +38,6 @@ UIColor *kRiotColorOrange; NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; -UIScrollViewIndicatorStyle kRiotScrollBarStyle; - @implementation RiotDesignValues + (RiotDesignValues *)sharedInstance @@ -96,31 +94,7 @@ UIScrollViewIndicatorStyle kRiotScrollBarStyle; - (void)userInterfaceThemeDidChange { - // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). - NSString *themeId = RiotSettings.shared.userInterfaceTheme; - - if (!themeId || [themeId isEqualToString:@"auto"]) - { - themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; - } - - if ([themeId isEqualToString:@"dark"]) - { - // Set dark theme colors - kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; - } - else if ([themeId isEqualToString:@"black"]) - { - // Set black theme colors - kRiotScrollBarStyle = UIScrollViewIndicatorStyleWhite; - } - else - { - // Set light theme colors by default. - kRiotScrollBarStyle = UIScrollViewIndicatorStyleDefault; - } - - [UIScrollView appearance].indicatorStyle = kRiotScrollBarStyle; + [UIScrollView appearance].indicatorStyle = RiotDesignValues.theme.scrollBarStyle; [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; } From f0c22a14af0ff2404f29df5c07b564f290183a99 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 10:32:56 +0100 Subject: [PATCH 045/244] reskin: Rename RiotDesignValues -> ThemeService --- Riot.xcodeproj/project.pbxproj | 16 +-- Riot/AppDelegate.h | 2 +- Riot/AppDelegate.m | 16 +-- .../MXKRoomBubbleTableViewCell+Riot.m | 10 +- Riot/Categories/UIViewController+RiotSearch.m | 6 +- Riot/Constants/Colors/DarkTheme.swift | 5 - Riot/Constants/Colors/DefaultTheme.swift | 11 +- .../{RiotDesignValues.h => ThemeService.h} | 6 +- .../{RiotDesignValues.m => ThemeService.m} | 22 ++-- .../AuthenticationViewController.m | 46 ++++---- .../Authentication/Views/AuthInputsView.m | 52 ++++----- .../Views/ForgotPasswordInputsView.m | 22 ++-- .../Authentication/Views/TermsView.swift | 2 +- .../BugReport/BugReportViewController.m | 48 ++++---- Riot/Modules/Call/CallViewController.m | 36 +++--- Riot/Modules/Call/Views/IncomingCallView.m | 24 ++-- .../Recents/DataSources/RecentsDataSource.m | 20 ++-- .../Common/Recents/RecentsViewController.m | 50 ++++----- .../Recents/Views/RecentTableViewCell.m | 20 ++-- .../SegmentedViewController.h | 2 +- .../SegmentedViewController.m | 24 ++-- .../WebViewController/WebViewViewController.m | 20 ++-- .../Communities/GroupsViewController.m | 44 ++++---- .../Home/GroupHomeViewController.m | 38 +++---- .../Members/GroupParticipantsViewController.m | 42 +++---- .../Rooms/GroupRoomsViewController.m | 32 +++--- .../Rooms/Views/GroupRoomTableViewCell.m | 6 +- .../TabDetail/GroupDetailsViewController.m | 2 +- .../Views/GroupInviteTableViewCell.m | 4 +- .../Communities/Views/GroupTableViewCell.m | 10 +- .../Contacts/ContactsTableViewController.m | 26 ++--- .../Contacts/DataSources/ContactsDataSource.m | 14 +-- .../Details/ContactDetailsViewController.m | 36 +++--- .../Details/Views/RoomTableViewCell.m | 6 +- .../Contacts/Views/ContactTableViewCell.m | 10 +- .../EncryptionInfo/EncryptionInfoView.m | 16 +-- .../UnifiedSearchRecentsDataSource.m | 2 +- .../Files/HomeFilesSearchViewController.m | 28 ++--- .../Files/Views/FilesSearchTableViewCell.m | 10 +- .../HomeMessagesSearchDataSource.m | 4 +- .../HomeMessagesSearchViewController.m | 28 ++--- ...MessagesSearchResultAttachmentBubbleCell.m | 8 +- .../MessagesSearchResultTextMsgBubbleCell.m | 8 +- .../Rooms/DirectoryViewController.m | 26 ++--- .../UnifiedSearchViewController.m | 2 +- .../Views/DirectoryRecentTableViewCell.m | 6 +- .../Views/RoomIdOrAliasTableViewCell.m | 6 +- Riot/Modules/Home/HomeViewController.m | 6 +- .../Home/Views/RoomCollectionViewCell.m | 18 +-- .../Views/TableViewCellWithCollectionView.m | 4 +- .../Library/MediaAlbumContentViewController.m | 20 ++-- .../MediaPicker/MediaPickerViewController.m | 36 +++--- .../MediaPicker/Views/MediaAlbumTableCell.m | 6 +- .../People/Views/InviteRecentTableViewCell.m | 8 +- .../PublicRoomsDirectoryDataSource.m | 2 +- .../Views/PublicRoomTableViewCell.m | 8 +- .../Attachements/AttachmentsViewController.m | 20 ++-- .../Modules/Room/DataSources/RoomDataSource.m | 16 +-- .../Room/Files/RoomFilesViewController.m | 26 ++--- .../Detail/RoomMemberDetailsViewController.m | 38 +++---- .../Members/RoomParticipantsViewController.m | 52 ++++----- .../ReadReceiptsViewController.m | 44 ++++---- Riot/Modules/Room/RoomViewController.m | 42 +++---- .../Search/DataSources/RoomSearchDataSource.m | 4 +- .../Files/RoomFilesSearchViewController.m | 28 ++--- .../RoomMessagesSearchViewController.m | 28 ++--- .../Room/Search/RoomSearchViewController.m | 2 +- .../Settings/RoomSettingsViewController.m | 88 +++++++-------- .../Views/TableViewCellWithCheckBoxAndLabel.m | 4 +- .../TableViewCellWithLabelAndLargeTextView.m | 6 +- .../Views/Activities/RoomActivitiesView.m | 22 ++-- ...dAttachmentWithPaginationTitleBubbleCell.m | 2 +- .../RoomIncomingAttachmentBubbleCell.m | 6 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 10 +- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 4 +- .../RoomIncomingTextMsgBubbleCell.m | 6 +- ...mingTextMsgWithPaginationTitleBubbleCell.m | 10 +- ...ginationTitleWithoutSenderNameBubbleCell.m | 4 +- ...comingTextMsgWithoutSenderInfoBubbleCell.m | 4 +- ...comingTextMsgWithoutSenderNameBubbleCell.m | 4 +- .../BubbleCells/RoomMembershipBubbleCell.m | 4 +- .../RoomMembershipCollapsedBubbleCell.m | 4 +- ...ipCollapsedWithPaginationTitleBubbleCell.m | 6 +- .../RoomMembershipExpandedBubbleCell.m | 6 +- ...hipExpandedWithPaginationTitleBubbleCell.m | 6 +- ...mMembershipWithPaginationTitleBubbleCell.m | 6 +- .../RoomOutgoingAttachmentBubbleCell.m | 6 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 10 +- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 4 +- .../RoomOutgoingTextMsgBubbleCell.m | 6 +- ...oingTextMsgWithPaginationTitleBubbleCell.m | 6 +- ...ginationTitleWithoutSenderNameBubbleCell.m | 2 +- ...tgoingTextMsgWithoutSenderInfoBubbleCell.m | 4 +- ...tgoingTextMsgWithoutSenderNameBubbleCell.m | 2 +- .../BubbleCells/RoomPredecessorBubbleCell.m | 6 +- .../RoomSelectedStickerBubbleCell.m | 6 +- .../Room/Views/Event/EventDetailsView.m | 12 +- .../DisabledRoomInputToolbarView.m | 8 +- .../Views/InputToolbar/RoomInputToolbarView.m | 14 +-- .../Views/Title/Avatar/RoomAvatarTitleView.m | 2 +- .../Title/Expanded/ExpandedRoomTitleView.m | 12 +- .../Title/Preview/PreviewRoomTitleView.m | 22 ++-- Riot/Modules/Room/Views/Title/RoomTitleView.m | 12 +- .../Views/Title/Simple/SimpleRoomTitleView.m | 2 +- .../DirectoryServerPickerViewController.m | 26 ++--- .../DirectoryServerDetailTableViewCell.m | 4 +- .../Views/DirectoryServerTableViewCell.m | 6 +- Riot/Modules/Rooms/RoomsViewController.m | 2 +- .../DeactivateAccountViewController.m | 18 +-- .../Language/LanguagePickerViewController.m | 34 +++--- .../CountryPickerViewController.m | 34 +++--- .../Modules/Settings/SettingsViewController.m | 106 +++++++++--------- Riot/Modules/Settings/Views/DeviceView.m | 14 +-- .../TableViewCellWithPhoneNumberTextField.m | 8 +- .../StartChat/StartChatViewController.m | 26 ++--- Riot/Modules/TabBar/MasterTabBarController.m | 30 ++--- .../UserDevices/UsersDevicesViewController.m | 26 ++--- .../UserDevices/Views/DeviceTableViewCell.m | 8 +- Riot/SupportingFiles/Riot-Bridging-Header.h | 2 +- Riot/Utils/AvatarGenerator.m | 8 +- Riot/Utils/EventFormatter.m | 16 +-- .../Modules/Fallback/FallbackViewController.m | 4 +- .../Share/Listing/RoomsListViewController.m | 4 +- 123 files changed, 992 insertions(+), 1004 deletions(-) rename Riot/Constants/{RiotDesignValues.h => ThemeService.h} (90%) rename Riot/Constants/{RiotDesignValues.m => ThemeService.m} (77%) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 8962111f1..f3fcbf652 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -51,8 +51,8 @@ B169329B20F39E6300746532 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B169329520F39E6300746532 /* Main.storyboard */; }; B16932A320F3A21C00746532 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B169329F20F3A21B00746532 /* main.m */; }; B16932A520F3A21C00746532 /* empty.mm in Sources */ = {isa = PBXBuildFile; fileRef = B16932A220F3A21B00746532 /* empty.mm */; }; - B16932AC20F3A7B100746532 /* RiotDesignValues.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AB20F3A7B000746532 /* RiotDesignValues.m */; }; - B16932AD20F3A7B100746532 /* RiotDesignValues.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AB20F3A7B000746532 /* RiotDesignValues.m */; }; + B16932AC20F3A7B100746532 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AB20F3A7B000746532 /* ThemeService.m */; }; + B16932AD20F3A7B100746532 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AB20F3A7B000746532 /* ThemeService.m */; }; B16932B120F3AC9200746532 /* RoomSearchDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AF20F3AC9200746532 /* RoomSearchDataSource.m */; }; B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932E620F3C37100746532 /* HomeMessagesSearchDataSource.m */; }; B16932EA20F3C39000746532 /* UnifiedSearchRecentsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932E920F3C39000746532 /* UnifiedSearchRecentsDataSource.m */; }; @@ -484,8 +484,8 @@ B16932A020F3A21B00746532 /* Riot.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Riot.entitlements; sourceTree = ""; }; B16932A120F3A21B00746532 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B16932A220F3A21B00746532 /* empty.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = empty.mm; sourceTree = ""; }; - B16932AA20F3A7B000746532 /* RiotDesignValues.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RiotDesignValues.h; sourceTree = ""; }; - B16932AB20F3A7B000746532 /* RiotDesignValues.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RiotDesignValues.m; sourceTree = ""; }; + B16932AA20F3A7B000746532 /* ThemeService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThemeService.h; sourceTree = ""; }; + B16932AB20F3A7B000746532 /* ThemeService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThemeService.m; sourceTree = ""; }; B16932AF20F3AC9200746532 /* RoomSearchDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomSearchDataSource.m; sourceTree = ""; }; B16932B020F3AC9200746532 /* RoomSearchDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomSearchDataSource.h; sourceTree = ""; }; B16932E520F3C37100746532 /* HomeMessagesSearchDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeMessagesSearchDataSource.h; sourceTree = ""; }; @@ -1166,8 +1166,8 @@ isa = PBXGroup; children = ( 3223D9BD21B00615000321C1 /* Colors */, - B16932AA20F3A7B000746532 /* RiotDesignValues.h */, - B16932AB20F3A7B000746532 /* RiotDesignValues.m */, + B16932AA20F3A7B000746532 /* ThemeService.h */, + B16932AB20F3A7B000746532 /* ThemeService.m */, ); path = Constants; sourceTree = ""; @@ -2983,7 +2983,7 @@ 3223D9C621B00788000321C1 /* DefaultTheme.swift in Sources */, B169328420F38BE300746532 /* SegmentedViewController.m in Sources */, 3223D9C521B00781000321C1 /* DarkTheme.swift in Sources */, - B16932AD20F3A7B100746532 /* RiotDesignValues.m in Sources */, + B16932AD20F3A7B100746532 /* ThemeService.m in Sources */, B1664BCA20F4E67600808783 /* ShareViewController.m in Sources */, B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */, 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */, @@ -3013,7 +3013,7 @@ buildActionMask = 2147483647; files = ( B1B557D120EF5E3500210D55 /* MediaAlbumTableCell.m in Sources */, - B16932AC20F3A7B100746532 /* RiotDesignValues.m in Sources */, + B16932AC20F3A7B100746532 /* ThemeService.m in Sources */, B1B557A120EF58AD00210D55 /* ContactTableViewCell.m in Sources */, F083BE021E7009ED00A9B29C /* AvatarGenerator.m in Sources */, B1B5573A20EE6C4D00210D55 /* GroupRoomsViewController.m in Sources */, diff --git a/Riot/AppDelegate.h b/Riot/AppDelegate.h index 8ab291656..2f04960be 100644 --- a/Riot/AppDelegate.h +++ b/Riot/AppDelegate.h @@ -24,7 +24,7 @@ #import "RageShakeManager.h" #import "Analytics.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #pragma mark - Notifications /** diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index c256a8b5a..587b8f141 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -422,7 +422,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [NSBundle mxk_setFallbackLanguage:@"en"]; // Define the navigation bar text color - [[UINavigationBar appearance] setTintColor:RiotDesignValues.theme.tintColor]; + [[UINavigationBar appearance] setTintColor:ThemeService.theme.tintColor]; // Customize the localized string table [NSBundle mxk_customizeLocalizedStringTableName:@"Vector"]; @@ -444,8 +444,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UINavigationController *secondNavController = self.secondaryNavigationController; if (secondNavController) { - secondNavController.navigationBar.barTintColor = RiotDesignValues.theme.backgroundColor; - secondNavController.topViewController.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + secondNavController.navigationBar.barTintColor = ThemeService.theme.backgroundColor; + secondNavController.topViewController.view.backgroundColor = ThemeService.theme.backgroundColor; } // on IOS 8 iPad devices, force to display the primary and the secondary viewcontroller @@ -835,7 +835,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; UIViewController *emptyDetailsViewController = [storyboard instantiateViewControllerWithIdentifier:@"EmptyDetailsViewControllerStoryboardId"]; - emptyDetailsViewController.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + emptyDetailsViewController.view.backgroundColor = ThemeService.theme.backgroundColor; splitViewController.viewControllers = @[mainViewController, emptyDetailsViewController]; } @@ -2825,7 +2825,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN if (!launchAnimationContainerView && window) { launchAnimationContainerView = [[UIView alloc] initWithFrame:window.bounds]; - launchAnimationContainerView.backgroundColor = RiotDesignValues.theme.backgroundColor; + launchAnimationContainerView.backgroundColor = ThemeService.theme.backgroundColor; launchAnimationContainerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [window addSubview:launchAnimationContainerView]; @@ -3531,7 +3531,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [_callStatusBarButton setTitle:buttonTitle forState:UIControlStateNormal]; [_callStatusBarButton setTitle:buttonTitle forState:UIControlStateHighlighted]; - _callStatusBarButton.titleLabel.textColor = RiotDesignValues.theme.backgroundColor; + _callStatusBarButton.titleLabel.textColor = ThemeService.theme.backgroundColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { @@ -3542,7 +3542,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN _callStatusBarButton.titleLabel.font = [UIFont boldSystemFontOfSize:17]; } - [_callStatusBarButton setBackgroundColor:RiotDesignValues.theme.tintColor]; + [_callStatusBarButton setBackgroundColor:ThemeService.theme.tintColor]; [_callStatusBarButton addTarget:self action:@selector(onCallStatusBarButtonPressed) forControlEvents:UIControlEventTouchUpInside]; // Place button into the new window @@ -3691,7 +3691,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; UIViewController *emptyDetailsViewController = [storyboard instantiateViewControllerWithIdentifier:@"EmptyDetailsViewControllerStoryboardId"]; - emptyDetailsViewController.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + emptyDetailsViewController.view.backgroundColor = ThemeService.theme.backgroundColor; return emptyDetailsViewController; } diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index f3374a5e3..69a71028e 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -19,7 +19,7 @@ #import "RoomBubbleCellData.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import @@ -62,7 +62,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT timeLabel.text = [bubbleData.eventFormatter timeStringFromDate:component.date]; timeLabel.textAlignment = NSTextAlignmentRight; - timeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + timeLabel.textColor = ThemeService.theme.textSecondaryColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { timeLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightLight]; @@ -209,7 +209,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT markPosY, VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH, markHeight)]; - markerView.backgroundColor = RiotDesignValues.theme.tintColor; + markerView.backgroundColor = ThemeService.theme.tintColor; [markerView setTranslatesAutoresizingMaskIntoConstraints:NO]; markerView.accessibilityIdentifier = @"markerView"; @@ -264,7 +264,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT timeLabel.text = [bubbleData.eventFormatter dateStringFromDate:date withTime:NO]; timeLabel.textAlignment = NSTextAlignmentRight; - timeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + timeLabel.textColor = ThemeService.theme.textSecondaryColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { timeLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightLight]; @@ -321,7 +321,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT if (blurred) { self.bubbleOverlayContainer.hidden = NO; - self.bubbleOverlayContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.bubbleOverlayContainer.backgroundColor = ThemeService.theme.backgroundColor; self.bubbleOverlayContainer.alpha = 0.8; self.bubbleOverlayContainer.userInteractionEnabled = YES; diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index 3845c3072..3e4647e66 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -19,7 +19,7 @@ #import -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" /** @@ -95,7 +95,7 @@ self.searchBar.text = @""; // Customize search bar - [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; + [ThemeService.theme applyStyleOnSearchBar:self.searchBar]; // Remove navigation buttons self.navigationItem.hidesBackButton = YES; @@ -134,7 +134,7 @@ - (void)addBackgroundImageViewToView:(UIView*)view { - UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:RiotDesignValues.theme.matrixSearchBackgroundImageTintColor]; + UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:ThemeService.theme.matrixSearchBackgroundImageTintColor]; UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:searchBgImage]; backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO; diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index a6f830263..0551f10c5 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -52,17 +52,12 @@ final class DarkTheme: NSObject, Theme { UIColor(rgb: 0x76DDD7)] let statusBarStyle: UIStatusBarStyle = .lightContent - let scrollBarStyle: UIScrollViewIndicatorStyle = .white - let keyboardAppearance: UIKeyboardAppearance = .dark let placeholderTextColor: UIColor? = UIColor(white: 1.0, alpha: 0.3) - let selectedBackgroundColor: UIColor? = UIColor.black - let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) - let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index 0bc04f5e9..96794e9f5 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -52,19 +52,12 @@ final class DefaultTheme: NSObject, Theme { UIColor(rgb: 0x76DDD7)] let statusBarStyle: UIStatusBarStyle = .lightContent - let scrollBarStyle: UIScrollViewIndicatorStyle = .default - let keyboardAppearance: UIKeyboardAppearance = .light - // Use default 70% gray color. - var placeholderTextColor: UIColor? - - // Use the default selection color - var selectedBackgroundColor: UIColor? - + var placeholderTextColor: UIColor? // Use default 70% gray color + var selectedBackgroundColor: UIColor? // Use the default selection color let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) - let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { diff --git a/Riot/Constants/RiotDesignValues.h b/Riot/Constants/ThemeService.h similarity index 90% rename from Riot/Constants/RiotDesignValues.h rename to Riot/Constants/ThemeService.h index fe0918824..1cc4443ba 100644 --- a/Riot/Constants/RiotDesignValues.h +++ b/Riot/Constants/ThemeService.h @@ -24,7 +24,7 @@ NS_ASSUME_NONNULL_BEGIN /** Posted when the user interface theme has been changed. */ -extern NSString *const kRiotDesignValuesDidChangeThemeNotification; +extern NSString *const kThemeServiceDidChangeThemeNotification; /** Convert a RGB hexadecimal value into a UIColor. @@ -48,9 +48,9 @@ extern NSInteger const kRiotRoomModeratorLevel; extern NSInteger const kRiotRoomAdminLevel; /** - `RiotDesignValues` class manages the Riot design parameters + `ThemeService` class manages the Riot design parameters */ -@interface RiotDesignValues : NSObject +@interface ThemeService : NSObject /** The current theme. diff --git a/Riot/Constants/RiotDesignValues.m b/Riot/Constants/ThemeService.m similarity index 77% rename from Riot/Constants/RiotDesignValues.m rename to Riot/Constants/ThemeService.m index 14ddb737d..b752be420 100644 --- a/Riot/Constants/RiotDesignValues.m +++ b/Riot/Constants/ThemeService.m @@ -15,7 +15,7 @@ limitations under the License. */ -#import "RiotDesignValues.h" +#import "ThemeService.h" #ifdef IS_SHARE_EXTENSION #import "RiotShareExtension-Swift.h" @@ -24,7 +24,7 @@ #endif -NSString *const kRiotDesignValuesDidChangeThemeNotification = @"kRiotDesignValuesDidChangeThemeNotification"; +NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChangeThemeNotification"; // Riot Colors UIColor *kRiotColorPinkRed; @@ -38,15 +38,15 @@ UIColor *kRiotColorOrange; NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; -@implementation RiotDesignValues +@implementation ThemeService -+ (RiotDesignValues *)sharedInstance ++ (ThemeService *)sharedInstance { - static RiotDesignValues *sharedOnceInstance; + static ThemeService *sharedOnceInstance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedOnceInstance = [[RiotDesignValues alloc] init]; + sharedOnceInstance = [[ThemeService alloc] init]; }); return sharedOnceInstance; @@ -67,11 +67,11 @@ NSInteger const kRiotRoomAdminLevel = 100; kRiotColorOrange = UIColorFromRGB(0xF8A15F); // Observe user interface theme change. - [[NSUserDefaults standardUserDefaults] addObserver:[RiotDesignValues sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil]; - [[RiotDesignValues sharedInstance] userInterfaceThemeDidChange]; + [[NSUserDefaults standardUserDefaults] addObserver:[ThemeService sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil]; + [[ThemeService sharedInstance] userInterfaceThemeDidChange]; // Observe "Invert Colours" settings changes (available since iOS 11) - [[NSNotificationCenter defaultCenter] addObserver:[RiotDesignValues sharedInstance] selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:[ThemeService sharedInstance] selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context @@ -94,9 +94,9 @@ NSInteger const kRiotRoomAdminLevel = 100; - (void)userInterfaceThemeDidChange { - [UIScrollView appearance].indicatorStyle = RiotDesignValues.theme.scrollBarStyle; + [UIScrollView appearance].indicatorStyle = ThemeService.theme.scrollBarStyle; - [[NSNotificationCenter defaultCenter] postNotificationName:kRiotDesignValuesDidChangeThemeNotification object:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:kThemeServiceDidChangeThemeNotification object:nil]; } + (id)theme diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index d3c83c199..f2bdae672 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -37,9 +37,9 @@ NSString *defaultCountryCode; /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -121,7 +121,7 @@ self.authInputsView = authInputsView; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -131,52 +131,52 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.view.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.authenticationScrollView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.authFallbackContentView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.authenticationScrollView.backgroundColor = ThemeService.theme.backgroundColor; + self.authFallbackContentView.backgroundColor = ThemeService.theme.backgroundColor; - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { if (self.homeServerTextField.placeholder) { self.homeServerTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.homeServerTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } if (self.identityServerTextField.placeholder) { self.identityServerTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.identityServerTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } } - self.submitButton.backgroundColor = RiotDesignValues.theme.tintColor; - self.skipButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.submitButton.backgroundColor = ThemeService.theme.tintColor; + self.skipButton.backgroundColor = ThemeService.theme.tintColor; self.noFlowLabel.textColor = kRiotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; - [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; + [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; [self updateForgotPwdButtonVisibility]; - NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textSecondaryColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}]; + NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textSecondaryColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateNormal]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateHighlighted]; - self.homeServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.homeServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.homeServerTextField.textColor = ThemeService.theme.textPrimaryColor; + self.homeServerLabel.textColor = ThemeService.theme.textSecondaryColor; - self.identityServerTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.identityServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.identityServerTextField.textColor = ThemeService.theme.textPrimaryColor; + self.identityServerLabel.textColor = ThemeService.theme.textSecondaryColor; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; [self.authInputsView customizeViewRendering]; @@ -185,7 +185,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -218,10 +218,10 @@ { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 7ee5e48de..3a67b064c 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -17,7 +17,7 @@ #import "AuthInputsView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Tools.h" #import "CountryPickerViewController.h" @@ -72,7 +72,7 @@ self.repeatPasswordTextField.placeholder = NSLocalizedStringFromTable(@"auth_repeat_password_placeholder", @"Vector", nil); self.passWordTextField.placeholder = NSLocalizedStringFromTable(@"auth_password_placeholder", @"Vector", nil); - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { // Apply placeholder color [self customizeViewRendering]; @@ -103,33 +103,33 @@ { [super customizeViewRendering]; - self.repeatPasswordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.userLoginTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.passWordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.repeatPasswordTextField.textColor = ThemeService.theme.textPrimaryColor; + self.userLoginTextField.textColor = ThemeService.theme.textPrimaryColor; + self.passWordTextField.textColor = ThemeService.theme.textPrimaryColor; - self.emailTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.phoneTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.emailTextField.textColor = ThemeService.theme.textPrimaryColor; + self.phoneTextField.textColor = ThemeService.theme.textPrimaryColor; - self.isoCountryCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.callingCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.isoCountryCodeLabel.textColor = ThemeService.theme.textPrimaryColor; + self.callingCodeLabel.textColor = ThemeService.theme.textPrimaryColor; - self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.messageLabel.textColor = ThemeService.theme.textSecondaryColor; self.messageLabel.numberOfLines = 0; - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { if (self.userLoginTextField.placeholder) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.userLoginTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } if (self.repeatPasswordTextField.placeholder) { self.repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.repeatPasswordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } @@ -137,21 +137,21 @@ { self.passWordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.passWordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } if (self.phoneTextField.placeholder) { self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } if (self.emailTextField.placeholder) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } } } @@ -196,14 +196,14 @@ self.messageLabel.text = NSLocalizedStringFromTable(@"or", @"Vector", nil); self.phoneTextField.placeholder = NSLocalizedStringFromTable(@"auth_phone_placeholder", @"Vector", nil); - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.userLoginTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } self.userLoginContainer.hidden = NO; @@ -1025,11 +1025,11 @@ { self.passWordTextField.returnKeyType = UIReturnKeyNext; - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_user_name_placeholder", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } else { @@ -1057,11 +1057,11 @@ self.emailTextField.placeholder = NSLocalizedStringFromTable(@"auth_optional_email_placeholder", @"Vector", nil); } - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } self.emailContainer.hidden = NO; @@ -1085,11 +1085,11 @@ self.phoneTextField.placeholder = NSLocalizedStringFromTable(@"auth_optional_phone_placeholder", @"Vector", nil); } - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } self.phoneContainer.hidden = NO; @@ -1149,7 +1149,7 @@ phoneNumberPickerNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - [RiotDesignValues.theme applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; [phoneNumberPickerNavigationController pushViewController:phoneNumberCountryPicker animated:NO]; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index a4bb9e550..4902677a9 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -18,7 +18,7 @@ #import "ForgotPasswordInputsView.h" #import "MXHTTPOperation.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @interface ForgotPasswordInputsView () @@ -60,7 +60,7 @@ self.passWordTextField.placeholder = NSLocalizedStringFromTable(@"auth_new_password_placeholder", @"Vector", nil); self.repeatPasswordTextField.placeholder = NSLocalizedStringFromTable(@"auth_repeat_new_password_placeholder", @"Vector", nil); - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { // Apply placeholder color [self customizeViewRendering]; @@ -105,37 +105,37 @@ { [super customizeViewRendering]; - self.messageLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.messageLabel.textColor = ThemeService.theme.textPrimaryColor; - self.emailTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.passWordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; - self.repeatPasswordTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.emailTextField.textColor = ThemeService.theme.textPrimaryColor; + self.passWordTextField.textColor = ThemeService.theme.textPrimaryColor; + self.repeatPasswordTextField.textColor = ThemeService.theme.textPrimaryColor; self.messageLabel.numberOfLines = 0; [self.nextStepButton.layer setCornerRadius:5]; self.nextStepButton.clipsToBounds = YES; - self.nextStepButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.nextStepButton.backgroundColor = ThemeService.theme.tintColor; - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { if (self.emailTextField.placeholder) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } if (self.passWordTextField.placeholder) { self.passWordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.passWordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } if (self.repeatPasswordTextField.placeholder) { self.repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.repeatPasswordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } } } diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index 228e3c22e..154ac3b27 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -80,7 +80,7 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie } func customizeViewRendering() { - acceptButton.backgroundColor = RiotDesignValues.theme().tintColor + acceptButton.backgroundColor = ThemeService.theme().tintColor } diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 91fc084b6..e6d9fe6ae 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -28,8 +28,8 @@ // The temporary file used to store the screenshot NSURL *screenShotFile; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @property (nonatomic) BOOL sendLogs; @@ -128,7 +128,7 @@ _bugReportDescriptionTextView.inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -138,44 +138,44 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.overlayView.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.overlayView.backgroundColor = ThemeService.theme.overlayBackgroundColor; self.overlayView.alpha = 1.0; - self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.sendingContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.containerView.backgroundColor = ThemeService.theme.backgroundColor; + self.sendingContainer.backgroundColor = ThemeService.theme.backgroundColor; - self.bugReportDescriptionTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; + self.bugReportDescriptionTextView.keyboardAppearance = ThemeService.theme.keyboardAppearance; - self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.sendingLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.descriptionLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.bugReportDescriptionTextView.textColor = RiotDesignValues.theme.textPrimaryColor; - self.bugReportDescriptionTextView.tintColor = RiotDesignValues.theme.tintColor; - self.logsDescriptionLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.sendLogsLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.sendScreenshotLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; + self.sendingLabel.textColor = ThemeService.theme.textPrimaryColor; + self.descriptionLabel.textColor = ThemeService.theme.textPrimaryColor; + self.bugReportDescriptionTextView.textColor = ThemeService.theme.textPrimaryColor; + self.bugReportDescriptionTextView.tintColor = ThemeService.theme.tintColor; + self.logsDescriptionLabel.textColor = ThemeService.theme.textPrimaryColor; + self.sendLogsLabel.textColor = ThemeService.theme.textPrimaryColor; + self.sendScreenshotLabel.textColor = ThemeService.theme.textPrimaryColor; - self.sendButton.tintColor = RiotDesignValues.theme.tintColor; - self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; + self.sendButton.tintColor = ThemeService.theme.tintColor; + self.cancelButton.tintColor = ThemeService.theme.tintColor; - _bugReportDescriptionTextView.layer.borderColor = RiotDesignValues.theme.headerBackgroundColor.CGColor; + _bugReportDescriptionTextView.layer.borderColor = ThemeService.theme.headerBackgroundColor.CGColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [super destroy]; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index b8f7e1086..151160e01 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -37,8 +37,8 @@ // Current alert (if any). UIAlertController *currentAlert; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -88,7 +88,7 @@ [self updateLocalPreviewLayout]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -98,20 +98,20 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.barTitleColor = RiotDesignValues.theme.textPrimaryColor; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.barTitleColor = ThemeService.theme.textPrimaryColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.callerNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.callStatusLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; + self.callerNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.callStatusLabel.textColor = ThemeService.theme.baseTextSecondaryColor; - self.localPreviewContainerView.layer.borderColor = RiotDesignValues.theme.tintColor.CGColor; + self.localPreviewContainerView.layer.borderColor = ThemeService.theme.tintColor.CGColor; self.localPreviewContainerView.layer.borderWidth = 2; self.localPreviewContainerView.layer.cornerRadius = 5; self.localPreviewContainerView.clipsToBounds = YES; - self.remotePreviewContainerView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.remotePreviewContainerView.backgroundColor = ThemeService.theme.backgroundColor; if (gradientMaskLayer) { @@ -121,9 +121,9 @@ // Add a gradient mask programatically at the top of the screen (background of the call information (name, status)) gradientMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the RiotDesignValues.theme.backgroundColor. + // Consider the grayscale components of the ThemeService.theme.backgroundColor. CGFloat white = 1.0; - [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -189,10 +189,10 @@ { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [gradientMaskLayer removeFromSuperlayer]; @@ -283,8 +283,8 @@ UINavigationController *usersDevicesNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - [RiotDesignValues.theme applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; - usersDevicesNavigationController.navigationBar.barTintColor = RiotDesignValues.theme.backgroundColor; + [ThemeService.theme applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; + usersDevicesNavigationController.navigationBar.barTintColor = ThemeService.theme.backgroundColor; [usersDevicesNavigationController pushViewController:usersDevicesViewController animated:NO]; @@ -350,7 +350,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.theme.tintColor]; + withColor:ThemeService.theme.tintColor]; } - (void)setMxCall:(MXCall *)call diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 56361c33d..cfb038122 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -21,7 +21,7 @@ #import #import "CircleButton.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" static const CGFloat kAvatarSize = 100.0; @@ -57,11 +57,11 @@ static const CGFloat kButtonSize = 80.0; self = [super initWithFrame:CGRectZero]; if (self) { - self.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.backgroundColor = ThemeService.theme.backgroundColor; self.opaque = YES; self.callerImageView = [[MXKImageView alloc] init]; - self.callerImageView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.callerImageView.backgroundColor = ThemeService.theme.backgroundColor; self.callerImageView.clipsToBounds = YES; self.callerImageView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder; self.callerImageView.enableInMemoryCache = YES; @@ -74,28 +74,28 @@ static const CGFloat kButtonSize = 80.0; mediaManager:mediaManager]; self.callerNameLabel = [[UILabel alloc] init]; - self.callerNameLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.callerNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.callerNameLabel.backgroundColor = ThemeService.theme.backgroundColor; + self.callerNameLabel.textColor = ThemeService.theme.textPrimaryColor; self.callerNameLabel.font = [UIFont systemFontOfSize:24.0 weight:UIFontWeightMedium]; self.callerNameLabel.text = callerName; self.callerNameLabel.textAlignment = NSTextAlignmentCenter; self.callInfoLabel = [[UILabel alloc] init]; - self.callInfoLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.callInfoLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.callInfoLabel.backgroundColor = ThemeService.theme.backgroundColor; + self.callInfoLabel.textColor = ThemeService.theme.textSecondaryColor; self.callInfoLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.callInfoLabel.text = callInfo; self.callInfoLabel.textAlignment = NSTextAlignmentCenter; - UIColor *answerButtonBorderColor = RiotDesignValues.theme.tintColor; + UIColor *answerButtonBorderColor = ThemeService.theme.tintColor; self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"] borderColor:answerButtonBorderColor]; - self.answerButton.defaultBackgroundColor = RiotDesignValues.theme.backgroundColor; + self.answerButton.defaultBackgroundColor = ThemeService.theme.backgroundColor; [self.answerButton addTarget:self action:@selector(didTapAnswerButton) forControlEvents:UIControlEventTouchUpInside]; self.answerTitleLabel = [[UILabel alloc] init]; - self.answerTitleLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.answerTitleLabel.backgroundColor = ThemeService.theme.backgroundColor; self.answerTitleLabel.textColor = answerButtonBorderColor; self.answerTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.answerTitleLabel.text = NSLocalizedStringFromTable(@"accept", @"Vector", nil); @@ -104,11 +104,11 @@ static const CGFloat kButtonSize = 80.0; self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"call_hangup_icon"] borderColor:rejectButtonBorderColor]; - self.rejectButton.defaultBackgroundColor = RiotDesignValues.theme.backgroundColor; + self.rejectButton.defaultBackgroundColor = ThemeService.theme.backgroundColor; [self.rejectButton addTarget:self action:@selector(didTapRejectButton) forControlEvents:UIControlEventTouchUpInside]; self.rejectTitleLabel = [[UILabel alloc] init]; - self.rejectTitleLabel.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.rejectTitleLabel.backgroundColor = ThemeService.theme.backgroundColor; self.rejectTitleLabel.textColor = rejectButtonBorderColor; self.rejectTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.rejectTitleLabel.text = NSLocalizedStringFromTable(@"decline", @"Vector", nil); diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 5a4a57628..ee608cae2 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -19,7 +19,7 @@ #import "RecentCellData.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "MXRoom+Riot.h" @@ -415,10 +415,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextSecondaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -426,7 +426,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } @@ -469,7 +469,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (count) { UILabel *missedNotifAndUnreadBadgeLabel = [[UILabel alloc] init]; - missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; + missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; missedNotifAndUnreadBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; if (count > 1000) { @@ -487,7 +487,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou missedNotifAndUnreadBadgeBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, bgViewWidth, 20)]; [missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10]; - missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; + missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.theme.headerTextSecondaryColor; [missedNotifAndUnreadBadgeBgView addSubview:missedNotifAndUnreadBadgeLabel]; missedNotifAndUnreadBadgeLabel.center = missedNotifAndUnreadBadgeBgView.center; @@ -516,7 +516,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame { UIView *sectionHeader = [[UIView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + sectionHeader.backgroundColor = ThemeService.theme.headerBackgroundColor; NSInteger sectionBitwise = 0; UIImageView *chevronView; UIView *accessoryView; @@ -754,8 +754,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } // Apply the current UI theme. - networkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - directoryServerLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + networkLabel.textColor = ThemeService.theme.textPrimaryColor; + directoryServerLabel.textColor = ThemeService.theme.textSecondaryColor; // Set the current directory server name directoryServerLabel.text = _publicRoomsDirectoryDataSource.directoryServerDisplayname; @@ -846,7 +846,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + tableViewCell.textLabel.textColor = ThemeService.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 2c182798c..23e085a44 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -63,8 +63,8 @@ // when the user selects it. UISearchBar *tableSearchBar; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -149,7 +149,7 @@ self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -159,17 +159,17 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Use the primary bg color for the recents table view in plain style. - self.recentsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - topview.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.recentsTableView.backgroundColor = ThemeService.theme.backgroundColor; + topview.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; - [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; - [RiotDesignValues.theme applyStyleOnSearchBar:self.recentsSearchBar]; + [ThemeService.theme applyStyleOnSearchBar:tableSearchBar]; + [ThemeService.theme applyStyleOnSearchBar:self.recentsSearchBar]; if (self.recentsTableView.dataSource) { @@ -180,7 +180,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy @@ -207,10 +207,10 @@ UIApplicationDidEnterBackgroundNotificationObserver = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -868,7 +868,7 @@ }]; UIImage *actionIcon = isDirect ? [UIImage imageNamed:@"directChatOff"] : [UIImage imageNamed:@"directChatOn"]; - directAction.backgroundColor = [MXKTools convertImageToPatternColor:isDirect ? @"directChatOff" : @"directChatOn" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + directAction.backgroundColor = [MXKTools convertImageToPatternColor:isDirect ? @"directChatOff" : @"directChatOn" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:directAction atIndex:0]; @@ -882,7 +882,7 @@ }]; actionIcon = isMuted ? [UIImage imageNamed:@"notifications"] : [UIImage imageNamed:@"notificationsOff"]; - muteAction.backgroundColor = [MXKTools convertImageToPatternColor:isMuted ? @"notifications" : @"notificationsOff" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + muteAction.backgroundColor = [MXKTools convertImageToPatternColor:isMuted ? @"notifications" : @"notificationsOff" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:muteAction atIndex:0]; // Favorites management @@ -907,7 +907,7 @@ }]; actionIcon = [UIImage imageNamed:@"favouriteOff"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"favouriteOff" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"favouriteOff" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } else @@ -919,7 +919,7 @@ }]; actionIcon = [UIImage imageNamed:@"favourite"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"favourite" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"favourite" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } @@ -932,7 +932,7 @@ }]; actionIcon = [UIImage imageNamed:@"priorityHigh"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityHigh" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityHigh" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } else @@ -944,7 +944,7 @@ }]; actionIcon = [UIImage imageNamed:@"priorityLow"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityLow" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityLow" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } @@ -955,7 +955,7 @@ }]; actionIcon = [UIImage imageNamed:@"leave"]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"leave" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"leave" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:leaveAction atIndex:0]; } @@ -1185,13 +1185,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -1413,7 +1413,7 @@ if (indexPath && [recentsDataSource isDraggableCellAt:indexPath]) { UITableViewCell *cell = [self.recentsTableView cellForRowAtIndexPath:indexPath]; - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // snapshot the cell UIGraphicsBeginImageContextWithOptions(cell.bounds.size, NO, 0); diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index a103bf775..4703015d4 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -21,7 +21,7 @@ #import "MXEvent.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -48,13 +48,13 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeTableViewCellRendering]; - self.roomTitle.textColor = RiotDesignValues.theme.textPrimaryColor; - self.lastEventDescription.textColor = RiotDesignValues.theme.textSecondaryColor; - self.lastEventDate.textColor = RiotDesignValues.theme.textSecondaryColor; - self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.roomTitle.textColor = ThemeService.theme.textPrimaryColor; + self.lastEventDescription.textColor = ThemeService.theme.textSecondaryColor; + self.lastEventDate.textColor = ThemeService.theme.textSecondaryColor; + self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -94,7 +94,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { // Force the default text color for the last message (cancel highlighted message color) NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:roomCellData.lastEventAttributedTextMessage]; - [lastEventDescription addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.textSecondaryColor range:NSMakeRange(0, lastEventDescription.length)]; + [lastEventDescription addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.textSecondaryColor range:NSMakeRange(0, lastEventDescription.length)]; self.lastEventDescription.attributedText = lastEventDescription; } else @@ -109,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; @@ -121,7 +121,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; } else { - self.missedNotifAndUnreadIndicator.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; + self.missedNotifAndUnreadIndicator.backgroundColor = ThemeService.theme.headerTextSecondaryColor; } // Use bold font for the room title @@ -136,7 +136,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; } else { - self.lastEventDate.textColor = RiotDesignValues.theme.textSecondaryColor; + self.lastEventDate.textColor = ThemeService.theme.textSecondaryColor; // The room title is not bold anymore if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h index 76192d5af..53f5966d1 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h @@ -38,7 +38,7 @@ limitations under the License. @property (nonatomic) NSUInteger selectedIndex; /** - The tint color for the section header (RiotDesignValues.theme.accent by default). + The tint color for the section header (ThemeService.theme.accent by default). */ @property (nonatomic) UIColor *sectionHeaderTintColor; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 17921f3b6..ae281daff 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -17,7 +17,7 @@ #import "SegmentedViewController.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #ifdef IS_SHARE_EXTENSION #import "RiotShareExtension-Swift.h" @@ -49,8 +49,8 @@ UIView* selectedMarkerView; NSLayoutConstraint *leftMarkerViewConstraint; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -104,10 +104,10 @@ selectedMarkerView = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [super destroy]; @@ -136,7 +136,7 @@ // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; - self.sectionHeaderTintColor = RiotDesignValues.theme.tintColor; + self.sectionHeaderTintColor = ThemeService.theme.tintColor; } - (void)viewDidLoad @@ -168,7 +168,7 @@ [self createSegmentedViews]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -178,16 +178,16 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index 25f900f71..e60a7b371 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -20,8 +20,8 @@ @interface WebViewViewController () { - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -42,7 +42,7 @@ [super viewDidLoad]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -52,24 +52,24 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - webView.backgroundColor = RiotDesignValues.theme.backgroundColor; + webView.backgroundColor = ThemeService.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [super destroy]; diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 7fa81a360..159fab7a8 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -39,8 +39,8 @@ // when the user selects it. UISearchBar *tableSearchBar; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -106,7 +106,7 @@ //[self addPlusButton]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -116,17 +116,17 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Use the primary bg color for the recents table view in plain style. - self.groupsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - topview.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.groupsTableView.backgroundColor = ThemeService.theme.backgroundColor; + topview.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; - [RiotDesignValues.theme applyStyleOnSearchBar:tableSearchBar]; - [RiotDesignValues.theme applyStyleOnSearchBar:self.groupsSearchBar]; + [ThemeService.theme applyStyleOnSearchBar:tableSearchBar]; + [ThemeService.theme applyStyleOnSearchBar:self.groupsSearchBar]; if (self.groupsTableView.dataSource) { @@ -137,7 +137,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy @@ -162,10 +162,10 @@ UIApplicationDidEnterBackgroundNotificationObserver = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -424,13 +424,13 @@ { [super tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath]; - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -452,8 +452,8 @@ if (tableView.numberOfSections > 1) { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; - sectionHeader.mxkContentView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - sectionHeader.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + sectionHeader.mxkContentView.backgroundColor = ThemeService.theme.headerBackgroundColor; + sectionHeader.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; NSString* title = [self.dataSource tableView:tableView titleForHeaderInSection:section]; @@ -462,9 +462,9 @@ { NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.headerTextPrimaryColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.headerTextPrimaryColor}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.headerTextSecondaryColor}]]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.headerTextSecondaryColor}]]; sectionHeader.mxkLabel.attributedText = mutableSectionTitle; } @@ -512,7 +512,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 43c62d7af..ea7d2a04d 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -20,7 +20,7 @@ #import "AppDelegate.h" #import "Riot-Swift.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Tools.h" #import "MXGroup+Riot.h" @@ -36,8 +36,8 @@ */ BOOL isStatusBarHidden; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; // The options used to load long description html content. NSDictionary *options; @@ -103,7 +103,7 @@ _groupAvatarMask.userInteractionEnabled = YES; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -113,22 +113,22 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.mainHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.mainHeaderContainer.backgroundColor = ThemeService.theme.headerBackgroundColor; - _groupName.textColor = RiotDesignValues.theme.textPrimaryColor; + _groupName.textColor = ThemeService.theme.textPrimaryColor; - _groupDescription.textColor = RiotDesignValues.theme.baseTextSecondaryColor; + _groupDescription.textColor = ThemeService.theme.baseTextSecondaryColor; _groupDescription.numberOfLines = 0; - self.inviteLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; + self.inviteLabel.textColor = ThemeService.theme.baseTextSecondaryColor; self.inviteLabel.numberOfLines = 0; - self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.separatorView.backgroundColor = ThemeService.theme.headerBackgroundColor; [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; @@ -140,11 +140,11 @@ if (_groupLongDescription) { - _groupLongDescription.textColor = RiotDesignValues.theme.textSecondaryColor; + _groupLongDescription.textColor = ThemeService.theme.textSecondaryColor; _groupLongDescription.tintColor = kRiotColorBlue; // Update HTML loading options - NSUInteger bgColor = [MXKTools rgbValueWithColor:RiotDesignValues.theme.headerBackgroundColor]; + NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.theme.headerBackgroundColor]; NSString *defaultCSS = [NSString stringWithFormat:@" \ pre,code { \ background-color: #%06lX; \ @@ -170,7 +170,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -259,10 +259,10 @@ [currentRequest cancel]; currentRequest = nil; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -481,7 +481,7 @@ _groupAvatar.layer.cornerRadius = _groupAvatar.frame.size.width / 2; _groupAvatar.clipsToBounds = YES; - _groupAvatar.defaultBackgroundColor = RiotDesignValues.theme.headerBackgroundColor; + _groupAvatar.defaultBackgroundColor = ThemeService.theme.headerBackgroundColor; } - (void)refreshGroupLongDescription diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 9b8a39c59..157e2ff2c 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -46,8 +46,8 @@ UIAlertController *currentAlert; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -135,7 +135,7 @@ //[self addAddParticipantButton]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -145,21 +145,21 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen CGFloat white = 1.0; - [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; @@ -172,7 +172,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. @@ -186,10 +186,10 @@ // Release the potential pushed view controller [self releasePushedViewController]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (currentAlert) @@ -444,9 +444,9 @@ // Add blur mask programmatically tableViewMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the RiotDesignValues.theme.backgroundColor. + // Consider the grayscale components of the ThemeService.theme.backgroundColor. CGFloat white = 1.0; - [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -877,13 +877,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -914,8 +914,8 @@ if (section == invitedSection) { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; - sectionHeader.mxkContentView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - sectionHeader.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + sectionHeader.mxkContentView.backgroundColor = ThemeService.theme.headerBackgroundColor; + sectionHeader.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; sectionHeader.mxkLabel.text = NSLocalizedStringFromTable(@"group_participants_invited_section", @"Vector", nil); @@ -985,7 +985,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } @@ -1205,7 +1205,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 4958580e6..93efa76ce 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -32,8 +32,8 @@ // The current pushed view controller UIViewController *pushedViewController; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -116,7 +116,7 @@ [self.tableView registerClass:GroupRoomTableViewCell.class forCellReuseIdentifier:@"RoomTableViewCellId"]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -126,16 +126,16 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -146,7 +146,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. @@ -160,10 +160,10 @@ // Release the potential pushed view controller [self releasePushedViewController]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } _group = nil; @@ -487,13 +487,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -588,7 +588,7 @@ // // }]; // -// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; +// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; // [actions insertObject:leaveAction atIndex:0]; // // return actions; @@ -606,7 +606,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m index a30f68051..334f16395 100644 --- a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m +++ b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m @@ -19,7 +19,7 @@ #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation GroupRoomTableViewCell @@ -37,8 +37,8 @@ { [super customizeTableViewCellRendering]; - self.roomDisplayName.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomTopic.textColor = RiotDesignValues.theme.textSecondaryColor; + self.roomDisplayName.textColor = ThemeService.theme.textPrimaryColor; + self.roomTopic.textColor = ThemeService.theme.textSecondaryColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m index c56b83804..c6c6902cf 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m @@ -122,7 +122,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 15726aa98..5c9985455 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -16,7 +16,7 @@ #import "GroupInviteTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #pragma mark - Constant definitions @@ -58,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = kRiotColorBlue; self.rightButton.backgroundColor = kRiotColorBlue; - self.noticeBadgeView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; + self.noticeBadgeView.backgroundColor = ThemeService.theme.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.m b/Riot/Modules/Communities/Views/GroupTableViewCell.m index 6f22506ca..ef8e7b0e7 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.m @@ -16,7 +16,7 @@ #import "GroupTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXGroup+Riot.h" @@ -41,13 +41,13 @@ { [super customizeTableViewCellRendering]; - self.groupName.textColor = RiotDesignValues.theme.textPrimaryColor; - self.groupDescription.textColor = RiotDesignValues.theme.textSecondaryColor; - self.memberCount.textColor = RiotDesignValues.theme.textSecondaryColor; + self.groupName.textColor = ThemeService.theme.textPrimaryColor; + self.groupDescription.textColor = ThemeService.theme.textSecondaryColor; + self.memberCount.textColor = ThemeService.theme.textSecondaryColor; if (self.missedNotifAndUnreadBadgeLabel) { - self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; } self.groupAvatar.defaultBackgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index a2e4fe1d5..2943ae0d2 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -36,9 +36,9 @@ id kAppDelegateDidTapStatusBarNotificationObserver; /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -94,7 +94,7 @@ self.contactsTableView.tableFooterView = [[UIView alloc] init]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -104,12 +104,12 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -120,7 +120,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)didReceiveMemoryWarning @@ -133,10 +133,10 @@ { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -288,13 +288,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index b20056971..43c1bc86f 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -17,7 +17,7 @@ #import "ContactsDataSource.h" #import "ContactTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #define CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE 0x01 @@ -595,7 +595,7 @@ if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + tableViewCell.textLabel.textColor = ThemeService.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -742,10 +742,10 @@ NSString *roomCount = [NSString stringWithFormat:roomCountFormat, count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextSecondaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -753,7 +753,7 @@ else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } @@ -767,7 +767,7 @@ NSInteger sectionBitwise = 0; sectionHeader = [[UIView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + sectionHeader.backgroundColor = ThemeService.theme.headerBackgroundColor; frame.origin.x = 20; frame.origin.y = 5; @@ -970,7 +970,7 @@ } // Apply UI theme - checkboxLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + checkboxLabel.textColor = ThemeService.theme.textPrimaryColor; // Set the right value of the tick box localContactsCheckbox.image = hideNonMatrixEnabledContacts ? [UIImage imageNamed:@"selection_tick"] : [UIImage imageNamed:@"selection_untick"]; diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 3cfd959ec..5a7aaab2f 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -77,9 +77,9 @@ UIAlertController *currentAlert; /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; /** The current visibility of the status bar in this view controller. @@ -221,7 +221,7 @@ }]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -231,16 +231,16 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.headerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.contactNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.contactStatusLabel.textColor = RiotDesignValues.theme.tintColor; + self.headerView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.contactNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.contactStatusLabel.textColor = ThemeService.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -251,7 +251,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -322,10 +322,10 @@ { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (roomCreationRequest) @@ -735,8 +735,8 @@ [cellWithButton.mxkButton setTitle:title forState:UIControlStateNormal]; [cellWithButton.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateHighlighted]; [cellWithButton.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; @@ -779,13 +779,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index 29c3aed7a..c9d6b5260 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -17,7 +17,7 @@ #import "RoomTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -35,10 +35,10 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index eefdc53ad..ae7306b37 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -19,7 +19,7 @@ #import -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "AvatarGenerator.h" @@ -53,8 +53,8 @@ [super customizeTableViewCellRendering]; // apply the vector colours - self.contactDisplayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.contactInformationLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.contactDisplayNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.contactInformationLabel.textColor = ThemeService.theme.textSecondaryColor; // Clear the default background color of a MXKImageView instance self.thumbnailView.defaultBackgroundColor = [UIColor clearColor]; @@ -223,11 +223,11 @@ } else if ((!contact.isMatrixContact && contact.phoneNumbers.count && !contact.emailAddresses.count)) { - image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:RiotDesignValues.theme.tintColor]; + image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:ThemeService.theme.tintColor]; } else { - image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:RiotDesignValues.theme.tintColor]; + image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:ThemeService.theme.tintColor]; } } diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index b3087cea3..78851ffd7 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -17,7 +17,7 @@ #import "EncryptionInfoView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation EncryptionInfoView @@ -28,13 +28,13 @@ { [super customizeViewRendering]; - self.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; - self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; - self.verifyButton.tintColor = RiotDesignValues.theme.tintColor; - self.blockButton.tintColor = RiotDesignValues.theme.tintColor; - self.confirmVerifyButton.tintColor = RiotDesignValues.theme.tintColor; + self.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.textView.backgroundColor = ThemeService.theme.backgroundColor; + self.defaultTextColor = ThemeService.theme.textPrimaryColor; + self.cancelButton.tintColor = ThemeService.theme.tintColor; + self.verifyButton.tintColor = ThemeService.theme.tintColor; + self.blockButton.tintColor = ThemeService.theme.tintColor; + self.confirmVerifyButton.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m index 4c87b10a5..df95e8ff8 100644 --- a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m +++ b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m @@ -16,7 +16,7 @@ #import "UnifiedSearchRecentsDataSource.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "RoomIdOrAliasTableViewCell.h" #import "DirectoryRecentTableViewCell.h" diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index defcbab58..6c35be7c2 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -30,9 +30,9 @@ @interface HomeFilesSearchViewController() { /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -61,7 +61,7 @@ self.searchTableView.tableFooterView = [[UIView alloc] init]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -71,15 +71,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -89,17 +89,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -153,13 +153,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index 0a380c467..9152118a8 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -18,7 +18,7 @@ #import "FilesSearchTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation FilesSearchTableViewCell @@ -28,11 +28,11 @@ { [super customizeTableViewCellRendering]; - self.title.textColor = RiotDesignValues.theme.textPrimaryColor; + self.title.textColor = ThemeService.theme.textPrimaryColor; - self.message.textColor = RiotDesignValues.theme.textSecondaryColor; + self.message.textColor = ThemeService.theme.textSecondaryColor; - self.date.tintColor = RiotDesignValues.theme.textSecondaryColor; + self.date.tintColor = ThemeService.theme.textSecondaryColor; } + (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth @@ -76,7 +76,7 @@ if (bubbleData.isAttachmentWithThumbnail) { - self.attachmentImageView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.attachmentImageView.backgroundColor = ThemeService.theme.backgroundColor; [self.attachmentImageView setAttachmentThumb:bubbleData.attachment]; } diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 0d159cb36..cd26647d1 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -22,7 +22,7 @@ #import "RoomBubbleCellData.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @@ -66,7 +66,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.theme.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.theme.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index 2249b3031..6d51eeadc 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -34,9 +34,9 @@ @interface HomeMessagesSearchViewController () { /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -68,7 +68,7 @@ self.searchTableView.tableFooterView = [[UIView alloc] init]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -78,15 +78,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -96,17 +96,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -196,13 +196,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index da3362a0a..fc2ced745 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -17,7 +17,7 @@ #import "MessagesSearchResultAttachmentBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation MessagesSearchResultAttachmentBubbleCell @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.roomNameLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.roomNameLabel.textColor = ThemeService.theme.textSecondaryColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index 1b5a067ea..41c3f7c76 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -17,7 +17,7 @@ #import "MessagesSearchResultTextMsgBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation MessagesSearchResultTextMsgBubbleCell @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.roomNameLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.roomNameLabel.textColor = ThemeService.theme.textSecondaryColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index dec10d228..20e1886d0 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -32,8 +32,8 @@ // The animated view displayed at the table view bottom when paginating UIView* footerSpinnerView; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -61,7 +61,7 @@ self.tableView.tableFooterView = [[UIView alloc] init]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -71,12 +71,12 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -87,17 +87,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -157,13 +157,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index 7725cbbac..fb91a4a33 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -115,7 +115,7 @@ UIImageView *backgroundImageView = self.backgroundImageView; if (backgroundImageView) { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:RiotDesignValues.theme.matrixSearchBackgroundImageTintColor]; + UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.theme.matrixSearchBackgroundImageTintColor]; backgroundImageView.image = image; } } diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m index 816fd7407..fa243ac3a 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m @@ -19,7 +19,7 @@ #import "PublicRoomsDirectoryDataSource.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation DirectoryRecentTableViewCell @@ -30,8 +30,8 @@ { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.descriptionLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; + self.descriptionLabel.textColor = ThemeService.theme.textSecondaryColor; } - (void)render:(PublicRoomsDirectoryDataSource *)publicRoomsDirectoryDataSource diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index c0ca9ce00..09a2f0a58 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -18,7 +18,7 @@ #import "RoomIdOrAliasTableViewCell.h" #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIdOrAliasTableViewCell @@ -29,7 +29,7 @@ { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; } - (void)layoutSubviews @@ -50,7 +50,7 @@ else { self.avatarImageView.image = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.theme.tintColor]; + withColor:ThemeService.theme.tintColor]; } self.titleLabel.text = roomIdOrAlias; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 6c842f03d..ae9b731ee 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -82,9 +82,9 @@ [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_home", @"Vector", nil); - [RiotDesignValues.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.theme.tintColor; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.theme.tintColor; if (recentsDataSource) { @@ -416,7 +416,7 @@ } } - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; return cell; } diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 53f8b9f1c..5bd5cc385 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -18,7 +18,7 @@ #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -66,13 +66,13 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeCollectionViewCellRendering]; - self.roomTitle.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomTitle1.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomTitle2.textColor = RiotDesignValues.theme.textPrimaryColor; - self.missedNotifAndUnreadBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.roomTitle.textColor = ThemeService.theme.textPrimaryColor; + self.roomTitle1.textColor = ThemeService.theme.textPrimaryColor; + self.roomTitle2.textColor = ThemeService.theme.textPrimaryColor; + self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(RiotDesignValues.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -81,7 +81,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; CFRelease(directRoomBorderColor); - self.editionArrowView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.editionArrowView.backgroundColor = ThemeService.theme.headerBackgroundColor; self.roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } @@ -126,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -147,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.theme.notificationMentionColor; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m index ef131331a..3a9f41332 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m @@ -15,7 +15,7 @@ */ #import "TableViewCellWithCollectionView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation TableViewCellWithCollectionView @@ -32,7 +32,7 @@ { [super customizeTableViewCellRendering]; - self.editionView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.editionView.backgroundColor = ThemeService.theme.headerBackgroundColor; } - (void)prepareForReuse diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index 416a20115..1d1eb9827 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -41,9 +41,9 @@ NSMutableArray *selectedAssets; /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -103,7 +103,7 @@ } // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -113,15 +113,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.assetsCollectionView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.assetsCollectionView.backgroundColor = ThemeService.theme.backgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -141,10 +141,10 @@ { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index b726a5307..db1814a29 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -84,9 +84,9 @@ static void *RecordingContext = &RecordingContext; NSDate *videoRecordStartDate; /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; /** The current visibility of the status bar in this view controller. @@ -172,7 +172,7 @@ static void *RecordingContext = &RecordingContext; }]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -182,20 +182,20 @@ static void *RecordingContext = &RecordingContext; - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.cameraVideoCaptureProgressView.progressColor = RiotDesignValues.theme.backgroundColor; + self.cameraVideoCaptureProgressView.progressColor = ThemeService.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor clearColor]; - self.userAlbumsTableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.userAlbumsTableView.backgroundColor = ThemeService.theme.backgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -343,12 +343,12 @@ static void *RecordingContext = &RecordingContext; if (self.cameraVideoCaptureProgressView.progressColor != [UIColor lightGrayColor]) { self.cameraVideoCaptureProgressView.progressColor = [UIColor lightGrayColor]; - self.cameraVideoCaptureProgressView.unprogressColor = RiotDesignValues.theme.backgroundColor; + self.cameraVideoCaptureProgressView.unprogressColor = ThemeService.theme.backgroundColor; } } - else if (self.cameraVideoCaptureProgressView.progressColor != RiotDesignValues.theme.backgroundColor) + else if (self.cameraVideoCaptureProgressView.progressColor != ThemeService.theme.backgroundColor) { - self.cameraVideoCaptureProgressView.progressColor = RiotDesignValues.theme.backgroundColor; + self.cameraVideoCaptureProgressView.progressColor = ThemeService.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor lightGrayColor]; } @@ -1005,10 +1005,10 @@ static void *RecordingContext = &RecordingContext; { [self stopAVCapture]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (UIApplicationWillEnterForegroundNotificationObserver) @@ -1765,13 +1765,13 @@ static void *RecordingContext = &RecordingContext; - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m index e6cc0ec11..227ad4c98 100644 --- a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m +++ b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m @@ -17,7 +17,7 @@ #import "MediaAlbumTableCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation MediaAlbumTableCell @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.albumDisplayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.albumCountLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.albumDisplayNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.albumCountLabel.textColor = ThemeService.theme.textSecondaryColor; } @end diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index c688d6894..41e265d46 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -21,7 +21,7 @@ #import "MXEvent.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #pragma mark - Constant definitions @@ -60,10 +60,10 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell { [super customizeTableViewCellRendering]; - self.leftButton.backgroundColor = RiotDesignValues.theme.tintColor; - self.rightButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.leftButton.backgroundColor = ThemeService.theme.tintColor; + self.rightButton.backgroundColor = ThemeService.theme.tintColor; - self.noticeBadgeView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; + self.noticeBadgeView.backgroundColor = ThemeService.theme.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m index f105775a2..dbc1cb419 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m @@ -339,7 +339,7 @@ double const kPublicRoomsDirectoryDataExpiration = 10; if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + tableViewCell.textLabel.textColor = ThemeService.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m index 87686ba7c..71654cc32 100644 --- a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m +++ b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m @@ -20,7 +20,7 @@ #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation PublicRoomTableViewCell @@ -38,9 +38,9 @@ { [super customizeTableViewCellRendering]; - self.roomDisplayName.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomTopic.textColor = RiotDesignValues.theme.textSecondaryColor; - self.memberCount.textColor = RiotDesignValues.theme.textSecondaryColor; + self.roomDisplayName.textColor = ThemeService.theme.textPrimaryColor; + self.roomTopic.textColor = ThemeService.theme.textSecondaryColor; + self.memberCount.textColor = ThemeService.theme.textSecondaryColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index 378fe3ec0..d15d775d4 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -22,8 +22,8 @@ @interface AttachmentsViewController () { - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -49,7 +49,7 @@ self.attachmentsCollection.accessibilityIdentifier =@"AttachmentsVC"; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -59,12 +59,12 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.backButton.tintColor = RiotDesignValues.theme.tintColor; + self.backButton.tintColor = ThemeService.theme.tintColor; } - (void)viewWillAppear:(BOOL)animated @@ -79,10 +79,10 @@ { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index fdb0fd9be..21af3d0ed 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -22,15 +22,15 @@ #import "MXKRoomBubbleTableViewCell+Riot.h" #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoom+Riot.h" @interface RoomDataSource() { - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -59,7 +59,7 @@ self.markTimelineInitialEvent = NO; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { // Force room data reload. [self updateEventFormatter]; @@ -106,10 +106,10 @@ - (void)destroy { - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [super destroy]; @@ -386,7 +386,7 @@ if ([component.event.eventId isEqualToString:self.room.accountData.readMarkerEventId]) { bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - 2, bubbleCell.bubbleOverlayContainer.frame.size.width, 2)]; - bubbleCell.readMarkerView.backgroundColor = RiotDesignValues.theme.tintColor; + bubbleCell.readMarkerView.backgroundColor = ThemeService.theme.tintColor; // Hide by default the marker, it will be shown and animated when the cell will be rendered. bubbleCell.readMarkerView.hidden = YES; bubbleCell.readMarkerView.tag = index; diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 61927b015..1dc6d7e68 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -27,9 +27,9 @@ @interface RoomFilesViewController () { /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -100,7 +100,7 @@ [UIView setAnimationsEnabled:YES]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -110,12 +110,12 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) @@ -126,17 +126,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -193,13 +193,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 987c9bde3..a0b50f358 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -70,9 +70,9 @@ id UIApplicationWillChangeStatusBarOrientationNotificationObserver; /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; /** The current visibility of the status bar in this view controller. @@ -208,7 +208,7 @@ }]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -218,17 +218,17 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.memberHeaderView.backgroundColor = RiotDesignValues.theme.baseColor; - self.roomMemberNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.roomMemberStatusLabel.textColor = RiotDesignValues.theme.tintColor; + self.memberHeaderView.backgroundColor = ThemeService.theme.baseColor; + self.roomMemberNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.roomMemberStatusLabel.textColor = ThemeService.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -239,7 +239,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -303,10 +303,10 @@ UIApplicationWillChangeStatusBarOrientationNotificationObserver = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [memberTitleView removeFromSuperview]; @@ -360,7 +360,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.theme.tintColor]; + withColor:ThemeService.theme.tintColor]; } - (void)updateMemberInfo @@ -781,8 +781,8 @@ } else { - [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:RiotDesignValues.theme.textPrimaryColor forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateHighlighted]; } [cellWithButton.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; @@ -843,13 +843,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 106b6f010..ef14422b9 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -61,8 +61,8 @@ UIAlertController *currentAlert; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -147,7 +147,7 @@ [self addAddParticipantButton]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -157,21 +157,21 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen CGFloat white = 1.0; - [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; @@ -184,7 +184,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. @@ -197,10 +197,10 @@ - (void)destroy { - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (leaveRoomNotificationObserver) @@ -575,9 +575,9 @@ // Add blur mask programmatically tableViewMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the RiotDesignValues.theme.backgroundColor. + // Consider the grayscale components of the ThemeService.theme.backgroundColor. CGFloat white = 1.0; - [RiotDesignValues.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -1175,13 +1175,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -1215,7 +1215,7 @@ if (section == invitedSection) { sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 30)]; - sectionHeader.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + sectionHeader.backgroundColor = ThemeService.theme.headerBackgroundColor; CGRect frame = sectionHeader.frame; frame.origin.x = 20; @@ -1223,7 +1223,7 @@ frame.size.width = sectionHeader.frame.size.width - 10; frame.size.height -= 10; UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame]; - headerLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + headerLabel.textColor = ThemeService.theme.textPrimaryColor; headerLabel.font = [UIFont boldSystemFontOfSize:15.0]; headerLabel.backgroundColor = [UIColor clearColor]; @@ -1327,7 +1327,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } @@ -1684,19 +1684,19 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.theme.tintColor; - searchBar.tintColor = RiotDesignValues.theme.tintColor; + searchBar.barTintColor = searchBar.tintColor = ThemeService.theme.tintColor; + searchBar.tintColor = ThemeService.theme.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = RiotDesignValues.theme.tintColor; + leftImageView.tintColor = ThemeService.theme.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -1707,8 +1707,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: RiotDesignValues.theme.tintColor, - NSForegroundColorAttributeName: RiotDesignValues.theme.tintColor}]; + NSUnderlineColorAttributeName: ThemeService.theme.tintColor, + NSForegroundColorAttributeName: ThemeService.theme.tintColor}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 585f76522..b861b80a2 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -19,13 +19,13 @@ #import #import "RageShakeManager.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @interface ReadReceiptsViewController () { - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @property (nonatomic) MXSession *session; @@ -78,7 +78,7 @@ [self addOverlayViewGesture]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -94,20 +94,20 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - self.overlayView.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.overlayView.backgroundColor = ThemeService.theme.overlayBackgroundColor; self.overlayView.alpha = 1.0; - self.titleLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.containerView.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; + self.containerView.backgroundColor = ThemeService.theme.backgroundColor; // Check the table view style to select its bg color. - self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); - self.closeButton.tintColor = RiotDesignValues.theme.tintColor; + self.closeButton.tintColor = ThemeService.theme.tintColor; if (self.receiptsTableView.dataSource) { @@ -118,15 +118,15 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } [super destroy]; @@ -196,8 +196,8 @@ { MXKReadReceiptTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[MXKReadReceiptTableViewCell defaultReuseIdentifier] forIndexPath:indexPath]; - cell.displayNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - cell.receiptDescriptionLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + cell.displayNameLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.receiptDescriptionLabel.textColor = ThemeService.theme.textSecondaryColor; if (indexPath.row < self.roomMembers.count) { @@ -224,9 +224,9 @@ NSString *receiptReadText = NSLocalizedStringFromTable(@"receipt_status_read", @"Vector", nil); NSString *receiptTimeText = [(MXKEventFormatter*)self.session.roomSummaryUpdateDelegate dateStringFromTimestamp:self.receipts[indexPath.row].ts withTime:YES]; - NSMutableAttributedString *receiptDescription = [[NSMutableAttributedString alloc] initWithString:receiptReadText attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textSecondaryColor, NSFontAttributeName : [UIFont boldSystemFontOfSize:15]}]; + NSMutableAttributedString *receiptDescription = [[NSMutableAttributedString alloc] initWithString:receiptReadText attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textSecondaryColor, NSFontAttributeName : [UIFont boldSystemFontOfSize:15]}]; - [receiptDescription appendAttributedString:[[NSAttributedString alloc] initWithString:receiptTimeText attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textSecondaryColor, NSFontAttributeName : [UIFont systemFontOfSize:15]}]]; + [receiptDescription appendAttributedString:[[NSAttributedString alloc] initWithString:receiptTimeText attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textSecondaryColor, NSFontAttributeName : [UIFont systemFontOfSize:15]}]]; cell.receiptDescriptionLabel.attributedText = receiptDescription; } @@ -240,13 +240,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 1c70aebc3..c15949e1a 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -203,8 +203,8 @@ // The right bar button items back up. NSArray *rightBarButtonItems; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; // Tell whether the input text field is in send reply mode. If true typed message will be sent to highlighted event. BOOL isInReplyMode; @@ -408,7 +408,7 @@ } // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -418,25 +418,25 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Prepare jump to last unread banner - self.jumpToLastUnreadBannerContainer.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: RiotDesignValues.theme.textPrimaryColor, NSForegroundColorAttributeName: RiotDesignValues.theme.textPrimaryColor}]; + self.jumpToLastUnreadBannerContainer.backgroundColor = ThemeService.theme.backgroundColor; + self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: ThemeService.theme.textPrimaryColor, NSForegroundColorAttributeName: ThemeService.theme.textPrimaryColor}]; - self.expandedHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.previewHeaderContainer.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.expandedHeaderContainer.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.previewHeaderContainer.backgroundColor = ThemeService.theme.headerBackgroundColor; - missedDiscussionsBadgeLabel.textColor = RiotDesignValues.theme.backgroundColor; + missedDiscussionsBadgeLabel.textColor = ThemeService.theme.backgroundColor; missedDiscussionsBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; missedDiscussionsBadgeLabel.backgroundColor = [UIColor clearColor]; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) @@ -447,7 +447,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)didReceiveMemoryWarning @@ -1142,10 +1142,10 @@ [self removeTypingNotificationsListener]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (kAppDelegateDidTapStatusBarNotificationObserver) { @@ -1752,7 +1752,7 @@ else { previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.theme.tintColor]; + withColor:ThemeService.theme.tintColor]; } } @@ -3338,13 +3338,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -4230,11 +4230,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.theme.notificationMentionColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.theme.notificationMentionColor; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = RiotDesignValues.theme.notificationUnreadColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.theme.notificationUnreadColor; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 046d9b70f..4aca0ba4d 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -19,7 +19,7 @@ #import "RoomBubbleCellData.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @@ -69,7 +69,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:RiotDesignValues.theme.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.theme.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index 4d1b60fbb..03e5b73fe 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -32,8 +32,8 @@ // Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar. id kAppDelegateDidTapStatusBarNotificationObserver; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -62,7 +62,7 @@ self.searchTableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -72,15 +72,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -90,17 +90,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -146,13 +146,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index 42d6123ec..a6698ab9c 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -34,8 +34,8 @@ // Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar. id kAppDelegateDidTapStatusBarNotificationObserver; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -63,7 +63,7 @@ [self.searchTableView registerClass:RoomIncomingAttachmentBubbleCell.class forCellReuseIdentifier:RoomIncomingAttachmentBubbleCell.defaultReuseIdentifier]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -73,15 +73,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = RiotDesignValues.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -91,17 +91,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -173,13 +173,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index 21b70c2ec..414848622 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -80,7 +80,7 @@ UIImageView *backgroundImageView = self.backgroundImageView; if (backgroundImageView) { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:RiotDesignValues.theme.matrixSearchBackgroundImageTintColor]; + UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.theme.matrixSearchBackgroundImageTintColor]; backgroundImageView.image = image; } } diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index b84ea93d1..54810537c 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -168,8 +168,8 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // A copy of the banned members NSArray *bannedMembers; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -256,7 +256,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [self setNavBarButtons]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -266,12 +266,12 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -282,7 +282,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -380,10 +380,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti actualDirectoryVisibilityRequest = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (appDelegateDidTapStatusBarNotificationObserver) @@ -2053,7 +2053,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { // Customize label style UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view; - tableViewHeaderFooterView.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + tableViewHeaderFooterView.textLabel.textColor = ThemeService.theme.textPrimaryColor; tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15]; } } @@ -2178,7 +2178,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomPhotoCell.mxkImageView.defaultBackgroundColor = [UIColor clearColor]; roomPhotoCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_photo", @"Vector", nil); - roomPhotoCell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + roomPhotoCell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; if (updatedItemsDict[kRoomSettingsAvatarKey]) { @@ -2213,16 +2213,16 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView.text = mxRoomState.topic; } - topicTextView.tintColor = RiotDesignValues.theme.tintColor; + topicTextView.tintColor = ThemeService.theme.tintColor; topicTextView.font = [UIFont systemFontOfSize:15]; topicTextView.bounces = NO; topicTextView.delegate = self; // disable the edition if the user cannot update it topicTextView.editable = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomTopic]); - topicTextView.textColor = RiotDesignValues.theme.textSecondaryColor; + topicTextView.textColor = ThemeService.theme.textSecondaryColor; - topicTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; + topicTextView.keyboardAppearance = ThemeService.theme.keyboardAppearance; cell = roomTopicCell; } @@ -2235,14 +2235,14 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomNameCell.mxkTextFieldTrailingConstraint.constant = 15; roomNameCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_room_name", @"Vector", nil); - roomNameCell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + roomNameCell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; roomNameCell.accessoryType = UITableViewCellAccessoryNone; roomNameCell.accessoryView = nil; nameTextField = roomNameCell.mxkTextField; - nameTextField.tintColor = RiotDesignValues.theme.tintColor; + nameTextField.tintColor = ThemeService.theme.tintColor; nameTextField.font = [UIFont systemFontOfSize:17]; nameTextField.borderStyle = UITextBorderStyleNone; nameTextField.textAlignment = NSTextAlignmentRight; @@ -2259,7 +2259,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // disable the edition if the user cannot update it nameTextField.userInteractionEnabled = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomName]); - nameTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + nameTextField.textColor = ThemeService.theme.textSecondaryColor; // Add a "textFieldDidChange" notification method to the text field control. [nameTextField addTarget:self action:@selector(onTextFieldUpdate:) forControlEvents:UIControlEventEditingChanged]; @@ -2280,10 +2280,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti NSArray *labels = roomTagCell.labels; UILabel *label; label = labels[0]; - label.textColor = RiotDesignValues.theme.textPrimaryColor; + label.textColor = ThemeService.theme.textPrimaryColor; label.text = NSLocalizedStringFromTable(@"room_details_favourite_tag", @"Vector", nil); label = labels[1]; - label.textColor = RiotDesignValues.theme.textPrimaryColor; + label.textColor = ThemeService.theme.textPrimaryColor; label.text = NSLocalizedStringFromTable(@"room_details_low_priority_tag", @"Vector", nil); if (updatedItemsDict[kRoomSettingsTagKey]) @@ -2320,7 +2320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [leaveCell.mxkButton setTitle:title forState:UIControlStateNormal]; [leaveCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [leaveCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; + [leaveCell.mxkButton setTintColor:ThemeService.theme.tintColor]; leaveCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [leaveCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2499,17 +2499,17 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressTextField = addAddressCell.mxkTextField; addAddressTextField.placeholder = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_details_new_address_placeholder", @"Vector", nil), self.mainSession.matrixRestClient.homeserverSuffix]; - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { addAddressTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:addAddressTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } addAddressTextField.userInteractionEnabled = YES; addAddressTextField.text = currentValue; - addAddressTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + addAddressTextField.textColor = ThemeService.theme.textSecondaryColor; - addAddressTextField.tintColor = RiotDesignValues.theme.tintColor; + addAddressTextField.tintColor = ThemeService.theme.tintColor; addAddressTextField.font = [UIFont systemFontOfSize:17]; addAddressTextField.borderStyle = UITextBorderStyleNone; addAddressTextField.textAlignment = NSTextAlignmentLeft; @@ -2525,7 +2525,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *addressCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; addressCell.textLabel.font = [UIFont systemFontOfSize:16]; - addressCell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + addressCell.textLabel.textColor = ThemeService.theme.textPrimaryColor; addressCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; addressCell.accessoryView = nil; addressCell.accessoryType = UITableViewCellAccessoryNone; @@ -2590,17 +2590,17 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addGroupTextField = addCommunityCell.mxkTextField; addGroupTextField.placeholder = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_details_new_flair_placeholder", @"Vector", nil), self.mainSession.matrixRestClient.homeserverSuffix]; - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { addGroupTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:addGroupTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } addGroupTextField.userInteractionEnabled = YES; addGroupTextField.text = currentValue; - addGroupTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + addGroupTextField.textColor = ThemeService.theme.textSecondaryColor; - addGroupTextField.tintColor = RiotDesignValues.theme.tintColor; + addGroupTextField.tintColor = ThemeService.theme.tintColor; addGroupTextField.font = [UIFont systemFontOfSize:17]; addGroupTextField.borderStyle = UITextBorderStyleNone; addGroupTextField.textAlignment = NSTextAlignmentLeft; @@ -2616,7 +2616,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *communityCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; communityCell.textLabel.font = [UIFont systemFontOfSize:16]; - communityCell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + communityCell.textLabel.textColor = ThemeService.theme.textPrimaryColor; communityCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; communityCell.accessoryView = nil; communityCell.accessoryType = UITableViewCellAccessoryNone; @@ -2634,7 +2634,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *addressCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; addressCell.textLabel.font = [UIFont systemFontOfSize:16]; - addressCell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + addressCell.textLabel.textColor = ThemeService.theme.textPrimaryColor; addressCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; addressCell.accessoryView = nil; addressCell.accessoryType = UITableViewCellAccessoryNone; @@ -2656,11 +2656,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_room_id", @"Vector", nil); - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; cell.detailTextLabel.font = [UIFont systemFontOfSize:15]; cell.detailTextLabel.text = mxRoomState.roomId; - cell.detailTextLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + cell.detailTextLabel.textColor = ThemeService.theme.textSecondaryColor; cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; cell.selectionStyle = UITableViewCellSelectionStyleNone; @@ -2672,7 +2672,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti MXKTableViewCellWithLabelAndSwitch *roomBlacklistUnverifiedDevicesCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; [roomBlacklistUnverifiedDevicesCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevice:) forControlEvents:UIControlEventValueChanged]; - roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; roomBlacklistUnverifiedDevicesCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_blacklist_unverified_devices", @"Vector", nil); @@ -2719,7 +2719,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_enabled", @"Vector", nil); - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; cell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -2753,7 +2753,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_disabled", @"Vector", nil); - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; cell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -2801,9 +2801,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.mxkLabelLeadingConstraint.constant = cell.separatorInset.left; cell.mxkSwitchTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; - cell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + cell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged]; // Reset the stored `directoryVisibilitySwitch` if the corresponding cell is reused. @@ -2822,13 +2822,13 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -3117,7 +3117,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti }]; - removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; + removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:removeAction atIndex:0]; } } @@ -3132,7 +3132,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti }]; - removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; + removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:removeAction atIndex:0]; } diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m index 3ac1cf733..d15818a8a 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m @@ -17,7 +17,7 @@ #import "TableViewCellWithCheckBoxAndLabel.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation TableViewCellWithCheckBoxAndLabel @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - _label.textColor = RiotDesignValues.theme.textPrimaryColor; + _label.textColor = ThemeService.theme.textPrimaryColor; } - (void)setEnabled:(BOOL)enabled diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m index 2b2cf6f03..36b34e556 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m @@ -17,7 +17,7 @@ #import "TableViewCellWithLabelAndLargeTextView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation TableViewCellWithLabelAndLargeTextView @@ -37,8 +37,8 @@ { [super customizeTableViewCellRendering]; - _label.textColor = RiotDesignValues.theme.textPrimaryColor; - _textView.textColor = RiotDesignValues.theme.textPrimaryColor; + _label.textColor = ThemeService.theme.textPrimaryColor; + _textView.textColor = ThemeService.theme.textPrimaryColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 9445af2af..7a88f7607 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -17,7 +17,7 @@ #import "RoomActivitiesView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import @@ -112,10 +112,10 @@ { [super customizeViewRendering]; - self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.separatorView.backgroundColor = ThemeService.theme.headerBackgroundColor; if (self.messageLabel.textColor != kRiotColorPinkRed) { - self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.messageLabel.textColor = ThemeService.theme.textSecondaryColor; } } @@ -260,12 +260,12 @@ // Display the string in white on pink red NSRange wholeString = NSMakeRange(0, onGoingConferenceCallAttibutedString.length); - [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.backgroundColor range:wholeString]; + [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.backgroundColor range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:kRiotColorPinkRed range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = onGoingConferenceCallAttibutedString; - self.messageTextView.tintColor = RiotDesignValues.theme.backgroundColor; + self.messageTextView.tintColor = ThemeService.theme.backgroundColor; self.messageTextView.hidden = NO; self.backgroundColor = kRiotColorPinkRed; @@ -356,7 +356,7 @@ [roomReplacementAttributedString appendAttributedString:roomLinkAttributedString]; NSRange wholeStringRange = NSMakeRange(0, roomReplacementAttributedString.length); - [roomReplacementAttributedString addAttribute:NSForegroundColorAttributeName value:RiotDesignValues.theme.textPrimaryColor range:wholeStringRange]; + [roomReplacementAttributedString addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.textPrimaryColor range:wholeStringRange]; self.messageTextView.attributedText = roomReplacementAttributedString; } @@ -365,7 +365,7 @@ self.messageTextView.text = NSLocalizedStringFromTable(@"room_replacement_information", @"Vector", nil); } - self.messageTextView.tintColor = RiotDesignValues.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.theme.textPrimaryColor; self.messageTextView.hidden = NO; self.messageTextView.backgroundColor = [UIColor clearColor]; @@ -432,13 +432,13 @@ message2 = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_resource_usage_limit_reached_message_2", @"Vector", nil) attributes:@{ NSFontAttributeName: [UIFont boldSystemFontOfSize:fontSize], - NSForegroundColorAttributeName: RiotDesignValues.theme.backgroundColor + NSForegroundColorAttributeName: ThemeService.theme.backgroundColor }]; } NSDictionary *attributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:fontSize], - NSForegroundColorAttributeName: RiotDesignValues.theme.backgroundColor + NSForegroundColorAttributeName: ThemeService.theme.backgroundColor }; NSDictionary *messageContact2LinkAttributes; @@ -482,7 +482,7 @@ [attributedText appendAttributedString:messageContact3]; self.messageTextView.attributedText = attributedText; - self.messageTextView.tintColor = RiotDesignValues.theme.backgroundColor; + self.messageTextView.tintColor = ThemeService.theme.backgroundColor; self.messageTextView.hidden = NO; if (hardLimit) @@ -535,7 +535,7 @@ [self.messageTextView resignFirstResponder]; self.messageTextView.hidden = YES; - self.messageLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.messageLabel.textColor = ThemeService.theme.textSecondaryColor; objc_removeAssociatedObjects(self.messageTextView); } diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m index 8439e4ccd..af76485f5 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomEncryptedDataBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" @implementation RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index 36d9bb7c7..b5ebb38d2 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingAttachmentBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingAttachmentBubbleCell @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index 51a5aba56..e831f0bb0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingAttachmentWithPaginationTitleBubbleCell @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m index effc143f1..86339cb3a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingAttachmentWithoutSenderInfoBubbleCell @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index eb3937c37..c14a48e76 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingTextMsgBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingTextMsgBubbleCell @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index 384bbc946..f9cad605a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithPaginationTitleBubbleCell @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index ed1dcf9ce..14252dccd 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m index bcf756e00..5ba8eeb40 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithoutSenderInfoBubbleCell @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m index c35e92c4f..b9aa838d8 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomIncomingTextMsgWithoutSenderNameBubbleCell @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m index 3536b961d..e8b42d519 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m @@ -16,7 +16,7 @@ #import "RoomMembershipBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -41,7 +41,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)prepareForReuse diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m index b9ec9456d..ffa7060b0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomMembershipCollapsedBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -30,7 +30,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m index 193a47787..27a2289bd 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m @@ -16,7 +16,7 @@ #import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index e17e76392..73461a2b0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -16,7 +16,7 @@ #import "RoomMembershipExpandedBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -38,9 +38,9 @@ NSString *const kRoomMembershipExpandedBubbleCellTapOnCollapseButton = @"kRoomMe { [super customizeTableViewCellRendering]; - self.separatorView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.separatorView.backgroundColor = ThemeService.theme.headerBackgroundColor; - [self.collapseButton setTintColor:RiotDesignValues.theme.tintColor]; + [self.collapseButton setTintColor:ThemeService.theme.tintColor]; self.collapseButton.titleLabel.font = [UIFont systemFontOfSize:14]; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m index 3b5115d82..12da4a91a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m @@ -16,7 +16,7 @@ #import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m index fd77e5da7..524e0e519 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m @@ -16,7 +16,7 @@ #import "RoomMembershipWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "RoomBubbleCellData.h" @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index f0f2dfebe..44ad81b97 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingAttachmentBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomOutgoingAttachmentBubbleCell @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index 4a0e72ee9..cb3bc41a9 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomOutgoingAttachmentWithPaginationTitleBubbleCell @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m index 7992756b8..c953a24ac 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index 04c5d8f01..fff5b9005 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingTextMsgBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomOutgoingTextMsgBubbleCell @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m index 55dff40d6..71491b57b 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomOutgoingTextMsgWithPaginationTitleBubbleCell @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = RiotDesignValues.theme.tintColor; - self.paginationSeparatorView.backgroundColor = RiotDesignValues.theme.tintColor; + self.paginationLabel.textColor = ThemeService.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index 5274fb96b..de0205036 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" @implementation RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m index 9c65559ec..9af0586e3 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomOutgoingTextMsgWithoutSenderInfoBubbleCell @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.tintColor; + self.messageTextView.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m index b9f1b08d0..b5b077c4e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" @implementation RoomOutgoingTextMsgWithoutSenderNameBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m index 7bc995254..5a866b7b3 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomPredecessorBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #pragma mark - Defines & Constants @@ -58,8 +58,8 @@ static CGFloat const kCustomBackgroundCornerRadius = 5.0; { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = RiotDesignValues.theme.textPrimaryColor; - self.customBackgroundView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.messageTextView.tintColor = ThemeService.theme.textPrimaryColor; + self.customBackgroundView.backgroundColor = ThemeService.theme.headerBackgroundColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m index f6671541d..e84ac884d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m @@ -24,7 +24,7 @@ #import "RoomIncomingEncryptedAttachmentBubbleCell.h" #import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomSelectedStickerBubbleCell @@ -45,8 +45,8 @@ arrowMaskLayer.path = path.CGPath; self.arrowView.layer.mask = arrowMaskLayer; - self.arrowView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.descriptionView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.arrowView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.descriptionView.backgroundColor = ThemeService.theme.headerBackgroundColor; [self.descriptionView.layer setCornerRadius:10]; } diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 605b636ce..c96230f45 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -16,7 +16,7 @@ #import "EventDetailsView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation EventDetailsView @@ -25,11 +25,11 @@ { [super customizeViewRendering]; - self.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.textView.textColor = RiotDesignValues.theme.textPrimaryColor; - self.redactButton.tintColor = RiotDesignValues.theme.tintColor; - self.closeButton.tintColor = RiotDesignValues.theme.tintColor; + self.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.textView.backgroundColor = ThemeService.theme.backgroundColor; + self.textView.textColor = ThemeService.theme.textPrimaryColor; + self.redactButton.tintColor = ThemeService.theme.tintColor; + self.closeButton.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 817fd370c..777ac8255 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -16,7 +16,7 @@ #import "DisabledRoomInputToolbarView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation DisabledRoomInputToolbarView @@ -48,11 +48,11 @@ // Remove default toolbar background color self.backgroundColor = [UIColor clearColor]; - self.separatorView.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; + self.separatorView.backgroundColor = ThemeService.theme.headerTextSecondaryColor; self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; - self.disabledReasonTextView.textColor = RiotDesignValues.theme.textPrimaryColor; - self.disabledReasonTextView.tintColor = RiotDesignValues.theme.tintColor; + self.disabledReasonTextView.textColor = ThemeService.theme.textPrimaryColor; + self.disabledReasonTextView.tintColor = ThemeService.theme.tintColor; self.disabledReasonTextView.editable = NO; self.disabledReasonTextView.scrollEnabled = NO; } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index f363c89a9..e88329627 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -17,7 +17,7 @@ #import "RoomInputToolbarView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "GBDeviceInfo_iOS.h" @@ -72,8 +72,8 @@ self.rightInputToolbarButton.hidden = YES; - [self.rightInputToolbarButton setTitleColor:RiotDesignValues.theme.tintColor forState:UIControlStateNormal]; - [self.rightInputToolbarButton setTitleColor:RiotDesignValues.theme.tintColor forState:UIControlStateHighlighted]; + [self.rightInputToolbarButton setTitleColor:ThemeService.theme.tintColor forState:UIControlStateNormal]; + [self.rightInputToolbarButton setTitleColor:ThemeService.theme.tintColor forState:UIControlStateHighlighted]; self.isEncryptionEnabled = _isEncryptionEnabled; } @@ -87,7 +87,7 @@ // Remove default toolbar background color self.backgroundColor = [UIColor clearColor]; - self.separatorView.backgroundColor = RiotDesignValues.theme.headerTextSecondaryColor; + self.separatorView.backgroundColor = ThemeService.theme.headerTextSecondaryColor; // Custom the growingTextView display growingTextView.layer.cornerRadius = 0; @@ -95,10 +95,10 @@ growingTextView.backgroundColor = [UIColor clearColor]; growingTextView.font = [UIFont systemFontOfSize:15]; - growingTextView.textColor = RiotDesignValues.theme.textPrimaryColor; - growingTextView.tintColor = RiotDesignValues.theme.tintColor; + growingTextView.textColor = ThemeService.theme.textPrimaryColor; + growingTextView.tintColor = ThemeService.theme.tintColor; - growingTextView.internalTextView.keyboardAppearance = RiotDesignValues.theme.keyboardAppearance; + growingTextView.internalTextView.keyboardAppearance = ThemeService.theme.keyboardAppearance; } #pragma mark - diff --git a/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.m b/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.m index 7df739f40..9e7bc5a07 100644 --- a/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.m +++ b/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.m @@ -17,7 +17,7 @@ #import "RoomAvatarTitleView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "MXRoomSummary+Riot.h" diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index 944329271..4709c4bf8 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -17,7 +17,7 @@ #import "ExpandedRoomTitleView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -40,19 +40,19 @@ [super layoutSubviews]; self.membersListIcon.image = [MXKTools paintImage:self.membersListIcon.image - withColor:RiotDesignValues.theme.tintColor]; + withColor:ThemeService.theme.tintColor]; // TODO: paintImage does not work here because addParticipantIcon has 2 colors // self.addParticipantIcon.image = [MXKTools paintImage:self.addParticipantIcon.image -// withColor:RiotDesignValues.theme.accent]; +// withColor:ThemeService.theme.accent]; } -(void)customizeViewRendering { [super customizeViewRendering]; - self.roomTopic.textColor = RiotDesignValues.theme.baseTextSecondaryColor; - self.roomMembers.textColor = RiotDesignValues.theme.tintColor; + self.roomTopic.textColor = ThemeService.theme.baseTextSecondaryColor; + self.roomMembers.textColor = ThemeService.theme.tintColor; } - (void)refreshDisplay @@ -131,7 +131,7 @@ self.roomAvatar.layer.cornerRadius = self.roomAvatar.frame.size.width / 2; self.roomAvatar.clipsToBounds = YES; - self.roomAvatar.defaultBackgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.roomAvatar.defaultBackgroundColor = ThemeService.theme.headerBackgroundColor; // Force the layout of subviews to update the position of 'bottomBorderView' which is used to define the actual height of the preview container. [self layoutIfNeeded]; diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 858f38a26..f9f1970d8 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -18,7 +18,7 @@ #import "PreviewRoomTitleView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoomSummary+Riot.h" @@ -64,28 +64,28 @@ [super customizeViewRendering]; // Use same color as navigation bar - self.mainHeaderBackground.backgroundColor = RiotDesignValues.theme.baseColor; + self.mainHeaderBackground.backgroundColor = ThemeService.theme.baseColor; - self.roomTopic.textColor = RiotDesignValues.theme.baseTextSecondaryColor; + self.roomTopic.textColor = ThemeService.theme.baseTextSecondaryColor; - self.roomMembers.textColor = RiotDesignValues.theme.tintColor; + self.roomMembers.textColor = ThemeService.theme.tintColor; - self.previewLabel.textColor = RiotDesignValues.theme.baseTextSecondaryColor; + self.previewLabel.textColor = ThemeService.theme.baseTextSecondaryColor; self.previewLabel.numberOfLines = 0; - self.subNoticeLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.subNoticeLabel.textColor = ThemeService.theme.textSecondaryColor; self.subNoticeLabel.numberOfLines = 0; - self.bottomBorderView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.bottomBorderView.backgroundColor = ThemeService.theme.headerBackgroundColor; [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; - self.leftButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.leftButton.backgroundColor = ThemeService.theme.tintColor; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - self.rightButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.rightButton.backgroundColor = ThemeService.theme.tintColor; } - (void)refreshDisplay @@ -103,7 +103,7 @@ toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.theme.tintColor] + withColor:ThemeService.theme.tintColor] mediaManager:self.mxRoom.mxSession.mediaManager]; } else @@ -249,7 +249,7 @@ self.roomAvatar.layer.cornerRadius = self.roomAvatar.frame.size.width / 2; self.roomAvatar.clipsToBounds = YES; - self.roomAvatar.defaultBackgroundColor = RiotDesignValues.theme.headerBackgroundColor; + self.roomAvatar.defaultBackgroundColor = ThemeService.theme.headerBackgroundColor; // Force the layout of subviews to update the position of 'bottomBorderView' which is used to define the actual height of the preview container. [self layoutIfNeeded]; diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 405fa53a6..8eddd61e9 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -17,7 +17,7 @@ #import "RoomTitleView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation RoomTitleView @@ -73,7 +73,7 @@ [super layoutSubviews]; self.roomDetailsIconImageView.image = [MXKTools paintImage:self.roomDetailsIconImageView.image - withColor:RiotDesignValues.theme.tintColor]; + withColor:ThemeService.theme.tintColor]; if (self.superview) { @@ -138,8 +138,8 @@ [super customizeViewRendering]; // Use same color as navigation bar - self.backgroundColor = RiotDesignValues.theme.baseColor; - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? RiotDesignValues.theme.baseTextPrimaryColor : RiotDesignValues.theme.textSecondaryColor); + self.backgroundColor = ThemeService.theme.baseColor; + self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? ThemeService.theme.baseTextPrimaryColor : ThemeService.theme.textSecondaryColor); } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -164,11 +164,11 @@ if (!self.displayNameTextField.text.length) { self.displayNameTextField.text = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; - self.displayNameTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + self.displayNameTextField.textColor = ThemeService.theme.textSecondaryColor; } else { - self.displayNameTextField.textColor = RiotDesignValues.theme.baseTextPrimaryColor; + self.displayNameTextField.textColor = ThemeService.theme.baseTextPrimaryColor; } } } diff --git a/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m b/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m index c6446edd3..db5fcc5e7 100644 --- a/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.m @@ -17,7 +17,7 @@ #import "SimpleRoomTitleView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" @implementation SimpleRoomTitleView diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index e22454615..711e8b051 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -36,8 +36,8 @@ // Current request in progress. MXHTTPOperation *mxCurrentOperation; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -58,10 +58,10 @@ dataSource = nil; onCompleteBlock = nil; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (kAppDelegateDidTapStatusBarNotificationObserver) @@ -110,7 +110,7 @@ self.tableView.tableFooterView = [[UIView alloc] init]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -120,12 +120,12 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -136,7 +136,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -226,13 +226,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m index f3a139de8..e897148bb 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m @@ -16,7 +16,7 @@ #import "DirectoryServerDetailTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation DirectoryServerDetailTableViewCell @@ -25,7 +25,7 @@ { [super customizeTableViewCellRendering]; - self.detailDescLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.detailDescLabel.textColor = ThemeService.theme.textSecondaryColor; } - (void)render:(id)cellData diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 858fbddd0..823415e1c 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -18,7 +18,7 @@ #import "DirectoryServerTableViewCell.h" #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation DirectoryServerTableViewCell @@ -29,7 +29,7 @@ { [super customizeTableViewCellRendering]; - self.descLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + self.descLabel.textColor = ThemeService.theme.textPrimaryColor; } - (void)layoutSubviews @@ -64,7 +64,7 @@ withType:nil andImageOrientation:UIImageOrientationUp previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:RiotDesignValues.theme.tintColor] + withColor:ThemeService.theme.tintColor] mediaManager:cellData.mediaManager]; } else diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 9e5a9e7f3..4774d1cd2 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -64,7 +64,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = RiotDesignValues.theme.tintColor; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.theme.tintColor; if ([self.dataSource isKindOfClass:RecentsDataSource.class]) { diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 13d07cbbc..17db945e3 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -16,7 +16,7 @@ #import "DeactivateAccountViewController.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "AppDelegate.h" @@ -109,36 +109,36 @@ static CGFloat const kTextFontSize = 15.0; - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } #pragma mark - Private - (void)registerThemeNotification { - self.themeDidChangeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + self.themeDidChangeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; }]; } - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; } - (void)setupStringAttributes { self.normalStringAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize], - NSForegroundColorAttributeName: RiotDesignValues.theme.textPrimaryColor + NSForegroundColorAttributeName: ThemeService.theme.textPrimaryColor }; self.emphasizeStringAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize weight:UIFontWeightBold], - NSForegroundColorAttributeName: RiotDesignValues.theme.textPrimaryColor + NSForegroundColorAttributeName: ThemeService.theme.textPrimaryColor }; } @@ -166,9 +166,9 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; self.deactivateAcccountButton.layer.masksToBounds = YES; - self.deactivateAcccountButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.deactivateAcccountButton.backgroundColor = ThemeService.theme.tintColor; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; - [self.deactivateAcccountButton setTitleColor:RiotDesignValues.theme.headerTextSecondaryColor forState:UIControlStateDisabled]; + [self.deactivateAcccountButton setTitleColor:ThemeService.theme.headerTextSecondaryColor forState:UIControlStateDisabled]; } - (void)setupDeactivateAccountInfosLabel diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index 224fa5a60..77170483f 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -22,9 +22,9 @@ @interface LanguagePickerViewController () { /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; /** The fake top view displayed in case of vertical bounce. @@ -59,7 +59,7 @@ [self.tableView addSubview:topview]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -69,15 +69,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; + [ThemeService.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. - self.tableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - topview.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.tableView.backgroundColor = ThemeService.theme.backgroundColor; + topview.backgroundColor = ThemeService.theme.backgroundColor; if (self.tableView.dataSource) { @@ -87,7 +87,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy @@ -97,10 +97,10 @@ [topview removeFromSuperview]; topview = nil; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -114,15 +114,15 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - cell.detailTextLabel.textColor = RiotDesignValues.theme.textSecondaryColor; - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.detailTextLabel.textColor = ThemeService.theme.textSecondaryColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 73d26ed7a..45e66a73f 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -22,9 +22,9 @@ @interface CountryPickerViewController () { /** - Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. + Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. */ - id kRiotDesignValuesDidChangeThemeNotificationObserver; + id kThemeServiceDidChangeThemeNotificationObserver; /** The fake top view displayed in case of vertical bounce. @@ -62,7 +62,7 @@ [self.tableView addSubview:topview]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -72,15 +72,15 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; - [RiotDesignValues.theme applyStyleOnSearchBar:self.searchBar]; + [ThemeService.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. - self.tableView.backgroundColor = RiotDesignValues.theme.backgroundColor; - topview.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.tableView.backgroundColor = ThemeService.theme.backgroundColor; + topview.backgroundColor = ThemeService.theme.backgroundColor; self.searchDisplayController.searchResultsTableView.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -91,7 +91,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -109,24 +109,24 @@ [topview removeFromSuperview]; topview = nil; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - cell.detailTextLabel.textColor = RiotDesignValues.theme.textSecondaryColor; - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.detailTextLabel.textColor = ThemeService.theme.textSecondaryColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 9bb49e631..275fdf265 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -38,7 +38,7 @@ #import "NBPhoneNumberUtil.h" #import "RageShakeManager.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "TableViewCellWithPhoneNumberTextField.h" #import "GroupsDataSource.h" @@ -202,8 +202,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Observe kAppDelegateDidTapStatusBarNotification to handle tap on clock status bar. id kAppDelegateDidTapStatusBarNotificationObserver; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; // Postpone destroy operation when saving, pwd reset or email binding is in progress BOOL isSavingInProgress; @@ -324,7 +324,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -334,12 +334,12 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -350,7 +350,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)didReceiveMemoryWarning @@ -378,10 +378,10 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); documentInteractionController = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } if (isSavingInProgress || isResetPwdInProgress || is3PIDBindingInProgress) @@ -955,30 +955,30 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Crypto information NSMutableAttributedString *cryptoInformationString = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_name", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:account.device.displayName ? account.device.displayName : @"" - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_id", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:account.device.deviceId ? account.device.deviceId : @"" - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_key", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; NSString *fingerprint = account.mxSession.crypto.deviceEd25519Key; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:fingerprint ? fingerprint : @"" - attributes:@{NSForegroundColorAttributeName : RiotDesignValues.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:17]}]]; return cryptoInformationString; @@ -1295,12 +1295,12 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkTextFieldLeadingConstraint.constant = 16; cell.mxkTextFieldTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; cell.mxkTextField.userInteractionEnabled = YES; cell.mxkTextField.borderStyle = UITextBorderStyleNone; cell.mxkTextField.textAlignment = NSTextAlignmentRight; - cell.mxkTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + cell.mxkTextField.textColor = ThemeService.theme.textSecondaryColor; cell.mxkTextField.font = [UIFont systemFontOfSize:16]; cell.mxkTextField.placeholder = nil; @@ -1322,7 +1322,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkLabelLeadingConstraint.constant = cell.separatorInset.left; cell.mxkSwitchTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1348,7 +1348,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); } cell.textLabel.accessibilityIdentifier = nil; cell.textLabel.font = [UIFont systemFontOfSize:17]; - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; return cell; } @@ -1357,7 +1357,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { MXKTableViewCellWithTextView *textViewCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier] forIndexPath:indexPath]; - textViewCell.mxkTextView.textColor = RiotDesignValues.theme.textPrimaryColor; + textViewCell.mxkTextView.textColor = ThemeService.theme.textPrimaryColor; textViewCell.mxkTextView.font = [UIFont systemFontOfSize:17]; textViewCell.mxkTextView.backgroundColor = [UIColor clearColor]; textViewCell.mxkTextViewLeadingConstraint.constant = tableView.separatorInset.left; @@ -1404,7 +1404,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); [signOutCell.mxkButton setTitle:title forState:UIControlStateNormal]; [signOutCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [signOutCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; + [signOutCell.mxkButton setTintColor:ThemeService.theme.tintColor]; signOutCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [signOutCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1436,7 +1436,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); profileCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_profile_picture", @"Vector", nil); profileCell.accessibilityIdentifier=@"SettingsVCProfilPictureStaticText"; - profileCell.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + profileCell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; // if the user defines a new avatar if (newAvatarImage) @@ -1527,11 +1527,11 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { newEmailCell.mxkLabel.text = nil; newEmailCell.mxkTextField.placeholder = NSLocalizedStringFromTable(@"settings_email_address_placeholder", @"Vector", nil); - if (RiotDesignValues.theme.placeholderTextColor) + if (ThemeService.theme.placeholderTextColor) { newEmailCell.mxkTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:newEmailCell.mxkTextField.placeholder - attributes:@{NSForegroundColorAttributeName: RiotDesignValues.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; } newEmailCell.mxkTextField.text = newEmailTextField.text; newEmailCell.mxkTextField.userInteractionEnabled = YES; @@ -1559,7 +1559,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newEmailTextField = newEmailCell.mxkTextField; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.theme.tintColor]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:ThemeService.theme.tintColor]; newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; } @@ -1652,7 +1652,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newPhoneNumberCell = newPhoneCell; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:RiotDesignValues.theme.tintColor]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:ThemeService.theme.tintColor]; newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; cell = newPhoneCell; @@ -1672,7 +1672,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); else if (row == userSettingsNightModeSepIndex) { UITableViewCell *sepCell = [[UITableViewCell alloc] init]; - sepCell.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; + sepCell.backgroundColor = ThemeService.theme.headerBackgroundColor; cell = sepCell; } @@ -1695,7 +1695,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_push_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.isPushKitNotificationActive; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePushNotifications:) forControlEvents:UIControlEventTouchUpInside]; @@ -1707,7 +1707,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_show_decrypted_content", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.showDecryptedContentInNotifications; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = account.isPushKitNotificationActive; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleShowDecodedContent:) forControlEvents:UIControlEventTouchUpInside]; @@ -1733,7 +1733,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_missed_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithMissedNotif:) forControlEvents:UIControlEventTouchUpInside]; @@ -1745,7 +1745,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_unread", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithUnread:) forControlEvents:UIControlEventTouchUpInside]; @@ -1759,7 +1759,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside]; @@ -1796,7 +1796,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language]; languageDescription = [languageDescription capitalizedStringWithLocale:locale]; - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_language", @"Vector", nil); cell.detailTextLabel.text = languageDescription; @@ -1833,7 +1833,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); @"Vector", nil); - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_theme", @"Vector", nil); cell.detailTextLabel.text = i18nTheme; @@ -1864,7 +1864,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.numberOfLines = 0; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_contacts_discover_matrix_users", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].syncLocalContacts; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLocalContactsSync:) forControlEvents:UIControlEventTouchUpInside]; @@ -1882,7 +1882,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[NSBundle mainBundle] preferredLocalizations][0]]; NSString *countryName = [local displayNameForKey:NSLocaleCountryCode value:countryCode]; - cell.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_contacts_phonebook_country", @"Vector", nil); cell.detailTextLabel.text = countryName; @@ -1973,7 +1973,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); sendCrashReportCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_send_crash_report", @"Vector", nil); sendCrashReportCell.mxkSwitch.on = RiotSettings.shared.enableCrashReport; - sendCrashReportCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + sendCrashReportCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; sendCrashReportCell.mxkSwitch.enabled = YES; [sendCrashReportCell.mxkSwitch addTarget:self action:@selector(toggleSendCrashReport:) forControlEvents:UIControlEventTouchUpInside]; @@ -1985,7 +1985,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); enableRageShakeCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_rageshake", @"Vector", nil); enableRageShakeCell.mxkSwitch.on = RiotSettings.shared.enableRageShake; - enableRageShakeCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + enableRageShakeCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; enableRageShakeCell.mxkSwitch.enabled = YES; [enableRageShakeCell.mxkSwitch addTarget:self action:@selector(toggleEnableRageShake:) forControlEvents:UIControlEventTouchUpInside]; @@ -2007,7 +2007,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_mark_all_as_read", @"Vector", nil); [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [markAllBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; + [markAllBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; markAllBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [markAllBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2032,7 +2032,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_clear_cache", @"Vector", nil); [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [clearCacheBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; + [clearCacheBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; clearCacheBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [clearCacheBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2057,7 +2057,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_report_bug", @"Vector", nil); [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [reportBugBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; + [reportBugBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; reportBugBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [reportBugBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2077,7 +2077,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; labelAndSwitchCell.mxkSwitch.on = account.mxSession.syncWithLazyLoadOfRoomMembers; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleSyncWithLazyLoadOfRoomMembers:) forControlEvents:UIControlEventTouchUpInside]; @@ -2089,7 +2089,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_create_conference_with_jitsi", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.createConferenceCallsWithJitsi; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleJitsiForConference:) forControlEvents:UIControlEventTouchUpInside]; @@ -2103,7 +2103,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_e2e_encryption", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = (nil != session.crypto); - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLabsEndToEndEncryption:) forControlEvents:UIControlEventTouchUpInside]; @@ -2177,7 +2177,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_crypto_blacklist_unverified_devices", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.mxSession.crypto.globalBlacklistUnverifiedDevices; - labelAndSwitchCell.mxkSwitch.onTintColor = RiotDesignValues.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevices:) forControlEvents:UIControlEventTouchUpInside]; @@ -2199,7 +2199,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_crypto_export", @"Vector", nil); [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [exportKeysBtnCell.mxkButton setTintColor:RiotDesignValues.theme.tintColor]; + [exportKeysBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; exportKeysBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [exportKeysBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2334,7 +2334,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { // Customize label style UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view; - tableViewHeaderFooterView.textLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + tableViewHeaderFooterView.textLabel.textColor = ThemeService.theme.textPrimaryColor; tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15]; } } @@ -2362,15 +2362,15 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; if (cell.selectionStyle != UITableViewCellSelectionStyleNone) { // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -2473,7 +2473,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_pink" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(50, cellHeight) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_pink" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(50, cellHeight) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } } diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 01fc6c8cf..6a3f3c7fa 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -17,7 +17,7 @@ #import "DeviceView.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" @implementation DeviceView @@ -28,12 +28,12 @@ { [super customizeViewRendering]; - self.containerView.backgroundColor = RiotDesignValues.theme.headerBackgroundColor; - self.textView.backgroundColor = RiotDesignValues.theme.backgroundColor; - self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; - self.cancelButton.tintColor = RiotDesignValues.theme.tintColor; - self.deleteButton.tintColor = RiotDesignValues.theme.tintColor; - self.renameButton.tintColor = RiotDesignValues.theme.tintColor; + self.containerView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.textView.backgroundColor = ThemeService.theme.backgroundColor; + self.defaultTextColor = ThemeService.theme.textPrimaryColor; + self.cancelButton.tintColor = ThemeService.theme.tintColor; + self.deleteButton.tintColor = ThemeService.theme.tintColor; + self.renameButton.tintColor = ThemeService.theme.tintColor; } @end diff --git a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m index 6476e51a9..a265e50b1 100644 --- a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m +++ b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m @@ -16,7 +16,7 @@ #import "TableViewCellWithPhoneNumberTextField.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "NBPhoneNumberUtil.h" @@ -27,10 +27,10 @@ { [super customizeTableViewCellRendering]; - self.mxkLabel.textColor = RiotDesignValues.theme.textPrimaryColor; - self.mxkTextField.textColor = RiotDesignValues.theme.textPrimaryColor; + self.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + self.mxkTextField.textColor = ThemeService.theme.textPrimaryColor; - _isoCountryCodeLabel.textColor = RiotDesignValues.theme.textPrimaryColor; + _isoCountryCodeLabel.textColor = ThemeService.theme.textPrimaryColor; } - (void)setIsoCountryCode:(NSString *)isoCountryCode diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 08f4b73c3..8faca7478 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -149,10 +149,10 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = RiotDesignValues.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -163,7 +163,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy @@ -381,13 +381,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { @@ -453,7 +453,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:RiotDesignValues.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } @@ -621,19 +621,19 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = RiotDesignValues.theme.tintColor; - searchBar.tintColor = RiotDesignValues.theme.tintColor; + searchBar.barTintColor = searchBar.tintColor = ThemeService.theme.tintColor; + searchBar.tintColor = ThemeService.theme.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = RiotDesignValues.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = RiotDesignValues.theme.tintColor; + leftImageView.tintColor = ThemeService.theme.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -646,8 +646,8 @@ { searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: RiotDesignValues.theme.tintColor, - NSForegroundColorAttributeName: RiotDesignValues.theme.tintColor}]; + NSUnderlineColorAttributeName: ThemeService.theme.tintColor, + NSForegroundColorAttributeName: ThemeService.theme.tintColor}]; } } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index c5f1882bd..114a7068c 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -55,8 +55,8 @@ // Keep reference on the pushed view controllers to release them correctly NSMutableArray *childViewControllers; - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; // The groups data source GroupsDataSource *groupsDataSource; @@ -104,7 +104,7 @@ [self initializeDataSources]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -114,19 +114,19 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.tabBar.tintColor = RiotDesignValues.theme.tintColor; - self.tabBar.barTintColor = RiotDesignValues.theme.headerBackgroundColor; + self.tabBar.tintColor = ThemeService.theme.tintColor; + self.tabBar.barTintColor = ThemeService.theme.headerBackgroundColor; - self.view.backgroundColor = RiotDesignValues.theme.backgroundColor; + self.view.backgroundColor = ThemeService.theme.backgroundColor; [self setNeedsStatusBarAppearanceUpdate]; } - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -218,10 +218,10 @@ authViewControllerObserver = nil; } - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } childViewControllers = nil; @@ -786,7 +786,7 @@ { _hidden = hidden; - [self.view superview].backgroundColor = RiotDesignValues.theme.backgroundColor; + [self.view superview].backgroundColor = ThemeService.theme.backgroundColor; self.view.hidden = hidden; self.navigationController.navigationBar.hidden = hidden; } @@ -798,15 +798,15 @@ // Use a middle dot to signal missed notif in favourites [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX - withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor)]; // Update the badge on People and Rooms tabs [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX - withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor)]; [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX - withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? RiotDesignValues.theme.notificationMentionColor : RiotDesignValues.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 7cbd10a38..3e288dfed 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -27,8 +27,8 @@ void (^onCompleteBlock)(BOOL doneButtonPressed); - // Observe kRiotDesignValuesDidChangeThemeNotification to handle user interface theme change. - id kRiotDesignValuesDidChangeThemeNotificationObserver; + // Observe kThemeServiceDidChangeThemeNotification to handle user interface theme change. + id kThemeServiceDidChangeThemeNotificationObserver; } @end @@ -72,7 +72,7 @@ self.tableView.tableFooterView = [[UIView alloc] init]; // Observe user interface theme change. - kRiotDesignValuesDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kRiotDesignValuesDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { + kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self userInterfaceThemeDidChange]; @@ -82,12 +82,12 @@ - (void)userInterfaceThemeDidChange { - [RiotDesignValues.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = RiotDesignValues.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? RiotDesignValues.theme.backgroundColor : RiotDesignValues.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -98,17 +98,17 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return RiotDesignValues.theme.statusBarStyle; + return ThemeService.theme.statusBarStyle; } - (void)destroy { [super destroy]; - if (kRiotDesignValuesDidChangeThemeNotificationObserver) + if (kThemeServiceDidChangeThemeNotificationObserver) { - [[NSNotificationCenter defaultCenter] removeObserver:kRiotDesignValuesDidChangeThemeNotificationObserver]; - kRiotDesignValuesDidChangeThemeNotificationObserver = nil; + [[NSNotificationCenter defaultCenter] removeObserver:kThemeServiceDidChangeThemeNotificationObserver]; + kThemeServiceDidChangeThemeNotificationObserver = nil; } } @@ -178,13 +178,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = RiotDesignValues.theme.backgroundColor; + cell.backgroundColor = ThemeService.theme.backgroundColor; // Update the selected background view - if (RiotDesignValues.theme.selectedBackgroundColor) + if (ThemeService.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = RiotDesignValues.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 7b3f42e3b..77ba00d6b 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -17,7 +17,7 @@ #import "DeviceTableViewCell.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "MXRoom+Riot.h" @@ -32,15 +32,15 @@ { [super customizeTableViewCellRendering]; - self.deviceName.textColor = RiotDesignValues.theme.textPrimaryColor; + self.deviceName.textColor = ThemeService.theme.textPrimaryColor; [self.verifyButton.layer setCornerRadius:5]; self.verifyButton.clipsToBounds = YES; - self.verifyButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.verifyButton.backgroundColor = ThemeService.theme.tintColor; [self.blockButton.layer setCornerRadius:5]; self.blockButton.clipsToBounds = YES; - self.blockButton.backgroundColor = RiotDesignValues.theme.tintColor; + self.blockButton.backgroundColor = ThemeService.theme.tintColor; } - (void)render:(MXDeviceInfo *)deviceInfo diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index 9dd6fab82..37a5b6f37 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -7,5 +7,5 @@ #import "WebViewViewController.h" #import "RiotNavigationController.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "TableViewCellWithCheckBoxAndLabel.h" diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index 67b4d5c4a..6b9ad57a9 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -17,7 +17,7 @@ #import "AvatarGenerator.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #ifdef IS_SHARE_EXTENSION #import "RiotShareExtension-Swift.h" @@ -39,7 +39,7 @@ static UILabel* backgroundLabel = nil; { if (!colorsList) { - colorsList = RiotDesignValues.theme.avatarColors; + colorsList = ThemeService.theme.avatarColors; } } @@ -93,7 +93,7 @@ static UILabel* backgroundLabel = nil; if (!backgroundLabel) { backgroundLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; - backgroundLabel.textColor = RiotDesignValues.theme.backgroundColor; + backgroundLabel.textColor = ThemeService.theme.backgroundColor; backgroundLabel.textAlignment = NSTextAlignmentCenter; backgroundLabel.font = [UIFont boldSystemFontOfSize:25]; } @@ -123,7 +123,7 @@ static UILabel* backgroundLabel = nil; + (UIImage *)imageFromText:(NSString*)text withBackgroundColor:(UIColor*)color size:(CGFloat)size andFontSize:(CGFloat)fontSize { UILabel *bgLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size, size)]; - bgLabel.textColor = RiotDesignValues.theme.backgroundColor; + bgLabel.textColor = ThemeService.theme.backgroundColor; bgLabel.textAlignment = NSTextAlignmentCenter; bgLabel.font = [UIFont boldSystemFontOfSize:fontSize]; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 9049e1c1e..36e8b88d1 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -17,7 +17,7 @@ #import "EventFormatter.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import "Riot-Swift.h" #import "WidgetManager.h" @@ -206,7 +206,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; // Use the secondary bg color to set the background color in the default CSS. - NSUInteger bgColor = [MXKTools rgbValueWithColor:RiotDesignValues.theme.headerBackgroundColor]; + NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.theme.headerBackgroundColor]; self.defaultCSS = [NSString stringWithFormat:@" \ pre,code { \ background-color: #%06lX; \ @@ -217,12 +217,12 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; font-size: small; \ }", (unsigned long)bgColor]; - self.defaultTextColor = RiotDesignValues.theme.textPrimaryColor; - self.subTitleTextColor = RiotDesignValues.theme.textSecondaryColor; - self.prefixTextColor = RiotDesignValues.theme.textSecondaryColor; - self.bingTextColor = RiotDesignValues.theme.notificationMentionColor; - self.encryptingTextColor = RiotDesignValues.theme.tintColor; - self.sendingTextColor = RiotDesignValues.theme.textSecondaryColor; + self.defaultTextColor = ThemeService.theme.textPrimaryColor; + self.subTitleTextColor = ThemeService.theme.textSecondaryColor; + self.prefixTextColor = ThemeService.theme.textSecondaryColor; + self.bingTextColor = ThemeService.theme.notificationMentionColor; + self.encryptingTextColor = ThemeService.theme.tintColor; + self.sendingTextColor = ThemeService.theme.textSecondaryColor; self.errorTextColor = kRiotColorRed; self.defaultTextFont = [UIFont systemFontOfSize:15]; diff --git a/RiotShareExtension/Modules/Fallback/FallbackViewController.m b/RiotShareExtension/Modules/Fallback/FallbackViewController.m index e10aba785..19b7165b6 100644 --- a/RiotShareExtension/Modules/Fallback/FallbackViewController.m +++ b/RiotShareExtension/Modules/Fallback/FallbackViewController.m @@ -15,7 +15,7 @@ */ #import "FallbackViewController.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #ifdef IS_SHARE_EXTENSION #import "RiotShareExtension-Swift.h" @@ -35,7 +35,7 @@ { [super viewDidLoad]; - self.titleLabel.textColor = RiotDesignValues.theme.textSecondaryColor; + self.titleLabel.textColor = ThemeService.theme.textSecondaryColor; self.titleLabel.text = NSLocalizedStringFromTable(@"share_extension_auth_prompt", @"Vector", nil); } diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m index 1a80aad7a..1f324bd7d 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m @@ -19,7 +19,7 @@ #import "NSBundle+MatrixKit.h" #import "ShareExtensionManager.h" #import "RecentCellData.h" -#import "RiotDesignValues.h" +#import "ThemeService.h" #import #ifdef IS_SHARE_EXTENSION @@ -96,7 +96,7 @@ self.recentsSearchBar.searchBarStyle = UISearchBarStyleMinimal; self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); - self.recentsSearchBar.tintColor = RiotDesignValues.theme.tintColor; + self.recentsSearchBar.tintColor = ThemeService.theme.tintColor; _tableSearchBar.tintColor = self.recentsSearchBar.tintColor; } From 2fdb06d8792e7863f04417a203a983613acbe0c2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 11:45:27 +0100 Subject: [PATCH 046/244] reskin: Create ThemeService.shared --- Riot/AppDelegate.m | 16 ++-- .../MXKRoomBubbleTableViewCell+Riot.m | 8 +- Riot/Categories/UIViewController+RiotSearch.m | 4 +- Riot/Constants/ThemeService.h | 25 ++++- Riot/Constants/ThemeService.m | 83 +++++++++-------- .../AuthenticationViewController.m | 34 +++---- .../Authentication/Views/AuthInputsView.m | 50 +++++----- .../Views/ForgotPasswordInputsView.m | 20 ++-- .../Authentication/Views/TermsView.swift | 2 +- .../BugReport/BugReportViewController.m | 36 ++++---- Riot/Modules/Call/CallViewController.m | 24 ++--- Riot/Modules/Call/Views/IncomingCallView.m | 22 ++--- .../Recents/DataSources/RecentsDataSource.m | 18 ++-- .../Common/Recents/RecentsViewController.m | 38 ++++---- .../Recents/Views/RecentTableViewCell.m | 18 ++-- .../SegmentedViewController.h | 2 +- .../SegmentedViewController.m | 10 +- .../WebViewController/WebViewViewController.m | 8 +- .../Communities/GroupsViewController.m | 32 +++---- .../Home/GroupHomeViewController.m | 24 ++--- .../Members/GroupParticipantsViewController.m | 30 +++--- .../Rooms/GroupRoomsViewController.m | 20 ++-- .../Rooms/Views/GroupRoomTableViewCell.m | 4 +- .../TabDetail/GroupDetailsViewController.m | 2 +- .../Views/GroupInviteTableViewCell.m | 2 +- .../Communities/Views/GroupTableViewCell.m | 8 +- .../Contacts/ContactsTableViewController.m | 14 +-- .../Contacts/DataSources/ContactsDataSource.m | 12 +-- .../Details/ContactDetailsViewController.m | 24 ++--- .../Details/Views/RoomTableViewCell.m | 4 +- .../Contacts/Views/ContactTableViewCell.m | 8 +- .../EncryptionInfo/EncryptionInfoView.m | 14 +-- .../Files/HomeFilesSearchViewController.m | 16 ++-- .../Files/Views/FilesSearchTableViewCell.m | 8 +- .../HomeMessagesSearchDataSource.m | 2 +- .../HomeMessagesSearchViewController.m | 16 ++-- ...MessagesSearchResultAttachmentBubbleCell.m | 6 +- .../MessagesSearchResultTextMsgBubbleCell.m | 6 +- .../Rooms/DirectoryViewController.m | 14 +-- .../UnifiedSearchViewController.m | 2 +- .../Views/DirectoryRecentTableViewCell.m | 4 +- .../Views/RoomIdOrAliasTableViewCell.m | 4 +- Riot/Modules/Home/HomeViewController.m | 6 +- .../Home/Views/RoomCollectionViewCell.m | 16 ++-- .../Views/TableViewCellWithCollectionView.m | 2 +- .../Library/MediaAlbumContentViewController.m | 8 +- .../MediaPicker/MediaPickerViewController.m | 24 ++--- .../MediaPicker/Views/MediaAlbumTableCell.m | 4 +- .../People/Views/InviteRecentTableViewCell.m | 6 +- .../PublicRoomsDirectoryDataSource.m | 2 +- .../Views/PublicRoomTableViewCell.m | 6 +- .../Attachements/AttachmentsViewController.m | 8 +- .../Modules/Room/DataSources/RoomDataSource.m | 2 +- .../Room/Files/RoomFilesViewController.m | 14 +-- .../Detail/RoomMemberDetailsViewController.m | 26 +++--- .../Members/RoomParticipantsViewController.m | 40 ++++---- .../ReadReceiptsViewController.m | 30 +++--- Riot/Modules/Room/RoomViewController.m | 30 +++--- .../Search/DataSources/RoomSearchDataSource.m | 2 +- .../Files/RoomFilesSearchViewController.m | 16 ++-- .../RoomMessagesSearchViewController.m | 16 ++-- .../Room/Search/RoomSearchViewController.m | 2 +- .../Settings/RoomSettingsViewController.m | 76 +++++++-------- .../Views/TableViewCellWithCheckBoxAndLabel.m | 2 +- .../TableViewCellWithLabelAndLargeTextView.m | 4 +- .../Views/Activities/RoomActivitiesView.m | 20 ++-- .../RoomIncomingAttachmentBubbleCell.m | 4 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 8 +- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../RoomIncomingTextMsgBubbleCell.m | 4 +- ...mingTextMsgWithPaginationTitleBubbleCell.m | 8 +- ...ginationTitleWithoutSenderNameBubbleCell.m | 2 +- ...comingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- ...comingTextMsgWithoutSenderNameBubbleCell.m | 2 +- .../BubbleCells/RoomMembershipBubbleCell.m | 2 +- .../RoomMembershipCollapsedBubbleCell.m | 2 +- ...ipCollapsedWithPaginationTitleBubbleCell.m | 4 +- .../RoomMembershipExpandedBubbleCell.m | 4 +- ...hipExpandedWithPaginationTitleBubbleCell.m | 4 +- ...mMembershipWithPaginationTitleBubbleCell.m | 4 +- .../RoomOutgoingAttachmentBubbleCell.m | 4 +- ...gAttachmentWithPaginationTitleBubbleCell.m | 8 +- ...ingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../RoomOutgoingTextMsgBubbleCell.m | 4 +- ...oingTextMsgWithPaginationTitleBubbleCell.m | 4 +- ...tgoingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- .../BubbleCells/RoomPredecessorBubbleCell.m | 4 +- .../RoomSelectedStickerBubbleCell.m | 4 +- .../Room/Views/Event/EventDetailsView.m | 10 +- .../DisabledRoomInputToolbarView.m | 6 +- .../Views/InputToolbar/RoomInputToolbarView.m | 12 +-- .../Title/Expanded/ExpandedRoomTitleView.m | 10 +- .../Title/Preview/PreviewRoomTitleView.m | 20 ++-- Riot/Modules/Room/Views/Title/RoomTitleView.m | 10 +- .../DirectoryServerPickerViewController.m | 14 +-- .../DirectoryServerDetailTableViewCell.m | 2 +- .../Views/DirectoryServerTableViewCell.m | 4 +- Riot/Modules/Rooms/RoomsViewController.m | 2 +- .../DeactivateAccountViewController.m | 14 +-- .../Language/LanguagePickerViewController.m | 22 ++--- .../CountryPickerViewController.m | 22 ++--- .../Modules/Settings/SettingsViewController.m | 92 +++++++++---------- Riot/Modules/Settings/Views/DeviceView.m | 12 +-- .../TableViewCellWithPhoneNumberTextField.m | 6 +- .../StartChat/StartChatViewController.m | 26 +++--- Riot/Modules/TabBar/MasterTabBarController.m | 18 ++-- .../UserDevices/UsersDevicesViewController.m | 14 +-- .../UserDevices/Views/DeviceTableViewCell.m | 6 +- Riot/Utils/AvatarGenerator.m | 6 +- Riot/Utils/EventFormatter.m | 14 +-- .../Modules/Fallback/FallbackViewController.m | 2 +- .../Share/Listing/RoomsListViewController.m | 2 +- 112 files changed, 758 insertions(+), 728 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 587b8f141..4f0a971ad 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -422,7 +422,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [NSBundle mxk_setFallbackLanguage:@"en"]; // Define the navigation bar text color - [[UINavigationBar appearance] setTintColor:ThemeService.theme.tintColor]; + [[UINavigationBar appearance] setTintColor:ThemeService.shared.theme.tintColor]; // Customize the localized string table [NSBundle mxk_customizeLocalizedStringTableName:@"Vector"]; @@ -444,8 +444,8 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UINavigationController *secondNavController = self.secondaryNavigationController; if (secondNavController) { - secondNavController.navigationBar.barTintColor = ThemeService.theme.backgroundColor; - secondNavController.topViewController.view.backgroundColor = ThemeService.theme.backgroundColor; + secondNavController.navigationBar.barTintColor = ThemeService.shared.theme.backgroundColor; + secondNavController.topViewController.view.backgroundColor = ThemeService.shared.theme.backgroundColor; } // on IOS 8 iPad devices, force to display the primary and the secondary viewcontroller @@ -835,7 +835,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; UIViewController *emptyDetailsViewController = [storyboard instantiateViewControllerWithIdentifier:@"EmptyDetailsViewControllerStoryboardId"]; - emptyDetailsViewController.view.backgroundColor = ThemeService.theme.backgroundColor; + emptyDetailsViewController.view.backgroundColor = ThemeService.shared.theme.backgroundColor; splitViewController.viewControllers = @[mainViewController, emptyDetailsViewController]; } @@ -2825,7 +2825,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN if (!launchAnimationContainerView && window) { launchAnimationContainerView = [[UIView alloc] initWithFrame:window.bounds]; - launchAnimationContainerView.backgroundColor = ThemeService.theme.backgroundColor; + launchAnimationContainerView.backgroundColor = ThemeService.shared.theme.backgroundColor; launchAnimationContainerView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; [window addSubview:launchAnimationContainerView]; @@ -3531,7 +3531,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [_callStatusBarButton setTitle:buttonTitle forState:UIControlStateNormal]; [_callStatusBarButton setTitle:buttonTitle forState:UIControlStateHighlighted]; - _callStatusBarButton.titleLabel.textColor = ThemeService.theme.backgroundColor; + _callStatusBarButton.titleLabel.textColor = ThemeService.shared.theme.backgroundColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { @@ -3542,7 +3542,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN _callStatusBarButton.titleLabel.font = [UIFont boldSystemFontOfSize:17]; } - [_callStatusBarButton setBackgroundColor:ThemeService.theme.tintColor]; + [_callStatusBarButton setBackgroundColor:ThemeService.shared.theme.tintColor]; [_callStatusBarButton addTarget:self action:@selector(onCallStatusBarButtonPressed) forControlEvents:UIControlEventTouchUpInside]; // Place button into the new window @@ -3691,7 +3691,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:[NSBundle mainBundle]]; UIViewController *emptyDetailsViewController = [storyboard instantiateViewControllerWithIdentifier:@"EmptyDetailsViewControllerStoryboardId"]; - emptyDetailsViewController.view.backgroundColor = ThemeService.theme.backgroundColor; + emptyDetailsViewController.view.backgroundColor = ThemeService.shared.theme.backgroundColor; return emptyDetailsViewController; } diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 69a71028e..92e6044b6 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -62,7 +62,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT timeLabel.text = [bubbleData.eventFormatter timeStringFromDate:component.date]; timeLabel.textAlignment = NSTextAlignmentRight; - timeLabel.textColor = ThemeService.theme.textSecondaryColor; + timeLabel.textColor = ThemeService.shared.theme.textSecondaryColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { timeLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightLight]; @@ -209,7 +209,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT markPosY, VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH, markHeight)]; - markerView.backgroundColor = ThemeService.theme.tintColor; + markerView.backgroundColor = ThemeService.shared.theme.tintColor; [markerView setTranslatesAutoresizingMaskIntoConstraints:NO]; markerView.accessibilityIdentifier = @"markerView"; @@ -264,7 +264,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT timeLabel.text = [bubbleData.eventFormatter dateStringFromDate:date withTime:NO]; timeLabel.textAlignment = NSTextAlignmentRight; - timeLabel.textColor = ThemeService.theme.textSecondaryColor; + timeLabel.textColor = ThemeService.shared.theme.textSecondaryColor; if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) { timeLabel.font = [UIFont systemFontOfSize:12 weight:UIFontWeightLight]; @@ -321,7 +321,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT if (blurred) { self.bubbleOverlayContainer.hidden = NO; - self.bubbleOverlayContainer.backgroundColor = ThemeService.theme.backgroundColor; + self.bubbleOverlayContainer.backgroundColor = ThemeService.shared.theme.backgroundColor; self.bubbleOverlayContainer.alpha = 0.8; self.bubbleOverlayContainer.userInteractionEnabled = YES; diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index 3e4647e66..7f4fe2eef 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -95,7 +95,7 @@ self.searchBar.text = @""; // Customize search bar - [ThemeService.theme applyStyleOnSearchBar:self.searchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:self.searchBar]; // Remove navigation buttons self.navigationItem.hidesBackButton = YES; @@ -134,7 +134,7 @@ - (void)addBackgroundImageViewToView:(UIView*)view { - UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:ThemeService.theme.matrixSearchBackgroundImageTintColor]; + UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:searchBgImage]; backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO; diff --git a/Riot/Constants/ThemeService.h b/Riot/Constants/ThemeService.h index 1cc4443ba..8d501c4dc 100644 --- a/Riot/Constants/ThemeService.h +++ b/Riot/Constants/ThemeService.h @@ -1,6 +1,7 @@ /* Copyright 2015 OpenMarket Ltd Copyright 2017 Vector Creations Ltd + Copyright 2019 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -48,14 +49,34 @@ extern NSInteger const kRiotRoomModeratorLevel; extern NSInteger const kRiotRoomAdminLevel; /** - `ThemeService` class manages the Riot design parameters + `ThemeService` class manages the application design values. */ @interface ThemeService : NSObject +/** + Returns the shared instance. + + @return the shared instance. + */ ++ (instancetype)shared; + +/** + The id of the theme corresponding to the current app settings. + */ +@property (nonatomic, readonly) NSString *themeId; + /** The current theme. */ -+ (id)theme; +@property (nonatomic, readonly) id theme; + +/** + Get the theme with the given id. + + @param themeId the theme id. + @return the theme. + */ +- (id)themeWithThemeId:(NSString*)themeId; @end diff --git a/Riot/Constants/ThemeService.m b/Riot/Constants/ThemeService.m index b752be420..d29b5799e 100644 --- a/Riot/Constants/ThemeService.m +++ b/Riot/Constants/ThemeService.m @@ -1,6 +1,7 @@ /* Copyright 2016 OpenMarket Ltd Copyright 2017 Vector Creations Ltd + Copyright 2019 New Vector Ltd Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -40,18 +41,52 @@ NSInteger const kRiotRoomAdminLevel = 100; @implementation ThemeService -+ (ThemeService *)sharedInstance ++ (ThemeService *)shared { static ThemeService *sharedOnceInstance; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - sharedOnceInstance = [[ThemeService alloc] init]; + sharedOnceInstance = [ThemeService new]; }); return sharedOnceInstance; } +- (NSString*)themeId +{ + // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). + NSString *themeId = RiotSettings.shared.userInterfaceTheme; + + if (!themeId || [themeId isEqualToString:@"auto"]) + { + themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; + } + + return themeId; +} + +- (id)themeWithThemeId:(NSString*)themeId +{ + // Use light theme colors by default. + id theme = DefaultTheme.shared; + + if ([themeId isEqualToString:@"dark"]) + { + // Set dark theme colors + theme = DarkTheme.shared; + } + else if ([themeId isEqualToString:@"black"]) + { + // TODO: Use dark theme colors for the moment + theme = DarkTheme.shared; + } + + return theme; +} + +#pragma mark - Private methods + + (void)load { [super load]; @@ -66,12 +101,14 @@ NSInteger const kRiotRoomAdminLevel = 100; kRiotColorIndigo = UIColorFromRGB(0xBD79CC); kRiotColorOrange = UIColorFromRGB(0xF8A15F); + ThemeService *themeService = ThemeService.shared; + // Observe user interface theme change. - [[NSUserDefaults standardUserDefaults] addObserver:[ThemeService sharedInstance] forKeyPath:@"userInterfaceTheme" options:0 context:nil]; - [[ThemeService sharedInstance] userInterfaceThemeDidChange]; + [[NSUserDefaults standardUserDefaults] addObserver:themeService forKeyPath:@"userInterfaceTheme" options:0 context:nil]; + [themeService userInterfaceThemeDidChange]; // Observe "Invert Colours" settings changes (available since iOS 11) - [[NSNotificationCenter defaultCenter] addObserver:[ThemeService sharedInstance] selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:themeService selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context @@ -94,40 +131,12 @@ NSInteger const kRiotRoomAdminLevel = 100; - (void)userInterfaceThemeDidChange { - [UIScrollView appearance].indicatorStyle = ThemeService.theme.scrollBarStyle; + // Update the current theme + _theme = [self themeWithThemeId:self.themeId]; + + [UIScrollView appearance].indicatorStyle = self.theme.scrollBarStyle; [[NSNotificationCenter defaultCenter] postNotificationName:kThemeServiceDidChangeThemeNotification object:nil]; } -+ (id)theme -{ - id theme; - - // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). - NSString *themeId = RiotSettings.shared.userInterfaceTheme; - - if (!themeId || [themeId isEqualToString:@"auto"]) - { - themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; - } - - if ([themeId isEqualToString:@"dark"]) - { - // Set dark theme colors - theme = DarkTheme.shared; - } - else if ([themeId isEqualToString:@"black"]) - { - // TODO: Use dark theme colors for the moment - theme = DarkTheme.shared; - } - else - { - // Set light theme colors by default. - theme = DefaultTheme.shared; - } - - return theme; -} - @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index f2bdae672..ae37370bb 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -131,52 +131,52 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.view.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - self.authenticationScrollView.backgroundColor = ThemeService.theme.backgroundColor; - self.authFallbackContentView.backgroundColor = ThemeService.theme.backgroundColor; + self.authenticationScrollView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.authFallbackContentView.backgroundColor = ThemeService.shared.theme.backgroundColor; - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { if (self.homeServerTextField.placeholder) { self.homeServerTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.homeServerTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } if (self.identityServerTextField.placeholder) { self.identityServerTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.identityServerTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } } - self.submitButton.backgroundColor = ThemeService.theme.tintColor; - self.skipButton.backgroundColor = ThemeService.theme.tintColor; + self.submitButton.backgroundColor = ThemeService.shared.theme.tintColor; + self.skipButton.backgroundColor = ThemeService.shared.theme.tintColor; self.noFlowLabel.textColor = kRiotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; - [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; + [forgotPasswordTitle addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.tintColor range:NSMakeRange(0, forgotPasswordTitle.length)]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateNormal]; [self.forgotPasswordButton setAttributedTitle:forgotPasswordTitle forState:UIControlStateHighlighted]; [self updateForgotPwdButtonVisibility]; - NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textSecondaryColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}]; + NSAttributedString *serverOptionsTitle = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_use_server_options", @"Vector", nil) attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textSecondaryColor, NSFontAttributeName: [UIFont systemFontOfSize:14]}]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateNormal]; [self.customServersTickButton setAttributedTitle:serverOptionsTitle forState:UIControlStateHighlighted]; - self.homeServerTextField.textColor = ThemeService.theme.textPrimaryColor; - self.homeServerLabel.textColor = ThemeService.theme.textSecondaryColor; + self.homeServerTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.homeServerLabel.textColor = ThemeService.shared.theme.textSecondaryColor; - self.identityServerTextField.textColor = ThemeService.theme.textPrimaryColor; - self.identityServerLabel.textColor = ThemeService.theme.textSecondaryColor; + self.identityServerTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.identityServerLabel.textColor = ThemeService.shared.theme.textSecondaryColor; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; [self.authInputsView customizeViewRendering]; @@ -185,7 +185,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 3a67b064c..a1a55cc73 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -72,7 +72,7 @@ self.repeatPasswordTextField.placeholder = NSLocalizedStringFromTable(@"auth_repeat_password_placeholder", @"Vector", nil); self.passWordTextField.placeholder = NSLocalizedStringFromTable(@"auth_password_placeholder", @"Vector", nil); - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { // Apply placeholder color [self customizeViewRendering]; @@ -103,33 +103,33 @@ { [super customizeViewRendering]; - self.repeatPasswordTextField.textColor = ThemeService.theme.textPrimaryColor; - self.userLoginTextField.textColor = ThemeService.theme.textPrimaryColor; - self.passWordTextField.textColor = ThemeService.theme.textPrimaryColor; + self.repeatPasswordTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.userLoginTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.passWordTextField.textColor = ThemeService.shared.theme.textPrimaryColor; - self.emailTextField.textColor = ThemeService.theme.textPrimaryColor; - self.phoneTextField.textColor = ThemeService.theme.textPrimaryColor; + self.emailTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.phoneTextField.textColor = ThemeService.shared.theme.textPrimaryColor; - self.isoCountryCodeLabel.textColor = ThemeService.theme.textPrimaryColor; - self.callingCodeLabel.textColor = ThemeService.theme.textPrimaryColor; + self.isoCountryCodeLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.callingCodeLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.messageLabel.textColor = ThemeService.theme.textSecondaryColor; + self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor; self.messageLabel.numberOfLines = 0; - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { if (self.userLoginTextField.placeholder) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.userLoginTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } if (self.repeatPasswordTextField.placeholder) { self.repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.repeatPasswordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } @@ -137,21 +137,21 @@ { self.passWordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.passWordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } if (self.phoneTextField.placeholder) { self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } if (self.emailTextField.placeholder) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } } } @@ -196,14 +196,14 @@ self.messageLabel.text = NSLocalizedStringFromTable(@"or", @"Vector", nil); self.phoneTextField.placeholder = NSLocalizedStringFromTable(@"auth_phone_placeholder", @"Vector", nil); - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.userLoginTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } self.userLoginContainer.hidden = NO; @@ -1025,11 +1025,11 @@ { self.passWordTextField.returnKeyType = UIReturnKeyNext; - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { self.userLoginTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_user_name_placeholder", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } else { @@ -1057,11 +1057,11 @@ self.emailTextField.placeholder = NSLocalizedStringFromTable(@"auth_optional_email_placeholder", @"Vector", nil); } - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } self.emailContainer.hidden = NO; @@ -1085,11 +1085,11 @@ self.phoneTextField.placeholder = NSLocalizedStringFromTable(@"auth_optional_phone_placeholder", @"Vector", nil); } - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { self.phoneTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.phoneTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } self.phoneContainer.hidden = NO; @@ -1149,7 +1149,7 @@ phoneNumberPickerNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - [ThemeService.theme applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:phoneNumberPickerNavigationController.navigationBar]; [phoneNumberPickerNavigationController pushViewController:phoneNumberCountryPicker animated:NO]; diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 4902677a9..0da181158 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -60,7 +60,7 @@ self.passWordTextField.placeholder = NSLocalizedStringFromTable(@"auth_new_password_placeholder", @"Vector", nil); self.repeatPasswordTextField.placeholder = NSLocalizedStringFromTable(@"auth_repeat_new_password_placeholder", @"Vector", nil); - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { // Apply placeholder color [self customizeViewRendering]; @@ -105,37 +105,37 @@ { [super customizeViewRendering]; - self.messageLabel.textColor = ThemeService.theme.textPrimaryColor; + self.messageLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.emailTextField.textColor = ThemeService.theme.textPrimaryColor; - self.passWordTextField.textColor = ThemeService.theme.textPrimaryColor; - self.repeatPasswordTextField.textColor = ThemeService.theme.textPrimaryColor; + self.emailTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.passWordTextField.textColor = ThemeService.shared.theme.textPrimaryColor; + self.repeatPasswordTextField.textColor = ThemeService.shared.theme.textPrimaryColor; self.messageLabel.numberOfLines = 0; [self.nextStepButton.layer setCornerRadius:5]; self.nextStepButton.clipsToBounds = YES; - self.nextStepButton.backgroundColor = ThemeService.theme.tintColor; + self.nextStepButton.backgroundColor = ThemeService.shared.theme.tintColor; - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { if (self.emailTextField.placeholder) { self.emailTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.emailTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } if (self.passWordTextField.placeholder) { self.passWordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.passWordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } if (self.repeatPasswordTextField.placeholder) { self.repeatPasswordTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:self.repeatPasswordTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } } } diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index 154ac3b27..480e0416b 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -80,7 +80,7 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie } func customizeViewRendering() { - acceptButton.backgroundColor = ThemeService.theme().tintColor + acceptButton.backgroundColor = ThemeService.shared().theme.tintColor } diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index e6d9fe6ae..cbf17f7ec 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -138,36 +138,36 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.overlayView.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.overlayView.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; self.overlayView.alpha = 1.0; - self.containerView.backgroundColor = ThemeService.theme.backgroundColor; - self.sendingContainer.backgroundColor = ThemeService.theme.backgroundColor; + self.containerView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.sendingContainer.backgroundColor = ThemeService.shared.theme.backgroundColor; - self.bugReportDescriptionTextView.keyboardAppearance = ThemeService.theme.keyboardAppearance; + self.bugReportDescriptionTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance; - self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; - self.sendingLabel.textColor = ThemeService.theme.textPrimaryColor; - self.descriptionLabel.textColor = ThemeService.theme.textPrimaryColor; - self.bugReportDescriptionTextView.textColor = ThemeService.theme.textPrimaryColor; - self.bugReportDescriptionTextView.tintColor = ThemeService.theme.tintColor; - self.logsDescriptionLabel.textColor = ThemeService.theme.textPrimaryColor; - self.sendLogsLabel.textColor = ThemeService.theme.textPrimaryColor; - self.sendScreenshotLabel.textColor = ThemeService.theme.textPrimaryColor; + self.titleLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.sendingLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.descriptionLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.bugReportDescriptionTextView.textColor = ThemeService.shared.theme.textPrimaryColor; + self.bugReportDescriptionTextView.tintColor = ThemeService.shared.theme.tintColor; + self.logsDescriptionLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.sendLogsLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.sendScreenshotLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.sendButton.tintColor = ThemeService.theme.tintColor; - self.cancelButton.tintColor = ThemeService.theme.tintColor; + self.sendButton.tintColor = ThemeService.shared.theme.tintColor; + self.cancelButton.tintColor = ThemeService.shared.theme.tintColor; - _bugReportDescriptionTextView.layer.borderColor = ThemeService.theme.headerBackgroundColor.CGColor; + _bugReportDescriptionTextView.layer.borderColor = ThemeService.shared.theme.headerBackgroundColor.CGColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 151160e01..7753347a8 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -98,20 +98,20 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.barTitleColor = ThemeService.theme.textPrimaryColor; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.barTitleColor = ThemeService.shared.theme.textPrimaryColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.callerNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.callStatusLabel.textColor = ThemeService.theme.baseTextSecondaryColor; + self.callerNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.callStatusLabel.textColor = ThemeService.shared.theme.baseTextSecondaryColor; - self.localPreviewContainerView.layer.borderColor = ThemeService.theme.tintColor.CGColor; + self.localPreviewContainerView.layer.borderColor = ThemeService.shared.theme.tintColor.CGColor; self.localPreviewContainerView.layer.borderWidth = 2; self.localPreviewContainerView.layer.cornerRadius = 5; self.localPreviewContainerView.clipsToBounds = YES; - self.remotePreviewContainerView.backgroundColor = ThemeService.theme.backgroundColor; + self.remotePreviewContainerView.backgroundColor = ThemeService.shared.theme.backgroundColor; if (gradientMaskLayer) { @@ -121,9 +121,9 @@ // Add a gradient mask programatically at the top of the screen (background of the call information (name, status)) gradientMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the ThemeService.theme.backgroundColor. + // Consider the grayscale components of the ThemeService.shared.theme.backgroundColor. CGFloat white = 1.0; - [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -283,8 +283,8 @@ UINavigationController *usersDevicesNavigationController = [[RiotNavigationController alloc] init]; // Set Riot navigation bar colors - [ThemeService.theme applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; - usersDevicesNavigationController.navigationBar.barTintColor = ThemeService.theme.backgroundColor; + [ThemeService.shared.theme applyStyleOnNavigationBar:usersDevicesNavigationController.navigationBar]; + usersDevicesNavigationController.navigationBar.barTintColor = ThemeService.shared.theme.backgroundColor; [usersDevicesNavigationController pushViewController:usersDevicesViewController animated:NO]; @@ -350,7 +350,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:ThemeService.theme.tintColor]; + withColor:ThemeService.shared.theme.tintColor]; } - (void)setMxCall:(MXCall *)call diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index cfb038122..eb55551ac 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -57,11 +57,11 @@ static const CGFloat kButtonSize = 80.0; self = [super initWithFrame:CGRectZero]; if (self) { - self.backgroundColor = ThemeService.theme.backgroundColor; + self.backgroundColor = ThemeService.shared.theme.backgroundColor; self.opaque = YES; self.callerImageView = [[MXKImageView alloc] init]; - self.callerImageView.backgroundColor = ThemeService.theme.backgroundColor; + self.callerImageView.backgroundColor = ThemeService.shared.theme.backgroundColor; self.callerImageView.clipsToBounds = YES; self.callerImageView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder; self.callerImageView.enableInMemoryCache = YES; @@ -74,28 +74,28 @@ static const CGFloat kButtonSize = 80.0; mediaManager:mediaManager]; self.callerNameLabel = [[UILabel alloc] init]; - self.callerNameLabel.backgroundColor = ThemeService.theme.backgroundColor; - self.callerNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.callerNameLabel.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.callerNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; self.callerNameLabel.font = [UIFont systemFontOfSize:24.0 weight:UIFontWeightMedium]; self.callerNameLabel.text = callerName; self.callerNameLabel.textAlignment = NSTextAlignmentCenter; self.callInfoLabel = [[UILabel alloc] init]; - self.callInfoLabel.backgroundColor = ThemeService.theme.backgroundColor; - self.callInfoLabel.textColor = ThemeService.theme.textSecondaryColor; + self.callInfoLabel.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.callInfoLabel.textColor = ThemeService.shared.theme.textSecondaryColor; self.callInfoLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.callInfoLabel.text = callInfo; self.callInfoLabel.textAlignment = NSTextAlignmentCenter; - UIColor *answerButtonBorderColor = ThemeService.theme.tintColor; + UIColor *answerButtonBorderColor = ThemeService.shared.theme.tintColor; self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_icon"] borderColor:answerButtonBorderColor]; - self.answerButton.defaultBackgroundColor = ThemeService.theme.backgroundColor; + self.answerButton.defaultBackgroundColor = ThemeService.shared.theme.backgroundColor; [self.answerButton addTarget:self action:@selector(didTapAnswerButton) forControlEvents:UIControlEventTouchUpInside]; self.answerTitleLabel = [[UILabel alloc] init]; - self.answerTitleLabel.backgroundColor = ThemeService.theme.backgroundColor; + self.answerTitleLabel.backgroundColor = ThemeService.shared.theme.backgroundColor; self.answerTitleLabel.textColor = answerButtonBorderColor; self.answerTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.answerTitleLabel.text = NSLocalizedStringFromTable(@"accept", @"Vector", nil); @@ -104,11 +104,11 @@ static const CGFloat kButtonSize = 80.0; self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"call_hangup_icon"] borderColor:rejectButtonBorderColor]; - self.rejectButton.defaultBackgroundColor = ThemeService.theme.backgroundColor; + self.rejectButton.defaultBackgroundColor = ThemeService.shared.theme.backgroundColor; [self.rejectButton addTarget:self action:@selector(didTapRejectButton) forControlEvents:UIControlEventTouchUpInside]; self.rejectTitleLabel = [[UILabel alloc] init]; - self.rejectTitleLabel.backgroundColor = ThemeService.theme.backgroundColor; + self.rejectTitleLabel.backgroundColor = ThemeService.shared.theme.backgroundColor; self.rejectTitleLabel.textColor = rejectButtonBorderColor; self.rejectTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.rejectTitleLabel.text = NSLocalizedStringFromTable(@"decline", @"Vector", nil); diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index ee608cae2..9f8472f13 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -415,10 +415,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextSecondaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -426,7 +426,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } @@ -469,7 +469,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (count) { UILabel *missedNotifAndUnreadBadgeLabel = [[UILabel alloc] init]; - missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; + missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.backgroundColor; missedNotifAndUnreadBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; if (count > 1000) { @@ -487,7 +487,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou missedNotifAndUnreadBadgeBgView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, bgViewWidth, 20)]; [missedNotifAndUnreadBadgeBgView.layer setCornerRadius:10]; - missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.theme.headerTextSecondaryColor; + missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.headerTextSecondaryColor; [missedNotifAndUnreadBadgeBgView addSubview:missedNotifAndUnreadBadgeLabel]; missedNotifAndUnreadBadgeLabel.center = missedNotifAndUnreadBadgeBgView.center; @@ -516,7 +516,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame { UIView *sectionHeader = [[UIView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = ThemeService.theme.headerBackgroundColor; + sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; NSInteger sectionBitwise = 0; UIImageView *chevronView; UIView *accessoryView; @@ -754,8 +754,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } // Apply the current UI theme. - networkLabel.textColor = ThemeService.theme.textPrimaryColor; - directoryServerLabel.textColor = ThemeService.theme.textSecondaryColor; + networkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + directoryServerLabel.textColor = ThemeService.shared.theme.textSecondaryColor; // Set the current directory server name directoryServerLabel.text = _publicRoomsDirectoryDataSource.directoryServerDisplayname; @@ -846,7 +846,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = ThemeService.theme.textSecondaryColor; + tableViewCell.textLabel.textColor = ThemeService.shared.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 23e085a44..3f4b6ae3a 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -159,17 +159,17 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Use the primary bg color for the recents table view in plain style. - self.recentsTableView.backgroundColor = ThemeService.theme.backgroundColor; - topview.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.recentsTableView.backgroundColor = ThemeService.shared.theme.backgroundColor; + topview.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; - [ThemeService.theme applyStyleOnSearchBar:tableSearchBar]; - [ThemeService.theme applyStyleOnSearchBar:self.recentsSearchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:tableSearchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:self.recentsSearchBar]; if (self.recentsTableView.dataSource) { @@ -180,7 +180,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -868,7 +868,7 @@ }]; UIImage *actionIcon = isDirect ? [UIImage imageNamed:@"directChatOff"] : [UIImage imageNamed:@"directChatOn"]; - directAction.backgroundColor = [MXKTools convertImageToPatternColor:isDirect ? @"directChatOff" : @"directChatOn" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + directAction.backgroundColor = [MXKTools convertImageToPatternColor:isDirect ? @"directChatOff" : @"directChatOn" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:directAction atIndex:0]; @@ -882,7 +882,7 @@ }]; actionIcon = isMuted ? [UIImage imageNamed:@"notifications"] : [UIImage imageNamed:@"notificationsOff"]; - muteAction.backgroundColor = [MXKTools convertImageToPatternColor:isMuted ? @"notifications" : @"notificationsOff" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + muteAction.backgroundColor = [MXKTools convertImageToPatternColor:isMuted ? @"notifications" : @"notificationsOff" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:muteAction atIndex:0]; // Favorites management @@ -907,7 +907,7 @@ }]; actionIcon = [UIImage imageNamed:@"favouriteOff"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"favouriteOff" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"favouriteOff" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } else @@ -919,7 +919,7 @@ }]; actionIcon = [UIImage imageNamed:@"favourite"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"favourite" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"favourite" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } @@ -932,7 +932,7 @@ }]; actionIcon = [UIImage imageNamed:@"priorityHigh"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityHigh" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityHigh" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } else @@ -944,7 +944,7 @@ }]; actionIcon = [UIImage imageNamed:@"priorityLow"]; - action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityLow" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + action.backgroundColor = [MXKTools convertImageToPatternColor:@"priorityLow" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:action atIndex:0]; } @@ -955,7 +955,7 @@ }]; actionIcon = [UIImage imageNamed:@"leave"]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"leave" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"leave" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:actionIcon.size]; [actions insertObject:leaveAction atIndex:0]; } @@ -1185,13 +1185,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -1413,7 +1413,7 @@ if (indexPath && [recentsDataSource isDraggableCellAt:indexPath]) { UITableViewCell *cell = [self.recentsTableView cellForRowAtIndexPath:indexPath]; - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // snapshot the cell UIGraphicsBeginImageContextWithOptions(cell.bounds.size, NO, 0); diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 4703015d4..368246820 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -48,13 +48,13 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeTableViewCellRendering]; - self.roomTitle.textColor = ThemeService.theme.textPrimaryColor; - self.lastEventDescription.textColor = ThemeService.theme.textSecondaryColor; - self.lastEventDate.textColor = ThemeService.theme.textSecondaryColor; - self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; + self.roomTitle.textColor = ThemeService.shared.theme.textPrimaryColor; + self.lastEventDescription.textColor = ThemeService.shared.theme.textSecondaryColor; + self.lastEventDate.textColor = ThemeService.shared.theme.textSecondaryColor; + self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.backgroundColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.shared.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -94,7 +94,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { // Force the default text color for the last message (cancel highlighted message color) NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:roomCellData.lastEventAttributedTextMessage]; - [lastEventDescription addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.textSecondaryColor range:NSMakeRange(0, lastEventDescription.length)]; + [lastEventDescription addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.textSecondaryColor range:NSMakeRange(0, lastEventDescription.length)]; self.lastEventDescription.attributedText = lastEventDescription; } else @@ -109,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; @@ -121,7 +121,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; } else { - self.missedNotifAndUnreadIndicator.backgroundColor = ThemeService.theme.headerTextSecondaryColor; + self.missedNotifAndUnreadIndicator.backgroundColor = ThemeService.shared.theme.headerTextSecondaryColor; } // Use bold font for the room title @@ -136,7 +136,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; } else { - self.lastEventDate.textColor = ThemeService.theme.textSecondaryColor; + self.lastEventDate.textColor = ThemeService.shared.theme.textSecondaryColor; // The room title is not bold anymore if ([UIFont respondsToSelector:@selector(systemFontOfSize:weight:)]) diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h index 53f5966d1..f68d498ae 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h @@ -38,7 +38,7 @@ limitations under the License. @property (nonatomic) NSUInteger selectedIndex; /** - The tint color for the section header (ThemeService.theme.accent by default). + The tint color for the section header (ThemeService.shared.theme.accent by default). */ @property (nonatomic) UIColor *sectionHeaderTintColor; diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index ae281daff..b992f663e 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -136,7 +136,7 @@ // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; - self.sectionHeaderTintColor = ThemeService.theme.tintColor; + self.sectionHeaderTintColor = ThemeService.shared.theme.tintColor; } - (void)viewDidLoad @@ -178,16 +178,16 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index e60a7b371..14426ff8c 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -52,16 +52,16 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - webView.backgroundColor = ThemeService.theme.backgroundColor; + webView.backgroundColor = ThemeService.shared.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 159fab7a8..a59dfe849 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -116,17 +116,17 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Use the primary bg color for the recents table view in plain style. - self.groupsTableView.backgroundColor = ThemeService.theme.backgroundColor; - topview.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.groupsTableView.backgroundColor = ThemeService.shared.theme.backgroundColor; + topview.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; - [ThemeService.theme applyStyleOnSearchBar:tableSearchBar]; - [ThemeService.theme applyStyleOnSearchBar:self.groupsSearchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:tableSearchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:self.groupsSearchBar]; if (self.groupsTableView.dataSource) { @@ -137,7 +137,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -424,13 +424,13 @@ { [super tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath]; - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -452,8 +452,8 @@ if (tableView.numberOfSections > 1) { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; - sectionHeader.mxkContentView.backgroundColor = ThemeService.theme.headerBackgroundColor; - sectionHeader.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + sectionHeader.mxkContentView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + sectionHeader.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; NSString* title = [self.dataSource tableView:tableView titleForHeaderInSection:section]; @@ -462,9 +462,9 @@ { NSString *roomCount = [NSString stringWithFormat:@" %tu", count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.headerTextPrimaryColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.headerTextPrimaryColor}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.headerTextSecondaryColor}]]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.headerTextSecondaryColor}]]; sectionHeader.mxkLabel.attributedText = mutableSectionTitle; } @@ -512,7 +512,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index ea7d2a04d..42cbe7505 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -113,22 +113,22 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.view.backgroundColor = ThemeService.theme.backgroundColor; - self.mainHeaderContainer.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.mainHeaderContainer.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - _groupName.textColor = ThemeService.theme.textPrimaryColor; + _groupName.textColor = ThemeService.shared.theme.textPrimaryColor; - _groupDescription.textColor = ThemeService.theme.baseTextSecondaryColor; + _groupDescription.textColor = ThemeService.shared.theme.baseTextSecondaryColor; _groupDescription.numberOfLines = 0; - self.inviteLabel.textColor = ThemeService.theme.baseTextSecondaryColor; + self.inviteLabel.textColor = ThemeService.shared.theme.baseTextSecondaryColor; self.inviteLabel.numberOfLines = 0; - self.separatorView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.separatorView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; @@ -140,11 +140,11 @@ if (_groupLongDescription) { - _groupLongDescription.textColor = ThemeService.theme.textSecondaryColor; + _groupLongDescription.textColor = ThemeService.shared.theme.textSecondaryColor; _groupLongDescription.tintColor = kRiotColorBlue; // Update HTML loading options - NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.theme.headerBackgroundColor]; + NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.shared.theme.headerBackgroundColor]; NSString *defaultCSS = [NSString stringWithFormat:@" \ pre,code { \ background-color: #%06lX; \ @@ -170,7 +170,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -481,7 +481,7 @@ _groupAvatar.layer.cornerRadius = _groupAvatar.frame.size.width / 2; _groupAvatar.clipsToBounds = YES; - _groupAvatar.defaultBackgroundColor = ThemeService.theme.headerBackgroundColor; + _groupAvatar.defaultBackgroundColor = ThemeService.shared.theme.headerBackgroundColor; } - (void)refreshGroupLongDescription diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 157e2ff2c..db0ab6aaf 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -145,21 +145,21 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.shared.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen CGFloat white = 1.0; - [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; @@ -172,7 +172,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. @@ -444,9 +444,9 @@ // Add blur mask programmatically tableViewMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the ThemeService.theme.backgroundColor. + // Consider the grayscale components of the ThemeService.shared.theme.backgroundColor. CGFloat white = 1.0; - [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -877,13 +877,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -914,8 +914,8 @@ if (section == invitedSection) { sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:MXKTableViewHeaderFooterWithLabel.defaultReuseIdentifier]; - sectionHeader.mxkContentView.backgroundColor = ThemeService.theme.headerBackgroundColor; - sectionHeader.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + sectionHeader.mxkContentView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + sectionHeader.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; sectionHeader.mxkLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleHeadline]; sectionHeader.mxkLabel.text = NSLocalizedStringFromTable(@"group_participants_invited_section", @"Vector", nil); @@ -985,7 +985,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } @@ -1205,7 +1205,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.shared.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 93efa76ce..8216249b4 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -126,16 +126,16 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.shared.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -146,7 +146,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. @@ -487,13 +487,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -588,7 +588,7 @@ // // }]; // -// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; +// leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_blue" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; // [actions insertObject:leaveAction atIndex:0]; // // return actions; @@ -606,7 +606,7 @@ // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.shared.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; diff --git a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m index 334f16395..0f11758c8 100644 --- a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m +++ b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m @@ -37,8 +37,8 @@ { [super customizeTableViewCellRendering]; - self.roomDisplayName.textColor = ThemeService.theme.textPrimaryColor; - self.roomTopic.textColor = ThemeService.theme.textSecondaryColor; + self.roomDisplayName.textColor = ThemeService.shared.theme.textPrimaryColor; + self.roomTopic.textColor = ThemeService.shared.theme.textSecondaryColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m index c6c6902cf..78d5fa770 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m @@ -122,7 +122,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 5c9985455..76fff5045 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -58,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = kRiotColorBlue; self.rightButton.backgroundColor = kRiotColorBlue; - self.noticeBadgeView.backgroundColor = ThemeService.theme.notificationMentionColor; + self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.m b/Riot/Modules/Communities/Views/GroupTableViewCell.m index ef8e7b0e7..a8d197120 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.m @@ -41,13 +41,13 @@ { [super customizeTableViewCellRendering]; - self.groupName.textColor = ThemeService.theme.textPrimaryColor; - self.groupDescription.textColor = ThemeService.theme.textSecondaryColor; - self.memberCount.textColor = ThemeService.theme.textSecondaryColor; + self.groupName.textColor = ThemeService.shared.theme.textPrimaryColor; + self.groupDescription.textColor = ThemeService.shared.theme.textSecondaryColor; + self.memberCount.textColor = ThemeService.shared.theme.textSecondaryColor; if (self.missedNotifAndUnreadBadgeLabel) { - self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; + self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.backgroundColor; } self.groupAvatar.defaultBackgroundColor = [UIColor clearColor]; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 2943ae0d2..558813569 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -104,12 +104,12 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -120,7 +120,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)didReceiveMemoryWarning @@ -288,13 +288,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 43c1bc86f..c77685d09 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -595,7 +595,7 @@ if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = ThemeService.theme.textSecondaryColor; + tableViewCell.textLabel.textColor = ThemeService.shared.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -742,10 +742,10 @@ NSString *roomCount = [NSString stringWithFormat:roomCountFormat, count]; NSMutableAttributedString *mutableSectionTitle = [[NSMutableAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; [mutableSectionTitle appendAttributedString:[[NSMutableAttributedString alloc] initWithString:roomCount - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextSecondaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.headerTextSecondaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]]; sectionTitle = mutableSectionTitle; @@ -753,7 +753,7 @@ else if (title) { sectionTitle = [[NSAttributedString alloc] initWithString:title - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.headerTextPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.headerTextPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:15.0]}]; } @@ -767,7 +767,7 @@ NSInteger sectionBitwise = 0; sectionHeader = [[UIView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = ThemeService.theme.headerBackgroundColor; + sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; frame.origin.x = 20; frame.origin.y = 5; @@ -970,7 +970,7 @@ } // Apply UI theme - checkboxLabel.textColor = ThemeService.theme.textPrimaryColor; + checkboxLabel.textColor = ThemeService.shared.theme.textPrimaryColor; // Set the right value of the tick box localContactsCheckbox.image = hideNonMatrixEnabledContacts ? [UIImage imageNamed:@"selection_tick"] : [UIImage imageNamed:@"selection_untick"]; diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 5a7aaab2f..dedcb530a 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -231,16 +231,16 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.headerView.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.contactNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.contactStatusLabel.textColor = ThemeService.theme.tintColor; + self.headerView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.contactNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.contactStatusLabel.textColor = ThemeService.shared.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -251,7 +251,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -735,8 +735,8 @@ [cellWithButton.mxkButton setTitle:title forState:UIControlStateNormal]; [cellWithButton.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.theme.textPrimaryColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.theme.textPrimaryColor forState:UIControlStateHighlighted]; [cellWithButton.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; @@ -779,13 +779,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index c9d6b5260..f715c5391 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -35,10 +35,10 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; + self.titleLabel.textColor = ThemeService.shared.theme.textPrimaryColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.shared.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index ae7306b37..f55ce88e9 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -53,8 +53,8 @@ [super customizeTableViewCellRendering]; // apply the vector colours - self.contactDisplayNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.contactInformationLabel.textColor = ThemeService.theme.textSecondaryColor; + self.contactDisplayNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.contactInformationLabel.textColor = ThemeService.shared.theme.textSecondaryColor; // Clear the default background color of a MXKImageView instance self.thumbnailView.defaultBackgroundColor = [UIColor clearColor]; @@ -223,11 +223,11 @@ } else if ((!contact.isMatrixContact && contact.phoneNumbers.count && !contact.emailAddresses.count)) { - image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:ThemeService.theme.tintColor]; + image = [AvatarGenerator imageFromText:@"#" withBackgroundColor:ThemeService.shared.theme.tintColor]; } else { - image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:ThemeService.theme.tintColor]; + image = [AvatarGenerator imageFromText:@"@" withBackgroundColor:ThemeService.shared.theme.tintColor]; } } diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index 78851ffd7..bcc35656e 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -28,13 +28,13 @@ { [super customizeViewRendering]; - self.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.textView.backgroundColor = ThemeService.theme.backgroundColor; - self.defaultTextColor = ThemeService.theme.textPrimaryColor; - self.cancelButton.tintColor = ThemeService.theme.tintColor; - self.verifyButton.tintColor = ThemeService.theme.tintColor; - self.blockButton.tintColor = ThemeService.theme.tintColor; - self.confirmVerifyButton.tintColor = ThemeService.theme.tintColor; + self.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.textView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor; + self.cancelButton.tintColor = ThemeService.shared.theme.tintColor; + self.verifyButton.tintColor = ThemeService.shared.theme.tintColor; + self.blockButton.tintColor = ThemeService.shared.theme.tintColor; + self.confirmVerifyButton.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 6c35be7c2..612297f11 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -71,15 +71,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.shared.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -89,7 +89,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -153,13 +153,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index 9152118a8..b853631cd 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -28,11 +28,11 @@ { [super customizeTableViewCellRendering]; - self.title.textColor = ThemeService.theme.textPrimaryColor; + self.title.textColor = ThemeService.shared.theme.textPrimaryColor; - self.message.textColor = ThemeService.theme.textSecondaryColor; + self.message.textColor = ThemeService.shared.theme.textSecondaryColor; - self.date.tintColor = ThemeService.theme.textSecondaryColor; + self.date.tintColor = ThemeService.shared.theme.textSecondaryColor; } + (CGFloat)heightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth @@ -76,7 +76,7 @@ if (bubbleData.isAttachmentWithThumbnail) { - self.attachmentImageView.backgroundColor = ThemeService.theme.backgroundColor; + self.attachmentImageView.backgroundColor = ThemeService.shared.theme.backgroundColor; [self.attachmentImageView setAttachmentThumb:bubbleData.attachment]; } diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index cd26647d1..4c69eab0f 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -66,7 +66,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.theme.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.shared.theme.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index 6d51eeadc..dc55572a9 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -78,15 +78,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.shared.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -96,7 +96,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -196,13 +196,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index fc2ced745..2423473ed 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.roomNameLabel.textColor = ThemeService.theme.textSecondaryColor; + self.roomNameLabel.textColor = ThemeService.shared.theme.textSecondaryColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index 41c3f7c76..ea0e14502 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.roomNameLabel.textColor = ThemeService.theme.textSecondaryColor; + self.roomNameLabel.textColor = ThemeService.shared.theme.textSecondaryColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index 20e1886d0..d4c420694 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -71,12 +71,12 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -87,7 +87,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -157,13 +157,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index fb91a4a33..5713ca837 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -115,7 +115,7 @@ UIImageView *backgroundImageView = self.backgroundImageView; if (backgroundImageView) { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.theme.matrixSearchBackgroundImageTintColor]; + UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; backgroundImageView.image = image; } } diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m index fa243ac3a..0ebf282f1 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m @@ -30,8 +30,8 @@ { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; - self.descriptionLabel.textColor = ThemeService.theme.textSecondaryColor; + self.titleLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.descriptionLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } - (void)render:(PublicRoomsDirectoryDataSource *)publicRoomsDirectoryDataSource diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index 09a2f0a58..44f788e91 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -29,7 +29,7 @@ { [super customizeTableViewCellRendering]; - self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; + self.titleLabel.textColor = ThemeService.shared.theme.textPrimaryColor; } - (void)layoutSubviews @@ -50,7 +50,7 @@ else { self.avatarImageView.image = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:ThemeService.theme.tintColor]; + withColor:ThemeService.shared.theme.tintColor]; } self.titleLabel.text = roomIdOrAlias; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index ae9b731ee..b8873d2b9 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -82,9 +82,9 @@ [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_home", @"Vector", nil); - [ThemeService.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.theme.tintColor; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.theme.tintColor; if (recentsDataSource) { @@ -416,7 +416,7 @@ } } - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; return cell; } diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 5bd5cc385..a9ccbd35f 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -66,13 +66,13 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; { [super customizeCollectionViewCellRendering]; - self.roomTitle.textColor = ThemeService.theme.textPrimaryColor; - self.roomTitle1.textColor = ThemeService.theme.textPrimaryColor; - self.roomTitle2.textColor = ThemeService.theme.textPrimaryColor; - self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.theme.backgroundColor; + self.roomTitle.textColor = ThemeService.shared.theme.textPrimaryColor; + self.roomTitle1.textColor = ThemeService.shared.theme.textPrimaryColor; + self.roomTitle2.textColor = ThemeService.shared.theme.textPrimaryColor; + self.missedNotifAndUnreadBadgeLabel.textColor = ThemeService.shared.theme.backgroundColor; // Prepare direct room border - CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); + CGColorRef directRoomBorderColor = CGColorCreateCopyWithAlpha(ThemeService.shared.theme.tintColor.CGColor, kDirectRoomBorderColorAlpha); [self.directRoomBorderView.layer setCornerRadius:self.directRoomBorderView.frame.size.width / 2]; self.directRoomBorderView.clipsToBounds = YES; @@ -81,7 +81,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; CFRelease(directRoomBorderColor); - self.editionArrowView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.editionArrowView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; self.roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } @@ -126,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -147,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.theme.notificationMentionColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m index 3a9f41332..bb7afbb8c 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m @@ -32,7 +32,7 @@ { [super customizeTableViewCellRendering]; - self.editionView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.editionView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; } - (void)prepareForReuse diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index 1d1eb9827..f74637cde 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -113,15 +113,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.assetsCollectionView.backgroundColor = ThemeService.theme.backgroundColor; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.assetsCollectionView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index db1814a29..ff48c46b0 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -182,20 +182,20 @@ static void *RecordingContext = &RecordingContext; - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.cameraVideoCaptureProgressView.progressColor = ThemeService.theme.backgroundColor; + self.cameraVideoCaptureProgressView.progressColor = ThemeService.shared.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor clearColor]; - self.userAlbumsTableView.backgroundColor = ThemeService.theme.backgroundColor; - self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.userAlbumsTableView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; } - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -343,12 +343,12 @@ static void *RecordingContext = &RecordingContext; if (self.cameraVideoCaptureProgressView.progressColor != [UIColor lightGrayColor]) { self.cameraVideoCaptureProgressView.progressColor = [UIColor lightGrayColor]; - self.cameraVideoCaptureProgressView.unprogressColor = ThemeService.theme.backgroundColor; + self.cameraVideoCaptureProgressView.unprogressColor = ThemeService.shared.theme.backgroundColor; } } - else if (self.cameraVideoCaptureProgressView.progressColor != ThemeService.theme.backgroundColor) + else if (self.cameraVideoCaptureProgressView.progressColor != ThemeService.shared.theme.backgroundColor) { - self.cameraVideoCaptureProgressView.progressColor = ThemeService.theme.backgroundColor; + self.cameraVideoCaptureProgressView.progressColor = ThemeService.shared.theme.backgroundColor; self.cameraVideoCaptureProgressView.unprogressColor = [UIColor lightGrayColor]; } @@ -1765,13 +1765,13 @@ static void *RecordingContext = &RecordingContext; - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m index 227ad4c98..2f2f1e40a 100644 --- a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m +++ b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.albumDisplayNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.albumCountLabel.textColor = ThemeService.theme.textSecondaryColor; + self.albumDisplayNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.albumCountLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } @end diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index 41e265d46..e094e6c85 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -60,10 +60,10 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell { [super customizeTableViewCellRendering]; - self.leftButton.backgroundColor = ThemeService.theme.tintColor; - self.rightButton.backgroundColor = ThemeService.theme.tintColor; + self.leftButton.backgroundColor = ThemeService.shared.theme.tintColor; + self.rightButton.backgroundColor = ThemeService.shared.theme.tintColor; - self.noticeBadgeView.backgroundColor = ThemeService.theme.notificationMentionColor; + self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m index dbc1cb419..7f490e176 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m @@ -339,7 +339,7 @@ double const kPublicRoomsDirectoryDataExpiration = 10; if (!tableViewCell) { tableViewCell = [[MXKTableViewCell alloc] init]; - tableViewCell.textLabel.textColor = ThemeService.theme.textSecondaryColor; + tableViewCell.textLabel.textColor = ThemeService.shared.theme.textSecondaryColor; tableViewCell.textLabel.font = [UIFont systemFontOfSize:15.0]; tableViewCell.selectionStyle = UITableViewCellSelectionStyleNone; } diff --git a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m index 71654cc32..4195b241b 100644 --- a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m +++ b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m @@ -38,9 +38,9 @@ { [super customizeTableViewCellRendering]; - self.roomDisplayName.textColor = ThemeService.theme.textPrimaryColor; - self.roomTopic.textColor = ThemeService.theme.textSecondaryColor; - self.memberCount.textColor = ThemeService.theme.textSecondaryColor; + self.roomDisplayName.textColor = ThemeService.shared.theme.textPrimaryColor; + self.roomTopic.textColor = ThemeService.shared.theme.textSecondaryColor; + self.memberCount.textColor = ThemeService.shared.theme.textSecondaryColor; _roomAvatar.defaultBackgroundColor = [UIColor clearColor]; } diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index d15d775d4..33637679b 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -59,12 +59,12 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.view.backgroundColor = ThemeService.theme.backgroundColor; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.backButton.tintColor = ThemeService.theme.tintColor; + self.backButton.tintColor = ThemeService.shared.theme.tintColor; } - (void)viewWillAppear:(BOOL)animated diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 21af3d0ed..03457f1dd 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -386,7 +386,7 @@ if ([component.event.eventId isEqualToString:self.room.accountData.readMarkerEventId]) { bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - 2, bubbleCell.bubbleOverlayContainer.frame.size.width, 2)]; - bubbleCell.readMarkerView.backgroundColor = ThemeService.theme.tintColor; + bubbleCell.readMarkerView.backgroundColor = ThemeService.shared.theme.tintColor; // Hide by default the marker, it will be shown and animated when the cell will be rendered. bubbleCell.readMarkerView.hidden = YES; bubbleCell.readMarkerView.tag = index; diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 1dc6d7e68..4fb62f934 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -110,12 +110,12 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) @@ -126,7 +126,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -193,13 +193,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index a0b50f358..95be2db5d 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -218,17 +218,17 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.memberHeaderView.backgroundColor = ThemeService.theme.baseColor; - self.roomMemberNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.roomMemberStatusLabel.textColor = ThemeService.theme.tintColor; + self.memberHeaderView.backgroundColor = ThemeService.shared.theme.baseColor; + self.roomMemberNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.roomMemberStatusLabel.textColor = ThemeService.shared.theme.tintColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -239,7 +239,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (BOOL)prefersStatusBarHidden @@ -360,7 +360,7 @@ } return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:ThemeService.theme.tintColor]; + withColor:ThemeService.shared.theme.tintColor]; } - (void)updateMemberInfo @@ -781,8 +781,8 @@ } else { - [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:ThemeService.theme.textPrimaryColor forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.theme.textPrimaryColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.theme.textPrimaryColor forState:UIControlStateHighlighted]; } [cellWithButton.mxkButton addTarget:self action:@selector(onActionButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; @@ -843,13 +843,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index ef14422b9..1ce43f6f2 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -157,21 +157,21 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.shared.theme.headerBorderColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; // Update the gradient view above the screen CGFloat white = 1.0; - [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; tableViewMaskLayer.colors = @[(__bridge id) transparentWhiteColor, (__bridge id) transparentWhiteColor, (__bridge id) opaqueWhiteColor]; @@ -184,7 +184,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } // This method is called when the viewcontroller is added or removed from a container view controller. @@ -575,9 +575,9 @@ // Add blur mask programmatically tableViewMaskLayer = [CAGradientLayer layer]; - // Consider the grayscale components of the ThemeService.theme.backgroundColor. + // Consider the grayscale components of the ThemeService.shared.theme.backgroundColor. CGFloat white = 1.0; - [ThemeService.theme.backgroundColor getWhite:&white alpha:nil]; + [ThemeService.shared.theme.backgroundColor getWhite:&white alpha:nil]; CGColorRef opaqueWhiteColor = [UIColor colorWithWhite:white alpha:1.0].CGColor; CGColorRef transparentWhiteColor = [UIColor colorWithWhite:white alpha:0].CGColor; @@ -1175,13 +1175,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -1215,7 +1215,7 @@ if (section == invitedSection) { sectionHeader = [[UIView alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, 30)]; - sectionHeader.backgroundColor = ThemeService.theme.headerBackgroundColor; + sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; CGRect frame = sectionHeader.frame; frame.origin.x = 20; @@ -1223,7 +1223,7 @@ frame.size.width = sectionHeader.frame.size.width - 10; frame.size.height -= 10; UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame]; - headerLabel.textColor = ThemeService.theme.textPrimaryColor; + headerLabel.textColor = ThemeService.shared.theme.textPrimaryColor; headerLabel.font = [UIFont boldSystemFontOfSize:15.0]; headerLabel.backgroundColor = [UIColor clearColor]; @@ -1327,7 +1327,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } @@ -1684,19 +1684,19 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = ThemeService.theme.tintColor; - searchBar.tintColor = ThemeService.theme.tintColor; + searchBar.barTintColor = searchBar.tintColor = ThemeService.shared.theme.tintColor; + searchBar.tintColor = ThemeService.shared.theme.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.shared.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = ThemeService.theme.tintColor; + leftImageView.tintColor = ThemeService.shared.theme.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -1707,8 +1707,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: ThemeService.theme.tintColor, - NSForegroundColorAttributeName: ThemeService.theme.tintColor}]; + NSUnderlineColorAttributeName: ThemeService.shared.theme.tintColor, + NSForegroundColorAttributeName: ThemeService.shared.theme.tintColor}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index b861b80a2..432d5f6c9 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -94,20 +94,20 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - self.overlayView.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.overlayView.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; self.overlayView.alpha = 1.0; - self.titleLabel.textColor = ThemeService.theme.textPrimaryColor; - self.containerView.backgroundColor = ThemeService.theme.backgroundColor; + self.titleLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.containerView.backgroundColor = ThemeService.shared.theme.backgroundColor; // Check the table view style to select its bg color. - self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.receiptsTableView.backgroundColor = ((self.receiptsTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); - self.closeButton.tintColor = ThemeService.theme.tintColor; + self.closeButton.tintColor = ThemeService.shared.theme.tintColor; if (self.receiptsTableView.dataSource) { @@ -118,7 +118,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -196,8 +196,8 @@ { MXKReadReceiptTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:[MXKReadReceiptTableViewCell defaultReuseIdentifier] forIndexPath:indexPath]; - cell.displayNameLabel.textColor = ThemeService.theme.textPrimaryColor; - cell.receiptDescriptionLabel.textColor = ThemeService.theme.textSecondaryColor; + cell.displayNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + cell.receiptDescriptionLabel.textColor = ThemeService.shared.theme.textSecondaryColor; if (indexPath.row < self.roomMembers.count) { @@ -224,9 +224,9 @@ NSString *receiptReadText = NSLocalizedStringFromTable(@"receipt_status_read", @"Vector", nil); NSString *receiptTimeText = [(MXKEventFormatter*)self.session.roomSummaryUpdateDelegate dateStringFromTimestamp:self.receipts[indexPath.row].ts withTime:YES]; - NSMutableAttributedString *receiptDescription = [[NSMutableAttributedString alloc] initWithString:receiptReadText attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textSecondaryColor, NSFontAttributeName : [UIFont boldSystemFontOfSize:15]}]; + NSMutableAttributedString *receiptDescription = [[NSMutableAttributedString alloc] initWithString:receiptReadText attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textSecondaryColor, NSFontAttributeName : [UIFont boldSystemFontOfSize:15]}]; - [receiptDescription appendAttributedString:[[NSAttributedString alloc] initWithString:receiptTimeText attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textSecondaryColor, NSFontAttributeName : [UIFont systemFontOfSize:15]}]]; + [receiptDescription appendAttributedString:[[NSAttributedString alloc] initWithString:receiptTimeText attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textSecondaryColor, NSFontAttributeName : [UIFont systemFontOfSize:15]}]]; cell.receiptDescriptionLabel.attributedText = receiptDescription; } @@ -240,13 +240,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index c15949e1a..c68afb7de 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -418,25 +418,25 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; self.navigationController.navigationBar.translucent = YES; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Prepare jump to last unread banner - self.jumpToLastUnreadBannerContainer.backgroundColor = ThemeService.theme.backgroundColor; - self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: ThemeService.theme.textPrimaryColor, NSForegroundColorAttributeName: ThemeService.theme.textPrimaryColor}]; + self.jumpToLastUnreadBannerContainer.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.jumpToLastUnreadLabel.attributedText = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_jump_to_first_unread", @"Vector", nil) attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSUnderlineColorAttributeName: ThemeService.shared.theme.textPrimaryColor, NSForegroundColorAttributeName: ThemeService.shared.theme.textPrimaryColor}]; - self.expandedHeaderContainer.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.previewHeaderContainer.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.expandedHeaderContainer.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.previewHeaderContainer.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - missedDiscussionsBadgeLabel.textColor = ThemeService.theme.backgroundColor; + missedDiscussionsBadgeLabel.textColor = ThemeService.shared.theme.backgroundColor; missedDiscussionsBadgeLabel.font = [UIFont boldSystemFontOfSize:14]; missedDiscussionsBadgeLabel.backgroundColor = [UIColor clearColor]; // Check the table view style to select its bg color. - self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.bubblesTableView.backgroundColor = ((self.bubblesTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.bubblesTableView.backgroundColor; if (self.bubblesTableView.dataSource) @@ -447,7 +447,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)didReceiveMemoryWarning @@ -1752,7 +1752,7 @@ else { previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:ThemeService.theme.tintColor]; + withColor:ThemeService.shared.theme.tintColor]; } } @@ -3338,13 +3338,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -4230,11 +4230,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.theme.notificationMentionColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.theme.notificationUnreadColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationUnreadColor; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 4aca0ba4d..3ff3145d6 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -69,7 +69,7 @@ if (cellData) { // Highlight the search pattern - [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.theme.tintColor andFont:patternFont]; + [cellData highlightPatternInTextMessage:self.searchText withForegroundColor:ThemeService.shared.theme.tintColor andFont:patternFont]; // Use profile information as data to display MXSearchUserProfile *userProfile = result.context.profileInfo[result.result.sender]; diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index 03e5b73fe..51c74d6a1 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -72,15 +72,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.shared.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -90,7 +90,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -146,13 +146,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index a6698ab9c..a13185f45 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -73,15 +73,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.searchTableView.backgroundColor = ((self.searchTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.searchTableView.backgroundColor; - self.noResultsLabel.textColor = ThemeService.theme.backgroundColor; + self.noResultsLabel.textColor = ThemeService.shared.theme.backgroundColor; if (self.searchTableView.dataSource) { @@ -91,7 +91,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -173,13 +173,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index 414848622..674c4abc7 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -80,7 +80,7 @@ UIImageView *backgroundImageView = self.backgroundImageView; if (backgroundImageView) { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.theme.matrixSearchBackgroundImageTintColor]; + UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; backgroundImageView.image = image; } } diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 54810537c..609422b8c 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -266,12 +266,12 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -282,7 +282,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -2053,7 +2053,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { // Customize label style UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view; - tableViewHeaderFooterView.textLabel.textColor = ThemeService.theme.textPrimaryColor; + tableViewHeaderFooterView.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15]; } } @@ -2178,7 +2178,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomPhotoCell.mxkImageView.defaultBackgroundColor = [UIColor clearColor]; roomPhotoCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_photo", @"Vector", nil); - roomPhotoCell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + roomPhotoCell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; if (updatedItemsDict[kRoomSettingsAvatarKey]) { @@ -2213,16 +2213,16 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti topicTextView.text = mxRoomState.topic; } - topicTextView.tintColor = ThemeService.theme.tintColor; + topicTextView.tintColor = ThemeService.shared.theme.tintColor; topicTextView.font = [UIFont systemFontOfSize:15]; topicTextView.bounces = NO; topicTextView.delegate = self; // disable the edition if the user cannot update it topicTextView.editable = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomTopic]); - topicTextView.textColor = ThemeService.theme.textSecondaryColor; + topicTextView.textColor = ThemeService.shared.theme.textSecondaryColor; - topicTextView.keyboardAppearance = ThemeService.theme.keyboardAppearance; + topicTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance; cell = roomTopicCell; } @@ -2235,14 +2235,14 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti roomNameCell.mxkTextFieldTrailingConstraint.constant = 15; roomNameCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_room_name", @"Vector", nil); - roomNameCell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + roomNameCell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; roomNameCell.accessoryType = UITableViewCellAccessoryNone; roomNameCell.accessoryView = nil; nameTextField = roomNameCell.mxkTextField; - nameTextField.tintColor = ThemeService.theme.tintColor; + nameTextField.tintColor = ThemeService.shared.theme.tintColor; nameTextField.font = [UIFont systemFontOfSize:17]; nameTextField.borderStyle = UITextBorderStyleNone; nameTextField.textAlignment = NSTextAlignmentRight; @@ -2259,7 +2259,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // disable the edition if the user cannot update it nameTextField.userInteractionEnabled = (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomName]); - nameTextField.textColor = ThemeService.theme.textSecondaryColor; + nameTextField.textColor = ThemeService.shared.theme.textSecondaryColor; // Add a "textFieldDidChange" notification method to the text field control. [nameTextField addTarget:self action:@selector(onTextFieldUpdate:) forControlEvents:UIControlEventEditingChanged]; @@ -2280,10 +2280,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti NSArray *labels = roomTagCell.labels; UILabel *label; label = labels[0]; - label.textColor = ThemeService.theme.textPrimaryColor; + label.textColor = ThemeService.shared.theme.textPrimaryColor; label.text = NSLocalizedStringFromTable(@"room_details_favourite_tag", @"Vector", nil); label = labels[1]; - label.textColor = ThemeService.theme.textPrimaryColor; + label.textColor = ThemeService.shared.theme.textPrimaryColor; label.text = NSLocalizedStringFromTable(@"room_details_low_priority_tag", @"Vector", nil); if (updatedItemsDict[kRoomSettingsTagKey]) @@ -2320,7 +2320,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti [leaveCell.mxkButton setTitle:title forState:UIControlStateNormal]; [leaveCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [leaveCell.mxkButton setTintColor:ThemeService.theme.tintColor]; + [leaveCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; leaveCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [leaveCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2499,17 +2499,17 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressTextField = addAddressCell.mxkTextField; addAddressTextField.placeholder = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_details_new_address_placeholder", @"Vector", nil), self.mainSession.matrixRestClient.homeserverSuffix]; - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { addAddressTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:addAddressTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } addAddressTextField.userInteractionEnabled = YES; addAddressTextField.text = currentValue; - addAddressTextField.textColor = ThemeService.theme.textSecondaryColor; + addAddressTextField.textColor = ThemeService.shared.theme.textSecondaryColor; - addAddressTextField.tintColor = ThemeService.theme.tintColor; + addAddressTextField.tintColor = ThemeService.shared.theme.tintColor; addAddressTextField.font = [UIFont systemFontOfSize:17]; addAddressTextField.borderStyle = UITextBorderStyleNone; addAddressTextField.textAlignment = NSTextAlignmentLeft; @@ -2525,7 +2525,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *addressCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; addressCell.textLabel.font = [UIFont systemFontOfSize:16]; - addressCell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + addressCell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; addressCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; addressCell.accessoryView = nil; addressCell.accessoryType = UITableViewCellAccessoryNone; @@ -2590,17 +2590,17 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addGroupTextField = addCommunityCell.mxkTextField; addGroupTextField.placeholder = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_details_new_flair_placeholder", @"Vector", nil), self.mainSession.matrixRestClient.homeserverSuffix]; - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { addGroupTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:addGroupTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } addGroupTextField.userInteractionEnabled = YES; addGroupTextField.text = currentValue; - addGroupTextField.textColor = ThemeService.theme.textSecondaryColor; + addGroupTextField.textColor = ThemeService.shared.theme.textSecondaryColor; - addGroupTextField.tintColor = ThemeService.theme.tintColor; + addGroupTextField.tintColor = ThemeService.shared.theme.tintColor; addGroupTextField.font = [UIFont systemFontOfSize:17]; addGroupTextField.borderStyle = UITextBorderStyleNone; addGroupTextField.textAlignment = NSTextAlignmentLeft; @@ -2616,7 +2616,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *communityCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; communityCell.textLabel.font = [UIFont systemFontOfSize:16]; - communityCell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + communityCell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; communityCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; communityCell.accessoryView = nil; communityCell.accessoryType = UITableViewCellAccessoryNone; @@ -2634,7 +2634,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti UITableViewCell *addressCell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsAddressCellViewIdentifier forIndexPath:indexPath]; addressCell.textLabel.font = [UIFont systemFontOfSize:16]; - addressCell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + addressCell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; addressCell.textLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; addressCell.accessoryView = nil; addressCell.accessoryType = UITableViewCellAccessoryNone; @@ -2656,11 +2656,11 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_room_id", @"Vector", nil); - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.detailTextLabel.font = [UIFont systemFontOfSize:15]; cell.detailTextLabel.text = mxRoomState.roomId; - cell.detailTextLabel.textColor = ThemeService.theme.textSecondaryColor; + cell.detailTextLabel.textColor = ThemeService.shared.theme.textSecondaryColor; cell.detailTextLabel.lineBreakMode = NSLineBreakByTruncatingMiddle; cell.selectionStyle = UITableViewCellSelectionStyleNone; @@ -2672,7 +2672,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti MXKTableViewCellWithLabelAndSwitch *roomBlacklistUnverifiedDevicesCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; [roomBlacklistUnverifiedDevicesCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevice:) forControlEvents:UIControlEventValueChanged]; - roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + roomBlacklistUnverifiedDevicesCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; roomBlacklistUnverifiedDevicesCell.mxkLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_blacklist_unverified_devices", @"Vector", nil); @@ -2719,7 +2719,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_enabled", @"Vector", nil); - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -2753,7 +2753,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.textLabel.font = [UIFont systemFontOfSize:17]; cell.textLabel.numberOfLines = 0; cell.textLabel.text = NSLocalizedStringFromTable(@"room_details_advanced_e2e_encryption_disabled", @"Vector", nil); - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.selectionStyle = UITableViewCellSelectionStyleNone; } @@ -2801,9 +2801,9 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell.mxkLabelLeadingConstraint.constant = cell.separatorInset.left; cell.mxkSwitchTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - cell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + cell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventValueChanged]; // Reset the stored `directoryVisibilitySwitch` if the corresponding cell is reused. @@ -2822,13 +2822,13 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -3117,7 +3117,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti }]; - removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; + removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:removeAction atIndex:0]; } } @@ -3132,7 +3132,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti }]; - removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; + removeAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(44, 44) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:removeAction atIndex:0]; } diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m index d15818a8a..5f575c745 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - _label.textColor = ThemeService.theme.textPrimaryColor; + _label.textColor = ThemeService.shared.theme.textPrimaryColor; } - (void)setEnabled:(BOOL)enabled diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m index 36b34e556..deecdd99e 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m @@ -37,8 +37,8 @@ { [super customizeTableViewCellRendering]; - _label.textColor = ThemeService.theme.textPrimaryColor; - _textView.textColor = ThemeService.theme.textPrimaryColor; + _label.textColor = ThemeService.shared.theme.textPrimaryColor; + _textView.textColor = ThemeService.shared.theme.textPrimaryColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 7a88f7607..c5ebadf5a 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -112,10 +112,10 @@ { [super customizeViewRendering]; - self.separatorView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.separatorView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; if (self.messageLabel.textColor != kRiotColorPinkRed) { - self.messageLabel.textColor = ThemeService.theme.textSecondaryColor; + self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } } @@ -260,12 +260,12 @@ // Display the string in white on pink red NSRange wholeString = NSMakeRange(0, onGoingConferenceCallAttibutedString.length); - [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.backgroundColor range:wholeString]; + [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.backgroundColor range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:kRiotColorPinkRed range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = onGoingConferenceCallAttibutedString; - self.messageTextView.tintColor = ThemeService.theme.backgroundColor; + self.messageTextView.tintColor = ThemeService.shared.theme.backgroundColor; self.messageTextView.hidden = NO; self.backgroundColor = kRiotColorPinkRed; @@ -356,7 +356,7 @@ [roomReplacementAttributedString appendAttributedString:roomLinkAttributedString]; NSRange wholeStringRange = NSMakeRange(0, roomReplacementAttributedString.length); - [roomReplacementAttributedString addAttribute:NSForegroundColorAttributeName value:ThemeService.theme.textPrimaryColor range:wholeStringRange]; + [roomReplacementAttributedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.textPrimaryColor range:wholeStringRange]; self.messageTextView.attributedText = roomReplacementAttributedString; } @@ -365,7 +365,7 @@ self.messageTextView.text = NSLocalizedStringFromTable(@"room_replacement_information", @"Vector", nil); } - self.messageTextView.tintColor = ThemeService.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.shared.theme.textPrimaryColor; self.messageTextView.hidden = NO; self.messageTextView.backgroundColor = [UIColor clearColor]; @@ -432,13 +432,13 @@ message2 = [[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"room_resource_usage_limit_reached_message_2", @"Vector", nil) attributes:@{ NSFontAttributeName: [UIFont boldSystemFontOfSize:fontSize], - NSForegroundColorAttributeName: ThemeService.theme.backgroundColor + NSForegroundColorAttributeName: ThemeService.shared.theme.backgroundColor }]; } NSDictionary *attributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:fontSize], - NSForegroundColorAttributeName: ThemeService.theme.backgroundColor + NSForegroundColorAttributeName: ThemeService.shared.theme.backgroundColor }; NSDictionary *messageContact2LinkAttributes; @@ -482,7 +482,7 @@ [attributedText appendAttributedString:messageContact3]; self.messageTextView.attributedText = attributedText; - self.messageTextView.tintColor = ThemeService.theme.backgroundColor; + self.messageTextView.tintColor = ThemeService.shared.theme.backgroundColor; self.messageTextView.hidden = NO; if (hardLimit) @@ -535,7 +535,7 @@ [self.messageTextView resignFirstResponder]; self.messageTextView.hidden = YES; - self.messageLabel.textColor = ThemeService.theme.textSecondaryColor; + self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor; objc_removeAssociatedObjects(self.messageTextView); } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index b5ebb38d2..ba01ef0b5 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index e831f0bb0..8686be688 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m index 86339cb3a..712385152 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index c14a48e76..605d9e9a3 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index f9cad605a..83bff1cf7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index 14252dccd..5078a9405 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m index 5ba8eeb40..56b0db94c 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m index b9aa838d8..15ab0389e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m index e8b42d519..a15817d01 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m @@ -41,7 +41,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)prepareForReuse diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m index ffa7060b0..c19773bf9 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m @@ -30,7 +30,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)layoutSubviews diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m index 27a2289bd..b93c8be3a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index 73461a2b0..8cf27a17f 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -38,9 +38,9 @@ NSString *const kRoomMembershipExpandedBubbleCellTapOnCollapseButton = @"kRoomMe { [super customizeTableViewCellRendering]; - self.separatorView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.separatorView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - [self.collapseButton setTintColor:ThemeService.theme.tintColor]; + [self.collapseButton setTintColor:ThemeService.shared.theme.tintColor]; self.collapseButton.titleLabel.font = [UIFont systemFontOfSize:14]; } diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m index 12da4a91a..63262f645 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m index 524e0e519..4ebebc70d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m @@ -27,8 +27,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index 44ad81b97..f24ac2f82 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index cb3bc41a9..25911ddf2 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -26,11 +26,11 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m index c953a24ac..b60dac677 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index fff5b9005..bff6e2f13 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.userNameLabel.textColor = ThemeService.theme.textPrimaryColor; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.userNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m index 71491b57b..85d4afb55 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m @@ -26,8 +26,8 @@ { [super customizeTableViewCellRendering]; - self.paginationLabel.textColor = ThemeService.theme.tintColor; - self.paginationSeparatorView.backgroundColor = ThemeService.theme.tintColor; + self.paginationLabel.textColor = ThemeService.shared.theme.tintColor; + self.paginationSeparatorView.backgroundColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXKCellData *)cellData diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m index 9af0586e3..1e0ffeb61 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m @@ -26,7 +26,7 @@ { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.tintColor; + self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m index 5a866b7b3..dbcb44b50 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m @@ -58,8 +58,8 @@ static CGFloat const kCustomBackgroundCornerRadius = 5.0; { [super customizeTableViewCellRendering]; - self.messageTextView.tintColor = ThemeService.theme.textPrimaryColor; - self.customBackgroundView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.messageTextView.tintColor = ThemeService.shared.theme.textPrimaryColor; + self.customBackgroundView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; } @end diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m index e84ac884d..f63b5180c 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m @@ -45,8 +45,8 @@ arrowMaskLayer.path = path.CGPath; self.arrowView.layer.mask = arrowMaskLayer; - self.arrowView.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.descriptionView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.arrowView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.descriptionView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; [self.descriptionView.layer setCornerRadius:10]; } diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index c96230f45..3f30e3987 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -25,11 +25,11 @@ { [super customizeViewRendering]; - self.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.textView.backgroundColor = ThemeService.theme.backgroundColor; - self.textView.textColor = ThemeService.theme.textPrimaryColor; - self.redactButton.tintColor = ThemeService.theme.tintColor; - self.closeButton.tintColor = ThemeService.theme.tintColor; + self.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.textView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.textView.textColor = ThemeService.shared.theme.textPrimaryColor; + self.redactButton.tintColor = ThemeService.shared.theme.tintColor; + self.closeButton.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 777ac8255..d3dce27e5 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -48,11 +48,11 @@ // Remove default toolbar background color self.backgroundColor = [UIColor clearColor]; - self.separatorView.backgroundColor = ThemeService.theme.headerTextSecondaryColor; + self.separatorView.backgroundColor = ThemeService.shared.theme.headerTextSecondaryColor; self.disabledReasonTextView.font = [UIFont systemFontOfSize:15]; - self.disabledReasonTextView.textColor = ThemeService.theme.textPrimaryColor; - self.disabledReasonTextView.tintColor = ThemeService.theme.tintColor; + self.disabledReasonTextView.textColor = ThemeService.shared.theme.textPrimaryColor; + self.disabledReasonTextView.tintColor = ThemeService.shared.theme.tintColor; self.disabledReasonTextView.editable = NO; self.disabledReasonTextView.scrollEnabled = NO; } diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index e88329627..577592a41 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -72,8 +72,8 @@ self.rightInputToolbarButton.hidden = YES; - [self.rightInputToolbarButton setTitleColor:ThemeService.theme.tintColor forState:UIControlStateNormal]; - [self.rightInputToolbarButton setTitleColor:ThemeService.theme.tintColor forState:UIControlStateHighlighted]; + [self.rightInputToolbarButton setTitleColor:ThemeService.shared.theme.tintColor forState:UIControlStateNormal]; + [self.rightInputToolbarButton setTitleColor:ThemeService.shared.theme.tintColor forState:UIControlStateHighlighted]; self.isEncryptionEnabled = _isEncryptionEnabled; } @@ -87,7 +87,7 @@ // Remove default toolbar background color self.backgroundColor = [UIColor clearColor]; - self.separatorView.backgroundColor = ThemeService.theme.headerTextSecondaryColor; + self.separatorView.backgroundColor = ThemeService.shared.theme.headerTextSecondaryColor; // Custom the growingTextView display growingTextView.layer.cornerRadius = 0; @@ -95,10 +95,10 @@ growingTextView.backgroundColor = [UIColor clearColor]; growingTextView.font = [UIFont systemFontOfSize:15]; - growingTextView.textColor = ThemeService.theme.textPrimaryColor; - growingTextView.tintColor = ThemeService.theme.tintColor; + growingTextView.textColor = ThemeService.shared.theme.textPrimaryColor; + growingTextView.tintColor = ThemeService.shared.theme.tintColor; - growingTextView.internalTextView.keyboardAppearance = ThemeService.theme.keyboardAppearance; + growingTextView.internalTextView.keyboardAppearance = ThemeService.shared.theme.keyboardAppearance; } #pragma mark - diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index 4709c4bf8..cd2972cbb 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -40,19 +40,19 @@ [super layoutSubviews]; self.membersListIcon.image = [MXKTools paintImage:self.membersListIcon.image - withColor:ThemeService.theme.tintColor]; + withColor:ThemeService.shared.theme.tintColor]; // TODO: paintImage does not work here because addParticipantIcon has 2 colors // self.addParticipantIcon.image = [MXKTools paintImage:self.addParticipantIcon.image -// withColor:ThemeService.theme.accent]; +// withColor:ThemeService.shared.theme.accent]; } -(void)customizeViewRendering { [super customizeViewRendering]; - self.roomTopic.textColor = ThemeService.theme.baseTextSecondaryColor; - self.roomMembers.textColor = ThemeService.theme.tintColor; + self.roomTopic.textColor = ThemeService.shared.theme.baseTextSecondaryColor; + self.roomMembers.textColor = ThemeService.shared.theme.tintColor; } - (void)refreshDisplay @@ -131,7 +131,7 @@ self.roomAvatar.layer.cornerRadius = self.roomAvatar.frame.size.width / 2; self.roomAvatar.clipsToBounds = YES; - self.roomAvatar.defaultBackgroundColor = ThemeService.theme.headerBackgroundColor; + self.roomAvatar.defaultBackgroundColor = ThemeService.shared.theme.headerBackgroundColor; // Force the layout of subviews to update the position of 'bottomBorderView' which is used to define the actual height of the preview container. [self layoutIfNeeded]; diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index f9f1970d8..fc4f74a7b 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -64,28 +64,28 @@ [super customizeViewRendering]; // Use same color as navigation bar - self.mainHeaderBackground.backgroundColor = ThemeService.theme.baseColor; + self.mainHeaderBackground.backgroundColor = ThemeService.shared.theme.baseColor; - self.roomTopic.textColor = ThemeService.theme.baseTextSecondaryColor; + self.roomTopic.textColor = ThemeService.shared.theme.baseTextSecondaryColor; - self.roomMembers.textColor = ThemeService.theme.tintColor; + self.roomMembers.textColor = ThemeService.shared.theme.tintColor; - self.previewLabel.textColor = ThemeService.theme.baseTextSecondaryColor; + self.previewLabel.textColor = ThemeService.shared.theme.baseTextSecondaryColor; self.previewLabel.numberOfLines = 0; - self.subNoticeLabel.textColor = ThemeService.theme.textSecondaryColor; + self.subNoticeLabel.textColor = ThemeService.shared.theme.textSecondaryColor; self.subNoticeLabel.numberOfLines = 0; - self.bottomBorderView.backgroundColor = ThemeService.theme.headerBackgroundColor; + self.bottomBorderView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; - self.leftButton.backgroundColor = ThemeService.theme.tintColor; + self.leftButton.backgroundColor = ThemeService.shared.theme.tintColor; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - self.rightButton.backgroundColor = ThemeService.theme.tintColor; + self.rightButton.backgroundColor = ThemeService.shared.theme.tintColor; } - (void)refreshDisplay @@ -103,7 +103,7 @@ toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:ThemeService.theme.tintColor] + withColor:ThemeService.shared.theme.tintColor] mediaManager:self.mxRoom.mxSession.mediaManager]; } else @@ -249,7 +249,7 @@ self.roomAvatar.layer.cornerRadius = self.roomAvatar.frame.size.width / 2; self.roomAvatar.clipsToBounds = YES; - self.roomAvatar.defaultBackgroundColor = ThemeService.theme.headerBackgroundColor; + self.roomAvatar.defaultBackgroundColor = ThemeService.shared.theme.headerBackgroundColor; // Force the layout of subviews to update the position of 'bottomBorderView' which is used to define the actual height of the preview container. [self layoutIfNeeded]; diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 8eddd61e9..7b38994ae 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -73,7 +73,7 @@ [super layoutSubviews]; self.roomDetailsIconImageView.image = [MXKTools paintImage:self.roomDetailsIconImageView.image - withColor:ThemeService.theme.tintColor]; + withColor:ThemeService.shared.theme.tintColor]; if (self.superview) { @@ -138,8 +138,8 @@ [super customizeViewRendering]; // Use same color as navigation bar - self.backgroundColor = ThemeService.theme.baseColor; - self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? ThemeService.theme.baseTextPrimaryColor : ThemeService.theme.textSecondaryColor); + self.backgroundColor = ThemeService.shared.theme.baseColor; + self.displayNameTextField.textColor = (self.mxRoom.summary.displayname.length ? ThemeService.shared.theme.baseTextPrimaryColor : ThemeService.shared.theme.textSecondaryColor); } - (void)setRoomPreviewData:(RoomPreviewData *)roomPreviewData @@ -164,11 +164,11 @@ if (!self.displayNameTextField.text.length) { self.displayNameTextField.text = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"]; - self.displayNameTextField.textColor = ThemeService.theme.textSecondaryColor; + self.displayNameTextField.textColor = ThemeService.shared.theme.textSecondaryColor; } else { - self.displayNameTextField.textColor = ThemeService.theme.baseTextPrimaryColor; + self.displayNameTextField.textColor = ThemeService.shared.theme.baseTextPrimaryColor; } } } diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index 711e8b051..97c5cf0de 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -120,12 +120,12 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -136,7 +136,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -226,13 +226,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m index e897148bb..dfa59ad8e 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m @@ -25,7 +25,7 @@ { [super customizeTableViewCellRendering]; - self.detailDescLabel.textColor = ThemeService.theme.textSecondaryColor; + self.detailDescLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } - (void)render:(id)cellData diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 823415e1c..3c1ceeabe 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -29,7 +29,7 @@ { [super customizeTableViewCellRendering]; - self.descLabel.textColor = ThemeService.theme.textPrimaryColor; + self.descLabel.textColor = ThemeService.shared.theme.textPrimaryColor; } - (void)layoutSubviews @@ -64,7 +64,7 @@ withType:nil andImageOrientation:UIImageOrientationUp previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] - withColor:ThemeService.theme.tintColor] + withColor:ThemeService.shared.theme.tintColor] mediaManager:cellData.mediaManager]; } else diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 4774d1cd2..47731c963 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -64,7 +64,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_rooms", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.theme.tintColor; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.theme.tintColor; if ([self.dataSource isKindOfClass:RecentsDataSource.class]) { diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 17db945e3..1366854c7 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -109,7 +109,7 @@ static CGFloat const kTextFontSize = 15.0; - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } #pragma mark - Private @@ -123,22 +123,22 @@ static CGFloat const kTextFontSize = 15.0; - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; } - (void)setupStringAttributes { self.normalStringAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize], - NSForegroundColorAttributeName: ThemeService.theme.textPrimaryColor + NSForegroundColorAttributeName: ThemeService.shared.theme.textPrimaryColor }; self.emphasizeStringAttributes = @{ NSFontAttributeName: [UIFont systemFontOfSize:kTextFontSize weight:UIFontWeightBold], - NSForegroundColorAttributeName: ThemeService.theme.textPrimaryColor + NSForegroundColorAttributeName: ThemeService.shared.theme.textPrimaryColor }; } @@ -166,9 +166,9 @@ static CGFloat const kTextFontSize = 15.0; self.deactivateAcccountButton.titleLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters; self.deactivateAcccountButton.layer.masksToBounds = YES; - self.deactivateAcccountButton.backgroundColor = ThemeService.theme.tintColor; + self.deactivateAcccountButton.backgroundColor = ThemeService.shared.theme.tintColor; [self.deactivateAcccountButton setTitle:NSLocalizedStringFromTable(@"deactivate_account_validate_action", @"Vector", nil) forState:UIControlStateNormal]; - [self.deactivateAcccountButton setTitleColor:ThemeService.theme.headerTextSecondaryColor forState:UIControlStateDisabled]; + [self.deactivateAcccountButton setTitleColor:ThemeService.shared.theme.headerTextSecondaryColor forState:UIControlStateDisabled]; } - (void)setupDeactivateAccountInfosLabel diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index 77170483f..915de9864 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -69,15 +69,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - [ThemeService.theme applyStyleOnSearchBar:self.searchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. - self.tableView.backgroundColor = ThemeService.theme.backgroundColor; - topview.backgroundColor = ThemeService.theme.backgroundColor; + self.tableView.backgroundColor = ThemeService.shared.theme.backgroundColor; + topview.backgroundColor = ThemeService.shared.theme.backgroundColor; if (self.tableView.dataSource) { @@ -87,7 +87,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -114,15 +114,15 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; - cell.detailTextLabel.textColor = ThemeService.theme.textSecondaryColor; - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + cell.detailTextLabel.textColor = ThemeService.shared.theme.textSecondaryColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index 45e66a73f..ef7943c5f 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -72,15 +72,15 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; - [ThemeService.theme applyStyleOnSearchBar:self.searchBar]; + [ThemeService.shared.theme applyStyleOnSearchBar:self.searchBar]; // Use the primary bg color for the table view in plain style. - self.tableView.backgroundColor = ThemeService.theme.backgroundColor; - topview.backgroundColor = ThemeService.theme.backgroundColor; + self.tableView.backgroundColor = ThemeService.shared.theme.backgroundColor; + topview.backgroundColor = ThemeService.shared.theme.backgroundColor; self.searchDisplayController.searchResultsTableView.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -91,7 +91,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -118,15 +118,15 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; - cell.detailTextLabel.textColor = ThemeService.theme.textSecondaryColor; - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + cell.detailTextLabel.textColor = ThemeService.shared.theme.textSecondaryColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 275fdf265..cf29b7e83 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -334,12 +334,12 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -350,7 +350,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)didReceiveMemoryWarning @@ -955,30 +955,30 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // Crypto information NSMutableAttributedString *cryptoInformationString = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_name", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:account.device.displayName ? account.device.displayName : @"" - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_id", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:account.device.deviceId ? account.device.deviceId : @"" - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"settings_crypto_device_key", @"Vector", nil) - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textPrimaryColor, NSFontAttributeName: [UIFont systemFontOfSize:17]}]]; NSString *fingerprint = account.mxSession.crypto.deviceEd25519Key; [cryptoInformationString appendAttributedString:[[NSMutableAttributedString alloc] initWithString:fingerprint ? fingerprint : @"" - attributes:@{NSForegroundColorAttributeName : ThemeService.theme.textPrimaryColor, + attributes:@{NSForegroundColorAttributeName : ThemeService.shared.theme.textPrimaryColor, NSFontAttributeName: [UIFont boldSystemFontOfSize:17]}]]; return cryptoInformationString; @@ -1295,12 +1295,12 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkTextFieldLeadingConstraint.constant = 16; cell.mxkTextFieldTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.mxkTextField.userInteractionEnabled = YES; cell.mxkTextField.borderStyle = UITextBorderStyleNone; cell.mxkTextField.textAlignment = NSTextAlignmentRight; - cell.mxkTextField.textColor = ThemeService.theme.textSecondaryColor; + cell.mxkTextField.textColor = ThemeService.shared.theme.textSecondaryColor; cell.mxkTextField.font = [UIFont systemFontOfSize:16]; cell.mxkTextField.placeholder = nil; @@ -1322,7 +1322,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell.mxkLabelLeadingConstraint.constant = cell.separatorInset.left; cell.mxkSwitchTrailingConstraint.constant = 15; - cell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; [cell.mxkSwitch removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1348,7 +1348,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); } cell.textLabel.accessibilityIdentifier = nil; cell.textLabel.font = [UIFont systemFontOfSize:17]; - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; return cell; } @@ -1357,7 +1357,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { MXKTableViewCellWithTextView *textViewCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithTextView defaultReuseIdentifier] forIndexPath:indexPath]; - textViewCell.mxkTextView.textColor = ThemeService.theme.textPrimaryColor; + textViewCell.mxkTextView.textColor = ThemeService.shared.theme.textPrimaryColor; textViewCell.mxkTextView.font = [UIFont systemFontOfSize:17]; textViewCell.mxkTextView.backgroundColor = [UIColor clearColor]; textViewCell.mxkTextViewLeadingConstraint.constant = tableView.separatorInset.left; @@ -1404,7 +1404,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); [signOutCell.mxkButton setTitle:title forState:UIControlStateNormal]; [signOutCell.mxkButton setTitle:title forState:UIControlStateHighlighted]; - [signOutCell.mxkButton setTintColor:ThemeService.theme.tintColor]; + [signOutCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; signOutCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [signOutCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -1436,7 +1436,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); profileCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_profile_picture", @"Vector", nil); profileCell.accessibilityIdentifier=@"SettingsVCProfilPictureStaticText"; - profileCell.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; + profileCell.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; // if the user defines a new avatar if (newAvatarImage) @@ -1527,11 +1527,11 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { newEmailCell.mxkLabel.text = nil; newEmailCell.mxkTextField.placeholder = NSLocalizedStringFromTable(@"settings_email_address_placeholder", @"Vector", nil); - if (ThemeService.theme.placeholderTextColor) + if (ThemeService.shared.theme.placeholderTextColor) { newEmailCell.mxkTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:newEmailCell.mxkTextField.placeholder - attributes:@{NSForegroundColorAttributeName: ThemeService.theme.placeholderTextColor}]; + attributes:@{NSForegroundColorAttributeName: ThemeService.shared.theme.placeholderTextColor}]; } newEmailCell.mxkTextField.text = newEmailTextField.text; newEmailCell.mxkTextField.userInteractionEnabled = YES; @@ -1559,7 +1559,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newEmailTextField = newEmailCell.mxkTextField; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:ThemeService.theme.tintColor]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:ThemeService.shared.theme.tintColor]; newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; } @@ -1652,7 +1652,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); newPhoneNumberCell = newPhoneCell; } - UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:ThemeService.theme.tintColor]; + UIImage *accessoryViewImage = [MXKTools paintImage:[UIImage imageNamed:@"plus_icon"] withColor:ThemeService.shared.theme.tintColor]; newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; cell = newPhoneCell; @@ -1672,7 +1672,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); else if (row == userSettingsNightModeSepIndex) { UITableViewCell *sepCell = [[UITableViewCell alloc] init]; - sepCell.backgroundColor = ThemeService.theme.headerBackgroundColor; + sepCell.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; cell = sepCell; } @@ -1695,7 +1695,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_push_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.isPushKitNotificationActive; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePushNotifications:) forControlEvents:UIControlEventTouchUpInside]; @@ -1707,7 +1707,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_show_decrypted_content", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.showDecryptedContentInNotifications; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = account.isPushKitNotificationActive; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleShowDecodedContent:) forControlEvents:UIControlEventTouchUpInside]; @@ -1733,7 +1733,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_missed_notif", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithMissedNotificationsOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithMissedNotif:) forControlEvents:UIControlEventTouchUpInside]; @@ -1745,7 +1745,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_pin_rooms_with_unread", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.pinRoomsWithUnreadMessagesOnHome; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(togglePinRoomsWithUnread:) forControlEvents:UIControlEventTouchUpInside]; @@ -1759,7 +1759,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_callkit", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].isCallKitEnabled; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleCallKit:) forControlEvents:UIControlEventTouchUpInside]; @@ -1796,7 +1796,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:language]; languageDescription = [languageDescription capitalizedStringWithLocale:locale]; - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_language", @"Vector", nil); cell.detailTextLabel.text = languageDescription; @@ -1833,7 +1833,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); @"Vector", nil); - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_ui_theme", @"Vector", nil); cell.detailTextLabel.text = i18nTheme; @@ -1864,7 +1864,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.numberOfLines = 0; labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_contacts_discover_matrix_users", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = [MXKAppSettings standardAppSettings].syncLocalContacts; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLocalContactsSync:) forControlEvents:UIControlEventTouchUpInside]; @@ -1882,7 +1882,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSLocale *local = [[NSLocale alloc] initWithLocaleIdentifier:[[NSBundle mainBundle] preferredLocalizations][0]]; NSString *countryName = [local displayNameForKey:NSLocaleCountryCode value:countryCode]; - cell.textLabel.textColor = ThemeService.theme.textPrimaryColor; + cell.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; cell.textLabel.text = NSLocalizedStringFromTable(@"settings_contacts_phonebook_country", @"Vector", nil); cell.detailTextLabel.text = countryName; @@ -1973,7 +1973,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); sendCrashReportCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_send_crash_report", @"Vector", nil); sendCrashReportCell.mxkSwitch.on = RiotSettings.shared.enableCrashReport; - sendCrashReportCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + sendCrashReportCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; sendCrashReportCell.mxkSwitch.enabled = YES; [sendCrashReportCell.mxkSwitch addTarget:self action:@selector(toggleSendCrashReport:) forControlEvents:UIControlEventTouchUpInside]; @@ -1985,7 +1985,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); enableRageShakeCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_enable_rageshake", @"Vector", nil); enableRageShakeCell.mxkSwitch.on = RiotSettings.shared.enableRageShake; - enableRageShakeCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + enableRageShakeCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; enableRageShakeCell.mxkSwitch.enabled = YES; [enableRageShakeCell.mxkSwitch addTarget:self action:@selector(toggleEnableRageShake:) forControlEvents:UIControlEventTouchUpInside]; @@ -2007,7 +2007,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_mark_all_as_read", @"Vector", nil); [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [markAllBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [markAllBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; + [markAllBtnCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; markAllBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [markAllBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2032,7 +2032,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_clear_cache", @"Vector", nil); [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [clearCacheBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [clearCacheBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; + [clearCacheBtnCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; clearCacheBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [clearCacheBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2057,7 +2057,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_report_bug", @"Vector", nil); [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [reportBugBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [reportBugBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; + [reportBugBtnCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; reportBugBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [reportBugBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2077,7 +2077,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; labelAndSwitchCell.mxkSwitch.on = account.mxSession.syncWithLazyLoadOfRoomMembers; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleSyncWithLazyLoadOfRoomMembers:) forControlEvents:UIControlEventTouchUpInside]; @@ -2089,7 +2089,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_create_conference_with_jitsi", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.createConferenceCallsWithJitsi; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleJitsiForConference:) forControlEvents:UIControlEventTouchUpInside]; @@ -2103,7 +2103,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_labs_e2e_encryption", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = (nil != session.crypto); - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleLabsEndToEndEncryption:) forControlEvents:UIControlEventTouchUpInside]; @@ -2177,7 +2177,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); labelAndSwitchCell.mxkLabel.text = NSLocalizedStringFromTable(@"settings_crypto_blacklist_unverified_devices", @"Vector", nil); labelAndSwitchCell.mxkSwitch.on = account.mxSession.crypto.globalBlacklistUnverifiedDevices; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.theme.tintColor; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; labelAndSwitchCell.mxkSwitch.enabled = YES; [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleBlacklistUnverifiedDevices:) forControlEvents:UIControlEventTouchUpInside]; @@ -2199,7 +2199,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_crypto_export", @"Vector", nil); [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [exportKeysBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [exportKeysBtnCell.mxkButton setTintColor:ThemeService.theme.tintColor]; + [exportKeysBtnCell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; exportKeysBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [exportKeysBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; @@ -2334,7 +2334,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { // Customize label style UITableViewHeaderFooterView *tableViewHeaderFooterView = (UITableViewHeaderFooterView*)view; - tableViewHeaderFooterView.textLabel.textColor = ThemeService.theme.textPrimaryColor; + tableViewHeaderFooterView.textLabel.textColor = ThemeService.shared.theme.textPrimaryColor; tableViewHeaderFooterView.textLabel.font = [UIFont systemFontOfSize:15]; } } @@ -2362,15 +2362,15 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; if (cell.selectionStyle != UITableViewCellSelectionStyleNone) { // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -2473,7 +2473,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_pink" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(50, cellHeight) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon_pink" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(50, cellHeight) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } } diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 6a3f3c7fa..7f1325990 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -28,12 +28,12 @@ { [super customizeViewRendering]; - self.containerView.backgroundColor = ThemeService.theme.headerBackgroundColor; - self.textView.backgroundColor = ThemeService.theme.backgroundColor; - self.defaultTextColor = ThemeService.theme.textPrimaryColor; - self.cancelButton.tintColor = ThemeService.theme.tintColor; - self.deleteButton.tintColor = ThemeService.theme.tintColor; - self.renameButton.tintColor = ThemeService.theme.tintColor; + self.containerView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + self.textView.backgroundColor = ThemeService.shared.theme.backgroundColor; + self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor; + self.cancelButton.tintColor = ThemeService.shared.theme.tintColor; + self.deleteButton.tintColor = ThemeService.shared.theme.tintColor; + self.renameButton.tintColor = ThemeService.shared.theme.tintColor; } @end diff --git a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m index a265e50b1..9db346839 100644 --- a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m +++ b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m @@ -27,10 +27,10 @@ { [super customizeTableViewCellRendering]; - self.mxkLabel.textColor = ThemeService.theme.textPrimaryColor; - self.mxkTextField.textColor = ThemeService.theme.textPrimaryColor; + self.mxkLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.mxkTextField.textColor = ThemeService.shared.theme.textPrimaryColor; - _isoCountryCodeLabel.textColor = ThemeService.theme.textPrimaryColor; + _isoCountryCodeLabel.textColor = ThemeService.shared.theme.textPrimaryColor; } - (void)setIsoCountryCode:(NSString *)isoCountryCode diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 8faca7478..cbc7dabf4 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -149,10 +149,10 @@ [self refreshSearchBarItemsColor:_searchBarView]; - _searchBarHeaderBorder.backgroundColor = ThemeService.theme.headerBorderColor; + _searchBarHeaderBorder.backgroundColor = ThemeService.shared.theme.headerBorderColor; // Check the table view style to select its bg color. - self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.contactsTableView.backgroundColor = ((self.contactsTableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.contactsTableView.backgroundColor; if (self.contactsTableView.dataSource) @@ -163,7 +163,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -381,13 +381,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { @@ -453,7 +453,7 @@ }]; - leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; + leaveAction.backgroundColor = [MXKTools convertImageToPatternColor:@"remove_icon" backgroundColor:ThemeService.shared.theme.headerBackgroundColor patternSize:CGSizeMake(74, 74) resourceSize:CGSizeMake(24, 24)]; [actions insertObject:leaveAction atIndex:0]; } @@ -621,19 +621,19 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = ThemeService.theme.tintColor; - searchBar.tintColor = ThemeService.theme.tintColor; + searchBar.barTintColor = searchBar.tintColor = ThemeService.shared.theme.tintColor; + searchBar.tintColor = ThemeService.shared.theme.tintColor; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. // text color UITextField *searchBarTextField = [searchBar valueForKey:@"_searchField"]; - searchBarTextField.textColor = ThemeService.theme.textSecondaryColor; + searchBarTextField.textColor = ThemeService.shared.theme.textSecondaryColor; // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = ThemeService.theme.tintColor; + leftImageView.tintColor = ThemeService.shared.theme.tintColor; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -646,8 +646,8 @@ { searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: ThemeService.theme.tintColor, - NSForegroundColorAttributeName: ThemeService.theme.tintColor}]; + NSUnderlineColorAttributeName: ThemeService.shared.theme.tintColor, + NSForegroundColorAttributeName: ThemeService.shared.theme.tintColor}]; } } diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 114a7068c..2d89150c7 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -114,19 +114,19 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.tabBar.tintColor = ThemeService.theme.tintColor; - self.tabBar.barTintColor = ThemeService.theme.headerBackgroundColor; + self.tabBar.tintColor = ThemeService.shared.theme.tintColor; + self.tabBar.barTintColor = ThemeService.shared.theme.headerBackgroundColor; - self.view.backgroundColor = ThemeService.theme.backgroundColor; + self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; [self setNeedsStatusBarAppearanceUpdate]; } - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)viewWillAppear:(BOOL)animated @@ -786,7 +786,7 @@ { _hidden = hidden; - [self.view superview].backgroundColor = ThemeService.theme.backgroundColor; + [self.view superview].backgroundColor = ThemeService.shared.theme.backgroundColor; self.view.hidden = hidden; self.navigationController.navigationBar.hidden = hidden; } @@ -798,15 +798,15 @@ // Use a middle dot to signal missed notif in favourites [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX - withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor)]; // Update the badge on People and Rooms tabs [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX - withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor)]; [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX - withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.theme.notificationMentionColor : ThemeService.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 3e288dfed..132627553 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -82,12 +82,12 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.activityIndicator.backgroundColor = ThemeService.theme.overlayBackgroundColor; + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Check the table view style to select its bg color. - self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.theme.backgroundColor : ThemeService.theme.headerBackgroundColor); + self.tableView.backgroundColor = ((self.tableView.style == UITableViewStylePlain) ? ThemeService.shared.theme.backgroundColor : ThemeService.shared.theme.headerBackgroundColor); self.view.backgroundColor = self.tableView.backgroundColor; if (self.tableView.dataSource) @@ -98,7 +98,7 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - return ThemeService.theme.statusBarStyle; + return ThemeService.shared.theme.statusBarStyle; } - (void)destroy @@ -178,13 +178,13 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; { - cell.backgroundColor = ThemeService.theme.backgroundColor; + cell.backgroundColor = ThemeService.shared.theme.backgroundColor; // Update the selected background view - if (ThemeService.theme.selectedBackgroundColor) + if (ThemeService.shared.theme.selectedBackgroundColor) { cell.selectedBackgroundView = [[UIView alloc] init]; - cell.selectedBackgroundView.backgroundColor = ThemeService.theme.selectedBackgroundColor; + cell.selectedBackgroundView.backgroundColor = ThemeService.shared.theme.selectedBackgroundColor; } else { diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 77ba00d6b..9ee73a778 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -32,15 +32,15 @@ { [super customizeTableViewCellRendering]; - self.deviceName.textColor = ThemeService.theme.textPrimaryColor; + self.deviceName.textColor = ThemeService.shared.theme.textPrimaryColor; [self.verifyButton.layer setCornerRadius:5]; self.verifyButton.clipsToBounds = YES; - self.verifyButton.backgroundColor = ThemeService.theme.tintColor; + self.verifyButton.backgroundColor = ThemeService.shared.theme.tintColor; [self.blockButton.layer setCornerRadius:5]; self.blockButton.clipsToBounds = YES; - self.blockButton.backgroundColor = ThemeService.theme.tintColor; + self.blockButton.backgroundColor = ThemeService.shared.theme.tintColor; } - (void)render:(MXDeviceInfo *)deviceInfo diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index 6b9ad57a9..dc0162ef3 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -39,7 +39,7 @@ static UILabel* backgroundLabel = nil; { if (!colorsList) { - colorsList = ThemeService.theme.avatarColors; + colorsList = ThemeService.shared.theme.avatarColors; } } @@ -93,7 +93,7 @@ static UILabel* backgroundLabel = nil; if (!backgroundLabel) { backgroundLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 40, 40)]; - backgroundLabel.textColor = ThemeService.theme.backgroundColor; + backgroundLabel.textColor = ThemeService.shared.theme.backgroundColor; backgroundLabel.textAlignment = NSTextAlignmentCenter; backgroundLabel.font = [UIFont boldSystemFontOfSize:25]; } @@ -123,7 +123,7 @@ static UILabel* backgroundLabel = nil; + (UIImage *)imageFromText:(NSString*)text withBackgroundColor:(UIColor*)color size:(CGFloat)size andFontSize:(CGFloat)fontSize { UILabel *bgLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, size, size)]; - bgLabel.textColor = ThemeService.theme.backgroundColor; + bgLabel.textColor = ThemeService.shared.theme.backgroundColor; bgLabel.textAlignment = NSTextAlignmentCenter; bgLabel.font = [UIFont boldSystemFontOfSize:fontSize]; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 36e8b88d1..a6bffccc1 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -206,7 +206,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]; // Use the secondary bg color to set the background color in the default CSS. - NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.theme.headerBackgroundColor]; + NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.shared.theme.headerBackgroundColor]; self.defaultCSS = [NSString stringWithFormat:@" \ pre,code { \ background-color: #%06lX; \ @@ -217,12 +217,12 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; font-size: small; \ }", (unsigned long)bgColor]; - self.defaultTextColor = ThemeService.theme.textPrimaryColor; - self.subTitleTextColor = ThemeService.theme.textSecondaryColor; - self.prefixTextColor = ThemeService.theme.textSecondaryColor; - self.bingTextColor = ThemeService.theme.notificationMentionColor; - self.encryptingTextColor = ThemeService.theme.tintColor; - self.sendingTextColor = ThemeService.theme.textSecondaryColor; + self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor; + self.subTitleTextColor = ThemeService.shared.theme.textSecondaryColor; + self.prefixTextColor = ThemeService.shared.theme.textSecondaryColor; + self.bingTextColor = ThemeService.shared.theme.notificationMentionColor; + self.encryptingTextColor = ThemeService.shared.theme.tintColor; + self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; self.errorTextColor = kRiotColorRed; self.defaultTextFont = [UIFont systemFontOfSize:15]; diff --git a/RiotShareExtension/Modules/Fallback/FallbackViewController.m b/RiotShareExtension/Modules/Fallback/FallbackViewController.m index 19b7165b6..42d213e82 100644 --- a/RiotShareExtension/Modules/Fallback/FallbackViewController.m +++ b/RiotShareExtension/Modules/Fallback/FallbackViewController.m @@ -35,7 +35,7 @@ { [super viewDidLoad]; - self.titleLabel.textColor = ThemeService.theme.textSecondaryColor; + self.titleLabel.textColor = ThemeService.shared.theme.textSecondaryColor; self.titleLabel.text = NSLocalizedStringFromTable(@"share_extension_auth_prompt", @"Vector", nil); } diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m index 1f324bd7d..2242cb599 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m @@ -96,7 +96,7 @@ self.recentsSearchBar.searchBarStyle = UISearchBarStyleMinimal; self.recentsSearchBar.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil); - self.recentsSearchBar.tintColor = ThemeService.theme.tintColor; + self.recentsSearchBar.tintColor = ThemeService.shared.theme.tintColor; _tableSearchBar.tintColor = self.recentsSearchBar.tintColor; } From 9cce93ecea7375fcdb4292ceefd8f91754ee1d2d Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 11:57:02 +0100 Subject: [PATCH 047/244] reskin: Kill kRiotColorXxxx --- Riot/Constants/ThemeService.h | 17 +++---- Riot/Constants/ThemeService.m | 46 ++++++++----------- .../AuthenticationViewController.m | 2 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../Communities/GroupsViewController.m | 2 +- .../Home/GroupHomeViewController.m | 6 +-- .../Members/GroupParticipantsViewController.m | 10 ++-- .../Rooms/GroupRoomsViewController.m | 10 ++-- .../TabDetail/GroupDetailsViewController.m | 2 +- .../Views/GroupInviteTableViewCell.m | 4 +- .../Favorites/FavouritesViewController.m | 2 +- Riot/Modules/People/PeopleViewController.m | 2 +- .../Detail/RoomMemberDetailsViewController.m | 4 +- Riot/Modules/Room/RoomViewController.m | 2 +- .../Settings/RoomSettingsViewController.m | 2 +- .../Views/Activities/RoomActivitiesView.m | 26 +++++------ .../RoomOutgoingAttachmentBubbleCell.m | 2 +- .../DeactivateAccountViewController.m | 2 +- .../Modules/Settings/SettingsViewController.m | 2 +- Riot/Utils/EventFormatter.m | 2 +- 20 files changed, 69 insertions(+), 78 deletions(-) diff --git a/Riot/Constants/ThemeService.h b/Riot/Constants/ThemeService.h index 8d501c4dc..cb2630e3e 100644 --- a/Riot/Constants/ThemeService.h +++ b/Riot/Constants/ThemeService.h @@ -36,14 +36,6 @@ extern NSString *const kThemeServiceDidChangeThemeNotification; blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ alpha:1.0] -#pragma mark - Riot Colors -extern UIColor *kRiotColorPinkRed; -extern UIColor *kRiotColorRed; -extern UIColor *kRiotColorBlue; -extern UIColor *kRiotColorCuriousBlue; -extern UIColor *kRiotColorIndigo; -extern UIColor *kRiotColorOrange; - #pragma mark - Riot Standard Room Member Power Level extern NSInteger const kRiotRoomModeratorLevel; extern NSInteger const kRiotRoomAdminLevel; @@ -78,6 +70,15 @@ extern NSInteger const kRiotRoomAdminLevel; */ - (id)themeWithThemeId:(NSString*)themeId; +#pragma mark - Riot Colors not yet themeable + +@property (nonatomic, readonly) UIColor *riotColorPinkRed; +@property (nonatomic, readonly) UIColor *riotColorRed; +@property (nonatomic, readonly) UIColor *riotColorBlue; +@property (nonatomic, readonly) UIColor *riotColorCuriousBlue; +@property (nonatomic, readonly) UIColor *riotColorIndigo; +@property (nonatomic, readonly) UIColor *riotColorOrange; + @end NS_ASSUME_NONNULL_END diff --git a/Riot/Constants/ThemeService.m b/Riot/Constants/ThemeService.m index d29b5799e..40c18d6b3 100644 --- a/Riot/Constants/ThemeService.m +++ b/Riot/Constants/ThemeService.m @@ -27,15 +27,6 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChangeThemeNotification"; -// Riot Colors -UIColor *kRiotColorPinkRed; -UIColor *kRiotColorRed; -UIColor *kRiotColorBlue; -UIColor *kRiotColorCuriousBlue; -UIColor *kRiotColorIndigo; -UIColor *kRiotColorOrange; - - NSInteger const kRiotRoomModeratorLevel = 50; NSInteger const kRiotRoomAdminLevel = 100; @@ -87,28 +78,27 @@ NSInteger const kRiotRoomAdminLevel = 100; #pragma mark - Private methods -+ (void)load +- (instancetype)init { - [super load]; + self = [super init]; + if (self) + { + // Riot Colors not yet themeable + _riotColorPinkRed = UIColorFromRGB(0xFF0064); + _riotColorRed = UIColorFromRGB(0xFF4444); + _riotColorBlue = UIColorFromRGB(0x81BDDB); + _riotColorCuriousBlue = UIColorFromRGB(0x2A9EDB); + _riotColorIndigo = UIColorFromRGB(0xBD79CC); + _riotColorOrange = UIColorFromRGB(0xF8A15F); - // Load colors at the app load time for the life of the app + // Observe user interface theme change. + [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"userInterfaceTheme" options:0 context:nil]; + [self userInterfaceThemeDidChange]; - // Colors as defined by the design - kRiotColorPinkRed = UIColorFromRGB(0xFF0064); - kRiotColorRed = UIColorFromRGB(0xFF4444); - kRiotColorBlue = UIColorFromRGB(0x81BDDB); - kRiotColorCuriousBlue = UIColorFromRGB(0x2A9EDB); - kRiotColorIndigo = UIColorFromRGB(0xBD79CC); - kRiotColorOrange = UIColorFromRGB(0xF8A15F); - - ThemeService *themeService = ThemeService.shared; - - // Observe user interface theme change. - [[NSUserDefaults standardUserDefaults] addObserver:themeService forKeyPath:@"userInterfaceTheme" options:0 context:nil]; - [themeService userInterfaceThemeDidChange]; - - // Observe "Invert Colours" settings changes (available since iOS 11) - [[NSNotificationCenter defaultCenter] addObserver:themeService selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; + // Observe "Invert Colours" settings changes (available since iOS 11) + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; + } + return self; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index ae37370bb..bfed3b3a4 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -157,7 +157,7 @@ self.submitButton.backgroundColor = ThemeService.shared.theme.tintColor; self.skipButton.backgroundColor = ThemeService.shared.theme.tintColor; - self.noFlowLabel.textColor = kRiotColorRed; + self.noFlowLabel.textColor = ThemeService.shared.riotColorRed; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index eb55551ac..6825f85d4 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -100,7 +100,7 @@ static const CGFloat kButtonSize = 80.0; self.answerTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.answerTitleLabel.text = NSLocalizedStringFromTable(@"accept", @"Vector", nil); - UIColor *rejectButtonBorderColor = kRiotColorPinkRed; + UIColor *rejectButtonBorderColor = ThemeService.shared.riotColorPinkRed; self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"call_hangup_icon"] borderColor:rejectButtonBorderColor]; diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index a59dfe849..b5a0c20fd 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -204,7 +204,7 @@ }]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_groups", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorBlue; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.riotColorBlue; } - (void)viewWillDisappear:(BOOL)animated diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 42cbe7505..b488c7102 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -132,16 +132,16 @@ [self.leftButton.layer setCornerRadius:5]; self.leftButton.clipsToBounds = YES; - self.leftButton.backgroundColor = kRiotColorBlue; + self.leftButton.backgroundColor = ThemeService.shared.riotColorBlue; [self.rightButton.layer setCornerRadius:5]; self.rightButton.clipsToBounds = YES; - self.rightButton.backgroundColor = kRiotColorBlue; + self.rightButton.backgroundColor = ThemeService.shared.riotColorBlue; if (_groupLongDescription) { _groupLongDescription.textColor = ThemeService.shared.theme.textSecondaryColor; - _groupLongDescription.tintColor = kRiotColorBlue; + _groupLongDescription.tintColor = ThemeService.shared.riotColorBlue; // Update HTML loading options NSUInteger bgColor = [MXKTools rgbValueWithColor:ThemeService.shared.theme.headerBackgroundColor]; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index db0ab6aaf..fc5ec787e 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -1198,8 +1198,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = kRiotColorBlue; - searchBar.tintColor = kRiotColorBlue; + searchBar.barTintColor = searchBar.tintColor = ThemeService.shared.riotColorBlue; + searchBar.tintColor = ThemeService.shared.riotColorBlue; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -1210,7 +1210,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = kRiotColorBlue; + leftImageView.tintColor = ThemeService.shared.riotColorBlue; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -1221,8 +1221,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: kRiotColorBlue, - NSForegroundColorAttributeName: kRiotColorBlue}]; + NSUnderlineColorAttributeName: ThemeService.shared.riotColorBlue, + NSForegroundColorAttributeName: ThemeService.shared.riotColorBlue}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 8216249b4..9eb349d5b 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -599,8 +599,8 @@ - (void)refreshSearchBarItemsColor:(UISearchBar *)searchBar { // bar tint color - searchBar.barTintColor = searchBar.tintColor = kRiotColorBlue; - searchBar.tintColor = kRiotColorBlue; + searchBar.barTintColor = searchBar.tintColor = ThemeService.shared.riotColorBlue; + searchBar.tintColor = ThemeService.shared.riotColorBlue; // FIXME: this all seems incredibly fragile and tied to gutwrenching the current UISearchBar internals. @@ -611,7 +611,7 @@ // Magnifying glass icon. UIImageView *leftImageView = (UIImageView *)searchBarTextField.leftView; leftImageView.image = [leftImageView.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; - leftImageView.tintColor = kRiotColorBlue; + leftImageView.tintColor = ThemeService.shared.riotColorBlue; // remove the gray background color UIView *effectBackgroundTop = [searchBarTextField valueForKey:@"_effectBackgroundTop"]; @@ -622,8 +622,8 @@ // place holder searchBarTextField.attributedPlaceholder = [[NSAttributedString alloc] initWithString:searchBarTextField.placeholder attributes:@{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), - NSUnderlineColorAttributeName: kRiotColorBlue, - NSForegroundColorAttributeName: kRiotColorBlue}]; + NSUnderlineColorAttributeName: ThemeService.shared.riotColorBlue, + NSForegroundColorAttributeName: ThemeService.shared.riotColorBlue}]; } - (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m index 78d5fa770..1b885599e 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m @@ -72,7 +72,7 @@ self.enableBarTintColorStatusChange = NO; self.rageShakeManager = [RageShakeManager sharedManager]; - self.sectionHeaderTintColor = kRiotColorBlue; + self.sectionHeaderTintColor = ThemeService.shared.riotColorBlue; // Keep visible the status bar by default. isStatusBarHidden = NO; diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 76fff5045..783cb420d 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -55,8 +55,8 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo { [super customizeTableViewCellRendering]; - self.leftButton.backgroundColor = kRiotColorBlue; - self.rightButton.backgroundColor = kRiotColorBlue; + self.leftButton.backgroundColor = ThemeService.shared.riotColorBlue; + self.rightButton.backgroundColor = ThemeService.shared.riotColorBlue; self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; } diff --git a/Riot/Modules/Favorites/FavouritesViewController.m b/Riot/Modules/Favorites/FavouritesViewController.m index a45af8da0..c01d59cc0 100644 --- a/Riot/Modules/Favorites/FavouritesViewController.m +++ b/Riot/Modules/Favorites/FavouritesViewController.m @@ -55,7 +55,7 @@ [super viewWillAppear:animated]; [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_favourites", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorIndigo; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.riotColorIndigo; if (recentsDataSource) { diff --git a/Riot/Modules/People/PeopleViewController.m b/Riot/Modules/People/PeopleViewController.m index 914fc6744..84ec480a7 100644 --- a/Riot/Modules/People/PeopleViewController.m +++ b/Riot/Modules/People/PeopleViewController.m @@ -108,7 +108,7 @@ } [AppDelegate theDelegate].masterTabBarController.navigationItem.title = NSLocalizedStringFromTable(@"title_people", @"Vector", nil); - [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = kRiotColorOrange; + [AppDelegate theDelegate].masterTabBarController.tabBar.tintColor = ThemeService.shared.riotColorOrange; if (recentsDataSource) { diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 95be2db5d..eb4f2d25d 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -776,8 +776,8 @@ if (actionNumber.unsignedIntegerValue == MXKRoomMemberDetailsActionKick) { - [cellWithButton.mxkButton setTitleColor:kRiotColorPinkRed forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:kRiotColorPinkRed forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.riotColorPinkRed forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.riotColorPinkRed forState:UIControlStateHighlighted]; } else { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index c68afb7de..f16e9cd7d 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1331,7 +1331,7 @@ // Show it in red only for room widgets, not user's widgets // TODO: Design must be reviewed UIImage *icon = self.navigationItem.rightBarButtonItems[1].image; - icon = [MXKTools paintImage:icon withColor:kRiotColorPinkRed]; + icon = [MXKTools paintImage:icon withColor:ThemeService.shared.riotColorPinkRed]; icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; self.navigationItem.rightBarButtonItems[1].image = icon; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 609422b8c..71d63f388 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2362,7 +2362,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsWarningCellViewIdentifier forIndexPath:indexPath]; cell.textLabel.font = [UIFont systemFontOfSize:17]; - cell.textLabel.textColor = kRiotColorPinkRed; + cell.textLabel.textColor = ThemeService.shared.riotColorPinkRed; cell.textLabel.numberOfLines = 0; cell.accessoryView = nil; cell.accessoryType = UITableViewCellAccessoryNone; diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index c5ebadf5a..e696e2ecd 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -113,7 +113,7 @@ [super customizeViewRendering]; self.separatorView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - if (self.messageLabel.textColor != kRiotColorPinkRed) + if (self.messageLabel.textColor != ThemeService.shared.riotColorPinkRed) { self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } @@ -145,18 +145,18 @@ [tappableNotif addAttribute:NSLinkAttributeName value:@"onCancelLink" range:range]; NSRange wholeString = NSMakeRange(0, tappableNotif.length); - [tappableNotif addAttribute:NSForegroundColorAttributeName value:kRiotColorPinkRed range:wholeString]; + [tappableNotif addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.riotColorPinkRed range:wholeString]; [tappableNotif addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = tappableNotif; - self.messageTextView.tintColor = kRiotColorPinkRed; + self.messageTextView.tintColor = ThemeService.shared.riotColorPinkRed; self.messageTextView.hidden = NO; self.messageTextView.backgroundColor = [UIColor clearColor]; } else { self.messageLabel.text = notification; - self.messageLabel.textColor = kRiotColorPinkRed; + self.messageLabel.textColor = ThemeService.shared.riotColorPinkRed; self.messageLabel.hidden = NO; } @@ -187,7 +187,7 @@ { self.iconImageView.image = [UIImage imageNamed:@"error"]; self.messageLabel.text = labelText; - self.messageLabel.textColor = kRiotColorPinkRed; + self.messageLabel.textColor = ThemeService.shared.riotColorPinkRed; self.iconImageView.hidden = NO; self.messageLabel.hidden = NO; @@ -261,15 +261,15 @@ // Display the string in white on pink red NSRange wholeString = NSMakeRange(0, onGoingConferenceCallAttibutedString.length); [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.backgroundColor range:wholeString]; - [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:kRiotColorPinkRed range:wholeString]; + [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:ThemeService.shared.riotColorPinkRed range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = onGoingConferenceCallAttibutedString; self.messageTextView.tintColor = ThemeService.shared.theme.backgroundColor; self.messageTextView.hidden = NO; - self.backgroundColor = kRiotColorPinkRed; - self.messageTextView.backgroundColor = kRiotColorPinkRed; + self.backgroundColor = ThemeService.shared.riotColorPinkRed; + self.messageTextView.backgroundColor = ThemeService.shared.riotColorPinkRed; // Hide the separator to display correctly the red pink conf call banner self.separatorView.hidden = YES; @@ -295,7 +295,7 @@ notification = NSLocalizedStringFromTable(@"room_new_message_notification", @"Vector", nil); } self.messageLabel.text = [NSString stringWithFormat:notification, newMessagesCount]; - self.messageLabel.textColor = kRiotColorPinkRed; + self.messageLabel.textColor = ThemeService.shared.riotColorPinkRed; self.messageLabel.hidden = NO; } else @@ -487,13 +487,13 @@ if (hardLimit) { - self.backgroundColor = kRiotColorPinkRed; - self.messageTextView.backgroundColor = kRiotColorPinkRed; + self.backgroundColor = ThemeService.shared.riotColorPinkRed; + self.messageTextView.backgroundColor = ThemeService.shared.riotColorPinkRed; } else { - self.backgroundColor = kRiotColorCuriousBlue; - self.messageTextView.backgroundColor = kRiotColorCuriousBlue; + self.backgroundColor = ThemeService.shared.riotColorCuriousBlue; + self.messageTextView.backgroundColor = ThemeService.shared.riotColorCuriousBlue; } // Hide the separator to display correctly the banner diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index f24ac2f82..a1e7b87b1 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -49,7 +49,7 @@ // Show a red border when the attachment sending failed if (bubbleCell->bubbleData.attachment.eventSentState == MXEventSentStateFailed) { - bubbleCell.attachmentView.layer.borderColor = kRiotColorPinkRed.CGColor; + bubbleCell.attachmentView.layer.borderColor = ThemeService.shared.riotColorPinkRed.CGColor; bubbleCell.attachmentView.layer.borderWidth = 1; } else diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 1366854c7..036ef9136 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -152,7 +152,7 @@ static CGFloat const kTextFontSize = 15.0; - (void)setupNavigationBar { - self.navigationController.navigationBar.titleTextAttributes = @{ NSForegroundColorAttributeName: kRiotColorRed }; + self.navigationController.navigationBar.titleTextAttributes = @{ NSForegroundColorAttributeName: ThemeService.shared.riotColorRed }; UIBarButtonItem *cancelBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedStringFromTable(@"cancel", @"Vector", nil) style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonAction:)]; self.navigationItem.rightBarButtonItem = cancelBarButtonItem; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index cf29b7e83..48703c93a 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -2226,7 +2226,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_deactivate_my_account", @"Vector", nil); [deactivateAccountBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [deactivateAccountBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [deactivateAccountBtnCell.mxkButton setTintColor:kRiotColorRed]; + [deactivateAccountBtnCell.mxkButton setTintColor:ThemeService.shared.riotColorRed]; deactivateAccountBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [deactivateAccountBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index a6bffccc1..ea370402d 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -223,7 +223,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.bingTextColor = ThemeService.shared.theme.notificationMentionColor; self.encryptingTextColor = ThemeService.shared.theme.tintColor; self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; - self.errorTextColor = kRiotColorRed; + self.errorTextColor = ThemeService.shared.riotColorRed; self.defaultTextFont = [UIFont systemFontOfSize:15]; self.prefixTextFont = [UIFont boldSystemFontOfSize:15]; From 6ee17b6d830348f6d7abd79eb4a055e5758caa6d Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 12:15:43 +0100 Subject: [PATCH 048/244] reskin: kill UIColorFromRGB and use UIColor swift extension --- Riot.xcodeproj/project.pbxproj | 6 ++++++ Riot/Categories/UIColor.swift | 28 ++++++++++++++++++++++++++++ Riot/Constants/Colors/Theme.swift | 13 ------------- Riot/Constants/ThemeService.h | 8 -------- Riot/Constants/ThemeService.m | 12 ++++++------ 5 files changed, 40 insertions(+), 27 deletions(-) create mode 100644 Riot/Categories/UIColor.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index f3fcbf652..24fc6db37 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -16,6 +16,8 @@ 3223D9C421B0077D000321C1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* Theme.swift */; }; 3223D9C521B00781000321C1 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkTheme.swift */; }; 3223D9C621B00788000321C1 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultTheme.swift */; }; + 32242F0921E8B05F00725742 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0821E8B05F00725742 /* UIColor.swift */; }; + 32242F0A21E8B21300725742 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0821E8B05F00725742 /* UIColor.swift */; }; 3233F7461F3497E2006ACA81 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; }; 3233F7471F3497E2006ACA81 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3275FD8B21A5A2C500B9C13D /* TermsView.swift */; }; @@ -391,6 +393,7 @@ 3223D9BE21B00615000321C1 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; 3223D9BF21B00615000321C1 /* DefaultTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultTheme.swift; sourceTree = ""; }; 3223D9C221B0065A000321C1 /* DarkTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkTheme.swift; sourceTree = ""; }; + 32242F0821E8B05F00725742 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = ""; }; 3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = ""; }; 3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; @@ -2481,6 +2484,7 @@ F083BBEC1E7009EC00A9B29C /* UIViewController+RiotSearch.m */, 926FA53D1F4C132000F826C2 /* MXSession+Riot.h */, 926FA53E1F4C132000F826C2 /* MXSession+Riot.m */, + 32242F0821E8B05F00725742 /* UIColor.swift */, ); path = Categories; sourceTree = ""; @@ -2993,6 +2997,7 @@ B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */, F0A8955F1F7D1FEA00BD6C2A /* MXRoomSummary+Riot.m in Sources */, B169328320F38AE600746532 /* RiotSettings.swift in Sources */, + 32242F0A21E8B21300725742 /* UIColor.swift in Sources */, B1664BC820F4E67600808783 /* ShareDataSource.m in Sources */, B1664BCD20F4E67600808783 /* RecentRoomTableViewCell.m in Sources */, B169331720F3CBE000746532 /* RecentCellData.m in Sources */, @@ -3181,6 +3186,7 @@ B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, + 32242F0921E8B05F00725742 /* UIColor.swift in Sources */, B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */, B1B558CE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.m in Sources */, B1B5577D20EE84BF00210D55 /* CircleButton.m in Sources */, diff --git a/Riot/Categories/UIColor.swift b/Riot/Categories/UIColor.swift new file mode 100644 index 000000000..6095c4fbf --- /dev/null +++ b/Riot/Categories/UIColor.swift @@ -0,0 +1,28 @@ +/* + Copyright 2019 New Vector 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 UIKit + +@objc extension UIColor { + convenience init(rgb: UInt) { + self.init( + red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgb & 0x0000FF) / 255.0, + alpha: CGFloat(1.0) + ) + } +} diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index 01812bf07..82f7017a7 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -87,16 +87,3 @@ import UIKit /// - Parameter searchBar: the search bar to customise. func applyStyle(onSearchBar: UISearchBar) } - - -/// TODO: to move -extension UIColor { - convenience init(rgb: UInt) { - self.init( - red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, - green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0, - blue: CGFloat(rgb & 0x0000FF) / 255.0, - alpha: CGFloat(1.0) - ) - } -} diff --git a/Riot/Constants/ThemeService.h b/Riot/Constants/ThemeService.h index cb2630e3e..0772c8a96 100644 --- a/Riot/Constants/ThemeService.h +++ b/Riot/Constants/ThemeService.h @@ -27,14 +27,6 @@ NS_ASSUME_NONNULL_BEGIN */ extern NSString *const kThemeServiceDidChangeThemeNotification; -/** - Convert a RGB hexadecimal value into a UIColor. - */ -#define UIColorFromRGB(rgbValue) \ - [UIColor colorWithRed:((float)((rgbValue & 0xFF0000) >> 16))/255.0 \ - green:((float)((rgbValue & 0x00FF00) >> 8))/255.0 \ - blue:((float)((rgbValue & 0x0000FF) >> 0))/255.0 \ - alpha:1.0] #pragma mark - Riot Standard Room Member Power Level extern NSInteger const kRiotRoomModeratorLevel; diff --git a/Riot/Constants/ThemeService.m b/Riot/Constants/ThemeService.m index 40c18d6b3..994ac951e 100644 --- a/Riot/Constants/ThemeService.m +++ b/Riot/Constants/ThemeService.m @@ -84,12 +84,12 @@ NSInteger const kRiotRoomAdminLevel = 100; if (self) { // Riot Colors not yet themeable - _riotColorPinkRed = UIColorFromRGB(0xFF0064); - _riotColorRed = UIColorFromRGB(0xFF4444); - _riotColorBlue = UIColorFromRGB(0x81BDDB); - _riotColorCuriousBlue = UIColorFromRGB(0x2A9EDB); - _riotColorIndigo = UIColorFromRGB(0xBD79CC); - _riotColorOrange = UIColorFromRGB(0xF8A15F); + _riotColorPinkRed = [[UIColor alloc] initWithRgb:0xFF0064]; + _riotColorRed = [[UIColor alloc] initWithRgb:0xFF4444]; + _riotColorBlue = [[UIColor alloc] initWithRgb:0x81BDDB]; + _riotColorCuriousBlue = [[UIColor alloc] initWithRgb:0x2A9EDB]; + _riotColorIndigo = [[UIColor alloc] initWithRgb:0xBD79CC]; + _riotColorOrange = [[UIColor alloc] initWithRgb:0xF8A15F]; // Observe user interface theme change. [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"userInterfaceTheme" options:0 context:nil]; From 8fd764227e74800c56cc4e24c4b847977d72d054 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 12:43:47 +0100 Subject: [PATCH 049/244] reskin: kill ThemeService.kRiotRoomXxxxLevel --- Riot/Constants/ThemeService.h | 4 ---- Riot/Constants/ThemeService.m | 4 ---- Riot/Managers/Settings/RiotSettings.swift | 9 ++++++++- .../Detail/RoomMemberDetailsViewController.m | 20 +++++++++---------- .../Members/RoomParticipantsViewController.m | 4 ++-- 5 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Riot/Constants/ThemeService.h b/Riot/Constants/ThemeService.h index 0772c8a96..eaeadf7c7 100644 --- a/Riot/Constants/ThemeService.h +++ b/Riot/Constants/ThemeService.h @@ -28,10 +28,6 @@ NS_ASSUME_NONNULL_BEGIN extern NSString *const kThemeServiceDidChangeThemeNotification; -#pragma mark - Riot Standard Room Member Power Level -extern NSInteger const kRiotRoomModeratorLevel; -extern NSInteger const kRiotRoomAdminLevel; - /** `ThemeService` class manages the application design values. */ diff --git a/Riot/Constants/ThemeService.m b/Riot/Constants/ThemeService.m index 994ac951e..c7956e39b 100644 --- a/Riot/Constants/ThemeService.m +++ b/Riot/Constants/ThemeService.m @@ -24,12 +24,8 @@ #import "Riot-Swift.h" #endif - NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChangeThemeNotification"; -NSInteger const kRiotRoomModeratorLevel = 50; -NSInteger const kRiotRoomAdminLevel = 100; - @implementation ThemeService + (ThemeService *)shared diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index e91b0ab15..6db8ec7b3 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -31,7 +31,14 @@ final class RiotSettings: NSObject { static let pinRoomsWithMissedNotifications = "pinRoomsWithMissedNotif" static let pinRoomsWithUnreadMessages = "pinRoomsWithUnread" } - + + /// Riot Standard Room Member Power Level + @objc + public enum RoomPowerLevel: Int { + case moderator = 50 + case admin = 100 + } + static let shared = RiotSettings() // MARK: - Public diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index eb4f2d25d..c89d734aa 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -376,12 +376,12 @@ MXRoomPowerLevels *powerLevels = [roomState powerLevels]; NSInteger powerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxRoomMember.userId]; - if (powerLevel >= kRiotRoomAdminLevel) + if (powerLevel >= RoomPowerLevelAdmin) { self->memberTitleView.memberBadge.image = [UIImage imageNamed:@"admin_icon"]; self->memberTitleView.memberBadge.hidden = NO; } - else if (powerLevel >= kRiotRoomModeratorLevel) + else if (powerLevel >= RoomPowerLevelModerator) { self->memberTitleView.memberBadge.image = [UIImage imageNamed:@"mod_icon"]; self->memberTitleView.memberBadge.hidden = NO; @@ -505,13 +505,13 @@ if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomPowerLevels]) { // Check whether the user is admin (in this case he may reduce his power level to become moderator or less, EXCEPT if he is the only admin). - if (oneSelfPowerLevel >= kRiotRoomAdminLevel) + if (oneSelfPowerLevel >= RoomPowerLevelAdmin) { NSArray *levelValues = powerLevels.users.allValues; NSUInteger adminCount = 0; for (NSNumber *valueNumber in levelValues) { - if ([valueNumber unsignedIntegerValue] >= kRiotRoomAdminLevel) + if ([valueNumber unsignedIntegerValue] >= RoomPowerLevelAdmin) { adminCount ++; } @@ -524,7 +524,7 @@ } } // Check whether the user is moderator (in this case he may reduce his power level to become normal user). - else if (oneSelfPowerLevel >= kRiotRoomModeratorLevel) + else if (oneSelfPowerLevel >= RoomPowerLevelModerator) { [adminActionsArray addObject:@(MXKRoomMemberDetailsActionSetDefaultPowerLevel)]; } @@ -542,18 +542,18 @@ if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomPowerLevels] && oneSelfPowerLevel > memberPowerLevel) { // Check whether user is admin - if (oneSelfPowerLevel >= kRiotRoomAdminLevel) + if (oneSelfPowerLevel >= RoomPowerLevelAdmin) { [adminActionsArray addObject:@(MXKRoomMemberDetailsActionSetAdmin)]; } // Check whether the member may become moderator - if (oneSelfPowerLevel >= kRiotRoomModeratorLevel && memberPowerLevel < kRiotRoomModeratorLevel) + if (oneSelfPowerLevel >= RoomPowerLevelModerator && memberPowerLevel < RoomPowerLevelModerator) { [adminActionsArray addObject:@(MXKRoomMemberDetailsActionSetModerator)]; } - if (memberPowerLevel >= kRiotRoomModeratorLevel) + if (memberPowerLevel >= RoomPowerLevelModerator) { [adminActionsArray addObject:@(MXKRoomMemberDetailsActionSetDefaultPowerLevel)]; } @@ -948,12 +948,12 @@ } case MXKRoomMemberDetailsActionSetModerator: { - [self setPowerLevel:kRiotRoomModeratorLevel promptUser:YES]; + [self setPowerLevel:RoomPowerLevelModerator promptUser:YES]; break; } case MXKRoomMemberDetailsActionSetAdmin: { - [self setPowerLevel:kRiotRoomAdminLevel promptUser:YES]; + [self setPowerLevel:RoomPowerLevelAdmin promptUser:YES]; break; } case MXKRoomMemberDetailsActionBan: diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 1ce43f6f2..14b54210f 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -1127,12 +1127,12 @@ // Update member badge MXRoomPowerLevels *powerLevels = [roomState powerLevels]; NSInteger powerLevel = [powerLevels powerLevelOfUserWithUserID:contact.mxMember.userId]; - if (powerLevel >= kRiotRoomAdminLevel) + if (powerLevel >= RoomPowerLevelAdmin) { participantCell.thumbnailBadgeView.image = [UIImage imageNamed:@"admin_icon"]; participantCell.thumbnailBadgeView.hidden = NO; } - else if (powerLevel >= kRiotRoomModeratorLevel) + else if (powerLevel >= RoomPowerLevelModerator) { participantCell.thumbnailBadgeView.image = [UIImage imageNamed:@"mod_icon"]; participantCell.thumbnailBadgeView.hidden = NO; From 1958f1b9fef9cc991d1cfd55201fcbef469b858e Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 12:55:23 +0100 Subject: [PATCH 050/244] reskin: Fix color of display name in RoomMemberDetailsVC --- .../Room/Members/Detail/RoomMemberDetailsViewController.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index c89d734aa..e9bef3823 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -224,7 +224,8 @@ self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; self.memberHeaderView.backgroundColor = ThemeService.shared.theme.baseColor; - self.roomMemberNameLabel.textColor = ThemeService.shared.theme.textPrimaryColor; + self.roomMemberNameLabel.textColor = ThemeService.shared.theme.baseTextPrimaryColor; + self.roomMemberStatusLabel.textColor = ThemeService.shared.theme.tintColor; // Check the table view style to select its bg color. From 478990ef65f95c16305270716ba73931af78840a Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 13:02:39 +0100 Subject: [PATCH 051/244] reskin: Fix mention color in dark theme --- Riot/Constants/Colors/DarkTheme.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index 0551f10c5..a66f8dac2 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -44,7 +44,7 @@ final class DarkTheme: NSObject, Theme { let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) let notificationUnreadColor: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationMentionColor: UIColor = UIColor(rgb: 0x3F4147) + let notificationMentionColor: UIColor = UIColor(rgb: 0xF56679) let avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), From 7efcf8f6c4e369c88e1a82cffd5c4dfe8a48cab2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 13:07:50 +0100 Subject: [PATCH 052/244] reskin: Theme: rename colors as it is in the palette now --- Riot/Constants/Colors/DarkTheme.swift | 4 ++-- Riot/Constants/Colors/DefaultTheme.swift | 4 ++-- Riot/Constants/Colors/Theme.swift | 6 ++++-- Riot/Modules/Common/Recents/Views/RecentTableViewCell.m | 2 +- Riot/Modules/Communities/Views/GroupInviteTableViewCell.m | 2 +- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 4 ++-- Riot/Modules/People/Views/InviteRecentTableViewCell.m | 2 +- Riot/Modules/Room/RoomViewController.m | 4 ++-- Riot/Modules/TabBar/MasterTabBarController.m | 6 +++--- Riot/Utils/EventFormatter.m | 2 +- 10 files changed, 19 insertions(+), 17 deletions(-) diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Constants/Colors/DarkTheme.swift index a66f8dac2..ba742d496 100644 --- a/Riot/Constants/Colors/DarkTheme.swift +++ b/Riot/Constants/Colors/DarkTheme.swift @@ -43,8 +43,8 @@ final class DarkTheme: NSObject, Theme { let tintColor: UIColor = UIColor(rgb: 0x7AC9A1) let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - let notificationUnreadColor: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationMentionColor: UIColor = UIColor(rgb: 0xF56679) + let notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) + let notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) let avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Constants/Colors/DefaultTheme.swift index 96794e9f5..ed81ba251 100644 --- a/Riot/Constants/Colors/DefaultTheme.swift +++ b/Riot/Constants/Colors/DefaultTheme.swift @@ -43,8 +43,8 @@ final class DefaultTheme: NSObject, Theme { let tintColor: UIColor = UIColor(rgb: 0x7AC9A1) let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - let notificationUnreadColor: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationMentionColor: UIColor = UIColor(rgb: 0xF56679) + let notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) + let notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) let avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Constants/Colors/Theme.swift index 82f7017a7..bbf46aa58 100644 --- a/Riot/Constants/Colors/Theme.swift +++ b/Riot/Constants/Colors/Theme.swift @@ -41,8 +41,10 @@ import UIKit var unreadRoomIndentColor: UIColor { get } - var notificationUnreadColor: UIColor { get } - var notificationMentionColor: UIColor { get } + /// Color for notifications for unread messages + var notificationSecondaryColor: UIColor { get } + /// Color for notifications for mention messages + var notificationPrimaryColor: UIColor { get } var avatarColors: [UIColor] { get } diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 368246820..cc0903d79 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -109,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 783cb420d..0152d8382 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -58,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = ThemeService.shared.riotColorBlue; self.rightButton.backgroundColor = ThemeService.shared.riotColorBlue; - self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; + self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index a9ccbd35f..1d9cb0f54 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -126,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -147,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index e094e6c85..993ed2a89 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -63,7 +63,7 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell self.leftButton.backgroundColor = ThemeService.shared.theme.tintColor; self.rightButton.backgroundColor = ThemeService.shared.theme.tintColor; - self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; + self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index f16e9cd7d..5f487e571 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4230,11 +4230,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationMentionColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationUnreadColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationSecondaryColor; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 2d89150c7..0e93fc032 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -798,15 +798,15 @@ // Use a middle dot to signal missed notif in favourites [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX - withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor)]; // Update the badge on People and Rooms tabs [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX - withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor)]; [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX - withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.notificationMentionColor : ThemeService.shared.theme.notificationUnreadColor)]; + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index ea370402d..7b893c038 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -220,7 +220,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor; self.subTitleTextColor = ThemeService.shared.theme.textSecondaryColor; self.prefixTextColor = ThemeService.shared.theme.textSecondaryColor; - self.bingTextColor = ThemeService.shared.theme.notificationMentionColor; + self.bingTextColor = ThemeService.shared.theme.notificationPrimaryColor; self.encryptingTextColor = ThemeService.shared.theme.tintColor; self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; self.errorTextColor = ThemeService.shared.riotColorRed; From 0d83d608421aa117210d3e41d945424a1a720a23 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 16:52:28 +0100 Subject: [PATCH 053/244] reskin: Fix theming in registration screens --- Riot/Modules/Authentication/AuthenticationViewController.m | 6 +++++- Riot/Modules/Authentication/Views/TermsView.swift | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index bfed3b3a4..af0ec0557 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -131,7 +131,11 @@ - (void)userInterfaceThemeDidChange { - [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + NSLog(@"### %@", self.navigationController); + NSLog(@"### %@", [AppDelegate theDelegate].masterTabBarController.navigationController); + + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationBar]; + //[ThemeService.shared.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; self.view.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index 480e0416b..ceec376fd 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -80,6 +80,8 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie } func customizeViewRendering() { + self.backgroundColor = UIColor.clear + self.tableView.backgroundColor = UIColor.clear acceptButton.backgroundColor = ThemeService.shared().theme.tintColor } @@ -137,6 +139,7 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie cell.label.text = policy.name cell.isEnabled = accepted cell.accessoryType = .disclosureIndicator + cell.backgroundColor = UIColor.clear let gesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapCheckbox)) From 65527426f709993ba663f73c0c48781ba3c807ee Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 16:58:59 +0100 Subject: [PATCH 054/244] reskin: CHANGES --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index ba143c122..6ce6d4344 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,7 @@ Changes in 0.7.x (2019-xx-xx) =============================================== Improvements: + * Theming: Create ThemeService to make theming easier. Use it to reskin Riot. * Use modern literals and array/dictionary syntax where possible (PR #2160). Bug fix: From cd375a34f0c845395d57c4b891bce95fdff98712 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 17:31:08 +0100 Subject: [PATCH 055/244] reskin: move theme files under Manager/Theme/ --- Riot.xcodeproj/project.pbxproj | 74 +++++++++---------- .../Colors => Managers/Theme}/Theme.swift | 0 .../Theme}/ThemeService.h | 0 .../Theme}/ThemeService.m | 0 .../Theme/Themes}/DarkTheme.swift | 0 .../Theme/Themes}/DefaultTheme.swift | 0 6 files changed, 37 insertions(+), 37 deletions(-) rename Riot/{Constants/Colors => Managers/Theme}/Theme.swift (100%) rename Riot/{Constants => Managers/Theme}/ThemeService.h (100%) rename Riot/{Constants => Managers/Theme}/ThemeService.m (100%) rename Riot/{Constants/Colors => Managers/Theme/Themes}/DarkTheme.swift (100%) rename Riot/{Constants/Colors => Managers/Theme/Themes}/DefaultTheme.swift (100%) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 24fc6db37..622751ebb 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -10,14 +10,16 @@ 24CBEC591F0EAD310093EABB /* RiotShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BBE81E7009EC00A9B29C /* MXRoom+Riot.m */; }; 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BC111E7009EC00A9B29C /* AvatarGenerator.m */; }; - 3223D9C021B00615000321C1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* Theme.swift */; }; - 3223D9C121B00615000321C1 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultTheme.swift */; }; - 3223D9C321B0065A000321C1 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkTheme.swift */; }; - 3223D9C421B0077D000321C1 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BE21B00615000321C1 /* Theme.swift */; }; - 3223D9C521B00781000321C1 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9C221B0065A000321C1 /* DarkTheme.swift */; }; - 3223D9C621B00788000321C1 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3223D9BF21B00615000321C1 /* DefaultTheme.swift */; }; 32242F0921E8B05F00725742 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0821E8B05F00725742 /* UIColor.swift */; }; 32242F0A21E8B21300725742 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0821E8B05F00725742 /* UIColor.swift */; }; + 32242F1221E8FBA900725742 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0C21E8FBA900725742 /* ThemeService.m */; }; + 32242F1321E8FBA900725742 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0D21E8FBA900725742 /* Theme.swift */; }; + 32242F1421E8FBA900725742 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0F21E8FBA900725742 /* DefaultTheme.swift */; }; + 32242F1521E8FBA900725742 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F1021E8FBA900725742 /* DarkTheme.swift */; }; + 32242F1621E8FBCC00725742 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0C21E8FBA900725742 /* ThemeService.m */; }; + 32242F1721E8FBE500725742 /* Theme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0D21E8FBA900725742 /* Theme.swift */; }; + 32242F1821E8FBF800725742 /* DefaultTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0F21E8FBA900725742 /* DefaultTheme.swift */; }; + 32242F1921E8FBFB00725742 /* DarkTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F1021E8FBA900725742 /* DarkTheme.swift */; }; 3233F7461F3497E2006ACA81 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; }; 3233F7471F3497E2006ACA81 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3275FD8B21A5A2C500B9C13D /* TermsView.swift */; }; @@ -53,8 +55,6 @@ B169329B20F39E6300746532 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B169329520F39E6300746532 /* Main.storyboard */; }; B16932A320F3A21C00746532 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B169329F20F3A21B00746532 /* main.m */; }; B16932A520F3A21C00746532 /* empty.mm in Sources */ = {isa = PBXBuildFile; fileRef = B16932A220F3A21B00746532 /* empty.mm */; }; - B16932AC20F3A7B100746532 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AB20F3A7B000746532 /* ThemeService.m */; }; - B16932AD20F3A7B100746532 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AB20F3A7B000746532 /* ThemeService.m */; }; B16932B120F3AC9200746532 /* RoomSearchDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932AF20F3AC9200746532 /* RoomSearchDataSource.m */; }; B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932E620F3C37100746532 /* HomeMessagesSearchDataSource.m */; }; B16932EA20F3C39000746532 /* UnifiedSearchRecentsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932E920F3C39000746532 /* UnifiedSearchRecentsDataSource.m */; }; @@ -390,10 +390,12 @@ 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = RiotShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 2510A69B4A681C1FEC36E848 /* Pods_RiotPods_Riot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_Riot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 319CD7C67A47A3D35959E18F /* Pods-RiotPods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.release.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.release.xcconfig"; sourceTree = ""; }; - 3223D9BE21B00615000321C1 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; - 3223D9BF21B00615000321C1 /* DefaultTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultTheme.swift; sourceTree = ""; }; - 3223D9C221B0065A000321C1 /* DarkTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkTheme.swift; sourceTree = ""; }; 32242F0821E8B05F00725742 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; + 32242F0C21E8FBA900725742 /* ThemeService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThemeService.m; sourceTree = ""; }; + 32242F0D21E8FBA900725742 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; + 32242F0F21E8FBA900725742 /* DefaultTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DefaultTheme.swift; sourceTree = ""; }; + 32242F1021E8FBA900725742 /* DarkTheme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DarkTheme.swift; sourceTree = ""; }; + 32242F1121E8FBA900725742 /* ThemeService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThemeService.h; sourceTree = ""; }; 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = JitsiMeet.framework; sourceTree = ""; }; 3267EFB320E379FD00FF1CAA /* CHANGES.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = CHANGES.rst; sourceTree = ""; }; 3267EFB420E379FD00FF1CAA /* Podfile */ = {isa = PBXFileReference; explicitFileType = text.script.ruby; fileEncoding = 4; path = Podfile; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; @@ -487,8 +489,6 @@ B16932A020F3A21B00746532 /* Riot.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Riot.entitlements; sourceTree = ""; }; B16932A120F3A21B00746532 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; B16932A220F3A21B00746532 /* empty.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = empty.mm; sourceTree = ""; }; - B16932AA20F3A7B000746532 /* ThemeService.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ThemeService.h; sourceTree = ""; }; - B16932AB20F3A7B000746532 /* ThemeService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThemeService.m; sourceTree = ""; }; B16932AF20F3AC9200746532 /* RoomSearchDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RoomSearchDataSource.m; sourceTree = ""; }; B16932B020F3AC9200746532 /* RoomSearchDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RoomSearchDataSource.h; sourceTree = ""; }; B16932E520F3C37100746532 /* HomeMessagesSearchDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HomeMessagesSearchDataSource.h; sourceTree = ""; }; @@ -984,14 +984,24 @@ path = RiotShareExtension; sourceTree = ""; }; - 3223D9BD21B00615000321C1 /* Colors */ = { + 32242F0B21E8FBA900725742 /* Theme */ = { isa = PBXGroup; children = ( - 3223D9BE21B00615000321C1 /* Theme.swift */, - 3223D9C221B0065A000321C1 /* DarkTheme.swift */, - 3223D9BF21B00615000321C1 /* DefaultTheme.swift */, + 32242F0C21E8FBA900725742 /* ThemeService.m */, + 32242F0D21E8FBA900725742 /* Theme.swift */, + 32242F1121E8FBA900725742 /* ThemeService.h */, + 32242F0E21E8FBA900725742 /* Themes */, ); - path = Colors; + path = Theme; + sourceTree = ""; + }; + 32242F0E21E8FBA900725742 /* Themes */ = { + isa = PBXGroup; + children = ( + 32242F0F21E8FBA900725742 /* DefaultTheme.swift */, + 32242F1021E8FBA900725742 /* DarkTheme.swift */, + ); + path = Themes; sourceTree = ""; }; 3233F7291F31F3B4006ACA81 /* libs */ = { @@ -1165,16 +1175,6 @@ path = SupportingFiles; sourceTree = ""; }; - B16932A620F3A6FA00746532 /* Constants */ = { - isa = PBXGroup; - children = ( - 3223D9BD21B00615000321C1 /* Colors */, - B16932AA20F3A7B000746532 /* ThemeService.h */, - B16932AB20F3A7B000746532 /* ThemeService.m */, - ); - path = Constants; - sourceTree = ""; - }; B16932AE20F3AC9200746532 /* DataSources */ = { isa = PBXGroup; children = ( @@ -2356,6 +2356,7 @@ B1B5598B20EFC5E400210D55 /* Analytics */, B1B5598920EFC41100210D55 /* BugReport */, B1B5598A20EFC42100210D55 /* Settings */, + 32242F0B21E8FBA900725742 /* Theme */, B1B5598020EFC3DF00210D55 /* Widgets */, ); path = Managers; @@ -2424,7 +2425,6 @@ children = ( F083BB0C1E7009EC00A9B29C /* AppDelegate.h */, F083BB0D1E7009EC00A9B29C /* AppDelegate.m */, - B16932A620F3A6FA00746532 /* Constants */, F083BBE41E7009EC00A9B29C /* Categories */, F083BBF21E7009EC00A9B29C /* Model */, B1B5597C20EFC3DF00210D55 /* Managers */, @@ -2984,20 +2984,20 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 3223D9C621B00788000321C1 /* DefaultTheme.swift in Sources */, B169328420F38BE300746532 /* SegmentedViewController.m in Sources */, - 3223D9C521B00781000321C1 /* DarkTheme.swift in Sources */, - B16932AD20F3A7B100746532 /* ThemeService.m in Sources */, + 32242F1821E8FBF800725742 /* DefaultTheme.swift in Sources */, B1664BCA20F4E67600808783 /* ShareViewController.m in Sources */, B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */, + 32242F1621E8FBCC00725742 /* ThemeService.m in Sources */, 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */, B1664BCF20F4E67600808783 /* ShareExtensionManager.m in Sources */, 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */, - 3223D9C421B0077D000321C1 /* Theme.swift in Sources */, B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */, F0A8955F1F7D1FEA00BD6C2A /* MXRoomSummary+Riot.m in Sources */, + 32242F1721E8FBE500725742 /* Theme.swift in Sources */, B169328320F38AE600746532 /* RiotSettings.swift in Sources */, 32242F0A21E8B21300725742 /* UIColor.swift in Sources */, + 32242F1921E8FBFB00725742 /* DarkTheme.swift in Sources */, B1664BC820F4E67600808783 /* ShareDataSource.m in Sources */, B1664BCD20F4E67600808783 /* RecentRoomTableViewCell.m in Sources */, B169331720F3CBE000746532 /* RecentCellData.m in Sources */, @@ -3018,7 +3018,6 @@ buildActionMask = 2147483647; files = ( B1B557D120EF5E3500210D55 /* MediaAlbumTableCell.m in Sources */, - B16932AC20F3A7B100746532 /* ThemeService.m in Sources */, B1B557A120EF58AD00210D55 /* ContactTableViewCell.m in Sources */, F083BE021E7009ED00A9B29C /* AvatarGenerator.m in Sources */, B1B5573A20EE6C4D00210D55 /* GroupRoomsViewController.m in Sources */, @@ -3043,6 +3042,7 @@ B1B5572220EE6C4D00210D55 /* RoomSettingsViewController.m in Sources */, B1B5577320EE702800210D55 /* JitsiViewController.m in Sources */, B169331620F3CAFC00746532 /* PublicRoomsDirectoryDataSource.m in Sources */, + 32242F1221E8FBA900725742 /* ThemeService.m in Sources */, B1B558E820EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */, B1B558F320EF768F00210D55 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, B1B557BD20EF5B4500210D55 /* KeyboardGrowingTextView.m in Sources */, @@ -3057,6 +3057,7 @@ B169330B20F3CA3A00746532 /* Contact.m in Sources */, B1B5599220EFC5E400210D55 /* Analytics.m in Sources */, B1B558C320EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m in Sources */, + 32242F1521E8FBA900725742 /* DarkTheme.swift in Sources */, B1B5577420EE702900210D55 /* WidgetViewController.m in Sources */, B1B5574A20EE6C4D00210D55 /* MediaPickerViewController.m in Sources */, B1B5598520EFC3E000210D55 /* RageShakeManager.m in Sources */, @@ -3086,6 +3087,8 @@ B1B558DD20EF768F00210D55 /* RoomIncomingEncryptedTextMsgBubbleCell.m in Sources */, B1B5573C20EE6C4D00210D55 /* MasterTabBarController.m in Sources */, B1B5592C20EF7A5D00210D55 /* TableViewCellWithButton.m in Sources */, + 32242F1421E8FBA900725742 /* DefaultTheme.swift in Sources */, + 32242F1321E8FBA900725742 /* Theme.swift in Sources */, B1B5582520EF638A00210D55 /* RoomMemberTitleView.m in Sources */, B1B5582C20EF666100210D55 /* DirectoryRecentTableViewCell.m in Sources */, B1B558E420EF768F00210D55 /* RoomMembershipWithPaginationTitleBubbleCell.m in Sources */, @@ -3121,7 +3124,6 @@ B1B5572620EE6C4D00210D55 /* RoomFilesSearchViewController.m in Sources */, B1B5583120EF66BA00210D55 /* RoomIdOrAliasTableViewCell.m in Sources */, F083BDFA1E7009ED00A9B29C /* RoomPreviewData.m in Sources */, - 3223D9C321B0065A000321C1 /* DarkTheme.swift in Sources */, B1B557B420EF5AEF00210D55 /* EventDetailsView.m in Sources */, B1B5577E20EE84BF00210D55 /* IncomingCallView.m in Sources */, B1B5578F20EF568D00210D55 /* GroupTableViewCell.m in Sources */, @@ -3147,7 +3149,6 @@ B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, B1B558CF20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B5575120EE6C4D00210D55 /* AuthenticationViewController.m in Sources */, - 3223D9C121B00615000321C1 /* DefaultTheme.swift in Sources */, B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */, B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */, B1B5575A20EE6C4D00210D55 /* UnifiedSearchViewController.m in Sources */, @@ -3182,7 +3183,6 @@ B1B558EE20EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.m in Sources */, B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, - 3223D9C021B00615000321C1 /* Theme.swift in Sources */, B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, diff --git a/Riot/Constants/Colors/Theme.swift b/Riot/Managers/Theme/Theme.swift similarity index 100% rename from Riot/Constants/Colors/Theme.swift rename to Riot/Managers/Theme/Theme.swift diff --git a/Riot/Constants/ThemeService.h b/Riot/Managers/Theme/ThemeService.h similarity index 100% rename from Riot/Constants/ThemeService.h rename to Riot/Managers/Theme/ThemeService.h diff --git a/Riot/Constants/ThemeService.m b/Riot/Managers/Theme/ThemeService.m similarity index 100% rename from Riot/Constants/ThemeService.m rename to Riot/Managers/Theme/ThemeService.m diff --git a/Riot/Constants/Colors/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift similarity index 100% rename from Riot/Constants/Colors/DarkTheme.swift rename to Riot/Managers/Theme/Themes/DarkTheme.swift diff --git a/Riot/Constants/Colors/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift similarity index 100% rename from Riot/Constants/Colors/DefaultTheme.swift rename to Riot/Managers/Theme/Themes/DefaultTheme.swift From 9ab70720920d3c765d1c5a1a9ff39e220fc6a125 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 11 Jan 2019 18:29:32 +0100 Subject: [PATCH 056/244] reskin: Fix Steve's remarks --- Riot/Managers/Theme/ThemeService.m | 15 +++++++++------ Riot/Managers/Theme/Themes/DarkTheme.swift | 4 +--- Riot/Managers/Theme/Themes/DefaultTheme.swift | 6 ++---- 3 files changed, 12 insertions(+), 13 deletions(-) diff --git a/Riot/Managers/Theme/ThemeService.m b/Riot/Managers/Theme/ThemeService.m index c7956e39b..ee216888c 100644 --- a/Riot/Managers/Theme/ThemeService.m +++ b/Riot/Managers/Theme/ThemeService.m @@ -55,18 +55,21 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan - (id)themeWithThemeId:(NSString*)themeId { - // Use light theme colors by default. - id theme = DefaultTheme.shared; + id theme; if ([themeId isEqualToString:@"dark"]) { - // Set dark theme colors - theme = DarkTheme.shared; + theme = [DarkTheme new]; } else if ([themeId isEqualToString:@"black"]) { - // TODO: Use dark theme colors for the moment - theme = DarkTheme.shared; + // TODO: Use dark theme for the moment + theme = [DarkTheme new]; + } + else + { + // Use light theme by default + theme = [DefaultTheme new]; } return theme; diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index ba742d496..0ba6f25dd 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -17,12 +17,10 @@ import Foundation import UIKit -/// Color constants for the dart theme +/// Color constants for the dark theme @objcMembers final class DarkTheme: NSObject, Theme { - static let shared = DarkTheme() - let backgroundColor: UIColor = UIColor(rgb: 0x212224) let baseColor: UIColor = UIColor(rgb: 0x292E37) diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index ed81ba251..55bcc096a 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -21,8 +21,6 @@ import UIKit @objcMembers final class DefaultTheme: NSObject, Theme { - static let shared = DefaultTheme() - let backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) let baseColor: UIColor = UIColor(rgb: 0x2E3648) @@ -55,8 +53,8 @@ final class DefaultTheme: NSObject, Theme { let scrollBarStyle: UIScrollViewIndicatorStyle = .default let keyboardAppearance: UIKeyboardAppearance = .light - var placeholderTextColor: UIColor? // Use default 70% gray color - var selectedBackgroundColor: UIColor? // Use the default selection color + let placeholderTextColor: UIColor? = nil // Use default 70% gray color + let selectedBackgroundColor: UIColor? = nil // Use the default selection color let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) From 208e0fe6b415e407cbe82485482b310bf256add2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 14 Jan 2019 10:53:43 +0100 Subject: [PATCH 057/244] reskin: Kill KVO on theme setting --- Riot/AppDelegate.m | 3 ++ Riot/Managers/Theme/ThemeService.h | 5 +- Riot/Managers/Theme/ThemeService.m | 52 +++++++------------ .../Modules/Settings/SettingsViewController.m | 1 + 4 files changed, 27 insertions(+), 34 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 4f0a971ad..0f6ccb1f4 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -403,6 +403,9 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [self setupUserDefaults]; + // Set up theme + ThemeService.shared.themeId = RiotSettings.shared.userInterfaceTheme; + // Set up runtime language and fallback by considering the userDefaults object shared within the application group. NSUserDefaults *sharedUserDefaults = [MXKAppSettings standardAppSettings].sharedUserDefaults; NSString *language = [sharedUserDefaults objectForKey:@"appLanguage"]; diff --git a/Riot/Managers/Theme/ThemeService.h b/Riot/Managers/Theme/ThemeService.h index eaeadf7c7..553b87156 100644 --- a/Riot/Managers/Theme/ThemeService.h +++ b/Riot/Managers/Theme/ThemeService.h @@ -41,12 +41,13 @@ extern NSString *const kThemeServiceDidChangeThemeNotification; + (instancetype)shared; /** - The id of the theme corresponding to the current app settings. + The id of the theme being used. */ -@property (nonatomic, readonly) NSString *themeId; +@property (nonatomic, nullable) NSString *themeId; /** The current theme. + Default value is the Default theme. */ @property (nonatomic, readonly) id theme; diff --git a/Riot/Managers/Theme/ThemeService.m b/Riot/Managers/Theme/ThemeService.m index ee216888c..283340271 100644 --- a/Riot/Managers/Theme/ThemeService.m +++ b/Riot/Managers/Theme/ThemeService.m @@ -27,6 +27,7 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChangeThemeNotification"; @implementation ThemeService +@synthesize themeId; + (ThemeService *)shared { @@ -40,23 +41,32 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan return sharedOnceInstance; } -- (NSString*)themeId +- (void)setThemeId:(NSString *)theThemeId { - // Retrieve the current selected theme ("light" if none. "auto" is used as default from iOS 11). - NSString *themeId = RiotSettings.shared.userInterfaceTheme; + // Update the current theme + themeId = theThemeId; + self.theme = [self themeWithThemeId:self.themeId]; +} - if (!themeId || [themeId isEqualToString:@"auto"]) - { - themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; - } +- (void)setTheme:(id _Nonnull)theme +{ + _theme = theme; - return themeId; + [UIScrollView appearance].indicatorStyle = self.theme.scrollBarStyle; + + [[NSNotificationCenter defaultCenter] postNotificationName:kThemeServiceDidChangeThemeNotification object:nil]; } - (id)themeWithThemeId:(NSString*)themeId { id theme; + if ([themeId isEqualToString:@"auto"]) + { + // Translate "auto" into a theme + themeId = UIAccessibilityIsInvertColorsEnabled() ? @"dark" : @"light"; + } + if ([themeId isEqualToString:@"dark"]) { theme = [DarkTheme new]; @@ -90,42 +100,20 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan _riotColorIndigo = [[UIColor alloc] initWithRgb:0xBD79CC]; _riotColorOrange = [[UIColor alloc] initWithRgb:0xF8A15F]; - // Observe user interface theme change. - [[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"userInterfaceTheme" options:0 context:nil]; - [self userInterfaceThemeDidChange]; - // Observe "Invert Colours" settings changes (available since iOS 11) [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(accessibilityInvertColorsStatusDidChange) name:UIAccessibilityInvertColorsStatusDidChangeNotification object:nil]; } return self; } -- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context -{ - if ([@"userInterfaceTheme" isEqualToString:keyPath]) - { - [self userInterfaceThemeDidChange]; - } -} - - (void)accessibilityInvertColorsStatusDidChange { // Refresh the theme only for "auto" - NSString *theme = RiotSettings.shared.userInterfaceTheme; - if (!theme || [theme isEqualToString:@"auto"]) + if ([self.themeId isEqualToString:@"auto"]) { - [self userInterfaceThemeDidChange]; + self.theme = [self themeWithThemeId:self.themeId]; } } -- (void)userInterfaceThemeDidChange -{ - // Update the current theme - _theme = [self themeWithThemeId:self.themeId]; - - [UIScrollView appearance].indicatorStyle = self.theme.scrollBarStyle; - - [[NSNotificationCenter defaultCenter] postNotificationName:kThemeServiceDidChangeThemeNotification object:nil]; -} @end diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 48703c93a..589054c68 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -3778,6 +3778,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // The user wants to select this theme RiotSettings.shared.userInterfaceTheme = newTheme; + ThemeService.shared.themeId = newTheme; [self.tableView reloadData]; } From 1dd6db21f18f0bf0fc9615c188a0e7ae8a4d7ffd Mon Sep 17 00:00:00 2001 From: manuroe Date: Mon, 14 Jan 2019 13:57:53 +0100 Subject: [PATCH 058/244] reskin: Kill KVO on theme setting --- Riot/Managers/Theme/ThemeService.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Managers/Theme/ThemeService.m b/Riot/Managers/Theme/ThemeService.m index 283340271..a12fafa04 100644 --- a/Riot/Managers/Theme/ThemeService.m +++ b/Riot/Managers/Theme/ThemeService.m @@ -27,7 +27,7 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChangeThemeNotification"; @implementation ThemeService -@synthesize themeId; +@synthesize themeId = _themeId; + (ThemeService *)shared { @@ -44,7 +44,7 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan - (void)setThemeId:(NSString *)theThemeId { // Update the current theme - themeId = theThemeId; + _themeId = theThemeId; self.theme = [self themeWithThemeId:self.themeId]; } From 87dd510197555fa9723dcd5452b4e8ee4472f3b3 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 14 Jan 2019 17:00:36 +0100 Subject: [PATCH 059/244] Add SwiftGen pod in order to generate Swift constants for assets (strings, images, storyboards, etc.). --- Podfile | 4 +++- Podfile.lock | 6 +++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Podfile b/Podfile index 4dc3be87d..045542561 100644 --- a/Podfile +++ b/Podfile @@ -76,7 +76,9 @@ abstract_target 'RiotPods' do pod 'OLMKit', :inhibit_warnings => true pod 'cmark', :inhibit_warnings => true pod 'DTCoreText', :inhibit_warnings => true - + + # Tools + pod 'SwiftGen', '~> 6.0' target "Riot" do import_MatrixKit diff --git a/Podfile.lock b/Podfile.lock index f885f7c7c..f171f0980 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -93,6 +93,7 @@ PODS: - Reusable/View (= 4.0.5) - Reusable/Storyboard (4.0.5) - Reusable/View (4.0.5) + - SwiftGen (6.0.2) - WebRTC (63.11.20455) DEPENDENCIES: @@ -106,6 +107,7 @@ DEPENDENCIES: - OLMKit - PiwikTracker (from `https://github.com/manuroe/matomo-sdk-ios.git`, branch `feature/CustomVariables`) - Reusable (~> 4.0) + - SwiftGen (~> 6.0) SPEC REPOS: https://github.com/cocoapods/specs.git: @@ -123,6 +125,7 @@ SPEC REPOS: - OLMKit - Realm - Reusable + - SwiftGen - WebRTC EXTERNAL SOURCES: @@ -151,8 +154,9 @@ SPEC CHECKSUMS: PiwikTracker: 42862c7b13028065c3dfd36b4dc38db8a5765acf Realm: 864477d028db77f7c5a0cba64a4892ad53db128a Reusable: 188be1a54ac0691bc66e5bb24ec6eb91971b315b + SwiftGen: e5b047067aa84082826a0c4f1c4c2ddc95bcf74c WebRTC: f2a6203584745fe53532633397557876b5d71640 -PODFILE CHECKSUM: fc0574145026734bcc9f3266b7b92f815ebf97e4 +PODFILE CHECKSUM: bbb50681758f3933fb8bfdfdcc03272cdcf7d167 COCOAPODS: 1.6.0.beta.2 From 91e7757c5b8dc347d1da862871be039a9eaa183e Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 14 Jan 2019 17:01:29 +0100 Subject: [PATCH 060/244] Add SwiftGen configuration file --- Tools/SwiftGen/swiftgen-config.yml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 Tools/SwiftGen/swiftgen-config.yml diff --git a/Tools/SwiftGen/swiftgen-config.yml b/Tools/SwiftGen/swiftgen-config.yml new file mode 100755 index 000000000..716c45725 --- /dev/null +++ b/Tools/SwiftGen/swiftgen-config.yml @@ -0,0 +1,29 @@ +input_dir: ../../Riot/ +output_dir: ../../Riot/Generated/ +ib: + - inputs: + - Assets/Base.lproj/LaunchScreen.storyboard + outputs: + - templateName: scenes-swift4 + output: Storyboards.swift +strings: + inputs: Assets/en.lproj/Vector.strings + outputs: + - templateName: flat-swift4 + output: Strings.swift + params: + enumName: VectorL10n +xcassets: + - inputs: + - Assets/Images.xcassets + - Assets/SharedImages.xcassets + outputs: + - templateName: swift4 + output: Images.swift +plist: + inputs: Assets/Riot-Defaults.plist + outputs: + templateName: runtime-swift4 + output: RiotDefaults.swift + params: + enumName: RiotDefaults \ No newline at end of file From 2c60efc0517e6aaae0a7a0d951791fa4759b3dfe Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 14 Jan 2019 17:04:40 +0100 Subject: [PATCH 061/244] Add SwiftGen to Riot build phases and generate constants --- Riot.xcodeproj/project.pbxproj | 43 ++ Riot/Generated/Images.swift | 198 +++++ Riot/Generated/RiotDefaults.swift | 79 ++ Riot/Generated/Storyboards.swift | 60 ++ Riot/Generated/Strings.swift | 1185 +++++++++++++++++++++++++++++ 5 files changed, 1565 insertions(+) create mode 100644 Riot/Generated/Images.swift create mode 100644 Riot/Generated/RiotDefaults.swift create mode 100644 Riot/Generated/Storyboards.swift create mode 100644 Riot/Generated/Strings.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 622751ebb..bbef3414d 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -31,6 +31,10 @@ 92726A471F58737A004AD26F /* IntentHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 92726A461F58737A004AD26F /* IntentHandler.m */; }; 92726A4B1F58737A004AD26F /* SiriIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 92726A431F58737A004AD26F /* SiriIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 92726A511F587410004AD26F /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92726A501F587410004AD26F /* Intents.framework */; }; + B1098BDF21ECE09F000DDA48 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDA21ECE09E000DDA48 /* Strings.swift */; }; + B1098BE121ECE09F000DDA48 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDC21ECE09E000DDA48 /* Images.swift */; }; + B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */; }; + B1098BE521ECE1FC000DDA48 /* Storyboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BE421ECE1FC000DDA48 /* Storyboards.swift */; }; B1664BC520F4E67600808783 /* FallbackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1664BAD20F4E67500808783 /* FallbackViewController.xib */; }; B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BAE20F4E67500808783 /* FallbackViewController.m */; }; B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BB220F4E67500808783 /* SharePresentingViewController.m */; }; @@ -429,6 +433,10 @@ 92726A481F58737A004AD26F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 92726A4F1F587393004AD26F /* SiriIntents.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SiriIntents.entitlements; sourceTree = ""; }; 92726A501F587410004AD26F /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; + B1098BDA21ECE09E000DDA48 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; + B1098BDC21ECE09E000DDA48 /* Images.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = ""; }; + B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiotDefaults.swift; sourceTree = ""; }; + B1098BE421ECE1FC000DDA48 /* Storyboards.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storyboards.swift; sourceTree = ""; }; B1664BAD20F4E67500808783 /* FallbackViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FallbackViewController.xib; sourceTree = ""; }; B1664BAE20F4E67500808783 /* FallbackViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FallbackViewController.m; sourceTree = ""; }; B1664BAF20F4E67500808783 /* FallbackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FallbackViewController.h; sourceTree = ""; }; @@ -1063,6 +1071,17 @@ name = Pods; sourceTree = ""; }; + B1098BD921ECE09E000DDA48 /* Generated */ = { + isa = PBXGroup; + children = ( + B1098BDA21ECE09E000DDA48 /* Strings.swift */, + B1098BDC21ECE09E000DDA48 /* Images.swift */, + B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */, + B1098BE421ECE1FC000DDA48 /* Storyboards.swift */, + ); + path = Generated; + sourceTree = ""; + }; B1664BAB20F4E67500808783 /* Modules */ = { isa = PBXGroup; children = ( @@ -2425,6 +2444,7 @@ children = ( F083BB0C1E7009EC00A9B29C /* AppDelegate.h */, F083BB0D1E7009EC00A9B29C /* AppDelegate.m */, + B1098BD921ECE09E000DDA48 /* Generated */, F083BBE41E7009EC00A9B29C /* Categories */, F083BBF21E7009EC00A9B29C /* Model */, B1B5597C20EFC3DF00210D55 /* Managers */, @@ -2595,6 +2615,7 @@ buildConfigurationList = F094A9C81B78D8F000B1FBBF /* Build configuration list for PBXNativeTarget "Riot" */; buildPhases = ( E34E30CD2CEE4A42FF8081D6 /* [CP] Check Pods Manifest.lock */, + B1098BD821ECD3ED000DDA48 /* 🛠 SwiftGen */, F094A99E1B78D8F000B1FBBF /* Sources */, F094A99F1B78D8F000B1FBBF /* Frameworks */, F094A9A01B78D8F000B1FBBF /* Resources */, @@ -2959,6 +2980,24 @@ shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; + B1098BD821ECD3ED000DDA48 /* 🛠 SwiftGen */ = { + isa = PBXShellScriptBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + inputFileListPaths = ( + ); + inputPaths = ( + ); + name = "🛠 SwiftGen"; + outputFileListPaths = ( + ); + outputPaths = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "${PODS_ROOT}/SwiftGen/bin/swiftgen config run --config Tools/SwiftGen/swiftgen-config.yml\n"; + }; E34E30CD2CEE4A42FF8081D6 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; @@ -3051,6 +3090,7 @@ F083BDEE1E7009ED00A9B29C /* MXRoom+Riot.m in Sources */, B1B5598620EFC3E000210D55 /* RiotSettings.swift in Sources */, B1B5581720EF625800210D55 /* PreviewRoomTitleView.m in Sources */, + B1098BDF21ECE09F000DDA48 /* Strings.swift in Sources */, B1B558C420EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, B1B5572F20EE6C4D00210D55 /* ReadReceiptsViewController.m in Sources */, B1B558CB20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */, @@ -3085,6 +3125,7 @@ B1B5571920EE6C4D00210D55 /* LanguagePickerViewController.m in Sources */, B1B5590520EF768F00210D55 /* RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m in Sources */, B1B558DD20EF768F00210D55 /* RoomIncomingEncryptedTextMsgBubbleCell.m in Sources */, + B1098BE521ECE1FC000DDA48 /* Storyboards.swift in Sources */, B1B5573C20EE6C4D00210D55 /* MasterTabBarController.m in Sources */, B1B5592C20EF7A5D00210D55 /* TableViewCellWithButton.m in Sources */, 32242F1421E8FBA900725742 /* DefaultTheme.swift in Sources */, @@ -3134,6 +3175,7 @@ B1B5577120EE702800210D55 /* StickerPickerViewController.m in Sources */, B1B5572020EE6C4D00210D55 /* ContactsTableViewController.m in Sources */, B1B5581920EF625800210D55 /* RoomTitleView.m in Sources */, + B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */, B1B557BE20EF5B4500210D55 /* RoomInputToolbarView.m in Sources */, B1B5573B20EE6C4D00210D55 /* FavouritesViewController.m in Sources */, B1B5579920EF575B00210D55 /* AuthInputsView.m in Sources */, @@ -3151,6 +3193,7 @@ B1B5575120EE6C4D00210D55 /* AuthenticationViewController.m in Sources */, B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */, B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */, + B1098BE121ECE09F000DDA48 /* Images.swift in Sources */, B1B5575A20EE6C4D00210D55 /* UnifiedSearchViewController.m in Sources */, B1B5572820EE6C4D00210D55 /* RoomViewController.m in Sources */, B1B558C720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */, diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift new file mode 100644 index 000000000..b2185823e --- /dev/null +++ b/Riot/Generated/Images.swift @@ -0,0 +1,198 @@ +// swiftlint:disable all +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +#if os(OSX) + import AppKit.NSImage + internal typealias AssetColorTypeAlias = NSColor + internal typealias AssetImageTypeAlias = NSImage +#elseif os(iOS) || os(tvOS) || os(watchOS) + import UIKit.UIImage + internal typealias AssetColorTypeAlias = UIColor + internal typealias AssetImageTypeAlias = UIImage +#endif + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Asset Catalogs + +// swiftlint:disable identifier_name line_length nesting type_body_length type_name +internal enum Asset { + internal enum Images { + internal static let callAudioMuteOffIcon = ImageAsset(name: "call_audio_mute_off_icon") + internal static let callAudioMuteOnIcon = ImageAsset(name: "call_audio_mute_on_icon") + internal static let callChatIcon = ImageAsset(name: "call_chat_icon") + internal static let callHangupIcon = ImageAsset(name: "call_hangup_icon") + internal static let callSpeakerOffIcon = ImageAsset(name: "call_speaker_off_icon") + internal static let callSpeakerOnIcon = ImageAsset(name: "call_speaker_on_icon") + internal static let callVideoMuteOffIcon = ImageAsset(name: "call_video_mute_off_icon") + internal static let callVideoMuteOnIcon = ImageAsset(name: "call_video_mute_on_icon") + internal static let cameraSwitch = ImageAsset(name: "camera_switch") + internal static let riotIconCallkit = ImageAsset(name: "riot_icon_callkit") + internal static let adminIcon = ImageAsset(name: "admin_icon") + internal static let backIcon = ImageAsset(name: "back_icon") + internal static let chevron = ImageAsset(name: "chevron") + internal static let disclosureIcon = ImageAsset(name: "disclosure_icon") + internal static let group = ImageAsset(name: "group") + internal static let logo = ImageAsset(name: "logo") + internal static let placeholder = ImageAsset(name: "placeholder") + internal static let plusIcon = ImageAsset(name: "plus_icon") + internal static let removeIcon = ImageAsset(name: "remove_icon") + internal static let selectionTick = ImageAsset(name: "selection_tick") + internal static let selectionUntick = ImageAsset(name: "selection_untick") + internal static let shrinkIcon = ImageAsset(name: "shrink_icon") + internal static let startChat = ImageAsset(name: "start_chat") + internal static let addGroupParticipant = ImageAsset(name: "add_group_participant") + internal static let createGroup = ImageAsset(name: "create_group") + internal static let removeIconBlue = ImageAsset(name: "remove_icon_blue") + internal static let riotIcon = ImageAsset(name: "riot_icon") + internal static let e2eBlocked = ImageAsset(name: "e2e_blocked") + internal static let e2eUnencrypted = ImageAsset(name: "e2e_unencrypted") + internal static let e2eWarning = ImageAsset(name: "e2e_warning") + internal static let directChatOff = ImageAsset(name: "directChatOff") + internal static let directChatOn = ImageAsset(name: "directChatOn") + internal static let favourite = ImageAsset(name: "favourite") + internal static let favouriteOff = ImageAsset(name: "favouriteOff") + internal static let leave = ImageAsset(name: "leave") + internal static let notifications = ImageAsset(name: "notifications") + internal static let notificationsOff = ImageAsset(name: "notificationsOff") + internal static let priorityHigh = ImageAsset(name: "priorityHigh") + internal static let priorityLow = ImageAsset(name: "priorityLow") + internal static let createRoom = ImageAsset(name: "create_room") + internal static let launchScreenRiot = ImageAsset(name: "LaunchScreenRiot") + internal static let cameraCapture = ImageAsset(name: "camera_capture") + internal static let cameraPlay = ImageAsset(name: "camera_play") + internal static let cameraStop = ImageAsset(name: "camera_stop") + internal static let cameraVideoCapture = ImageAsset(name: "camera_video_capture") + internal static let videoIcon = ImageAsset(name: "video_icon") + internal static let createDirectChat = ImageAsset(name: "create_direct_chat") + internal static let error = ImageAsset(name: "error") + internal static let newmessages = ImageAsset(name: "newmessages") + internal static let scrolldown = ImageAsset(name: "scrolldown") + internal static let scrollup = ImageAsset(name: "scrollup") + internal static let typing = ImageAsset(name: "typing") + internal static let uploadIcon = ImageAsset(name: "upload_icon") + internal static let voiceCallIcon = ImageAsset(name: "voice_call_icon") + internal static let addParticipant = ImageAsset(name: "add_participant") + internal static let appsIcon = ImageAsset(name: "apps-icon") + internal static let detailsIcon = ImageAsset(name: "details_icon") + internal static let editIcon = ImageAsset(name: "edit_icon") + internal static let jumpToUnread = ImageAsset(name: "jump_to_unread") + internal static let mainAliasIcon = ImageAsset(name: "main_alias_icon") + internal static let membersListIcon = ImageAsset(name: "members_list_icon") + internal static let modIcon = ImageAsset(name: "mod_icon") + internal static let fileDocIcon = ImageAsset(name: "file_doc_icon") + internal static let fileMusicIcon = ImageAsset(name: "file_music_icon") + internal static let filePhotoIcon = ImageAsset(name: "file_photo_icon") + internal static let fileVideoIcon = ImageAsset(name: "file_video_icon") + internal static let searchBg = ImageAsset(name: "search_bg") + internal static let searchIcon = ImageAsset(name: "search_icon") + internal static let removeIconPink = ImageAsset(name: "remove_icon_pink") + internal static let settingsIcon = ImageAsset(name: "settings_icon") + internal static let tabFavourites = ImageAsset(name: "tab_favourites") + internal static let tabFavouritesSelected = ImageAsset(name: "tab_favourites_selected") + internal static let tabGroups = ImageAsset(name: "tab_groups") + internal static let tabGroupsSelected = ImageAsset(name: "tab_groups_selected") + internal static let tabHome = ImageAsset(name: "tab_home") + internal static let tabHomeSelected = ImageAsset(name: "tab_home_selected") + internal static let tabPeople = ImageAsset(name: "tab_people") + internal static let tabPeopleSelected = ImageAsset(name: "tab_people_selected") + internal static let tabRooms = ImageAsset(name: "tab_rooms") + internal static let tabRoomsSelected = ImageAsset(name: "tab_rooms_selected") + } + internal enum SharedImages { + internal static let animatedLogo0 = ImageAsset(name: "animatedLogo-0") + internal static let animatedLogo1 = ImageAsset(name: "animatedLogo-1") + internal static let animatedLogo2 = ImageAsset(name: "animatedLogo-2") + internal static let animatedLogo3 = ImageAsset(name: "animatedLogo-3") + internal static let animatedLogo4 = ImageAsset(name: "animatedLogo-4") + internal static let cancel = ImageAsset(name: "cancel") + internal static let e2eVerified = ImageAsset(name: "e2e_verified") + } +} +// swiftlint:enable identifier_name line_length nesting type_body_length type_name + +// MARK: - Implementation Details + +internal struct ColorAsset { + internal fileprivate(set) var name: String + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, OSX 10.13, *) + internal var color: AssetColorTypeAlias { + return AssetColorTypeAlias(asset: self) + } +} + +internal extension AssetColorTypeAlias { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, OSX 10.13, *) + convenience init!(asset: ColorAsset) { + let bundle = Bundle(for: BundleToken.self) + #if os(iOS) || os(tvOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(OSX) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +internal struct DataAsset { + internal fileprivate(set) var name: String + + #if os(iOS) || os(tvOS) || os(OSX) + @available(iOS 9.0, tvOS 9.0, OSX 10.11, *) + internal var data: NSDataAsset { + return NSDataAsset(asset: self) + } + #endif +} + +#if os(iOS) || os(tvOS) || os(OSX) +@available(iOS 9.0, tvOS 9.0, OSX 10.11, *) +internal extension NSDataAsset { + convenience init!(asset: DataAsset) { + let bundle = Bundle(for: BundleToken.self) + #if os(iOS) || os(tvOS) + self.init(name: asset.name, bundle: bundle) + #elseif os(OSX) + self.init(name: NSDataAsset.Name(asset.name), bundle: bundle) + #endif + } +} +#endif + +internal struct ImageAsset { + internal fileprivate(set) var name: String + + internal var image: AssetImageTypeAlias { + let bundle = Bundle(for: BundleToken.self) + #if os(iOS) || os(tvOS) + let image = AssetImageTypeAlias(named: name, in: bundle, compatibleWith: nil) + #elseif os(OSX) + let image = bundle.image(forResource: NSImage.Name(name)) + #elseif os(watchOS) + let image = AssetImageTypeAlias(named: name) + #endif + guard let result = image else { fatalError("Unable to load image named \(name).") } + return result + } +} + +internal extension AssetImageTypeAlias { + @available(iOS 1.0, tvOS 1.0, watchOS 1.0, *) + @available(OSX, deprecated, + message: "This initializer is unsafe on macOS, please use the ImageAsset.image property") + convenience init!(asset: ImageAsset) { + #if os(iOS) || os(tvOS) + let bundle = Bundle(for: BundleToken.self) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(OSX) + self.init(named: NSImage.Name(asset.name)) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} + +private final class BundleToken {} diff --git a/Riot/Generated/RiotDefaults.swift b/Riot/Generated/RiotDefaults.swift new file mode 100644 index 000000000..66279954e --- /dev/null +++ b/Riot/Generated/RiotDefaults.swift @@ -0,0 +1,79 @@ +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +import Foundation + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Plist Files + +// swiftlint:disable identifier_name line_length type_body_length +internal enum RiotDefaults { + private static let _document = PlistDocument(path: "Riot-Defaults.plist") + + internal static let bugReportApp: String = _document["bugReportApp"] + internal static let bugReportEndpointUrl: String = _document["bugReportEndpointUrl"] + internal static let createConferenceCallsWithJitsi: Bool = _document["createConferenceCallsWithJitsi"] + internal static let enableRageShake: Bool = _document["enableRageShake"] + internal static let homeserver: String = _document["homeserver"] + internal static let homeserverurl: String = _document["homeserverurl"] + internal static let identityserverurl: String = _document["identityserverurl"] + internal static let integrationsRestUrl: String = _document["integrationsRestUrl"] + internal static let integrationsUiUrl: String = _document["integrationsUiUrl"] + internal static let matrixApps: Bool = _document["matrixApps"] + internal static let maxAllowedMediaCacheSize: Int = _document["maxAllowedMediaCacheSize"] + internal static let pinRoomsWithMissedNotif: Bool = _document["pinRoomsWithMissedNotif"] + internal static let pinRoomsWithUnread: Bool = _document["pinRoomsWithUnread"] + internal static let piwik: [String: Any] = _document["piwik"] + internal static let presenceColorForOfflineUser: Int = _document["presenceColorForOfflineUser"] + internal static let presenceColorForOnlineUser: Int = _document["presenceColorForOnlineUser"] + internal static let presenceColorForUnavailableUser: Int = _document["presenceColorForUnavailableUser"] + internal static let pushGatewayURL: String = _document["pushGatewayURL"] + internal static let pushKitAppIdProd: String = _document["pushKitAppIdProd"] + internal static let pusherAppIdDev: String = _document["pusherAppIdDev"] + internal static let pusherAppIdProd: String = _document["pusherAppIdProd"] + internal static let roomDirectoryServers: [String: Any] = _document["roomDirectoryServers"] + internal static let showAllEventsInRoomHistory: Bool = _document["showAllEventsInRoomHistory"] + internal static let showLeftMembersInRoomMemberList: Bool = _document["showLeftMembersInRoomMemberList"] + internal static let showRedactionsInRoomHistory: Bool = _document["showRedactionsInRoomHistory"] + internal static let showUnsupportedEventsInRoomHistory: Bool = _document["showUnsupportedEventsInRoomHistory"] + internal static let sortRoomMembersUsingLastSeenTime: Bool = _document["sortRoomMembersUsingLastSeenTime"] + internal static let syncLocalContacts: Bool = _document["syncLocalContacts"] + internal static let webAppUrl: String = _document["webAppUrl"] + internal static let webAppUrlBeta: String = _document["webAppUrlBeta"] + internal static let webAppUrlDev: String = _document["webAppUrlDev"] +} +// swiftlint:enable identifier_name line_length type_body_length + +// MARK: - Implementation Details + +private func arrayFromPlist(at path: String) -> [T] { + let bundle = Bundle(for: BundleToken.self) + guard let url = bundle.url(forResource: path, withExtension: nil), + let data = NSArray(contentsOf: url) as? [T] else { + fatalError("Unable to load PLIST at path: \(path)") + } + return data +} + +private struct PlistDocument { + let data: [String: Any] + + init(path: String) { + let bundle = Bundle(for: BundleToken.self) + guard let url = bundle.url(forResource: path, withExtension: nil), + let data = NSDictionary(contentsOf: url) as? [String: Any] else { + fatalError("Unable to load PLIST at path: \(path)") + } + self.data = data + } + + subscript(key: String) -> T { + guard let result = data[key] as? T else { + fatalError("Property '\(key)' is not of type \(T.self)") + } + return result + } +} + +private final class BundleToken {} diff --git a/Riot/Generated/Storyboards.swift b/Riot/Generated/Storyboards.swift new file mode 100644 index 000000000..7a6f36b77 --- /dev/null +++ b/Riot/Generated/Storyboards.swift @@ -0,0 +1,60 @@ +// swiftlint:disable all +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +// swiftlint:disable sorted_imports +import Foundation +import UIKit + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Storyboard Scenes + +// swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name +internal enum StoryboardScene { + internal enum LaunchScreen: StoryboardType { + internal static let storyboardName = "LaunchScreen" + + internal static let initialScene = InitialSceneType(storyboard: LaunchScreen.self) + } +} +// swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name + +// MARK: - Implementation Details + +internal protocol StoryboardType { + static var storyboardName: String { get } +} + +internal extension StoryboardType { + static var storyboard: UIStoryboard { + let name = self.storyboardName + return UIStoryboard(name: name, bundle: Bundle(for: BundleToken.self)) + } +} + +internal struct SceneType { + internal let storyboard: StoryboardType.Type + internal let identifier: String + + internal func instantiate() -> T { + let identifier = self.identifier + guard let controller = storyboard.storyboard.instantiateViewController(withIdentifier: identifier) as? T else { + fatalError("ViewController '\(identifier)' is not of the expected class \(T.self).") + } + return controller + } +} + +internal struct InitialSceneType { + internal let storyboard: StoryboardType.Type + + internal func instantiate() -> T { + guard let controller = storyboard.storyboard.instantiateInitialViewController() as? T else { + fatalError("ViewController is not of the expected class \(T.self).") + } + return controller + } +} + +private final class BundleToken {} diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift new file mode 100644 index 000000000..fc980242a --- /dev/null +++ b/Riot/Generated/Strings.swift @@ -0,0 +1,1185 @@ +// swiftlint:disable all +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +import Foundation + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Strings + +// swiftlint:disable function_parameter_count identifier_name line_length type_body_length +internal enum VectorL10n { + /// Accept + internal static let accept = VectorL10n.tr("Vector", "accept") + /// Logout all accounts + internal static let accountLogoutAll = VectorL10n.tr("Vector", "account_logout_all") + /// Active Call + internal static let activeCall = VectorL10n.tr("Vector", "active_call") + /// Active Call (%@) + internal static func activeCallDetails(_ p1: String) -> String { + return VectorL10n.tr("Vector", "active_call_details", p1) + } + /// Please review and accept the policies of this homeserver: + internal static let authAcceptPolicies = VectorL10n.tr("Vector", "auth_accept_policies") + /// Add an email address and a phone number to your account to let users discover you. Email address will also let you reset your password. + internal static let authAddEmailAndPhoneMessage = VectorL10n.tr("Vector", "auth_add_email_and_phone_message") + /// Registration with email and phone number at once is not supported yet until the api exists. Only the phone number will be taken into account. You may add your email to your profile in settings. + internal static let authAddEmailAndPhoneWarning = VectorL10n.tr("Vector", "auth_add_email_and_phone_warning") + /// Add an email address to your account to let users discover you, and let you reset password. + internal static let authAddEmailMessage = VectorL10n.tr("Vector", "auth_add_email_message") + /// Add an email address and/or a phone number to your account to let users discover you. Email address will also let you reset your password. + internal static let authAddEmailPhoneMessage = VectorL10n.tr("Vector", "auth_add_email_phone_message") + /// Add a phone number to your account to let users discover you. + internal static let authAddPhoneMessage = VectorL10n.tr("Vector", "auth_add_phone_message") + /// This email address is already in use + internal static let authEmailInUse = VectorL10n.tr("Vector", "auth_email_in_use") + /// Failed to send email: This email address was not found + internal static let authEmailNotFound = VectorL10n.tr("Vector", "auth_email_not_found") + /// Email address + internal static let authEmailPlaceholder = VectorL10n.tr("Vector", "auth_email_placeholder") + /// Please check your email to continue registration + internal static let authEmailValidationMessage = VectorL10n.tr("Vector", "auth_email_validation_message") + /// Forgot password? + internal static let authForgotPassword = VectorL10n.tr("Vector", "auth_forgot_password") + /// URL (e.g. https://matrix.org) + internal static let authHomeServerPlaceholder = VectorL10n.tr("Vector", "auth_home_server_placeholder") + /// URL (e.g. https://matrix.org) + internal static let authIdentityServerPlaceholder = VectorL10n.tr("Vector", "auth_identity_server_placeholder") + /// This doesn't look like a valid email address + internal static let authInvalidEmail = VectorL10n.tr("Vector", "auth_invalid_email") + /// Incorrect username and/or password + internal static let authInvalidLoginParam = VectorL10n.tr("Vector", "auth_invalid_login_param") + /// Password too short (min 6) + internal static let authInvalidPassword = VectorL10n.tr("Vector", "auth_invalid_password") + /// This doesn't look like a valid phone number + internal static let authInvalidPhone = VectorL10n.tr("Vector", "auth_invalid_phone") + /// User names may only contain letters, numbers, dots, hyphens and underscores + internal static let authInvalidUserName = VectorL10n.tr("Vector", "auth_invalid_user_name") + /// Log in + internal static let authLogin = VectorL10n.tr("Vector", "auth_login") + /// Missing email address + internal static let authMissingEmail = VectorL10n.tr("Vector", "auth_missing_email") + /// Missing email address or phone number + internal static let authMissingEmailOrPhone = VectorL10n.tr("Vector", "auth_missing_email_or_phone") + /// Missing password + internal static let authMissingPassword = VectorL10n.tr("Vector", "auth_missing_password") + /// Missing phone number + internal static let authMissingPhone = VectorL10n.tr("Vector", "auth_missing_phone") + /// Unable to verify phone number. + internal static let authMsisdnValidationError = VectorL10n.tr("Vector", "auth_msisdn_validation_error") + /// We've sent an SMS with an activation code. Please enter this code below. + internal static let authMsisdnValidationMessage = VectorL10n.tr("Vector", "auth_msisdn_validation_message") + /// Verification Pending + internal static let authMsisdnValidationTitle = VectorL10n.tr("Vector", "auth_msisdn_validation_title") + /// New password + internal static let authNewPasswordPlaceholder = VectorL10n.tr("Vector", "auth_new_password_placeholder") + /// Email address (optional) + internal static let authOptionalEmailPlaceholder = VectorL10n.tr("Vector", "auth_optional_email_placeholder") + /// Phone number (optional) + internal static let authOptionalPhonePlaceholder = VectorL10n.tr("Vector", "auth_optional_phone_placeholder") + /// Passwords don't match + internal static let authPasswordDontMatch = VectorL10n.tr("Vector", "auth_password_dont_match") + /// Password + internal static let authPasswordPlaceholder = VectorL10n.tr("Vector", "auth_password_placeholder") + /// This phone number is already in use + internal static let authPhoneInUse = VectorL10n.tr("Vector", "auth_phone_in_use") + /// Phone number + internal static let authPhonePlaceholder = VectorL10n.tr("Vector", "auth_phone_placeholder") + /// This Home Server would like to make sure you are not a robot + internal static let authRecaptchaMessage = VectorL10n.tr("Vector", "auth_recaptcha_message") + /// Register + internal static let authRegister = VectorL10n.tr("Vector", "auth_register") + /// Confirm your new password + internal static let authRepeatNewPasswordPlaceholder = VectorL10n.tr("Vector", "auth_repeat_new_password_placeholder") + /// Repeat password + internal static let authRepeatPasswordPlaceholder = VectorL10n.tr("Vector", "auth_repeat_password_placeholder") + /// An email has been sent to %@. Once you've followed the link it contains, click below. + internal static func authResetPasswordEmailValidationMessage(_ p1: String) -> String { + return VectorL10n.tr("Vector", "auth_reset_password_email_validation_message", p1) + } + /// Your email address does not appear to be associated with a Matrix ID on this Homeserver. + internal static let authResetPasswordErrorNotFound = VectorL10n.tr("Vector", "auth_reset_password_error_not_found") + /// Failed to verify email address: make sure you clicked the link in the email + internal static let authResetPasswordErrorUnauthorized = VectorL10n.tr("Vector", "auth_reset_password_error_unauthorized") + /// To reset your password, enter the email address linked to your account: + internal static let authResetPasswordMessage = VectorL10n.tr("Vector", "auth_reset_password_message") + /// The email address linked to your account must be entered. + internal static let authResetPasswordMissingEmail = VectorL10n.tr("Vector", "auth_reset_password_missing_email") + /// A new password must be entered. + internal static let authResetPasswordMissingPassword = VectorL10n.tr("Vector", "auth_reset_password_missing_password") + /// I have verified my email address + internal static let authResetPasswordNextStepButton = VectorL10n.tr("Vector", "auth_reset_password_next_step_button") + /// Your password has been reset.\n\nYou have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, re-log in on each device. + internal static let authResetPasswordSuccessMessage = VectorL10n.tr("Vector", "auth_reset_password_success_message") + /// Return to login screen + internal static let authReturnToLogin = VectorL10n.tr("Vector", "auth_return_to_login") + /// Send Reset Email + internal static let authSendResetEmail = VectorL10n.tr("Vector", "auth_send_reset_email") + /// Skip + internal static let authSkip = VectorL10n.tr("Vector", "auth_skip") + /// Submit + internal static let authSubmit = VectorL10n.tr("Vector", "auth_submit") + /// The identity server is not trusted + internal static let authUntrustedIdServer = VectorL10n.tr("Vector", "auth_untrusted_id_server") + /// Use custom server options (advanced) + internal static let authUseServerOptions = VectorL10n.tr("Vector", "auth_use_server_options") + /// Email or user name + internal static let authUserIdPlaceholder = VectorL10n.tr("Vector", "auth_user_id_placeholder") + /// User name + internal static let authUserNamePlaceholder = VectorL10n.tr("Vector", "auth_user_name_placeholder") + /// Username in use + internal static let authUsernameInUse = VectorL10n.tr("Vector", "auth_username_in_use") + /// Back + internal static let back = VectorL10n.tr("Vector", "back") + /// Please describe what you did before the crash: + internal static let bugCrashReportDescription = VectorL10n.tr("Vector", "bug_crash_report_description") + /// Crash Report + internal static let bugCrashReportTitle = VectorL10n.tr("Vector", "bug_crash_report_title") + /// Please describe the bug. What did you do? What did you expect to happen? What actually happened? + internal static let bugReportDescription = VectorL10n.tr("Vector", "bug_report_description") + /// In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick: + internal static let bugReportLogsDescription = VectorL10n.tr("Vector", "bug_report_logs_description") + /// Uploading report + internal static let bugReportProgressUploading = VectorL10n.tr("Vector", "bug_report_progress_uploading") + /// Collecting logs + internal static let bugReportProgressZipping = VectorL10n.tr("Vector", "bug_report_progress_zipping") + /// The application has crashed last time. Would you like to submit a crash report? + internal static let bugReportPrompt = VectorL10n.tr("Vector", "bug_report_prompt") + /// Send + internal static let bugReportSend = VectorL10n.tr("Vector", "bug_report_send") + /// Send logs + internal static let bugReportSendLogs = VectorL10n.tr("Vector", "bug_report_send_logs") + /// Send screenshot + internal static let bugReportSendScreenshot = VectorL10n.tr("Vector", "bug_report_send_screenshot") + /// Bug Report + internal static let bugReportTitle = VectorL10n.tr("Vector", "bug_report_title") + /// There is already a call in progress. + internal static let callAlreadyDisplayed = VectorL10n.tr("Vector", "call_already_displayed") + /// Incoming video call... + internal static let callIncomingVideo = VectorL10n.tr("Vector", "call_incoming_video") + /// Incoming video call from %@ + internal static func callIncomingVideoPrompt(_ p1: String) -> String { + return VectorL10n.tr("Vector", "call_incoming_video_prompt", p1) + } + /// Incoming call... + internal static let callIncomingVoice = VectorL10n.tr("Vector", "call_incoming_voice") + /// Incoming voice call from %@ + internal static func callIncomingVoicePrompt(_ p1: String) -> String { + return VectorL10n.tr("Vector", "call_incoming_voice_prompt", p1) + } + /// Failed to join the conference call. + internal static let callJitsiError = VectorL10n.tr("Vector", "call_jitsi_error") + /// Camera + internal static let camera = VectorL10n.tr("Vector", "camera") + /// %@ doesn't have permission to use Camera, please change privacy settings + internal static func cameraAccessNotGranted(_ p1: String) -> String { + return VectorL10n.tr("Vector", "camera_access_not_granted", p1) + } + /// Cancel + internal static let cancel = VectorL10n.tr("Vector", "cancel") + /// collapse + internal static let collapse = VectorL10n.tr("Vector", "collapse") + /// Matrix users only + internal static let contactsAddressBookMatrixUsersToggle = VectorL10n.tr("Vector", "contacts_address_book_matrix_users_toggle") + /// No local contacts + internal static let contactsAddressBookNoContact = VectorL10n.tr("Vector", "contacts_address_book_no_contact") + /// You didn't allow Riot to access your local contacts + internal static let contactsAddressBookPermissionDenied = VectorL10n.tr("Vector", "contacts_address_book_permission_denied") + /// Permission required to access local contacts + internal static let contactsAddressBookPermissionRequired = VectorL10n.tr("Vector", "contacts_address_book_permission_required") + /// LOCAL CONTACTS + internal static let contactsAddressBookSection = VectorL10n.tr("Vector", "contacts_address_book_section") + /// USER DIRECTORY (offline) + internal static let contactsUserDirectoryOfflineSection = VectorL10n.tr("Vector", "contacts_user_directory_offline_section") + /// USER DIRECTORY + internal static let contactsUserDirectorySection = VectorL10n.tr("Vector", "contacts_user_directory_section") + /// Continue + internal static let `continue` = VectorL10n.tr("Vector", "continue") + /// Create + internal static let create = VectorL10n.tr("Vector", "create") + /// Please forget all messages I have sent when my account is deactivated ( + internal static let deactivateAccountForgetMessagesInformationPart1 = VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part1") + /// Warning + internal static let deactivateAccountForgetMessagesInformationPart2Emphasize = VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part2_emphasize") + /// : this will cause future users to see an incomplete view of conversations) + internal static let deactivateAccountForgetMessagesInformationPart3 = VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part3") + /// This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. + internal static let deactivateAccountInformationsPart1 = VectorL10n.tr("Vector", "deactivate_account_informations_part1") + /// This action is irreversible. + internal static let deactivateAccountInformationsPart2Emphasize = VectorL10n.tr("Vector", "deactivate_account_informations_part2_emphasize") + /// \n\nDeactivating your account + internal static let deactivateAccountInformationsPart3 = VectorL10n.tr("Vector", "deactivate_account_informations_part3") + /// does not by default cause us to forget messages you have sent. + internal static let deactivateAccountInformationsPart4Emphasize = VectorL10n.tr("Vector", "deactivate_account_informations_part4_emphasize") + /// If you would like us to forget your messages, please tick the box below\n\nMessage visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy. + internal static let deactivateAccountInformationsPart5 = VectorL10n.tr("Vector", "deactivate_account_informations_part5") + /// To continue, please enter your password + internal static let deactivateAccountPasswordAlertMessage = VectorL10n.tr("Vector", "deactivate_account_password_alert_message") + /// Deactivate Account + internal static let deactivateAccountPasswordAlertTitle = VectorL10n.tr("Vector", "deactivate_account_password_alert_title") + /// Deactivate Account + internal static let deactivateAccountTitle = VectorL10n.tr("Vector", "deactivate_account_title") + /// Deactivate account + internal static let deactivateAccountValidateAction = VectorL10n.tr("Vector", "deactivate_account_validate_action") + /// Decline + internal static let decline = VectorL10n.tr("Vector", "decline") + /// %tu rooms + internal static func directoryCellDescription(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "directory_cell_description", p1) + } + /// Browse directory + internal static let directoryCellTitle = VectorL10n.tr("Vector", "directory_cell_title") + /// Failed to fetch data + internal static let directorySearchFail = VectorL10n.tr("Vector", "directory_search_fail") + /// %tu results found for %@ + internal static func directorySearchResults(_ p1: Int, _ p2: String) -> String { + return VectorL10n.tr("Vector", "directory_search_results", p1, p2) + } + /// >%tu results found for %@ + internal static func directorySearchResultsMoreThan(_ p1: Int, _ p2: String) -> String { + return VectorL10n.tr("Vector", "directory_search_results_more_than", p1, p2) + } + /// Browse directory results + internal static let directorySearchResultsTitle = VectorL10n.tr("Vector", "directory_search_results_title") + /// Searching directory… + internal static let directorySearchingTitle = VectorL10n.tr("Vector", "directory_searching_title") + /// All native Matrix rooms + internal static let directoryServerAllNativeRooms = VectorL10n.tr("Vector", "directory_server_all_native_rooms") + /// All rooms on %@ server + internal static func directoryServerAllRooms(_ p1: String) -> String { + return VectorL10n.tr("Vector", "directory_server_all_rooms", p1) + } + /// Select a directory + internal static let directoryServerPickerTitle = VectorL10n.tr("Vector", "directory_server_picker_title") + /// matrix.org + internal static let directoryServerPlaceholder = VectorL10n.tr("Vector", "directory_server_placeholder") + /// Type a homeserver to list public rooms from + internal static let directoryServerTypeHomeserver = VectorL10n.tr("Vector", "directory_server_type_homeserver") + /// Directory + internal static let directoryTitle = VectorL10n.tr("Vector", "directory_title") + /// Do not ask again + internal static let doNotAskAgain = VectorL10n.tr("Vector", "do_not_ask_again") + /// Riot now supports end-to-end encryption but you need to log in again to enable it.\n\nYou can do it now or later from the application settings. + internal static let e2eEnablingOnAppUpdate = VectorL10n.tr("Vector", "e2e_enabling_on_app_update") + /// You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver.\nThis is a once off; sorry for the inconvenience. + internal static let e2eNeedLogInAgain = VectorL10n.tr("Vector", "e2e_need_log_in_again") + /// Ignore request + internal static let e2eRoomKeyRequestIgnoreRequest = VectorL10n.tr("Vector", "e2e_room_key_request_ignore_request") + /// Your unverified device '%@' is requesting encryption keys. + internal static func e2eRoomKeyRequestMessage(_ p1: String) -> String { + return VectorL10n.tr("Vector", "e2e_room_key_request_message", p1) + } + /// You added a new device '%@', which is requesting encryption keys. + internal static func e2eRoomKeyRequestMessageNewDevice(_ p1: String) -> String { + return VectorL10n.tr("Vector", "e2e_room_key_request_message_new_device", p1) + } + /// Share without verifying + internal static let e2eRoomKeyRequestShareWithoutVerifying = VectorL10n.tr("Vector", "e2e_room_key_request_share_without_verifying") + /// Start verification... + internal static let e2eRoomKeyRequestStartVerification = VectorL10n.tr("Vector", "e2e_room_key_request_start_verification") + /// Encryption key request + internal static let e2eRoomKeyRequestTitle = VectorL10n.tr("Vector", "e2e_room_key_request_title") + /// Send an encrypted message… + internal static let encryptedRoomMessagePlaceholder = VectorL10n.tr("Vector", "encrypted_room_message_placeholder") + /// Send an encrypted reply… + internal static let encryptedRoomMessageReplyToPlaceholder = VectorL10n.tr("Vector", "encrypted_room_message_reply_to_placeholder") + /// VoIP conference added by %@ + internal static func eventFormatterJitsiWidgetAdded(_ p1: String) -> String { + return VectorL10n.tr("Vector", "event_formatter_jitsi_widget_added", p1) + } + /// VoIP conference removed by %@ + internal static func eventFormatterJitsiWidgetRemoved(_ p1: String) -> String { + return VectorL10n.tr("Vector", "event_formatter_jitsi_widget_removed", p1) + } + /// %tu membership changes + internal static func eventFormatterMemberUpdates(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "event_formatter_member_updates", p1) + } + /// Re-request encryption keys + internal static let eventFormatterRerequestKeysPart1Link = VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part1_link") + /// from your other devices. + internal static let eventFormatterRerequestKeysPart2 = VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part2") + /// %@ widget added by %@ + internal static func eventFormatterWidgetAdded(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "event_formatter_widget_added", p1, p2) + } + /// %@ widget removed by %@ + internal static func eventFormatterWidgetRemoved(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "event_formatter_widget_removed", p1, p2) + } + /// To continue using the %@ homeserver you must review and agree to the terms and conditions. + internal static func gdprConsentNotGivenAlertMessage(_ p1: String) -> String { + return VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_message", p1) + } + /// Review now + internal static let gdprConsentNotGivenAlertReviewNowAction = VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_review_now_action") + /// Would you like to help improve %@ by automatically reporting anonymous crash reports and usage data? + internal static func googleAnalyticsUsePrompt(_ p1: String) -> String { + return VectorL10n.tr("Vector", "google_analytics_use_prompt", p1) + } + /// Home + internal static let groupDetailsHome = VectorL10n.tr("Vector", "group_details_home") + /// People + internal static let groupDetailsPeople = VectorL10n.tr("Vector", "group_details_people") + /// Rooms + internal static let groupDetailsRooms = VectorL10n.tr("Vector", "group_details_rooms") + /// Community Details + internal static let groupDetailsTitle = VectorL10n.tr("Vector", "group_details_title") + /// %tu members + internal static func groupHomeMultiMembersFormat(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "group_home_multi_members_format", p1) + } + /// %tu rooms + internal static func groupHomeMultiRoomsFormat(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "group_home_multi_rooms_format", p1) + } + /// 1 member + internal static let groupHomeOneMemberFormat = VectorL10n.tr("Vector", "group_home_one_member_format") + /// 1 room + internal static let groupHomeOneRoomFormat = VectorL10n.tr("Vector", "group_home_one_room_format") + /// %@ has invited you to join this community + internal static func groupInvitationFormat(_ p1: String) -> String { + return VectorL10n.tr("Vector", "group_invitation_format", p1) + } + /// INVITES + internal static let groupInviteSection = VectorL10n.tr("Vector", "group_invite_section") + /// Add participant + internal static let groupParticipantsAddParticipant = VectorL10n.tr("Vector", "group_participants_add_participant") + /// Filter community members + internal static let groupParticipantsFilterMembers = VectorL10n.tr("Vector", "group_participants_filter_members") + /// Search / invite by User ID or Name + internal static let groupParticipantsInviteAnotherUser = VectorL10n.tr("Vector", "group_participants_invite_another_user") + /// Malformed ID. Should be a Matrix ID like '@localpart:domain' + internal static let groupParticipantsInviteMalformedId = VectorL10n.tr("Vector", "group_participants_invite_malformed_id") + /// Invite Error + internal static let groupParticipantsInviteMalformedIdTitle = VectorL10n.tr("Vector", "group_participants_invite_malformed_id_title") + /// Are you sure you want to invite %@ to this group? + internal static func groupParticipantsInvitePromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "group_participants_invite_prompt_msg", p1) + } + /// Confirmation + internal static let groupParticipantsInvitePromptTitle = VectorL10n.tr("Vector", "group_participants_invite_prompt_title") + /// INVITED + internal static let groupParticipantsInvitedSection = VectorL10n.tr("Vector", "group_participants_invited_section") + /// Are you sure you want to leave the group? + internal static let groupParticipantsLeavePromptMsg = VectorL10n.tr("Vector", "group_participants_leave_prompt_msg") + /// Leave group + internal static let groupParticipantsLeavePromptTitle = VectorL10n.tr("Vector", "group_participants_leave_prompt_title") + /// Are you sure you want to remove %@ from this group? + internal static func groupParticipantsRemovePromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "group_participants_remove_prompt_msg", p1) + } + /// Confirmation + internal static let groupParticipantsRemovePromptTitle = VectorL10n.tr("Vector", "group_participants_remove_prompt_title") + /// Filter community rooms + internal static let groupRoomsFilterRooms = VectorL10n.tr("Vector", "group_rooms_filter_rooms") + /// COMMUNITIES + internal static let groupSection = VectorL10n.tr("Vector", "group_section") + /// Could not connect to the homeserver. + internal static let homeserverConnectionLost = VectorL10n.tr("Vector", "homeserver_connection_lost") + /// Invite + internal static let invite = VectorL10n.tr("Vector", "invite") + /// Join + internal static let join = VectorL10n.tr("Vector", "join") + /// %.1fK + internal static func largeBadgeValueKFormat(_ p1: Float) -> String { + return VectorL10n.tr("Vector", "large_badge_value_k_format", p1) + } + /// Later + internal static let later = VectorL10n.tr("Vector", "later") + /// Leave + internal static let leave = VectorL10n.tr("Vector", "leave") + /// Library + internal static let mediaPickerLibrary = VectorL10n.tr("Vector", "media_picker_library") + /// Select + internal static let mediaPickerSelect = VectorL10n.tr("Vector", "media_picker_select") + /// The Internet connection appears to be offline. + internal static let networkOfflinePrompt = VectorL10n.tr("Vector", "network_offline_prompt") + /// Next + internal static let next = VectorL10n.tr("Vector", "next") + /// %@ is calling you but %@ does not support calls yet.\nYou can ignore this notification and answer the call from another device or you can reject it. + internal static func noVoip(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "no_voip", p1, p2) + } + /// Incoming call + internal static let noVoipTitle = VectorL10n.tr("Vector", "no_voip_title") + /// Off + internal static let off = VectorL10n.tr("Vector", "off") + /// On + internal static let on = VectorL10n.tr("Vector", "on") + /// or + internal static let or = VectorL10n.tr("Vector", "or") + /// CONVERSATIONS + internal static let peopleConversationSection = VectorL10n.tr("Vector", "people_conversation_section") + /// INVITES + internal static let peopleInvitesSection = VectorL10n.tr("Vector", "people_invites_section") + /// No conversations + internal static let peopleNoConversation = VectorL10n.tr("Vector", "people_no_conversation") + /// Preview + internal static let preview = VectorL10n.tr("Vector", "preview") + /// Public Rooms (at %@): + internal static func publicRoomSectionTitle(_ p1: String) -> String { + return VectorL10n.tr("Vector", "public_room_section_title", p1) + } + /// You seem to be shaking the phone in frustration. Would you like to submit a bug report? + internal static let rageShakePrompt = VectorL10n.tr("Vector", "rage_shake_prompt") + /// Read Receipts List + internal static let readReceiptsList = VectorL10n.tr("Vector", "read_receipts_list") + /// Read: + internal static let receiptStatusRead = VectorL10n.tr("Vector", "receipt_status_read") + /// Remove + internal static let remove = VectorL10n.tr("Vector", "remove") + /// Rename + internal static let rename = VectorL10n.tr("Vector", "rename") + /// Please launch Riot on another device that can decrypt the message so it can send the keys to this device. + internal static let rerequestKeysAlertMessage = VectorL10n.tr("Vector", "rerequest_keys_alert_message") + /// Request Sent + internal static let rerequestKeysAlertTitle = VectorL10n.tr("Vector", "rerequest_keys_alert_title") + /// Retry + internal static let retry = VectorL10n.tr("Vector", "retry") + /// Send photo or video + internal static let roomActionSendPhotoOrVideo = VectorL10n.tr("Vector", "room_action_send_photo_or_video") + /// Send sticker + internal static let roomActionSendSticker = VectorL10n.tr("Vector", "room_action_send_sticker") + /// You need permission to manage conference call in this room + internal static let roomConferenceCallNoPower = VectorL10n.tr("Vector", "room_conference_call_no_power") + /// Account + internal static let roomCreationAccount = VectorL10n.tr("Vector", "room_creation_account") + /// Appearance + internal static let roomCreationAppearance = VectorL10n.tr("Vector", "room_creation_appearance") + /// Name + internal static let roomCreationAppearanceName = VectorL10n.tr("Vector", "room_creation_appearance_name") + /// Chat picture (optional) + internal static let roomCreationAppearancePicture = VectorL10n.tr("Vector", "room_creation_appearance_picture") + /// Search / invite by User ID, Name or email + internal static let roomCreationInviteAnotherUser = VectorL10n.tr("Vector", "room_creation_invite_another_user") + /// Keep private + internal static let roomCreationKeepPrivate = VectorL10n.tr("Vector", "room_creation_keep_private") + /// Make private + internal static let roomCreationMakePrivate = VectorL10n.tr("Vector", "room_creation_make_private") + /// Make public + internal static let roomCreationMakePublic = VectorL10n.tr("Vector", "room_creation_make_public") + /// Are you sure you want to make this chat public? Anyone can read your messages and join the chat. + internal static let roomCreationMakePublicPromptMsg = VectorL10n.tr("Vector", "room_creation_make_public_prompt_msg") + /// Make this chat public? + internal static let roomCreationMakePublicPromptTitle = VectorL10n.tr("Vector", "room_creation_make_public_prompt_title") + /// Privacy + internal static let roomCreationPrivacy = VectorL10n.tr("Vector", "room_creation_privacy") + /// This chat is private + internal static let roomCreationPrivateRoom = VectorL10n.tr("Vector", "room_creation_private_room") + /// This chat is public + internal static let roomCreationPublicRoom = VectorL10n.tr("Vector", "room_creation_public_room") + /// New Chat + internal static let roomCreationTitle = VectorL10n.tr("Vector", "room_creation_title") + /// A room is already being created. Please wait. + internal static let roomCreationWaitForCreation = VectorL10n.tr("Vector", "room_creation_wait_for_creation") + /// Delete unsent messages + internal static let roomDeleteUnsentMessages = VectorL10n.tr("Vector", "room_delete_unsent_messages") + /// Who can access this room? + internal static let roomDetailsAccessSection = VectorL10n.tr("Vector", "room_details_access_section") + /// Anyone who knows the room's link, including guests + internal static let roomDetailsAccessSectionAnyone = VectorL10n.tr("Vector", "room_details_access_section_anyone") + /// Anyone who knows the room's link, apart from guests + internal static let roomDetailsAccessSectionAnyoneApartFromGuest = VectorL10n.tr("Vector", "room_details_access_section_anyone_apart_from_guest") + /// List this room in room directory + internal static let roomDetailsAccessSectionDirectoryToggle = VectorL10n.tr("Vector", "room_details_access_section_directory_toggle") + /// Only people who have been invited + internal static let roomDetailsAccessSectionInvitedOnly = VectorL10n.tr("Vector", "room_details_access_section_invited_only") + /// To link to a room it must have an address + internal static let roomDetailsAccessSectionNoAddressWarning = VectorL10n.tr("Vector", "room_details_access_section_no_address_warning") + /// You will have no main address specified. The default main address for this room will be picked randomly + internal static let roomDetailsAddressesDisableMainAddressPromptMsg = VectorL10n.tr("Vector", "room_details_addresses_disable_main_address_prompt_msg") + /// Main address warning + internal static let roomDetailsAddressesDisableMainAddressPromptTitle = VectorL10n.tr("Vector", "room_details_addresses_disable_main_address_prompt_title") + /// %@ is not a valid format for an alias + internal static func roomDetailsAddressesInvalidAddressPromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_details_addresses_invalid_address_prompt_msg", p1) + } + /// Invalid alias format + internal static let roomDetailsAddressesInvalidAddressPromptTitle = VectorL10n.tr("Vector", "room_details_addresses_invalid_address_prompt_title") + /// Addresses + internal static let roomDetailsAddressesSection = VectorL10n.tr("Vector", "room_details_addresses_section") + /// Encrypt to verified devices only + internal static let roomDetailsAdvancedE2eEncryptionBlacklistUnverifiedDevices = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_blacklist_unverified_devices") + /// Encryption is not enabled in this room. + internal static let roomDetailsAdvancedE2eEncryptionDisabled = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_disabled") + /// Encryption is enabled in this room + internal static let roomDetailsAdvancedE2eEncryptionEnabled = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_enabled") + /// End-to-end encryption is experimental and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nOnce encryption is enabled for a room it cannot be turned off again (for now).\n\nEncrypted messages will not be visible on clients that do not yet implement encryption. + internal static let roomDetailsAdvancedE2eEncryptionPromptMessage = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_prompt_message") + /// Enable encryption (warning: cannot be disabled again!) + internal static let roomDetailsAdvancedEnableE2eEncryption = VectorL10n.tr("Vector", "room_details_advanced_enable_e2e_encryption") + /// Room ID: + internal static let roomDetailsAdvancedRoomId = VectorL10n.tr("Vector", "room_details_advanced_room_id") + /// Advanced + internal static let roomDetailsAdvancedSection = VectorL10n.tr("Vector", "room_details_advanced_section") + /// Banned users + internal static let roomDetailsBannedUsersSection = VectorL10n.tr("Vector", "room_details_banned_users_section") + /// Copy Room Address + internal static let roomDetailsCopyRoomAddress = VectorL10n.tr("Vector", "room_details_copy_room_address") + /// Copy Room ID + internal static let roomDetailsCopyRoomId = VectorL10n.tr("Vector", "room_details_copy_room_id") + /// Copy Room URL + internal static let roomDetailsCopyRoomUrl = VectorL10n.tr("Vector", "room_details_copy_room_url") + /// Direct Chat + internal static let roomDetailsDirectChat = VectorL10n.tr("Vector", "room_details_direct_chat") + /// Fail to add the new room addresses + internal static let roomDetailsFailToAddRoomAliases = VectorL10n.tr("Vector", "room_details_fail_to_add_room_aliases") + /// Fail to enable encryption in this room + internal static let roomDetailsFailToEnableEncryption = VectorL10n.tr("Vector", "room_details_fail_to_enable_encryption") + /// Fail to remove the room addresses + internal static let roomDetailsFailToRemoveRoomAliases = VectorL10n.tr("Vector", "room_details_fail_to_remove_room_aliases") + /// Fail to update the room photo + internal static let roomDetailsFailToUpdateAvatar = VectorL10n.tr("Vector", "room_details_fail_to_update_avatar") + /// Fail to update the history visibility + internal static let roomDetailsFailToUpdateHistoryVisibility = VectorL10n.tr("Vector", "room_details_fail_to_update_history_visibility") + /// Fail to update the main address + internal static let roomDetailsFailToUpdateRoomCanonicalAlias = VectorL10n.tr("Vector", "room_details_fail_to_update_room_canonical_alias") + /// Fail to update the related communities + internal static let roomDetailsFailToUpdateRoomCommunities = VectorL10n.tr("Vector", "room_details_fail_to_update_room_communities") + /// Fail to update the direct flag of this room + internal static let roomDetailsFailToUpdateRoomDirect = VectorL10n.tr("Vector", "room_details_fail_to_update_room_direct") + /// Fail to update the room directory visibility + internal static let roomDetailsFailToUpdateRoomDirectoryVisibility = VectorL10n.tr("Vector", "room_details_fail_to_update_room_directory_visibility") + /// Fail to update the room guest access + internal static let roomDetailsFailToUpdateRoomGuestAccess = VectorL10n.tr("Vector", "room_details_fail_to_update_room_guest_access") + /// Fail to update the join rule + internal static let roomDetailsFailToUpdateRoomJoinRule = VectorL10n.tr("Vector", "room_details_fail_to_update_room_join_rule") + /// Fail to update the room name + internal static let roomDetailsFailToUpdateRoomName = VectorL10n.tr("Vector", "room_details_fail_to_update_room_name") + /// Fail to update the topic + internal static let roomDetailsFailToUpdateTopic = VectorL10n.tr("Vector", "room_details_fail_to_update_topic") + /// Favourite + internal static let roomDetailsFavouriteTag = VectorL10n.tr("Vector", "room_details_favourite_tag") + /// Files + internal static let roomDetailsFiles = VectorL10n.tr("Vector", "room_details_files") + /// %@ is not a valid identifier for a community + internal static func roomDetailsFlairInvalidIdPromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_details_flair_invalid_id_prompt_msg", p1) + } + /// Invalid format + internal static let roomDetailsFlairInvalidIdPromptTitle = VectorL10n.tr("Vector", "room_details_flair_invalid_id_prompt_title") + /// Show flair for communities + internal static let roomDetailsFlairSection = VectorL10n.tr("Vector", "room_details_flair_section") + /// Who can read history? + internal static let roomDetailsHistorySection = VectorL10n.tr("Vector", "room_details_history_section") + /// Anyone + internal static let roomDetailsHistorySectionAnyone = VectorL10n.tr("Vector", "room_details_history_section_anyone") + /// Members only (since the point in time of selecting this option) + internal static let roomDetailsHistorySectionMembersOnly = VectorL10n.tr("Vector", "room_details_history_section_members_only") + /// Members only (since they were invited) + internal static let roomDetailsHistorySectionMembersOnlySinceInvited = VectorL10n.tr("Vector", "room_details_history_section_members_only_since_invited") + /// Members only (since they joined) + internal static let roomDetailsHistorySectionMembersOnlySinceJoined = VectorL10n.tr("Vector", "room_details_history_section_members_only_since_joined") + /// Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged. + internal static let roomDetailsHistorySectionPromptMsg = VectorL10n.tr("Vector", "room_details_history_section_prompt_msg") + /// Privacy warning + internal static let roomDetailsHistorySectionPromptTitle = VectorL10n.tr("Vector", "room_details_history_section_prompt_title") + /// Low priority + internal static let roomDetailsLowPriorityTag = VectorL10n.tr("Vector", "room_details_low_priority_tag") + /// Mute notifications + internal static let roomDetailsMuteNotifs = VectorL10n.tr("Vector", "room_details_mute_notifs") + /// Add new address + internal static let roomDetailsNewAddress = VectorL10n.tr("Vector", "room_details_new_address") + /// Add new address (e.g. #foo%@) + internal static func roomDetailsNewAddressPlaceholder(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_details_new_address_placeholder", p1) + } + /// Add new community ID (e.g. +foo%@) + internal static func roomDetailsNewFlairPlaceholder(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_details_new_flair_placeholder", p1) + } + /// This room has no local addresses + internal static let roomDetailsNoLocalAddresses = VectorL10n.tr("Vector", "room_details_no_local_addresses") + /// Members + internal static let roomDetailsPeople = VectorL10n.tr("Vector", "room_details_people") + /// Room Photo + internal static let roomDetailsPhoto = VectorL10n.tr("Vector", "room_details_photo") + /// Room Name + internal static let roomDetailsRoomName = VectorL10n.tr("Vector", "room_details_room_name") + /// Do you want to save changes? + internal static let roomDetailsSaveChangesPrompt = VectorL10n.tr("Vector", "room_details_save_changes_prompt") + /// Set as Main Address + internal static let roomDetailsSetMainAddress = VectorL10n.tr("Vector", "room_details_set_main_address") + /// Settings + internal static let roomDetailsSettings = VectorL10n.tr("Vector", "room_details_settings") + /// Room Details + internal static let roomDetailsTitle = VectorL10n.tr("Vector", "room_details_title") + /// Topic + internal static let roomDetailsTopic = VectorL10n.tr("Vector", "room_details_topic") + /// Unset as Main Address + internal static let roomDetailsUnsetMainAddress = VectorL10n.tr("Vector", "room_details_unset_main_address") + /// No public rooms available + internal static let roomDirectoryNoPublicRoom = VectorL10n.tr("Vector", "room_directory_no_public_room") + /// You do not have permission to post to this room + internal static let roomDoNotHavePermissionToPost = VectorL10n.tr("Vector", "room_do_not_have_permission_to_post") + /// Reason for banning this user + internal static let roomEventActionBanPromptReason = VectorL10n.tr("Vector", "room_event_action_ban_prompt_reason") + /// Cancel Download + internal static let roomEventActionCancelDownload = VectorL10n.tr("Vector", "room_event_action_cancel_download") + /// Cancel Send + internal static let roomEventActionCancelSend = VectorL10n.tr("Vector", "room_event_action_cancel_send") + /// Copy + internal static let roomEventActionCopy = VectorL10n.tr("Vector", "room_event_action_copy") + /// Delete + internal static let roomEventActionDelete = VectorL10n.tr("Vector", "room_event_action_delete") + /// Reason for kicking this user + internal static let roomEventActionKickPromptReason = VectorL10n.tr("Vector", "room_event_action_kick_prompt_reason") + /// More + internal static let roomEventActionMore = VectorL10n.tr("Vector", "room_event_action_more") + /// Permalink + internal static let roomEventActionPermalink = VectorL10n.tr("Vector", "room_event_action_permalink") + /// Quote + internal static let roomEventActionQuote = VectorL10n.tr("Vector", "room_event_action_quote") + /// Redact + internal static let roomEventActionRedact = VectorL10n.tr("Vector", "room_event_action_redact") + /// Report content + internal static let roomEventActionReport = VectorL10n.tr("Vector", "room_event_action_report") + /// Do you want to hide all messages from this user? + internal static let roomEventActionReportPromptIgnoreUser = VectorL10n.tr("Vector", "room_event_action_report_prompt_ignore_user") + /// Reason for reporting this content + internal static let roomEventActionReportPromptReason = VectorL10n.tr("Vector", "room_event_action_report_prompt_reason") + /// Resend + internal static let roomEventActionResend = VectorL10n.tr("Vector", "room_event_action_resend") + /// Save + internal static let roomEventActionSave = VectorL10n.tr("Vector", "room_event_action_save") + /// Share + internal static let roomEventActionShare = VectorL10n.tr("Vector", "room_event_action_share") + /// View Decrypted Source + internal static let roomEventActionViewDecryptedSource = VectorL10n.tr("Vector", "room_event_action_view_decrypted_source") + /// Encryption Information + internal static let roomEventActionViewEncryption = VectorL10n.tr("Vector", "room_event_action_view_encryption") + /// View Source + internal static let roomEventActionViewSource = VectorL10n.tr("Vector", "room_event_action_view_source") + /// Failed to send + internal static let roomEventFailedToSend = VectorL10n.tr("Vector", "room_event_failed_to_send") + /// Jump to first unread message + internal static let roomJumpToFirstUnread = VectorL10n.tr("Vector", "room_jump_to_first_unread") + /// %@, %@ & others are typing… + internal static func roomManyUsersAreTyping(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_many_users_are_typing", p1, p2) + } + /// Send a message (unencrypted)… + internal static let roomMessagePlaceholder = VectorL10n.tr("Vector", "room_message_placeholder") + /// Send a reply (unencrypted)… + internal static let roomMessageReplyToPlaceholder = VectorL10n.tr("Vector", "room_message_reply_to_placeholder") + /// Send a reply… + internal static let roomMessageReplyToShortPlaceholder = VectorL10n.tr("Vector", "room_message_reply_to_short_placeholder") + /// Send a message… + internal static let roomMessageShortPlaceholder = VectorL10n.tr("Vector", "room_message_short_placeholder") + /// %d new message + internal static func roomNewMessageNotification(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "room_new_message_notification", p1) + } + /// %d new messages + internal static func roomNewMessagesNotification(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "room_new_messages_notification", p1) + } + /// Connectivity to the server has been lost. + internal static let roomOfflineNotification = VectorL10n.tr("Vector", "room_offline_notification") + /// %@ is typing… + internal static func roomOneUserIsTyping(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_one_user_is_typing", p1) + } + /// Ongoing conference call. Join as %@ or %@. + internal static func roomOngoingConferenceCall(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_ongoing_conference_call", p1, p2) + } + /// Close + internal static let roomOngoingConferenceCallClose = VectorL10n.tr("Vector", "room_ongoing_conference_call_close") + /// Ongoing conference call. Join as %@ or %@. %@ it. + internal static func roomOngoingConferenceCallWithClose(_ p1: String, _ p2: String, _ p3: String) -> String { + return VectorL10n.tr("Vector", "room_ongoing_conference_call_with_close", p1, p2, p3) + } + /// Ban from this room + internal static let roomParticipantsActionBan = VectorL10n.tr("Vector", "room_participants_action_ban") + /// Hide all messages from this user + internal static let roomParticipantsActionIgnore = VectorL10n.tr("Vector", "room_participants_action_ignore") + /// Invite + internal static let roomParticipantsActionInvite = VectorL10n.tr("Vector", "room_participants_action_invite") + /// Leave this room + internal static let roomParticipantsActionLeave = VectorL10n.tr("Vector", "room_participants_action_leave") + /// Mention + internal static let roomParticipantsActionMention = VectorL10n.tr("Vector", "room_participants_action_mention") + /// Remove from this room + internal static let roomParticipantsActionRemove = VectorL10n.tr("Vector", "room_participants_action_remove") + /// Admin tools + internal static let roomParticipantsActionSectionAdminTools = VectorL10n.tr("Vector", "room_participants_action_section_admin_tools") + /// Devices + internal static let roomParticipantsActionSectionDevices = VectorL10n.tr("Vector", "room_participants_action_section_devices") + /// Direct chats + internal static let roomParticipantsActionSectionDirectChats = VectorL10n.tr("Vector", "room_participants_action_section_direct_chats") + /// Other + internal static let roomParticipantsActionSectionOther = VectorL10n.tr("Vector", "room_participants_action_section_other") + /// Make admin + internal static let roomParticipantsActionSetAdmin = VectorL10n.tr("Vector", "room_participants_action_set_admin") + /// Reset to normal user + internal static let roomParticipantsActionSetDefaultPowerLevel = VectorL10n.tr("Vector", "room_participants_action_set_default_power_level") + /// Make moderator + internal static let roomParticipantsActionSetModerator = VectorL10n.tr("Vector", "room_participants_action_set_moderator") + /// Start new chat + internal static let roomParticipantsActionStartNewChat = VectorL10n.tr("Vector", "room_participants_action_start_new_chat") + /// Start video call + internal static let roomParticipantsActionStartVideoCall = VectorL10n.tr("Vector", "room_participants_action_start_video_call") + /// Start voice call + internal static let roomParticipantsActionStartVoiceCall = VectorL10n.tr("Vector", "room_participants_action_start_voice_call") + /// Unban + internal static let roomParticipantsActionUnban = VectorL10n.tr("Vector", "room_participants_action_unban") + /// Show all messages from this user + internal static let roomParticipantsActionUnignore = VectorL10n.tr("Vector", "room_participants_action_unignore") + /// Add participant + internal static let roomParticipantsAddParticipant = VectorL10n.tr("Vector", "room_participants_add_participant") + /// ago + internal static let roomParticipantsAgo = VectorL10n.tr("Vector", "room_participants_ago") + /// Filter room members + internal static let roomParticipantsFilterRoomMembers = VectorL10n.tr("Vector", "room_participants_filter_room_members") + /// Idle + internal static let roomParticipantsIdle = VectorL10n.tr("Vector", "room_participants_idle") + /// Search / invite by User ID, Name or email + internal static let roomParticipantsInviteAnotherUser = VectorL10n.tr("Vector", "room_participants_invite_another_user") + /// Malformed ID. Should be an email address or a Matrix ID like '@localpart:domain' + internal static let roomParticipantsInviteMalformedId = VectorL10n.tr("Vector", "room_participants_invite_malformed_id") + /// Invite Error + internal static let roomParticipantsInviteMalformedIdTitle = VectorL10n.tr("Vector", "room_participants_invite_malformed_id_title") + /// Are you sure you want to invite %@ to this chat? + internal static func roomParticipantsInvitePromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_participants_invite_prompt_msg", p1) + } + /// Confirmation + internal static let roomParticipantsInvitePromptTitle = VectorL10n.tr("Vector", "room_participants_invite_prompt_title") + /// INVITED + internal static let roomParticipantsInvitedSection = VectorL10n.tr("Vector", "room_participants_invited_section") + /// Are you sure you want to leave the room? + internal static let roomParticipantsLeavePromptMsg = VectorL10n.tr("Vector", "room_participants_leave_prompt_msg") + /// Leave room + internal static let roomParticipantsLeavePromptTitle = VectorL10n.tr("Vector", "room_participants_leave_prompt_title") + /// %d participants + internal static func roomParticipantsMultiParticipants(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "room_participants_multi_participants", p1) + } + /// now + internal static let roomParticipantsNow = VectorL10n.tr("Vector", "room_participants_now") + /// Offline + internal static let roomParticipantsOffline = VectorL10n.tr("Vector", "room_participants_offline") + /// 1 participant + internal static let roomParticipantsOneParticipant = VectorL10n.tr("Vector", "room_participants_one_participant") + /// Online + internal static let roomParticipantsOnline = VectorL10n.tr("Vector", "room_participants_online") + /// Are you sure you want to remove %@ from this chat? + internal static func roomParticipantsRemovePromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_participants_remove_prompt_msg", p1) + } + /// Confirmation + internal static let roomParticipantsRemovePromptTitle = VectorL10n.tr("Vector", "room_participants_remove_prompt_title") + /// Remove third-party invite is not supported yet until the api exists + internal static let roomParticipantsRemoveThirdPartyInviteMsg = VectorL10n.tr("Vector", "room_participants_remove_third_party_invite_msg") + /// Participants + internal static let roomParticipantsTitle = VectorL10n.tr("Vector", "room_participants_title") + /// Unknown + internal static let roomParticipantsUnknown = VectorL10n.tr("Vector", "room_participants_unknown") + /// This room is a continuation of another conversation. + internal static let roomPredecessorInformation = VectorL10n.tr("Vector", "room_predecessor_information") + /// Click here to see older messages. + internal static let roomPredecessorLink = VectorL10n.tr("Vector", "room_predecessor_link") + /// You have been invited to join this room by %@ + internal static func roomPreviewInvitationFormat(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_preview_invitation_format", p1) + } + /// This is a preview of this room. Room interactions have been disabled. + internal static let roomPreviewSubtitle = VectorL10n.tr("Vector", "room_preview_subtitle") + /// You are trying to access %@. Would you like to join in order to participate in the discussion? + internal static func roomPreviewTryJoinAnUnknownRoom(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_preview_try_join_an_unknown_room", p1) + } + /// a room + internal static let roomPreviewTryJoinAnUnknownRoomDefault = VectorL10n.tr("Vector", "room_preview_try_join_an_unknown_room_default") + /// This invitation was sent to %@, which is not associated with this account. You may wish to login with a different account, or add this email to your this account. + internal static func roomPreviewUnlinkedEmailWarning(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_preview_unlinked_email_warning", p1) + } + /// cancel all + internal static let roomPromptCancel = VectorL10n.tr("Vector", "room_prompt_cancel") + /// Resend all + internal static let roomPromptResend = VectorL10n.tr("Vector", "room_prompt_resend") + /// ROOMS + internal static let roomRecentsConversationsSection = VectorL10n.tr("Vector", "room_recents_conversations_section") + /// Create room + internal static let roomRecentsCreateEmptyRoom = VectorL10n.tr("Vector", "room_recents_create_empty_room") + /// ROOM DIRECTORY + internal static let roomRecentsDirectorySection = VectorL10n.tr("Vector", "room_recents_directory_section") + /// Network + internal static let roomRecentsDirectorySectionNetwork = VectorL10n.tr("Vector", "room_recents_directory_section_network") + /// FAVOURITES + internal static let roomRecentsFavouritesSection = VectorL10n.tr("Vector", "room_recents_favourites_section") + /// INVITES + internal static let roomRecentsInvitesSection = VectorL10n.tr("Vector", "room_recents_invites_section") + /// Join room + internal static let roomRecentsJoinRoom = VectorL10n.tr("Vector", "room_recents_join_room") + /// Type a room id or a room alias + internal static let roomRecentsJoinRoomPrompt = VectorL10n.tr("Vector", "room_recents_join_room_prompt") + /// Join a room + internal static let roomRecentsJoinRoomTitle = VectorL10n.tr("Vector", "room_recents_join_room_title") + /// LOW PRIORITY + internal static let roomRecentsLowPrioritySection = VectorL10n.tr("Vector", "room_recents_low_priority_section") + /// No rooms + internal static let roomRecentsNoConversation = VectorL10n.tr("Vector", "room_recents_no_conversation") + /// PEOPLE + internal static let roomRecentsPeopleSection = VectorL10n.tr("Vector", "room_recents_people_section") + /// SYSTEM ALERTS + internal static let roomRecentsServerNoticeSection = VectorL10n.tr("Vector", "room_recents_server_notice_section") + /// Start chat + internal static let roomRecentsStartChatWith = VectorL10n.tr("Vector", "room_recents_start_chat_with") + /// This room has been replaced and is no longer active. + internal static let roomReplacementInformation = VectorL10n.tr("Vector", "room_replacement_information") + /// The conversation continues here. + internal static let roomReplacementLink = VectorL10n.tr("Vector", "room_replacement_link") + /// Resend unsent messages + internal static let roomResendUnsentMessages = VectorL10n.tr("Vector", "room_resend_unsent_messages") + /// Please + internal static let roomResourceLimitExceededMessageContact1 = VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_1") + /// contact your service administrator + internal static let roomResourceLimitExceededMessageContact2Link = VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_2_link") + /// to continue using this service. + internal static let roomResourceLimitExceededMessageContact3 = VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_3") + /// This homeserver has exceeded one of its resource limits so + internal static let roomResourceUsageLimitReachedMessage1Default = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_1_default") + /// This homeserver has hit its Monthly Active User limit so + internal static let roomResourceUsageLimitReachedMessage1MonthlyActiveUser = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_1_monthly_active_user") + /// some users will not be able to log in. + internal static let roomResourceUsageLimitReachedMessage2 = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_2") + /// to get this limit increased. + internal static let roomResourceUsageLimitReachedMessageContact3 = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_contact_3") + /// Invite members + internal static let roomTitleInviteMembers = VectorL10n.tr("Vector", "room_title_invite_members") + /// %@ members + internal static func roomTitleMembers(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_title_members", p1) + } + /// %@/%@ active members + internal static func roomTitleMultipleActiveMembers(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_title_multiple_active_members", p1, p2) + } + /// New room + internal static let roomTitleNewRoom = VectorL10n.tr("Vector", "room_title_new_room") + /// %@/%@ active member + internal static func roomTitleOneActiveMember(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_title_one_active_member", p1, p2) + } + /// 1 member + internal static let roomTitleOneMember = VectorL10n.tr("Vector", "room_title_one_member") + /// %@ & %@ are typing… + internal static func roomTwoUsersAreTyping(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_two_users_are_typing", p1, p2) + } + /// Messages not sent. %@ or %@ now? + internal static func roomUnsentMessagesNotification(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_unsent_messages_notification", p1, p2) + } + /// Message not sent due to unknown devices being present. %@ or %@ now? + internal static func roomUnsentMessagesUnknownDevicesNotification(_ p1: String, _ p2: String) -> String { + return VectorL10n.tr("Vector", "room_unsent_messages_unknown_devices_notification", p1, p2) + } + /// End-to-end encryption is in beta and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nEncrypted messages will not be visible on clients that do not yet implement encryption. + internal static let roomWarningAboutEncryption = VectorL10n.tr("Vector", "room_warning_about_encryption") + /// Save + internal static let save = VectorL10n.tr("Vector", "save") + /// Search + internal static let searchDefaultPlaceholder = VectorL10n.tr("Vector", "search_default_placeholder") + /// Files + internal static let searchFiles = VectorL10n.tr("Vector", "search_files") + /// Searching… + internal static let searchInProgress = VectorL10n.tr("Vector", "search_in_progress") + /// Messages + internal static let searchMessages = VectorL10n.tr("Vector", "search_messages") + /// No results + internal static let searchNoResult = VectorL10n.tr("Vector", "search_no_result") + /// People + internal static let searchPeople = VectorL10n.tr("Vector", "search_people") + /// Search by User ID, Name or email + internal static let searchPeoplePlaceholder = VectorL10n.tr("Vector", "search_people_placeholder") + /// Rooms + internal static let searchRooms = VectorL10n.tr("Vector", "search_rooms") + /// Send to %@ + internal static func sendTo(_ p1: String) -> String { + return VectorL10n.tr("Vector", "send_to", p1) + } + /// Sending + internal static let sending = VectorL10n.tr("Vector", "sending") + /// Add email address + internal static let settingsAddEmailAddress = VectorL10n.tr("Vector", "settings_add_email_address") + /// Add phone number + internal static let settingsAddPhoneNumber = VectorL10n.tr("Vector", "settings_add_phone_number") + /// ADVANCED + internal static let settingsAdvanced = VectorL10n.tr("Vector", "settings_advanced") + /// Receive incoming calls on your lock screen. See your Riot calls in the system's call history. If iCloud is enabled, this call history will be shared with Apple. + internal static let settingsCallkitInfo = VectorL10n.tr("Vector", "settings_callkit_info") + /// CALLS + internal static let settingsCallsSettings = VectorL10n.tr("Vector", "settings_calls_settings") + /// Change password + internal static let settingsChangePassword = VectorL10n.tr("Vector", "settings_change_password") + /// Clear cache + internal static let settingsClearCache = VectorL10n.tr("Vector", "settings_clear_cache") + /// Home server is %@ + internal static func settingsConfigHomeServer(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_config_home_server", p1) + } + /// Identity server is %@ + internal static func settingsConfigIdentityServer(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_config_identity_server", p1) + } + /// No build info + internal static let settingsConfigNoBuildInfo = VectorL10n.tr("Vector", "settings_config_no_build_info") + /// Logged in as %@ + internal static func settingsConfigUserId(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_config_user_id", p1) + } + /// confirm password + internal static let settingsConfirmPassword = VectorL10n.tr("Vector", "settings_confirm_password") + /// LOCAL CONTACTS + internal static let settingsContacts = VectorL10n.tr("Vector", "settings_contacts") + /// Use emails and phone numbers to discover users + internal static let settingsContactsDiscoverMatrixUsers = VectorL10n.tr("Vector", "settings_contacts_discover_matrix_users") + /// Phonebook country + internal static let settingsContactsPhonebookCountry = VectorL10n.tr("Vector", "settings_contacts_phonebook_country") + /// Copyright + internal static let settingsCopyright = VectorL10n.tr("Vector", "settings_copyright") + /// https://riot.im/copyright + internal static let settingsCopyrightUrl = VectorL10n.tr("Vector", "settings_copyright_url") + /// Encrypt to verified devices only + internal static let settingsCryptoBlacklistUnverifiedDevices = VectorL10n.tr("Vector", "settings_crypto_blacklist_unverified_devices") + /// \nDevice ID: + internal static let settingsCryptoDeviceId = VectorL10n.tr("Vector", "settings_crypto_device_id") + /// \nDevice key: + internal static let settingsCryptoDeviceKey = VectorL10n.tr("Vector", "settings_crypto_device_key") + /// Device name: + internal static let settingsCryptoDeviceName = VectorL10n.tr("Vector", "settings_crypto_device_name") + /// Export keys + internal static let settingsCryptoExport = VectorL10n.tr("Vector", "settings_crypto_export") + /// CRYPTOGRAPHY + internal static let settingsCryptography = VectorL10n.tr("Vector", "settings_cryptography") + /// DEACTIVATE ACCOUNT + internal static let settingsDeactivateAccount = VectorL10n.tr("Vector", "settings_deactivate_account") + /// Deactivate my account + internal static let settingsDeactivateMyAccount = VectorL10n.tr("Vector", "settings_deactivate_my_account") + /// DEVICES + internal static let settingsDevices = VectorL10n.tr("Vector", "settings_devices") + /// Display Name + internal static let settingsDisplayName = VectorL10n.tr("Vector", "settings_display_name") + /// Email + internal static let settingsEmailAddress = VectorL10n.tr("Vector", "settings_email_address") + /// Enter your email address + internal static let settingsEmailAddressPlaceholder = VectorL10n.tr("Vector", "settings_email_address_placeholder") + /// Integrated calling + internal static let settingsEnableCallkit = VectorL10n.tr("Vector", "settings_enable_callkit") + /// Notifications on this device + internal static let settingsEnablePushNotif = VectorL10n.tr("Vector", "settings_enable_push_notif") + /// Rage shake to report bug + internal static let settingsEnableRageshake = VectorL10n.tr("Vector", "settings_enable_rageshake") + /// Fail to update password + internal static let settingsFailToUpdatePassword = VectorL10n.tr("Vector", "settings_fail_to_update_password") + /// Fail to update profile + internal static let settingsFailToUpdateProfile = VectorL10n.tr("Vector", "settings_fail_to_update_profile") + /// First Name + internal static let settingsFirstName = VectorL10n.tr("Vector", "settings_first_name") + /// Show flair where allowed + internal static let settingsFlair = VectorL10n.tr("Vector", "settings_flair") + /// Global notification settings are available on your %@ web client + internal static func settingsGlobalSettingsInfo(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_global_settings_info", p1) + } + /// IGNORED USERS + internal static let settingsIgnoredUsers = VectorL10n.tr("Vector", "settings_ignored_users") + /// LABS + internal static let settingsLabs = VectorL10n.tr("Vector", "settings_labs") + /// Create conference calls with jitsi + internal static let settingsLabsCreateConferenceWithJitsi = VectorL10n.tr("Vector", "settings_labs_create_conference_with_jitsi") + /// End-to-End Encryption + internal static let settingsLabsE2eEncryption = VectorL10n.tr("Vector", "settings_labs_e2e_encryption") + /// To finish setting up encryption you must log in again. + internal static let settingsLabsE2eEncryptionPromptMessage = VectorL10n.tr("Vector", "settings_labs_e2e_encryption_prompt_message") + /// Lazy load rooms members + internal static let settingsLabsRoomMembersLazyLoading = VectorL10n.tr("Vector", "settings_labs_room_members_lazy_loading") + /// Your homeserver does not support lazy loading of room members yet. Try later. + internal static let settingsLabsRoomMembersLazyLoadingErrorMessage = VectorL10n.tr("Vector", "settings_labs_room_members_lazy_loading_error_message") + /// Mark all messages as read + internal static let settingsMarkAllAsRead = VectorL10n.tr("Vector", "settings_mark_all_as_read") + /// new password + internal static let settingsNewPassword = VectorL10n.tr("Vector", "settings_new_password") + /// Night Mode + internal static let settingsNightMode = VectorL10n.tr("Vector", "settings_night_mode") + /// NOTIFICATION SETTINGS + internal static let settingsNotificationsSettings = VectorL10n.tr("Vector", "settings_notifications_settings") + /// old password + internal static let settingsOldPassword = VectorL10n.tr("Vector", "settings_old_password") + /// Olm Version %@ + internal static func settingsOlmVersion(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_olm_version", p1) + } + /// Notifications are denied for %@, please allow them in your device settings + internal static func settingsOnDeniedNotification(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_on_denied_notification", p1) + } + /// OTHER + internal static let settingsOther = VectorL10n.tr("Vector", "settings_other") + /// Your password has been updated + internal static let settingsPasswordUpdated = VectorL10n.tr("Vector", "settings_password_updated") + /// Phone + internal static let settingsPhoneNumber = VectorL10n.tr("Vector", "settings_phone_number") + /// Pin rooms with missed notifications + internal static let settingsPinRoomsWithMissedNotif = VectorL10n.tr("Vector", "settings_pin_rooms_with_missed_notif") + /// Pin rooms with unread messages + internal static let settingsPinRoomsWithUnread = VectorL10n.tr("Vector", "settings_pin_rooms_with_unread") + /// Privacy Policy + internal static let settingsPrivacyPolicy = VectorL10n.tr("Vector", "settings_privacy_policy") + /// https://riot.im/privacy + internal static let settingsPrivacyPolicyUrl = VectorL10n.tr("Vector", "settings_privacy_policy_url") + /// Profile Picture + internal static let settingsProfilePicture = VectorL10n.tr("Vector", "settings_profile_picture") + /// Are you sure you want to remove the email address %@? + internal static func settingsRemoveEmailPromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_remove_email_prompt_msg", p1) + } + /// Are you sure you want to remove the phone number %@? + internal static func settingsRemovePhonePromptMsg(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_remove_phone_prompt_msg", p1) + } + /// Confirmation + internal static let settingsRemovePromptTitle = VectorL10n.tr("Vector", "settings_remove_prompt_title") + /// Report bug + internal static let settingsReportBug = VectorL10n.tr("Vector", "settings_report_bug") + /// Send anon crash & usage data + internal static let settingsSendCrashReport = VectorL10n.tr("Vector", "settings_send_crash_report") + /// Show decrypted content + internal static let settingsShowDecryptedContent = VectorL10n.tr("Vector", "settings_show_decrypted_content") + /// Sign Out + internal static let settingsSignOut = VectorL10n.tr("Vector", "settings_sign_out") + /// Are you sure? + internal static let settingsSignOutConfirmation = VectorL10n.tr("Vector", "settings_sign_out_confirmation") + /// You will lose your end-to-end encryption keys. That means you will no longer be able to read old messages in encrypted rooms on this device. + internal static let settingsSignOutE2eWarn = VectorL10n.tr("Vector", "settings_sign_out_e2e_warn") + /// Surname + internal static let settingsSurname = VectorL10n.tr("Vector", "settings_surname") + /// Terms & Conditions + internal static let settingsTermConditions = VectorL10n.tr("Vector", "settings_term_conditions") + /// https://riot.im/tac_apple + internal static let settingsTermConditionsUrl = VectorL10n.tr("Vector", "settings_term_conditions_url") + /// Third-party Notices + internal static let settingsThirdPartyNotices = VectorL10n.tr("Vector", "settings_third_party_notices") + /// Settings + internal static let settingsTitle = VectorL10n.tr("Vector", "settings_title") + /// Language + internal static let settingsUiLanguage = VectorL10n.tr("Vector", "settings_ui_language") + /// Theme + internal static let settingsUiTheme = VectorL10n.tr("Vector", "settings_ui_theme") + /// Auto + internal static let settingsUiThemeAuto = VectorL10n.tr("Vector", "settings_ui_theme_auto") + /// Black + internal static let settingsUiThemeBlack = VectorL10n.tr("Vector", "settings_ui_theme_black") + /// Dark + internal static let settingsUiThemeDark = VectorL10n.tr("Vector", "settings_ui_theme_dark") + /// Light + internal static let settingsUiThemeLight = VectorL10n.tr("Vector", "settings_ui_theme_light") + /// "Auto" uses your device "Invert Colours" settings + internal static let settingsUiThemePickerMessage = VectorL10n.tr("Vector", "settings_ui_theme_picker_message") + /// Select a theme + internal static let settingsUiThemePickerTitle = VectorL10n.tr("Vector", "settings_ui_theme_picker_title") + /// Show all messages from %@? + internal static func settingsUnignoreUser(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_unignore_user", p1) + } + /// USER INTERFACE + internal static let settingsUserInterface = VectorL10n.tr("Vector", "settings_user_interface") + /// USER SETTINGS + internal static let settingsUserSettings = VectorL10n.tr("Vector", "settings_user_settings") + /// Version %@ + internal static func settingsVersion(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_version", p1) + } + /// Login in the main app to share content + internal static let shareExtensionAuthPrompt = VectorL10n.tr("Vector", "share_extension_auth_prompt") + /// Failed to send. Check in the main app the encryption settings for this room + internal static let shareExtensionFailedToEncrypt = VectorL10n.tr("Vector", "share_extension_failed_to_encrypt") + /// Start + internal static let start = VectorL10n.tr("Vector", "start") + /// Favourites + internal static let titleFavourites = VectorL10n.tr("Vector", "title_favourites") + /// Communities + internal static let titleGroups = VectorL10n.tr("Vector", "title_groups") + /// Home + internal static let titleHome = VectorL10n.tr("Vector", "title_home") + /// People + internal static let titlePeople = VectorL10n.tr("Vector", "title_people") + /// Rooms + internal static let titleRooms = VectorL10n.tr("Vector", "title_rooms") + /// Today + internal static let today = VectorL10n.tr("Vector", "today") + /// This room contains unknown devices which have not been verified.\nThis means there is no guarantee that the devices belong to the users they claim to.\nWe recommend you go through the verification process for each device before continuing, but you can resend the message without verifying if you prefer. + internal static let unknownDevicesAlert = VectorL10n.tr("Vector", "unknown_devices_alert") + /// Room contains unknown devices + internal static let unknownDevicesAlertTitle = VectorL10n.tr("Vector", "unknown_devices_alert_title") + /// Answer Anyway + internal static let unknownDevicesAnswerAnyway = VectorL10n.tr("Vector", "unknown_devices_answer_anyway") + /// Call Anyway + internal static let unknownDevicesCallAnyway = VectorL10n.tr("Vector", "unknown_devices_call_anyway") + /// Send Anyway + internal static let unknownDevicesSendAnyway = VectorL10n.tr("Vector", "unknown_devices_send_anyway") + /// Unknown devices + internal static let unknownDevicesTitle = VectorL10n.tr("Vector", "unknown_devices_title") + /// Verify… + internal static let unknownDevicesVerify = VectorL10n.tr("Vector", "unknown_devices_verify") + /// Video + internal static let video = VectorL10n.tr("Vector", "video") + /// View + internal static let view = VectorL10n.tr("Vector", "view") + /// Voice + internal static let voice = VectorL10n.tr("Vector", "voice") + /// Warning + internal static let warning = VectorL10n.tr("Vector", "warning") + /// Widget creation has failed + internal static let widgetCreationFailure = VectorL10n.tr("Vector", "widget_creation_failure") + /// Failed to send request. + internal static let widgetIntegrationFailedToSendRequest = VectorL10n.tr("Vector", "widget_integration_failed_to_send_request") + /// Missing room_id in request. + internal static let widgetIntegrationMissingRoomId = VectorL10n.tr("Vector", "widget_integration_missing_room_id") + /// Missing user_id in request. + internal static let widgetIntegrationMissingUserId = VectorL10n.tr("Vector", "widget_integration_missing_user_id") + /// You are not in this room. + internal static let widgetIntegrationMustBeInRoom = VectorL10n.tr("Vector", "widget_integration_must_be_in_room") + /// You need to be able to invite users to do that. + internal static let widgetIntegrationNeedToBeAbleToInvite = VectorL10n.tr("Vector", "widget_integration_need_to_be_able_to_invite") + /// You do not have permission to do that in this room. + internal static let widgetIntegrationNoPermissionInRoom = VectorL10n.tr("Vector", "widget_integration_no_permission_in_room") + /// Power level must be positive integer. + internal static let widgetIntegrationPositivePowerLevel = VectorL10n.tr("Vector", "widget_integration_positive_power_level") + /// This room is not recognised. + internal static let widgetIntegrationRoomNotRecognised = VectorL10n.tr("Vector", "widget_integration_room_not_recognised") + /// Room %@ is not visible. + internal static func widgetIntegrationRoomNotVisible(_ p1: String) -> String { + return VectorL10n.tr("Vector", "widget_integration_room_not_visible", p1) + } + /// Unable to create widget. + internal static let widgetIntegrationUnableToCreate = VectorL10n.tr("Vector", "widget_integration_unable_to_create") + /// You need permission to manage widgets in this room + internal static let widgetNoPowerToManage = VectorL10n.tr("Vector", "widget_no_power_to_manage") + /// You don't currently have any stickerpacks enabled. + internal static let widgetStickerPickerNoStickerpacksAlert = VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert") + /// Add some now? + internal static let widgetStickerPickerNoStickerpacksAlertAddNow = VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert_add_now") + /// Yesterday + internal static let yesterday = VectorL10n.tr("Vector", "yesterday") + /// You + internal static let you = VectorL10n.tr("Vector", "you") +} +// swiftlint:enable function_parameter_count identifier_name line_length type_body_length + +// MARK: - Implementation Details + +extension VectorL10n { + private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "") + return String(format: format, locale: Locale.current, arguments: args) + } +} + +private final class BundleToken {} From a182234fa17c95931cc3203f982c44ad5a3d812b Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 14 Jan 2019 17:09:49 +0100 Subject: [PATCH 062/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 6ce6d4344..c8978bc61 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,6 +4,7 @@ Changes in 0.7.x (2019-xx-xx) Improvements: * Theming: Create ThemeService to make theming easier. Use it to reskin Riot. * Use modern literals and array/dictionary syntax where possible (PR #2160). + * Add SwiftGen pod in order to generate Swift constants for assets (#2177). Bug fix: * Use white scroll bar on dark themes (#2158) From 23356d8a064d1f35a7e5b9b0c0ccffedcc63b9f1 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 16 Jan 2019 16:51:36 +0100 Subject: [PATCH 063/244] RoomVC: `Redact` has been renamed to `Remove` to match riot/web #2134 --- CHANGES.rst | 1 + Riot/Assets/en.lproj/Vector.strings | 2 +- Riot/Generated/Strings.swift | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index c8978bc61..6462bedda 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,7 @@ Improvements: * Theming: Create ThemeService to make theming easier. Use it to reskin Riot. * Use modern literals and array/dictionary syntax where possible (PR #2160). * Add SwiftGen pod in order to generate Swift constants for assets (#2177). + * RoomVC: `Redact` has been renamed to `Remove` to match riot/web (#2134). Bug fix: * Use white scroll bar on dark themes (#2158) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 9fad99136..7f168d5a6 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -254,7 +254,7 @@ "room_delete_unsent_messages" = "Delete unsent messages"; "room_event_action_copy" = "Copy"; "room_event_action_quote" = "Quote"; -"room_event_action_redact" = "Redact"; +"room_event_action_redact" = "Remove"; "room_event_action_more" = "More"; "room_event_action_share" = "Share"; "room_event_action_permalink" = "Permalink"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index fc980242a..1b1ab9bf4 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -632,7 +632,7 @@ internal enum VectorL10n { internal static let roomEventActionPermalink = VectorL10n.tr("Vector", "room_event_action_permalink") /// Quote internal static let roomEventActionQuote = VectorL10n.tr("Vector", "room_event_action_quote") - /// Redact + /// Remove internal static let roomEventActionRedact = VectorL10n.tr("Vector", "room_event_action_redact") /// Report content internal static let roomEventActionReport = VectorL10n.tr("Vector", "room_event_action_report") From fae1d1da265b8ca522934c39a62a4e8e2c0bb39b Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 17 Jan 2019 11:59:21 +0100 Subject: [PATCH 064/244] BF: Registration: fix tap gesture on checkboxes in the terms screen --- CHANGES.rst | 1 + .../Modules/Authentication/Views/TermsView.swift | 16 +++++++--------- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 6462bedda..2e56c3156 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,7 @@ Improvements: Bug fix: * Use white scroll bar on dark themes (#2158) + * Registration: fix tap gesture on checkboxes in the terms screen Changes in 0.7.11 (2019-01-08) =============================================== diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index ceec376fd..0e368831c 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -141,16 +141,14 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie cell.accessoryType = .disclosureIndicator cell.backgroundColor = UIColor.clear + if let checkBox = cell.checkBox, checkBox.gestureRecognizers?.isEmpty ?? true { + let gesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapCheckbox)) + gesture.numberOfTapsRequired = 1 + gesture.numberOfTouchesRequired = 1 - let gesture: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(didTapCheckbox)) - gesture.numberOfTapsRequired = 1 - gesture.numberOfTouchesRequired = 1 - - cell.checkBox.tag = indexPath.row - - cell.checkBox?.isUserInteractionEnabled = true - if (cell.checkBox?.gestureRecognizers?.count == 0) { - cell.checkBox?.addGestureRecognizer(gesture) + checkBox.isUserInteractionEnabled = true + checkBox.tag = indexPath.row + checkBox.addGestureRecognizer(gesture) } return cell From 8a210a5fa14ec3b7419efbef34630230d7197322 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 17 Jan 2019 12:04:42 +0100 Subject: [PATCH 065/244] Registration: improve validation UX on the terms screen #2164 Do like on android (https://github.com/vector-im/riot-ios/issues/2164#issuecomment-455108199) --- CHANGES.rst | 5 +++-- Riot/Modules/Authentication/Views/TermsView.swift | 13 ------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 2e56c3156..4a6e35c30 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,8 +8,9 @@ Improvements: * RoomVC: `Redact` has been renamed to `Remove` to match riot/web (#2134). Bug fix: - * Use white scroll bar on dark themes (#2158) - * Registration: fix tap gesture on checkboxes in the terms screen + * Use white scroll bar on dark themes (#2158). + * Registration: fix tap gesture on checkboxes in the terms screen. + * Registration: improve validation UX on the terms screen (#2164). Changes in 0.7.11 (2019-01-08) =============================================== diff --git a/Riot/Modules/Authentication/Views/TermsView.swift b/Riot/Modules/Authentication/Views/TermsView.swift index 0e368831c..7a387fd7c 100644 --- a/Riot/Modules/Authentication/Views/TermsView.swift +++ b/Riot/Modules/Authentication/Views/TermsView.swift @@ -189,9 +189,6 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie let leftBarButtonItem: UIBarButtonItem = UIBarButtonItem(image: UIImage(named: "back_icon"), style: .plain, target: self, action:#selector(didTapCancelOnPolicyScreen)) webViewViewController.navigationItem.leftBarButtonItem = leftBarButtonItem - let rightBarButtonItem: UIBarButtonItem = UIBarButtonItem(title: NSLocalizedString("accept", tableName: "Vector", comment: ""), style: .plain, target: self, action: #selector(didAcceptPolicy)) - webViewViewController.navigationItem.rightBarButtonItem = rightBarButtonItem - navigationController = RiotNavigationController() delegate?.authInputsView?(nil, present: navigationController, animated: false) navigationController?.pushViewController(webViewViewController, animated: false) @@ -201,16 +198,6 @@ final class TermsView: UIView, NibOwnerLoadable, UITableViewDelegate, UITableVie removePolicyScreen() } - @objc private func didAcceptPolicy() { - - if let displayedPolicyIndex = self.displayedPolicyIndex { - acceptedPolicies.insert(displayedPolicyIndex) - } - - removePolicyScreen() - reload() - } - private func removePolicyScreen() { displayedPolicyIndex = nil From 688e219a3267e3935077ad7c02a229f655053c56 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 17 Jan 2019 15:35:40 +0100 Subject: [PATCH 066/244] Reskin: Fix regression: Wrong status bar color on login/registration screens #2184 --- .../Authentication/AuthenticationViewController.m | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index af0ec0557..e2a13010c 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -131,13 +131,15 @@ - (void)userInterfaceThemeDidChange { - NSLog(@"### %@", self.navigationController); - NSLog(@"### %@", [AppDelegate theDelegate].masterTabBarController.navigationController); - [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationBar]; - //[ThemeService.shared.theme applyStyleOnNavigationBar:[AppDelegate theDelegate].masterTabBarController.navigationController.navigationBar]; - self.view.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + // This view controller is not part of a navigation controller + // so that applyStyleOnNavigationBar does not fully work. + // In order to have the right status bar color, use the expected status bar color + // as the main view background color. + // Hopefully, subviews define their own background color with `theme.backgroundColor`, + // which makes all work together. + self.view.backgroundColor = ThemeService.shared.theme.baseColor; self.authenticationScrollView.backgroundColor = ThemeService.shared.theme.backgroundColor; self.authFallbackContentView.backgroundColor = ThemeService.shared.theme.backgroundColor; From ec43309cbe5eb210638758db5123596248faed27 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 17 Jan 2019 16:02:55 +0100 Subject: [PATCH 067/244] Registration: improve scrolling on the reCaptcha screen #2165 --- CHANGES.rst | 1 + Riot/Modules/Authentication/Views/AuthInputsView.m | 3 +++ 2 files changed, 4 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 4a6e35c30..0da0334f7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ Bug fix: * Use white scroll bar on dark themes (#2158). * Registration: fix tap gesture on checkboxes in the terms screen. * Registration: improve validation UX on the terms screen (#2164). + * Registration: improve scrolling on the reCaptcha screen (#2165). Changes in 0.7.11 (2019-01-08) =============================================== diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index a1a55cc73..6f024caff 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -1320,6 +1320,9 @@ reCaptchaWebView.translatesAutoresizingMaskIntoConstraints = NO; [self.recaptchaContainer addSubview:reCaptchaWebView]; + // Disable the webview scrollView to avoid 2 scrollviews on the same screen + reCaptchaWebView.scrollView.scrollEnabled = NO; + [self.recaptchaContainer addConstraints: [NSLayoutConstraint constraintsWithVisualFormat:@"|-[view]-|" options:0 From daf0bf8a912a3c86206bf4864d86fdceb7f2e8c8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 17 Jan 2019 17:46:49 +0100 Subject: [PATCH 068/244] BF: Infinite loading wheel when taping on a fake room alias #679 --- CHANGES.rst | 1 + Riot/AppDelegate.h | 1 + Riot/AppDelegate.m | 51 +++++++++++++++-------------- Riot/Assets/en.lproj/Vector.strings | 1 + Riot/Generated/Strings.swift | 4 +++ 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 4a6e35c30..50d4404b8 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ Bug fix: * Use white scroll bar on dark themes (#2158). * Registration: fix tap gesture on checkboxes in the terms screen. * Registration: improve validation UX on the terms screen (#2164). + * Infinite loading wheel when taping on a fake room alias (#679). Changes in 0.7.11 (2019-01-08) =============================================== diff --git a/Riot/AppDelegate.h b/Riot/AppDelegate.h index 2f04960be..811161010 100644 --- a/Riot/AppDelegate.h +++ b/Riot/AppDelegate.h @@ -90,6 +90,7 @@ extern NSString *const kAppDelegateNetworkStatusDidChangeNotification; - (void)restoreEmptyDetailsViewController; - (UIAlertController*)showErrorAsAlert:(NSError*)error; +- (UIAlertController*)showAlertWithTitle:(NSString*)title message:(NSString*)message; #pragma mark - Matrix Sessions handling diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 0f6ccb1f4..3132f6db6 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -871,9 +871,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN return nil; } } - - [_errorNotification dismissViewControllerAnimated:NO completion:nil]; - + NSString *title = [error.userInfo valueForKey:NSLocalizedFailureReasonErrorKey]; NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey]; if (!title) @@ -889,13 +887,26 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } } - _errorNotification = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert]; + // Switch in offline mode in case of network reachability error + if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorNotConnectedToInternet) + { + self.isOffline = YES; + } + + return [self showAlertWithTitle:title message:msg]; +} + +- (UIAlertController*)showAlertWithTitle:(NSString*)title message:(NSString*)message +{ + [_errorNotification dismissViewControllerAnimated:NO completion:nil]; + + _errorNotification = [UIAlertController alertControllerWithTitle:title message:message preferredStyle:UIAlertControllerStyleAlert]; [_errorNotification addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - + [AppDelegate theDelegate].errorNotification = nil; - + }]]; // Display the error notification if (!isErrorNotificationSuspended) @@ -903,13 +914,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [_errorNotification mxk_setAccessibilityIdentifier:@"AppDelegateErrorAlert"]; [self showNotificationAlert:_errorNotification]; } - - // Switch in offline mode in case of network reachability error - if ([error.domain isEqualToString:NSURLErrorDomain] && error.code == NSURLErrorNotConnectedToInternet) - { - self.isOffline = YES; - } - + return self.errorNotification; } @@ -1917,6 +1922,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } failure:^(NSError *error) { NSLog(@"[AppDelegate] Universal link: Error: The home server failed to resolve the room alias (%@)", roomIdOrAlias); + + [homeViewController stopActivityIndicator]; + + NSString *errorMessage = [NSString stringWithFormat:NSLocalizedStringFromTable(@"room_does_not_exist", @"Vector", nil), roomIdOrAlias]; + + [self showAlertWithTitle:nil message:errorMessage]; }]; } else if ([roomIdOrAlias hasPrefix:@"!"] && ((MXKAccount*)accountManager.activeAccounts.firstObject).mxSession.state != MXSessionStateRunning) @@ -3452,22 +3463,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN _jitsiViewController = nil; - NSError *theError = [NSError errorWithDomain:@"" - code:0 - userInfo:@{ - NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"call_jitsi_error", @"Vector", nil) - }]; - [self showErrorAsAlert:theError]; + [self showAlertWithTitle:nil message:NSLocalizedStringFromTable(@"call_jitsi_error", @"Vector", nil)]; }]; } else { - NSError *error = [NSError errorWithDomain:@"" - code:0 - userInfo:@{ - NSLocalizedDescriptionKey: NSLocalizedStringFromTable(@"call_already_displayed", @"Vector", nil) - }]; - [self showErrorAsAlert:error]; + [self showAlertWithTitle:nil message:NSLocalizedStringFromTable(@"call_already_displayed", @"Vector", nil)]; } } diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 7f168d5a6..f6ab41dfa 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -553,6 +553,7 @@ "do_not_ask_again" = "Do not ask again"; "camera_access_not_granted" = "%@ doesn't have permission to use Camera, please change privacy settings"; "large_badge_value_k_format" = "%.1fK"; +"room_does_not_exist" = "%@ does not exist"; // Call "call_incoming_voice_prompt" = "Incoming voice call from %@"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 1b1ab9bf4..ccdfdc3b3 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -614,6 +614,10 @@ internal enum VectorL10n { internal static let roomDirectoryNoPublicRoom = VectorL10n.tr("Vector", "room_directory_no_public_room") /// You do not have permission to post to this room internal static let roomDoNotHavePermissionToPost = VectorL10n.tr("Vector", "room_do_not_have_permission_to_post") + /// %@ does not exist + internal static func roomDoesNotExist(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_does_not_exist", p1) + } /// Reason for banning this user internal static let roomEventActionBanPromptReason = VectorL10n.tr("Vector", "room_event_action_ban_prompt_reason") /// Cancel Download From e11568d89829bee38948863309687412ace3248b Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Jan 2019 10:24:58 +0100 Subject: [PATCH 069/244] In Theme set placeholderTextColor non optional. Add commodity methods for text field and button. --- Riot/Managers/Theme/Theme.swift | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Riot/Managers/Theme/Theme.swift b/Riot/Managers/Theme/Theme.swift index bbf46aa58..e4279f026 100644 --- a/Riot/Managers/Theme/Theme.swift +++ b/Riot/Managers/Theme/Theme.swift @@ -64,7 +64,7 @@ import UIKit /// nil is used to keep the default color - var placeholderTextColor: UIColor? { get } + var placeholderTextColor: UIColor { get } /// nil is used to keep the default color var selectedBackgroundColor: UIColor? { get } @@ -74,7 +74,9 @@ import UIKit /// Color to tint the search background image var matrixSearchBackgroundImageTintColor: UIColor { get } - + + /// Color of separator (when table view is not used) + var separatorColor: UIColor { get } // MARK: - Customisation methods @@ -88,4 +90,14 @@ import UIKit /// /// - Parameter searchBar: the search bar to customise. func applyStyle(onSearchBar: UISearchBar) + + /// Apply the theme on a text field. + /// + /// - Parameter textField: the text field to customise. + func applyStyle(onTextField textField: UITextField) + + /// Apply the theme on a button. + /// + /// - Parameter button: The button to customise. + func applyStyle(onButton button: UIButton) } From 0f2160c5a895dbd67b91c35d96ef77fd30fee41b Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Jan 2019 10:40:37 +0100 Subject: [PATCH 070/244] Update DarkTheme and DefaultTheme to conform Theme protocol --- Riot/Managers/Theme/Themes/DarkTheme.swift | 13 ++++++++++++- Riot/Managers/Theme/Themes/DefaultTheme.swift | 15 +++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index 0ba6f25dd..8ce68186b 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -53,10 +53,11 @@ final class DarkTheme: NSObject, Theme { let scrollBarStyle: UIScrollViewIndicatorStyle = .white let keyboardAppearance: UIKeyboardAppearance = .dark - let placeholderTextColor: UIColor? = UIColor(white: 1.0, alpha: 0.3) + let placeholderTextColor: UIColor = UIColor(white: 1.0, alpha: 0.3) let selectedBackgroundColor: UIColor? = UIColor.black let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) + let separatorColor: UIColor = UIColor(rgb: 0x2E2F31) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; @@ -76,4 +77,14 @@ final class DarkTheme: NSObject, Theme { searchBar.layer.borderWidth = 1; searchBar.layer.borderColor = self.headerBorderColor.cgColor; } + + func applyStyle(onTextField texField: UITextField) { + texField.textColor = self.textPrimaryColor + texField.tintColor = self.tintColor + } + + func applyStyle(onButton button: UIButton) { + // NOTE: Tint color does nothing by default on button type `UIButtonType.custom` + button.tintColor = self.tintColor + } } diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index 55bcc096a..920fa8019 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -32,7 +32,7 @@ final class DefaultTheme: NSObject, Theme { let headerBackgroundColor: UIColor = UIColor(rgb: 0xF1F5F8) let headerBorderColor: UIColor = UIColor(rgb: 0xEAEEF2) - let headerTextPrimaryColor: UIColor = UIColor(rgb: 0x96A1B7) + let headerTextPrimaryColor: UIColor = UIColor(rgb: 0x72708B) let headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) let textPrimaryColor: UIColor = UIColor(rgb: 0x383838) @@ -53,10 +53,11 @@ final class DefaultTheme: NSObject, Theme { let scrollBarStyle: UIScrollViewIndicatorStyle = .default let keyboardAppearance: UIKeyboardAppearance = .light - let placeholderTextColor: UIColor? = nil // Use default 70% gray color + let placeholderTextColor: UIColor = UIColor(white: 0.7, alpha: 1.0) // Use default 70% gray color let selectedBackgroundColor: UIColor? = nil // Use the default selection color let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) + let separatorColor: UIColor = UIColor(rgb: 0xEAEEF2) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; @@ -76,4 +77,14 @@ final class DefaultTheme: NSObject, Theme { searchBar.layer.borderWidth = 1; searchBar.layer.borderColor = self.headerBorderColor.cgColor; } + + func applyStyle(onTextField texField: UITextField) { + texField.textColor = self.textPrimaryColor + texField.tintColor = self.tintColor + } + + func applyStyle(onButton button: UIButton) { + // NOTE: Tint color does nothing by default on button type `UIButtonType.custom` + button.tintColor = self.tintColor + } } From 58b3b659b76ffd2eb23a97e9cfa7415587c0a09d Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 18 Jan 2019 11:31:29 +0100 Subject: [PATCH 071/244] reskin: Make existing themes inheritable --- Riot/Managers/Theme/Themes/DarkTheme.swift | 52 +++++++++---------- Riot/Managers/Theme/Themes/DefaultTheme.swift | 52 +++++++++---------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index 8ce68186b..0053ccd6e 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -19,45 +19,45 @@ import UIKit /// Color constants for the dark theme @objcMembers -final class DarkTheme: NSObject, Theme { +class DarkTheme: NSObject, Theme { - let backgroundColor: UIColor = UIColor(rgb: 0x212224) + var backgroundColor: UIColor = UIColor(rgb: 0x212224) - let baseColor: UIColor = UIColor(rgb: 0x292E37) - let baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + var baseColor: UIColor = UIColor(rgb: 0x292E37) + var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let searchBackgroundColor: UIColor = UIColor(rgb: 0x3E434B) - let searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) + var searchBackgroundColor: UIColor = UIColor(rgb: 0x3E434B) + var searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) - let headerBackgroundColor: UIColor = UIColor(rgb: 0x303540) - let headerBorderColor: UIColor = UIColor(rgb: 0x2E2F31) - let headerTextPrimaryColor: UIColor = UIColor(rgb: 0x96A1B7) - let headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) + var headerBackgroundColor: UIColor = UIColor(rgb: 0x303540) + var headerBorderColor: UIColor = UIColor(rgb: 0x2E2F31) + var headerTextPrimaryColor: UIColor = UIColor(rgb: 0x96A1B7) + var headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) - let textPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let textSecondaryColor: UIColor = UIColor(rgb: 0xD8D8D8) + var textPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + var textSecondaryColor: UIColor = UIColor(rgb: 0xD8D8D8) - let tintColor: UIColor = UIColor(rgb: 0x7AC9A1) - let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) + var tintColor: UIColor = UIColor(rgb: 0x7AC9A1) + var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - let notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) + var notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) + var notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) - let avatarColors: [UIColor] = [ + var avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] - let statusBarStyle: UIStatusBarStyle = .lightContent - let scrollBarStyle: UIScrollViewIndicatorStyle = .white - let keyboardAppearance: UIKeyboardAppearance = .dark + var statusBarStyle: UIStatusBarStyle = .lightContent + var scrollBarStyle: UIScrollViewIndicatorStyle = .white + var keyboardAppearance: UIKeyboardAppearance = .dark - let placeholderTextColor: UIColor = UIColor(white: 1.0, alpha: 0.3) - let selectedBackgroundColor: UIColor? = UIColor.black - let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) - let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) - let separatorColor: UIColor = UIColor(rgb: 0x2E2F31) + var placeholderTextColor: UIColor = UIColor(white: 1.0, alpha: 0.3) + var selectedBackgroundColor: UIColor? = UIColor.black + var overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) + var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) + var separatorColor: UIColor = UIColor(rgb: 0x2E2F31) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index 920fa8019..f7a9dba66 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -19,45 +19,45 @@ import UIKit /// Color constants for the default theme @objcMembers -final class DefaultTheme: NSObject, Theme { +class DefaultTheme: NSObject, Theme { - let backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) + var backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) - let baseColor: UIColor = UIColor(rgb: 0x2E3648) - let baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + var baseColor: UIColor = UIColor(rgb: 0x2E3648) + var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - let searchBackgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) - let searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) + var searchBackgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) + var searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) - let headerBackgroundColor: UIColor = UIColor(rgb: 0xF1F5F8) - let headerBorderColor: UIColor = UIColor(rgb: 0xEAEEF2) - let headerTextPrimaryColor: UIColor = UIColor(rgb: 0x72708B) - let headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) + var headerBackgroundColor: UIColor = UIColor(rgb: 0xF1F5F8) + var headerBorderColor: UIColor = UIColor(rgb: 0xEAEEF2) + var headerTextPrimaryColor: UIColor = UIColor(rgb: 0x72708B) + var headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) - let textPrimaryColor: UIColor = UIColor(rgb: 0x383838) - let textSecondaryColor: UIColor = UIColor(rgb: 0x9E9E9E) + var textPrimaryColor: UIColor = UIColor(rgb: 0x383838) + var textSecondaryColor: UIColor = UIColor(rgb: 0x9E9E9E) - let tintColor: UIColor = UIColor(rgb: 0x7AC9A1) - let unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) + var tintColor: UIColor = UIColor(rgb: 0x7AC9A1) + var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - let notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) - let notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) + var notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) + var notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) - let avatarColors: [UIColor] = [ + var avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), UIColor(rgb: 0x76DDD7)] - let statusBarStyle: UIStatusBarStyle = .lightContent - let scrollBarStyle: UIScrollViewIndicatorStyle = .default - let keyboardAppearance: UIKeyboardAppearance = .light + var statusBarStyle: UIStatusBarStyle = .lightContent + var scrollBarStyle: UIScrollViewIndicatorStyle = .default + var keyboardAppearance: UIKeyboardAppearance = .light - let placeholderTextColor: UIColor = UIColor(white: 0.7, alpha: 1.0) // Use default 70% gray color - let selectedBackgroundColor: UIColor? = nil // Use the default selection color - let overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) - let matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) - let separatorColor: UIColor = UIColor(rgb: 0xEAEEF2) + var placeholderTextColor: UIColor = UIColor(white: 0.7, alpha: 1.0) // Use default 70% gray color + var selectedBackgroundColor: UIColor? = nil // Use the default selection color + var overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) + var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) + var separatorColor: UIColor = UIColor(rgb: 0xEAEEF2) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; From cc4ae57c1e4d8c6374abf9f22e49cf52f7b78605 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 18 Jan 2019 11:32:37 +0100 Subject: [PATCH 072/244] reskin: Create a black theme from the dark theme #2175 --- Riot.xcodeproj/project.pbxproj | 6 +++++ Riot/Managers/Theme/ThemeService.m | 3 +-- Riot/Managers/Theme/Themes/BlackTheme.swift | 25 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 Riot/Managers/Theme/Themes/BlackTheme.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index bbef3414d..e58805c27 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -10,6 +10,8 @@ 24CBEC591F0EAD310093EABB /* RiotShareExtension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BBE81E7009EC00A9B29C /* MXRoom+Riot.m */; }; 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BC111E7009EC00A9B29C /* AvatarGenerator.m */; }; + 3209451221F1C1430088CAA2 /* BlackTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3209451121F1C1430088CAA2 /* BlackTheme.swift */; }; + 3209451321F1C1D50088CAA2 /* BlackTheme.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3209451121F1C1430088CAA2 /* BlackTheme.swift */; }; 32242F0921E8B05F00725742 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0821E8B05F00725742 /* UIColor.swift */; }; 32242F0A21E8B21300725742 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0821E8B05F00725742 /* UIColor.swift */; }; 32242F1221E8FBA900725742 /* ThemeService.m in Sources */ = {isa = PBXBuildFile; fileRef = 32242F0C21E8FBA900725742 /* ThemeService.m */; }; @@ -394,6 +396,7 @@ 24CBEC4E1F0EAD310093EABB /* RiotShareExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = RiotShareExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; 2510A69B4A681C1FEC36E848 /* Pods_RiotPods_Riot.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_Riot.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 319CD7C67A47A3D35959E18F /* Pods-RiotPods-Riot.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-Riot.release.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-Riot/Pods-RiotPods-Riot.release.xcconfig"; sourceTree = ""; }; + 3209451121F1C1430088CAA2 /* BlackTheme.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BlackTheme.swift; sourceTree = ""; }; 32242F0821E8B05F00725742 /* UIColor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = ""; }; 32242F0C21E8FBA900725742 /* ThemeService.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ThemeService.m; sourceTree = ""; }; 32242F0D21E8FBA900725742 /* Theme.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Theme.swift; sourceTree = ""; }; @@ -1008,6 +1011,7 @@ children = ( 32242F0F21E8FBA900725742 /* DefaultTheme.swift */, 32242F1021E8FBA900725742 /* DarkTheme.swift */, + 3209451121F1C1430088CAA2 /* BlackTheme.swift */, ); path = Themes; sourceTree = ""; @@ -3030,6 +3034,7 @@ 32242F1621E8FBCC00725742 /* ThemeService.m in Sources */, 24EEE5A31F23A8C300B3C705 /* AvatarGenerator.m in Sources */, B1664BCF20F4E67600808783 /* ShareExtensionManager.m in Sources */, + 3209451321F1C1D50088CAA2 /* BlackTheme.swift in Sources */, 24EEE5A21F23A8B400B3C705 /* MXRoom+Riot.m in Sources */, B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */, F0A8955F1F7D1FEA00BD6C2A /* MXRoomSummary+Riot.m in Sources */, @@ -3115,6 +3120,7 @@ F083BE041E7009ED00A9B29C /* Tools.m in Sources */, 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */, B1B5573D20EE6C4D00210D55 /* WebViewViewController.m in Sources */, + 3209451221F1C1430088CAA2 /* BlackTheme.swift in Sources */, B1B5572720EE6C4D00210D55 /* RoomSearchViewController.m in Sources */, F05927C91FDED836009F2A68 /* MXGroup+Riot.m in Sources */, B1B5594520EF7BD000210D55 /* TableViewCellWithCollectionView.m in Sources */, diff --git a/Riot/Managers/Theme/ThemeService.m b/Riot/Managers/Theme/ThemeService.m index a12fafa04..3efd09d3d 100644 --- a/Riot/Managers/Theme/ThemeService.m +++ b/Riot/Managers/Theme/ThemeService.m @@ -73,8 +73,7 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan } else if ([themeId isEqualToString:@"black"]) { - // TODO: Use dark theme for the moment - theme = [DarkTheme new]; + theme = [BlackTheme new]; } else { diff --git a/Riot/Managers/Theme/Themes/BlackTheme.swift b/Riot/Managers/Theme/Themes/BlackTheme.swift new file mode 100644 index 000000000..0a42eae34 --- /dev/null +++ b/Riot/Managers/Theme/Themes/BlackTheme.swift @@ -0,0 +1,25 @@ +/* + Copyright 2019 New Vector 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 UIKit + +class BlackTheme: DarkTheme { + + override init() { + super.init() + self.backgroundColor = UIColor.black + } +} From ad1969fbc89193415c49dafc08873baf48910283 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 18 Jan 2019 13:40:09 +0100 Subject: [PATCH 073/244] reskin: kill riotColorRed & riotColorPinkRed Merge them into Theme.warningColor Part of #2174 --- Riot/Managers/Theme/Theme.swift | 3 +++ Riot/Managers/Theme/ThemeService.h | 2 -- Riot/Managers/Theme/ThemeService.m | 2 -- Riot/Managers/Theme/Themes/DarkTheme.swift | 2 ++ Riot/Managers/Theme/Themes/DefaultTheme.swift | 2 ++ .../AuthenticationViewController.m | 2 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../Detail/RoomMemberDetailsViewController.m | 4 ++-- Riot/Modules/Room/RoomViewController.m | 2 +- .../Settings/RoomSettingsViewController.m | 2 +- .../Views/Activities/RoomActivitiesView.m | 22 +++++++++---------- .../RoomOutgoingAttachmentBubbleCell.m | 2 +- .../DeactivateAccountViewController.m | 2 +- .../Modules/Settings/SettingsViewController.m | 2 +- Riot/Utils/EventFormatter.m | 2 +- 15 files changed, 28 insertions(+), 25 deletions(-) diff --git a/Riot/Managers/Theme/Theme.swift b/Riot/Managers/Theme/Theme.swift index e4279f026..43ad45c28 100644 --- a/Riot/Managers/Theme/Theme.swift +++ b/Riot/Managers/Theme/Theme.swift @@ -46,6 +46,9 @@ import UIKit /// Color for notifications for mention messages var notificationPrimaryColor: UIColor { get } + /// Color for errors or warnings + var warningColor: UIColor { get } + var avatarColors: [UIColor] { get } diff --git a/Riot/Managers/Theme/ThemeService.h b/Riot/Managers/Theme/ThemeService.h index 553b87156..4097896f5 100644 --- a/Riot/Managers/Theme/ThemeService.h +++ b/Riot/Managers/Theme/ThemeService.h @@ -61,8 +61,6 @@ extern NSString *const kThemeServiceDidChangeThemeNotification; #pragma mark - Riot Colors not yet themeable -@property (nonatomic, readonly) UIColor *riotColorPinkRed; -@property (nonatomic, readonly) UIColor *riotColorRed; @property (nonatomic, readonly) UIColor *riotColorBlue; @property (nonatomic, readonly) UIColor *riotColorCuriousBlue; @property (nonatomic, readonly) UIColor *riotColorIndigo; diff --git a/Riot/Managers/Theme/ThemeService.m b/Riot/Managers/Theme/ThemeService.m index 3efd09d3d..2c54ec5ad 100644 --- a/Riot/Managers/Theme/ThemeService.m +++ b/Riot/Managers/Theme/ThemeService.m @@ -92,8 +92,6 @@ NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChan if (self) { // Riot Colors not yet themeable - _riotColorPinkRed = [[UIColor alloc] initWithRgb:0xFF0064]; - _riotColorRed = [[UIColor alloc] initWithRgb:0xFF4444]; _riotColorBlue = [[UIColor alloc] initWithRgb:0x81BDDB]; _riotColorCuriousBlue = [[UIColor alloc] initWithRgb:0x2A9EDB]; _riotColorIndigo = [[UIColor alloc] initWithRgb:0xBD79CC]; diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index 0053ccd6e..f0c2ee557 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -44,6 +44,8 @@ class DarkTheme: NSObject, Theme { var notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) var notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) + var warningColor: UIColor = UIColor(rgb: 0xF56679) + var avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index f7a9dba66..9e1e887da 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -44,6 +44,8 @@ class DefaultTheme: NSObject, Theme { var notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) var notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) + var warningColor: UIColor = UIColor(rgb: 0xF56679) + var avatarColors: [UIColor] = [ UIColor(rgb: 0x7AC9A1), UIColor(rgb: 0x1E7DDC), diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index e2a13010c..c3b939335 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -163,7 +163,7 @@ self.submitButton.backgroundColor = ThemeService.shared.theme.tintColor; self.skipButton.backgroundColor = ThemeService.shared.theme.tintColor; - self.noFlowLabel.textColor = ThemeService.shared.riotColorRed; + self.noFlowLabel.textColor = ThemeService.shared.theme.warningColor; NSMutableAttributedString *forgotPasswordTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"auth_forgot_password", @"Vector", nil)]; [forgotPasswordTitle addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, forgotPasswordTitle.length)]; diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 6825f85d4..bc2757b60 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -100,7 +100,7 @@ static const CGFloat kButtonSize = 80.0; self.answerTitleLabel.font = [UIFont systemFontOfSize:18.0 weight:UIFontWeightRegular]; self.answerTitleLabel.text = NSLocalizedStringFromTable(@"accept", @"Vector", nil); - UIColor *rejectButtonBorderColor = ThemeService.shared.riotColorPinkRed; + UIColor *rejectButtonBorderColor = ThemeService.shared.theme.warningColor; self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"call_hangup_icon"] borderColor:rejectButtonBorderColor]; diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index e9bef3823..fe4a29c1d 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -777,8 +777,8 @@ if (actionNumber.unsignedIntegerValue == MXKRoomMemberDetailsActionKick) { - [cellWithButton.mxkButton setTitleColor:ThemeService.shared.riotColorPinkRed forState:UIControlStateNormal]; - [cellWithButton.mxkButton setTitleColor:ThemeService.shared.riotColorPinkRed forState:UIControlStateHighlighted]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.theme.warningColor forState:UIControlStateNormal]; + [cellWithButton.mxkButton setTitleColor:ThemeService.shared.theme.warningColor forState:UIControlStateHighlighted]; } else { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 5f487e571..2574f80fe 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1331,7 +1331,7 @@ // Show it in red only for room widgets, not user's widgets // TODO: Design must be reviewed UIImage *icon = self.navigationItem.rightBarButtonItems[1].image; - icon = [MXKTools paintImage:icon withColor:ThemeService.shared.riotColorPinkRed]; + icon = [MXKTools paintImage:icon withColor:ThemeService.shared.theme.warningColor]; icon = [icon imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal]; self.navigationItem.rightBarButtonItems[1].image = icon; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 71d63f388..27e3b1c60 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -2362,7 +2362,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti cell = [tableView dequeueReusableCellWithIdentifier:kRoomSettingsWarningCellViewIdentifier forIndexPath:indexPath]; cell.textLabel.font = [UIFont systemFontOfSize:17]; - cell.textLabel.textColor = ThemeService.shared.riotColorPinkRed; + cell.textLabel.textColor = ThemeService.shared.theme.warningColor; cell.textLabel.numberOfLines = 0; cell.accessoryView = nil; cell.accessoryType = UITableViewCellAccessoryNone; diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index e696e2ecd..e5b959ec4 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -113,7 +113,7 @@ [super customizeViewRendering]; self.separatorView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - if (self.messageLabel.textColor != ThemeService.shared.riotColorPinkRed) + if (self.messageLabel.textColor != ThemeService.shared.theme.warningColor) { self.messageLabel.textColor = ThemeService.shared.theme.textSecondaryColor; } @@ -145,18 +145,18 @@ [tappableNotif addAttribute:NSLinkAttributeName value:@"onCancelLink" range:range]; NSRange wholeString = NSMakeRange(0, tappableNotif.length); - [tappableNotif addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.riotColorPinkRed range:wholeString]; + [tappableNotif addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.warningColor range:wholeString]; [tappableNotif addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = tappableNotif; - self.messageTextView.tintColor = ThemeService.shared.riotColorPinkRed; + self.messageTextView.tintColor = ThemeService.shared.theme.warningColor; self.messageTextView.hidden = NO; self.messageTextView.backgroundColor = [UIColor clearColor]; } else { self.messageLabel.text = notification; - self.messageLabel.textColor = ThemeService.shared.riotColorPinkRed; + self.messageLabel.textColor = ThemeService.shared.theme.warningColor; self.messageLabel.hidden = NO; } @@ -187,7 +187,7 @@ { self.iconImageView.image = [UIImage imageNamed:@"error"]; self.messageLabel.text = labelText; - self.messageLabel.textColor = ThemeService.shared.riotColorPinkRed; + self.messageLabel.textColor = ThemeService.shared.theme.warningColor; self.iconImageView.hidden = NO; self.messageLabel.hidden = NO; @@ -261,15 +261,15 @@ // Display the string in white on pink red NSRange wholeString = NSMakeRange(0, onGoingConferenceCallAttibutedString.length); [onGoingConferenceCallAttibutedString addAttribute:NSForegroundColorAttributeName value:ThemeService.shared.theme.backgroundColor range:wholeString]; - [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:ThemeService.shared.riotColorPinkRed range:wholeString]; + [onGoingConferenceCallAttibutedString addAttribute:NSBackgroundColorAttributeName value:ThemeService.shared.theme.warningColor range:wholeString]; [onGoingConferenceCallAttibutedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:15] range:wholeString]; self.messageTextView.attributedText = onGoingConferenceCallAttibutedString; self.messageTextView.tintColor = ThemeService.shared.theme.backgroundColor; self.messageTextView.hidden = NO; - self.backgroundColor = ThemeService.shared.riotColorPinkRed; - self.messageTextView.backgroundColor = ThemeService.shared.riotColorPinkRed; + self.backgroundColor = ThemeService.shared.theme.warningColor; + self.messageTextView.backgroundColor = ThemeService.shared.theme.warningColor; // Hide the separator to display correctly the red pink conf call banner self.separatorView.hidden = YES; @@ -295,7 +295,7 @@ notification = NSLocalizedStringFromTable(@"room_new_message_notification", @"Vector", nil); } self.messageLabel.text = [NSString stringWithFormat:notification, newMessagesCount]; - self.messageLabel.textColor = ThemeService.shared.riotColorPinkRed; + self.messageLabel.textColor = ThemeService.shared.theme.warningColor; self.messageLabel.hidden = NO; } else @@ -487,8 +487,8 @@ if (hardLimit) { - self.backgroundColor = ThemeService.shared.riotColorPinkRed; - self.messageTextView.backgroundColor = ThemeService.shared.riotColorPinkRed; + self.backgroundColor = ThemeService.shared.theme.warningColor; + self.messageTextView.backgroundColor = ThemeService.shared.theme.warningColor; } else { diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index a1e7b87b1..bb786416a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -49,7 +49,7 @@ // Show a red border when the attachment sending failed if (bubbleCell->bubbleData.attachment.eventSentState == MXEventSentStateFailed) { - bubbleCell.attachmentView.layer.borderColor = ThemeService.shared.riotColorPinkRed.CGColor; + bubbleCell.attachmentView.layer.borderColor = ThemeService.shared.theme.warningColor.CGColor; bubbleCell.attachmentView.layer.borderWidth = 1; } else diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 036ef9136..975146130 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -152,7 +152,7 @@ static CGFloat const kTextFontSize = 15.0; - (void)setupNavigationBar { - self.navigationController.navigationBar.titleTextAttributes = @{ NSForegroundColorAttributeName: ThemeService.shared.riotColorRed }; + self.navigationController.navigationBar.titleTextAttributes = @{ NSForegroundColorAttributeName: ThemeService.shared.theme.warningColor }; UIBarButtonItem *cancelBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedStringFromTable(@"cancel", @"Vector", nil) style:UIBarButtonItemStylePlain target:self action:@selector(cancelButtonAction:)]; self.navigationItem.rightBarButtonItem = cancelBarButtonItem; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 589054c68..1a6ec2402 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -2226,7 +2226,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); NSString *btnTitle = NSLocalizedStringFromTable(@"settings_deactivate_my_account", @"Vector", nil); [deactivateAccountBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateNormal]; [deactivateAccountBtnCell.mxkButton setTitle:btnTitle forState:UIControlStateHighlighted]; - [deactivateAccountBtnCell.mxkButton setTintColor:ThemeService.shared.riotColorRed]; + [deactivateAccountBtnCell.mxkButton setTintColor:ThemeService.shared.theme.warningColor]; deactivateAccountBtnCell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [deactivateAccountBtnCell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 7b893c038..562e86d3a 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -223,7 +223,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.bingTextColor = ThemeService.shared.theme.notificationPrimaryColor; self.encryptingTextColor = ThemeService.shared.theme.tintColor; self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; - self.errorTextColor = ThemeService.shared.riotColorRed; + self.errorTextColor = ThemeService.shared.theme.warningColor; self.defaultTextFont = [UIFont systemFontOfSize:15]; self.prefixTextFont = [UIFont boldSystemFontOfSize:15]; From db611552999422a4087e543709945e4a609ab6c3 Mon Sep 17 00:00:00 2001 From: fridtjof <2780577+fridtjof@users.noreply.github.com> Date: Mon, 7 Jan 2019 23:36:40 +0100 Subject: [PATCH 074/244] MasterTabBarController: Use @available instead of instancesRespondToSelector --- Riot/Modules/TabBar/MasterTabBarController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 0e93fc032..49a94f664 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -817,7 +817,7 @@ self.tabBar.items[index].badgeValue = badgeValue; - if ([UITabBarItem instancesRespondToSelector:@selector(setBadgeColor:)]) + if (@available(iOS 10, *)) { self.tabBar.items[index].badgeColor = badgeColor; } @@ -834,7 +834,7 @@ { self.tabBar.items[index].badgeValue = mark; - if ([UITabBarItem instancesRespondToSelector:@selector(setBadgeColor:)]) + if (@available(iOS 10, *)) { self.tabBar.items[index].badgeColor = badgeColor; } From 5088a7cfdd20fa916ec2d05a3a424d5e42d4e6d8 Mon Sep 17 00:00:00 2001 From: fridtjof <2780577+fridtjof@users.noreply.github.com> Date: Mon, 7 Jan 2019 23:37:35 +0100 Subject: [PATCH 075/244] AppDelegate: no need to check for iOS 8+ notifications anymore, the minimum supported version is iOS 9 --- Riot/AppDelegate.m | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 3132f6db6..2c7a00574 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -892,7 +892,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN { self.isOffline = YES; } - + return [self showAlertWithTitle:title message:msg]; } @@ -1077,20 +1077,18 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN if (!isPushRegistered) { NSMutableSet* notificationCategories = [NSMutableSet set]; - if ([[UIMutableUserNotificationAction class] instancesRespondToSelector:@selector(behavior)]) - { - UIMutableUserNotificationAction* quickReply = [[UIMutableUserNotificationAction alloc] init]; - quickReply.title = NSLocalizedStringFromTable(@"room_message_short_placeholder", @"Vector", nil); - quickReply.identifier = @"inline-reply"; - quickReply.activationMode = UIUserNotificationActivationModeBackground; - quickReply.authenticationRequired = true; - quickReply.behavior = UIUserNotificationActionBehaviorTextInput; - UIMutableUserNotificationCategory* quickReplyCategory = [[UIMutableUserNotificationCategory alloc] init]; - quickReplyCategory.identifier = @"QUICK_REPLY"; - [quickReplyCategory setActions:@[quickReply] forContext:UIUserNotificationActionContextDefault]; - [notificationCategories addObject:quickReplyCategory]; - } + UIMutableUserNotificationAction* quickReply = [[UIMutableUserNotificationAction alloc] init]; + quickReply.title = NSLocalizedStringFromTable(@"room_message_short_placeholder", @"Vector", nil); + quickReply.identifier = @"inline-reply"; + quickReply.activationMode = UIUserNotificationActivationModeBackground; + quickReply.authenticationRequired = true; + quickReply.behavior = UIUserNotificationActionBehaviorTextInput; + + UIMutableUserNotificationCategory* quickReplyCategory = [[UIMutableUserNotificationCategory alloc] init]; + quickReplyCategory.identifier = @"QUICK_REPLY"; + [quickReplyCategory setActions:@[quickReply] forContext:UIUserNotificationActionContextDefault]; + [notificationCategories addObject:quickReplyCategory]; // Registration on iOS 8 and later UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeBadge | UIUserNotificationTypeSound |UIUserNotificationTypeAlert) categories:notificationCategories]; From e8d72981bfa1ef0c79e763e9b80d946359febad9 Mon Sep 17 00:00:00 2001 From: fridtjof <2780577+fridtjof@users.noreply.github.com> Date: Fri, 18 Jan 2019 20:35:06 +0100 Subject: [PATCH 076/244] update CHANGES.rst --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index c058299ee..0c32d434f 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -6,6 +6,7 @@ Improvements: * Use modern literals and array/dictionary syntax where possible (PR #2160). * Add SwiftGen pod in order to generate Swift constants for assets (#2177). * RoomVC: `Redact` has been renamed to `Remove` to match riot/web (#2134). + * Clean up iOS version checking (#2190). Bug fix: * Use white scroll bar on dark themes (#2158). From dcc00bbdad1bdca6421e6401d5aa2e1f4f92f461 Mon Sep 17 00:00:00 2001 From: Paulo Miranda Date: Mon, 21 Jan 2019 17:29:02 +0000 Subject: [PATCH 077/244] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (520 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/pt_BR/ --- Riot/Assets/pt_BR.lproj/Vector.strings | 376 ++++++++++++++++++++++++- 1 file changed, 375 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index f8df570ca..81310fb58 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -181,4 +181,378 @@ "room_participants_action_section_devices" = "Dispositivos"; "room_participants_action_section_other" = "Outros"; "room_participants_action_invite" = "Convidar"; -"room_participants_action_leave" = "Deixar esta sala"; +"room_participants_action_leave" = "Sair desta sala"; +"room_participants_action_remove" = "Remover desta sala"; +"room_participants_action_ban" = "Bloquear desta sala"; +"room_participants_action_unban" = "Desbloquear"; +"room_participants_action_ignore" = "Esconder todas as mensagens deste usuário"; +"room_participants_action_unignore" = "Mostrar todas as mensagens deste usuário"; +"room_participants_invite_malformed_id" = "ID malformado. Deve ser utlizado um endereço de e-mail ou um Matrix ID, como \"@localpart:domain\""; +"room_participants_action_set_default_power_level" = "Redefinir para usuário normal"; +"room_participants_action_set_moderator" = "Faça moderador"; +"room_participants_action_set_admin" = "Faça administrador"; +"room_participants_action_start_new_chat" = "Iniciar um novo bate-papo"; +"room_participants_action_start_voice_call" = "Iniciar chamada de voz"; +"room_participants_action_start_video_call" = "Iniciar chamada de vídeo"; +"room_participants_action_mention" = "Menção"; +// Chat +"room_jump_to_first_unread" = "Ir para a primeira mensagem não lida"; +"room_new_message_notification" = "%d nova mensagem"; +"room_new_messages_notification" = "%d novas mensagens"; +"room_one_user_is_typing" = "%@ está digitando…"; +"room_two_users_are_typing" = "%@ & %@ estão digitando…"; +"room_many_users_are_typing" = "%@, %@ e outros estão digitando…"; +"room_message_placeholder" = "Enviar uma mensagem (não criptografada)…"; +"room_message_reply_to_placeholder" = "Enviar uma resposta (não criptografada)…"; +"room_do_not_have_permission_to_post" = "Você não tem permissão para postar nesta sala"; +"encrypted_room_message_placeholder" = "Enviar uma mensagem criptografada…"; +"encrypted_room_message_reply_to_placeholder" = "Enviar uma resposta criptografada…"; +"room_message_short_placeholder" = "Enviar uma mensagem…"; +"room_message_reply_to_short_placeholder" = "Enviar uma resposta…"; +"room_offline_notification" = "A conectividade com o servidor foi perdida."; +"room_unsent_messages_notification" = "Mensagens não enviadas. %@ ou %@ agora?"; +"room_unsent_messages_unknown_devices_notification" = "Mensagem não enviada devido a dispositivos desconhecidos presentes. %@ ou %@ agora?"; +"room_ongoing_conference_call" = "Teleconferência em andamento. Junte-se como %@ ou %@."; +"room_ongoing_conference_call_with_close" = "Teleconferência em andamento. Junte-se como %@ ou %@. %@ isto."; +"room_ongoing_conference_call_close" = "Fechar"; +"room_conference_call_no_power" = "Você precisa de permissão para gerenciar a teleconferência nesta sala"; +"room_prompt_resend" = "Reenviar tudo"; +"room_prompt_cancel" = "Cancelar todas"; +"room_resend_unsent_messages" = "Reenviar mensagens não enviadas"; +"room_delete_unsent_messages" = "Excluir mensagens não enviadas"; +"room_event_action_copy" = "Copiar"; +"room_event_action_quote" = "Citar"; +"room_event_action_redact" = "Redigir"; +"room_event_action_more" = "Mais"; +"room_event_action_share" = "Compartilhar"; +"room_event_action_permalink" = "Link permanente"; +"room_event_action_view_source" = "Ver fonte"; +"room_event_action_view_decrypted_source" = "Ver fonte descriptografado"; +"room_event_action_report" = "Denunciar conteúdo"; +"room_event_action_report_prompt_reason" = "Razão para denunciar este conteúdo"; +"room_event_action_kick_prompt_reason" = "Razão para chutar este usuário"; +"room_event_action_ban_prompt_reason" = "Razão para banir este usuário"; +"room_event_action_report_prompt_ignore_user" = "Você quer esconder todas as mensagens deste usuário?"; +"room_event_action_save" = "Salvar"; +"room_event_action_resend" = "Reenviar"; +"room_event_action_delete" = "Excluir"; +"room_event_action_cancel_send" = "Cancelar envio"; +"room_event_action_cancel_download" = "Cancelar download"; +"room_event_action_view_encryption" = "Informação criptografada"; +"room_warning_about_encryption" = "A criptografia de ponta a ponta está na versão beta e pode não ser confiável.\n\nVocê ainda não deve confiar nele para proteger os dados.\n\nOs dispositivos ainda não poderão descriptografar o histórico antes de entrarem na sala.\n\nAs mensagens criptografadas não estarão visíveis em clientes que ainda não implementam a criptografia."; +"room_event_failed_to_send" = "Falha ao enviar"; +"room_action_send_photo_or_video" = "Enviar foto ou vídeo"; +"room_action_send_sticker" = "Enviar sticker"; +"room_replacement_information" = "Esta sala foi substituída e não está mais ativa."; +"room_replacement_link" = "A conversa continua aqui."; +"room_predecessor_information" = "Esta sala é uma continuação de outra conversa."; +"room_predecessor_link" = "Clique aqui para ver as mensagens mais antigas."; +"room_resource_limit_exceeded_message_contact_1" = " Por favor "; +"room_resource_limit_exceeded_message_contact_2_link" = "entre em contato com o administrador do serviço"; +"room_resource_limit_exceeded_message_contact_3" = " para continuar usando este serviço."; +"room_resource_usage_limit_reached_message_1_default" = "Este homeserver ultrapassou um dos seus limites de recursos então "; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Esse homeserver atingiu seu limite de usuário ativo mensal então "; +"room_resource_usage_limit_reached_message_2" = "alguns usuários não poderão efetuar login."; +"room_resource_usage_limit_reached_message_contact_3" = " para ter este limite aumentado."; +// Unknown devices +"unknown_devices_alert_title" = "A sala contém dispositivos desconhecidos"; +"unknown_devices_send_anyway" = "Enviar mesmo assim"; +"unknown_devices_call_anyway" = "Ligar mesmo assim"; +"unknown_devices_answer_anyway" = "Responder mesmo assim"; +"unknown_devices_verify" = "Verificar…"; +"unknown_devices_title" = "Dispositivos desconhecidos"; +// Room Title +"room_title_new_room" = "Nova sala"; +"room_title_multiple_active_members" = "%@/%@ membros ativos"; +"room_title_one_active_member" = "%@/%@ membro ativo"; +"room_title_invite_members" = "Convidar membros"; +"room_title_members" = "%@ membros"; +"room_title_one_member" = "1 membro"; +// Room Preview +"room_preview_invitation_format" = "Você foi convidado a participar desta sala por %@"; +"unknown_devices_alert" = "Esta sala contém dispositivos desconhecidos que não foram verificados.\nIsso significa que não há garantia de que os dispositivos pertencem aos usuários que eles reivindicam.\nRecomendamos que você passe pelo processo de verificação de cada dispositivo antes de continuar, mas é possível reenviar a mensagem sem verificar se preferir."; +"room_preview_subtitle" = "Esta é uma prévia desta sala. Interações de sala foram desativadas."; +"room_preview_unlinked_email_warning" = "Este convite foi enviado para %@, que não está associado a esta conta. Você pode querer fazer login com uma conta diferente ou adicionar este e-mail a essa conta."; +"room_preview_try_join_an_unknown_room" = "Você está tentando acessar %@. Você gostaria de entrar para participar da discussão?"; +"room_preview_try_join_an_unknown_room_default" = "uma sala"; +// Settings +"settings_title" = "Configurações"; +"account_logout_all" = "Sair de todas as contas"; +"settings_config_no_build_info" = "Nenhuma informação da build"; +"settings_mark_all_as_read" = "Marcar todas as mensagens como lidas"; +"settings_report_bug" = "Relatar erro"; +"settings_config_home_server" = "Home server é %@"; +"settings_config_identity_server" = "Servidor de Identidades é %@"; +"settings_config_user_id" = "Logado como %@"; +"settings_user_settings" = "CONFIGURAÇÕES DE USUÁRIO"; +"settings_notifications_settings" = "CONFIGURAÇÕES DE NOTIFICAÇÕES"; +"settings_calls_settings" = "CHAMADAS"; +"settings_user_interface" = "INTERFACE DO USUÁRIO"; +"settings_ignored_users" = "USUÁRIOS IGNORADOS"; +"settings_contacts" = "CONTATOS LOCAIS"; +"settings_advanced" = "AVANÇADO"; +"settings_other" = "OUTROS"; +"settings_labs" = "LABORATÓRIO"; +"settings_flair" = "Mostrar insígnias onde permitido"; +"settings_devices" = "DISPOSITIVOS"; +"settings_cryptography" = "CRIPTOGRAFIA"; +"settings_deactivate_account" = "DESATIVAR A CONTA"; +"settings_sign_out" = "Sair"; +"settings_sign_out_confirmation" = "Você tem certeza?"; +"settings_sign_out_e2e_warn" = "Você perderá suas chaves de criptografia de ponta a ponta. Isso significa que você não poderá mais ler mensagens antigas em salas criptografadas neste dispositivo."; +"settings_profile_picture" = "Imagem de Perfil"; +// Room Details +"room_details_title" = "Detalhes da sala"; +"settings_first_name" = "Primeiro nome"; +"settings_surname" = "Sobrenome"; +"settings_remove_prompt_title" = "Confirmação"; +"settings_remove_email_prompt_msg" = "Tem certeza de que deseja remover o endereço de e-mail %@?"; +"settings_remove_phone_prompt_msg" = "Tem certeza de que deseja remover o número de telefone %@?"; +"settings_email_address" = "E-mail"; +"settings_email_address_placeholder" = "Insira o seu endereço de e-mail"; +"settings_add_email_address" = "Adicionar endereço de e-mail"; +"settings_phone_number" = "Telefone"; +"settings_add_phone_number" = "Adicionar número de telefone"; +"settings_night_mode" = "Modo noturno"; +"settings_fail_to_update_profile" = "Falha ao atualizar perfil"; +"settings_enable_push_notif" = "Notificações neste dispositivo"; +"settings_show_decrypted_content" = "Mostrar conteúdo descriptografado"; +"settings_global_settings_info" = "Configurações globais de notificação estão disponíveis no seu cliente web %@"; +"settings_on_denied_notification" = "As notificações são negadas para %@, permita-as nas configurações do seu dispositivo"; +"settings_enable_callkit" = "Chamada Integrada"; +"settings_callkit_info" = "Receba as chamadas na sua tela de bloqueio. Veja suas chamadas da Riot no histórico de chamadas do sistema. Se o iCloud estiver ativado, esse histórico de chamadas será compartilhado com a Apple."; +"settings_ui_language" = "Idioma"; +"settings_ui_theme" = "Tema"; +"settings_ui_theme_auto" = "Automático"; +"settings_ui_theme_light" = "Claro"; +"settings_ui_theme_dark" = "Escuro"; +"settings_ui_theme_black" = "Preto"; +"settings_ui_theme_picker_title" = "Selecione o tema"; +"settings_ui_theme_picker_message" = "\"Auto\" usa as configurações \"Inverter cores\" do seu dispositivo"; +"settings_unignore_user" = "Mostrar todas as mensagens de %@?"; +"settings_contacts_discover_matrix_users" = "Use e-mails e números de telefone para descobrir usuários"; +"settings_contacts_phonebook_country" = "País da lista telefônica"; +"settings_labs_e2e_encryption" = "Criptografia de ponta a ponta"; +"settings_labs_e2e_encryption_prompt_message" = "Para concluir a configuração da criptografia, você deve efetuar login novamente."; +"settings_labs_room_members_lazy_loading" = "Usuários de carrregamento Lazy de salas"; +"settings_labs_room_members_lazy_loading_error_message" = "Seu homeserver não suporta o carregamento Lazy de membros da sala ainda. Tente depois."; +"settings_labs_create_conference_with_jitsi" = "Crie chamadas de conferência com jitsi"; +"settings_version" = "Versão %@"; +"settings_olm_version" = "Versão do Olm %@"; +"settings_copyright" = "Copyright"; +"settings_copyright_url" = "https://riot.im/copyright"; +"settings_term_conditions" = "Termos e Condições"; +"settings_term_conditions_url" = "https://riot.im/tac_apple"; +"settings_privacy_policy" = "Política de Privacidade"; +"settings_privacy_policy_url" = "https://riot.im/privacy"; +"settings_third_party_notices" = "Avisos de terceiros"; +"settings_send_crash_report" = "Enviar dados de falha e uso anônimos"; +"settings_enable_rageshake" = "Agite rapidamente para relatar um erro"; +"settings_clear_cache" = "Limpar cache"; +"settings_change_password" = "Mudar senha"; +"settings_old_password" = "senha antiga"; +"settings_new_password" = "senha nova"; +"settings_confirm_password" = "confirme a senha"; +"settings_fail_to_update_password" = "Falha ao atualizar senha"; +"settings_password_updated" = "Sua senha foi atualizada"; +"settings_crypto_device_name" = "Nome do dispositivo "; +"settings_crypto_device_id" = "\nID do dispositivo: "; +"settings_crypto_device_key" = "\nChave do dispositivo: "; +"settings_crypto_export" = "Chaves de exportação"; +"settings_crypto_blacklist_unverified_devices" = "Criptografar apenas para dispositivos verificados"; +"settings_deactivate_my_account" = "Desativar minha conta"; +"room_details_people" = "Membros"; +"room_details_files" = "Arquivos"; +"room_details_settings" = "Configurações"; +"room_details_photo" = "Imagem da Sala"; +"room_details_room_name" = "Nome da sala"; +"room_details_topic" = "Tópico"; +"room_details_favourite_tag" = "Favorito"; +"room_details_low_priority_tag" = "Baixa prioridade"; +"room_details_mute_notifs" = "Silenciar notificações"; +"room_details_direct_chat" = "Chat direto"; +"room_details_access_section" = "Quem pode acessar esta sala?"; +"room_details_access_section_invited_only" = "Apenas pessoas que foram convidadas"; +"room_details_access_section_anyone_apart_from_guest" = "Quem conhece o link da sala, além dos convidados"; +"room_details_access_section_anyone" = "Qualquer pessoa que conheça o link da sala, incluindo convidados"; +"room_details_access_section_no_address_warning" = "Para ligar a uma sala, isto deve ter um endereço"; +"room_details_access_section_directory_toggle" = "Listar esta sala no diretório de salas"; +"room_details_history_section" = "Quem pode ler o histórico?"; +"room_details_history_section_anyone" = "Qualquer um"; +"room_details_history_section_members_only" = "Apenas membros (desde o momento em que selecionamos esta opção)"; +"room_details_history_section_members_only_since_invited" = "Apenas membros (desde que foram convidados)"; +"room_details_history_section_members_only_since_joined" = "Apenas membros (desde que aderiram)"; +"room_details_history_section_prompt_title" = "Aviso de privacidade"; +"room_details_history_section_prompt_msg" = "As alterações em quem pode ler o histórico só se aplicam a mensagens futuras nesta sala. A visibilidade do histórico existente não será alterada."; +"room_details_addresses_section" = "Endereços"; +"room_details_no_local_addresses" = "Este quarto não tem endereços locais"; +"room_details_new_address" = "adicionar novo endereço"; +"room_details_new_address_placeholder" = "Adicionar novo endereço (por exemplo, #foo%@)"; +"room_details_addresses_invalid_address_prompt_title" = "Formato de alias inválido"; +"room_details_addresses_invalid_address_prompt_msg" = "%@ não é um formato válido para um alias"; +"room_details_addresses_disable_main_address_prompt_title" = "Aviso de endereço principal"; +"room_details_addresses_disable_main_address_prompt_msg" = "Você não terá nenhum endereço principal especificado. O endereço principal padrão para esta sala será escolhido aleatoriamente"; +"room_details_flair_section" = "Mostrar insígnias para as comunidades"; +"room_details_new_flair_placeholder" = "Adicionar nova ID de comunidade (por exemplo, +foo%@)"; +"room_details_flair_invalid_id_prompt_title" = "Formato Inválido"; +"room_details_flair_invalid_id_prompt_msg" = "%@ não é um identificador válido para uma comunidade"; +"room_details_banned_users_section" = "Usuários banidos"; +"room_details_advanced_section" = "Avançado"; +"room_details_advanced_room_id" = "ID da sala:"; +"room_details_advanced_enable_e2e_encryption" = "Ativar criptografia (aviso: não pode ser desativado novamente!)"; +"room_details_advanced_e2e_encryption_enabled" = "A criptografia está ativada nesta sala"; +"room_details_advanced_e2e_encryption_disabled" = "A criptografia não está habilitada nesta sala."; +"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Criptografar apenas para dispositivos verificados"; +"room_details_fail_to_update_avatar" = "Falha ao atualizar a imagem da sala"; +"room_details_fail_to_update_room_name" = "Falha ao atualizar o nome da sala"; +"room_details_fail_to_update_topic" = "Falha ao atualizar o tópico"; +"room_details_fail_to_update_room_guest_access" = "Falha ao atualizar o acesso do convidado da sala"; +"room_details_fail_to_update_room_join_rule" = "Falha ao atualizar a regra de participação"; +"room_details_fail_to_update_room_directory_visibility" = "Falha ao atualizar a visibilidade da sala no diretório"; +"room_details_fail_to_update_history_visibility" = "Falha ao atualizar a visibilidade do histórico"; +"room_details_advanced_e2e_encryption_prompt_message" = "A criptografia de ponta a ponta é experimental e pode não ser confiável.\n\nVocê ainda não deve confiar nele para proteger os dados.\n\nOs dispositivos ainda não poderão descriptografar o histórico antes de ingressarem na sala.\n\nQuando a criptografia estiver ativada para uma sala, ela não poderá ser desativada novamente (por enquanto).\n\nAs mensagens criptografadas não estarão visíveis em clientes que ainda não implementam a criptografia."; +"room_details_fail_to_add_room_aliases" = "Falha ao adicionar os novos endereços da sala"; +"room_details_fail_to_remove_room_aliases" = "Falha ao remover os endereços da sala"; +"room_details_fail_to_update_room_canonical_alias" = "Falha ao atualizar o endereço principal"; +"room_details_fail_to_update_room_communities" = "Falha ao atualizar as comunidades relacionadas"; +"room_details_fail_to_update_room_direct" = "Falha ao atualizar o sinalizador direto desta sala"; +"room_details_fail_to_enable_encryption" = "Falha ao ativar a criptografia nesta sala"; +"room_details_save_changes_prompt" = "Você quer salvar as alterações?"; +"room_details_set_main_address" = "Definir como endereço principal"; +"room_details_unset_main_address" = "Desativar como endereço principal"; +"room_details_copy_room_id" = "Copiar o ID da sala"; +"room_details_copy_room_address" = "Copiar o endereço da sala"; +"room_details_copy_room_url" = "Copiar o URL da sala"; +// Group Details +"group_details_title" = "Detalhes da Comunidade"; +"group_details_home" = "Início"; +"group_details_people" = "Pessoas"; +"group_details_rooms" = "Salas"; +// Group Home +"group_home_one_member_format" = "1 membro"; +"group_home_multi_members_format" = "%tu membros"; +"group_home_one_room_format" = "1 sala"; +"group_home_multi_rooms_format" = "%tu salas"; +"group_invitation_format" = "%@ convidou você para participar desta comunidade"; +// Group participants +"group_participants_add_participant" = "Adicionar participante"; +"group_participants_leave_prompt_title" = "Sair do grupo"; +"group_participants_leave_prompt_msg" = "Tem certeza de que deseja sair do grupo?"; +"group_participants_remove_prompt_title" = "Confirmação"; +"group_participants_remove_prompt_msg" = "Tem certeza de que deseja remover %@ deste grupo?"; +"group_participants_invite_prompt_title" = "Confirmação"; +"group_participants_invite_prompt_msg" = "Tem certeza de que deseja convidar %@ para este grupo?"; +"group_participants_filter_members" = "Filtrar membros da comunidade"; +"group_participants_invite_another_user" = "Pesquisar / convidar por ID do usuário ou nome"; +"group_participants_invite_malformed_id_title" = "Erro ao convidar"; +"group_participants_invite_malformed_id" = "ID malformado. Deve ser um ID da Matrix como \"@localpart:domain\""; +"group_participants_invited_section" = "CONVIDADO"; +// Group rooms +"group_rooms_filter_rooms" = "Filtrar salas da comunidade"; +// Read Receipts +"read_receipts_list" = "Lista de confirmações de leitura"; +"receipt_status_read" = "Leitura: "; +// Media picker +"media_picker_library" = "Biblioteca"; +"media_picker_select" = "Selecionar"; +// Directory +"directory_title" = "Diretório"; +"directory_server_picker_title" = "Selecionar um diretório"; +"settings_display_name" = "Nome de Visualização"; +"settings_pin_rooms_with_missed_notif" = "Fixar sala com notificações perdidas"; +"settings_pin_rooms_with_unread" = "Fixar sala com mensagens não lidas"; +"directory_server_all_rooms" = "Todas as salas no servidor %@"; +"directory_server_all_native_rooms" = "Todas as salas nativas da Matrix"; +"directory_server_type_homeserver" = "Digite um homeserver para listar salas públicas dele"; +"directory_server_placeholder" = "matrix.org"; +// Events formatter +"event_formatter_member_updates" = "%tu mudanças na filiação"; +"event_formatter_widget_added" = "%@ widget adicionado por %@"; +"event_formatter_widget_removed" = "%@ widget removido por %@"; +"event_formatter_jitsi_widget_added" = "Conferência VoIP adicionada por %@"; +"event_formatter_jitsi_widget_removed" = "Conferência de VoIP removida por %@"; +"event_formatter_rerequest_keys_part1_link" = "Solicitar novamente chaves de criptografia"; +"event_formatter_rerequest_keys_part2" = " dos seus outros dispositivos."; +// Others +"or" = "ou"; +"you" = "Você"; +"today" = "Hoje"; +"yesterday" = "Ontem"; +"network_offline_prompt" = "A conexão com a Internet parece estar off-line."; +"homeserver_connection_lost" = "Não foi possível conectar-se ao homeserver."; +"public_room_section_title" = "Salas Públicas (em %@):"; +"bug_report_prompt" = "O aplicativo encerrou abruptamente na última vez. Gostaria de enviar um relatório de falhas?"; +"rage_shake_prompt" = "Você parece estar agitando o telefone em frustração. Gostaria de enviar um relatório de erro?"; +"do_not_ask_again" = "Não pergunte novamente"; +"camera_access_not_granted" = "%@ não tem permissão para usar a câmera, altere as configurações de privacidade"; +"large_badge_value_k_format" = "%.1fK"; +// Call +"call_incoming_voice_prompt" = "Recebendo chamada de voz de %@"; +"call_incoming_video_prompt" = "Recebendo chamada de vídeo de %@"; +"call_incoming_voice" = "Recebendo chamada..."; +"call_incoming_video" = "Recebendo chamada de vídeo..."; +"call_already_displayed" = "Já existe uma chamada em andamento."; +"call_jitsi_error" = "Não foi possível participar da conferência."; +// No VoIP support +"no_voip_title" = "Recebendo chamada"; +"no_voip" = "%@ está chamando você, mas %@ ainda não suporta chamadas.\nVocê pode ignorar essa notificação e atender a chamada de outro dispositivo ou pode rejeitá-la."; +// Crash report +"google_analytics_use_prompt" = "Você gostaria de ajudar a melhorar o %@ informando automaticamente relatórios de falhas e dados de uso anônimos?"; +// Crypto +"e2e_enabling_on_app_update" = "O Riot agora suporta criptografia de ponta a ponta, mas você precisa fazer login novamente para ativá-lo.\n\nVocê pode fazer isso agora ou mais tarde a partir das configurações do aplicativo."; +"e2e_need_log_in_again" = "Você precisa fazer login novamente para gerar chaves de criptografia de ponta a ponta para este dispositivo e enviar a chave pública para o seu homeserver.\nIsso é apenas dessa vez; Desculpe pela inconveniência."; +// Bug report +"bug_report_title" = "Relatório de erro"; +"bug_report_description" = "Por favor, descreva o erro. O que você fez? O que você esperava que acontecesse? O que realmente aconteceu?"; +"bug_crash_report_title" = "Relatório de erros"; +"bug_crash_report_description" = "Por favor, descreva o que você fez antes do erro:"; +"bug_report_logs_description" = "Para diagnosticar problemas, os logs deste cliente serão enviados com este relatório de erro. Se preferir enviar apenas o texto acima, por favor desmarque:"; +"bug_report_send_logs" = "Enviar logs"; +"bug_report_send_screenshot" = "Enviar screenshot"; +"bug_report_progress_zipping" = "Coletando logs"; +"bug_report_progress_uploading" = "Enviando relatório"; +"bug_report_send" = "Enviar"; +// Widget +"widget_no_power_to_manage" = "Você precisa de permissão para gerenciar widgets nesta sala"; +"widget_creation_failure" = "A criação do widget falhou"; +"widget_sticker_picker_no_stickerpacks_alert" = "Atualmente, você não tem nenhum stickerpacks ativado."; +"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Adicione alguns agora?"; +// Widget Integration Manager +"widget_integration_need_to_be_able_to_invite" = "Você precisa convidar os usuários para fazer isso."; +"widget_integration_unable_to_create" = "Não é possível criar widget."; +"widget_integration_failed_to_send_request" = "Falha ao enviar solicitação."; +"widget_integration_room_not_recognised" = "Esta sala não é reconhecida."; +"widget_integration_positive_power_level" = "O nível de permissão deve ser inteiro positivo."; +"widget_integration_must_be_in_room" = "Você não está nesta sala."; +"widget_integration_no_permission_in_room" = "Você não tem permissão para fazer isso nesta sala."; +"widget_integration_missing_room_id" = "room_id ausente em pedido."; +"widget_integration_missing_user_id" = "user_id ausente em pedido."; +"widget_integration_room_not_visible" = "Sala %@ não é visível."; +// Share extension +"share_extension_auth_prompt" = "Entre no aplicativo principal para compartilhar conteúdo"; +"share_extension_failed_to_encrypt" = "Falha ao enviar. Verifique no aplicativo principal as configurações de criptografia para esta sala"; +// Room key request dialog +"e2e_room_key_request_title" = "Pedido de chave de encriptação"; +"e2e_room_key_request_message_new_device" = "Você adicionou um novo dispositivo '%@', que está solicitando chaves de criptografia."; +"e2e_room_key_request_message" = "Seu dispositivo não verificado '%@' está solicitando chaves de criptografia."; +"e2e_room_key_request_start_verification" = "Iniciar verificação..."; +"e2e_room_key_request_share_without_verifying" = "Compartilhar sem verificar"; +"e2e_room_key_request_ignore_request" = "Ignorar requisição"; +// GDPR +"gdpr_consent_not_given_alert_message" = "Para continuar usando o %@ homeserver, você deve revisar e concordar com os termos e condições."; +"gdpr_consent_not_given_alert_review_now_action" = "Revisar agora"; +"deactivate_account_title" = "Desativar Conta"; +"deactivate_account_informations_part1" = "Isso tornará sua conta permanentemente inutilizável. Você não poderá efetuar login e ninguém poderá registrar novamente o mesmo ID de usuário. Isso fará com que sua conta deixe todas as salas nas quais está participando e removerá os detalhes da sua conta do seu servidor de identidade. "; +"deactivate_account_informations_part2_emphasize" = "Essa ação é irreversível."; +"deactivate_account_informations_part3" = "\n\nDesativando sua conta "; +"deactivate_account_informations_part4_emphasize" = "não nos faz esquecer, por padrão, as mensagens que você enviou. "; +"deactivate_account_informations_part5" = "Se você gostaria que nós esquecêssemos suas mensagens, por favor marque a caixa abaixo\n\nA visibilidade das mensagens no Matrix é semelhante ao e-mail. O fato de esquecermos suas mensagens significa que as mensagens que você enviou não serão compartilhadas com usuários novos ou não registrados, mas os usuários registrados que já têm acesso a essas mensagens ainda terão acesso à sua cópia."; +"deactivate_account_forget_messages_information_part1" = "Por favor, esqueça todas as mensagens que enviei quando minha conta está desativada ("; +"deactivate_account_forget_messages_information_part2_emphasize" = "Aviso"; +"deactivate_account_forget_messages_information_part3" = ": isso fará com que futuros usuários vejam uma visão incompleta das conversas)"; +"deactivate_account_validate_action" = "Desativar conta"; +"deactivate_account_password_alert_title" = "Desativar Conta"; +"deactivate_account_password_alert_message" = "Para continuar, por favor, digite sua senha"; +// Re-request confirmation dialog +"rerequest_keys_alert_title" = "Requisição enviada"; +"rerequest_keys_alert_message" = "Por favor, inicie o Riot em outro dispositivo que possa descriptografar a mensagem para que ela possa enviar as chaves para este dispositivo."; From 7f4fc4917184f59214d8c0c9d9dd7faad0253ab7 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 21 Jan 2019 18:54:51 +0100 Subject: [PATCH 078/244] Add SwiftGen custom template for strings. Update SwiftGen config file. --- .../Strings/flat-swift4-vector.stencil | 84 +++++++++++++++++++ Tools/SwiftGen/swiftgen-config.yml | 4 +- 2 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 Tools/SwiftGen/Templates/Strings/flat-swift4-vector.stencil diff --git a/Tools/SwiftGen/Templates/Strings/flat-swift4-vector.stencil b/Tools/SwiftGen/Templates/Strings/flat-swift4-vector.stencil new file mode 100644 index 000000000..a7f61cdee --- /dev/null +++ b/Tools/SwiftGen/Templates/Strings/flat-swift4-vector.stencil @@ -0,0 +1,84 @@ +// swiftlint:disable all +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +{% if tables.count > 0 %} +{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %} +import Foundation + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Strings + +{% macro parametersBlock types %}{% filter removeNewlines:"leading" %} + {% for type in types %} + _ p{{forloop.counter}}: {{type}}{{ ", " if not forloop.last }} + {% endfor %} +{% endfilter %}{% endmacro %} +{% macro argumentsBlock types %}{% filter removeNewlines:"leading" %} + {% for type in types %} + {% if type == "UnsafeRawPointer" %} + Int(bitPattern: p{{forloop.counter}}) + {% else %} + p{{forloop.counter}} + {% endif %} + {{ ", " if not forloop.last }} + {% endfor %} +{% endfilter %}{% endmacro %} +{% macro recursiveBlock table item %} + {% for string in item.strings %} + {% if not param.noComments %} + /// {{string.translation}} + {% endif %} + {% if string.types %} + {{accessModifier}} static func {{string.key|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}({% call parametersBlock string.types %}) -> String { + return {{enumName}}.tr("{{table}}", "{{string.key}}", {% call argumentsBlock string.types %}) + } + {% else %} + {{accessModifier}} static var {{string.key|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}: String { + return {{enumName}}.tr("{{table}}", "{{string.key}}") + } + {% endif %} + {% endfor %} + {% for child in item.children %} + {% call recursiveBlock table child %} + {% endfor %} +{% endmacro %} +// swiftlint:disable function_parameter_count identifier_name line_length type_body_length +{% set enumName %}{{param.enumName|default:"L10n"}}{% endset %} +{{accessModifier}} enum {{enumName}} { + {% if tables.count > 1 %} + {% for table in tables %} + {{accessModifier}} enum {{table.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} { + {% filter indent:2 %}{% call recursiveBlock table.name table.levels %}{% endfilter %} + } + {% endfor %} + {% else %} + {% call recursiveBlock tables.first.name tables.first.levels %} + {% endif %} +} +// swiftlint:enable function_parameter_count identifier_name line_length type_body_length + +// MARK: - Implementation Details + +extension {{enumName}} { + private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "") + let locale: Locale + + if let localeIdentifier = Bundle.mxk_language() { + locale = Locale(identifier: localeIdentifier) + } else if let fallbackLocaleIdentifier = Bundle.mxk_fallbackLanguage() { + locale = Locale(identifier: fallbackLocaleIdentifier) + } else { + locale = Locale.current + } + + return String(format: format, locale: locale, arguments: args) + } +} + +private final class BundleToken {} +{% else %} +// No string found +{% endif %} \ No newline at end of file diff --git a/Tools/SwiftGen/swiftgen-config.yml b/Tools/SwiftGen/swiftgen-config.yml index 716c45725..7da2a05f6 100755 --- a/Tools/SwiftGen/swiftgen-config.yml +++ b/Tools/SwiftGen/swiftgen-config.yml @@ -2,14 +2,14 @@ input_dir: ../../Riot/ output_dir: ../../Riot/Generated/ ib: - inputs: - - Assets/Base.lproj/LaunchScreen.storyboard + - Modules/KeyBackup/ outputs: - templateName: scenes-swift4 output: Storyboards.swift strings: inputs: Assets/en.lproj/Vector.strings outputs: - - templateName: flat-swift4 + - templatePath: Templates/Strings/flat-swift4-vector.stencil output: Strings.swift params: enumName: VectorL10n From 76783bec2b43576152e4e2f3a8850dd6604faf97 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 21 Jan 2019 23:31:33 +0100 Subject: [PATCH 079/244] Add key backup setup strings --- Riot/Assets/en.lproj/Vector.strings | 36 + Riot/Generated/Strings.swift | 1941 ++++++++++++++++++++------- 2 files changed, 1515 insertions(+), 462 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index f6ab41dfa..5aa2686e4 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -642,3 +642,39 @@ // Re-request confirmation dialog "rerequest_keys_alert_title" = "Request Sent"; "rerequest_keys_alert_message" = "Please launch Riot on another device that can decrypt the message so it can send the keys to this device."; + +// MARK: Key backup setup + +"key_backup_setup_title" = "Message Recovery"; +"key_backup_setup_skip_action" = "Skip"; + +"key_backup_setup_skip_alert_title" = "Are you sure?"; +"key_backup_setup_skip_alert_message" = "You may lose secure messages if you log out of lose your device."; +"key_backup_setup_skip_alert_skip_action" = "Skip"; + +// Intro + +"key_backup_setup_intro_title" = "Never lose encrypted messages"; +"key_backup_setup_intro_info" = "Set up Secure Message Recovery in case you lose or log out of this device."; +"key_backup_setup_intro_setup_action" = "Set up"; + + +// Passphrase + +"key_backup_setup_passphrase_info" = "Secure your encrypted message history with a Recovery Passphrase.\n\nYou’ll need it if you log out, or lose access to this device."; +"key_backup_setup_passphrase_passphrase_title" = "Enter"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Enter passphrase"; +"key_backup_setup_passphrase_passphrase_valid" = "Great!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Try adding a word"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Confirm"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Confirm passphrase"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Great!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passphrase doesn’t match"; +"key_backup_setup_passphrase_set_passphrase_action" = "Set recovery passphrase"; + +// Recovery key + +"key_backup_setup_recovery_key_info" = "Make a copy of this Recovery Key and keep it safe.\n\nAs a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase."; +"key_backup_setup_recovery_key_recovery_key_title" = "Recovery Key"; +"key_backup_setup_recovery_key_make_copy_action" = "Make a Copy"; +"key_backup_setup_recovery_key_made_copy_action" = "I've made a copy"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index ccdfdc3b3..dd71113a3 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -11,227 +11,425 @@ import Foundation // swiftlint:disable function_parameter_count identifier_name line_length type_body_length internal enum VectorL10n { /// Accept - internal static let accept = VectorL10n.tr("Vector", "accept") + internal static var accept: String { + return VectorL10n.tr("Vector", "accept") + } /// Logout all accounts - internal static let accountLogoutAll = VectorL10n.tr("Vector", "account_logout_all") + internal static var accountLogoutAll: String { + return VectorL10n.tr("Vector", "account_logout_all") + } /// Active Call - internal static let activeCall = VectorL10n.tr("Vector", "active_call") + internal static var activeCall: String { + return VectorL10n.tr("Vector", "active_call") + } /// Active Call (%@) internal static func activeCallDetails(_ p1: String) -> String { return VectorL10n.tr("Vector", "active_call_details", p1) } /// Please review and accept the policies of this homeserver: - internal static let authAcceptPolicies = VectorL10n.tr("Vector", "auth_accept_policies") + internal static var authAcceptPolicies: String { + return VectorL10n.tr("Vector", "auth_accept_policies") + } /// Add an email address and a phone number to your account to let users discover you. Email address will also let you reset your password. - internal static let authAddEmailAndPhoneMessage = VectorL10n.tr("Vector", "auth_add_email_and_phone_message") + internal static var authAddEmailAndPhoneMessage: String { + return VectorL10n.tr("Vector", "auth_add_email_and_phone_message") + } /// Registration with email and phone number at once is not supported yet until the api exists. Only the phone number will be taken into account. You may add your email to your profile in settings. - internal static let authAddEmailAndPhoneWarning = VectorL10n.tr("Vector", "auth_add_email_and_phone_warning") + internal static var authAddEmailAndPhoneWarning: String { + return VectorL10n.tr("Vector", "auth_add_email_and_phone_warning") + } /// Add an email address to your account to let users discover you, and let you reset password. - internal static let authAddEmailMessage = VectorL10n.tr("Vector", "auth_add_email_message") + internal static var authAddEmailMessage: String { + return VectorL10n.tr("Vector", "auth_add_email_message") + } /// Add an email address and/or a phone number to your account to let users discover you. Email address will also let you reset your password. - internal static let authAddEmailPhoneMessage = VectorL10n.tr("Vector", "auth_add_email_phone_message") + internal static var authAddEmailPhoneMessage: String { + return VectorL10n.tr("Vector", "auth_add_email_phone_message") + } /// Add a phone number to your account to let users discover you. - internal static let authAddPhoneMessage = VectorL10n.tr("Vector", "auth_add_phone_message") + internal static var authAddPhoneMessage: String { + return VectorL10n.tr("Vector", "auth_add_phone_message") + } /// This email address is already in use - internal static let authEmailInUse = VectorL10n.tr("Vector", "auth_email_in_use") + internal static var authEmailInUse: String { + return VectorL10n.tr("Vector", "auth_email_in_use") + } /// Failed to send email: This email address was not found - internal static let authEmailNotFound = VectorL10n.tr("Vector", "auth_email_not_found") + internal static var authEmailNotFound: String { + return VectorL10n.tr("Vector", "auth_email_not_found") + } /// Email address - internal static let authEmailPlaceholder = VectorL10n.tr("Vector", "auth_email_placeholder") + internal static var authEmailPlaceholder: String { + return VectorL10n.tr("Vector", "auth_email_placeholder") + } /// Please check your email to continue registration - internal static let authEmailValidationMessage = VectorL10n.tr("Vector", "auth_email_validation_message") + internal static var authEmailValidationMessage: String { + return VectorL10n.tr("Vector", "auth_email_validation_message") + } /// Forgot password? - internal static let authForgotPassword = VectorL10n.tr("Vector", "auth_forgot_password") + internal static var authForgotPassword: String { + return VectorL10n.tr("Vector", "auth_forgot_password") + } /// URL (e.g. https://matrix.org) - internal static let authHomeServerPlaceholder = VectorL10n.tr("Vector", "auth_home_server_placeholder") + internal static var authHomeServerPlaceholder: String { + return VectorL10n.tr("Vector", "auth_home_server_placeholder") + } /// URL (e.g. https://matrix.org) - internal static let authIdentityServerPlaceholder = VectorL10n.tr("Vector", "auth_identity_server_placeholder") + internal static var authIdentityServerPlaceholder: String { + return VectorL10n.tr("Vector", "auth_identity_server_placeholder") + } /// This doesn't look like a valid email address - internal static let authInvalidEmail = VectorL10n.tr("Vector", "auth_invalid_email") + internal static var authInvalidEmail: String { + return VectorL10n.tr("Vector", "auth_invalid_email") + } /// Incorrect username and/or password - internal static let authInvalidLoginParam = VectorL10n.tr("Vector", "auth_invalid_login_param") + internal static var authInvalidLoginParam: String { + return VectorL10n.tr("Vector", "auth_invalid_login_param") + } /// Password too short (min 6) - internal static let authInvalidPassword = VectorL10n.tr("Vector", "auth_invalid_password") + internal static var authInvalidPassword: String { + return VectorL10n.tr("Vector", "auth_invalid_password") + } /// This doesn't look like a valid phone number - internal static let authInvalidPhone = VectorL10n.tr("Vector", "auth_invalid_phone") + internal static var authInvalidPhone: String { + return VectorL10n.tr("Vector", "auth_invalid_phone") + } /// User names may only contain letters, numbers, dots, hyphens and underscores - internal static let authInvalidUserName = VectorL10n.tr("Vector", "auth_invalid_user_name") + internal static var authInvalidUserName: String { + return VectorL10n.tr("Vector", "auth_invalid_user_name") + } /// Log in - internal static let authLogin = VectorL10n.tr("Vector", "auth_login") + internal static var authLogin: String { + return VectorL10n.tr("Vector", "auth_login") + } /// Missing email address - internal static let authMissingEmail = VectorL10n.tr("Vector", "auth_missing_email") + internal static var authMissingEmail: String { + return VectorL10n.tr("Vector", "auth_missing_email") + } /// Missing email address or phone number - internal static let authMissingEmailOrPhone = VectorL10n.tr("Vector", "auth_missing_email_or_phone") + internal static var authMissingEmailOrPhone: String { + return VectorL10n.tr("Vector", "auth_missing_email_or_phone") + } /// Missing password - internal static let authMissingPassword = VectorL10n.tr("Vector", "auth_missing_password") + internal static var authMissingPassword: String { + return VectorL10n.tr("Vector", "auth_missing_password") + } /// Missing phone number - internal static let authMissingPhone = VectorL10n.tr("Vector", "auth_missing_phone") + internal static var authMissingPhone: String { + return VectorL10n.tr("Vector", "auth_missing_phone") + } /// Unable to verify phone number. - internal static let authMsisdnValidationError = VectorL10n.tr("Vector", "auth_msisdn_validation_error") + internal static var authMsisdnValidationError: String { + return VectorL10n.tr("Vector", "auth_msisdn_validation_error") + } /// We've sent an SMS with an activation code. Please enter this code below. - internal static let authMsisdnValidationMessage = VectorL10n.tr("Vector", "auth_msisdn_validation_message") + internal static var authMsisdnValidationMessage: String { + return VectorL10n.tr("Vector", "auth_msisdn_validation_message") + } /// Verification Pending - internal static let authMsisdnValidationTitle = VectorL10n.tr("Vector", "auth_msisdn_validation_title") + internal static var authMsisdnValidationTitle: String { + return VectorL10n.tr("Vector", "auth_msisdn_validation_title") + } /// New password - internal static let authNewPasswordPlaceholder = VectorL10n.tr("Vector", "auth_new_password_placeholder") + internal static var authNewPasswordPlaceholder: String { + return VectorL10n.tr("Vector", "auth_new_password_placeholder") + } /// Email address (optional) - internal static let authOptionalEmailPlaceholder = VectorL10n.tr("Vector", "auth_optional_email_placeholder") + internal static var authOptionalEmailPlaceholder: String { + return VectorL10n.tr("Vector", "auth_optional_email_placeholder") + } /// Phone number (optional) - internal static let authOptionalPhonePlaceholder = VectorL10n.tr("Vector", "auth_optional_phone_placeholder") + internal static var authOptionalPhonePlaceholder: String { + return VectorL10n.tr("Vector", "auth_optional_phone_placeholder") + } /// Passwords don't match - internal static let authPasswordDontMatch = VectorL10n.tr("Vector", "auth_password_dont_match") + internal static var authPasswordDontMatch: String { + return VectorL10n.tr("Vector", "auth_password_dont_match") + } /// Password - internal static let authPasswordPlaceholder = VectorL10n.tr("Vector", "auth_password_placeholder") + internal static var authPasswordPlaceholder: String { + return VectorL10n.tr("Vector", "auth_password_placeholder") + } /// This phone number is already in use - internal static let authPhoneInUse = VectorL10n.tr("Vector", "auth_phone_in_use") + internal static var authPhoneInUse: String { + return VectorL10n.tr("Vector", "auth_phone_in_use") + } /// Phone number - internal static let authPhonePlaceholder = VectorL10n.tr("Vector", "auth_phone_placeholder") + internal static var authPhonePlaceholder: String { + return VectorL10n.tr("Vector", "auth_phone_placeholder") + } /// This Home Server would like to make sure you are not a robot - internal static let authRecaptchaMessage = VectorL10n.tr("Vector", "auth_recaptcha_message") + internal static var authRecaptchaMessage: String { + return VectorL10n.tr("Vector", "auth_recaptcha_message") + } /// Register - internal static let authRegister = VectorL10n.tr("Vector", "auth_register") + internal static var authRegister: String { + return VectorL10n.tr("Vector", "auth_register") + } /// Confirm your new password - internal static let authRepeatNewPasswordPlaceholder = VectorL10n.tr("Vector", "auth_repeat_new_password_placeholder") + internal static var authRepeatNewPasswordPlaceholder: String { + return VectorL10n.tr("Vector", "auth_repeat_new_password_placeholder") + } /// Repeat password - internal static let authRepeatPasswordPlaceholder = VectorL10n.tr("Vector", "auth_repeat_password_placeholder") + internal static var authRepeatPasswordPlaceholder: String { + return VectorL10n.tr("Vector", "auth_repeat_password_placeholder") + } /// An email has been sent to %@. Once you've followed the link it contains, click below. internal static func authResetPasswordEmailValidationMessage(_ p1: String) -> String { return VectorL10n.tr("Vector", "auth_reset_password_email_validation_message", p1) } /// Your email address does not appear to be associated with a Matrix ID on this Homeserver. - internal static let authResetPasswordErrorNotFound = VectorL10n.tr("Vector", "auth_reset_password_error_not_found") + internal static var authResetPasswordErrorNotFound: String { + return VectorL10n.tr("Vector", "auth_reset_password_error_not_found") + } /// Failed to verify email address: make sure you clicked the link in the email - internal static let authResetPasswordErrorUnauthorized = VectorL10n.tr("Vector", "auth_reset_password_error_unauthorized") + internal static var authResetPasswordErrorUnauthorized: String { + return VectorL10n.tr("Vector", "auth_reset_password_error_unauthorized") + } /// To reset your password, enter the email address linked to your account: - internal static let authResetPasswordMessage = VectorL10n.tr("Vector", "auth_reset_password_message") + internal static var authResetPasswordMessage: String { + return VectorL10n.tr("Vector", "auth_reset_password_message") + } /// The email address linked to your account must be entered. - internal static let authResetPasswordMissingEmail = VectorL10n.tr("Vector", "auth_reset_password_missing_email") + internal static var authResetPasswordMissingEmail: String { + return VectorL10n.tr("Vector", "auth_reset_password_missing_email") + } /// A new password must be entered. - internal static let authResetPasswordMissingPassword = VectorL10n.tr("Vector", "auth_reset_password_missing_password") + internal static var authResetPasswordMissingPassword: String { + return VectorL10n.tr("Vector", "auth_reset_password_missing_password") + } /// I have verified my email address - internal static let authResetPasswordNextStepButton = VectorL10n.tr("Vector", "auth_reset_password_next_step_button") + internal static var authResetPasswordNextStepButton: String { + return VectorL10n.tr("Vector", "auth_reset_password_next_step_button") + } /// Your password has been reset.\n\nYou have been logged out of all devices and will no longer receive push notifications. To re-enable notifications, re-log in on each device. - internal static let authResetPasswordSuccessMessage = VectorL10n.tr("Vector", "auth_reset_password_success_message") + internal static var authResetPasswordSuccessMessage: String { + return VectorL10n.tr("Vector", "auth_reset_password_success_message") + } /// Return to login screen - internal static let authReturnToLogin = VectorL10n.tr("Vector", "auth_return_to_login") + internal static var authReturnToLogin: String { + return VectorL10n.tr("Vector", "auth_return_to_login") + } /// Send Reset Email - internal static let authSendResetEmail = VectorL10n.tr("Vector", "auth_send_reset_email") + internal static var authSendResetEmail: String { + return VectorL10n.tr("Vector", "auth_send_reset_email") + } /// Skip - internal static let authSkip = VectorL10n.tr("Vector", "auth_skip") + internal static var authSkip: String { + return VectorL10n.tr("Vector", "auth_skip") + } /// Submit - internal static let authSubmit = VectorL10n.tr("Vector", "auth_submit") + internal static var authSubmit: String { + return VectorL10n.tr("Vector", "auth_submit") + } /// The identity server is not trusted - internal static let authUntrustedIdServer = VectorL10n.tr("Vector", "auth_untrusted_id_server") + internal static var authUntrustedIdServer: String { + return VectorL10n.tr("Vector", "auth_untrusted_id_server") + } /// Use custom server options (advanced) - internal static let authUseServerOptions = VectorL10n.tr("Vector", "auth_use_server_options") + internal static var authUseServerOptions: String { + return VectorL10n.tr("Vector", "auth_use_server_options") + } /// Email or user name - internal static let authUserIdPlaceholder = VectorL10n.tr("Vector", "auth_user_id_placeholder") + internal static var authUserIdPlaceholder: String { + return VectorL10n.tr("Vector", "auth_user_id_placeholder") + } /// User name - internal static let authUserNamePlaceholder = VectorL10n.tr("Vector", "auth_user_name_placeholder") + internal static var authUserNamePlaceholder: String { + return VectorL10n.tr("Vector", "auth_user_name_placeholder") + } /// Username in use - internal static let authUsernameInUse = VectorL10n.tr("Vector", "auth_username_in_use") + internal static var authUsernameInUse: String { + return VectorL10n.tr("Vector", "auth_username_in_use") + } /// Back - internal static let back = VectorL10n.tr("Vector", "back") + internal static var back: String { + return VectorL10n.tr("Vector", "back") + } /// Please describe what you did before the crash: - internal static let bugCrashReportDescription = VectorL10n.tr("Vector", "bug_crash_report_description") + internal static var bugCrashReportDescription: String { + return VectorL10n.tr("Vector", "bug_crash_report_description") + } /// Crash Report - internal static let bugCrashReportTitle = VectorL10n.tr("Vector", "bug_crash_report_title") + internal static var bugCrashReportTitle: String { + return VectorL10n.tr("Vector", "bug_crash_report_title") + } /// Please describe the bug. What did you do? What did you expect to happen? What actually happened? - internal static let bugReportDescription = VectorL10n.tr("Vector", "bug_report_description") + internal static var bugReportDescription: String { + return VectorL10n.tr("Vector", "bug_report_description") + } /// In order to diagnose problems, logs from this client will be sent with this bug report. If you would prefer to only send the text above, please untick: - internal static let bugReportLogsDescription = VectorL10n.tr("Vector", "bug_report_logs_description") + internal static var bugReportLogsDescription: String { + return VectorL10n.tr("Vector", "bug_report_logs_description") + } /// Uploading report - internal static let bugReportProgressUploading = VectorL10n.tr("Vector", "bug_report_progress_uploading") + internal static var bugReportProgressUploading: String { + return VectorL10n.tr("Vector", "bug_report_progress_uploading") + } /// Collecting logs - internal static let bugReportProgressZipping = VectorL10n.tr("Vector", "bug_report_progress_zipping") + internal static var bugReportProgressZipping: String { + return VectorL10n.tr("Vector", "bug_report_progress_zipping") + } /// The application has crashed last time. Would you like to submit a crash report? - internal static let bugReportPrompt = VectorL10n.tr("Vector", "bug_report_prompt") + internal static var bugReportPrompt: String { + return VectorL10n.tr("Vector", "bug_report_prompt") + } /// Send - internal static let bugReportSend = VectorL10n.tr("Vector", "bug_report_send") + internal static var bugReportSend: String { + return VectorL10n.tr("Vector", "bug_report_send") + } /// Send logs - internal static let bugReportSendLogs = VectorL10n.tr("Vector", "bug_report_send_logs") + internal static var bugReportSendLogs: String { + return VectorL10n.tr("Vector", "bug_report_send_logs") + } /// Send screenshot - internal static let bugReportSendScreenshot = VectorL10n.tr("Vector", "bug_report_send_screenshot") + internal static var bugReportSendScreenshot: String { + return VectorL10n.tr("Vector", "bug_report_send_screenshot") + } /// Bug Report - internal static let bugReportTitle = VectorL10n.tr("Vector", "bug_report_title") + internal static var bugReportTitle: String { + return VectorL10n.tr("Vector", "bug_report_title") + } /// There is already a call in progress. - internal static let callAlreadyDisplayed = VectorL10n.tr("Vector", "call_already_displayed") + internal static var callAlreadyDisplayed: String { + return VectorL10n.tr("Vector", "call_already_displayed") + } /// Incoming video call... - internal static let callIncomingVideo = VectorL10n.tr("Vector", "call_incoming_video") + internal static var callIncomingVideo: String { + return VectorL10n.tr("Vector", "call_incoming_video") + } /// Incoming video call from %@ internal static func callIncomingVideoPrompt(_ p1: String) -> String { return VectorL10n.tr("Vector", "call_incoming_video_prompt", p1) } /// Incoming call... - internal static let callIncomingVoice = VectorL10n.tr("Vector", "call_incoming_voice") + internal static var callIncomingVoice: String { + return VectorL10n.tr("Vector", "call_incoming_voice") + } /// Incoming voice call from %@ internal static func callIncomingVoicePrompt(_ p1: String) -> String { return VectorL10n.tr("Vector", "call_incoming_voice_prompt", p1) } /// Failed to join the conference call. - internal static let callJitsiError = VectorL10n.tr("Vector", "call_jitsi_error") + internal static var callJitsiError: String { + return VectorL10n.tr("Vector", "call_jitsi_error") + } /// Camera - internal static let camera = VectorL10n.tr("Vector", "camera") + internal static var camera: String { + return VectorL10n.tr("Vector", "camera") + } /// %@ doesn't have permission to use Camera, please change privacy settings internal static func cameraAccessNotGranted(_ p1: String) -> String { return VectorL10n.tr("Vector", "camera_access_not_granted", p1) } /// Cancel - internal static let cancel = VectorL10n.tr("Vector", "cancel") + internal static var cancel: String { + return VectorL10n.tr("Vector", "cancel") + } /// collapse - internal static let collapse = VectorL10n.tr("Vector", "collapse") + internal static var collapse: String { + return VectorL10n.tr("Vector", "collapse") + } /// Matrix users only - internal static let contactsAddressBookMatrixUsersToggle = VectorL10n.tr("Vector", "contacts_address_book_matrix_users_toggle") + internal static var contactsAddressBookMatrixUsersToggle: String { + return VectorL10n.tr("Vector", "contacts_address_book_matrix_users_toggle") + } /// No local contacts - internal static let contactsAddressBookNoContact = VectorL10n.tr("Vector", "contacts_address_book_no_contact") + internal static var contactsAddressBookNoContact: String { + return VectorL10n.tr("Vector", "contacts_address_book_no_contact") + } /// You didn't allow Riot to access your local contacts - internal static let contactsAddressBookPermissionDenied = VectorL10n.tr("Vector", "contacts_address_book_permission_denied") + internal static var contactsAddressBookPermissionDenied: String { + return VectorL10n.tr("Vector", "contacts_address_book_permission_denied") + } /// Permission required to access local contacts - internal static let contactsAddressBookPermissionRequired = VectorL10n.tr("Vector", "contacts_address_book_permission_required") + internal static var contactsAddressBookPermissionRequired: String { + return VectorL10n.tr("Vector", "contacts_address_book_permission_required") + } /// LOCAL CONTACTS - internal static let contactsAddressBookSection = VectorL10n.tr("Vector", "contacts_address_book_section") + internal static var contactsAddressBookSection: String { + return VectorL10n.tr("Vector", "contacts_address_book_section") + } /// USER DIRECTORY (offline) - internal static let contactsUserDirectoryOfflineSection = VectorL10n.tr("Vector", "contacts_user_directory_offline_section") + internal static var contactsUserDirectoryOfflineSection: String { + return VectorL10n.tr("Vector", "contacts_user_directory_offline_section") + } /// USER DIRECTORY - internal static let contactsUserDirectorySection = VectorL10n.tr("Vector", "contacts_user_directory_section") + internal static var contactsUserDirectorySection: String { + return VectorL10n.tr("Vector", "contacts_user_directory_section") + } /// Continue - internal static let `continue` = VectorL10n.tr("Vector", "continue") + internal static var `continue`: String { + return VectorL10n.tr("Vector", "continue") + } /// Create - internal static let create = VectorL10n.tr("Vector", "create") + internal static var create: String { + return VectorL10n.tr("Vector", "create") + } /// Please forget all messages I have sent when my account is deactivated ( - internal static let deactivateAccountForgetMessagesInformationPart1 = VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part1") + internal static var deactivateAccountForgetMessagesInformationPart1: String { + return VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part1") + } /// Warning - internal static let deactivateAccountForgetMessagesInformationPart2Emphasize = VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part2_emphasize") + internal static var deactivateAccountForgetMessagesInformationPart2Emphasize: String { + return VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part2_emphasize") + } /// : this will cause future users to see an incomplete view of conversations) - internal static let deactivateAccountForgetMessagesInformationPart3 = VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part3") + internal static var deactivateAccountForgetMessagesInformationPart3: String { + return VectorL10n.tr("Vector", "deactivate_account_forget_messages_information_part3") + } /// This will make your account permanently unusable. You will not be able to log in, and no one will be able to re-register the same user ID. This will cause your account to leave all rooms it is participating in, and it will remove your account details from your identity server. - internal static let deactivateAccountInformationsPart1 = VectorL10n.tr("Vector", "deactivate_account_informations_part1") + internal static var deactivateAccountInformationsPart1: String { + return VectorL10n.tr("Vector", "deactivate_account_informations_part1") + } /// This action is irreversible. - internal static let deactivateAccountInformationsPart2Emphasize = VectorL10n.tr("Vector", "deactivate_account_informations_part2_emphasize") + internal static var deactivateAccountInformationsPart2Emphasize: String { + return VectorL10n.tr("Vector", "deactivate_account_informations_part2_emphasize") + } /// \n\nDeactivating your account - internal static let deactivateAccountInformationsPart3 = VectorL10n.tr("Vector", "deactivate_account_informations_part3") + internal static var deactivateAccountInformationsPart3: String { + return VectorL10n.tr("Vector", "deactivate_account_informations_part3") + } /// does not by default cause us to forget messages you have sent. - internal static let deactivateAccountInformationsPart4Emphasize = VectorL10n.tr("Vector", "deactivate_account_informations_part4_emphasize") + internal static var deactivateAccountInformationsPart4Emphasize: String { + return VectorL10n.tr("Vector", "deactivate_account_informations_part4_emphasize") + } /// If you would like us to forget your messages, please tick the box below\n\nMessage visibility in Matrix is similar to email. Our forgetting your messages means that messages you have sent will not be shared with any new or unregistered users, but registered users who already have access to these messages will still have access to their copy. - internal static let deactivateAccountInformationsPart5 = VectorL10n.tr("Vector", "deactivate_account_informations_part5") + internal static var deactivateAccountInformationsPart5: String { + return VectorL10n.tr("Vector", "deactivate_account_informations_part5") + } /// To continue, please enter your password - internal static let deactivateAccountPasswordAlertMessage = VectorL10n.tr("Vector", "deactivate_account_password_alert_message") + internal static var deactivateAccountPasswordAlertMessage: String { + return VectorL10n.tr("Vector", "deactivate_account_password_alert_message") + } /// Deactivate Account - internal static let deactivateAccountPasswordAlertTitle = VectorL10n.tr("Vector", "deactivate_account_password_alert_title") + internal static var deactivateAccountPasswordAlertTitle: String { + return VectorL10n.tr("Vector", "deactivate_account_password_alert_title") + } /// Deactivate Account - internal static let deactivateAccountTitle = VectorL10n.tr("Vector", "deactivate_account_title") + internal static var deactivateAccountTitle: String { + return VectorL10n.tr("Vector", "deactivate_account_title") + } /// Deactivate account - internal static let deactivateAccountValidateAction = VectorL10n.tr("Vector", "deactivate_account_validate_action") + internal static var deactivateAccountValidateAction: String { + return VectorL10n.tr("Vector", "deactivate_account_validate_action") + } /// Decline - internal static let decline = VectorL10n.tr("Vector", "decline") + internal static var decline: String { + return VectorL10n.tr("Vector", "decline") + } /// %tu rooms internal static func directoryCellDescription(_ p1: Int) -> String { return VectorL10n.tr("Vector", "directory_cell_description", p1) } /// Browse directory - internal static let directoryCellTitle = VectorL10n.tr("Vector", "directory_cell_title") + internal static var directoryCellTitle: String { + return VectorL10n.tr("Vector", "directory_cell_title") + } /// Failed to fetch data - internal static let directorySearchFail = VectorL10n.tr("Vector", "directory_search_fail") + internal static var directorySearchFail: String { + return VectorL10n.tr("Vector", "directory_search_fail") + } /// %tu results found for %@ internal static func directorySearchResults(_ p1: Int, _ p2: String) -> String { return VectorL10n.tr("Vector", "directory_search_results", p1, p2) @@ -241,31 +439,53 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "directory_search_results_more_than", p1, p2) } /// Browse directory results - internal static let directorySearchResultsTitle = VectorL10n.tr("Vector", "directory_search_results_title") + internal static var directorySearchResultsTitle: String { + return VectorL10n.tr("Vector", "directory_search_results_title") + } /// Searching directory… - internal static let directorySearchingTitle = VectorL10n.tr("Vector", "directory_searching_title") + internal static var directorySearchingTitle: String { + return VectorL10n.tr("Vector", "directory_searching_title") + } /// All native Matrix rooms - internal static let directoryServerAllNativeRooms = VectorL10n.tr("Vector", "directory_server_all_native_rooms") + internal static var directoryServerAllNativeRooms: String { + return VectorL10n.tr("Vector", "directory_server_all_native_rooms") + } /// All rooms on %@ server internal static func directoryServerAllRooms(_ p1: String) -> String { return VectorL10n.tr("Vector", "directory_server_all_rooms", p1) } /// Select a directory - internal static let directoryServerPickerTitle = VectorL10n.tr("Vector", "directory_server_picker_title") + internal static var directoryServerPickerTitle: String { + return VectorL10n.tr("Vector", "directory_server_picker_title") + } /// matrix.org - internal static let directoryServerPlaceholder = VectorL10n.tr("Vector", "directory_server_placeholder") + internal static var directoryServerPlaceholder: String { + return VectorL10n.tr("Vector", "directory_server_placeholder") + } /// Type a homeserver to list public rooms from - internal static let directoryServerTypeHomeserver = VectorL10n.tr("Vector", "directory_server_type_homeserver") + internal static var directoryServerTypeHomeserver: String { + return VectorL10n.tr("Vector", "directory_server_type_homeserver") + } /// Directory - internal static let directoryTitle = VectorL10n.tr("Vector", "directory_title") + internal static var directoryTitle: String { + return VectorL10n.tr("Vector", "directory_title") + } /// Do not ask again - internal static let doNotAskAgain = VectorL10n.tr("Vector", "do_not_ask_again") + internal static var doNotAskAgain: String { + return VectorL10n.tr("Vector", "do_not_ask_again") + } /// Riot now supports end-to-end encryption but you need to log in again to enable it.\n\nYou can do it now or later from the application settings. - internal static let e2eEnablingOnAppUpdate = VectorL10n.tr("Vector", "e2e_enabling_on_app_update") + internal static var e2eEnablingOnAppUpdate: String { + return VectorL10n.tr("Vector", "e2e_enabling_on_app_update") + } /// You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver.\nThis is a once off; sorry for the inconvenience. - internal static let e2eNeedLogInAgain = VectorL10n.tr("Vector", "e2e_need_log_in_again") + internal static var e2eNeedLogInAgain: String { + return VectorL10n.tr("Vector", "e2e_need_log_in_again") + } /// Ignore request - internal static let e2eRoomKeyRequestIgnoreRequest = VectorL10n.tr("Vector", "e2e_room_key_request_ignore_request") + internal static var e2eRoomKeyRequestIgnoreRequest: String { + return VectorL10n.tr("Vector", "e2e_room_key_request_ignore_request") + } /// Your unverified device '%@' is requesting encryption keys. internal static func e2eRoomKeyRequestMessage(_ p1: String) -> String { return VectorL10n.tr("Vector", "e2e_room_key_request_message", p1) @@ -275,15 +495,25 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "e2e_room_key_request_message_new_device", p1) } /// Share without verifying - internal static let e2eRoomKeyRequestShareWithoutVerifying = VectorL10n.tr("Vector", "e2e_room_key_request_share_without_verifying") + internal static var e2eRoomKeyRequestShareWithoutVerifying: String { + return VectorL10n.tr("Vector", "e2e_room_key_request_share_without_verifying") + } /// Start verification... - internal static let e2eRoomKeyRequestStartVerification = VectorL10n.tr("Vector", "e2e_room_key_request_start_verification") + internal static var e2eRoomKeyRequestStartVerification: String { + return VectorL10n.tr("Vector", "e2e_room_key_request_start_verification") + } /// Encryption key request - internal static let e2eRoomKeyRequestTitle = VectorL10n.tr("Vector", "e2e_room_key_request_title") + internal static var e2eRoomKeyRequestTitle: String { + return VectorL10n.tr("Vector", "e2e_room_key_request_title") + } /// Send an encrypted message… - internal static let encryptedRoomMessagePlaceholder = VectorL10n.tr("Vector", "encrypted_room_message_placeholder") + internal static var encryptedRoomMessagePlaceholder: String { + return VectorL10n.tr("Vector", "encrypted_room_message_placeholder") + } /// Send an encrypted reply… - internal static let encryptedRoomMessageReplyToPlaceholder = VectorL10n.tr("Vector", "encrypted_room_message_reply_to_placeholder") + internal static var encryptedRoomMessageReplyToPlaceholder: String { + return VectorL10n.tr("Vector", "encrypted_room_message_reply_to_placeholder") + } /// VoIP conference added by %@ internal static func eventFormatterJitsiWidgetAdded(_ p1: String) -> String { return VectorL10n.tr("Vector", "event_formatter_jitsi_widget_added", p1) @@ -297,9 +527,13 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "event_formatter_member_updates", p1) } /// Re-request encryption keys - internal static let eventFormatterRerequestKeysPart1Link = VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part1_link") + internal static var eventFormatterRerequestKeysPart1Link: String { + return VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part1_link") + } /// from your other devices. - internal static let eventFormatterRerequestKeysPart2 = VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part2") + internal static var eventFormatterRerequestKeysPart2: String { + return VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part2") + } /// %@ widget added by %@ internal static func eventFormatterWidgetAdded(_ p1: String, _ p2: String) -> String { return VectorL10n.tr("Vector", "event_formatter_widget_added", p1, p2) @@ -313,19 +547,29 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_message", p1) } /// Review now - internal static let gdprConsentNotGivenAlertReviewNowAction = VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_review_now_action") + internal static var gdprConsentNotGivenAlertReviewNowAction: String { + return VectorL10n.tr("Vector", "gdpr_consent_not_given_alert_review_now_action") + } /// Would you like to help improve %@ by automatically reporting anonymous crash reports and usage data? internal static func googleAnalyticsUsePrompt(_ p1: String) -> String { return VectorL10n.tr("Vector", "google_analytics_use_prompt", p1) } /// Home - internal static let groupDetailsHome = VectorL10n.tr("Vector", "group_details_home") + internal static var groupDetailsHome: String { + return VectorL10n.tr("Vector", "group_details_home") + } /// People - internal static let groupDetailsPeople = VectorL10n.tr("Vector", "group_details_people") + internal static var groupDetailsPeople: String { + return VectorL10n.tr("Vector", "group_details_people") + } /// Rooms - internal static let groupDetailsRooms = VectorL10n.tr("Vector", "group_details_rooms") + internal static var groupDetailsRooms: String { + return VectorL10n.tr("Vector", "group_details_rooms") + } /// Community Details - internal static let groupDetailsTitle = VectorL10n.tr("Vector", "group_details_title") + internal static var groupDetailsTitle: String { + return VectorL10n.tr("Vector", "group_details_title") + } /// %tu members internal static func groupHomeMultiMembersFormat(_ p1: Int) -> String { return VectorL10n.tr("Vector", "group_home_multi_members_format", p1) @@ -335,253 +579,557 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "group_home_multi_rooms_format", p1) } /// 1 member - internal static let groupHomeOneMemberFormat = VectorL10n.tr("Vector", "group_home_one_member_format") + internal static var groupHomeOneMemberFormat: String { + return VectorL10n.tr("Vector", "group_home_one_member_format") + } /// 1 room - internal static let groupHomeOneRoomFormat = VectorL10n.tr("Vector", "group_home_one_room_format") + internal static var groupHomeOneRoomFormat: String { + return VectorL10n.tr("Vector", "group_home_one_room_format") + } /// %@ has invited you to join this community internal static func groupInvitationFormat(_ p1: String) -> String { return VectorL10n.tr("Vector", "group_invitation_format", p1) } /// INVITES - internal static let groupInviteSection = VectorL10n.tr("Vector", "group_invite_section") + internal static var groupInviteSection: String { + return VectorL10n.tr("Vector", "group_invite_section") + } /// Add participant - internal static let groupParticipantsAddParticipant = VectorL10n.tr("Vector", "group_participants_add_participant") + internal static var groupParticipantsAddParticipant: String { + return VectorL10n.tr("Vector", "group_participants_add_participant") + } /// Filter community members - internal static let groupParticipantsFilterMembers = VectorL10n.tr("Vector", "group_participants_filter_members") + internal static var groupParticipantsFilterMembers: String { + return VectorL10n.tr("Vector", "group_participants_filter_members") + } /// Search / invite by User ID or Name - internal static let groupParticipantsInviteAnotherUser = VectorL10n.tr("Vector", "group_participants_invite_another_user") + internal static var groupParticipantsInviteAnotherUser: String { + return VectorL10n.tr("Vector", "group_participants_invite_another_user") + } /// Malformed ID. Should be a Matrix ID like '@localpart:domain' - internal static let groupParticipantsInviteMalformedId = VectorL10n.tr("Vector", "group_participants_invite_malformed_id") + internal static var groupParticipantsInviteMalformedId: String { + return VectorL10n.tr("Vector", "group_participants_invite_malformed_id") + } /// Invite Error - internal static let groupParticipantsInviteMalformedIdTitle = VectorL10n.tr("Vector", "group_participants_invite_malformed_id_title") + internal static var groupParticipantsInviteMalformedIdTitle: String { + return VectorL10n.tr("Vector", "group_participants_invite_malformed_id_title") + } /// Are you sure you want to invite %@ to this group? internal static func groupParticipantsInvitePromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "group_participants_invite_prompt_msg", p1) } /// Confirmation - internal static let groupParticipantsInvitePromptTitle = VectorL10n.tr("Vector", "group_participants_invite_prompt_title") + internal static var groupParticipantsInvitePromptTitle: String { + return VectorL10n.tr("Vector", "group_participants_invite_prompt_title") + } /// INVITED - internal static let groupParticipantsInvitedSection = VectorL10n.tr("Vector", "group_participants_invited_section") + internal static var groupParticipantsInvitedSection: String { + return VectorL10n.tr("Vector", "group_participants_invited_section") + } /// Are you sure you want to leave the group? - internal static let groupParticipantsLeavePromptMsg = VectorL10n.tr("Vector", "group_participants_leave_prompt_msg") + internal static var groupParticipantsLeavePromptMsg: String { + return VectorL10n.tr("Vector", "group_participants_leave_prompt_msg") + } /// Leave group - internal static let groupParticipantsLeavePromptTitle = VectorL10n.tr("Vector", "group_participants_leave_prompt_title") + internal static var groupParticipantsLeavePromptTitle: String { + return VectorL10n.tr("Vector", "group_participants_leave_prompt_title") + } /// Are you sure you want to remove %@ from this group? internal static func groupParticipantsRemovePromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "group_participants_remove_prompt_msg", p1) } /// Confirmation - internal static let groupParticipantsRemovePromptTitle = VectorL10n.tr("Vector", "group_participants_remove_prompt_title") + internal static var groupParticipantsRemovePromptTitle: String { + return VectorL10n.tr("Vector", "group_participants_remove_prompt_title") + } /// Filter community rooms - internal static let groupRoomsFilterRooms = VectorL10n.tr("Vector", "group_rooms_filter_rooms") + internal static var groupRoomsFilterRooms: String { + return VectorL10n.tr("Vector", "group_rooms_filter_rooms") + } /// COMMUNITIES - internal static let groupSection = VectorL10n.tr("Vector", "group_section") + internal static var groupSection: String { + return VectorL10n.tr("Vector", "group_section") + } /// Could not connect to the homeserver. - internal static let homeserverConnectionLost = VectorL10n.tr("Vector", "homeserver_connection_lost") + internal static var homeserverConnectionLost: String { + return VectorL10n.tr("Vector", "homeserver_connection_lost") + } /// Invite - internal static let invite = VectorL10n.tr("Vector", "invite") + internal static var invite: String { + return VectorL10n.tr("Vector", "invite") + } /// Join - internal static let join = VectorL10n.tr("Vector", "join") + internal static var join: String { + return VectorL10n.tr("Vector", "join") + } + /// Set up Secure Message Recovery in case you lose or log out of this device. + internal static var keyBackupSetupIntroInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_info") + } + /// Set up + internal static var keyBackupSetupIntroSetupAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_setup_action") + } + /// Never lose encrypted messages + internal static var keyBackupSetupIntroTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_title") + } + /// Passphrase doesn’t match + internal static var keyBackupSetupPassphraseConfirmPassphraseInvalid: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_confirm_passphrase_invalid") + } + /// Confirm passphrase + internal static var keyBackupSetupPassphraseConfirmPassphrasePlaceholder: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_confirm_passphrase_placeholder") + } + /// Confirm + internal static var keyBackupSetupPassphraseConfirmPassphraseTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_confirm_passphrase_title") + } + /// Great! + internal static var keyBackupSetupPassphraseConfirmPassphraseValid: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_confirm_passphrase_valid") + } + /// Secure your encrypted message history with a Recovery Passphrase.\n\nYou’ll need it if you log out, or lose access to this device. + internal static var keyBackupSetupPassphraseInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_info") + } + /// Try adding a word + internal static var keyBackupSetupPassphrasePassphraseInvalid: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_passphrase_invalid") + } + /// Enter passphrase + internal static var keyBackupSetupPassphrasePassphrasePlaceholder: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_passphrase_placeholder") + } + /// Enter + internal static var keyBackupSetupPassphrasePassphraseTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_passphrase_title") + } + /// Great! + internal static var keyBackupSetupPassphrasePassphraseValid: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_passphrase_valid") + } + /// Set recovery passphrase + internal static var keyBackupSetupPassphraseSetPassphraseAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_set_passphrase_action") + } + /// Make a copy of this Recovery Key and keep it safe.\n\nAs a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase. + internal static var keyBackupSetupRecoveryKeyInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_info") + } + /// I've made a copy + internal static var keyBackupSetupRecoveryKeyMadeCopyAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_made_copy_action") + } + /// Make a Copy + internal static var keyBackupSetupRecoveryKeyMakeCopyAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_make_copy_action") + } + /// Recovery Key + internal static var keyBackupSetupRecoveryKeyRecoveryKeyTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_recovery_key_title") + } + /// Skip + internal static var keyBackupSetupSkipAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_skip_action") + } + /// You may lose secure messages if you log out of lose your device. + internal static var keyBackupSetupSkipAlertMessage: String { + return VectorL10n.tr("Vector", "key_backup_setup_skip_alert_message") + } + /// Skip + internal static var keyBackupSetupSkipAlertSkipAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_skip_alert_skip_action") + } + /// Are you sure? + internal static var keyBackupSetupSkipAlertTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_skip_alert_title") + } + /// Message Recovery + internal static var keyBackupSetupTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_title") + } /// %.1fK internal static func largeBadgeValueKFormat(_ p1: Float) -> String { return VectorL10n.tr("Vector", "large_badge_value_k_format", p1) } /// Later - internal static let later = VectorL10n.tr("Vector", "later") + internal static var later: String { + return VectorL10n.tr("Vector", "later") + } /// Leave - internal static let leave = VectorL10n.tr("Vector", "leave") + internal static var leave: String { + return VectorL10n.tr("Vector", "leave") + } /// Library - internal static let mediaPickerLibrary = VectorL10n.tr("Vector", "media_picker_library") + internal static var mediaPickerLibrary: String { + return VectorL10n.tr("Vector", "media_picker_library") + } /// Select - internal static let mediaPickerSelect = VectorL10n.tr("Vector", "media_picker_select") + internal static var mediaPickerSelect: String { + return VectorL10n.tr("Vector", "media_picker_select") + } /// The Internet connection appears to be offline. - internal static let networkOfflinePrompt = VectorL10n.tr("Vector", "network_offline_prompt") + internal static var networkOfflinePrompt: String { + return VectorL10n.tr("Vector", "network_offline_prompt") + } /// Next - internal static let next = VectorL10n.tr("Vector", "next") + internal static var next: String { + return VectorL10n.tr("Vector", "next") + } /// %@ is calling you but %@ does not support calls yet.\nYou can ignore this notification and answer the call from another device or you can reject it. internal static func noVoip(_ p1: String, _ p2: String) -> String { return VectorL10n.tr("Vector", "no_voip", p1, p2) } /// Incoming call - internal static let noVoipTitle = VectorL10n.tr("Vector", "no_voip_title") + internal static var noVoipTitle: String { + return VectorL10n.tr("Vector", "no_voip_title") + } /// Off - internal static let off = VectorL10n.tr("Vector", "off") + internal static var off: String { + return VectorL10n.tr("Vector", "off") + } /// On - internal static let on = VectorL10n.tr("Vector", "on") + internal static var on: String { + return VectorL10n.tr("Vector", "on") + } /// or - internal static let or = VectorL10n.tr("Vector", "or") + internal static var or: String { + return VectorL10n.tr("Vector", "or") + } /// CONVERSATIONS - internal static let peopleConversationSection = VectorL10n.tr("Vector", "people_conversation_section") + internal static var peopleConversationSection: String { + return VectorL10n.tr("Vector", "people_conversation_section") + } /// INVITES - internal static let peopleInvitesSection = VectorL10n.tr("Vector", "people_invites_section") + internal static var peopleInvitesSection: String { + return VectorL10n.tr("Vector", "people_invites_section") + } /// No conversations - internal static let peopleNoConversation = VectorL10n.tr("Vector", "people_no_conversation") + internal static var peopleNoConversation: String { + return VectorL10n.tr("Vector", "people_no_conversation") + } /// Preview - internal static let preview = VectorL10n.tr("Vector", "preview") + internal static var preview: String { + return VectorL10n.tr("Vector", "preview") + } /// Public Rooms (at %@): internal static func publicRoomSectionTitle(_ p1: String) -> String { return VectorL10n.tr("Vector", "public_room_section_title", p1) } /// You seem to be shaking the phone in frustration. Would you like to submit a bug report? - internal static let rageShakePrompt = VectorL10n.tr("Vector", "rage_shake_prompt") + internal static var rageShakePrompt: String { + return VectorL10n.tr("Vector", "rage_shake_prompt") + } /// Read Receipts List - internal static let readReceiptsList = VectorL10n.tr("Vector", "read_receipts_list") + internal static var readReceiptsList: String { + return VectorL10n.tr("Vector", "read_receipts_list") + } /// Read: - internal static let receiptStatusRead = VectorL10n.tr("Vector", "receipt_status_read") + internal static var receiptStatusRead: String { + return VectorL10n.tr("Vector", "receipt_status_read") + } /// Remove - internal static let remove = VectorL10n.tr("Vector", "remove") + internal static var remove: String { + return VectorL10n.tr("Vector", "remove") + } /// Rename - internal static let rename = VectorL10n.tr("Vector", "rename") + internal static var rename: String { + return VectorL10n.tr("Vector", "rename") + } /// Please launch Riot on another device that can decrypt the message so it can send the keys to this device. - internal static let rerequestKeysAlertMessage = VectorL10n.tr("Vector", "rerequest_keys_alert_message") + internal static var rerequestKeysAlertMessage: String { + return VectorL10n.tr("Vector", "rerequest_keys_alert_message") + } /// Request Sent - internal static let rerequestKeysAlertTitle = VectorL10n.tr("Vector", "rerequest_keys_alert_title") + internal static var rerequestKeysAlertTitle: String { + return VectorL10n.tr("Vector", "rerequest_keys_alert_title") + } /// Retry - internal static let retry = VectorL10n.tr("Vector", "retry") + internal static var retry: String { + return VectorL10n.tr("Vector", "retry") + } /// Send photo or video - internal static let roomActionSendPhotoOrVideo = VectorL10n.tr("Vector", "room_action_send_photo_or_video") + internal static var roomActionSendPhotoOrVideo: String { + return VectorL10n.tr("Vector", "room_action_send_photo_or_video") + } /// Send sticker - internal static let roomActionSendSticker = VectorL10n.tr("Vector", "room_action_send_sticker") + internal static var roomActionSendSticker: String { + return VectorL10n.tr("Vector", "room_action_send_sticker") + } /// You need permission to manage conference call in this room - internal static let roomConferenceCallNoPower = VectorL10n.tr("Vector", "room_conference_call_no_power") + internal static var roomConferenceCallNoPower: String { + return VectorL10n.tr("Vector", "room_conference_call_no_power") + } /// Account - internal static let roomCreationAccount = VectorL10n.tr("Vector", "room_creation_account") + internal static var roomCreationAccount: String { + return VectorL10n.tr("Vector", "room_creation_account") + } /// Appearance - internal static let roomCreationAppearance = VectorL10n.tr("Vector", "room_creation_appearance") + internal static var roomCreationAppearance: String { + return VectorL10n.tr("Vector", "room_creation_appearance") + } /// Name - internal static let roomCreationAppearanceName = VectorL10n.tr("Vector", "room_creation_appearance_name") + internal static var roomCreationAppearanceName: String { + return VectorL10n.tr("Vector", "room_creation_appearance_name") + } /// Chat picture (optional) - internal static let roomCreationAppearancePicture = VectorL10n.tr("Vector", "room_creation_appearance_picture") + internal static var roomCreationAppearancePicture: String { + return VectorL10n.tr("Vector", "room_creation_appearance_picture") + } /// Search / invite by User ID, Name or email - internal static let roomCreationInviteAnotherUser = VectorL10n.tr("Vector", "room_creation_invite_another_user") + internal static var roomCreationInviteAnotherUser: String { + return VectorL10n.tr("Vector", "room_creation_invite_another_user") + } /// Keep private - internal static let roomCreationKeepPrivate = VectorL10n.tr("Vector", "room_creation_keep_private") + internal static var roomCreationKeepPrivate: String { + return VectorL10n.tr("Vector", "room_creation_keep_private") + } /// Make private - internal static let roomCreationMakePrivate = VectorL10n.tr("Vector", "room_creation_make_private") + internal static var roomCreationMakePrivate: String { + return VectorL10n.tr("Vector", "room_creation_make_private") + } /// Make public - internal static let roomCreationMakePublic = VectorL10n.tr("Vector", "room_creation_make_public") + internal static var roomCreationMakePublic: String { + return VectorL10n.tr("Vector", "room_creation_make_public") + } /// Are you sure you want to make this chat public? Anyone can read your messages and join the chat. - internal static let roomCreationMakePublicPromptMsg = VectorL10n.tr("Vector", "room_creation_make_public_prompt_msg") + internal static var roomCreationMakePublicPromptMsg: String { + return VectorL10n.tr("Vector", "room_creation_make_public_prompt_msg") + } /// Make this chat public? - internal static let roomCreationMakePublicPromptTitle = VectorL10n.tr("Vector", "room_creation_make_public_prompt_title") + internal static var roomCreationMakePublicPromptTitle: String { + return VectorL10n.tr("Vector", "room_creation_make_public_prompt_title") + } /// Privacy - internal static let roomCreationPrivacy = VectorL10n.tr("Vector", "room_creation_privacy") + internal static var roomCreationPrivacy: String { + return VectorL10n.tr("Vector", "room_creation_privacy") + } /// This chat is private - internal static let roomCreationPrivateRoom = VectorL10n.tr("Vector", "room_creation_private_room") + internal static var roomCreationPrivateRoom: String { + return VectorL10n.tr("Vector", "room_creation_private_room") + } /// This chat is public - internal static let roomCreationPublicRoom = VectorL10n.tr("Vector", "room_creation_public_room") + internal static var roomCreationPublicRoom: String { + return VectorL10n.tr("Vector", "room_creation_public_room") + } /// New Chat - internal static let roomCreationTitle = VectorL10n.tr("Vector", "room_creation_title") + internal static var roomCreationTitle: String { + return VectorL10n.tr("Vector", "room_creation_title") + } /// A room is already being created. Please wait. - internal static let roomCreationWaitForCreation = VectorL10n.tr("Vector", "room_creation_wait_for_creation") + internal static var roomCreationWaitForCreation: String { + return VectorL10n.tr("Vector", "room_creation_wait_for_creation") + } /// Delete unsent messages - internal static let roomDeleteUnsentMessages = VectorL10n.tr("Vector", "room_delete_unsent_messages") + internal static var roomDeleteUnsentMessages: String { + return VectorL10n.tr("Vector", "room_delete_unsent_messages") + } /// Who can access this room? - internal static let roomDetailsAccessSection = VectorL10n.tr("Vector", "room_details_access_section") + internal static var roomDetailsAccessSection: String { + return VectorL10n.tr("Vector", "room_details_access_section") + } /// Anyone who knows the room's link, including guests - internal static let roomDetailsAccessSectionAnyone = VectorL10n.tr("Vector", "room_details_access_section_anyone") + internal static var roomDetailsAccessSectionAnyone: String { + return VectorL10n.tr("Vector", "room_details_access_section_anyone") + } /// Anyone who knows the room's link, apart from guests - internal static let roomDetailsAccessSectionAnyoneApartFromGuest = VectorL10n.tr("Vector", "room_details_access_section_anyone_apart_from_guest") + internal static var roomDetailsAccessSectionAnyoneApartFromGuest: String { + return VectorL10n.tr("Vector", "room_details_access_section_anyone_apart_from_guest") + } /// List this room in room directory - internal static let roomDetailsAccessSectionDirectoryToggle = VectorL10n.tr("Vector", "room_details_access_section_directory_toggle") + internal static var roomDetailsAccessSectionDirectoryToggle: String { + return VectorL10n.tr("Vector", "room_details_access_section_directory_toggle") + } /// Only people who have been invited - internal static let roomDetailsAccessSectionInvitedOnly = VectorL10n.tr("Vector", "room_details_access_section_invited_only") + internal static var roomDetailsAccessSectionInvitedOnly: String { + return VectorL10n.tr("Vector", "room_details_access_section_invited_only") + } /// To link to a room it must have an address - internal static let roomDetailsAccessSectionNoAddressWarning = VectorL10n.tr("Vector", "room_details_access_section_no_address_warning") + internal static var roomDetailsAccessSectionNoAddressWarning: String { + return VectorL10n.tr("Vector", "room_details_access_section_no_address_warning") + } /// You will have no main address specified. The default main address for this room will be picked randomly - internal static let roomDetailsAddressesDisableMainAddressPromptMsg = VectorL10n.tr("Vector", "room_details_addresses_disable_main_address_prompt_msg") + internal static var roomDetailsAddressesDisableMainAddressPromptMsg: String { + return VectorL10n.tr("Vector", "room_details_addresses_disable_main_address_prompt_msg") + } /// Main address warning - internal static let roomDetailsAddressesDisableMainAddressPromptTitle = VectorL10n.tr("Vector", "room_details_addresses_disable_main_address_prompt_title") + internal static var roomDetailsAddressesDisableMainAddressPromptTitle: String { + return VectorL10n.tr("Vector", "room_details_addresses_disable_main_address_prompt_title") + } /// %@ is not a valid format for an alias internal static func roomDetailsAddressesInvalidAddressPromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_details_addresses_invalid_address_prompt_msg", p1) } /// Invalid alias format - internal static let roomDetailsAddressesInvalidAddressPromptTitle = VectorL10n.tr("Vector", "room_details_addresses_invalid_address_prompt_title") + internal static var roomDetailsAddressesInvalidAddressPromptTitle: String { + return VectorL10n.tr("Vector", "room_details_addresses_invalid_address_prompt_title") + } /// Addresses - internal static let roomDetailsAddressesSection = VectorL10n.tr("Vector", "room_details_addresses_section") + internal static var roomDetailsAddressesSection: String { + return VectorL10n.tr("Vector", "room_details_addresses_section") + } /// Encrypt to verified devices only - internal static let roomDetailsAdvancedE2eEncryptionBlacklistUnverifiedDevices = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_blacklist_unverified_devices") + internal static var roomDetailsAdvancedE2eEncryptionBlacklistUnverifiedDevices: String { + return VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_blacklist_unverified_devices") + } /// Encryption is not enabled in this room. - internal static let roomDetailsAdvancedE2eEncryptionDisabled = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_disabled") + internal static var roomDetailsAdvancedE2eEncryptionDisabled: String { + return VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_disabled") + } /// Encryption is enabled in this room - internal static let roomDetailsAdvancedE2eEncryptionEnabled = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_enabled") + internal static var roomDetailsAdvancedE2eEncryptionEnabled: String { + return VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_enabled") + } /// End-to-end encryption is experimental and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nOnce encryption is enabled for a room it cannot be turned off again (for now).\n\nEncrypted messages will not be visible on clients that do not yet implement encryption. - internal static let roomDetailsAdvancedE2eEncryptionPromptMessage = VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_prompt_message") + internal static var roomDetailsAdvancedE2eEncryptionPromptMessage: String { + return VectorL10n.tr("Vector", "room_details_advanced_e2e_encryption_prompt_message") + } /// Enable encryption (warning: cannot be disabled again!) - internal static let roomDetailsAdvancedEnableE2eEncryption = VectorL10n.tr("Vector", "room_details_advanced_enable_e2e_encryption") + internal static var roomDetailsAdvancedEnableE2eEncryption: String { + return VectorL10n.tr("Vector", "room_details_advanced_enable_e2e_encryption") + } /// Room ID: - internal static let roomDetailsAdvancedRoomId = VectorL10n.tr("Vector", "room_details_advanced_room_id") + internal static var roomDetailsAdvancedRoomId: String { + return VectorL10n.tr("Vector", "room_details_advanced_room_id") + } /// Advanced - internal static let roomDetailsAdvancedSection = VectorL10n.tr("Vector", "room_details_advanced_section") + internal static var roomDetailsAdvancedSection: String { + return VectorL10n.tr("Vector", "room_details_advanced_section") + } /// Banned users - internal static let roomDetailsBannedUsersSection = VectorL10n.tr("Vector", "room_details_banned_users_section") + internal static var roomDetailsBannedUsersSection: String { + return VectorL10n.tr("Vector", "room_details_banned_users_section") + } /// Copy Room Address - internal static let roomDetailsCopyRoomAddress = VectorL10n.tr("Vector", "room_details_copy_room_address") + internal static var roomDetailsCopyRoomAddress: String { + return VectorL10n.tr("Vector", "room_details_copy_room_address") + } /// Copy Room ID - internal static let roomDetailsCopyRoomId = VectorL10n.tr("Vector", "room_details_copy_room_id") + internal static var roomDetailsCopyRoomId: String { + return VectorL10n.tr("Vector", "room_details_copy_room_id") + } /// Copy Room URL - internal static let roomDetailsCopyRoomUrl = VectorL10n.tr("Vector", "room_details_copy_room_url") + internal static var roomDetailsCopyRoomUrl: String { + return VectorL10n.tr("Vector", "room_details_copy_room_url") + } /// Direct Chat - internal static let roomDetailsDirectChat = VectorL10n.tr("Vector", "room_details_direct_chat") + internal static var roomDetailsDirectChat: String { + return VectorL10n.tr("Vector", "room_details_direct_chat") + } /// Fail to add the new room addresses - internal static let roomDetailsFailToAddRoomAliases = VectorL10n.tr("Vector", "room_details_fail_to_add_room_aliases") + internal static var roomDetailsFailToAddRoomAliases: String { + return VectorL10n.tr("Vector", "room_details_fail_to_add_room_aliases") + } /// Fail to enable encryption in this room - internal static let roomDetailsFailToEnableEncryption = VectorL10n.tr("Vector", "room_details_fail_to_enable_encryption") + internal static var roomDetailsFailToEnableEncryption: String { + return VectorL10n.tr("Vector", "room_details_fail_to_enable_encryption") + } /// Fail to remove the room addresses - internal static let roomDetailsFailToRemoveRoomAliases = VectorL10n.tr("Vector", "room_details_fail_to_remove_room_aliases") + internal static var roomDetailsFailToRemoveRoomAliases: String { + return VectorL10n.tr("Vector", "room_details_fail_to_remove_room_aliases") + } /// Fail to update the room photo - internal static let roomDetailsFailToUpdateAvatar = VectorL10n.tr("Vector", "room_details_fail_to_update_avatar") + internal static var roomDetailsFailToUpdateAvatar: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_avatar") + } /// Fail to update the history visibility - internal static let roomDetailsFailToUpdateHistoryVisibility = VectorL10n.tr("Vector", "room_details_fail_to_update_history_visibility") + internal static var roomDetailsFailToUpdateHistoryVisibility: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_history_visibility") + } /// Fail to update the main address - internal static let roomDetailsFailToUpdateRoomCanonicalAlias = VectorL10n.tr("Vector", "room_details_fail_to_update_room_canonical_alias") + internal static var roomDetailsFailToUpdateRoomCanonicalAlias: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_canonical_alias") + } /// Fail to update the related communities - internal static let roomDetailsFailToUpdateRoomCommunities = VectorL10n.tr("Vector", "room_details_fail_to_update_room_communities") + internal static var roomDetailsFailToUpdateRoomCommunities: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_communities") + } /// Fail to update the direct flag of this room - internal static let roomDetailsFailToUpdateRoomDirect = VectorL10n.tr("Vector", "room_details_fail_to_update_room_direct") + internal static var roomDetailsFailToUpdateRoomDirect: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_direct") + } /// Fail to update the room directory visibility - internal static let roomDetailsFailToUpdateRoomDirectoryVisibility = VectorL10n.tr("Vector", "room_details_fail_to_update_room_directory_visibility") + internal static var roomDetailsFailToUpdateRoomDirectoryVisibility: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_directory_visibility") + } /// Fail to update the room guest access - internal static let roomDetailsFailToUpdateRoomGuestAccess = VectorL10n.tr("Vector", "room_details_fail_to_update_room_guest_access") + internal static var roomDetailsFailToUpdateRoomGuestAccess: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_guest_access") + } /// Fail to update the join rule - internal static let roomDetailsFailToUpdateRoomJoinRule = VectorL10n.tr("Vector", "room_details_fail_to_update_room_join_rule") + internal static var roomDetailsFailToUpdateRoomJoinRule: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_join_rule") + } /// Fail to update the room name - internal static let roomDetailsFailToUpdateRoomName = VectorL10n.tr("Vector", "room_details_fail_to_update_room_name") + internal static var roomDetailsFailToUpdateRoomName: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_room_name") + } /// Fail to update the topic - internal static let roomDetailsFailToUpdateTopic = VectorL10n.tr("Vector", "room_details_fail_to_update_topic") + internal static var roomDetailsFailToUpdateTopic: String { + return VectorL10n.tr("Vector", "room_details_fail_to_update_topic") + } /// Favourite - internal static let roomDetailsFavouriteTag = VectorL10n.tr("Vector", "room_details_favourite_tag") + internal static var roomDetailsFavouriteTag: String { + return VectorL10n.tr("Vector", "room_details_favourite_tag") + } /// Files - internal static let roomDetailsFiles = VectorL10n.tr("Vector", "room_details_files") + internal static var roomDetailsFiles: String { + return VectorL10n.tr("Vector", "room_details_files") + } /// %@ is not a valid identifier for a community internal static func roomDetailsFlairInvalidIdPromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_details_flair_invalid_id_prompt_msg", p1) } /// Invalid format - internal static let roomDetailsFlairInvalidIdPromptTitle = VectorL10n.tr("Vector", "room_details_flair_invalid_id_prompt_title") + internal static var roomDetailsFlairInvalidIdPromptTitle: String { + return VectorL10n.tr("Vector", "room_details_flair_invalid_id_prompt_title") + } /// Show flair for communities - internal static let roomDetailsFlairSection = VectorL10n.tr("Vector", "room_details_flair_section") + internal static var roomDetailsFlairSection: String { + return VectorL10n.tr("Vector", "room_details_flair_section") + } /// Who can read history? - internal static let roomDetailsHistorySection = VectorL10n.tr("Vector", "room_details_history_section") + internal static var roomDetailsHistorySection: String { + return VectorL10n.tr("Vector", "room_details_history_section") + } /// Anyone - internal static let roomDetailsHistorySectionAnyone = VectorL10n.tr("Vector", "room_details_history_section_anyone") + internal static var roomDetailsHistorySectionAnyone: String { + return VectorL10n.tr("Vector", "room_details_history_section_anyone") + } /// Members only (since the point in time of selecting this option) - internal static let roomDetailsHistorySectionMembersOnly = VectorL10n.tr("Vector", "room_details_history_section_members_only") + internal static var roomDetailsHistorySectionMembersOnly: String { + return VectorL10n.tr("Vector", "room_details_history_section_members_only") + } /// Members only (since they were invited) - internal static let roomDetailsHistorySectionMembersOnlySinceInvited = VectorL10n.tr("Vector", "room_details_history_section_members_only_since_invited") + internal static var roomDetailsHistorySectionMembersOnlySinceInvited: String { + return VectorL10n.tr("Vector", "room_details_history_section_members_only_since_invited") + } /// Members only (since they joined) - internal static let roomDetailsHistorySectionMembersOnlySinceJoined = VectorL10n.tr("Vector", "room_details_history_section_members_only_since_joined") + internal static var roomDetailsHistorySectionMembersOnlySinceJoined: String { + return VectorL10n.tr("Vector", "room_details_history_section_members_only_since_joined") + } /// Changes to who can read history will only apply to future messages in this room. The visibility of existing history will be unchanged. - internal static let roomDetailsHistorySectionPromptMsg = VectorL10n.tr("Vector", "room_details_history_section_prompt_msg") + internal static var roomDetailsHistorySectionPromptMsg: String { + return VectorL10n.tr("Vector", "room_details_history_section_prompt_msg") + } /// Privacy warning - internal static let roomDetailsHistorySectionPromptTitle = VectorL10n.tr("Vector", "room_details_history_section_prompt_title") + internal static var roomDetailsHistorySectionPromptTitle: String { + return VectorL10n.tr("Vector", "room_details_history_section_prompt_title") + } /// Low priority - internal static let roomDetailsLowPriorityTag = VectorL10n.tr("Vector", "room_details_low_priority_tag") + internal static var roomDetailsLowPriorityTag: String { + return VectorL10n.tr("Vector", "room_details_low_priority_tag") + } /// Mute notifications - internal static let roomDetailsMuteNotifs = VectorL10n.tr("Vector", "room_details_mute_notifs") + internal static var roomDetailsMuteNotifs: String { + return VectorL10n.tr("Vector", "room_details_mute_notifs") + } /// Add new address - internal static let roomDetailsNewAddress = VectorL10n.tr("Vector", "room_details_new_address") + internal static var roomDetailsNewAddress: String { + return VectorL10n.tr("Vector", "room_details_new_address") + } /// Add new address (e.g. #foo%@) internal static func roomDetailsNewAddressPlaceholder(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_details_new_address_placeholder", p1) @@ -591,87 +1139,161 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "room_details_new_flair_placeholder", p1) } /// This room has no local addresses - internal static let roomDetailsNoLocalAddresses = VectorL10n.tr("Vector", "room_details_no_local_addresses") + internal static var roomDetailsNoLocalAddresses: String { + return VectorL10n.tr("Vector", "room_details_no_local_addresses") + } /// Members - internal static let roomDetailsPeople = VectorL10n.tr("Vector", "room_details_people") + internal static var roomDetailsPeople: String { + return VectorL10n.tr("Vector", "room_details_people") + } /// Room Photo - internal static let roomDetailsPhoto = VectorL10n.tr("Vector", "room_details_photo") + internal static var roomDetailsPhoto: String { + return VectorL10n.tr("Vector", "room_details_photo") + } /// Room Name - internal static let roomDetailsRoomName = VectorL10n.tr("Vector", "room_details_room_name") + internal static var roomDetailsRoomName: String { + return VectorL10n.tr("Vector", "room_details_room_name") + } /// Do you want to save changes? - internal static let roomDetailsSaveChangesPrompt = VectorL10n.tr("Vector", "room_details_save_changes_prompt") + internal static var roomDetailsSaveChangesPrompt: String { + return VectorL10n.tr("Vector", "room_details_save_changes_prompt") + } /// Set as Main Address - internal static let roomDetailsSetMainAddress = VectorL10n.tr("Vector", "room_details_set_main_address") + internal static var roomDetailsSetMainAddress: String { + return VectorL10n.tr("Vector", "room_details_set_main_address") + } /// Settings - internal static let roomDetailsSettings = VectorL10n.tr("Vector", "room_details_settings") + internal static var roomDetailsSettings: String { + return VectorL10n.tr("Vector", "room_details_settings") + } /// Room Details - internal static let roomDetailsTitle = VectorL10n.tr("Vector", "room_details_title") + internal static var roomDetailsTitle: String { + return VectorL10n.tr("Vector", "room_details_title") + } /// Topic - internal static let roomDetailsTopic = VectorL10n.tr("Vector", "room_details_topic") + internal static var roomDetailsTopic: String { + return VectorL10n.tr("Vector", "room_details_topic") + } /// Unset as Main Address - internal static let roomDetailsUnsetMainAddress = VectorL10n.tr("Vector", "room_details_unset_main_address") + internal static var roomDetailsUnsetMainAddress: String { + return VectorL10n.tr("Vector", "room_details_unset_main_address") + } /// No public rooms available - internal static let roomDirectoryNoPublicRoom = VectorL10n.tr("Vector", "room_directory_no_public_room") + internal static var roomDirectoryNoPublicRoom: String { + return VectorL10n.tr("Vector", "room_directory_no_public_room") + } /// You do not have permission to post to this room - internal static let roomDoNotHavePermissionToPost = VectorL10n.tr("Vector", "room_do_not_have_permission_to_post") + internal static var roomDoNotHavePermissionToPost: String { + return VectorL10n.tr("Vector", "room_do_not_have_permission_to_post") + } /// %@ does not exist internal static func roomDoesNotExist(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_does_not_exist", p1) } /// Reason for banning this user - internal static let roomEventActionBanPromptReason = VectorL10n.tr("Vector", "room_event_action_ban_prompt_reason") + internal static var roomEventActionBanPromptReason: String { + return VectorL10n.tr("Vector", "room_event_action_ban_prompt_reason") + } /// Cancel Download - internal static let roomEventActionCancelDownload = VectorL10n.tr("Vector", "room_event_action_cancel_download") + internal static var roomEventActionCancelDownload: String { + return VectorL10n.tr("Vector", "room_event_action_cancel_download") + } /// Cancel Send - internal static let roomEventActionCancelSend = VectorL10n.tr("Vector", "room_event_action_cancel_send") + internal static var roomEventActionCancelSend: String { + return VectorL10n.tr("Vector", "room_event_action_cancel_send") + } /// Copy - internal static let roomEventActionCopy = VectorL10n.tr("Vector", "room_event_action_copy") + internal static var roomEventActionCopy: String { + return VectorL10n.tr("Vector", "room_event_action_copy") + } /// Delete - internal static let roomEventActionDelete = VectorL10n.tr("Vector", "room_event_action_delete") + internal static var roomEventActionDelete: String { + return VectorL10n.tr("Vector", "room_event_action_delete") + } /// Reason for kicking this user - internal static let roomEventActionKickPromptReason = VectorL10n.tr("Vector", "room_event_action_kick_prompt_reason") + internal static var roomEventActionKickPromptReason: String { + return VectorL10n.tr("Vector", "room_event_action_kick_prompt_reason") + } /// More - internal static let roomEventActionMore = VectorL10n.tr("Vector", "room_event_action_more") + internal static var roomEventActionMore: String { + return VectorL10n.tr("Vector", "room_event_action_more") + } /// Permalink - internal static let roomEventActionPermalink = VectorL10n.tr("Vector", "room_event_action_permalink") + internal static var roomEventActionPermalink: String { + return VectorL10n.tr("Vector", "room_event_action_permalink") + } /// Quote - internal static let roomEventActionQuote = VectorL10n.tr("Vector", "room_event_action_quote") + internal static var roomEventActionQuote: String { + return VectorL10n.tr("Vector", "room_event_action_quote") + } /// Remove - internal static let roomEventActionRedact = VectorL10n.tr("Vector", "room_event_action_redact") + internal static var roomEventActionRedact: String { + return VectorL10n.tr("Vector", "room_event_action_redact") + } /// Report content - internal static let roomEventActionReport = VectorL10n.tr("Vector", "room_event_action_report") + internal static var roomEventActionReport: String { + return VectorL10n.tr("Vector", "room_event_action_report") + } /// Do you want to hide all messages from this user? - internal static let roomEventActionReportPromptIgnoreUser = VectorL10n.tr("Vector", "room_event_action_report_prompt_ignore_user") + internal static var roomEventActionReportPromptIgnoreUser: String { + return VectorL10n.tr("Vector", "room_event_action_report_prompt_ignore_user") + } /// Reason for reporting this content - internal static let roomEventActionReportPromptReason = VectorL10n.tr("Vector", "room_event_action_report_prompt_reason") + internal static var roomEventActionReportPromptReason: String { + return VectorL10n.tr("Vector", "room_event_action_report_prompt_reason") + } /// Resend - internal static let roomEventActionResend = VectorL10n.tr("Vector", "room_event_action_resend") + internal static var roomEventActionResend: String { + return VectorL10n.tr("Vector", "room_event_action_resend") + } /// Save - internal static let roomEventActionSave = VectorL10n.tr("Vector", "room_event_action_save") + internal static var roomEventActionSave: String { + return VectorL10n.tr("Vector", "room_event_action_save") + } /// Share - internal static let roomEventActionShare = VectorL10n.tr("Vector", "room_event_action_share") + internal static var roomEventActionShare: String { + return VectorL10n.tr("Vector", "room_event_action_share") + } /// View Decrypted Source - internal static let roomEventActionViewDecryptedSource = VectorL10n.tr("Vector", "room_event_action_view_decrypted_source") + internal static var roomEventActionViewDecryptedSource: String { + return VectorL10n.tr("Vector", "room_event_action_view_decrypted_source") + } /// Encryption Information - internal static let roomEventActionViewEncryption = VectorL10n.tr("Vector", "room_event_action_view_encryption") + internal static var roomEventActionViewEncryption: String { + return VectorL10n.tr("Vector", "room_event_action_view_encryption") + } /// View Source - internal static let roomEventActionViewSource = VectorL10n.tr("Vector", "room_event_action_view_source") + internal static var roomEventActionViewSource: String { + return VectorL10n.tr("Vector", "room_event_action_view_source") + } /// Failed to send - internal static let roomEventFailedToSend = VectorL10n.tr("Vector", "room_event_failed_to_send") + internal static var roomEventFailedToSend: String { + return VectorL10n.tr("Vector", "room_event_failed_to_send") + } /// Jump to first unread message - internal static let roomJumpToFirstUnread = VectorL10n.tr("Vector", "room_jump_to_first_unread") + internal static var roomJumpToFirstUnread: String { + return VectorL10n.tr("Vector", "room_jump_to_first_unread") + } /// %@, %@ & others are typing… internal static func roomManyUsersAreTyping(_ p1: String, _ p2: String) -> String { return VectorL10n.tr("Vector", "room_many_users_are_typing", p1, p2) } /// Send a message (unencrypted)… - internal static let roomMessagePlaceholder = VectorL10n.tr("Vector", "room_message_placeholder") + internal static var roomMessagePlaceholder: String { + return VectorL10n.tr("Vector", "room_message_placeholder") + } /// Send a reply (unencrypted)… - internal static let roomMessageReplyToPlaceholder = VectorL10n.tr("Vector", "room_message_reply_to_placeholder") + internal static var roomMessageReplyToPlaceholder: String { + return VectorL10n.tr("Vector", "room_message_reply_to_placeholder") + } /// Send a reply… - internal static let roomMessageReplyToShortPlaceholder = VectorL10n.tr("Vector", "room_message_reply_to_short_placeholder") + internal static var roomMessageReplyToShortPlaceholder: String { + return VectorL10n.tr("Vector", "room_message_reply_to_short_placeholder") + } /// Send a message… - internal static let roomMessageShortPlaceholder = VectorL10n.tr("Vector", "room_message_short_placeholder") + internal static var roomMessageShortPlaceholder: String { + return VectorL10n.tr("Vector", "room_message_short_placeholder") + } /// %d new message internal static func roomNewMessageNotification(_ p1: Int) -> String { return VectorL10n.tr("Vector", "room_new_message_notification", p1) @@ -681,7 +1303,9 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "room_new_messages_notification", p1) } /// Connectivity to the server has been lost. - internal static let roomOfflineNotification = VectorL10n.tr("Vector", "room_offline_notification") + internal static var roomOfflineNotification: String { + return VectorL10n.tr("Vector", "room_offline_notification") + } /// %@ is typing… internal static func roomOneUserIsTyping(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_one_user_is_typing", p1) @@ -691,171 +1315,309 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "room_ongoing_conference_call", p1, p2) } /// Close - internal static let roomOngoingConferenceCallClose = VectorL10n.tr("Vector", "room_ongoing_conference_call_close") + internal static var roomOngoingConferenceCallClose: String { + return VectorL10n.tr("Vector", "room_ongoing_conference_call_close") + } /// Ongoing conference call. Join as %@ or %@. %@ it. internal static func roomOngoingConferenceCallWithClose(_ p1: String, _ p2: String, _ p3: String) -> String { return VectorL10n.tr("Vector", "room_ongoing_conference_call_with_close", p1, p2, p3) } /// Ban from this room - internal static let roomParticipantsActionBan = VectorL10n.tr("Vector", "room_participants_action_ban") + internal static var roomParticipantsActionBan: String { + return VectorL10n.tr("Vector", "room_participants_action_ban") + } /// Hide all messages from this user - internal static let roomParticipantsActionIgnore = VectorL10n.tr("Vector", "room_participants_action_ignore") + internal static var roomParticipantsActionIgnore: String { + return VectorL10n.tr("Vector", "room_participants_action_ignore") + } /// Invite - internal static let roomParticipantsActionInvite = VectorL10n.tr("Vector", "room_participants_action_invite") + internal static var roomParticipantsActionInvite: String { + return VectorL10n.tr("Vector", "room_participants_action_invite") + } /// Leave this room - internal static let roomParticipantsActionLeave = VectorL10n.tr("Vector", "room_participants_action_leave") + internal static var roomParticipantsActionLeave: String { + return VectorL10n.tr("Vector", "room_participants_action_leave") + } /// Mention - internal static let roomParticipantsActionMention = VectorL10n.tr("Vector", "room_participants_action_mention") + internal static var roomParticipantsActionMention: String { + return VectorL10n.tr("Vector", "room_participants_action_mention") + } /// Remove from this room - internal static let roomParticipantsActionRemove = VectorL10n.tr("Vector", "room_participants_action_remove") + internal static var roomParticipantsActionRemove: String { + return VectorL10n.tr("Vector", "room_participants_action_remove") + } /// Admin tools - internal static let roomParticipantsActionSectionAdminTools = VectorL10n.tr("Vector", "room_participants_action_section_admin_tools") + internal static var roomParticipantsActionSectionAdminTools: String { + return VectorL10n.tr("Vector", "room_participants_action_section_admin_tools") + } /// Devices - internal static let roomParticipantsActionSectionDevices = VectorL10n.tr("Vector", "room_participants_action_section_devices") + internal static var roomParticipantsActionSectionDevices: String { + return VectorL10n.tr("Vector", "room_participants_action_section_devices") + } /// Direct chats - internal static let roomParticipantsActionSectionDirectChats = VectorL10n.tr("Vector", "room_participants_action_section_direct_chats") + internal static var roomParticipantsActionSectionDirectChats: String { + return VectorL10n.tr("Vector", "room_participants_action_section_direct_chats") + } /// Other - internal static let roomParticipantsActionSectionOther = VectorL10n.tr("Vector", "room_participants_action_section_other") + internal static var roomParticipantsActionSectionOther: String { + return VectorL10n.tr("Vector", "room_participants_action_section_other") + } /// Make admin - internal static let roomParticipantsActionSetAdmin = VectorL10n.tr("Vector", "room_participants_action_set_admin") + internal static var roomParticipantsActionSetAdmin: String { + return VectorL10n.tr("Vector", "room_participants_action_set_admin") + } /// Reset to normal user - internal static let roomParticipantsActionSetDefaultPowerLevel = VectorL10n.tr("Vector", "room_participants_action_set_default_power_level") + internal static var roomParticipantsActionSetDefaultPowerLevel: String { + return VectorL10n.tr("Vector", "room_participants_action_set_default_power_level") + } /// Make moderator - internal static let roomParticipantsActionSetModerator = VectorL10n.tr("Vector", "room_participants_action_set_moderator") + internal static var roomParticipantsActionSetModerator: String { + return VectorL10n.tr("Vector", "room_participants_action_set_moderator") + } /// Start new chat - internal static let roomParticipantsActionStartNewChat = VectorL10n.tr("Vector", "room_participants_action_start_new_chat") + internal static var roomParticipantsActionStartNewChat: String { + return VectorL10n.tr("Vector", "room_participants_action_start_new_chat") + } /// Start video call - internal static let roomParticipantsActionStartVideoCall = VectorL10n.tr("Vector", "room_participants_action_start_video_call") + internal static var roomParticipantsActionStartVideoCall: String { + return VectorL10n.tr("Vector", "room_participants_action_start_video_call") + } /// Start voice call - internal static let roomParticipantsActionStartVoiceCall = VectorL10n.tr("Vector", "room_participants_action_start_voice_call") + internal static var roomParticipantsActionStartVoiceCall: String { + return VectorL10n.tr("Vector", "room_participants_action_start_voice_call") + } /// Unban - internal static let roomParticipantsActionUnban = VectorL10n.tr("Vector", "room_participants_action_unban") + internal static var roomParticipantsActionUnban: String { + return VectorL10n.tr("Vector", "room_participants_action_unban") + } /// Show all messages from this user - internal static let roomParticipantsActionUnignore = VectorL10n.tr("Vector", "room_participants_action_unignore") + internal static var roomParticipantsActionUnignore: String { + return VectorL10n.tr("Vector", "room_participants_action_unignore") + } /// Add participant - internal static let roomParticipantsAddParticipant = VectorL10n.tr("Vector", "room_participants_add_participant") + internal static var roomParticipantsAddParticipant: String { + return VectorL10n.tr("Vector", "room_participants_add_participant") + } /// ago - internal static let roomParticipantsAgo = VectorL10n.tr("Vector", "room_participants_ago") + internal static var roomParticipantsAgo: String { + return VectorL10n.tr("Vector", "room_participants_ago") + } /// Filter room members - internal static let roomParticipantsFilterRoomMembers = VectorL10n.tr("Vector", "room_participants_filter_room_members") + internal static var roomParticipantsFilterRoomMembers: String { + return VectorL10n.tr("Vector", "room_participants_filter_room_members") + } /// Idle - internal static let roomParticipantsIdle = VectorL10n.tr("Vector", "room_participants_idle") + internal static var roomParticipantsIdle: String { + return VectorL10n.tr("Vector", "room_participants_idle") + } /// Search / invite by User ID, Name or email - internal static let roomParticipantsInviteAnotherUser = VectorL10n.tr("Vector", "room_participants_invite_another_user") + internal static var roomParticipantsInviteAnotherUser: String { + return VectorL10n.tr("Vector", "room_participants_invite_another_user") + } /// Malformed ID. Should be an email address or a Matrix ID like '@localpart:domain' - internal static let roomParticipantsInviteMalformedId = VectorL10n.tr("Vector", "room_participants_invite_malformed_id") + internal static var roomParticipantsInviteMalformedId: String { + return VectorL10n.tr("Vector", "room_participants_invite_malformed_id") + } /// Invite Error - internal static let roomParticipantsInviteMalformedIdTitle = VectorL10n.tr("Vector", "room_participants_invite_malformed_id_title") + internal static var roomParticipantsInviteMalformedIdTitle: String { + return VectorL10n.tr("Vector", "room_participants_invite_malformed_id_title") + } /// Are you sure you want to invite %@ to this chat? internal static func roomParticipantsInvitePromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_participants_invite_prompt_msg", p1) } /// Confirmation - internal static let roomParticipantsInvitePromptTitle = VectorL10n.tr("Vector", "room_participants_invite_prompt_title") + internal static var roomParticipantsInvitePromptTitle: String { + return VectorL10n.tr("Vector", "room_participants_invite_prompt_title") + } /// INVITED - internal static let roomParticipantsInvitedSection = VectorL10n.tr("Vector", "room_participants_invited_section") + internal static var roomParticipantsInvitedSection: String { + return VectorL10n.tr("Vector", "room_participants_invited_section") + } /// Are you sure you want to leave the room? - internal static let roomParticipantsLeavePromptMsg = VectorL10n.tr("Vector", "room_participants_leave_prompt_msg") + internal static var roomParticipantsLeavePromptMsg: String { + return VectorL10n.tr("Vector", "room_participants_leave_prompt_msg") + } /// Leave room - internal static let roomParticipantsLeavePromptTitle = VectorL10n.tr("Vector", "room_participants_leave_prompt_title") + internal static var roomParticipantsLeavePromptTitle: String { + return VectorL10n.tr("Vector", "room_participants_leave_prompt_title") + } /// %d participants internal static func roomParticipantsMultiParticipants(_ p1: Int) -> String { return VectorL10n.tr("Vector", "room_participants_multi_participants", p1) } /// now - internal static let roomParticipantsNow = VectorL10n.tr("Vector", "room_participants_now") + internal static var roomParticipantsNow: String { + return VectorL10n.tr("Vector", "room_participants_now") + } /// Offline - internal static let roomParticipantsOffline = VectorL10n.tr("Vector", "room_participants_offline") + internal static var roomParticipantsOffline: String { + return VectorL10n.tr("Vector", "room_participants_offline") + } /// 1 participant - internal static let roomParticipantsOneParticipant = VectorL10n.tr("Vector", "room_participants_one_participant") + internal static var roomParticipantsOneParticipant: String { + return VectorL10n.tr("Vector", "room_participants_one_participant") + } /// Online - internal static let roomParticipantsOnline = VectorL10n.tr("Vector", "room_participants_online") + internal static var roomParticipantsOnline: String { + return VectorL10n.tr("Vector", "room_participants_online") + } /// Are you sure you want to remove %@ from this chat? internal static func roomParticipantsRemovePromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_participants_remove_prompt_msg", p1) } /// Confirmation - internal static let roomParticipantsRemovePromptTitle = VectorL10n.tr("Vector", "room_participants_remove_prompt_title") + internal static var roomParticipantsRemovePromptTitle: String { + return VectorL10n.tr("Vector", "room_participants_remove_prompt_title") + } /// Remove third-party invite is not supported yet until the api exists - internal static let roomParticipantsRemoveThirdPartyInviteMsg = VectorL10n.tr("Vector", "room_participants_remove_third_party_invite_msg") + internal static var roomParticipantsRemoveThirdPartyInviteMsg: String { + return VectorL10n.tr("Vector", "room_participants_remove_third_party_invite_msg") + } /// Participants - internal static let roomParticipantsTitle = VectorL10n.tr("Vector", "room_participants_title") + internal static var roomParticipantsTitle: String { + return VectorL10n.tr("Vector", "room_participants_title") + } /// Unknown - internal static let roomParticipantsUnknown = VectorL10n.tr("Vector", "room_participants_unknown") + internal static var roomParticipantsUnknown: String { + return VectorL10n.tr("Vector", "room_participants_unknown") + } /// This room is a continuation of another conversation. - internal static let roomPredecessorInformation = VectorL10n.tr("Vector", "room_predecessor_information") + internal static var roomPredecessorInformation: String { + return VectorL10n.tr("Vector", "room_predecessor_information") + } /// Click here to see older messages. - internal static let roomPredecessorLink = VectorL10n.tr("Vector", "room_predecessor_link") + internal static var roomPredecessorLink: String { + return VectorL10n.tr("Vector", "room_predecessor_link") + } /// You have been invited to join this room by %@ internal static func roomPreviewInvitationFormat(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_preview_invitation_format", p1) } /// This is a preview of this room. Room interactions have been disabled. - internal static let roomPreviewSubtitle = VectorL10n.tr("Vector", "room_preview_subtitle") + internal static var roomPreviewSubtitle: String { + return VectorL10n.tr("Vector", "room_preview_subtitle") + } /// You are trying to access %@. Would you like to join in order to participate in the discussion? internal static func roomPreviewTryJoinAnUnknownRoom(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_preview_try_join_an_unknown_room", p1) } /// a room - internal static let roomPreviewTryJoinAnUnknownRoomDefault = VectorL10n.tr("Vector", "room_preview_try_join_an_unknown_room_default") + internal static var roomPreviewTryJoinAnUnknownRoomDefault: String { + return VectorL10n.tr("Vector", "room_preview_try_join_an_unknown_room_default") + } /// This invitation was sent to %@, which is not associated with this account. You may wish to login with a different account, or add this email to your this account. internal static func roomPreviewUnlinkedEmailWarning(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_preview_unlinked_email_warning", p1) } /// cancel all - internal static let roomPromptCancel = VectorL10n.tr("Vector", "room_prompt_cancel") + internal static var roomPromptCancel: String { + return VectorL10n.tr("Vector", "room_prompt_cancel") + } /// Resend all - internal static let roomPromptResend = VectorL10n.tr("Vector", "room_prompt_resend") + internal static var roomPromptResend: String { + return VectorL10n.tr("Vector", "room_prompt_resend") + } /// ROOMS - internal static let roomRecentsConversationsSection = VectorL10n.tr("Vector", "room_recents_conversations_section") + internal static var roomRecentsConversationsSection: String { + return VectorL10n.tr("Vector", "room_recents_conversations_section") + } /// Create room - internal static let roomRecentsCreateEmptyRoom = VectorL10n.tr("Vector", "room_recents_create_empty_room") + internal static var roomRecentsCreateEmptyRoom: String { + return VectorL10n.tr("Vector", "room_recents_create_empty_room") + } /// ROOM DIRECTORY - internal static let roomRecentsDirectorySection = VectorL10n.tr("Vector", "room_recents_directory_section") + internal static var roomRecentsDirectorySection: String { + return VectorL10n.tr("Vector", "room_recents_directory_section") + } /// Network - internal static let roomRecentsDirectorySectionNetwork = VectorL10n.tr("Vector", "room_recents_directory_section_network") + internal static var roomRecentsDirectorySectionNetwork: String { + return VectorL10n.tr("Vector", "room_recents_directory_section_network") + } /// FAVOURITES - internal static let roomRecentsFavouritesSection = VectorL10n.tr("Vector", "room_recents_favourites_section") + internal static var roomRecentsFavouritesSection: String { + return VectorL10n.tr("Vector", "room_recents_favourites_section") + } /// INVITES - internal static let roomRecentsInvitesSection = VectorL10n.tr("Vector", "room_recents_invites_section") + internal static var roomRecentsInvitesSection: String { + return VectorL10n.tr("Vector", "room_recents_invites_section") + } /// Join room - internal static let roomRecentsJoinRoom = VectorL10n.tr("Vector", "room_recents_join_room") + internal static var roomRecentsJoinRoom: String { + return VectorL10n.tr("Vector", "room_recents_join_room") + } /// Type a room id or a room alias - internal static let roomRecentsJoinRoomPrompt = VectorL10n.tr("Vector", "room_recents_join_room_prompt") + internal static var roomRecentsJoinRoomPrompt: String { + return VectorL10n.tr("Vector", "room_recents_join_room_prompt") + } /// Join a room - internal static let roomRecentsJoinRoomTitle = VectorL10n.tr("Vector", "room_recents_join_room_title") + internal static var roomRecentsJoinRoomTitle: String { + return VectorL10n.tr("Vector", "room_recents_join_room_title") + } /// LOW PRIORITY - internal static let roomRecentsLowPrioritySection = VectorL10n.tr("Vector", "room_recents_low_priority_section") + internal static var roomRecentsLowPrioritySection: String { + return VectorL10n.tr("Vector", "room_recents_low_priority_section") + } /// No rooms - internal static let roomRecentsNoConversation = VectorL10n.tr("Vector", "room_recents_no_conversation") + internal static var roomRecentsNoConversation: String { + return VectorL10n.tr("Vector", "room_recents_no_conversation") + } /// PEOPLE - internal static let roomRecentsPeopleSection = VectorL10n.tr("Vector", "room_recents_people_section") + internal static var roomRecentsPeopleSection: String { + return VectorL10n.tr("Vector", "room_recents_people_section") + } /// SYSTEM ALERTS - internal static let roomRecentsServerNoticeSection = VectorL10n.tr("Vector", "room_recents_server_notice_section") + internal static var roomRecentsServerNoticeSection: String { + return VectorL10n.tr("Vector", "room_recents_server_notice_section") + } /// Start chat - internal static let roomRecentsStartChatWith = VectorL10n.tr("Vector", "room_recents_start_chat_with") + internal static var roomRecentsStartChatWith: String { + return VectorL10n.tr("Vector", "room_recents_start_chat_with") + } /// This room has been replaced and is no longer active. - internal static let roomReplacementInformation = VectorL10n.tr("Vector", "room_replacement_information") + internal static var roomReplacementInformation: String { + return VectorL10n.tr("Vector", "room_replacement_information") + } /// The conversation continues here. - internal static let roomReplacementLink = VectorL10n.tr("Vector", "room_replacement_link") + internal static var roomReplacementLink: String { + return VectorL10n.tr("Vector", "room_replacement_link") + } /// Resend unsent messages - internal static let roomResendUnsentMessages = VectorL10n.tr("Vector", "room_resend_unsent_messages") + internal static var roomResendUnsentMessages: String { + return VectorL10n.tr("Vector", "room_resend_unsent_messages") + } /// Please - internal static let roomResourceLimitExceededMessageContact1 = VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_1") + internal static var roomResourceLimitExceededMessageContact1: String { + return VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_1") + } /// contact your service administrator - internal static let roomResourceLimitExceededMessageContact2Link = VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_2_link") + internal static var roomResourceLimitExceededMessageContact2Link: String { + return VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_2_link") + } /// to continue using this service. - internal static let roomResourceLimitExceededMessageContact3 = VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_3") + internal static var roomResourceLimitExceededMessageContact3: String { + return VectorL10n.tr("Vector", "room_resource_limit_exceeded_message_contact_3") + } /// This homeserver has exceeded one of its resource limits so - internal static let roomResourceUsageLimitReachedMessage1Default = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_1_default") + internal static var roomResourceUsageLimitReachedMessage1Default: String { + return VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_1_default") + } /// This homeserver has hit its Monthly Active User limit so - internal static let roomResourceUsageLimitReachedMessage1MonthlyActiveUser = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_1_monthly_active_user") + internal static var roomResourceUsageLimitReachedMessage1MonthlyActiveUser: String { + return VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_1_monthly_active_user") + } /// some users will not be able to log in. - internal static let roomResourceUsageLimitReachedMessage2 = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_2") + internal static var roomResourceUsageLimitReachedMessage2: String { + return VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_2") + } /// to get this limit increased. - internal static let roomResourceUsageLimitReachedMessageContact3 = VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_contact_3") + internal static var roomResourceUsageLimitReachedMessageContact3: String { + return VectorL10n.tr("Vector", "room_resource_usage_limit_reached_message_contact_3") + } /// Invite members - internal static let roomTitleInviteMembers = VectorL10n.tr("Vector", "room_title_invite_members") + internal static var roomTitleInviteMembers: String { + return VectorL10n.tr("Vector", "room_title_invite_members") + } /// %@ members internal static func roomTitleMembers(_ p1: String) -> String { return VectorL10n.tr("Vector", "room_title_members", p1) @@ -865,13 +1627,17 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "room_title_multiple_active_members", p1, p2) } /// New room - internal static let roomTitleNewRoom = VectorL10n.tr("Vector", "room_title_new_room") + internal static var roomTitleNewRoom: String { + return VectorL10n.tr("Vector", "room_title_new_room") + } /// %@/%@ active member internal static func roomTitleOneActiveMember(_ p1: String, _ p2: String) -> String { return VectorL10n.tr("Vector", "room_title_one_active_member", p1, p2) } /// 1 member - internal static let roomTitleOneMember = VectorL10n.tr("Vector", "room_title_one_member") + internal static var roomTitleOneMember: String { + return VectorL10n.tr("Vector", "room_title_one_member") + } /// %@ & %@ are typing… internal static func roomTwoUsersAreTyping(_ p1: String, _ p2: String) -> String { return VectorL10n.tr("Vector", "room_two_users_are_typing", p1, p2) @@ -885,45 +1651,81 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "room_unsent_messages_unknown_devices_notification", p1, p2) } /// End-to-end encryption is in beta and may not be reliable.\n\nYou should not yet trust it to secure data.\n\nDevices will not yet be able to decrypt history from before they joined the room.\n\nEncrypted messages will not be visible on clients that do not yet implement encryption. - internal static let roomWarningAboutEncryption = VectorL10n.tr("Vector", "room_warning_about_encryption") + internal static var roomWarningAboutEncryption: String { + return VectorL10n.tr("Vector", "room_warning_about_encryption") + } /// Save - internal static let save = VectorL10n.tr("Vector", "save") + internal static var save: String { + return VectorL10n.tr("Vector", "save") + } /// Search - internal static let searchDefaultPlaceholder = VectorL10n.tr("Vector", "search_default_placeholder") + internal static var searchDefaultPlaceholder: String { + return VectorL10n.tr("Vector", "search_default_placeholder") + } /// Files - internal static let searchFiles = VectorL10n.tr("Vector", "search_files") + internal static var searchFiles: String { + return VectorL10n.tr("Vector", "search_files") + } /// Searching… - internal static let searchInProgress = VectorL10n.tr("Vector", "search_in_progress") + internal static var searchInProgress: String { + return VectorL10n.tr("Vector", "search_in_progress") + } /// Messages - internal static let searchMessages = VectorL10n.tr("Vector", "search_messages") + internal static var searchMessages: String { + return VectorL10n.tr("Vector", "search_messages") + } /// No results - internal static let searchNoResult = VectorL10n.tr("Vector", "search_no_result") + internal static var searchNoResult: String { + return VectorL10n.tr("Vector", "search_no_result") + } /// People - internal static let searchPeople = VectorL10n.tr("Vector", "search_people") + internal static var searchPeople: String { + return VectorL10n.tr("Vector", "search_people") + } /// Search by User ID, Name or email - internal static let searchPeoplePlaceholder = VectorL10n.tr("Vector", "search_people_placeholder") + internal static var searchPeoplePlaceholder: String { + return VectorL10n.tr("Vector", "search_people_placeholder") + } /// Rooms - internal static let searchRooms = VectorL10n.tr("Vector", "search_rooms") + internal static var searchRooms: String { + return VectorL10n.tr("Vector", "search_rooms") + } /// Send to %@ internal static func sendTo(_ p1: String) -> String { return VectorL10n.tr("Vector", "send_to", p1) } /// Sending - internal static let sending = VectorL10n.tr("Vector", "sending") + internal static var sending: String { + return VectorL10n.tr("Vector", "sending") + } /// Add email address - internal static let settingsAddEmailAddress = VectorL10n.tr("Vector", "settings_add_email_address") + internal static var settingsAddEmailAddress: String { + return VectorL10n.tr("Vector", "settings_add_email_address") + } /// Add phone number - internal static let settingsAddPhoneNumber = VectorL10n.tr("Vector", "settings_add_phone_number") + internal static var settingsAddPhoneNumber: String { + return VectorL10n.tr("Vector", "settings_add_phone_number") + } /// ADVANCED - internal static let settingsAdvanced = VectorL10n.tr("Vector", "settings_advanced") + internal static var settingsAdvanced: String { + return VectorL10n.tr("Vector", "settings_advanced") + } /// Receive incoming calls on your lock screen. See your Riot calls in the system's call history. If iCloud is enabled, this call history will be shared with Apple. - internal static let settingsCallkitInfo = VectorL10n.tr("Vector", "settings_callkit_info") + internal static var settingsCallkitInfo: String { + return VectorL10n.tr("Vector", "settings_callkit_info") + } /// CALLS - internal static let settingsCallsSettings = VectorL10n.tr("Vector", "settings_calls_settings") + internal static var settingsCallsSettings: String { + return VectorL10n.tr("Vector", "settings_calls_settings") + } /// Change password - internal static let settingsChangePassword = VectorL10n.tr("Vector", "settings_change_password") + internal static var settingsChangePassword: String { + return VectorL10n.tr("Vector", "settings_change_password") + } /// Clear cache - internal static let settingsClearCache = VectorL10n.tr("Vector", "settings_clear_cache") + internal static var settingsClearCache: String { + return VectorL10n.tr("Vector", "settings_clear_cache") + } /// Home server is %@ internal static func settingsConfigHomeServer(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_config_home_server", p1) @@ -933,89 +1735,165 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "settings_config_identity_server", p1) } /// No build info - internal static let settingsConfigNoBuildInfo = VectorL10n.tr("Vector", "settings_config_no_build_info") + internal static var settingsConfigNoBuildInfo: String { + return VectorL10n.tr("Vector", "settings_config_no_build_info") + } /// Logged in as %@ internal static func settingsConfigUserId(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_config_user_id", p1) } /// confirm password - internal static let settingsConfirmPassword = VectorL10n.tr("Vector", "settings_confirm_password") + internal static var settingsConfirmPassword: String { + return VectorL10n.tr("Vector", "settings_confirm_password") + } /// LOCAL CONTACTS - internal static let settingsContacts = VectorL10n.tr("Vector", "settings_contacts") + internal static var settingsContacts: String { + return VectorL10n.tr("Vector", "settings_contacts") + } /// Use emails and phone numbers to discover users - internal static let settingsContactsDiscoverMatrixUsers = VectorL10n.tr("Vector", "settings_contacts_discover_matrix_users") + internal static var settingsContactsDiscoverMatrixUsers: String { + return VectorL10n.tr("Vector", "settings_contacts_discover_matrix_users") + } /// Phonebook country - internal static let settingsContactsPhonebookCountry = VectorL10n.tr("Vector", "settings_contacts_phonebook_country") + internal static var settingsContactsPhonebookCountry: String { + return VectorL10n.tr("Vector", "settings_contacts_phonebook_country") + } /// Copyright - internal static let settingsCopyright = VectorL10n.tr("Vector", "settings_copyright") + internal static var settingsCopyright: String { + return VectorL10n.tr("Vector", "settings_copyright") + } /// https://riot.im/copyright - internal static let settingsCopyrightUrl = VectorL10n.tr("Vector", "settings_copyright_url") + internal static var settingsCopyrightUrl: String { + return VectorL10n.tr("Vector", "settings_copyright_url") + } /// Encrypt to verified devices only - internal static let settingsCryptoBlacklistUnverifiedDevices = VectorL10n.tr("Vector", "settings_crypto_blacklist_unverified_devices") + internal static var settingsCryptoBlacklistUnverifiedDevices: String { + return VectorL10n.tr("Vector", "settings_crypto_blacklist_unverified_devices") + } /// \nDevice ID: - internal static let settingsCryptoDeviceId = VectorL10n.tr("Vector", "settings_crypto_device_id") + internal static var settingsCryptoDeviceId: String { + return VectorL10n.tr("Vector", "settings_crypto_device_id") + } /// \nDevice key: - internal static let settingsCryptoDeviceKey = VectorL10n.tr("Vector", "settings_crypto_device_key") + internal static var settingsCryptoDeviceKey: String { + return VectorL10n.tr("Vector", "settings_crypto_device_key") + } /// Device name: - internal static let settingsCryptoDeviceName = VectorL10n.tr("Vector", "settings_crypto_device_name") + internal static var settingsCryptoDeviceName: String { + return VectorL10n.tr("Vector", "settings_crypto_device_name") + } /// Export keys - internal static let settingsCryptoExport = VectorL10n.tr("Vector", "settings_crypto_export") + internal static var settingsCryptoExport: String { + return VectorL10n.tr("Vector", "settings_crypto_export") + } /// CRYPTOGRAPHY - internal static let settingsCryptography = VectorL10n.tr("Vector", "settings_cryptography") + internal static var settingsCryptography: String { + return VectorL10n.tr("Vector", "settings_cryptography") + } /// DEACTIVATE ACCOUNT - internal static let settingsDeactivateAccount = VectorL10n.tr("Vector", "settings_deactivate_account") + internal static var settingsDeactivateAccount: String { + return VectorL10n.tr("Vector", "settings_deactivate_account") + } /// Deactivate my account - internal static let settingsDeactivateMyAccount = VectorL10n.tr("Vector", "settings_deactivate_my_account") + internal static var settingsDeactivateMyAccount: String { + return VectorL10n.tr("Vector", "settings_deactivate_my_account") + } /// DEVICES - internal static let settingsDevices = VectorL10n.tr("Vector", "settings_devices") + internal static var settingsDevices: String { + return VectorL10n.tr("Vector", "settings_devices") + } /// Display Name - internal static let settingsDisplayName = VectorL10n.tr("Vector", "settings_display_name") + internal static var settingsDisplayName: String { + return VectorL10n.tr("Vector", "settings_display_name") + } /// Email - internal static let settingsEmailAddress = VectorL10n.tr("Vector", "settings_email_address") + internal static var settingsEmailAddress: String { + return VectorL10n.tr("Vector", "settings_email_address") + } /// Enter your email address - internal static let settingsEmailAddressPlaceholder = VectorL10n.tr("Vector", "settings_email_address_placeholder") + internal static var settingsEmailAddressPlaceholder: String { + return VectorL10n.tr("Vector", "settings_email_address_placeholder") + } /// Integrated calling - internal static let settingsEnableCallkit = VectorL10n.tr("Vector", "settings_enable_callkit") + internal static var settingsEnableCallkit: String { + return VectorL10n.tr("Vector", "settings_enable_callkit") + } /// Notifications on this device - internal static let settingsEnablePushNotif = VectorL10n.tr("Vector", "settings_enable_push_notif") + internal static var settingsEnablePushNotif: String { + return VectorL10n.tr("Vector", "settings_enable_push_notif") + } /// Rage shake to report bug - internal static let settingsEnableRageshake = VectorL10n.tr("Vector", "settings_enable_rageshake") + internal static var settingsEnableRageshake: String { + return VectorL10n.tr("Vector", "settings_enable_rageshake") + } /// Fail to update password - internal static let settingsFailToUpdatePassword = VectorL10n.tr("Vector", "settings_fail_to_update_password") + internal static var settingsFailToUpdatePassword: String { + return VectorL10n.tr("Vector", "settings_fail_to_update_password") + } /// Fail to update profile - internal static let settingsFailToUpdateProfile = VectorL10n.tr("Vector", "settings_fail_to_update_profile") + internal static var settingsFailToUpdateProfile: String { + return VectorL10n.tr("Vector", "settings_fail_to_update_profile") + } /// First Name - internal static let settingsFirstName = VectorL10n.tr("Vector", "settings_first_name") + internal static var settingsFirstName: String { + return VectorL10n.tr("Vector", "settings_first_name") + } /// Show flair where allowed - internal static let settingsFlair = VectorL10n.tr("Vector", "settings_flair") + internal static var settingsFlair: String { + return VectorL10n.tr("Vector", "settings_flair") + } /// Global notification settings are available on your %@ web client internal static func settingsGlobalSettingsInfo(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_global_settings_info", p1) } /// IGNORED USERS - internal static let settingsIgnoredUsers = VectorL10n.tr("Vector", "settings_ignored_users") + internal static var settingsIgnoredUsers: String { + return VectorL10n.tr("Vector", "settings_ignored_users") + } /// LABS - internal static let settingsLabs = VectorL10n.tr("Vector", "settings_labs") + internal static var settingsLabs: String { + return VectorL10n.tr("Vector", "settings_labs") + } /// Create conference calls with jitsi - internal static let settingsLabsCreateConferenceWithJitsi = VectorL10n.tr("Vector", "settings_labs_create_conference_with_jitsi") + internal static var settingsLabsCreateConferenceWithJitsi: String { + return VectorL10n.tr("Vector", "settings_labs_create_conference_with_jitsi") + } /// End-to-End Encryption - internal static let settingsLabsE2eEncryption = VectorL10n.tr("Vector", "settings_labs_e2e_encryption") + internal static var settingsLabsE2eEncryption: String { + return VectorL10n.tr("Vector", "settings_labs_e2e_encryption") + } /// To finish setting up encryption you must log in again. - internal static let settingsLabsE2eEncryptionPromptMessage = VectorL10n.tr("Vector", "settings_labs_e2e_encryption_prompt_message") + internal static var settingsLabsE2eEncryptionPromptMessage: String { + return VectorL10n.tr("Vector", "settings_labs_e2e_encryption_prompt_message") + } /// Lazy load rooms members - internal static let settingsLabsRoomMembersLazyLoading = VectorL10n.tr("Vector", "settings_labs_room_members_lazy_loading") + internal static var settingsLabsRoomMembersLazyLoading: String { + return VectorL10n.tr("Vector", "settings_labs_room_members_lazy_loading") + } /// Your homeserver does not support lazy loading of room members yet. Try later. - internal static let settingsLabsRoomMembersLazyLoadingErrorMessage = VectorL10n.tr("Vector", "settings_labs_room_members_lazy_loading_error_message") + internal static var settingsLabsRoomMembersLazyLoadingErrorMessage: String { + return VectorL10n.tr("Vector", "settings_labs_room_members_lazy_loading_error_message") + } /// Mark all messages as read - internal static let settingsMarkAllAsRead = VectorL10n.tr("Vector", "settings_mark_all_as_read") + internal static var settingsMarkAllAsRead: String { + return VectorL10n.tr("Vector", "settings_mark_all_as_read") + } /// new password - internal static let settingsNewPassword = VectorL10n.tr("Vector", "settings_new_password") + internal static var settingsNewPassword: String { + return VectorL10n.tr("Vector", "settings_new_password") + } /// Night Mode - internal static let settingsNightMode = VectorL10n.tr("Vector", "settings_night_mode") + internal static var settingsNightMode: String { + return VectorL10n.tr("Vector", "settings_night_mode") + } /// NOTIFICATION SETTINGS - internal static let settingsNotificationsSettings = VectorL10n.tr("Vector", "settings_notifications_settings") + internal static var settingsNotificationsSettings: String { + return VectorL10n.tr("Vector", "settings_notifications_settings") + } /// old password - internal static let settingsOldPassword = VectorL10n.tr("Vector", "settings_old_password") + internal static var settingsOldPassword: String { + return VectorL10n.tr("Vector", "settings_old_password") + } /// Olm Version %@ internal static func settingsOlmVersion(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_olm_version", p1) @@ -1025,21 +1903,37 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "settings_on_denied_notification", p1) } /// OTHER - internal static let settingsOther = VectorL10n.tr("Vector", "settings_other") + internal static var settingsOther: String { + return VectorL10n.tr("Vector", "settings_other") + } /// Your password has been updated - internal static let settingsPasswordUpdated = VectorL10n.tr("Vector", "settings_password_updated") + internal static var settingsPasswordUpdated: String { + return VectorL10n.tr("Vector", "settings_password_updated") + } /// Phone - internal static let settingsPhoneNumber = VectorL10n.tr("Vector", "settings_phone_number") + internal static var settingsPhoneNumber: String { + return VectorL10n.tr("Vector", "settings_phone_number") + } /// Pin rooms with missed notifications - internal static let settingsPinRoomsWithMissedNotif = VectorL10n.tr("Vector", "settings_pin_rooms_with_missed_notif") + internal static var settingsPinRoomsWithMissedNotif: String { + return VectorL10n.tr("Vector", "settings_pin_rooms_with_missed_notif") + } /// Pin rooms with unread messages - internal static let settingsPinRoomsWithUnread = VectorL10n.tr("Vector", "settings_pin_rooms_with_unread") + internal static var settingsPinRoomsWithUnread: String { + return VectorL10n.tr("Vector", "settings_pin_rooms_with_unread") + } /// Privacy Policy - internal static let settingsPrivacyPolicy = VectorL10n.tr("Vector", "settings_privacy_policy") + internal static var settingsPrivacyPolicy: String { + return VectorL10n.tr("Vector", "settings_privacy_policy") + } /// https://riot.im/privacy - internal static let settingsPrivacyPolicyUrl = VectorL10n.tr("Vector", "settings_privacy_policy_url") + internal static var settingsPrivacyPolicyUrl: String { + return VectorL10n.tr("Vector", "settings_privacy_policy_url") + } /// Profile Picture - internal static let settingsProfilePicture = VectorL10n.tr("Vector", "settings_profile_picture") + internal static var settingsProfilePicture: String { + return VectorL10n.tr("Vector", "settings_profile_picture") + } /// Are you sure you want to remove the email address %@? internal static func settingsRemoveEmailPromptMsg(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_remove_email_prompt_msg", p1) @@ -1049,131 +1943,245 @@ internal enum VectorL10n { return VectorL10n.tr("Vector", "settings_remove_phone_prompt_msg", p1) } /// Confirmation - internal static let settingsRemovePromptTitle = VectorL10n.tr("Vector", "settings_remove_prompt_title") + internal static var settingsRemovePromptTitle: String { + return VectorL10n.tr("Vector", "settings_remove_prompt_title") + } /// Report bug - internal static let settingsReportBug = VectorL10n.tr("Vector", "settings_report_bug") + internal static var settingsReportBug: String { + return VectorL10n.tr("Vector", "settings_report_bug") + } /// Send anon crash & usage data - internal static let settingsSendCrashReport = VectorL10n.tr("Vector", "settings_send_crash_report") + internal static var settingsSendCrashReport: String { + return VectorL10n.tr("Vector", "settings_send_crash_report") + } /// Show decrypted content - internal static let settingsShowDecryptedContent = VectorL10n.tr("Vector", "settings_show_decrypted_content") + internal static var settingsShowDecryptedContent: String { + return VectorL10n.tr("Vector", "settings_show_decrypted_content") + } /// Sign Out - internal static let settingsSignOut = VectorL10n.tr("Vector", "settings_sign_out") + internal static var settingsSignOut: String { + return VectorL10n.tr("Vector", "settings_sign_out") + } /// Are you sure? - internal static let settingsSignOutConfirmation = VectorL10n.tr("Vector", "settings_sign_out_confirmation") + internal static var settingsSignOutConfirmation: String { + return VectorL10n.tr("Vector", "settings_sign_out_confirmation") + } /// You will lose your end-to-end encryption keys. That means you will no longer be able to read old messages in encrypted rooms on this device. - internal static let settingsSignOutE2eWarn = VectorL10n.tr("Vector", "settings_sign_out_e2e_warn") + internal static var settingsSignOutE2eWarn: String { + return VectorL10n.tr("Vector", "settings_sign_out_e2e_warn") + } /// Surname - internal static let settingsSurname = VectorL10n.tr("Vector", "settings_surname") + internal static var settingsSurname: String { + return VectorL10n.tr("Vector", "settings_surname") + } /// Terms & Conditions - internal static let settingsTermConditions = VectorL10n.tr("Vector", "settings_term_conditions") + internal static var settingsTermConditions: String { + return VectorL10n.tr("Vector", "settings_term_conditions") + } /// https://riot.im/tac_apple - internal static let settingsTermConditionsUrl = VectorL10n.tr("Vector", "settings_term_conditions_url") + internal static var settingsTermConditionsUrl: String { + return VectorL10n.tr("Vector", "settings_term_conditions_url") + } /// Third-party Notices - internal static let settingsThirdPartyNotices = VectorL10n.tr("Vector", "settings_third_party_notices") + internal static var settingsThirdPartyNotices: String { + return VectorL10n.tr("Vector", "settings_third_party_notices") + } /// Settings - internal static let settingsTitle = VectorL10n.tr("Vector", "settings_title") + internal static var settingsTitle: String { + return VectorL10n.tr("Vector", "settings_title") + } /// Language - internal static let settingsUiLanguage = VectorL10n.tr("Vector", "settings_ui_language") + internal static var settingsUiLanguage: String { + return VectorL10n.tr("Vector", "settings_ui_language") + } /// Theme - internal static let settingsUiTheme = VectorL10n.tr("Vector", "settings_ui_theme") + internal static var settingsUiTheme: String { + return VectorL10n.tr("Vector", "settings_ui_theme") + } /// Auto - internal static let settingsUiThemeAuto = VectorL10n.tr("Vector", "settings_ui_theme_auto") + internal static var settingsUiThemeAuto: String { + return VectorL10n.tr("Vector", "settings_ui_theme_auto") + } /// Black - internal static let settingsUiThemeBlack = VectorL10n.tr("Vector", "settings_ui_theme_black") + internal static var settingsUiThemeBlack: String { + return VectorL10n.tr("Vector", "settings_ui_theme_black") + } /// Dark - internal static let settingsUiThemeDark = VectorL10n.tr("Vector", "settings_ui_theme_dark") + internal static var settingsUiThemeDark: String { + return VectorL10n.tr("Vector", "settings_ui_theme_dark") + } /// Light - internal static let settingsUiThemeLight = VectorL10n.tr("Vector", "settings_ui_theme_light") + internal static var settingsUiThemeLight: String { + return VectorL10n.tr("Vector", "settings_ui_theme_light") + } /// "Auto" uses your device "Invert Colours" settings - internal static let settingsUiThemePickerMessage = VectorL10n.tr("Vector", "settings_ui_theme_picker_message") + internal static var settingsUiThemePickerMessage: String { + return VectorL10n.tr("Vector", "settings_ui_theme_picker_message") + } /// Select a theme - internal static let settingsUiThemePickerTitle = VectorL10n.tr("Vector", "settings_ui_theme_picker_title") + internal static var settingsUiThemePickerTitle: String { + return VectorL10n.tr("Vector", "settings_ui_theme_picker_title") + } /// Show all messages from %@? internal static func settingsUnignoreUser(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_unignore_user", p1) } /// USER INTERFACE - internal static let settingsUserInterface = VectorL10n.tr("Vector", "settings_user_interface") + internal static var settingsUserInterface: String { + return VectorL10n.tr("Vector", "settings_user_interface") + } /// USER SETTINGS - internal static let settingsUserSettings = VectorL10n.tr("Vector", "settings_user_settings") + internal static var settingsUserSettings: String { + return VectorL10n.tr("Vector", "settings_user_settings") + } /// Version %@ internal static func settingsVersion(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_version", p1) } /// Login in the main app to share content - internal static let shareExtensionAuthPrompt = VectorL10n.tr("Vector", "share_extension_auth_prompt") + internal static var shareExtensionAuthPrompt: String { + return VectorL10n.tr("Vector", "share_extension_auth_prompt") + } /// Failed to send. Check in the main app the encryption settings for this room - internal static let shareExtensionFailedToEncrypt = VectorL10n.tr("Vector", "share_extension_failed_to_encrypt") + internal static var shareExtensionFailedToEncrypt: String { + return VectorL10n.tr("Vector", "share_extension_failed_to_encrypt") + } /// Start - internal static let start = VectorL10n.tr("Vector", "start") + internal static var start: String { + return VectorL10n.tr("Vector", "start") + } /// Favourites - internal static let titleFavourites = VectorL10n.tr("Vector", "title_favourites") + internal static var titleFavourites: String { + return VectorL10n.tr("Vector", "title_favourites") + } /// Communities - internal static let titleGroups = VectorL10n.tr("Vector", "title_groups") + internal static var titleGroups: String { + return VectorL10n.tr("Vector", "title_groups") + } /// Home - internal static let titleHome = VectorL10n.tr("Vector", "title_home") + internal static var titleHome: String { + return VectorL10n.tr("Vector", "title_home") + } /// People - internal static let titlePeople = VectorL10n.tr("Vector", "title_people") + internal static var titlePeople: String { + return VectorL10n.tr("Vector", "title_people") + } /// Rooms - internal static let titleRooms = VectorL10n.tr("Vector", "title_rooms") + internal static var titleRooms: String { + return VectorL10n.tr("Vector", "title_rooms") + } /// Today - internal static let today = VectorL10n.tr("Vector", "today") + internal static var today: String { + return VectorL10n.tr("Vector", "today") + } /// This room contains unknown devices which have not been verified.\nThis means there is no guarantee that the devices belong to the users they claim to.\nWe recommend you go through the verification process for each device before continuing, but you can resend the message without verifying if you prefer. - internal static let unknownDevicesAlert = VectorL10n.tr("Vector", "unknown_devices_alert") + internal static var unknownDevicesAlert: String { + return VectorL10n.tr("Vector", "unknown_devices_alert") + } /// Room contains unknown devices - internal static let unknownDevicesAlertTitle = VectorL10n.tr("Vector", "unknown_devices_alert_title") + internal static var unknownDevicesAlertTitle: String { + return VectorL10n.tr("Vector", "unknown_devices_alert_title") + } /// Answer Anyway - internal static let unknownDevicesAnswerAnyway = VectorL10n.tr("Vector", "unknown_devices_answer_anyway") + internal static var unknownDevicesAnswerAnyway: String { + return VectorL10n.tr("Vector", "unknown_devices_answer_anyway") + } /// Call Anyway - internal static let unknownDevicesCallAnyway = VectorL10n.tr("Vector", "unknown_devices_call_anyway") + internal static var unknownDevicesCallAnyway: String { + return VectorL10n.tr("Vector", "unknown_devices_call_anyway") + } /// Send Anyway - internal static let unknownDevicesSendAnyway = VectorL10n.tr("Vector", "unknown_devices_send_anyway") + internal static var unknownDevicesSendAnyway: String { + return VectorL10n.tr("Vector", "unknown_devices_send_anyway") + } /// Unknown devices - internal static let unknownDevicesTitle = VectorL10n.tr("Vector", "unknown_devices_title") + internal static var unknownDevicesTitle: String { + return VectorL10n.tr("Vector", "unknown_devices_title") + } /// Verify… - internal static let unknownDevicesVerify = VectorL10n.tr("Vector", "unknown_devices_verify") + internal static var unknownDevicesVerify: String { + return VectorL10n.tr("Vector", "unknown_devices_verify") + } /// Video - internal static let video = VectorL10n.tr("Vector", "video") + internal static var video: String { + return VectorL10n.tr("Vector", "video") + } /// View - internal static let view = VectorL10n.tr("Vector", "view") + internal static var view: String { + return VectorL10n.tr("Vector", "view") + } /// Voice - internal static let voice = VectorL10n.tr("Vector", "voice") + internal static var voice: String { + return VectorL10n.tr("Vector", "voice") + } /// Warning - internal static let warning = VectorL10n.tr("Vector", "warning") + internal static var warning: String { + return VectorL10n.tr("Vector", "warning") + } /// Widget creation has failed - internal static let widgetCreationFailure = VectorL10n.tr("Vector", "widget_creation_failure") + internal static var widgetCreationFailure: String { + return VectorL10n.tr("Vector", "widget_creation_failure") + } /// Failed to send request. - internal static let widgetIntegrationFailedToSendRequest = VectorL10n.tr("Vector", "widget_integration_failed_to_send_request") + internal static var widgetIntegrationFailedToSendRequest: String { + return VectorL10n.tr("Vector", "widget_integration_failed_to_send_request") + } /// Missing room_id in request. - internal static let widgetIntegrationMissingRoomId = VectorL10n.tr("Vector", "widget_integration_missing_room_id") + internal static var widgetIntegrationMissingRoomId: String { + return VectorL10n.tr("Vector", "widget_integration_missing_room_id") + } /// Missing user_id in request. - internal static let widgetIntegrationMissingUserId = VectorL10n.tr("Vector", "widget_integration_missing_user_id") + internal static var widgetIntegrationMissingUserId: String { + return VectorL10n.tr("Vector", "widget_integration_missing_user_id") + } /// You are not in this room. - internal static let widgetIntegrationMustBeInRoom = VectorL10n.tr("Vector", "widget_integration_must_be_in_room") + internal static var widgetIntegrationMustBeInRoom: String { + return VectorL10n.tr("Vector", "widget_integration_must_be_in_room") + } /// You need to be able to invite users to do that. - internal static let widgetIntegrationNeedToBeAbleToInvite = VectorL10n.tr("Vector", "widget_integration_need_to_be_able_to_invite") + internal static var widgetIntegrationNeedToBeAbleToInvite: String { + return VectorL10n.tr("Vector", "widget_integration_need_to_be_able_to_invite") + } /// You do not have permission to do that in this room. - internal static let widgetIntegrationNoPermissionInRoom = VectorL10n.tr("Vector", "widget_integration_no_permission_in_room") + internal static var widgetIntegrationNoPermissionInRoom: String { + return VectorL10n.tr("Vector", "widget_integration_no_permission_in_room") + } /// Power level must be positive integer. - internal static let widgetIntegrationPositivePowerLevel = VectorL10n.tr("Vector", "widget_integration_positive_power_level") + internal static var widgetIntegrationPositivePowerLevel: String { + return VectorL10n.tr("Vector", "widget_integration_positive_power_level") + } /// This room is not recognised. - internal static let widgetIntegrationRoomNotRecognised = VectorL10n.tr("Vector", "widget_integration_room_not_recognised") + internal static var widgetIntegrationRoomNotRecognised: String { + return VectorL10n.tr("Vector", "widget_integration_room_not_recognised") + } /// Room %@ is not visible. internal static func widgetIntegrationRoomNotVisible(_ p1: String) -> String { return VectorL10n.tr("Vector", "widget_integration_room_not_visible", p1) } /// Unable to create widget. - internal static let widgetIntegrationUnableToCreate = VectorL10n.tr("Vector", "widget_integration_unable_to_create") + internal static var widgetIntegrationUnableToCreate: String { + return VectorL10n.tr("Vector", "widget_integration_unable_to_create") + } /// You need permission to manage widgets in this room - internal static let widgetNoPowerToManage = VectorL10n.tr("Vector", "widget_no_power_to_manage") + internal static var widgetNoPowerToManage: String { + return VectorL10n.tr("Vector", "widget_no_power_to_manage") + } /// You don't currently have any stickerpacks enabled. - internal static let widgetStickerPickerNoStickerpacksAlert = VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert") + internal static var widgetStickerPickerNoStickerpacksAlert: String { + return VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert") + } /// Add some now? - internal static let widgetStickerPickerNoStickerpacksAlertAddNow = VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert_add_now") + internal static var widgetStickerPickerNoStickerpacksAlertAddNow: String { + return VectorL10n.tr("Vector", "widget_sticker_picker_no_stickerpacks_alert_add_now") + } /// Yesterday - internal static let yesterday = VectorL10n.tr("Vector", "yesterday") + internal static var yesterday: String { + return VectorL10n.tr("Vector", "yesterday") + } /// You - internal static let you = VectorL10n.tr("Vector", "you") + internal static var you: String { + return VectorL10n.tr("Vector", "you") + } } // swiftlint:enable function_parameter_count identifier_name line_length type_body_length @@ -1182,8 +2190,17 @@ internal enum VectorL10n { extension VectorL10n { private static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "") - return String(format: format, locale: Locale.current, arguments: args) - } + let locale: Locale + if let localeIdentifier = Bundle.mxk_language() { + locale = Locale(identifier: localeIdentifier) + } else if let fallbackLocaleIdentifier = Bundle.mxk_fallbackLanguage() { + locale = Locale(identifier: fallbackLocaleIdentifier) + } else { + locale = Locale.current + } + + return String(format: format, locale: locale, arguments: args) + } } private final class BundleToken {} From 23b8df8ad5c80f574170cbbd51b6188b0e920e04 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 21 Jan 2019 23:32:51 +0100 Subject: [PATCH 080/244] Add reveal password button image --- .../Images.xcassets/KeyBackup/Contents.json | 6 +++++ .../Contents.json | 23 ++++++++++++++++++ .../reveal_password_button.png | Bin 0 -> 721 bytes .../reveal_password_button@2x.png | Bin 0 -> 1639 bytes .../reveal_password_button@3x.png | Bin 0 -> 2584 bytes Riot/Generated/Images.swift | 1 + 6 files changed, 30 insertions(+) create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/Contents.json create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button.png create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button@2x.png create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button@3x.png diff --git a/Riot/Assets/Images.xcassets/KeyBackup/Contents.json b/Riot/Assets/Images.xcassets/KeyBackup/Contents.json new file mode 100644 index 000000000..da4a164c9 --- /dev/null +++ b/Riot/Assets/Images.xcassets/KeyBackup/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/Contents.json b/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/Contents.json new file mode 100644 index 000000000..2762fc2b1 --- /dev/null +++ b/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "reveal_password_button.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "reveal_password_button@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "reveal_password_button@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button.png b/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button.png new file mode 100644 index 0000000000000000000000000000000000000000..eafa300c879189502c22acf92b651963368bbb71 GIT binary patch literal 721 zcmV;?0xtcDP)Px%i%CR5R5%f}l|5+FK^VsK*@O&2iuD6pb<-sZ9khW2f)O!xQe5I9IAqqPQkBwE+JN-~gAO5S65{Xqdl#ZfJGBQdclW-}^SpQO-T(e> z*DfuS$@puv+B}eSzu!Maf84-7(SLBe-A^Nt$Z9s5?HK<^=N|DG$K2f94Fr}EKC}}? zelXv_EL5x2$K!A#2@;9K!FIcygLJ_V))9H+^?HlJVDO`Styb$quh&a}xykgjd|+M& z0)cd~Sp1>6ZT}>Q#bU=GzJhoX!goNoDwWC;3m(@;qtWa5AHtb}v%x|xmdoYO7CT75 z%8#(JcLZhtz7K^$mkWi$R}0*&PbQOxo6Y76lFWkJWT$7@$(A@y0>pikk&X?BVPCW{a43` zuMyWxI%+HpXHAK10&&D;UYC|xkjq02FX6aNVB6>OT`QGJs{NpuwOB$TT(>CuYV@Ck<&C-;z_JVZdIGm0(e# zZ0R1?^xT*PMftd4S=C&ovB5bpGj=*@NXz&ZJ>2t`Z0P}xiEg+1EFOcAv3!aRW5tyQz6tEUw4D+ekrK}7PN(x+SI!bubK++Z%wb=Q<>XV$;=~bG8emGC z(;db3{X-iZGOO9*is>WSpoX)2nKkna*hP-*g%MU9ait+G3m)viIyl7rd+cly^?UVP z4@xvFuCd;CekMAwE7%IIb?lchJ>e^g3A59`0Icf|_N{zX_!U_K00000NkvXXu0mjf Dt^rbS literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button@2x.png b/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3e9307b0f4a4ec91e4a94bd12f67a4b5aa6ca386 GIT binary patch literal 1639 zcmV-t2AKJYP)Px*AxT6*R9FesnR`f{RT#kiJ};GFx`mDKmJv!@ZH)fN>nM$tEw@^V&@6H#ZOm4= z=>CU6MT{J?SyCI@V9OZRV$oWY)bLLK>|QXW(Ue$?O+iw;efE1k-}mMDj<1(bE%Lze zeeUOZp7Wf`cl3lTKpP()_he>freP`vcolsG@U0$?Cq~SJ_wl&~et~`lxUsFRtrK`$ z`15I=`6#ESr{9HhFJhyJzAQ*vexj=OfUK;nl(Dg~4{?42mb{L& zxdA?cI2IZj`bKMO>&0MA1Qh@ozX_+`V-U%Dc(8-bAU^_s55c^{j10~o>#%1X0M4(* z`7hAC+tCgLMi~4!q#x*~A|oSzkBErq8yp<;klpBkfq^9GtLcwmXC2?E67VZ_HW9=r zWM*u$3V;Q=(dYBkGVl$iMFu+$eSdg(_~Dk8ma8V;4bRTbjvW~pDMoiQy7!ne(1*NU z?^7)FqbAS9XAB@CBcqf-YUrU_nL&E#JKEdZ4`_O@F!oEZT}fY}b+J80--`Xcnr^}Y zPMJ)~=1mOmh90m`G5i%JvaY$gxz*GO7VqxvKAoDHdT?}f^bT~FD}66x=O-j24EOZ( zOgYY!Gmw^+_7TQ*D1!oyFtwY>%3*`PASkm@OsVe2n7KYGJ3BjHbsNNW1~61k^c9A} z-(>!A7S}fheZf#><188f8G}#IBb4Ec#KgpY_#KMo2Pe${&Tk+KvUr@b!SU;4ex012 zrU4UY!LLC7c@nS|y+q*yUk0wn#y)IZFm+5^PIYV?M{lX(`Ox3U>>pFKkbnTF`Fl~4 zC~vlf7+9_WYsmaLo96Z{EG&$mR(GMl6}}U^AuESgO?-TOd0k!Iu)zyJ#TN+8*z;dU zET&XJy7t8xC@(Khw#Zt#c77DRKr2{=0zQ`WCm3uS498}G&;%k2a~px45FHo3L$by! zz+v&hZsJ?5<*T3Otby3rSlPk&m=h&L-RDqqKiaq@d=TeLEO^R~)I9g1vk2(S_mH{Q!otFS z5=FMi2XJC1V7%Z~^KnA2oXwhGN0hVXSzD3sIP2jd)n->t4wPt^_rn+)4|AJ)_hs8 z8rQJNGj+AB35!qSn?bMk#>B*Y3{n3QlAsQ;yF?knt|-%5uNe%olfm=}>Sqg0cv{xf z)jSPbz8r$4E9Rp39@^E_HO5~13&x*8z}|_LfZxtu8*prEqc)tBl+=Ul7NvU&@Fwmw zSCW&HufdOsi;K%g<|uS~2NHGJMoYQhToq)xhW=;pA5=23jTSXEHFenzhmfJ&4Dyl^ z60nrBV4p#ogrZxGuAIWNZe;%x7G}T(;-<_QRmzt6x#po;h3?BjbEbspcpb)hL$C(t zay88jmb(qQjczoQ zx~rVPoWF9FeUjQc=}`U!fGT*HvXKj<+&rDeqLts@yBvZAIJZ&FkY7I3sBEM9Jdo>e z5j)l;`Q@bL7YZhE#W;Tidp8<3D@okD2F;I7Dj_YzE$}Vy_ccvmWT#&ysm=~n6g@&|KKnKsi>&% l*4NkH4?Tza{!jnK^bhLv6(MV(U-|$5002ovPDHLkV1k~jCx!q3 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button@3x.png b/Riot/Assets/Images.xcassets/KeyBackup/reveal_password_button.imageset/reveal_password_button@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..31f4c088ddb94249b6ba164382287c8ba7493fb9 GIT binary patch literal 2584 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 Date: Mon, 21 Jan 2019 23:45:51 +0100 Subject: [PATCH 081/244] Add convenient method on UIView to add a subview matching parent --- Riot/Categories/UIView.swift | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 Riot/Categories/UIView.swift diff --git a/Riot/Categories/UIView.swift b/Riot/Categories/UIView.swift new file mode 100644 index 000000000..b27ec3657 --- /dev/null +++ b/Riot/Categories/UIView.swift @@ -0,0 +1,34 @@ +/* + Copyright 2019 New Vector 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 Foundation + +extension UIView { + + /// Add a subview matching parent view using autolayout + func vc_addSubViewMathingParent(_ subView: UIView) { + self.addSubview(subView) + subView.translatesAutoresizingMaskIntoConstraints = false + let views = ["view": subView] + ["H:|[view]|", "V:|[view]|"].forEach { vfl in + let constraints = NSLayoutConstraint.constraints(withVisualFormat: vfl, + options: [], + metrics: nil, + views: views) + constraints.forEach { $0.isActive = true } + } + } +} From 210bb6e12d5007fde5d47a4d0cfef7a4f9e97200 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:04:34 +0100 Subject: [PATCH 082/244] Add extension methods for view controller containment on UIViewController and add convenient method to remove back bar button title when pushing a view controller on UINavigationViewController. --- Riot/Categories/UIViewController.swift | 64 ++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 Riot/Categories/UIViewController.swift diff --git a/Riot/Categories/UIViewController.swift b/Riot/Categories/UIViewController.swift new file mode 100644 index 000000000..9bfc63008 --- /dev/null +++ b/Riot/Categories/UIViewController.swift @@ -0,0 +1,64 @@ +/* + Copyright 2019 New Vector 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 UIKit + +extension UIViewController { + + /// Remove back bar button title when pushing a view controller. + /// This method should be called on the previous controller in UINavigationController stack. + func vc_removeBackTitle() { + self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil) + } + + + /// Add a child view controller matching current view controller view. + /// + /// - Parameter viewController: The child view controller to add. + func vc_addChildViewController(viewController: UIViewController) { + self.vc_addChildViewController(viewController: viewController, onView: self.view) + } + + + /// Add a child view controller on current view controller. + /// + /// - Parameters: + /// - viewController: The child view controller to add. + /// - view: The view on which to add the child view controller view. + func vc_addChildViewController(viewController: UIViewController, onView view: UIView) { + self.addChildViewController(viewController) + + viewController.view.frame = view.bounds + view.vc_addSubViewMathingParent(viewController.view) + viewController.didMove(toParentViewController: self) + } + + + /// Remove a child view controller from current view controller. + /// + /// - Parameter viewController: The child view controller to remove. + func vc_removeChildViewController(viewController: UIViewController) { + viewController.willMove(toParentViewController: nil) + viewController.view.removeFromSuperview() + viewController.removeFromParentViewController() + } + + + /// Remove current view controller from parent. + func vc_removeFromParent() { + self.vc_removeChildViewController(viewController: self) + } +} From f12643fae1abada3e7d9930b963c9da998664164 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:10:25 +0100 Subject: [PATCH 083/244] Introduce routers, used to be passed between coordinators. They handles only `physical` navigation. Add navigation router to handle navigation with UINavigationController. --- Riot/Routers/NavigationRouter.swift | 120 ++++++++++++++++++++++++ Riot/Routers/NavigationRouterType.swift | 69 ++++++++++++++ Riot/Routers/Presentable.swift | 28 ++++++ 3 files changed, 217 insertions(+) create mode 100755 Riot/Routers/NavigationRouter.swift create mode 100755 Riot/Routers/NavigationRouterType.swift create mode 100755 Riot/Routers/Presentable.swift diff --git a/Riot/Routers/NavigationRouter.swift b/Riot/Routers/NavigationRouter.swift new file mode 100755 index 000000000..76e52d392 --- /dev/null +++ b/Riot/Routers/NavigationRouter.swift @@ -0,0 +1,120 @@ +/* + Copyright 2018 New Vector 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 UIKit + +/// `NavigationRouter` is a concrete implementation of NavigationRouterType. +final class NavigationRouter: NSObject, NavigationRouterType { + + // MARK: - Properties + + // MARK: Private + + private var completions: [UIViewController : () -> Void] + + // MARK: Public + + private let navigationController: UINavigationController + + // MARK: - Setup + + init(navigationController: UINavigationController = UINavigationController()) { + self.navigationController = navigationController + self.completions = [:] + super.init() + self.navigationController.delegate = self + } + + // MARK: - Public + + func present(_ module: Presentable, animated: Bool = true) { + navigationController.present(module.toPresentable(), animated: animated, completion: nil) + } + + func dismissModule(animated: Bool = true, completion: (() -> Void)? = nil) { + navigationController.dismiss(animated: animated, completion: completion) + } + + func setRootModule(_ module: Presentable, hideNavigationBar: Bool = false) { + // Call all completions so all coordinators can be deallocated + completions.forEach { $0.value() } + navigationController.setViewControllers([module.toPresentable()], animated: false) + navigationController.isNavigationBarHidden = hideNavigationBar + } + + func popToRootModule(animated: Bool) { + if let controllers = navigationController.popToRootViewController(animated: animated) { + controllers.forEach { runCompletion(for: $0) } + } + } + + func popToModule(_ module: Presentable, animated: Bool) { + if let controllers = navigationController.popToViewController(module.toPresentable(), animated: animated) { + controllers.forEach { runCompletion(for: $0) } + } + } + + func push(_ module: Presentable, animated: Bool = true, popCompletion: (() -> Void)? = nil) { + + let controller = module.toPresentable() + + // Avoid pushing UINavigationController onto stack + guard controller is UINavigationController == false else { + return + } + + if let completion = popCompletion { + completions[controller] = completion + } + + navigationController.pushViewController(controller, animated: animated) + } + + func popModule(animated: Bool = true) { + if let controller = navigationController.popViewController(animated: animated) { + runCompletion(for: controller) + } + } + + // MARK: Presentable + + func toPresentable() -> UIViewController { + return navigationController + } + + // MARK: - Private + + private func runCompletion(for controller: UIViewController) { + guard let completion = completions[controller] else { return } + completion() + completions.removeValue(forKey: controller) + } +} + +// MARK: - UINavigationControllerDelegate +extension NavigationRouter: UINavigationControllerDelegate { + + func navigationController(_ navigationController: UINavigationController, didShow viewController: UIViewController, animated: Bool) { + + // Ensure the view controller is popping + guard let poppedViewController = navigationController.transitionCoordinator?.viewController(forKey: .from), + !navigationController.viewControllers.contains(poppedViewController) else { + return + } + + runCompletion(for: poppedViewController) + } +} diff --git a/Riot/Routers/NavigationRouterType.swift b/Riot/Routers/NavigationRouterType.swift new file mode 100755 index 000000000..e86457d6f --- /dev/null +++ b/Riot/Routers/NavigationRouterType.swift @@ -0,0 +1,69 @@ +/* + Copyright 2018 New Vector 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 UIKit + +/// Protocol describing a router that wraps a UINavigationController and add convenient completion handlers. Completions are called when a Presentable is removed. +/// Routers are used to be passed between coordinators. They handles only `physical` navigation. +protocol NavigationRouterType: class, Presentable { + + /// Present modally a view controller on the navigation controller + /// + /// - Parameter module: The Presentable to present. + /// - Parameter animated: Specify true to animate the transition. + func present(_ module: Presentable, animated: Bool) + + /// Dismiss presented view controller from navigation controller + /// + /// - Parameter animated: Specify true to animate the transition. + /// - Parameter completion: Animation completion (not the pop completion). + func dismissModule(animated: Bool, completion: (() -> Void)?) + + /// Set root view controller of navigation controller + /// + /// - Parameter module: The Presentable to set as root. + /// - Parameter hideNavigationBar: Specify true to hide the UINavigationBar. + func setRootModule(_ module: Presentable, hideNavigationBar: Bool) + + /// Pop to root view controller of navigation controller and remove all others + /// + /// - Parameter animated: Specify true to animate the transition. + func popToRootModule(animated: Bool) + + /// Pops view controllers until the specified view controller is at the top of the navigation stack + /// + /// - Parameter module: The Presentable that should to be at the top of the stack. + /// - Parameter animated: Specify true to animate the transition. + func popToModule(_ module: Presentable, animated: Bool) + + /// Push a view controller on navigation controller stack + /// + /// - Parameter animated: Specify true to animate the transition. + /// - Parameter popCompletion: Completion called when `module` is removed from the navigation stack. + func push(_ module: Presentable, animated: Bool, popCompletion: (() -> Void)?) + + /// Pop last view controller from navigation controller stack + /// + /// - Parameter animated: Specify true to animate the transition. + func popModule(animated: Bool) +} + +// `NavigationRouterType` default implementation +extension NavigationRouterType { + func setRootModule(_ module: Presentable) { + setRootModule(module, hideNavigationBar: false) + } +} diff --git a/Riot/Routers/Presentable.swift b/Riot/Routers/Presentable.swift new file mode 100755 index 000000000..6ab57990d --- /dev/null +++ b/Riot/Routers/Presentable.swift @@ -0,0 +1,28 @@ +/* + Copyright 2018 New Vector 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 UIKit + +/// Protocol used to pass UIViewControllers to routers +protocol Presentable { + func toPresentable() -> UIViewController +} + +extension UIViewController: Presentable { + public func toPresentable() -> UIViewController { + return self + } +} From bd99e11d9982047cba60f018c48bde6f48ecf176 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:12:17 +0100 Subject: [PATCH 084/244] Introduce Coordinator pattern. Coordinators are the objects which control the navigation flow of the application. Add `Coordinator` base protocol. --- Riot/Coordinators/Coordinator.swift | 51 +++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100755 Riot/Coordinators/Coordinator.swift diff --git a/Riot/Coordinators/Coordinator.swift b/Riot/Coordinators/Coordinator.swift new file mode 100755 index 000000000..41f006ea8 --- /dev/null +++ b/Riot/Coordinators/Coordinator.swift @@ -0,0 +1,51 @@ +/* + Copyright 2018 New Vector 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 UIKit + +/// Protocol describing a [Coordinator](http://khanlou.com/2015/10/coordinators-redux/). +/// Coordinators are the objects which control the navigation flow of the application. +/// It helps to isolate and reuse view controllers and pass dependencies down the navigation hierarchy. +protocol Coordinator: class { + + /// Starts job of the coordinator. + func start() + + /// Child coordinators to retain. Prevent them from getting deallocated. + var childCoordinators: [Coordinator] { get set } + + /// Stores coordinator to the `childCoordinators` array. + /// + /// - Parameter childCoordinator: Child coordinator to store. + func add(childCoordinator: Coordinator) + + /// Remove coordinator from the `childCoordinators` array. + /// + /// - Parameter childCoordinator: Child coordinator to remove. + func remove(childCoordinator: Coordinator) +} + +// `Coordinator` default implementation +extension Coordinator { + + func add(childCoordinator coordinator: Coordinator) { + childCoordinators.append(coordinator) + } + + func remove(childCoordinator: Coordinator) { + self.childCoordinators = self.childCoordinators.filter { $0 !== childCoordinator } + } +} From 5d9cff6e695eaa2432e5aa48bfa78c1ded828064 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:15:20 +0100 Subject: [PATCH 085/244] Create ActivityIndicatorView in order to wrap activity indicator customization and create ActivityIndicatorPresenter in order to manage activity indicator presentation. --- .../ActivityIndicatorPresenter.swift | 119 ++++++++++++++++++ .../ActivityIndicatorPresenterType.swift | 34 +++++ .../ActivityIndicatorView.swift | 75 +++++++++++ .../ActivityIndicatorView.xib | 40 ++++++ 4 files changed, 268 insertions(+) create mode 100755 Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift create mode 100644 Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenterType.swift create mode 100755 Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift create mode 100755 Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift new file mode 100755 index 000000000..41b569446 --- /dev/null +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift @@ -0,0 +1,119 @@ +/* + Copyright 2018 New Vector 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 Foundation +import UIKit + +/// Used to present activity indicator on a view +final class ActivityIndicatorPresenter: ActivityIndicatorPresenterType { + + // MARK: - Constants + + private enum Constants { + static let animationDuration: TimeInterval = 0.3 + static let backgroundOverlayColor = UIColor.black + static let backgroundOverlayAlpha: CGFloat = 0.3 + } + + // MARK: - Properties + + private weak var backgroundOverlayView: UIView? + private weak var activityIndicatorView: ActivityIndicatorView? + private weak var presentingView: UIView? + + // MARK: - Public + + func presentActivityIndicator(on view: UIView, animated: Bool, completion: (() -> Void)? = nil) { + self.presentingView = view + + view.isUserInteractionEnabled = false + + let backgroundOverlayView = self.createBackgroundOverlayView(with: view.frame) + + let activityIndicatorView = ActivityIndicatorView() + + // Add activityIndicatorView on backgroundOverlayView centered + backgroundOverlayView.addSubview(activityIndicatorView) + activityIndicatorView.translatesAutoresizingMaskIntoConstraints = false + activityIndicatorView.centerXAnchor.constraint(equalTo: backgroundOverlayView.centerXAnchor).isActive = true + activityIndicatorView.centerYAnchor.constraint(equalTo: backgroundOverlayView.centerYAnchor).isActive = true + + activityIndicatorView.startAnimating() + + backgroundOverlayView.alpha = 0 + backgroundOverlayView.isHidden = false + + view.vc_addSubViewMathingParent(backgroundOverlayView) + + self.backgroundOverlayView = backgroundOverlayView + self.activityIndicatorView = activityIndicatorView + + let animationInstructions = { + backgroundOverlayView.alpha = Constants.backgroundOverlayAlpha + } + + if animated { + UIView.animate(withDuration: Constants.animationDuration, animations: { + animationInstructions() + }, completion: { _ in + completion?() + }) + } else { + animationInstructions() + completion?() + } + } + + func removeCurrentActivityIndicator(animated: Bool, completion: (() -> Void)? = nil) { + guard let presentingView = self.presentingView, + let backgroundOverlayView = self.backgroundOverlayView, + let activityIndicatorView = self.activityIndicatorView else { + return + } + + presentingView.isUserInteractionEnabled = true + + let animationInstructions = { + activityIndicatorView.alpha = 0 + } + + let animationCompletionInstructions = { + activityIndicatorView.stopAnimating() + backgroundOverlayView.isHidden = true + backgroundOverlayView.removeFromSuperview() + } + + if animated { + UIView.animate(withDuration: Constants.animationDuration, animations: { + animationInstructions() + }, completion: { _ in + animationCompletionInstructions() + }) + } else { + animationInstructions() + animationCompletionInstructions() + } + } + + // MARK: - Private + + private func createBackgroundOverlayView(with frame: CGRect = CGRect.zero) -> UIView { + let backgroundOverlayView = UIView(frame: frame) + backgroundOverlayView.backgroundColor = Constants.backgroundOverlayColor + backgroundOverlayView.alpha = Constants.backgroundOverlayAlpha + return backgroundOverlayView + } +} diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenterType.swift b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenterType.swift new file mode 100644 index 000000000..c7a4f29b5 --- /dev/null +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenterType.swift @@ -0,0 +1,34 @@ +/* + Copyright 2018 New Vector 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 Foundation + +/// Protocol used to present activity indicator on a view +protocol ActivityIndicatorPresenterType { + func presentActivityIndicator(on view: UIView, animated: Bool, completion: (() -> Void)?) + func removeCurrentActivityIndicator(animated: Bool, completion: (() -> Void)?) +} + +// `ActivityIndicatorPresenterType` default implementation +extension ActivityIndicatorPresenterType { + func presentActivityIndicator(on view: UIView, animated: Bool) { + self.presentActivityIndicator(on: view, animated: animated, completion: nil) + } + + func removeCurrentActivityIndicator(animated: Bool) { + self.removeCurrentActivityIndicator(animated: animated, completion: nil) + } +} diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift new file mode 100755 index 000000000..4519854ba --- /dev/null +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift @@ -0,0 +1,75 @@ +/* + Copyright 2018 New Vector 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 UIKit +import Reusable + +final class ActivityIndicatorView: UIView, NibOwnerLoadable { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView! + + // MARK: Public + + var color: UIColor? { + get { + return activityIndicatorView.color + } + set { + activityIndicatorView.color = newValue + } + } + + // MARK: - Setup + + private func commonInit() { + } + + convenience init() { + self.init(frame: CGRect.zero) + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.loadNibContent() + self.commonInit() + } + + override init(frame: CGRect) { + super.init(frame: frame) + self.loadNibContent() + self.commonInit() + } + + // MARK: - Overrides + + override var intrinsicContentSize: CGSize { + return CGSize(width: self.activityIndicatorView.intrinsicContentSize.width, height: self.activityIndicatorView.intrinsicContentSize.height) + } + + // MARK: - Public + + func startAnimating() { + self.activityIndicatorView.startAnimating() + } + + func stopAnimating() { + self.activityIndicatorView.stopAnimating() + } +} diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib new file mode 100755 index 000000000..9dddf369c --- /dev/null +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 93a4c74071e65183243c98e505a250eaaec528ad Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:18:54 +0100 Subject: [PATCH 086/244] Create KeyboardAvoider that help to avoid keyboard overlap with scroll view content. --- .../KeyboardAvoiding/KeyboardAvoider.swift | 130 ++++++++++++++++++ .../KeyboardNotification.swift | 65 +++++++++ 2 files changed, 195 insertions(+) create mode 100644 Riot/Modules/Common/KeyboardAvoiding/KeyboardAvoider.swift create mode 100644 Riot/Modules/Common/KeyboardAvoiding/KeyboardNotification.swift diff --git a/Riot/Modules/Common/KeyboardAvoiding/KeyboardAvoider.swift b/Riot/Modules/Common/KeyboardAvoiding/KeyboardAvoider.swift new file mode 100644 index 000000000..d4211ef3d --- /dev/null +++ b/Riot/Modules/Common/KeyboardAvoiding/KeyboardAvoider.swift @@ -0,0 +1,130 @@ +/* + Copyright 2018 New Vector 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 Foundation + +/// Avoid keyboard overlap with scroll view content +final class KeyboardAvoider { + + // MARK: - Constants + + private enum KeyboardAnimation { + static let defaultDuration: TimeInterval = 0.25 + static let defaultAnimationCurveRawValue: Int = UIViewAnimationCurve.easeInOut.rawValue + } + + // MARK: - Properties + + weak var scrollViewContainerView: UIView? + weak var scrollView: UIScrollView? + + // MARK: - Setup + + /// Designated initializer. + /// + /// - Parameter scrollViewContainerView: The view that wrap the scroll view. + /// - Parameter scrollView: The scroll view containing keyboard inputs and where content view overlap with keyboard should be avoided. + init(scrollViewContainerView: UIView, scrollView: UIScrollView) { + self.scrollViewContainerView = scrollViewContainerView + self.scrollView = scrollView + } + + // MARK: - Public + + /// Start keyboard avoiding + func startAvoiding() { + self.registerKeyboardNotifications() + } + + /// Stop keyboard avoiding + func stopAvoiding() { + self.unregisterKeyboardNotifications() + } + + // MARK: - Private + + private func registerKeyboardNotifications() { + let notificationCenter = NotificationCenter.default + notificationCenter.addObserver( + self, + selector: #selector(keyboardWillShow(notification:)), + name: .UIKeyboardWillShow, + object: nil) + notificationCenter.addObserver( + self, + selector: #selector(keyboardWillHide(notification:)), + name: .UIKeyboardWillHide, + object: nil) + } + + private func unregisterKeyboardNotifications() { + NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillShow, object: nil) + NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil) + } + + @objc private func keyboardWillShow(notification: Notification) { + guard let view = self.scrollViewContainerView, let scrollView = self.scrollView else { + return + } + + guard let keyboardNotification = KeyboardNotification(notification: notification), + let keyboardFrame = keyboardNotification.keyboardFrameEnd else { + return + } + + let animationDuration = keyboardNotification.animationDuration ?? KeyboardAnimation.defaultDuration + + let animationOptions = keyboardNotification.animationOptions(fallbackAnimationCurveValue: KeyboardAnimation.defaultAnimationCurveRawValue) + + // Transform the keyboard's frame into our view's coordinate system + let keyboardFrameInView = view.convert(keyboardFrame, from: nil) + + // Find how much the keyboard overlaps the scroll view + let scrollViewBottomInset = scrollView.frame.maxY - keyboardFrameInView.origin.y + + UIView.animate(withDuration: animationDuration, + delay: 0.0, + options: animationOptions, animations: { + + scrollView.contentInset.bottom = scrollViewBottomInset + scrollView.scrollIndicatorInsets.bottom = scrollViewBottomInset + }, completion: nil) + } + + @objc private func keyboardWillHide(notification: Notification) { + guard let scrollView = self.scrollView else { + return + } + + guard let keyboardNotification = KeyboardNotification(notification: notification) else { + return + } + + let animationDuration = keyboardNotification.animationDuration ?? KeyboardAnimation.defaultDuration + + let animationOptions = keyboardNotification.animationOptions(fallbackAnimationCurveValue: KeyboardAnimation.defaultAnimationCurveRawValue) + + // Reset scroll view bottom inset to zero + let scrollViewBottomInset: CGFloat = 0.0 + + UIView.animate(withDuration: animationDuration, + delay: 0.0, + options: animationOptions, animations: { + scrollView.contentInset.bottom = scrollViewBottomInset + scrollView.scrollIndicatorInsets.bottom = scrollViewBottomInset + }, completion: nil) + } +} diff --git a/Riot/Modules/Common/KeyboardAvoiding/KeyboardNotification.swift b/Riot/Modules/Common/KeyboardAvoiding/KeyboardNotification.swift new file mode 100644 index 000000000..8bd25c565 --- /dev/null +++ b/Riot/Modules/Common/KeyboardAvoiding/KeyboardNotification.swift @@ -0,0 +1,65 @@ +/* + Copyright 2018 New Vector 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 UIKit + +/// Wrapper for the Notification userInfo values associated with a keyboard notification. +public struct KeyboardNotification { + + let userInfo: [AnyHashable: Any] + + public init?(notification: Notification) { + guard let userInfo = notification.userInfo else { + return nil + } + self.userInfo = userInfo + } + + public var keyboardFrameBegin: CGRect? { + guard let value = userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue else { + return nil + } + return value.cgRectValue + } + + public var keyboardFrameEnd: CGRect? { + guard let value = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue else { + return nil + } + return value.cgRectValue + } + + public var animationDuration: TimeInterval? { + guard let number = userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber else { + return nil + } + return number.doubleValue + } + + /// Keyboard UIViewAnimationCurve enum raw value + public var animationCurveRawValue: Int? { + guard let number = userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber else { + return nil + } + return number.intValue + } + + /// Convert UIViewAnimationCurve raw value to UIViewAnimationOptions + public func animationOptions(fallbackAnimationCurveValue: Int = UIViewAnimationCurve.easeInOut.rawValue) -> UIViewAnimationOptions { + let animationCurveRawValue = self.animationCurveRawValue ?? fallbackAnimationCurveValue + return UIViewAnimationOptions(rawValue: UInt(animationCurveRawValue << 16)) + } +} From e53e4ac4ab3fe9faa32691d53364c61b04241a1d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:33:12 +0100 Subject: [PATCH 087/244] Add zxcvbn-ios pod to help compute password strength --- Podfile | 1 + Podfile.lock | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Podfile b/Podfile index 045542561..9c33472e9 100644 --- a/Podfile +++ b/Podfile @@ -76,6 +76,7 @@ abstract_target 'RiotPods' do pod 'OLMKit', :inhibit_warnings => true pod 'cmark', :inhibit_warnings => true pod 'DTCoreText', :inhibit_warnings => true + pod 'zxcvbn-ios' # Tools pod 'SwiftGen', '~> 6.0' diff --git a/Podfile.lock b/Podfile.lock index f171f0980..d4c795cc8 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -95,6 +95,7 @@ PODS: - Reusable/View (4.0.5) - SwiftGen (6.0.2) - WebRTC (63.11.20455) + - zxcvbn-ios (1.0.4) DEPENDENCIES: - cmark @@ -108,6 +109,7 @@ DEPENDENCIES: - PiwikTracker (from `https://github.com/manuroe/matomo-sdk-ios.git`, branch `feature/CustomVariables`) - Reusable (~> 4.0) - SwiftGen (~> 6.0) + - zxcvbn-ios SPEC REPOS: https://github.com/cocoapods/specs.git: @@ -127,6 +129,7 @@ SPEC REPOS: - Reusable - SwiftGen - WebRTC + - zxcvbn-ios EXTERNAL SOURCES: PiwikTracker: @@ -156,7 +159,8 @@ SPEC CHECKSUMS: Reusable: 188be1a54ac0691bc66e5bb24ec6eb91971b315b SwiftGen: e5b047067aa84082826a0c4f1c4c2ddc95bcf74c WebRTC: f2a6203584745fe53532633397557876b5d71640 + zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c -PODFILE CHECKSUM: bbb50681758f3933fb8bfdfdcc03272cdcf7d167 +PODFILE CHECKSUM: 4a490fe13099d33a5152d8fb185df82a0b3b72bd COCOAPODS: 1.6.0.beta.2 From 02d1e992293c3110822e22af0d4bad7db3da0356 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 00:34:00 +0100 Subject: [PATCH 088/244] Create PasswordStrengthManager to compute password strength from a given string. --- .../PasswordStrength/PasswordStrength.swift | 27 +++++++++++ .../PasswordStrengthManager.swift | 47 +++++++++++++++++++ 2 files changed, 74 insertions(+) create mode 100644 Riot/Managers/PasswordStrength/PasswordStrength.swift create mode 100644 Riot/Managers/PasswordStrength/PasswordStrengthManager.swift diff --git a/Riot/Managers/PasswordStrength/PasswordStrength.swift b/Riot/Managers/PasswordStrength/PasswordStrength.swift new file mode 100644 index 000000000..a9081dcba --- /dev/null +++ b/Riot/Managers/PasswordStrength/PasswordStrength.swift @@ -0,0 +1,27 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// Paswword strength +enum PasswordStrength: UInt { + + case tooGuessable + case veryGuessable + case somewhatGuessable + case safelyUnguessable + case veryUnguessable +} diff --git a/Riot/Managers/PasswordStrength/PasswordStrengthManager.swift b/Riot/Managers/PasswordStrength/PasswordStrengthManager.swift new file mode 100644 index 000000000..bf9277246 --- /dev/null +++ b/Riot/Managers/PasswordStrength/PasswordStrengthManager.swift @@ -0,0 +1,47 @@ +/* + Copyright 2019 New Vector 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 Foundation +import zxcvbn_ios + +/// PasswordStrengthManager compute password strength for a given string. +final class PasswordStrengthManager { + + // MARK: - Properties + + private let zxcvbn = DBZxcvbn() + + // MARK: - Public + + func passwordStrength(for password: String) -> PasswordStrength { + guard let result = zxcvbn.passwordStrength(password) else { + return .tooGuessable + } + return self.passwordStrength(from: result.score) + } + + // MARK: - Private + + private func passwordStrength(from zxcvbnScore: Int32) -> PasswordStrength { + let passwordStrengthRawValue = UInt(zxcvbnScore) + + guard let passwordStrength = PasswordStrength(rawValue: passwordStrengthRawValue) else { + return .tooGuessable + } + + return passwordStrength + } +} From 8bfb79af89def551cadb11c508643c5f298c0d78 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 10:05:08 +0100 Subject: [PATCH 089/244] Create key back setup intro view controller --- ...yBackupSetupIntroViewController.storyboard | 90 ++++++++++++++ .../KeyBackupSetupIntroViewController.swift | 115 ++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard new file mode 100644 index 000000000..cde9fb81e --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift new file mode 100644 index 000000000..f4424e0cd --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift @@ -0,0 +1,115 @@ +/* + Copyright 2019 New Vector 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 UIKit + +protocol KeyBackupSetupIntroViewControllerDelegate: class { + func keyBackupSetupIntroViewControllerDidTapSetupAction(_ keyBackupSetupIntroViewController: KeyBackupSetupIntroViewController) + func keyBackupSetupIntroViewControllerDidCancel(_ keyBackupSetupIntroViewController: KeyBackupSetupIntroViewController) +} + +final class KeyBackupSetupIntroViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var titleLabel: UILabel! + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var setUpButtonBackgroundView: UIView! + @IBOutlet private weak var setUpButton: UIButton! + + // MARK: Private + + private var theme: Theme! + + // MARK: Public + + weak var delegate: KeyBackupSetupIntroViewControllerDelegate? + + // MARK: - Setup + + class func instantiate() -> KeyBackupSetupIntroViewController { + let viewController = StoryboardScene.KeyBackupSetupIntroViewController.initialScene.instantiate() + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupSetupTitle + self.vc_removeBackTitle() + + self.setupViews() + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.keyBackupSetupSkipAction, style: .plain) { [weak self] in + if let sself = self { + sself.delegate?.keyBackupSetupIntroViewControllerDidCancel(sself) + } + } + self.navigationItem.rightBarButtonItem = cancelBarButtonItem + + self.titleLabel.text = VectorL10n.keyBackupSetupIntroTitle + self.informationLabel.text = VectorL10n.keyBackupSetupIntroInfo + self.setUpButton.setTitle(VectorL10n.keyBackupSetupIntroSetupAction, for: .normal) + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.titleLabel.textColor = theme.textPrimaryColor + self.informationLabel.textColor = theme.textPrimaryColor + + self.setUpButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.setUpButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + // MARK: - Actions + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + @IBAction private func validateButtonAction(_ sender: Any) { + self.delegate?.keyBackupSetupIntroViewControllerDidTapSetupAction(self) + } +} From 036fdeee53026e9dcfc62cfd9236fcec3ece45bd Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 10:25:36 +0100 Subject: [PATCH 090/244] Implement key backup setup passphrase scene with view controller, view model, coordinator --- .../KeyBackupSetupPassphraseCoordinator.swift | 73 ++++ ...BackupSetupPassphraseCoordinatorType.swift | 21 + .../KeyBackupSetupPassphraseViewAction.swift | 25 ++ ...upSetupPassphraseViewController.storyboard | 309 ++++++++++++++ ...yBackupSetupPassphraseViewController.swift | 395 ++++++++++++++++++ .../KeyBackupSetupPassphraseViewModel.swift | 138 ++++++ ...eyBackupSetupPassphraseViewModelType.swift | 44 ++ .../KeyBackupSetupPassphraseViewState.swift | 24 ++ .../Passphrase/PasswordStrengthView.swift | 131 ++++++ .../Setup/Passphrase/PasswordStrengthView.xib | 60 +++ 10 files changed, 1220 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewState.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.xib diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift new file mode 100644 index 000000000..c00b9b7a4 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift @@ -0,0 +1,73 @@ +/* + Copyright 2019 New Vector 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 Foundation +import UIKit + +protocol KeyBackupSetupPassphraseCoordinatorDelegate: class { + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinator, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) + func keyBackupSetupPassphraseCoordinatorDidCancel(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinator) +} + +final class KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private var keyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModelType + private let keyBackupSetupPassphraseViewController: KeyBackupSetupPassphraseViewController + + // MARK: Public + + var childCoordinators: [Coordinator] = [] + + weak var delegate: KeyBackupSetupPassphraseCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession) { + self.session = session + + let keyBackup = MXKeyBackup(matrixSession: session) + let keyBackupSetupPassphraseViewModel = KeyBackupSetupPassphraseViewModel(keyBackup: keyBackup) + let keyBackupSetupPassphraseViewController = KeyBackupSetupPassphraseViewController.instantiate(with: keyBackupSetupPassphraseViewModel) + self.keyBackupSetupPassphraseViewModel = keyBackupSetupPassphraseViewModel + self.keyBackupSetupPassphraseViewController = keyBackupSetupPassphraseViewController + } + + // MARK: - Public methods + + func start() { + self.keyBackupSetupPassphraseViewModel.coordinatorDelegate = self + } + + func toPresentable() -> UIViewController { + return self.keyBackupSetupPassphraseViewController + } +} + +// MARK: - KeyBackupSetupPassphraseViewModelCoordinatorDelegate +extension KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseViewModelCoordinatorDelegate { + func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) { + self.delegate?.keyBackupSetupPassphraseCoordinatorDidCancel(self) + } + + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { + self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCompleteWithMegolmBackupCreationInfo: megolmBackupCreationInfo) + } +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift new file mode 100644 index 000000000..f163f7af3 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift @@ -0,0 +1,21 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// `KeyBackupSetupPassphraseCoordinatorType` is a protocol describing a Coordinator that handle key backup setup passphrase navigation flow. +protocol KeyBackupSetupPassphraseCoordinatorType: Coordinator, Presentable { +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift new file mode 100644 index 000000000..9f74ae331 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift @@ -0,0 +1,25 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupSetupPassphraseViewController view actions exposed to view model +enum KeyBackupSetupPassphraseViewAction { + case setupPassphrase + case skip + case skipAlertSkip + case skipAlertContinue +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard new file mode 100644 index 000000000..3f1e48e8f --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard @@ -0,0 +1,309 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift new file mode 100644 index 000000000..0186cdb36 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift @@ -0,0 +1,395 @@ +/* + Copyright 2019 New Vector 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 UIKit + +final class KeyBackupSetupPassphraseViewController: UIViewController { + + // MARK: - Constants + + private enum Constants { + static let animationDuration: TimeInterval = 0.3 + } + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var scrollView: UIScrollView! + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var formBackgroundView: UIView! + + @IBOutlet private weak var passphraseTitleLabel: UILabel! + @IBOutlet private weak var passphraseTextField: UITextField! + + @IBOutlet private weak var passphraseAdditionalInfoView: UIView! + @IBOutlet private weak var passphraseStrengthView: PasswordStrengthView! + @IBOutlet private weak var passphraseAdditionalLabel: UILabel! + + @IBOutlet private weak var formSeparatorView: UIView! + + @IBOutlet private weak var confirmPassphraseTitleLabel: UILabel! + @IBOutlet private weak var confirmPassphraseTextField: UITextField! + + @IBOutlet private weak var confirmPassphraseAdditionalInfoView: UIView! + @IBOutlet private weak var confirmPassphraseAdditionalLabel: UILabel! + + @IBOutlet private weak var setPassphraseButtonBackgroundView: UIView! + @IBOutlet private weak var setPassphraseButton: UIButton! + + // MARK: Private + + private var isFirstViewAppearing: Bool = true + private var isPassphraseTextFieldEditedOnce: Bool = false + private var isConfirmPassphraseTextFieldEditedOnce: Bool = false + private var keyboardAvoider: KeyboardAvoider? + private var viewModel: KeyBackupSetupPassphraseViewModelType! + private var theme: Theme! + private var errorPresenter: MXKErrorPresentation! + private var activityPresenter: ActivityIndicatorPresenter! + private weak var skipAlertController: UIAlertController? + + // MARK: - Setup + + class func instantiate(with viewModel: KeyBackupSetupPassphraseViewModelType) -> KeyBackupSetupPassphraseViewController { + let viewController = StoryboardScene.KeyBackupSetupPassphraseViewController.initialScene.instantiate() + viewController.viewModel = viewModel + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupSetupTitle + self.vc_removeBackTitle() + + self.setupViews() + self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView) + self.activityPresenter = ActivityIndicatorPresenter() + self.errorPresenter = MXKErrorAlertPresentation() + + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + + self.viewModel.viewDelegate = self + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + self.keyboardAvoider?.startAvoiding() + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if self.isFirstViewAppearing { + self.isFirstViewAppearing = false + } + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + + self.view.endEditing(true) + self.keyboardAvoider?.stopAvoiding() + } + + override func viewDidLayoutSubviews() { + super.viewDidLayoutSubviews() + + if self.isFirstViewAppearing { + // Workaround to layout passphraseStrengthView corner radius + self.passphraseStrengthView.setNeedsLayout() + } + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.informationLabel.textColor = theme.textPrimaryColor + + self.formBackgroundView.backgroundColor = theme.backgroundColor + self.passphraseTitleLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onTextField: self.passphraseTextField) + self.passphraseTextField.attributedPlaceholder = NSAttributedString(string: VectorL10n.keyBackupSetupPassphrasePassphrasePlaceholder, + attributes: [.foregroundColor : theme.placeholderTextColor]) + self.updatePassphraseAdditionalLabel() + + self.formSeparatorView.backgroundColor = theme.separatorColor + + self.confirmPassphraseTitleLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onTextField: self.confirmPassphraseTextField) + self.confirmPassphraseTextField.attributedPlaceholder = NSAttributedString(string: VectorL10n.keyBackupSetupPassphraseConfirmPassphraseTitle, + attributes: [.foregroundColor : theme.placeholderTextColor]) + self.updateConfirmPassphraseAdditionalLabel() + + self.setPassphraseButton.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.setPassphraseButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func setupViews() { + let skipBarButtonItem = MXKBarButtonItem(title: VectorL10n.keyBackupSetupSkipAction, style: .plain) { [weak self] in + self?.skipButtonAction() + } + + self.navigationItem.rightBarButtonItem = skipBarButtonItem + + self.scrollView.keyboardDismissMode = .interactive + + self.informationLabel.text = VectorL10n.keyBackupSetupPassphraseInfo + + self.passphraseTitleLabel.text = VectorL10n.keyBackupSetupPassphrasePassphraseTitle + self.passphraseTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) + self.passphraseStrengthView.strength = self.viewModel.passphraseStrength + self.passphraseAdditionalInfoView.isHidden = true + + self.confirmPassphraseTitleLabel.text = VectorL10n.keyBackupSetupPassphraseConfirmPassphraseTitle + self.confirmPassphraseTextField.addTarget(self, action: #selector(textFieldDidChange(_:)), for: .editingChanged) + self.confirmPassphraseAdditionalInfoView.isHidden = true + + self.setPassphraseButton.titleLabel?.numberOfLines = 0 + self.setPassphraseButton.setTitle(VectorL10n.keyBackupSetupPassphraseSetPassphraseAction, for: .normal) + + self.updateSetPassphraseButton() + } + + private func showPassphraseAdditionalInfo(animated: Bool) { + guard self.passphraseAdditionalInfoView.isHidden else { + return + } + + UIView.animate(withDuration: Constants.animationDuration) { + self.passphraseAdditionalInfoView.isHidden = false + } + } + + private func showConfirmPassphraseAdditionalInfo(animated: Bool) { + guard self.confirmPassphraseAdditionalInfoView.isHidden else { + return + } + + UIView.animate(withDuration: Constants.animationDuration) { + self.confirmPassphraseAdditionalInfoView.isHidden = false + } + } + + private func hideConfirmPassphraseAdditionalInfo(animated: Bool) { + guard self.confirmPassphraseAdditionalInfoView.isHidden == false else { + return + } + + UIView.animate(withDuration: Constants.animationDuration) { + self.confirmPassphraseAdditionalInfoView.isHidden = true + } + } + + private func updatePassphraseStrengthView() { + self.passphraseStrengthView.strength = self.viewModel.passphraseStrength + } + + private func updatePassphraseAdditionalLabel() { + + let text: String + let textColor: UIColor + + if self.viewModel.isPassphraseValid { + text = VectorL10n.keyBackupSetupPassphrasePassphraseValid + textColor = self.theme.tintColor + } else { + text = VectorL10n.keyBackupSetupPassphrasePassphraseInvalid + textColor = self.theme.notificationPrimaryColor + } + + self.passphraseAdditionalLabel.text = text + self.passphraseAdditionalLabel.textColor = textColor + } + + private func updateConfirmPassphraseAdditionalLabel() { + + let text: String + let textColor: UIColor + + if self.viewModel.isConfirmPassphraseValid { + text = VectorL10n.keyBackupSetupPassphraseConfirmPassphraseValid + textColor = self.theme.tintColor + } else { + text = VectorL10n.keyBackupSetupPassphraseConfirmPassphraseInvalid + textColor = self.theme.notificationPrimaryColor + } + + self.confirmPassphraseAdditionalLabel.text = text + self.confirmPassphraseAdditionalLabel.textColor = textColor + } + + private func updateSetPassphraseButton() { + self.setPassphraseButton.isEnabled = self.viewModel.isFormValid + } + + private func render(viewState: KeyBackupSetupPassphraseViewState) { + switch viewState { + case .loading: + self.renderLoading() + case .loaded: + self.renderLoaded() + case .error(let error): + self.render(error: error) + } + } + + private func renderLoading() { + self.view.endEditing(true) + self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + } + + private func renderLoaded() { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + } + + private func render(error: Error) { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + self.hideSkipAlert(animated: false) + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } + + private func showSkipAlert() { + guard self.skipAlertController == nil else { + return + } + + let alertController = UIAlertController(title: VectorL10n.keyBackupSetupSkipAlertTitle, + message: VectorL10n.keyBackupSetupSkipAlertMessage, + preferredStyle:.alert) + + alertController.addAction(UIAlertAction(title: VectorL10n.continue, style: .cancel, handler: { action in + self.viewModel.process(viewAction: .skipAlertContinue) + })) + + alertController.addAction(UIAlertAction(title: VectorL10n.keyBackupSetupSkipAlertSkipAction , style: .default, handler: { action in + self.viewModel.process(viewAction: .skipAlertSkip) + })) + + self.present(alertController, animated: true, completion: nil) + self.skipAlertController = alertController + } + + private func hideSkipAlert(animated: Bool) { + self.skipAlertController?.dismiss(animated: true, completion: nil) + } + + // MARK: - Actions + + @IBAction private func passphraseVisibilityButtonAction(_ sender: Any) { + guard self.isPassphraseTextFieldEditedOnce else { + return + } + self.passphraseTextField.isSecureTextEntry.toggle() + } + + @objc func textFieldDidChange(_ textField: UITextField) { + + if textField == self.passphraseTextField { + self.viewModel.passphrase = textField.text + + self.updatePassphraseAdditionalLabel() + self.updatePassphraseStrengthView() + + // Show passphrase additional info at first character entered + if self.isPassphraseTextFieldEditedOnce == false && textField.text?.isEmpty == false { + self.isPassphraseTextFieldEditedOnce = true + self.showPassphraseAdditionalInfo(animated: true) + } + } else { + self.viewModel.confirmPassphrase = textField.text + } + + // Show confirm passphrase additional info if needed + self.updateConfirmPassphraseAdditionalLabel() + if self.viewModel.confirmPassphrase?.isEmpty == false && self.viewModel.isPassphraseValid { + self.showConfirmPassphraseAdditionalInfo(animated: true) + } else { + self.hideConfirmPassphraseAdditionalInfo(animated: true) + } + + // Enable validate button if form is valid + self.updateSetPassphraseButton() + } + + @IBAction private func setPassphraseButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .setupPassphrase) + } + + private func skipButtonAction() { + self.viewModel.process(viewAction: .skip) + } +} + +// MARK: - UITextFieldDelegate +extension KeyBackupSetupPassphraseViewController: UITextFieldDelegate { + + func textFieldShouldClear(_ textField: UITextField) -> Bool { + self.textFieldDidChange(textField) + return true + } + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + + if textField == self.passphraseTextField { + self.confirmPassphraseTextField.becomeFirstResponder() + } else { + textField.resignFirstResponder() + } + + return true + } +} + +// MARK: - KeyBackupSetupPassphraseViewModelViewDelegate +extension KeyBackupSetupPassphraseViewController: KeyBackupSetupPassphraseViewModelViewDelegate { + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didUpdateViewState viewSate: KeyBackupSetupPassphraseViewState) { + self.render(viewState: viewSate) + } + + func keyBackupSetupPassphraseViewModelShowSkipAlert(_ viewModel: KeyBackupSetupPassphraseViewModelType) { + self.showSkipAlert() + } +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift new file mode 100644 index 000000000..17bccb7b0 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift @@ -0,0 +1,138 @@ +/* + Copyright 2019 New Vector 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 Foundation + +final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModelType { + + // MARK: - Properties + + // MARK: Private + + private(set) var passphraseStrength: PasswordStrength = .tooGuessable + private let passwordStrengthManager: PasswordStrengthManager + private let keyBackup: MXKeyBackup + private let coordinatorDelegateQueue: OperationQueue + + // MARK: Public + + var passphrase: String? { + didSet { + self.updatePassphraseStrength() + } + } + + var confirmPassphrase: String? + + var isPassphraseValid: Bool { + return self.passphraseStrength == .veryUnguessable + } + + var isConfirmPassphraseValid: Bool { + guard self.isPassphraseValid, let confirmPassphrase = self.confirmPassphrase else { + return false + } + return confirmPassphrase == passphrase + } + + var isFormValid: Bool { + return self.isPassphraseValid && self.isConfirmPassphraseValid + } + + weak var viewDelegate: KeyBackupSetupPassphraseViewModelViewDelegate? + weak var coordinatorDelegate: KeyBackupSetupPassphraseViewModelCoordinatorDelegate? + + // MARK: - Setup + + init(keyBackup: MXKeyBackup) { + self.passwordStrengthManager = PasswordStrengthManager() + self.keyBackup = keyBackup + + let coordinatorDelegateQueue = OperationQueue() + coordinatorDelegateQueue.name = "KeyBackupSetupPassphraseViewModel.coordinatorDelegateQueue" + coordinatorDelegateQueue.maxConcurrentOperationCount = 1 + self.coordinatorDelegateQueue = coordinatorDelegateQueue + } + + // MARK: - Public + + func process(viewAction: KeyBackupSetupPassphraseViewAction) { + switch viewAction { + case .setupPassphrase: + self.setupPassphrase() + case .skip: + self.pauseCoordinatorOperations() + self.viewDelegate?.keyBackupSetupPassphraseViewModelShowSkipAlert(self) + case.skipAlertContinue: + self.resumeCoordinatorOperations() + case.skipAlertSkip: + self.cancelCoordinatorOperations() + self.coordinatorDelegate?.keyBackupSetupPassphraseViewModelDidCancel(self) + } + } + + // MARK: - Private + + func setupPassphrase() { + guard let passphrase = self.passphrase else { + return + } + + self.viewDelegate?.keyBackupSetupPassphraseViewModel(self, didUpdateViewState: .loading) + + self.keyBackup.prepareKeyBackupVersion(withPassword: passphrase, success: { [weak self] (megolmBackupCreationInfo) in + guard let sself = self else { + return + } + + sself.viewDelegate?.keyBackupSetupPassphraseViewModel(sself, didUpdateViewState: .loaded) + + sself.coordinatorDelegateQueue.addOperation { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCompleteWithMegolmBackupCreationInfo: megolmBackupCreationInfo) + } + } + }, failure: { [weak self] error in + guard let sself = self else { + return + } + sself.viewDelegate?.keyBackupSetupPassphraseViewModel(sself, didUpdateViewState: .error(error)) + }) + } + + private func updatePassphraseStrength() { + self.passphraseStrength = self.passwordStrength(for: self.passphrase) + } + + private func passwordStrength(for password: String?) -> PasswordStrength { + guard let password = password else { + return .tooGuessable + } + return self.passwordStrengthManager.passwordStrength(for: password) + } + + private func pauseCoordinatorOperations() { + self.coordinatorDelegateQueue.isSuspended = true + } + + private func resumeCoordinatorOperations() { + self.coordinatorDelegateQueue.isSuspended = false + } + + private func cancelCoordinatorOperations() { + self.coordinatorDelegateQueue.cancelAllOperations() + } +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift new file mode 100644 index 000000000..40d94da38 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift @@ -0,0 +1,44 @@ +/* + Copyright 2019 New Vector 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 Foundation + +protocol KeyBackupSetupPassphraseViewModelViewDelegate: class { + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didUpdateViewState viewSate: KeyBackupSetupPassphraseViewState) + func keyBackupSetupPassphraseViewModelShowSkipAlert(_ viewModel: KeyBackupSetupPassphraseViewModelType) +} + +protocol KeyBackupSetupPassphraseViewModelCoordinatorDelegate: class { + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) + func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) +} + +/// Protocol describing the view model used by `KeyBackupSetupPassphraseViewController` +protocol KeyBackupSetupPassphraseViewModelType { + + var passphrase: String? { get set } + var confirmPassphrase: String? { get set } + var passphraseStrength: PasswordStrength { get } + + var isPassphraseValid: Bool { get } + var isConfirmPassphraseValid: Bool { get } + var isFormValid: Bool { get } + + var viewDelegate: KeyBackupSetupPassphraseViewModelViewDelegate? { get set } + var coordinatorDelegate: KeyBackupSetupPassphraseViewModelCoordinatorDelegate? { get set } + + func process(viewAction: KeyBackupSetupPassphraseViewAction) +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewState.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewState.swift new file mode 100644 index 000000000..ba0e09e1d --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewState.swift @@ -0,0 +1,24 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupSetupPassphraseViewController view state +enum KeyBackupSetupPassphraseViewState { + case loading + case loaded + case error(Error) +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift new file mode 100644 index 000000000..aa498124f --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift @@ -0,0 +1,131 @@ +/* + Copyright 2019 New Vector 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 Foundation +import Reusable + +final class PasswordStrengthView: UIView, NibOwnerLoadable { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var firstStrengthView: UIView! + @IBOutlet private weak var secondStrengthView: UIView! + @IBOutlet private weak var thirdStrengthView: UIView! + @IBOutlet private weak var fourthStrengthView: UIView! + + // MARK: Private + + private var strengthViews: [UIView] = [] + + private let strengthViewDefaultColor = UIColor(rgb: 0x9E9E9E) + + private var strengthViewColors: [Int: UIColor] = [ + 0: UIColor(rgb: 0xF56679), + 1: UIColor(rgb: 0xFFC666), + 2: UIColor(rgb: 0xF8E71C), + 3: UIColor(rgb: 0x7AC9A1) + ] + + // MARK: Public + + var strength: PasswordStrength = .tooGuessable { + didSet { + self.updateStrengthColors() + } + } + + // MARK: - Setup + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + self.loadNibContent() + } + + override init(frame: CGRect) { + super.init(frame: frame) + self.loadNibContent() + } + + // MARK: - Life cycle + + override func awakeFromNib() { + super.awakeFromNib() + + self.strengthViews = [self.firstStrengthView, + self.secondStrengthView, + self.thirdStrengthView, + self.fourthStrengthView] + + for strenghView in self.strengthViews { + strenghView.layer.masksToBounds = true + } + } + + override func layoutSubviews() { + super.layoutSubviews() + + for strenghView in self.strengthViews { + strenghView.layer.cornerRadius = strenghView.bounds.height/2 + } + } + + // MARK: - Private + + private func updateStrengthColors() { + let strengthViewIndex: Int + + switch self.strength { + case .tooGuessable, .veryGuessable: + strengthViewIndex = 0 + case .somewhatGuessable: + strengthViewIndex = 1 + case .safelyUnguessable: + strengthViewIndex = 2 + case .veryUnguessable: + strengthViewIndex = 3 + } + + self.color(until: strengthViewIndex) + } + + private func color(until strengthViewIndex: Int) { + var index: Int = 0 + + for strenghView in self.strengthViews { + + let color: UIColor + + if index <= strengthViewIndex { + color = self.color(for: index) + } else { + color = self.strengthViewDefaultColor + } + + strenghView.backgroundColor = color + + index+=1 + } + } + + private func color(for index: Int) -> UIColor { + guard let color = self.strengthViewColors[index] else { + return self.strengthViewDefaultColor + } + return color + } +} diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.xib b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.xib new file mode 100644 index 000000000..2ab94ba6c --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.xib @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From 65bf03569b188f3c405c08a64884d0f1fc429956 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 11:04:06 +0100 Subject: [PATCH 091/244] Implement key backup setup recovery key scene with view controller, view model and coordinator --- Riot/Generated/Storyboards.swift | 16 +- ...KeyBackupSetupRecoveryKeyCoordinator.swift | 71 ++++++ ...ackupSetupRecoveryKeyCoordinatorType.swift | 21 ++ .../KeyBackupSetupRecoveryKeyViewAction.swift | 25 ++ ...pSetupRecoveryKeyViewController.storyboard | 220 ++++++++++++++++ ...BackupSetupRecoveryKeyViewController.swift | 234 ++++++++++++++++++ .../KeyBackupSetupRecoveryKeyViewModel.swift | 102 ++++++++ ...yBackupSetupRecoveryKeyViewModelType.swift | 38 +++ .../KeyBackupSetupRecoveryKeyViewState.swift | 24 ++ 9 files changed, 748 insertions(+), 3 deletions(-) create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinatorType.swift create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewAction.swift create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift create mode 100644 Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift diff --git a/Riot/Generated/Storyboards.swift b/Riot/Generated/Storyboards.swift index 7a6f36b77..345c6a643 100644 --- a/Riot/Generated/Storyboards.swift +++ b/Riot/Generated/Storyboards.swift @@ -12,10 +12,20 @@ import UIKit // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name internal enum StoryboardScene { - internal enum LaunchScreen: StoryboardType { - internal static let storyboardName = "LaunchScreen" + internal enum KeyBackupSetupIntroViewController: StoryboardType { + internal static let storyboardName = "KeyBackupSetupIntroViewController" - internal static let initialScene = InitialSceneType(storyboard: LaunchScreen.self) + internal static let initialScene = InitialSceneType(storyboard: KeyBackupSetupIntroViewController.self) + } + internal enum KeyBackupSetupPassphraseViewController: StoryboardType { + internal static let storyboardName = "KeyBackupSetupPassphraseViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupSetupPassphraseViewController.self) + } + internal enum KeyBackupSetupRecoveryKeyViewController: StoryboardType { + internal static let storyboardName = "KeyBackupSetupRecoveryKeyViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupSetupRecoveryKeyViewController.self) } } // swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift new file mode 100644 index 000000000..74c95266b --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift @@ -0,0 +1,71 @@ +/* + Copyright 2019 New Vector 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 Foundation +import UIKit + +protocol KeyBackupSetupRecoveryKeyCoordinatorDelegate: class { + func keyBackupSetupRecoveryKeyCoordinatorDidCreateBackup(_ keyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType) + func keyBackupSetupRecoveryKeyCoordinatorDidCancel(_ keyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType) +} + +final class KeyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType { + + // MARK: - Properties + + // MARK: Private + + private var keyBackupSetupRecoveryKeyViewModel: KeyBackupSetupRecoveryKeyViewModelType + private let keyBackupSetupRecoveryKeyViewController: KeyBackupSetupRecoveryKeyViewController + + // MARK: Public + + var childCoordinators: [Coordinator] = [] + + weak var delegate: KeyBackupSetupRecoveryKeyCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession, megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { + let keyBackup = MXKeyBackup(matrixSession: session) + let keyBackupSetupRecoveryKeyViewModel = KeyBackupSetupRecoveryKeyViewModel(keyBackup: keyBackup, megolmBackupCreationInfo: megolmBackupCreationInfo) + let keyBackupSetupRecoveryKeyViewController = KeyBackupSetupRecoveryKeyViewController.instantiate(with: keyBackupSetupRecoveryKeyViewModel) + self.keyBackupSetupRecoveryKeyViewModel = keyBackupSetupRecoveryKeyViewModel + self.keyBackupSetupRecoveryKeyViewController = keyBackupSetupRecoveryKeyViewController + } + + // MARK: - Public methods + + func start() { + self.keyBackupSetupRecoveryKeyViewModel.coordinatorDelegate = self + } + + func toPresentable() -> UIViewController { + return self.keyBackupSetupRecoveryKeyViewController + } +} + +// MARK: - KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate +extension KeyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate { + + func keyBackupSetupRecoveryKeyViewModelDidCancel(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) { + self.delegate?.keyBackupSetupRecoveryKeyCoordinatorDidCancel(self) + } + + func keyBackupSetupRecoveryKeyViewModelDidCreateBackup(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) { + self.delegate?.keyBackupSetupRecoveryKeyCoordinatorDidCreateBackup(self) + } +} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinatorType.swift new file mode 100644 index 000000000..42a08cc63 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinatorType.swift @@ -0,0 +1,21 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// `KeyBackupSetupRecoveryKeyCoordinatorType` is a protocol describing a Coordinator that handle key backup setup recovery key navigation flow. +protocol KeyBackupSetupRecoveryKeyCoordinatorType: Coordinator, Presentable { +} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewAction.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewAction.swift new file mode 100644 index 000000000..edce649c7 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewAction.swift @@ -0,0 +1,25 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupSetupRecoveryKeyViewController view actions exposed to view model +enum KeyBackupSetupRecoveryKeyViewAction { + case madeCopy + case skip + case skipAlertSkip + case skipAlertContinue +} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.storyboard b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.storyboard new file mode 100644 index 000000000..311afc377 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.storyboard @@ -0,0 +1,220 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift new file mode 100644 index 000000000..0e154c506 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift @@ -0,0 +1,234 @@ +/* + Copyright 2019 New Vector 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 UIKit + +final class KeyBackupSetupRecoveryKeyViewController: UIViewController { + + // MARK: - Constants + + private enum Constants { + static let animationDuration: TimeInterval = 0.3 + } + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var recoveryKeyBackgroundView: UIView! + + @IBOutlet private weak var recoveryKeyTitleLabel: UILabel! + @IBOutlet private weak var recoveryKeyLabel: UILabel! + + @IBOutlet private weak var separatorView: UIView! + + @IBOutlet private weak var makeCopyButton: UIButton! + + @IBOutlet private weak var madeCopyButtonBackgroundView: UIView! + @IBOutlet private weak var madeCopyButton: UIButton! + + // MARK: Private + + private var theme: Theme! + private var hasMadeACopy: Bool = false + private var viewModel: KeyBackupSetupRecoveryKeyViewModelType! + private var errorPresenter: MXKErrorPresentation! + private var activityPresenter: ActivityIndicatorPresenter! + private weak var skipAlertController: UIAlertController? + + // MARK: - Setup + + class func instantiate(with viewModel: KeyBackupSetupRecoveryKeyViewModelType) -> KeyBackupSetupRecoveryKeyViewController { + let viewController = StoryboardScene.KeyBackupSetupRecoveryKeyViewController.initialScene.instantiate() + viewController.viewModel = viewModel + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupSetupTitle + + self.activityPresenter = ActivityIndicatorPresenter() + self.errorPresenter = MXKErrorAlertPresentation() + + self.setupViews() + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + + self.viewModel.viewDelegate = self + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.informationLabel.textColor = theme.textPrimaryColor + + self.recoveryKeyBackgroundView.backgroundColor = theme.backgroundColor + + self.recoveryKeyTitleLabel.textColor = theme.textPrimaryColor + self.recoveryKeyLabel.textColor = theme.textPrimaryColor + + self.separatorView.backgroundColor = theme.separatorColor + + theme.applyStyle(onButton: self.makeCopyButton) + + self.madeCopyButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.madeCopyButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func setupViews() { + let skipBarButtonItem = MXKBarButtonItem(title: VectorL10n.keyBackupSetupSkipAction, style: .plain) { [weak self] in + self?.skipButtonAction() + } + self.navigationItem.rightBarButtonItem = skipBarButtonItem + + self.informationLabel.text = VectorL10n.keyBackupSetupRecoveryKeyInfo + self.recoveryKeyTitleLabel.text = VectorL10n.keyBackupSetupRecoveryKeyRecoveryKeyTitle + self.recoveryKeyLabel.text = self.viewModel.recoveryKey + + self.makeCopyButton.setTitle(VectorL10n.keyBackupSetupRecoveryKeyMakeCopyAction, for: .normal) + self.madeCopyButton.setTitle(VectorL10n.keyBackupSetupRecoveryKeyMadeCopyAction, for: .normal) + + self.updateMadeCopyButton() + } + + private func shareRecoveryKey() { + + // Set up activity view controller + let activityItems: [Any] = [ self.viewModel.recoveryKey ] + let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) + + activityViewController.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in + + // Enable made copy button only if user has selected an activity item + if completed { + self.hasMadeACopy = true + self.updateMadeCopyButton() + } + } + + // Configure source view when activity view controller is presented with a popover + if let popoverPresentationController = activityViewController.popoverPresentationController { + popoverPresentationController.sourceView = self.makeCopyButton + popoverPresentationController.sourceRect = self.makeCopyButton.bounds + popoverPresentationController.permittedArrowDirections = [.down, .up] + } + + self.present(activityViewController, animated: true) + } + + private func updateMadeCopyButton() { + self.madeCopyButton.isEnabled = self.hasMadeACopy + } + + private func render(viewState: KeyBackupSetupRecoveryKeyViewState) { + switch viewState { + case .loading: + self.renderLoading() + case .loaded: + self.renderLoaded() + case .error(let error): + self.render(error: error) + } + } + + private func renderLoading() { + self.view.endEditing(true) + self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + } + + private func renderLoaded() { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + } + + private func render(error: Error) { + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } + + private func showSkipAlert() { + guard self.skipAlertController == nil else { + return + } + + let alertController = UIAlertController(title: VectorL10n.keyBackupSetupSkipAlertTitle, + message: VectorL10n.keyBackupSetupSkipAlertMessage, + preferredStyle:.alert) + + alertController.addAction(UIAlertAction(title: VectorL10n.continue, style: .cancel, handler: { action in + self.viewModel.process(viewAction: .skipAlertContinue) + })) + + alertController.addAction(UIAlertAction(title: VectorL10n.keyBackupSetupSkipAlertSkipAction, style: .default, handler: { action in + self.viewModel.process(viewAction: .skipAlertSkip) + })) + + self.present(alertController, animated: true, completion: nil) + self.skipAlertController = alertController + } + + // MARK: - Actions + + @IBAction private func makeCopyButtonAction(_ sender: Any) { + self.shareRecoveryKey() + } + + @IBAction private func madeCopyButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .madeCopy) + } + + private func skipButtonAction() { + self.viewModel.process(viewAction: .skip) + } +} + +// MARK: - KeyBackupSetupRecoveryKeyViewModelViewDelegate +extension KeyBackupSetupRecoveryKeyViewController: KeyBackupSetupRecoveryKeyViewModelViewDelegate { + func keyBackupSetupRecoveryKeyViewModel(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType, didUpdateViewState viewSate: KeyBackupSetupRecoveryKeyViewState) { + self.render(viewState: viewSate) + } + + func keyBackupSetupPassphraseViewModelShowSkipAlert(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) { + self.showSkipAlert() + } +} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift new file mode 100644 index 000000000..8959edfea --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift @@ -0,0 +1,102 @@ +/* + Copyright 2019 New Vector 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 Foundation + +final class KeyBackupSetupRecoveryKeyViewModel: KeyBackupSetupRecoveryKeyViewModelType { + + // MARK: - Properties + + // MARK: Private + + private let megolmBackupCreationInfo: MXMegolmBackupCreationInfo + private let keyBackup: MXKeyBackup + private let coordinatorDelegateQueue: OperationQueue + private var createKeyBackupOperation: MXHTTPOperation? + + // MARK: Public + + let recoveryKey: String + + weak var viewDelegate: KeyBackupSetupRecoveryKeyViewModelViewDelegate? + weak var coordinatorDelegate: KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate? + + // MARK: - Setup + + init(keyBackup: MXKeyBackup, megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { + self.megolmBackupCreationInfo = megolmBackupCreationInfo + self.recoveryKey = megolmBackupCreationInfo.recoveryKey + self.keyBackup = keyBackup + + let coordinatorDelegateQueue = OperationQueue() + coordinatorDelegateQueue.name = "KeyBackupSetupRecoveryKeyViewModel.coordinatorDelegateQueue" + coordinatorDelegateQueue.maxConcurrentOperationCount = 1 + self.coordinatorDelegateQueue = coordinatorDelegateQueue + } + + deinit { + self.createKeyBackupOperation?.cancel() + } + + // MARK: - Public + + func process(viewAction: KeyBackupSetupRecoveryKeyViewAction) { + switch viewAction { + case .madeCopy: + self.createBackup() + case .skip: + self.pauseCoordinatorOperations() + self.viewDelegate?.keyBackupSetupPassphraseViewModelShowSkipAlert(self) + case.skipAlertContinue: + self.resumeCoordinatorOperations() + case.skipAlertSkip: + self.createKeyBackupOperation?.cancel() + self.cancelCoordinatorOperations() + self.coordinatorDelegate?.keyBackupSetupRecoveryKeyViewModelDidCancel(self) + } + } + + // MARK: - Private + + func createBackup() { + self.viewDelegate?.keyBackupSetupRecoveryKeyViewModel(self, didUpdateViewState: .loading) + + self.keyBackup.createKeyBackupVersion(self.megolmBackupCreationInfo, success: { [weak self] (keyBackupVersion) in + guard let sself = self else { + return + } + sself.viewDelegate?.keyBackupSetupRecoveryKeyViewModel(sself, didUpdateViewState: .loaded) + sself.coordinatorDelegate?.keyBackupSetupRecoveryKeyViewModelDidCreateBackup(sself) + }, failure: { [weak self] error in + guard let sself = self else { + return + } + sself.viewDelegate?.keyBackupSetupRecoveryKeyViewModel(sself, didUpdateViewState: .error(error)) + }) + } + + private func pauseCoordinatorOperations() { + self.coordinatorDelegateQueue.isSuspended = true + } + + private func resumeCoordinatorOperations() { + self.coordinatorDelegateQueue.isSuspended = false + } + + private func cancelCoordinatorOperations() { + self.coordinatorDelegateQueue.cancelAllOperations() + } +} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift new file mode 100644 index 000000000..5b9da8a52 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift @@ -0,0 +1,38 @@ +/* + Copyright 2019 New Vector 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 Foundation + +protocol KeyBackupSetupRecoveryKeyViewModelViewDelegate: class { + func keyBackupSetupRecoveryKeyViewModel(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType, didUpdateViewState viewSate: KeyBackupSetupRecoveryKeyViewState) + func keyBackupSetupPassphraseViewModelShowSkipAlert(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) +} + +protocol KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate: class { + func keyBackupSetupRecoveryKeyViewModelDidCreateBackup(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) + func keyBackupSetupRecoveryKeyViewModelDidCancel(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) +} + +/// Protocol describing the view model used by `KeyBackupSetupRecoveryKeyViewController` +protocol KeyBackupSetupRecoveryKeyViewModelType { + + var recoveryKey: String { get } + + var viewDelegate: KeyBackupSetupRecoveryKeyViewModelViewDelegate? { get set } + var coordinatorDelegate: KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate? { get set } + + func process(viewAction: KeyBackupSetupRecoveryKeyViewAction) +} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift new file mode 100644 index 000000000..71331f3a7 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift @@ -0,0 +1,24 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupSetupRecoveryKeyViewController view state +enum KeyBackupSetupRecoveryKeyViewState { + case loading + case loaded + case error(Error) +} From 0840fb2260e3186e071dbc00fcdc9c31e4c94d71 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 11:05:48 +0100 Subject: [PATCH 092/244] Handle key backup setup navigation flow with KeyBackupSetupCoordinator --- .../Setup/KeyBackupSetupCoordinator.swift | 120 ++++++++++++++++++ .../Setup/KeyBackupSetupCoordinatorType.swift | 21 +++ 2 files changed, 141 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift create mode 100644 Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift new file mode 100644 index 000000000..432e438c7 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift @@ -0,0 +1,120 @@ +/* + Copyright 2019 New Vector 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 UIKit + +@objc protocol KeyBackupSetupCoordinatorDelegate: class { + func keyBackupSetupCoordinatorDidCancel(_ keyBackupSetupCoordinator: KeyBackupSetupCoordinator) + func keyBackupSetupCoordinatorDidSetupRecoveryKey(_ keyBackupSetupCoordinator: KeyBackupSetupCoordinator) +} + +@objcMembers +final class KeyBackupSetupCoordinator: NSObject, KeyBackupSetupCoordinatorType { + + // MARK: - Properties + + // MARK: Private + + private let navigationRouter: NavigationRouterType + private let session: MXSession + + // MARK: Public + + var childCoordinators: [Coordinator] = [] + + weak var delegate: KeyBackupSetupCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession) { + self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController()) + self.session = session + } + + // MARK: - Public methods + + func start() { + + // Set key backup setup intro as root controller + + let keyBackupSetupIntroViewController = KeyBackupSetupIntroViewController.instantiate() + keyBackupSetupIntroViewController.delegate = self + self.navigationRouter.setRootModule(keyBackupSetupIntroViewController) + } + + func toPresentable() -> UIViewController { + return self.navigationRouter.toPresentable() + } + + // MARK: - Private methods + + private func showSetupPassphrase(animated: Bool) { + let keyBackupSetupPassphraseCoordinator = KeyBackupSetupPassphraseCoordinator(session: self.session) + keyBackupSetupPassphraseCoordinator.delegate = self + keyBackupSetupPassphraseCoordinator.start() + + self.add(childCoordinator: keyBackupSetupPassphraseCoordinator) + self.navigationRouter.push(keyBackupSetupPassphraseCoordinator, animated: animated) { + self.remove(childCoordinator: keyBackupSetupPassphraseCoordinator) + } + } + + private func showRecoveryKey(with megolmBackupCreationInfo: MXMegolmBackupCreationInfo, animated: Bool) { + + let keyBackupSetupRecoveryKeyCoordinator = KeyBackupSetupRecoveryKeyCoordinator(session: self.session, megolmBackupCreationInfo: megolmBackupCreationInfo) + keyBackupSetupRecoveryKeyCoordinator.delegate = self + keyBackupSetupRecoveryKeyCoordinator.start() + + self.add(childCoordinator: keyBackupSetupRecoveryKeyCoordinator) + self.navigationRouter.push(keyBackupSetupRecoveryKeyCoordinator, animated: animated) { + self.remove(childCoordinator: keyBackupSetupRecoveryKeyCoordinator) + } + } +} + +// MARK: - KeyBackupSetupIntroViewControllerDelegate +extension KeyBackupSetupCoordinator: KeyBackupSetupIntroViewControllerDelegate { + + func keyBackupSetupIntroViewControllerDidTapSetupAction(_ keyBackupSetupIntroViewController: KeyBackupSetupIntroViewController) { + self.showSetupPassphrase(animated: true) + } + + func keyBackupSetupIntroViewControllerDidCancel(_ keyBackupSetupIntroViewController: KeyBackupSetupIntroViewController) { + self.delegate?.keyBackupSetupCoordinatorDidCancel(self) + } +} + +// MARK: - KeyRecoveryPassphraseCoordinatorDelegate +extension KeyBackupSetupCoordinator: KeyBackupSetupPassphraseCoordinatorDelegate { + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinator, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { + self.showRecoveryKey(with: megolmBackupCreationInfo, animated: true) + } + + func keyBackupSetupPassphraseCoordinatorDidCancel(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinator) { + self.delegate?.keyBackupSetupCoordinatorDidCancel(self) + } +} + +// MARK: - KeyBackupSetupRecoveryKeyCoordinatorDelegate +extension KeyBackupSetupCoordinator: KeyBackupSetupRecoveryKeyCoordinatorDelegate { + func keyBackupSetupRecoveryKeyCoordinatorDidCreateBackup(_ keyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType) { + self.delegate?.keyBackupSetupCoordinatorDidSetupRecoveryKey(self) + } + + func keyBackupSetupRecoveryKeyCoordinatorDidCancel(_ keyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType) { + self.delegate?.keyBackupSetupCoordinatorDidCancel(self) + } +} diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift new file mode 100644 index 000000000..f3c32dd5a --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift @@ -0,0 +1,21 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// `KeyBackupSetupCoordinatorType` is a protocol describing a Coordinator that handle keybackup setup navigation flow. +protocol KeyBackupSetupCoordinatorType: Coordinator, Presentable { +} From ef1ccefe5f965a07ed809466c5b90fcbff39e900 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 11:05:59 +0100 Subject: [PATCH 093/244] Update pbxproj --- Riot.xcodeproj/project.pbxproj | 226 +++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index e58805c27..ba328fbc8 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -37,6 +37,29 @@ B1098BE121ECE09F000DDA48 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDC21ECE09E000DDA48 /* Images.swift */; }; B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */; }; B1098BE521ECE1FC000DDA48 /* Storyboards.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BE421ECE1FC000DDA48 /* Storyboards.swift */; }; + B1098BE821ECFE52000DDA48 /* Coordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BE721ECFE51000DDA48 /* Coordinator.swift */; }; + B1098BF621ECFE65000DDA48 /* KeyBackupSetupPassphraseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BEA21ECFE64000DDA48 /* KeyBackupSetupPassphraseCoordinator.swift */; }; + B1098BF721ECFE65000DDA48 /* PasswordStrength.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BEB21ECFE64000DDA48 /* PasswordStrength.swift */; }; + B1098BF821ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1098BEC21ECFE64000DDA48 /* KeyBackupSetupPassphraseViewController.storyboard */; }; + B1098BF921ECFE65000DDA48 /* KeyBackupSetupCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BED21ECFE64000DDA48 /* KeyBackupSetupCoordinator.swift */; }; + B1098BFA21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BEE21ECFE64000DDA48 /* KeyBackupSetupPassphraseViewModel.swift */; }; + B1098BFB21ECFE65000DDA48 /* KeyBackupSetupCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BEF21ECFE64000DDA48 /* KeyBackupSetupCoordinatorType.swift */; }; + B1098BFC21ECFE65000DDA48 /* PasswordStrengthView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1098BF021ECFE64000DDA48 /* PasswordStrengthView.xib */; }; + B1098BFD21ECFE65000DDA48 /* PasswordStrengthManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BF121ECFE64000DDA48 /* PasswordStrengthManager.swift */; }; + B1098BFE21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BF221ECFE64000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift */; }; + B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BF321ECFE64000DDA48 /* PasswordStrengthView.swift */; }; + B1098C0021ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BF421ECFE64000DDA48 /* KeyBackupSetupPassphraseViewController.swift */; }; + B1098C0121ECFE65000DDA48 /* KeyBackupSetupPassphraseCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BF521ECFE64000DDA48 /* KeyBackupSetupPassphraseCoordinatorType.swift */; }; + B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */; }; + B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0B21ED07E4000DDA48 /* Presentable.swift */; }; + B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */; }; + B110871921EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */; }; + B110871B21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B110871A21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard */; }; + B110871D21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871C21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift */; }; + B110872321F098F0003554A5 /* ActivityIndicatorPresenterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871F21F098EF003554A5 /* ActivityIndicatorPresenterType.swift */; }; + B110872421F098F0003554A5 /* ActivityIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B110872021F098EF003554A5 /* ActivityIndicatorView.xib */; }; + B110872521F098F0003554A5 /* ActivityIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */; }; + B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872221F098F0003554A5 /* ActivityIndicatorView.swift */; }; B1664BC520F4E67600808783 /* FallbackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1664BAD20F4E67500808783 /* FallbackViewController.xib */; }; B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BAE20F4E67500808783 /* FallbackViewController.m */; }; B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BB220F4E67500808783 /* SharePresentingViewController.m */; }; @@ -315,7 +338,20 @@ B1B5599320EFC5E400210D55 /* DecryptionFailure.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5598D20EFC5E400210D55 /* DecryptionFailure.m */; }; B1B5599420EFC5E400210D55 /* DecryptionFailureTracker.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5599120EFC5E400210D55 /* DecryptionFailureTracker.m */; }; B1B9194C2118984300FE25B5 /* RoomPredecessorBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1B9194A2118984300FE25B5 /* RoomPredecessorBubbleCell.xib */; }; + B1CA3A2721EF6914000D1D89 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2621EF6913000D1D89 /* UIViewController.swift */; }; + B1CA3A2921EF692B000D1D89 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2821EF692B000D1D89 /* UIView.swift */; }; B1D250D82118AA0A000F4E93 /* RoomPredecessorBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D250D72118AA0A000F4E93 /* RoomPredecessorBubbleCell.m */; }; + B1D3F15B21F0E28F001AEF85 /* KeyBackupSetupRecoveryKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D3F15A21F0E28E001AEF85 /* KeyBackupSetupRecoveryKeyViewModel.swift */; }; + B1D3F15D21F0E29F001AEF85 /* KeyBackupSetupRecoveryKeyViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D3F15C21F0E29F001AEF85 /* KeyBackupSetupRecoveryKeyViewModelType.swift */; }; + B1D3F15F21F0E7BA001AEF85 /* KeyBackupSetupRecoveryKeyCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D3F15E21F0E7BA001AEF85 /* KeyBackupSetupRecoveryKeyCoordinatorType.swift */; }; + B1D3F16121F0E7CC001AEF85 /* KeyBackupSetupRecoveryKeyCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D3F16021F0E7CC001AEF85 /* KeyBackupSetupRecoveryKeyCoordinator.swift */; }; + B1D3F16321F0F1A7001AEF85 /* KeyBackupSetupRecoveryKeyViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D3F16221F0F1A7001AEF85 /* KeyBackupSetupRecoveryKeyViewState.swift */; }; + B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752521EE4E620067973F /* KeyboardAvoider.swift */; }; + B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752621EE4E620067973F /* KeyboardNotification.swift */; }; + B1D4752A21EE52B10067973F /* KeyBackupSetupIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752921EE52B10067973F /* KeyBackupSetupIntroViewController.swift */; }; + B1D4752C21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1D4752B21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard */; }; + B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */; }; + B1FDF56221F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF56121F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift */; }; CD9C4E21170ABE528E087A51 /* Pods_RiotPods_SiriIntents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC0B9DB497F579AB1084E3DC /* Pods_RiotPods_SiriIntents.framework */; }; F05927C91FDED836009F2A68 /* MXGroup+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = F05927C71FDED835009F2A68 /* MXGroup+Riot.m */; }; F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F083BB0D1E7009EC00A9B29C /* AppDelegate.m */; }; @@ -440,6 +476,29 @@ B1098BDC21ECE09E000DDA48 /* Images.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = ""; }; B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiotDefaults.swift; sourceTree = ""; }; B1098BE421ECE1FC000DDA48 /* Storyboards.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Storyboards.swift; sourceTree = ""; }; + B1098BE721ECFE51000DDA48 /* Coordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Coordinator.swift; sourceTree = ""; }; + B1098BEA21ECFE64000DDA48 /* KeyBackupSetupPassphraseCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseCoordinator.swift; sourceTree = ""; }; + B1098BEB21ECFE64000DDA48 /* PasswordStrength.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordStrength.swift; sourceTree = ""; }; + B1098BEC21ECFE64000DDA48 /* KeyBackupSetupPassphraseViewController.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = KeyBackupSetupPassphraseViewController.storyboard; sourceTree = ""; }; + B1098BED21ECFE64000DDA48 /* KeyBackupSetupCoordinator.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupCoordinator.swift; sourceTree = ""; }; + B1098BEE21ECFE64000DDA48 /* KeyBackupSetupPassphraseViewModel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewModel.swift; sourceTree = ""; }; + B1098BEF21ECFE64000DDA48 /* KeyBackupSetupCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupCoordinatorType.swift; sourceTree = ""; }; + B1098BF021ECFE64000DDA48 /* PasswordStrengthView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PasswordStrengthView.xib; sourceTree = ""; }; + B1098BF121ECFE64000DDA48 /* PasswordStrengthManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordStrengthManager.swift; sourceTree = ""; }; + B1098BF221ECFE64000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewModelType.swift; sourceTree = ""; }; + B1098BF321ECFE64000DDA48 /* PasswordStrengthView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PasswordStrengthView.swift; sourceTree = ""; }; + B1098BF421ECFE64000DDA48 /* KeyBackupSetupPassphraseViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewController.swift; sourceTree = ""; }; + B1098BF521ECFE64000DDA48 /* KeyBackupSetupPassphraseCoordinatorType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseCoordinatorType.swift; sourceTree = ""; }; + B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; + B1098C0B21ED07E4000DDA48 /* Presentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = ""; }; + B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = ""; }; + B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewController.swift; sourceTree = ""; }; + B110871A21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupSetupRecoveryKeyViewController.storyboard; sourceTree = ""; }; + B110871C21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewState.swift; sourceTree = ""; }; + B110871F21F098EF003554A5 /* ActivityIndicatorPresenterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorPresenterType.swift; sourceTree = ""; }; + B110872021F098EF003554A5 /* ActivityIndicatorView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ActivityIndicatorView.xib; sourceTree = ""; }; + B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorPresenter.swift; sourceTree = ""; }; + B110872221F098F0003554A5 /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = ""; }; B1664BAD20F4E67500808783 /* FallbackViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FallbackViewController.xib; sourceTree = ""; }; B1664BAE20F4E67500808783 /* FallbackViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FallbackViewController.m; sourceTree = ""; }; B1664BAF20F4E67500808783 /* FallbackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FallbackViewController.h; sourceTree = ""; }; @@ -902,8 +961,21 @@ B1B5599020EFC5E400210D55 /* Analytics.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Analytics.h; sourceTree = ""; }; B1B5599120EFC5E400210D55 /* DecryptionFailureTracker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DecryptionFailureTracker.m; sourceTree = ""; }; B1B9194A2118984300FE25B5 /* RoomPredecessorBubbleCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RoomPredecessorBubbleCell.xib; sourceTree = ""; }; + B1CA3A2621EF6913000D1D89 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; + B1CA3A2821EF692B000D1D89 /* UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; B1D250D62118AA0A000F4E93 /* RoomPredecessorBubbleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoomPredecessorBubbleCell.h; sourceTree = ""; }; B1D250D72118AA0A000F4E93 /* RoomPredecessorBubbleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoomPredecessorBubbleCell.m; sourceTree = ""; }; + B1D3F15A21F0E28E001AEF85 /* KeyBackupSetupRecoveryKeyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewModel.swift; sourceTree = ""; }; + B1D3F15C21F0E29F001AEF85 /* KeyBackupSetupRecoveryKeyViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewModelType.swift; sourceTree = ""; }; + B1D3F15E21F0E7BA001AEF85 /* KeyBackupSetupRecoveryKeyCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyCoordinatorType.swift; sourceTree = ""; }; + B1D3F16021F0E7CC001AEF85 /* KeyBackupSetupRecoveryKeyCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyCoordinator.swift; sourceTree = ""; }; + B1D3F16221F0F1A7001AEF85 /* KeyBackupSetupRecoveryKeyViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewState.swift; sourceTree = ""; }; + B1D4752521EE4E620067973F /* KeyboardAvoider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardAvoider.swift; sourceTree = ""; }; + B1D4752621EE4E620067973F /* KeyboardNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardNotification.swift; sourceTree = ""; }; + B1D4752921EE52B10067973F /* KeyBackupSetupIntroViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupIntroViewController.swift; sourceTree = ""; }; + B1D4752B21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupSetupIntroViewController.storyboard; sourceTree = ""; }; + B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewAction.swift; sourceTree = ""; }; + B1FDF56121F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewAction.swift; sourceTree = ""; }; B4B35D08E11507BEE733BBC4 /* Pods-RiotPods-SiriIntents.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-SiriIntents.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-SiriIntents/Pods-RiotPods-SiriIntents.debug.xcconfig"; sourceTree = ""; }; BC0B9DB497F579AB1084E3DC /* Pods_RiotPods_SiriIntents.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RiotPods_SiriIntents.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D523D0ED52562EDD393BE0F0 /* Pods-RiotPods-RiotShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-RiotShareExtension.release.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-RiotShareExtension/Pods-RiotPods-RiotShareExtension.release.xcconfig"; sourceTree = ""; }; @@ -1086,6 +1158,96 @@ path = Generated; sourceTree = ""; }; + B1098BE621ECFE51000DDA48 /* Coordinators */ = { + isa = PBXGroup; + children = ( + B1098BE721ECFE51000DDA48 /* Coordinator.swift */, + ); + path = Coordinators; + sourceTree = ""; + }; + B1098BE921ECFE64000DDA48 /* KeyBackup */ = { + isa = PBXGroup; + children = ( + B1098C0221ECFEAF000DDA48 /* Setup */, + ); + path = KeyBackup; + sourceTree = ""; + }; + B1098C0221ECFEAF000DDA48 /* Setup */ = { + isa = PBXGroup; + children = ( + B1098BEF21ECFE64000DDA48 /* KeyBackupSetupCoordinatorType.swift */, + B1098BED21ECFE64000DDA48 /* KeyBackupSetupCoordinator.swift */, + B1098C0521ECFF5B000DDA48 /* Intro */, + B1098C0321ECFECC000DDA48 /* Passphrase */, + B1098C0621ED00A9000DDA48 /* RecoveryKey */, + ); + path = Setup; + sourceTree = ""; + }; + B1098C0321ECFECC000DDA48 /* Passphrase */ = { + isa = PBXGroup; + children = ( + B1098BF521ECFE64000DDA48 /* KeyBackupSetupPassphraseCoordinatorType.swift */, + B1098BEA21ECFE64000DDA48 /* KeyBackupSetupPassphraseCoordinator.swift */, + B1098BF221ECFE64000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift */, + B1098BEE21ECFE64000DDA48 /* KeyBackupSetupPassphraseViewModel.swift */, + B110871C21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift */, + B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */, + B1098BF421ECFE64000DDA48 /* KeyBackupSetupPassphraseViewController.swift */, + B1098BEC21ECFE64000DDA48 /* KeyBackupSetupPassphraseViewController.storyboard */, + B1098BF321ECFE64000DDA48 /* PasswordStrengthView.swift */, + B1098BF021ECFE64000DDA48 /* PasswordStrengthView.xib */, + ); + path = Passphrase; + sourceTree = ""; + }; + B1098C0521ECFF5B000DDA48 /* Intro */ = { + isa = PBXGroup; + children = ( + B1D4752921EE52B10067973F /* KeyBackupSetupIntroViewController.swift */, + B1D4752B21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard */, + ); + path = Intro; + sourceTree = ""; + }; + B1098C0621ED00A9000DDA48 /* RecoveryKey */ = { + isa = PBXGroup; + children = ( + B1D3F15E21F0E7BA001AEF85 /* KeyBackupSetupRecoveryKeyCoordinatorType.swift */, + B1D3F16021F0E7CC001AEF85 /* KeyBackupSetupRecoveryKeyCoordinator.swift */, + B1D3F15C21F0E29F001AEF85 /* KeyBackupSetupRecoveryKeyViewModelType.swift */, + B1D3F15A21F0E28E001AEF85 /* KeyBackupSetupRecoveryKeyViewModel.swift */, + B1D3F16221F0F1A7001AEF85 /* KeyBackupSetupRecoveryKeyViewState.swift */, + B1FDF56121F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift */, + B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */, + B110871A21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard */, + ); + path = RecoveryKey; + sourceTree = ""; + }; + B1098C0721ED07E4000DDA48 /* Routers */ = { + isa = PBXGroup; + children = ( + B1098C0B21ED07E4000DDA48 /* Presentable.swift */, + B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */, + B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */, + ); + path = Routers; + sourceTree = ""; + }; + B110871E21F098EF003554A5 /* ActivityIndicator */ = { + isa = PBXGroup; + children = ( + B110871F21F098EF003554A5 /* ActivityIndicatorPresenterType.swift */, + B110872021F098EF003554A5 /* ActivityIndicatorView.xib */, + B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */, + B110872221F098F0003554A5 /* ActivityIndicatorView.swift */, + ); + path = ActivityIndicator; + sourceTree = ""; + }; B1664BAB20F4E67500808783 /* Modules */ = { isa = PBXGroup; children = ( @@ -1366,6 +1528,7 @@ B1B5596B20EFA85C00210D55 /* EncryptionInfo */, B1B556FD20EE6C4C00210D55 /* RoomKeyRequest */, B1B556B020EE6C4C00210D55 /* BugReport */, + B1098BE921ECFE64000DDA48 /* KeyBackup */, B1B556CD20EE6C4C00210D55 /* Common */, ); path = Modules; @@ -1636,6 +1799,8 @@ B1B556D420EE6C4C00210D55 /* SegmentedViewController */, B1B556D820EE6C4C00210D55 /* Recents */, B1B5592720EF7A5D00210D55 /* Cells */, + B1D4752421EE4E620067973F /* KeyboardAvoiding */, + B110871E21F098EF003554A5 /* ActivityIndicator */, ); path = Common; sourceTree = ""; @@ -2375,6 +2540,7 @@ B1B5597C20EFC3DF00210D55 /* Managers */ = { isa = PBXGroup; children = ( + B1FDF56321F68C0700BA3834 /* PasswordStrength */, B1798300211B137B001FD722 /* OnBoarding */, B1B5598B20EFC5E400210D55 /* Analytics */, B1B5598920EFC41100210D55 /* BugReport */, @@ -2426,6 +2592,24 @@ path = Analytics; sourceTree = ""; }; + B1D4752421EE4E620067973F /* KeyboardAvoiding */ = { + isa = PBXGroup; + children = ( + B1D4752521EE4E620067973F /* KeyboardAvoider.swift */, + B1D4752621EE4E620067973F /* KeyboardNotification.swift */, + ); + path = KeyboardAvoiding; + sourceTree = ""; + }; + B1FDF56321F68C0700BA3834 /* PasswordStrength */ = { + isa = PBXGroup; + children = ( + B1098BEB21ECFE64000DDA48 /* PasswordStrength.swift */, + B1098BF121ECFE64000DDA48 /* PasswordStrengthManager.swift */, + ); + path = PasswordStrength; + sourceTree = ""; + }; F083BB021E7005FD00A9B29C /* RiotTests */ = { isa = PBXGroup; children = ( @@ -2450,6 +2634,8 @@ F083BB0D1E7009EC00A9B29C /* AppDelegate.m */, B1098BD921ECE09E000DDA48 /* Generated */, F083BBE41E7009EC00A9B29C /* Categories */, + B1098BE621ECFE51000DDA48 /* Coordinators */, + B1098C0721ED07E4000DDA48 /* Routers */, F083BBF21E7009EC00A9B29C /* Model */, B1B5597C20EFC3DF00210D55 /* Managers */, B1B5567620EE6C4C00210D55 /* Modules */, @@ -2509,6 +2695,8 @@ 926FA53D1F4C132000F826C2 /* MXSession+Riot.h */, 926FA53E1F4C132000F826C2 /* MXSession+Riot.m */, 32242F0821E8B05F00725742 /* UIColor.swift */, + B1CA3A2621EF6913000D1D89 /* UIViewController.swift */, + B1CA3A2821EF692B000D1D89 /* UIView.swift */, ); path = Categories; sourceTree = ""; @@ -2768,6 +2956,7 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( + B110871B21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard in Resources */, B1B5590220EF768F00210D55 /* RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib in Resources */, B1B558CA20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib in Resources */, F083BDE91E7009ED00A9B29C /* ring.mp3 in Resources */, @@ -2820,7 +3009,9 @@ F083BDE81E7009ED00A9B29C /* message.mp3 in Resources */, B1B5579C20EF575B00210D55 /* ForgotPasswordInputsView.xib in Resources */, F083BE011E7009ED00A9B29C /* third_party_licenses.html in Resources */, + B1098BFC21ECFE65000DDA48 /* PasswordStrengthView.xib in Resources */, B1B5573720EE6C4D00210D55 /* GroupParticipantsViewController.xib in Resources */, + B110872421F098F0003554A5 /* ActivityIndicatorView.xib in Resources */, B1B5573320EE6C4D00210D55 /* GroupHomeViewController.xib in Resources */, B1B5593920EF7BAC00210D55 /* TableViewCellWithCheckBoxes.xib in Resources */, B1B557C120EF5B4500210D55 /* DisabledRoomInputToolbarView.xib in Resources */, @@ -2852,6 +3043,7 @@ B1B5572D20EE6C4D00210D55 /* RoomParticipantsViewController.xib in Resources */, B1B5577220EE702800210D55 /* JitsiViewController.xib in Resources */, B1B557D720EF5EA900210D55 /* RoomActivitiesView.xib in Resources */, + B1098BF821ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.storyboard in Resources */, F083BDF31E7009ED00A9B29C /* Images.xcassets in Resources */, B1B5590720EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib in Resources */, B169329920F39E6300746532 /* LaunchScreen.storyboard in Resources */, @@ -2884,6 +3076,7 @@ B1B558FD20EF768F00210D55 /* RoomIncomingAttachmentBubbleCell.xib in Resources */, B1B558DB20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib in Resources */, B1B5572B20EE6C4D00210D55 /* RoomMemberDetailsViewController.xib in Resources */, + B1D4752C21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard in Resources */, B1B558C620EF768F00210D55 /* RoomIncomingEncryptedAttachmentBubbleCell.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -2939,6 +3132,7 @@ "${BUILT_PRODUCTS_DIR}/cmark/cmark.framework", "${BUILT_PRODUCTS_DIR}/libPhoneNumber-iOS/libPhoneNumber_iOS.framework", "${BUILT_PRODUCTS_DIR}/libbase58/libbase58.framework", + "${BUILT_PRODUCTS_DIR}/zxcvbn-ios/zxcvbn_ios.framework", "${BUILT_PRODUCTS_DIR}/DTCoreText.default-Extension/DTCoreText.framework", "${BUILT_PRODUCTS_DIR}/MatrixKit-AppExtension/MatrixKit.framework", ); @@ -2960,6 +3154,7 @@ "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cmark.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libPhoneNumber_iOS.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libbase58.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/zxcvbn_ios.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; @@ -3066,6 +3261,7 @@ F083BE021E7009ED00A9B29C /* AvatarGenerator.m in Sources */, B1B5573A20EE6C4D00210D55 /* GroupRoomsViewController.m in Sources */, B1B558F920EF768F00210D55 /* RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m in Sources */, + B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */, B1B5573120EE6C4D00210D55 /* BugReportViewController.m in Sources */, B16932A520F3A21C00746532 /* empty.mm in Sources */, B16932FA20F3C51A00746532 /* RecentCellData.m in Sources */, @@ -3086,7 +3282,10 @@ B1B5572220EE6C4D00210D55 /* RoomSettingsViewController.m in Sources */, B1B5577320EE702800210D55 /* JitsiViewController.m in Sources */, B169331620F3CAFC00746532 /* PublicRoomsDirectoryDataSource.m in Sources */, + B110871D21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift in Sources */, + B1098C0121ECFE65000DDA48 /* KeyBackupSetupPassphraseCoordinatorType.swift in Sources */, 32242F1221E8FBA900725742 /* ThemeService.m in Sources */, + B1D3F16321F0F1A7001AEF85 /* KeyBackupSetupRecoveryKeyViewState.swift in Sources */, B1B558E820EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */, B1B558F320EF768F00210D55 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, B1B557BD20EF5B4500210D55 /* KeyboardGrowingTextView.m in Sources */, @@ -3100,8 +3299,13 @@ B1B5572F20EE6C4D00210D55 /* ReadReceiptsViewController.m in Sources */, B1B558CB20EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */, B169330B20F3CA3A00746532 /* Contact.m in Sources */, + B1D4752A21EE52B10067973F /* KeyBackupSetupIntroViewController.swift in Sources */, B1B5599220EFC5E400210D55 /* Analytics.m in Sources */, + B1098BF621ECFE65000DDA48 /* KeyBackupSetupPassphraseCoordinator.swift in Sources */, + B1D3F16121F0E7CC001AEF85 /* KeyBackupSetupRecoveryKeyCoordinator.swift in Sources */, + B1D3F15D21F0E29F001AEF85 /* KeyBackupSetupRecoveryKeyViewModelType.swift in Sources */, B1B558C320EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m in Sources */, + B110872521F098F0003554A5 /* ActivityIndicatorPresenter.swift in Sources */, 32242F1521E8FBA900725742 /* DarkTheme.swift in Sources */, B1B5577420EE702900210D55 /* WidgetViewController.m in Sources */, B1B5574A20EE6C4D00210D55 /* MediaPickerViewController.m in Sources */, @@ -3113,12 +3317,14 @@ B1B5594720EF7BD000210D55 /* RoomCollectionViewCell.m in Sources */, B1B558C120EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */, B1B5573E20EE6C4D00210D55 /* RiotNavigationController.m in Sources */, + B1FDF56221F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift in Sources */, B1B5593B20EF7BAC00210D55 /* TableViewCellWithCheckBoxAndLabel.m in Sources */, B1B5581A20EF625800210D55 /* ExpandedRoomTitleView.m in Sources */, B1B558E920EF768F00210D55 /* RoomSelectedStickerBubbleCell.m in Sources */, B1B558DF20EF768F00210D55 /* RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m in Sources */, F083BE041E7009ED00A9B29C /* Tools.m in Sources */, 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */, + B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */, B1B5573D20EE6C4D00210D55 /* WebViewViewController.m in Sources */, 3209451221F1C1430088CAA2 /* BlackTheme.swift in Sources */, B1B5572720EE6C4D00210D55 /* RoomSearchViewController.m in Sources */, @@ -3132,6 +3338,8 @@ B1B5590520EF768F00210D55 /* RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m in Sources */, B1B558DD20EF768F00210D55 /* RoomIncomingEncryptedTextMsgBubbleCell.m in Sources */, B1098BE521ECE1FC000DDA48 /* Storyboards.swift in Sources */, + B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */, + B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */, B1B5573C20EE6C4D00210D55 /* MasterTabBarController.m in Sources */, B1B5592C20EF7A5D00210D55 /* TableViewCellWithButton.m in Sources */, 32242F1421E8FBA900725742 /* DefaultTheme.swift in Sources */, @@ -3143,14 +3351,18 @@ B1B5572A20EE6C4D00210D55 /* RoomMemberDetailsViewController.m in Sources */, B1B5590120EF768F00210D55 /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m in Sources */, B1B558C920EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */, + B110871921EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift in Sources */, B1B5571B20EE6C4D00210D55 /* DeactivateAccountViewController.m in Sources */, B1B5590620EF768F00210D55 /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */, F083BE031E7009ED00A9B29C /* EventFormatter.m in Sources */, B16932F720F3C50E00746532 /* RecentsDataSource.m in Sources */, B1B558FC20EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */, + B1D3F15B21F0E28F001AEF85 /* KeyBackupSetupRecoveryKeyViewModel.swift in Sources */, B1B5572920EE6C4D00210D55 /* RoomFilesViewController.m in Sources */, + B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */, B1B558E020EF768F00210D55 /* RoomOutgoingTextMsgBubbleCell.m in Sources */, B1B5593C20EF7BAC00210D55 /* TableViewCellWithCheckBoxes.m in Sources */, + B1CA3A2721EF6914000D1D89 /* UIViewController.swift in Sources */, F0D2ADA11F6AA5FD00A7097D /* MXRoomSummary+Riot.m in Sources */, B1B5596F20EFA85D00210D55 /* EncryptionInfoView.m in Sources */, B1B5573820EE6C4D00210D55 /* GroupParticipantsViewController.m in Sources */, @@ -3165,11 +3377,14 @@ B1B557DE20EF5FBB00210D55 /* FilesSearchTableViewCell.m in Sources */, B1B5574020EE6C4D00210D55 /* SegmentedViewController.m in Sources */, B1B5599320EFC5E400210D55 /* DecryptionFailure.m in Sources */, + B1098BF921ECFE65000DDA48 /* KeyBackupSetupCoordinator.swift in Sources */, + B1098BFE21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift in Sources */, B1B558BE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */, F083BDED1E7009ED00A9B29C /* MXKRoomBubbleTableViewCell+Riot.m in Sources */, B1B557A820EF5A1B00210D55 /* DeviceTableViewCell.m in Sources */, B1B5572620EE6C4D00210D55 /* RoomFilesSearchViewController.m in Sources */, B1B5583120EF66BA00210D55 /* RoomIdOrAliasTableViewCell.m in Sources */, + B1CA3A2921EF692B000D1D89 /* UIView.swift in Sources */, F083BDFA1E7009ED00A9B29C /* RoomPreviewData.m in Sources */, B1B557B420EF5AEF00210D55 /* EventDetailsView.m in Sources */, B1B5577E20EE84BF00210D55 /* IncomingCallView.m in Sources */, @@ -3183,15 +3398,19 @@ B1B5581920EF625800210D55 /* RoomTitleView.m in Sources */, B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */, B1B557BE20EF5B4500210D55 /* RoomInputToolbarView.m in Sources */, + B1D3F15F21F0E7BA001AEF85 /* KeyBackupSetupRecoveryKeyCoordinatorType.swift in Sources */, B1B5573B20EE6C4D00210D55 /* FavouritesViewController.m in Sources */, B1B5579920EF575B00210D55 /* AuthInputsView.m in Sources */, B1B5597520EFB02A00210D55 /* InviteRecentTableViewCell.m in Sources */, B1B5571E20EE6C4D00210D55 /* ContactDetailsViewController.m in Sources */, B1798302211B13B3001FD722 /* OnBoardingManager.swift in Sources */, B1B5573520EE6C4D00210D55 /* GroupDetailsViewController.m in Sources */, + B1098BFA21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModel.swift in Sources */, B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */, F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */, B1B558E620EF768F00210D55 /* RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, + B1098BFB21ECFE65000DDA48 /* KeyBackupSetupCoordinatorType.swift in Sources */, + B1098BF721ECFE65000DDA48 /* PasswordStrength.swift in Sources */, B1B557D820EF5EA900210D55 /* RoomActivitiesView.m in Sources */, B1B5596620EF9E9B00210D55 /* RoomTableViewCell.m in Sources */, B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, @@ -3210,11 +3429,16 @@ B1B557C620EF5CD400210D55 /* DirectoryServerDetailTableViewCell.m in Sources */, B1B5590920EF768F00210D55 /* RoomEmptyBubbleCell.m in Sources */, B1B5574720EE6C4D00210D55 /* UsersDevicesViewController.m in Sources */, + B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */, B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */, B1B558FA20EF768F00210D55 /* RoomMembershipBubbleCell.m in Sources */, B1B557BF20EF5B4500210D55 /* DisabledRoomInputToolbarView.m in Sources */, B1B5578620EF564900210D55 /* GroupTableViewCellWithSwitch.m in Sources */, + B1098BE821ECFE52000DDA48 /* Coordinator.swift in Sources */, B1B557E920EF60F500210D55 /* MessagesSearchResultTextMsgBubbleCell.m in Sources */, + B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */, + B110872321F098F0003554A5 /* ActivityIndicatorPresenterType.swift in Sources */, + B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */, B169330320F3C98900746532 /* RoomBubbleCellData.m in Sources */, B1B557CC20EF5D8000210D55 /* DirectoryServerTableViewCell.m in Sources */, B1B5575C20EE6C4D00210D55 /* DirectoryViewController.m in Sources */, @@ -3233,6 +3457,7 @@ B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, + B1098BFD21ECFE65000DDA48 /* PasswordStrengthManager.swift in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, 32242F0921E8B05F00725742 /* UIColor.swift in Sources */, @@ -3240,6 +3465,7 @@ B1B558CE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.m in Sources */, B1B5577D20EE84BF00210D55 /* CircleButton.m in Sources */, B1B558FF20EF768F00210D55 /* RoomIncomingTextMsgBubbleCell.m in Sources */, + B1098C0021ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.swift in Sources */, B1B5591020EF782800210D55 /* TableViewCellWithPhoneNumberTextField.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; From c649c4c957c50170bb7b1de0187f82776c2476c7 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 11:13:26 +0100 Subject: [PATCH 094/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 0c32d434f..7ea1daa35 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,6 +7,7 @@ Improvements: * Add SwiftGen pod in order to generate Swift constants for assets (#2177). * RoomVC: `Redact` has been renamed to `Remove` to match riot/web (#2134). * Clean up iOS version checking (#2190). + * Key backup: Implement setup screen (#2198). Bug fix: * Use white scroll bar on dark themes (#2158). From aa797359e5bc37fbaf2a0b90459741cd311df866 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 15:26:34 +0100 Subject: [PATCH 095/244] Update ActivityIndicatorView and ActivityIndicatorPresenter to match activity indicator UI in MXKViewController --- .../ActivityIndicatorPresenter.swift | 4 +-- .../ActivityIndicatorView.swift | 18 ++++++++++- .../ActivityIndicatorView.xib | 31 ++++++++++++++----- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift index 41b569446..6acfaec94 100755 --- a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorPresenter.swift @@ -24,8 +24,8 @@ final class ActivityIndicatorPresenter: ActivityIndicatorPresenterType { private enum Constants { static let animationDuration: TimeInterval = 0.3 - static let backgroundOverlayColor = UIColor.black - static let backgroundOverlayAlpha: CGFloat = 0.3 + static let backgroundOverlayColor = UIColor.clear + static let backgroundOverlayAlpha: CGFloat = 1.0 } // MARK: - Properties diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift index 4519854ba..8ab41098f 100755 --- a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.swift @@ -19,11 +19,19 @@ import Reusable final class ActivityIndicatorView: UIView, NibOwnerLoadable { + // MARK: - Constants + + private enum Constants { + static let cornerRadius: CGFloat = 5.0 + static let activityIndicatorMargin = CGSize(width: 30.0, height: 30.0) + } + // MARK: - Properties // MARK: Outlets @IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView! + @IBOutlet private weak var activityIndicatorBackgroundView: UIView! // MARK: Public @@ -39,6 +47,7 @@ final class ActivityIndicatorView: UIView, NibOwnerLoadable { // MARK: - Setup private func commonInit() { + self.activityIndicatorBackgroundView.layer.masksToBounds = true } convenience init() { @@ -60,7 +69,14 @@ final class ActivityIndicatorView: UIView, NibOwnerLoadable { // MARK: - Overrides override var intrinsicContentSize: CGSize { - return CGSize(width: self.activityIndicatorView.intrinsicContentSize.width, height: self.activityIndicatorView.intrinsicContentSize.height) + return CGSize(width: self.activityIndicatorView.intrinsicContentSize.width + Constants.activityIndicatorMargin.width, + height: self.activityIndicatorView.intrinsicContentSize.height + Constants.activityIndicatorMargin.height) + } + + override func layoutSubviews() { + super.layoutSubviews() + + self.activityIndicatorBackgroundView.layer.cornerRadius = Constants.cornerRadius } // MARK: - Public diff --git a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib index 9dddf369c..874a4e665 100755 --- a/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib +++ b/Riot/Modules/Common/ActivityIndicator/ActivityIndicatorView.xib @@ -1,17 +1,18 @@ - + - + - + + @@ -20,14 +21,28 @@ - - - + + + + + + + + + + + + + + + - - + + + + From a478663351e1f01948787aae7a52473f557203a1 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 22 Jan 2019 15:46:26 +0100 Subject: [PATCH 096/244] Update reveal password margin on KeyBackupSetupPassphraseViewController --- .../KeyBackupSetupPassphraseViewController.storyboard | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard index 3f1e48e8f..a72291f90 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard @@ -52,7 +52,7 @@ You’ll need it if you log out, or lose access to this device. - + @@ -64,7 +64,7 @@ You’ll need it if you log out, or lose access to this device. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift new file mode 100644 index 000000000..9a5830204 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift @@ -0,0 +1,229 @@ +/* + Copyright 2019 New Vector 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 UIKit + +final class KeyBackupRecoverFromPassphraseViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var scrollView: UIScrollView! + + @IBOutlet private weak var shieldImageView: UIImageView! + + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var passphraseTitleLabel: UILabel! + @IBOutlet private weak var passphraseTextField: UITextField! + @IBOutlet private weak var passphraseTextFieldBackgroundView: UIView! + + @IBOutlet private weak var passphraseVisibilityButton: UIButton! + + @IBOutlet private weak var unknownPassphraseButton: UIButton! + + @IBOutlet private weak var recoverButtonBackgroundView: UIView! + @IBOutlet private weak var recoverButton: UIButton! + + // MARK: Private + + private var viewModel: KeyBackupRecoverFromPassphraseViewModelType! + private var keyboardAvoider: KeyboardAvoider? + private var theme: Theme! + private var errorPresenter: MXKErrorPresentation! + private var activityPresenter: ActivityIndicatorPresenter! + + // MARK: Public + + // MARK: - Setup + + class func instantiate(with viewModel: KeyBackupRecoverFromPassphraseViewModelType) -> KeyBackupRecoverFromPassphraseViewController { + let viewController = StoryboardScene.KeyBackupRecoverFromPassphraseViewController.initialScene.instantiate() + viewController.viewModel = viewModel + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupRecoverTitle + self.vc_removeBackTitle() + + self.setupViews() + self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView) + self.activityPresenter = ActivityIndicatorPresenter() + self.errorPresenter = MXKErrorAlertPresentation() + + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + + self.viewModel.viewDelegate = self + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.viewModel.process(viewAction: .cancel) + } + + self.navigationItem.rightBarButtonItem = cancelBarButtonItem + + self.scrollView.keyboardDismissMode = .interactive + + let shieldImage = Asset.Images.shield.image.withRenderingMode(.alwaysTemplate) + self.shieldImageView.image = shieldImage + + let visibilityImage = Asset.Images.revealPasswordButton.image.withRenderingMode(.alwaysTemplate) + self.passphraseVisibilityButton.setImage(visibilityImage, for: .normal) + + self.informationLabel.text = VectorL10n.keyBackupRecoverFromPassphraseInfo + + self.passphraseTitleLabel.text = VectorL10n.keyBackupRecoverFromPassphrasePassphraseTitle + self.passphraseTextField.addTarget(self, action: #selector(passphraseTextFieldDidChange(_:)), for: .editingChanged) + + self.unknownPassphraseButton.vc_enableMultiLinesTitle() + + self.recoverButton.vc_enableMultiLinesTitle() + self.recoverButton.setTitle(VectorL10n.keyBackupRecoverFromPassphraseRecoverAction, for: .normal) + + self.updateRecoverButton() + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.informationLabel.textColor = theme.textPrimaryColor + + self.shieldImageView.tintColor = theme.textPrimaryColor + + self.passphraseTextFieldBackgroundView.backgroundColor = theme.backgroundColor + self.passphraseTitleLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onTextField: self.passphraseTextField) + self.passphraseTextField.attributedPlaceholder = NSAttributedString(string: VectorL10n.keyBackupRecoverFromPassphrasePassphrasePlaceholder, + attributes: [.foregroundColor : theme.placeholderTextColor]) + + self.theme.applyStyle(onButton: self.passphraseVisibilityButton) + + self.recoverButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.recoverButton) + + let unknownRecoveryKeyAttributedString = NSMutableAttributedString(string: VectorL10n.keyBackupRecoverFromPassphraseLostPassphraseActionPart1, attributes: [.foregroundColor : self.theme.textPrimaryColor]) + let unknownRecoveryKeyAttributedStringPart2 = NSAttributedString(string: VectorL10n.keyBackupRecoverFromPassphraseLostPassphraseActionPart2, attributes: [.foregroundColor : self.theme.tintColor]) + let unknownRecoveryKeyAttributedStringPart3 = NSAttributedString(string: VectorL10n.keyBackupRecoverFromPassphraseLostPassphraseActionPart3, attributes: [.foregroundColor : self.theme.textPrimaryColor]) + + unknownRecoveryKeyAttributedString.append(unknownRecoveryKeyAttributedStringPart2) + unknownRecoveryKeyAttributedString.append(unknownRecoveryKeyAttributedStringPart3) + + self.unknownPassphraseButton.setAttributedTitle(unknownRecoveryKeyAttributedString, for: .normal) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func updateRecoverButton() { + self.recoverButton.isEnabled = self.viewModel.isFormValid + } + + private func render(viewState: KeyBackupRecoverFromPassphraseViewState) { + switch viewState { + case .loading: + self.renderLoading() + case .loaded(totalKeys: let totalKeys): + self.renderLoaded(with: totalKeys) + case .error(let error): + self.render(error: error) + } + } + + private func renderLoading() { + self.view.endEditing(true) + self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + } + + private func renderLoaded(with totalKeys: UInt) { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + + if totalKeys == 0 { + self.errorPresenter.presentError(from: self, + title: VectorL10n.keyBackupRecoverEmptyBackupTitle, + message: VectorL10n.keyBackupRecoverEmptyBackupMessage, + animated: true, + handler: nil) + } + } + + private func render(error: Error) { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } + + // MARK: - Actions + + @IBAction private func passphraseVisibilityButtonAction(_ sender: Any) { + self.passphraseTextField.isSecureTextEntry = !self.passphraseTextField.isSecureTextEntry + } + + @objc private func passphraseTextFieldDidChange(_ textField: UITextField) { + self.viewModel.passphrase = textField.text + self.updateRecoverButton() + } + + @IBAction private func recoverButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .recover) + } + + @IBAction private func unknownPassphraseButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .unknownPassphrase) + } +} + +// MARK: - UITextFieldDelegate +extension KeyBackupRecoverFromPassphraseViewController: UITextFieldDelegate { + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } +} + +// MARK: - KeyBackupRecoverFromPassphraseViewModelViewDelegate +extension KeyBackupRecoverFromPassphraseViewController: KeyBackupRecoverFromPassphraseViewModelViewDelegate { + func keyBackupRecoverFromPassphraseViewModel(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromPassphraseViewState) { + self.render(viewState: viewSate) + } +} diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift new file mode 100644 index 000000000..825fe508e --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift @@ -0,0 +1,105 @@ +/* + Copyright 2019 New Vector 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 Foundation + +enum KeyBackupRecoverFromPassphraseViewModelError: Error { + case missingKeyBackupVersion +} + +final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphraseViewModelType { + + // MARK: - Properties + + // MARK: Private + + private let keyBackup: MXKeyBackup + private var currentHTTPOperation: MXHTTPOperation? + private let keyBackupVersion: MXKeyBackupVersion + + // MARK: Public + + var passphrase: String? + + var isFormValid: Bool { + return self.passphrase?.isEmpty == false + } + + weak var viewDelegate: KeyBackupRecoverFromPassphraseViewModelViewDelegate? + weak var coordinatorDelegate: KeyBackupRecoverFromPassphraseViewModelCoordinatorDelegate? + + // MARK: - Setup + + init(keyBackup: MXKeyBackup, keyBackupVersion: MXKeyBackupVersion) { + self.keyBackup = keyBackup + self.keyBackupVersion = keyBackupVersion + } + + deinit { + self.currentHTTPOperation?.cancel() + } + + // MARK: - Public + + func process(viewAction: KeyBackupRecoverFromPassphraseViewAction) { + switch viewAction { + case .recover: + self.recoverWithPassphrase() + case .cancel: + self.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidCancel(self) + case .unknownPassphrase: + self.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDoNotKnowPassphrase(self) + } + } + + // MARK: - Private + + private func recoverWithPassphrase() { + guard let passphrase = self.passphrase else { + return + } + + guard let keyBackupVersion = self.keyBackupVersion.version else { + self.update(viewState: .error(KeyBackupRecoverFromPassphraseViewModelError.missingKeyBackupVersion)) + return + } + + self.update(viewState: .loading) + + self.currentHTTPOperation = self.keyBackup.restore(keyBackupVersion, withPassword: passphrase, room: nil, session: nil, success: { [weak self] (totalKeys, _) in + guard let sself = self else { + return + } + sself.update(viewState: .loaded(totalKeys: totalKeys)) + if totalKeys > 0 { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(sself) + } + } + }, failure: { [weak self] error in + guard let sself = self else { + return + } + DispatchQueue.main.async { + sself.update(viewState: .error(error)) + } + }) + } + + private func update(viewState: KeyBackupRecoverFromPassphraseViewState) { + self.viewDelegate?.keyBackupRecoverFromPassphraseViewModel(self, didUpdateViewState: viewState) + } +} diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift new file mode 100644 index 000000000..8b19bc589 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift @@ -0,0 +1,39 @@ +/* + Copyright 2019 New Vector 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 Foundation + +protocol KeyBackupRecoverFromPassphraseViewModelViewDelegate: class { + func keyBackupRecoverFromPassphraseViewModel(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromPassphraseViewState) +} + +protocol KeyBackupRecoverFromPassphraseViewModelCoordinatorDelegate: class { + func keyBackupRecoverFromPassphraseViewModelDidRecover(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType) + func keyBackupRecoverFromPassphraseViewModelDidCancel(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType) + func keyBackupRecoverFromPassphraseViewModelDoNotKnowPassphrase(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType) +} + +/// Protocol describing the view model used by `KeyBackupRecoverFromPassphraseViewController` +protocol KeyBackupRecoverFromPassphraseViewModelType { + + var passphrase: String? { get set } + var isFormValid: Bool { get } + + var viewDelegate: KeyBackupRecoverFromPassphraseViewModelViewDelegate? { get set } + var coordinatorDelegate: KeyBackupRecoverFromPassphraseViewModelCoordinatorDelegate? { get set } + + func process(viewAction: KeyBackupRecoverFromPassphraseViewAction) +} diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift new file mode 100644 index 000000000..34789954f --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift @@ -0,0 +1,24 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupRecoverFromPassphraseViewController view state +enum KeyBackupRecoverFromPassphraseViewState { + case loading + case loaded(totalKeys: UInt) + case error(Error) +} From ed8b95d9a0cbcd221c520b3aa1670ce5a42704f5 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 10:58:24 +0100 Subject: [PATCH 123/244] Create key backup recover from recovery key scene with coordinator, view model, view controller --- ...kupRecoverFromRecoveryKeyCoordinator.swift | 70 +++++ ...ecoverFromRecoveryKeyCoordinatorType.swift | 27 ++ ...ckupRecoverFromRecoveryKeyViewAction.swift | 24 ++ ...erFromRecoveryKeyViewController.storyboard | 211 ++++++++++++++ ...RecoverFromRecoveryKeyViewController.swift | 274 ++++++++++++++++++ ...ackupRecoverFromRecoveryKeyViewModel.swift | 105 +++++++ ...pRecoverFromRecoveryKeyViewModelType.swift | 38 +++ ...ackupRecoverFromRecoveryKeyViewState.swift | 24 ++ 8 files changed, 773 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewAction.swift create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift create mode 100644 Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift new file mode 100644 index 000000000..eb4eb17ee --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift @@ -0,0 +1,70 @@ +/* + Copyright 2019 New Vector 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 Foundation + +final class KeyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private let keyBackupRecoverFromRecoveryKeyViewController: KeyBackupRecoverFromRecoveryKeyViewController + private let keyBackupVersion: MXKeyBackupVersion + private let keyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecoveryKeyViewModel + + // MARK: Public + + var childCoordinators: [Coordinator] = [] + + weak var delegate: KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession, keyBackupVersion: MXKeyBackupVersion) { + self.session = session + self.keyBackupVersion = keyBackupVersion + + let keyBackup = MXKeyBackup(matrixSession: session) + let keyBackupRecoverFromRecoveryKeyViewModel = KeyBackupRecoverFromRecoveryKeyViewModel(keyBackup: keyBackup, keyBackupVersion: keyBackupVersion) + let keyBackupRecoverFromRecoveryKeyViewController = KeyBackupRecoverFromRecoveryKeyViewController.instantiate(with: keyBackupRecoverFromRecoveryKeyViewModel) + self.keyBackupRecoverFromRecoveryKeyViewController = keyBackupRecoverFromRecoveryKeyViewController + self.keyBackupRecoverFromRecoveryKeyViewModel = keyBackupRecoverFromRecoveryKeyViewModel + } + + // MARK: - Public + + func start() { + self.keyBackupRecoverFromRecoveryKeyViewModel.coordinatorDelegate = self + } + + func toPresentable() -> UIViewController { + return self.keyBackupRecoverFromRecoveryKeyViewController + } +} + +// MARK: - KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate +extension KeyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate { + func keyBackupRecoverFromRecoveryKeyViewModelDidRecover(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) { + self.delegate?.keyBackupRecoverFromPassphraseCoordinatorDidRecover(self) + } + + func keyBackupRecoverFromRecoveryKeyViewModelDidCancel(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) { + self.delegate?.keyBackupRecoverFromPassphraseCoordinatorDidCancel(self) + } +} + diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift new file mode 100644 index 000000000..11d528b4f --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift @@ -0,0 +1,27 @@ +/* + Copyright 2019 New Vector 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 Foundation + +protocol KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate: class { + func keyBackupRecoverFromPassphraseCoordinatorDidRecover(_ keyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType) + func keyBackupRecoverFromPassphraseCoordinatorDidCancel(_ keyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType) +} + +/// `KeyBackupRecoverFromRecoveryKeyCoordinatorType` is a protocol describing a Coordinator that handle key backup recover from recovery key navigation flow. +protocol KeyBackupRecoverFromRecoveryKeyCoordinatorType: Coordinator, Presentable { + var delegate: KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate? { get } +} diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewAction.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewAction.swift new file mode 100644 index 000000000..c1d030e0c --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewAction.swift @@ -0,0 +1,24 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupRecoverFromRecoveryKeyViewController view actions exposed to view model +enum KeyBackupRecoverFromRecoveryKeyViewAction { + case recover + case unknownRecoveryKey + case cancel +} diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.storyboard b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.storyboard new file mode 100644 index 000000000..aef3ad780 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.storyboard @@ -0,0 +1,211 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift new file mode 100644 index 000000000..f66e8f9bb --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift @@ -0,0 +1,274 @@ +/* + Copyright 2019 New Vector 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 UIKit +import MobileCoreServices + +final class KeyBackupRecoverFromRecoveryKeyViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var scrollView: UIScrollView! + + @IBOutlet private weak var shieldImageView: UIImageView! + + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var recoveryKeyTitleLabel: UILabel! + @IBOutlet private weak var recoveryKeyTextField: UITextField! + @IBOutlet private weak var recoveryKeyTextFieldBackgroundView: UIView! + + @IBOutlet private weak var importFileButton: UIButton! + + @IBOutlet private weak var unknownRecoveryKeyButton: UIButton! + + @IBOutlet private weak var recoverButtonBackgroundView: UIView! + @IBOutlet private weak var recoverButton: UIButton! + + // MARK: Private + + private var viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType! + private var keyboardAvoider: KeyboardAvoider? + private var theme: Theme! + private var errorPresenter: MXKErrorPresentation! + private var activityPresenter: ActivityIndicatorPresenter! + private weak var skipAlertController: UIAlertController? + + // MARK: Public + + // MARK: - Setup + + class func instantiate(with viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) -> KeyBackupRecoverFromRecoveryKeyViewController { + let viewController = StoryboardScene.KeyBackupRecoverFromRecoveryKeyViewController.initialScene.instantiate() + viewController.viewModel = viewModel + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupRecoverTitle + self.vc_removeBackTitle() + + self.setupViews() + self.keyboardAvoider = KeyboardAvoider(scrollViewContainerView: self.view, scrollView: self.scrollView) + self.activityPresenter = ActivityIndicatorPresenter() + self.errorPresenter = MXKErrorAlertPresentation() + + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + + self.viewModel.viewDelegate = self + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.cancelButtonAction() + } + + self.navigationItem.rightBarButtonItem = cancelBarButtonItem + + self.scrollView.keyboardDismissMode = .interactive + + let shieldImage = Asset.Images.shield.image.withRenderingMode(.alwaysTemplate) + self.shieldImageView.image = shieldImage + + self.informationLabel.text = VectorL10n.keyBackupRecoverFromRecoveryKeyInfo + + self.recoveryKeyTitleLabel.text = VectorL10n.keyBackupRecoverFromRecoveryKeyRecoveryKeyTitle + self.recoveryKeyTextField.addTarget(self, action: #selector(recoveryKeyTextFieldDidChange(_:)), for: .editingChanged) + + let importFileImage = Asset.Images.importFilesButton.image.withRenderingMode(.alwaysTemplate) + self.importFileButton.setImage(importFileImage, for: .normal) + + self.unknownRecoveryKeyButton.vc_enableMultiLinesTitle() + self.unknownRecoveryKeyButton.setTitle(VectorL10n.keyBackupRecoverFromRecoveryKeyLostRecoveryKeyAction, for: .normal) + // Interaction is disabled for the moment + self.unknownRecoveryKeyButton.isUserInteractionEnabled = false + + self.recoverButton.vc_enableMultiLinesTitle() + self.recoverButton.setTitle(VectorL10n.keyBackupRecoverFromPassphraseRecoverAction, for: .normal) + + self.updateRecoverButton() + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.informationLabel.textColor = theme.textPrimaryColor + + self.shieldImageView.tintColor = theme.textPrimaryColor + + self.recoveryKeyTextFieldBackgroundView.backgroundColor = theme.backgroundColor + self.recoveryKeyTitleLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onTextField: self.recoveryKeyTextField) + self.recoveryKeyTextField.attributedPlaceholder = NSAttributedString(string: VectorL10n.keyBackupRecoverFromRecoveryKeyRecoveryKeyPlaceholder, + attributes: [.foregroundColor : theme.placeholderTextColor]) + + theme.applyStyle(onButton: self.importFileButton) + + self.recoverButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.recoverButton) + + self.unknownRecoveryKeyButton.setTitleColor(theme.textPrimaryColor, for: .normal) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func updateRecoverButton() { + self.recoverButton.isEnabled = self.viewModel.isFormValid + } + + private func render(viewState: KeyBackupRecoverFromRecoveryKeyViewState) { + switch viewState { + case .loading: + self.renderLoading() + case .loaded(totalKeys: let totalKeys): + self.renderLoaded(with: totalKeys) + case .error(let error): + self.render(error: error) + } + } + + private func renderLoading() { + self.view.endEditing(true) + self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) + } + + private func renderLoaded(with totalKeys: UInt) { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + + if totalKeys == 0 { + self.errorPresenter.presentError(from: self, + title: VectorL10n.keyBackupRecoverEmptyBackupTitle, + message: VectorL10n.keyBackupRecoverEmptyBackupMessage, + animated: true, + handler: nil) + } + } + + private func render(error: Error) { + self.activityPresenter.removeCurrentActivityIndicator(animated: true) + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } + + private func showFileSelection() { + // Show only text documents + let documentPicker = UIDocumentPickerViewController(documentTypes: [kUTTypeText as String], in: .import) + documentPicker.delegate = self + self.present(documentPicker, animated: true, completion: nil) + } + + private func importRecoveryKey(from url: URL) { + if let recoveryKey = self.getDocumentContent(from: url) { + self.recoveryKeyTextField.text = recoveryKey + } else { + self.errorPresenter.presentGenericError(from: self, animated: true, handler: nil) + } + } + + private func getDocumentContent(from documentURL: URL) -> String? { + let documentContent: String? + + do { + documentContent = try String(contentsOf: documentURL) + } catch { + print("Error: \(error)") + documentContent = nil + } + + return documentContent + } + + // MARK: - Actions + + private func cancelButtonAction() { + self.viewModel.process(viewAction: .cancel) + } + + @IBAction private func importFileButtonAction(_ sender: Any) { + self.showFileSelection() + } + + @objc private func recoveryKeyTextFieldDidChange(_ textField: UITextField) { + self.viewModel.recoveryKey = textField.text + self.updateRecoverButton() + } + + @IBAction private func usePassphraseButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .recover) + } + + @IBAction private func unknownPassphraseButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .unknownRecoveryKey) + } +} + +// MARK: - UITextFieldDelegate +extension KeyBackupRecoverFromRecoveryKeyViewController: UITextFieldDelegate { + + func textFieldShouldReturn(_ textField: UITextField) -> Bool { + textField.resignFirstResponder() + return true + } +} + +// MARK: - KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate +extension KeyBackupRecoverFromRecoveryKeyViewController: KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate { + func keyBackupRecoverFromPassphraseViewModel(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromRecoveryKeyViewState) { + self.render(viewState: viewSate) + } +} + +// MARK: - UIDocumentPickerDelegate +extension KeyBackupRecoverFromRecoveryKeyViewController: UIDocumentPickerDelegate { + + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { + guard let documentUrl = urls.first else { + return + } + self.importRecoveryKey(from: documentUrl) + } + + func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { + self.importRecoveryKey(from: url) + } +} diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift new file mode 100644 index 000000000..a5cf9741d --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift @@ -0,0 +1,105 @@ +/* + Copyright 2019 New Vector 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 Foundation + +enum KeyBackupRecoverFromRecoveryKeyViewModelError: Error { + case missingKeyBackupVersion +} + +final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecoveryKeyViewModelType { + + // MARK: - Properties + + // MARK: Private + + private let keyBackup: MXKeyBackup + private var currentHTTPOperation: MXHTTPOperation? + private let keyBackupVersion: MXKeyBackupVersion + + // MARK: Public + + var recoveryKey: String? + + var isFormValid: Bool { + return self.recoveryKey?.isEmpty == false + } + + weak var viewDelegate: KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate? + weak var coordinatorDelegate: KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate? + + // MARK: - Setup + + init(keyBackup: MXKeyBackup, keyBackupVersion: MXKeyBackupVersion) { + self.keyBackup = keyBackup + self.keyBackupVersion = keyBackupVersion + } + + deinit { + self.currentHTTPOperation?.cancel() + } + + // MARK: - Public + + func process(viewAction: KeyBackupRecoverFromRecoveryKeyViewAction) { + switch viewAction { + case .recover: + self.recover() + case .cancel: + self.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidCancel(self) + case .unknownRecoveryKey: + break + } + } + + // MARK: - Private + + private func recover() { + guard let recoveryKey = self.recoveryKey else { + return + } + + guard let keyBackupVersion = self.keyBackupVersion.version else { + self.update(viewState: .error(KeyBackupRecoverFromRecoveryKeyViewModelError.missingKeyBackupVersion)) + return + } + + self.update(viewState: .loading) + + self.currentHTTPOperation = self.keyBackup.restore(keyBackupVersion, withRecoveryKey: recoveryKey, room: nil, session: nil, success: { [weak self] (totalKeys, _) in + guard let sself = self else { + return + } + sself.update(viewState: .loaded(totalKeys: totalKeys)) + if totalKeys > 0 { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(sself) + } + } + }, failure: { [weak self] error in + guard let sself = self else { + return + } + DispatchQueue.main.async { + sself.update(viewState: .error(error)) + } + }) + } + + private func update(viewState: KeyBackupRecoverFromRecoveryKeyViewState) { + self.viewDelegate?.keyBackupRecoverFromPassphraseViewModel(self, didUpdateViewState: viewState) + } +} diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift new file mode 100644 index 000000000..e952c70a3 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift @@ -0,0 +1,38 @@ +/* + Copyright 2019 New Vector 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 Foundation + +protocol KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate: class { + func keyBackupRecoverFromPassphraseViewModel(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromRecoveryKeyViewState) +} + +protocol KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate: class { + func keyBackupRecoverFromRecoveryKeyViewModelDidRecover(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) + func keyBackupRecoverFromRecoveryKeyViewModelDidCancel(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) +} + +/// Protocol describing the view model used by `KeyBackupSetupPassphraseViewController` +protocol KeyBackupRecoverFromRecoveryKeyViewModelType { + + var recoveryKey: String? { get set } + var isFormValid: Bool { get } + + var viewDelegate: KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate? { get set } + var coordinatorDelegate: KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate? { get set } + + func process(viewAction: KeyBackupRecoverFromRecoveryKeyViewAction) +} diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift new file mode 100644 index 000000000..57042fe11 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift @@ -0,0 +1,24 @@ +/* + Copyright 2019 New Vector 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 Foundation + +/// KeyBackupRecoverFromRecoveryKeyViewController view state +enum KeyBackupRecoverFromRecoveryKeyViewState { + case loading + case loaded(totalKeys: UInt) + case error(Error) +} From 53bca433a0d474cbc5b47cc2a711da1d87bea07c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 10:59:42 +0100 Subject: [PATCH 124/244] Create key backup recover success view controller --- ...kupRecoverSuccessViewController.storyboard | 131 ++++++++++++++++++ ...eyBackupRecoverSuccessViewController.swift | 120 ++++++++++++++++ 2 files changed, 251 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift diff --git a/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.storyboard b/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.storyboard new file mode 100644 index 000000000..da5aff092 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.storyboard @@ -0,0 +1,131 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift b/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift new file mode 100644 index 000000000..967064f1d --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift @@ -0,0 +1,120 @@ +/* + Copyright 2019 New Vector 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 UIKit + +protocol KeyBackupRecoverSuccessViewControllerDelegate: class { + func KeyBackupRecoverSuccessViewControllerDidTapDone(_ keyBackupRecoverSuccessViewController: KeyBackupRecoverSuccessViewController) +} + +final class KeyBackupRecoverSuccessViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var shieldImageView: UIImageView! + + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var doneButtonBackgroundView: UIView! + @IBOutlet private weak var doneButton: UIButton! + + // MARK: Private + + private var theme: Theme! + + // MARK: Public + + weak var delegate: KeyBackupRecoverSuccessViewControllerDelegate? + + // MARK: - Setup + + class func instantiate() -> KeyBackupRecoverSuccessViewController { + let viewController = StoryboardScene.KeyBackupRecoverSuccessViewController.initialScene.instantiate() + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupRecoverTitle + self.vc_removeBackTitle() + + self.setupViews() + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Hide back button + self.navigationItem.setHidesBackButton(true, animated: animated) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + let shieldImage = Asset.Images.shield.image.withRenderingMode(.alwaysTemplate) + self.shieldImageView.image = shieldImage + + self.informationLabel.text = VectorL10n.keyBackupRecoverSuccessInfo + + self.doneButton.vc_enableMultiLinesTitle() + self.doneButton.setTitle(VectorL10n.keyBackupRecoverDoneAction, for: .normal) + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.shieldImageView.tintColor = theme.textPrimaryColor + + self.informationLabel.textColor = theme.textPrimaryColor + + self.doneButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.doneButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + // MARK: - Actions + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + @IBAction private func doneButtonAction(_ sender: Any) { + self.delegate?.KeyBackupRecoverSuccessViewControllerDidTapDone(self) + } +} From fdd3514c1366d7d8f4a1e89f62af90c2be82ee72 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 11:08:01 +0100 Subject: [PATCH 125/244] Create key backup recover coordinator --- .../Recover/KeyBackupRecoverCoordinator.swift | 132 ++++++++++++++++++ .../KeyBackupRecoverCoordinatorType.swift | 27 ++++ 2 files changed, 159 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift create mode 100644 Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift new file mode 100644 index 000000000..01f783a69 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift @@ -0,0 +1,132 @@ +/* + Copyright 2019 New Vector 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 Foundation + +final class KeyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private let navigationRouter: NavigationRouterType + private let keyBackupVersion: MXKeyBackupVersion + + // MARK: Public + + var childCoordinators: [Coordinator] = [] + + weak var delegate: KeyBackupRecoverCoordinatorDelegate? + + // MARK: - Setup + + init(session: MXSession, keyBackupVersion: MXKeyBackupVersion) { + self.session = session + self.keyBackupVersion = keyBackupVersion + self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController()) + } + + // MARK: - Public + + func start() { + + let rootCoordinator: Coordinator & Presentable + + // Check if a passphrase has been set for given backup + if let megolmBackupAuthData = MXMegolmBackupAuthData(fromJSON: self.keyBackupVersion.authData), megolmBackupAuthData.privateKeySalt != nil { + rootCoordinator = self.createRecoverFromPassphraseCoordinator() + } else { + rootCoordinator = self.createRecoverFromRecoveryKeyCoordinator() + } + + rootCoordinator.start() + + self.add(childCoordinator: rootCoordinator) + + self.navigationRouter.setRootModule(rootCoordinator) + } + + func toPresentable() -> UIViewController { + return self.navigationRouter.toPresentable() + } + + // MARK: - Private + + private func createRecoverFromPassphraseCoordinator() -> KeyBackupRecoverFromPassphraseCoordinator { + let coordinator = KeyBackupRecoverFromPassphraseCoordinator(session: self.session, keyBackupVersion: self.keyBackupVersion) + coordinator.delegate = self + return coordinator + } + + private func createRecoverFromRecoveryKeyCoordinator() -> KeyBackupRecoverFromRecoveryKeyCoordinator { + let coordinator = KeyBackupRecoverFromRecoveryKeyCoordinator(session: self.session, keyBackupVersion: self.keyBackupVersion) + coordinator.delegate = self + return coordinator + } + + private func showRecoverFromRecoveryKey() { + let coordinator = self.createRecoverFromRecoveryKeyCoordinator() + + self.add(childCoordinator: coordinator) + + self.navigationRouter.push(coordinator, animated: true) { + self.remove(childCoordinator: coordinator) + } + + coordinator.start() + } + + private func showRecoverSuccess() { + let keyBackupRecoverSuccessViewController = KeyBackupRecoverSuccessViewController.instantiate() + keyBackupRecoverSuccessViewController.delegate = self + self.navigationRouter.push(keyBackupRecoverSuccessViewController, animated: true, popCompletion: nil) + } +} + +// MARK: - KeyBackupRecoverFromPassphraseCoordinatorDelegate +extension KeyBackupRecoverCoordinator: KeyBackupRecoverFromPassphraseCoordinatorDelegate { + func keyBackupRecoverFromPassphraseCoordinatorDidRecover(_ keyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassphraseCoordinatorType) { + self.showRecoverSuccess() + } + + func keyBackupRecoverFromPassphraseCoordinatorDoNotKnowPassphrase(_ keyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassphraseCoordinatorType) { + self.showRecoverFromRecoveryKey() + } + + func keyBackupRecoverFromPassphraseCoordinatorDidCancel(_ keyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassphraseCoordinatorType) { + self.delegate?.keyBackupRecoverCoordinatorDidCancel(self) + } +} + +// MARK: - KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate +extension KeyBackupRecoverCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate { + func keyBackupRecoverFromPassphraseCoordinatorDidRecover(_ keyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType) { + self.showRecoverSuccess() + } + + func keyBackupRecoverFromPassphraseCoordinatorDidCancel(_ keyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType) { + self.delegate?.keyBackupRecoverCoordinatorDidCancel(self) + } +} + +// MARK: - KeyBackupRecoverSuccessViewControllerDelegate +extension KeyBackupRecoverCoordinator: KeyBackupRecoverSuccessViewControllerDelegate { + func KeyBackupRecoverSuccessViewControllerDidTapDone(_ keyBackupRecoverSuccessViewController: KeyBackupRecoverSuccessViewController) { + self.delegate?.keyBackupRecoverCoordinatorDidRecover(self) + } +} + diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift new file mode 100644 index 000000000..30d9c34d3 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift @@ -0,0 +1,27 @@ +/* + Copyright 2019 New Vector 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 Foundation + +protocol KeyBackupRecoverCoordinatorDelegate: class { + func keyBackupRecoverCoordinatorDidRecover(_ keyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType) + func keyBackupRecoverCoordinatorDidCancel(_ keyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType) +} + +/// `KeyBackupSetupPassphraseCoordinatorType` is a protocol describing a Coordinator that handle key backup recover navigation flow. +protocol KeyBackupRecoverCoordinatorType: Coordinator, Presentable { + var delegate: KeyBackupRecoverCoordinatorDelegate? { get } +} From 4f155d2680968f69c8caa5b81e735a3e162a3f57 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 11:09:03 +0100 Subject: [PATCH 126/244] Enable iCloud capability in order to use UIDocumentPickerViewController --- Riot/SupportingFiles/Riot.entitlements | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Riot/SupportingFiles/Riot.entitlements b/Riot/SupportingFiles/Riot.entitlements index 779cd8dff..d65fe32b0 100644 --- a/Riot/SupportingFiles/Riot.entitlements +++ b/Riot/SupportingFiles/Riot.entitlements @@ -12,8 +12,22 @@ applinks:www.riot.im webcredentials:riot.im + com.apple.developer.icloud-container-identifiers + + iCloud.$(CFBundleIdentifier) + + com.apple.developer.icloud-services + + CloudDocuments + com.apple.developer.siri + com.apple.developer.ubiquity-container-identifiers + + iCloud.$(CFBundleIdentifier) + + com.apple.developer.ubiquity-kvstore-identifier + $(TeamIdentifierPrefix)$(CFBundleIdentifier) com.apple.security.application-groups group.im.vector From 5d543d8a3b256fc0c0b34c1b748c5c7c953d01d5 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 11:11:04 +0100 Subject: [PATCH 127/244] Create KeyBackupRecoverCoordinatorBridgePresenter which enables to start KeyBackupRecoverCoordinator from a view controller --- ...kupRecoverCoordinatorBridgePresenter.swift | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift new file mode 100644 index 000000000..ba3375221 --- /dev/null +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorBridgePresenter.swift @@ -0,0 +1,79 @@ +/* + Copyright 2019 New Vector 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 Foundation + +@objc protocol KeyBackupRecoverCoordinatorBridgePresenterDelegate { + func keyBackupRecoverCoordinatorBridgePresenterDidCancel(_ keyBackupRecoverCoordinatorBridgePresenter: KeyBackupRecoverCoordinatorBridgePresenter) + func keyBackupRecoverCoordinatorBridgePresenterDidRecover(_ keyBackupRecoverCoordinatorBridgePresenter: KeyBackupRecoverCoordinatorBridgePresenter) +} + +/// KeyBackupRecoverCoordinatorBridgePresenter enables to start KeyBackupRecoverCoordinator from a view controller. +/// This bridge is used while waiting for global usage of coordinator pattern. +@objcMembers +final class KeyBackupRecoverCoordinatorBridgePresenter: NSObject { + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private let keyBackupVersion: MXKeyBackupVersion + private var coordinator: KeyBackupRecoverCoordinator? + + // MARK: Public + + weak var delegate: KeyBackupRecoverCoordinatorBridgePresenterDelegate? + + // MARK: - Setup + + init(session: MXSession, keyBackupVersion: MXKeyBackupVersion) { + self.session = session + self.keyBackupVersion = keyBackupVersion + super.init() + } + + // MARK: - Public + + func present(from viewController: UIViewController, animated: Bool) { + let keyBackupSetupCoordinator = KeyBackupRecoverCoordinator(session: self.session, keyBackupVersion: keyBackupVersion) + keyBackupSetupCoordinator.delegate = self + viewController.present(keyBackupSetupCoordinator.toPresentable(), animated: animated, completion: nil) + keyBackupSetupCoordinator.start() + + self.coordinator = keyBackupSetupCoordinator + } + + func dismiss(animated: Bool) { + guard let coordinator = self.coordinator else { + return + } + coordinator.toPresentable().dismiss(animated: animated) { + self.coordinator = nil + } + } +} + +// MARK: - KeyBackupRecoverCoordinatorDelegate +extension KeyBackupRecoverCoordinatorBridgePresenter: KeyBackupRecoverCoordinatorDelegate { + func keyBackupRecoverCoordinatorDidRecover(_ keyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType) { + self.delegate?.keyBackupRecoverCoordinatorBridgePresenterDidRecover(self) + } + + func keyBackupRecoverCoordinatorDidCancel(_ keyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType) { + self.delegate?.keyBackupRecoverCoordinatorBridgePresenterDidCancel(self) + } +} From 73fbc67d3fc9b378869640998a9c6f6b90ef7974 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 11:11:45 +0100 Subject: [PATCH 128/244] Update pbxproj --- Riot.xcodeproj/project.pbxproj | 129 ++++++++++++++++++++++++++++++- Riot/Generated/Storyboards.swift | 15 ++++ 2 files changed, 143 insertions(+), 1 deletion(-) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 1f144c57a..940d86d1a 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -53,6 +53,8 @@ B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */; }; B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0B21ED07E4000DDA48 /* Presentable.swift */; }; B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */; }; + B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */; }; + B1107ECA2200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */; }; B110871921EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */; }; B110871B21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B110871A21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard */; }; B110871D21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871C21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift */; }; @@ -60,7 +62,23 @@ B110872421F098F0003554A5 /* ActivityIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = B110872021F098EF003554A5 /* ActivityIndicatorView.xib */; }; B110872521F098F0003554A5 /* ActivityIndicatorPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */; }; B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110872221F098F0003554A5 /* ActivityIndicatorView.swift */; }; + B139C21B21FE5B9200BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C21A21FE5B9100BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift */; }; + B139C21D21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C21C21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift */; }; + B139C21F21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C21E21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift */; }; + B139C22121FE5D9D00BB68EC /* KeyBackupRecoverFromPassphraseViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22021FE5D9D00BB68EC /* KeyBackupRecoverFromPassphraseViewState.swift */; }; + B139C22321FF01B200BB68EC /* KeyBackupRecoverFromPassphraseCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22221FF01B200BB68EC /* KeyBackupRecoverFromPassphraseCoordinatorType.swift */; }; + B139C22521FF01C100BB68EC /* KeyBackupRecoverFromPassphraseCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22421FF01C100BB68EC /* KeyBackupRecoverFromPassphraseCoordinator.swift */; }; + B139C22721FF319B00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22621FF319B00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift */; }; + B139C22921FF31AA00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22821FF31AA00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModel.swift */; }; + B139C22B21FF31E600BB68EC /* KeyBackupRecoverFromRecoveryKeyViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22A21FF31E600BB68EC /* KeyBackupRecoverFromRecoveryKeyViewAction.swift */; }; + B139C22D21FF32F000BB68EC /* KeyBackupRecoverFromRecoveryKeyViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22C21FF32F000BB68EC /* KeyBackupRecoverFromRecoveryKeyViewState.swift */; }; + B139C22F21FF378C00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C22E21FF378C00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.swift */; }; + B139C23121FF37B400BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B139C23021FF37B400BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.storyboard */; }; + B139C23321FF38A400BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C23221FF38A400BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift */; }; + B139C23521FF38C600BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B139C23421FF38C600BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift */; }; B140B4A221F87F7100E3F5FE /* OperationQueue.swift in Sources */ = {isa = PBXBuildFile; fileRef = B140B4A121F87F7100E3F5FE /* OperationQueue.swift */; }; + B140B4A621F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B140B4A521F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift */; }; + B140B4A821F8AB4600E3F5FE /* KeyBackupRecoverCoordinatorBridgePresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B140B4A721F8AB4600E3F5FE /* KeyBackupRecoverCoordinatorBridgePresenter.swift */; }; B1664BC520F4E67600808783 /* FallbackViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1664BAD20F4E67500808783 /* FallbackViewController.xib */; }; B1664BC620F4E67600808783 /* FallbackViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BAE20F4E67500808783 /* FallbackViewController.m */; }; B1664BC720F4E67600808783 /* SharePresentingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1664BB220F4E67500808783 /* SharePresentingViewController.m */; }; @@ -102,6 +120,8 @@ B169331720F3CBE000746532 /* RecentCellData.m in Sources */ = {isa = PBXBuildFile; fileRef = B16932F920F3C51900746532 /* RecentCellData.m */; }; B17982FF2119FED2001FD722 /* GDPRConsentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B17982FE2119FED2001FD722 /* GDPRConsentViewController.swift */; }; B1798302211B13B3001FD722 /* OnBoardingManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1798301211B13B3001FD722 /* OnBoardingManager.swift */; }; + B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */; }; + B19EFA3B21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */; }; B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */; }; B1B5571920EE6C4D00210D55 /* LanguagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567C20EE6C4C00210D55 /* LanguagePickerViewController.m */; }; B1B5571A20EE6C4D00210D55 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567E20EE6C4C00210D55 /* SettingsViewController.m */; }; @@ -351,6 +371,9 @@ B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752621EE4E620067973F /* KeyboardNotification.swift */; }; B1D4752A21EE52B10067973F /* KeyBackupSetupIntroViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752921EE52B10067973F /* KeyBackupSetupIntroViewController.swift */; }; B1D4752C21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1D4752B21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard */; }; + B1E5368921FB1E20001F3AFF /* UIButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368821FB1E20001F3AFF /* UIButton.swift */; }; + B1E5368D21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */; }; + B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */; }; B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */; }; B1FDF56221F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1FDF56121F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift */; }; CD9C4E21170ABE528E087A51 /* Pods_RiotPods_SiriIntents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BC0B9DB497F579AB1084E3DC /* Pods_RiotPods_SiriIntents.framework */; }; @@ -493,6 +516,8 @@ B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; B1098C0B21ED07E4000DDA48 /* Presentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = ""; }; B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = ""; }; + B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverSuccessViewController.swift; sourceTree = ""; }; + B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverSuccessViewController.storyboard; sourceTree = ""; }; B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewController.swift; sourceTree = ""; }; B110871A21EF809A003554A5 /* KeyBackupSetupRecoveryKeyViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupSetupRecoveryKeyViewController.storyboard; sourceTree = ""; }; B110871C21F087F4003554A5 /* KeyBackupSetupPassphraseViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewState.swift; sourceTree = ""; }; @@ -500,7 +525,23 @@ B110872021F098EF003554A5 /* ActivityIndicatorView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = ActivityIndicatorView.xib; sourceTree = ""; }; B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorPresenter.swift; sourceTree = ""; }; B110872221F098F0003554A5 /* ActivityIndicatorView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ActivityIndicatorView.swift; sourceTree = ""; }; + B139C21A21FE5B9100BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewModel.swift; sourceTree = ""; }; + B139C21C21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewModelType.swift; sourceTree = ""; }; + B139C21E21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewAction.swift; sourceTree = ""; }; + B139C22021FE5D9D00BB68EC /* KeyBackupRecoverFromPassphraseViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewState.swift; sourceTree = ""; }; + B139C22221FF01B200BB68EC /* KeyBackupRecoverFromPassphraseCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseCoordinatorType.swift; sourceTree = ""; }; + B139C22421FF01C100BB68EC /* KeyBackupRecoverFromPassphraseCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseCoordinator.swift; sourceTree = ""; }; + B139C22621FF319B00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyViewModelType.swift; sourceTree = ""; }; + B139C22821FF31AA00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyViewModel.swift; sourceTree = ""; }; + B139C22A21FF31E600BB68EC /* KeyBackupRecoverFromRecoveryKeyViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyViewAction.swift; sourceTree = ""; }; + B139C22C21FF32F000BB68EC /* KeyBackupRecoverFromRecoveryKeyViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyViewState.swift; sourceTree = ""; }; + B139C22E21FF378C00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyViewController.swift; sourceTree = ""; }; + B139C23021FF37B400BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverFromRecoveryKeyViewController.storyboard; sourceTree = ""; }; + B139C23221FF38A400BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift; sourceTree = ""; }; + B139C23421FF38C600BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromRecoveryKeyCoordinator.swift; sourceTree = ""; }; B140B4A121F87F7100E3F5FE /* OperationQueue.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OperationQueue.swift; sourceTree = ""; }; + B140B4A521F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupCoordinatorBridgePresenter.swift; sourceTree = ""; }; + B140B4A721F8AB4600E3F5FE /* KeyBackupRecoverCoordinatorBridgePresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinatorBridgePresenter.swift; sourceTree = ""; }; B1664BAD20F4E67500808783 /* FallbackViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FallbackViewController.xib; sourceTree = ""; }; B1664BAE20F4E67500808783 /* FallbackViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FallbackViewController.m; sourceTree = ""; }; B1664BAF20F4E67500808783 /* FallbackViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FallbackViewController.h; sourceTree = ""; }; @@ -590,6 +631,8 @@ B169331320F3CAFC00746532 /* PublicRoomsDirectoryDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PublicRoomsDirectoryDataSource.h; sourceTree = ""; }; B17982FE2119FED2001FD722 /* GDPRConsentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GDPRConsentViewController.swift; sourceTree = ""; }; B1798301211B13B3001FD722 /* OnBoardingManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnBoardingManager.swift; sourceTree = ""; }; + B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinatorType.swift; sourceTree = ""; }; + B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinator.swift; sourceTree = ""; }; B1B5567920EE6C4C00210D55 /* CountryPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryPickerViewController.h; sourceTree = ""; }; B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryPickerViewController.m; sourceTree = ""; }; B1B5567C20EE6C4C00210D55 /* LanguagePickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LanguagePickerViewController.m; sourceTree = ""; }; @@ -976,6 +1019,9 @@ B1D4752621EE4E620067973F /* KeyboardNotification.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardNotification.swift; sourceTree = ""; }; B1D4752921EE52B10067973F /* KeyBackupSetupIntroViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupIntroViewController.swift; sourceTree = ""; }; B1D4752B21EE52C30067973F /* KeyBackupSetupIntroViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupSetupIntroViewController.storyboard; sourceTree = ""; }; + B1E5368821FB1E20001F3AFF /* UIButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIButton.swift; sourceTree = ""; }; + B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverFromPassphraseViewController.swift; sourceTree = ""; }; + B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverFromPassphraseViewController.storyboard; sourceTree = ""; }; B1FDF55F21F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupPassphraseViewAction.swift; sourceTree = ""; }; B1FDF56121F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewAction.swift; sourceTree = ""; }; B4B35D08E11507BEE733BBC4 /* Pods-RiotPods-SiriIntents.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RiotPods-SiriIntents.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RiotPods-SiriIntents/Pods-RiotPods-SiriIntents.debug.xcconfig"; sourceTree = ""; }; @@ -1172,6 +1218,7 @@ isa = PBXGroup; children = ( B1098C0221ECFEAF000DDA48 /* Setup */, + B1FDF56421F726AD00BA3834 /* Recover */, ); path = KeyBackup; sourceTree = ""; @@ -1181,6 +1228,7 @@ children = ( B1098BEF21ECFE64000DDA48 /* KeyBackupSetupCoordinatorType.swift */, B1098BED21ECFE64000DDA48 /* KeyBackupSetupCoordinator.swift */, + B140B4A521F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift */, B1098C0521ECFF5B000DDA48 /* Intro */, B1098C0321ECFECC000DDA48 /* Passphrase */, B1098C0621ED00A9000DDA48 /* RecoveryKey */, @@ -1239,13 +1287,22 @@ path = Routers; sourceTree = ""; }; + B1107EC62200B0190038014B /* Success */ = { + isa = PBXGroup; + children = ( + B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */, + B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */, + ); + path = Success; + sourceTree = ""; + }; B110871E21F098EF003554A5 /* ActivityIndicator */ = { isa = PBXGroup; children = ( B110871F21F098EF003554A5 /* ActivityIndicatorPresenterType.swift */, - B110872021F098EF003554A5 /* ActivityIndicatorView.xib */, B110872121F098EF003554A5 /* ActivityIndicatorPresenter.swift */, B110872221F098F0003554A5 /* ActivityIndicatorView.swift */, + B110872021F098EF003554A5 /* ActivityIndicatorView.xib */, ); path = ActivityIndicator; sourceTree = ""; @@ -2603,6 +2660,36 @@ path = KeyboardAvoiding; sourceTree = ""; }; + B1E5368A21FB6FC0001F3AFF /* Passphrase */ = { + isa = PBXGroup; + children = ( + B139C22221FF01B200BB68EC /* KeyBackupRecoverFromPassphraseCoordinatorType.swift */, + B139C22421FF01C100BB68EC /* KeyBackupRecoverFromPassphraseCoordinator.swift */, + B139C21C21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift */, + B139C21A21FE5B9100BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift */, + B139C21E21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift */, + B139C22021FE5D9D00BB68EC /* KeyBackupRecoverFromPassphraseViewState.swift */, + B1E5368C21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift */, + B1E5368E21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard */, + ); + path = Passphrase; + sourceTree = ""; + }; + B1E5368B21FB6FD8001F3AFF /* RecoveryKey */ = { + isa = PBXGroup; + children = ( + B139C23221FF38A400BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift */, + B139C23421FF38C600BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift */, + B139C22621FF319B00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift */, + B139C22821FF31AA00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModel.swift */, + B139C22C21FF32F000BB68EC /* KeyBackupRecoverFromRecoveryKeyViewState.swift */, + B139C22A21FF31E600BB68EC /* KeyBackupRecoverFromRecoveryKeyViewAction.swift */, + B139C22E21FF378C00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.swift */, + B139C23021FF37B400BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.storyboard */, + ); + path = RecoveryKey; + sourceTree = ""; + }; B1FDF56321F68C0700BA3834 /* PasswordStrength */ = { isa = PBXGroup; children = ( @@ -2612,6 +2699,19 @@ path = PasswordStrength; sourceTree = ""; }; + B1FDF56421F726AD00BA3834 /* Recover */ = { + isa = PBXGroup; + children = ( + B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */, + B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */, + B140B4A721F8AB4600E3F5FE /* KeyBackupRecoverCoordinatorBridgePresenter.swift */, + B1E5368A21FB6FC0001F3AFF /* Passphrase */, + B1E5368B21FB6FD8001F3AFF /* RecoveryKey */, + B1107EC62200B0190038014B /* Success */, + ); + path = Recover; + sourceTree = ""; + }; F083BB021E7005FD00A9B29C /* RiotTests */ = { isa = PBXGroup; children = ( @@ -2700,6 +2800,7 @@ B1CA3A2621EF6913000D1D89 /* UIViewController.swift */, B1CA3A2821EF692B000D1D89 /* UIView.swift */, B140B4A121F87F7100E3F5FE /* OperationQueue.swift */, + B1E5368821FB1E20001F3AFF /* UIButton.swift */, ); path = Categories; sourceTree = ""; @@ -2888,6 +2989,9 @@ com.apple.Push = { enabled = 1; }; + com.apple.iCloud = { + enabled = 1; + }; }; }; F094A9BD1B78D8F000B1FBBF = { @@ -3003,6 +3107,7 @@ F083BDEA1E7009ED00A9B29C /* ringback.mp3 in Resources */, F083BDF21E7009ED00A9B29C /* GoogleService-Info.plist in Resources */, B1B558E320EF768F00210D55 /* RoomEmptyBubbleCell.xib in Resources */, + B1E5368F21FB7258001F3AFF /* KeyBackupRecoverFromPassphraseViewController.storyboard in Resources */, B1B5590420EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.xib in Resources */, B1B558F120EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib in Resources */, B1B557CB20EF5D8000210D55 /* DirectoryServerTableViewCell.xib in Resources */, @@ -3010,6 +3115,7 @@ B1B558D720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib in Resources */, B1B5590820EF768F00210D55 /* RoomMembershipWithPaginationTitleBubbleCell.xib in Resources */, F083BDE81E7009ED00A9B29C /* message.mp3 in Resources */, + B1107ECA2200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard in Resources */, B1B5579C20EF575B00210D55 /* ForgotPasswordInputsView.xib in Resources */, F083BE011E7009ED00A9B29C /* third_party_licenses.html in Resources */, B1098BFC21ECFE65000DDA48 /* PasswordStrengthView.xib in Resources */, @@ -3070,6 +3176,7 @@ B1B558C020EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib in Resources */, B1B5572420EE6C4D00210D55 /* RoomViewController.xib in Resources */, B169331520F3CAFC00746532 /* PublicRoomTableViewCell.xib in Resources */, + B139C23121FF37B400BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.storyboard in Resources */, 3284A35120A07C210044F922 /* postMessageAPI.js in Resources */, B1B557A220EF58AD00210D55 /* ContactTableViewCell.xib in Resources */, B1B558EB20EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib in Resources */, @@ -3267,6 +3374,7 @@ B1FDF56021F5FE5500BA3834 /* KeyBackupSetupPassphraseViewAction.swift in Sources */, B1B5573120EE6C4D00210D55 /* BugReportViewController.m in Sources */, B16932A520F3A21C00746532 /* empty.mm in Sources */, + B19EFA3B21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift in Sources */, B16932FA20F3C51A00746532 /* RecentCellData.m in Sources */, B16932F220F3C49E00746532 /* GroupsDataSource.m in Sources */, B1B5581C20EF625800210D55 /* RoomAvatarTitleView.m in Sources */, @@ -3310,7 +3418,9 @@ B1B558C320EF768F00210D55 /* RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m in Sources */, B110872521F098F0003554A5 /* ActivityIndicatorPresenter.swift in Sources */, 32242F1521E8FBA900725742 /* DarkTheme.swift in Sources */, + B140B4A621F89E7600E3F5FE /* KeyBackupSetupCoordinatorBridgePresenter.swift in Sources */, B1B5577420EE702900210D55 /* WidgetViewController.m in Sources */, + B139C21B21FE5B9200BB68EC /* KeyBackupRecoverFromPassphraseViewModel.swift in Sources */, B1B5574A20EE6C4D00210D55 /* MediaPickerViewController.m in Sources */, B1B5598520EFC3E000210D55 /* RageShakeManager.m in Sources */, B1B558D420EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */, @@ -3323,6 +3433,7 @@ B1FDF56221F5FFAF00BA3834 /* KeyBackupSetupRecoveryKeyViewAction.swift in Sources */, B1B5593B20EF7BAC00210D55 /* TableViewCellWithCheckBoxAndLabel.m in Sources */, B1B5581A20EF625800210D55 /* ExpandedRoomTitleView.m in Sources */, + B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */, B1B558E920EF768F00210D55 /* RoomSelectedStickerBubbleCell.m in Sources */, B1B558DF20EF768F00210D55 /* RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m in Sources */, F083BE041E7009ED00A9B29C /* Tools.m in Sources */, @@ -3345,6 +3456,7 @@ B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */, B1B5573C20EE6C4D00210D55 /* MasterTabBarController.m in Sources */, B1B5592C20EF7A5D00210D55 /* TableViewCellWithButton.m in Sources */, + B139C22F21FF378C00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewController.swift in Sources */, 32242F1421E8FBA900725742 /* DefaultTheme.swift in Sources */, 32242F1321E8FBA900725742 /* Theme.swift in Sources */, B1B5582520EF638A00210D55 /* RoomMemberTitleView.m in Sources */, @@ -3353,16 +3465,19 @@ B1B5573620EE6C4D00210D55 /* GroupsViewController.m in Sources */, B1B5572A20EE6C4D00210D55 /* RoomMemberDetailsViewController.m in Sources */, B1B5590120EF768F00210D55 /* RoomMembershipExpandedWithPaginationTitleBubbleCell.m in Sources */, + B139C22B21FF31E600BB68EC /* KeyBackupRecoverFromRecoveryKeyViewAction.swift in Sources */, B1B558C920EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */, B110871921EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift in Sources */, B1B5571B20EE6C4D00210D55 /* DeactivateAccountViewController.m in Sources */, B1B5590620EF768F00210D55 /* RoomMembershipCollapsedWithPaginationTitleBubbleCell.m in Sources */, + B139C21D21FE5BF500BB68EC /* KeyBackupRecoverFromPassphraseViewModelType.swift in Sources */, F083BE031E7009ED00A9B29C /* EventFormatter.m in Sources */, B16932F720F3C50E00746532 /* RecentsDataSource.m in Sources */, B1B558FC20EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1D3F15B21F0E28F001AEF85 /* KeyBackupSetupRecoveryKeyViewModel.swift in Sources */, B1B5572920EE6C4D00210D55 /* RoomFilesViewController.m in Sources */, B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */, + B139C22921FF31AA00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModel.swift in Sources */, B1B558E020EF768F00210D55 /* RoomOutgoingTextMsgBubbleCell.m in Sources */, B1B5593C20EF7BAC00210D55 /* TableViewCellWithCheckBoxes.m in Sources */, B1CA3A2721EF6914000D1D89 /* UIViewController.swift in Sources */, @@ -3372,6 +3487,7 @@ B1B5583E20EF6E7F00210D55 /* GroupRoomTableViewCell.m in Sources */, B1B5574F20EE6C4D00210D55 /* RoomsViewController.m in Sources */, B1B5572520EE6C4D00210D55 /* RoomMessagesSearchViewController.m in Sources */, + B139C22121FE5D9D00BB68EC /* KeyBackupRecoverFromPassphraseViewState.swift in Sources */, B1B5579120EF568D00210D55 /* GroupInviteTableViewCell.m in Sources */, B1B5579A20EF575B00210D55 /* ForgotPasswordInputsView.m in Sources */, B1B558CC20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m in Sources */, @@ -3381,6 +3497,7 @@ B1B5574020EE6C4D00210D55 /* SegmentedViewController.m in Sources */, B1B5599320EFC5E400210D55 /* DecryptionFailure.m in Sources */, B1098BF921ECFE65000DDA48 /* KeyBackupSetupCoordinator.swift in Sources */, + B140B4A821F8AB4600E3F5FE /* KeyBackupRecoverCoordinatorBridgePresenter.swift in Sources */, B1098BFE21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModelType.swift in Sources */, B1B558BE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */, F083BDED1E7009ED00A9B29C /* MXKRoomBubbleTableViewCell+Riot.m in Sources */, @@ -3428,10 +3545,13 @@ B1B558C720EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F020EF768F00210D55 /* RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m in Sources */, 926FA53F1F4C132000F826C2 /* MXSession+Riot.m in Sources */, + B139C22721FF319B00BB68EC /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift in Sources */, B1B5593820EF7BAC00210D55 /* TableViewCellWithLabelAndLargeTextView.m in Sources */, B1B558C820EF768F00210D55 /* RoomIncomingEncryptedAttachmentBubbleCell.m in Sources */, B1B557C620EF5CD400210D55 /* DirectoryServerDetailTableViewCell.m in Sources */, B1B5590920EF768F00210D55 /* RoomEmptyBubbleCell.m in Sources */, + B139C23321FF38A400BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift in Sources */, + B139C21F21FE5D6600BB68EC /* KeyBackupRecoverFromPassphraseViewAction.swift in Sources */, B1B5574720EE6C4D00210D55 /* UsersDevicesViewController.m in Sources */, B1098BFF21ECFE65000DDA48 /* PasswordStrengthView.swift in Sources */, B1B558D220EF768F00210D55 /* RoomEncryptedDataBubbleCell.m in Sources */, @@ -3442,7 +3562,10 @@ B1B557E920EF60F500210D55 /* MessagesSearchResultTextMsgBubbleCell.m in Sources */, B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */, B110872321F098F0003554A5 /* ActivityIndicatorPresenterType.swift in Sources */, + B139C22321FF01B200BB68EC /* KeyBackupRecoverFromPassphraseCoordinatorType.swift in Sources */, B110872621F098F0003554A5 /* ActivityIndicatorView.swift in Sources */, + B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */, + B1E5368D21FB7245001F3AFF /* KeyBackupRecoverFromPassphraseViewController.swift in Sources */, B169330320F3C98900746532 /* RoomBubbleCellData.m in Sources */, B1B557CC20EF5D8000210D55 /* DirectoryServerTableViewCell.m in Sources */, B1B5575C20EE6C4D00210D55 /* DirectoryViewController.m in Sources */, @@ -3455,12 +3578,15 @@ B1B558E520EF768F00210D55 /* RoomMembershipExpandedBubbleCell.m in Sources */, B1B5599420EFC5E400210D55 /* DecryptionFailureTracker.m in Sources */, F083BDF01E7009ED00A9B29C /* UIViewController+RiotSearch.m in Sources */, + B139C22D21FF32F000BB68EC /* KeyBackupRecoverFromRecoveryKeyViewState.swift in Sources */, + B139C23521FF38C600BB68EC /* KeyBackupRecoverFromRecoveryKeyCoordinator.swift in Sources */, F083BDF91E7009ED00A9B29C /* RoomEmailInvitation.m in Sources */, B1B5572C20EE6C4D00210D55 /* RoomParticipantsViewController.m in Sources */, B1B558EE20EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.m in Sources */, B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, + B139C22521FF01C100BB68EC /* KeyBackupRecoverFromPassphraseCoordinator.swift in Sources */, B1098BFD21ECFE65000DDA48 /* PasswordStrengthManager.swift in Sources */, B1B558F520EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m in Sources */, B1B558F820EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, @@ -3471,6 +3597,7 @@ B1B558FF20EF768F00210D55 /* RoomIncomingTextMsgBubbleCell.m in Sources */, B1098C0021ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.swift in Sources */, B1B5591020EF782800210D55 /* TableViewCellWithPhoneNumberTextField.m in Sources */, + B1E5368921FB1E20001F3AFF /* UIButton.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Riot/Generated/Storyboards.swift b/Riot/Generated/Storyboards.swift index 345c6a643..27244bb99 100644 --- a/Riot/Generated/Storyboards.swift +++ b/Riot/Generated/Storyboards.swift @@ -12,6 +12,21 @@ import UIKit // swiftlint:disable explicit_type_interface identifier_name line_length type_body_length type_name internal enum StoryboardScene { + internal enum KeyBackupRecoverFromPassphraseViewController: StoryboardType { + internal static let storyboardName = "KeyBackupRecoverFromPassphraseViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupRecoverFromPassphraseViewController.self) + } + internal enum KeyBackupRecoverFromRecoveryKeyViewController: StoryboardType { + internal static let storyboardName = "KeyBackupRecoverFromRecoveryKeyViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupRecoverFromRecoveryKeyViewController.self) + } + internal enum KeyBackupRecoverSuccessViewController: StoryboardType { + internal static let storyboardName = "KeyBackupRecoverSuccessViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupRecoverSuccessViewController.self) + } internal enum KeyBackupSetupIntroViewController: StoryboardType { internal static let storyboardName = "KeyBackupSetupIntroViewController" From af0a4e5ed5c8e453d4ef6ec12ef6eacf143e47a2 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 11:25:54 +0100 Subject: [PATCH 129/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 0a270b225..325cbf2c4 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -8,6 +8,7 @@ Improvements: * RoomVC: `Redact` has been renamed to `Remove` to match riot/web (#2134). * Clean up iOS version checking (#2190). * Key backup: Implement setup screen (#2198). + * Key backup: Implement recover screen (#2196). Bug fix: * Use white scroll bar on dark themes (#2158). From fdd6b7dd5cb9f6a06651752b55367c01833565aa Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 15:35:57 +0100 Subject: [PATCH 130/244] Fix Manu's remarks --- .../KeyBackupRecoverFromPassphraseViewModel.swift | 8 ++------ .../KeyBackupRecoverFromRecoveryKeyViewController.swift | 1 + .../KeyBackupRecoverFromRecoveryKeyViewModel.swift | 8 ++------ 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift index 825fe508e..d20572b4b 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift @@ -85,17 +85,13 @@ final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphr } sself.update(viewState: .loaded(totalKeys: totalKeys)) if totalKeys > 0 { - DispatchQueue.main.async { - sself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(sself) - } + sself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(sself) } }, failure: { [weak self] error in guard let sself = self else { return } - DispatchQueue.main.async { - sself.update(viewState: .error(error)) - } + sself.update(viewState: .error(error)) }) } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift index f66e8f9bb..8a4795cfe 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift @@ -200,6 +200,7 @@ final class KeyBackupRecoverFromRecoveryKeyViewController: UIViewController { private func importRecoveryKey(from url: URL) { if let recoveryKey = self.getDocumentContent(from: url) { self.recoveryKeyTextField.text = recoveryKey + self.recoveryKeyTextFieldDidChange(self.recoveryKeyTextField) } else { self.errorPresenter.presentGenericError(from: self, animated: true, handler: nil) } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift index a5cf9741d..0fefec573 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift @@ -85,17 +85,13 @@ final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecove } sself.update(viewState: .loaded(totalKeys: totalKeys)) if totalKeys > 0 { - DispatchQueue.main.async { - sself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(sself) - } + sself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(sself) } }, failure: { [weak self] error in guard let sself = self else { return } - DispatchQueue.main.async { - sself.update(viewState: .error(error)) - } + sself.update(viewState: .error(error)) }) } From ea126329cd8830759dc9534edead0807f9274752 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 30 Jan 2019 15:55:25 +0100 Subject: [PATCH 131/244] Update key backup recover coordinator initializers to give right instance of MXKeyBackup --- .../KeyBackup/Recover/KeyBackupRecoverCoordinator.swift | 4 ++-- .../KeyBackupRecoverFromPassphraseCoordinator.swift | 7 +++---- .../KeyBackupRecoverFromRecoveryKeyCoordinator.swift | 7 +++---- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift index 01f783a69..084bdc25e 100644 --- a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinator.swift @@ -67,13 +67,13 @@ final class KeyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType { // MARK: - Private private func createRecoverFromPassphraseCoordinator() -> KeyBackupRecoverFromPassphraseCoordinator { - let coordinator = KeyBackupRecoverFromPassphraseCoordinator(session: self.session, keyBackupVersion: self.keyBackupVersion) + let coordinator = KeyBackupRecoverFromPassphraseCoordinator(keyBackup: self.session.crypto.backup, keyBackupVersion: self.keyBackupVersion) coordinator.delegate = self return coordinator } private func createRecoverFromRecoveryKeyCoordinator() -> KeyBackupRecoverFromRecoveryKeyCoordinator { - let coordinator = KeyBackupRecoverFromRecoveryKeyCoordinator(session: self.session, keyBackupVersion: self.keyBackupVersion) + let coordinator = KeyBackupRecoverFromRecoveryKeyCoordinator(keyBackup: self.session.crypto.backup, keyBackupVersion: self.keyBackupVersion) coordinator.delegate = self return coordinator } diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinator.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinator.swift index b4c45ac66..40c85ff7e 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinator.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinator.swift @@ -22,7 +22,7 @@ final class KeyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassp // MARK: Private - private let session: MXSession + private let keyBackup: MXKeyBackup private let keyBackupRecoverFromPassphraseViewController: KeyBackupRecoverFromPassphraseViewController private let keyBackupVersion: MXKeyBackupVersion private var keyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphraseViewModelType @@ -35,11 +35,10 @@ final class KeyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassp // MARK: - Setup - init(session: MXSession, keyBackupVersion: MXKeyBackupVersion) { - self.session = session + init(keyBackup: MXKeyBackup, keyBackupVersion: MXKeyBackupVersion) { + self.keyBackup = keyBackup self.keyBackupVersion = keyBackupVersion - let keyBackup = MXKeyBackup(matrixSession: session) let keyBackupRecoverFromPassphraseViewModel = KeyBackupRecoverFromPassphraseViewModel(keyBackup: keyBackup, keyBackupVersion: keyBackupVersion) let keyBackupRecoverFromPassphraseViewController = KeyBackupRecoverFromPassphraseViewController.instantiate(with: keyBackupRecoverFromPassphraseViewModel) self.keyBackupRecoverFromPassphraseViewController = keyBackupRecoverFromPassphraseViewController diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift index eb4eb17ee..cf0f62353 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinator.swift @@ -22,7 +22,7 @@ final class KeyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromReco // MARK: Private - private let session: MXSession + private let keyBackup: MXKeyBackup private let keyBackupRecoverFromRecoveryKeyViewController: KeyBackupRecoverFromRecoveryKeyViewController private let keyBackupVersion: MXKeyBackupVersion private let keyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecoveryKeyViewModel @@ -35,11 +35,10 @@ final class KeyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromReco // MARK: - Setup - init(session: MXSession, keyBackupVersion: MXKeyBackupVersion) { - self.session = session + init(keyBackup: MXKeyBackup, keyBackupVersion: MXKeyBackupVersion) { + self.keyBackup = keyBackup self.keyBackupVersion = keyBackupVersion - let keyBackup = MXKeyBackup(matrixSession: session) let keyBackupRecoverFromRecoveryKeyViewModel = KeyBackupRecoverFromRecoveryKeyViewModel(keyBackup: keyBackup, keyBackupVersion: keyBackupVersion) let keyBackupRecoverFromRecoveryKeyViewController = KeyBackupRecoverFromRecoveryKeyViewController.instantiate(with: keyBackupRecoverFromRecoveryKeyViewModel) self.keyBackupRecoverFromRecoveryKeyViewController = keyBackupRecoverFromRecoveryKeyViewController From b4aa3d732f6cd63e5b8fbebfb0c609970fb81d14 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 03:06:47 +0100 Subject: [PATCH 132/244] key backup: Add a dedicated section to settings #2193 Still WIP --- Riot.xcodeproj/project.pbxproj | 32 ++ Riot/Assets/en.lproj/Vector.strings | 16 + Riot/Categories/UIControl.swift | 38 +++ Riot/Generated/Strings.swift | 60 ++++ .../SettingsKeyBackupTableViewSection.swift | 312 ++++++++++++++++++ .../SettingsKeyBackupViewAction.swift | 25 ++ .../SettingsKeyBackupViewModel.swift | 142 ++++++++ .../SettingsKeyBackupViewModelType.swift | 32 ++ .../SettingsKeyBackupViewState.swift | 33 ++ .../Modules/Settings/SettingsViewController.m | 202 +++++++++++- 10 files changed, 886 insertions(+), 6 deletions(-) create mode 100644 Riot/Categories/UIControl.swift create mode 100644 Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift create mode 100644 Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift create mode 100644 Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift create mode 100644 Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift create mode 100644 Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 940d86d1a..8b1f1605c 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -25,8 +25,14 @@ 3233F7461F3497E2006ACA81 /* JitsiMeet.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; }; 3233F7471F3497E2006ACA81 /* JitsiMeet.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3233F7441F3497DA006ACA81 /* JitsiMeet.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 3275FD8C21A5A2C500B9C13D /* TermsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3275FD8B21A5A2C500B9C13D /* TermsView.swift */; }; + 3281BCF72201FA4200F4A383 /* UIControl.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3281BCF62201FA4200F4A383 /* UIControl.swift */; }; 3284A35120A07C210044F922 /* postMessageAPI.js in Resources */ = {isa = PBXBuildFile; fileRef = 3284A35020A07C210044F922 /* postMessageAPI.js */; }; 32B1FEDB21A46F2C00637127 /* TermsView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 32B1FEDA21A46F2C00637127 /* TermsView.xib */; }; + 32BF994F21FA29A400698084 /* SettingsKeyBackupViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF994E21FA29A400698084 /* SettingsKeyBackupViewModel.swift */; }; + 32BF995121FA29DC00698084 /* SettingsKeyBackupViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995021FA29DC00698084 /* SettingsKeyBackupViewModelType.swift */; }; + 32BF995321FA2A1300698084 /* SettingsKeyBackupViewState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995221FA2A1300698084 /* SettingsKeyBackupViewState.swift */; }; + 32BF995521FA2AB700698084 /* SettingsKeyBackupViewAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995421FA2AB700698084 /* SettingsKeyBackupViewAction.swift */; }; + 32BF995721FB07A400698084 /* SettingsKeyBackupTableViewSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 32BF995621FB07A400698084 /* SettingsKeyBackupTableViewSection.swift */; }; 358DB9429359F97520545D35 /* Pods_RiotPods_RiotShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F5856BA7A55E53C0AEAFC084 /* Pods_RiotPods_RiotShareExtension.framework */; }; 89C94E649229EA68AE787E9E /* Pods_RiotPods_Riot.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2510A69B4A681C1FEC36E848 /* Pods_RiotPods_Riot.framework */; }; 926FA53F1F4C132000F826C2 /* MXSession+Riot.m in Sources */ = {isa = PBXBuildFile; fileRef = 926FA53E1F4C132000F826C2 /* MXSession+Riot.m */; }; @@ -469,6 +475,7 @@ 3267EFB520E379FD00FF1CAA /* AUTHORS.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = AUTHORS.rst; sourceTree = ""; }; 3267EFB620E379FD00FF1CAA /* README.rst */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = README.rst; sourceTree = ""; }; 3275FD8B21A5A2C500B9C13D /* TermsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TermsView.swift; sourceTree = ""; }; + 3281BCF62201FA4200F4A383 /* UIControl.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIControl.swift; sourceTree = ""; }; 3284A35020A07C210044F922 /* postMessageAPI.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = postMessageAPI.js; sourceTree = ""; }; 32B1FEDA21A46F2C00637127 /* TermsView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = TermsView.xib; sourceTree = ""; }; 32BDC9A1211C2C870064AF51 /* zh_Hant */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = zh_Hant; path = zh_Hant.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -477,6 +484,11 @@ 32BDC9A4211C34C90064AF51 /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/InfoPlist.strings; sourceTree = ""; }; 32BDC9A5211C34C90064AF51 /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Localizable.strings; sourceTree = ""; }; 32BDC9A6211C34C90064AF51 /* sq */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = sq; path = sq.lproj/Vector.strings; sourceTree = ""; }; + 32BF994E21FA29A400698084 /* SettingsKeyBackupViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKeyBackupViewModel.swift; sourceTree = ""; }; + 32BF995021FA29DC00698084 /* SettingsKeyBackupViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKeyBackupViewModelType.swift; sourceTree = ""; }; + 32BF995221FA2A1300698084 /* SettingsKeyBackupViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKeyBackupViewState.swift; sourceTree = ""; }; + 32BF995421FA2AB700698084 /* SettingsKeyBackupViewAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKeyBackupViewAction.swift; sourceTree = ""; }; + 32BF995621FB07A400698084 /* SettingsKeyBackupTableViewSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsKeyBackupTableViewSection.swift; sourceTree = ""; }; 32D7159E2146CC6F00DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Vector.strings; sourceTree = ""; }; 32D7159F2146CC7F00DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/Localizable.strings; sourceTree = ""; }; 32D715A02146CC8800DF59C9 /* es */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/InfoPlist.strings; sourceTree = ""; }; @@ -1160,6 +1172,18 @@ path = js; sourceTree = ""; }; + 32BF994D21FA1C6300698084 /* KeyBackup */ = { + isa = PBXGroup; + children = ( + 32BF994E21FA29A400698084 /* SettingsKeyBackupViewModel.swift */, + 32BF995021FA29DC00698084 /* SettingsKeyBackupViewModelType.swift */, + 32BF995221FA2A1300698084 /* SettingsKeyBackupViewState.swift */, + 32BF995421FA2AB700698084 /* SettingsKeyBackupViewAction.swift */, + 32BF995621FB07A400698084 /* SettingsKeyBackupTableViewSection.swift */, + ); + path = KeyBackup; + sourceTree = ""; + }; 5FC42FA41F5186AFFB6A2404 /* Frameworks */ = { isa = PBXGroup; children = ( @@ -1599,6 +1623,7 @@ B1B5567F20EE6C4C00210D55 /* SettingsViewController.h */, B1B5567E20EE6C4C00210D55 /* SettingsViewController.m */, B1B5578120EF564900210D55 /* Views */, + 32BF994D21FA1C6300698084 /* KeyBackup */, B1B5567B20EE6C4C00210D55 /* Language */, B1B5567820EE6C4C00210D55 /* PhoneCountry */, B1B5568020EE6C4C00210D55 /* DeactivateAccount */, @@ -2801,6 +2826,7 @@ B1CA3A2821EF692B000D1D89 /* UIView.swift */, B140B4A121F87F7100E3F5FE /* OperationQueue.swift */, B1E5368821FB1E20001F3AFF /* UIButton.swift */, + 3281BCF62201FA4200F4A383 /* UIControl.swift */, ); path = Categories; sourceTree = ""; @@ -3425,6 +3451,7 @@ B1B5598520EFC3E000210D55 /* RageShakeManager.m in Sources */, B1B558D420EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m in Sources */, B169331420F3CAFC00746532 /* PublicRoomTableViewCell.m in Sources */, + 32BF995721FB07A400698084 /* SettingsKeyBackupTableViewSection.swift in Sources */, B1B558E120EF768F00210D55 /* RoomMembershipCollapsedBubbleCell.m in Sources */, B1B5571A20EE6C4D00210D55 /* SettingsViewController.m in Sources */, B1B5594720EF7BD000210D55 /* RoomCollectionViewCell.m in Sources */, @@ -3574,8 +3601,11 @@ B1B558D320EF768F00210D55 /* RoomOutgoingEncryptedTextMsgBubbleCell.m in Sources */, B1B5576F20EE702800210D55 /* IntegrationManagerViewController.m in Sources */, B1B557AC20EF5A6D00210D55 /* DeviceView.m in Sources */, + 3281BCF72201FA4200F4A383 /* UIControl.swift in Sources */, B16932EE20F3C3C900746532 /* FilesSearchCellData.m in Sources */, B1B558E520EF768F00210D55 /* RoomMembershipExpandedBubbleCell.m in Sources */, + 32BF995121FA29DC00698084 /* SettingsKeyBackupViewModelType.swift in Sources */, + 32BF995321FA2A1300698084 /* SettingsKeyBackupViewState.swift in Sources */, B1B5599420EFC5E400210D55 /* DecryptionFailureTracker.m in Sources */, F083BDF01E7009ED00A9B29C /* UIViewController+RiotSearch.m in Sources */, B139C22D21FF32F000BB68EC /* KeyBackupRecoverFromRecoveryKeyViewState.swift in Sources */, @@ -3583,6 +3613,7 @@ F083BDF91E7009ED00A9B29C /* RoomEmailInvitation.m in Sources */, B1B5572C20EE6C4D00210D55 /* RoomParticipantsViewController.m in Sources */, B1B558EE20EF768F00210D55 /* RoomOutgoingAttachmentBubbleCell.m in Sources */, + 32BF994F21FA29A400698084 /* SettingsKeyBackupViewModel.swift in Sources */, B1B5574920EE6C4D00210D55 /* RiotSplitViewController.m in Sources */, B1B5574E20EE6C4D00210D55 /* DirectoryServerPickerViewController.m in Sources */, B1B5575B20EE6C4D00210D55 /* HomeFilesSearchViewController.m in Sources */, @@ -3594,6 +3625,7 @@ B16932E720F3C37100746532 /* HomeMessagesSearchDataSource.m in Sources */, B1B558CE20EF768F00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.m in Sources */, B1B5577D20EE84BF00210D55 /* CircleButton.m in Sources */, + 32BF995521FA2AB700698084 /* SettingsKeyBackupViewAction.swift in Sources */, B1B558FF20EF768F00210D55 /* RoomIncomingTextMsgBubbleCell.m in Sources */, B1098C0021ECFE65000DDA48 /* KeyBackupSetupPassphraseViewController.swift in Sources */, B1B5591020EF782800210D55 /* TableViewCellWithPhoneNumberTextField.m in Sources */, diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index a1b7a6015..9ad236d78 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -335,6 +335,7 @@ "settings_flair" = "Show flair where allowed"; "settings_devices" = "DEVICES"; "settings_cryptography" = "CRYPTOGRAPHY"; +"settings_key_backup" = "SECURE MESSAGE"; "settings_deactivate_account" = "DEACTIVATE ACCOUNT"; "settings_sign_out" = "Sign Out"; @@ -420,6 +421,21 @@ "settings_deactivate_my_account" = "Deactivate my account"; +"settings_key_backup_info_none" = "No backup is present"; +"settings_key_backup_info_version" = "Backup version: %@"; +"settings_key_backup_info_algorithm" = "Algorithm: %@"; +"settings_key_backup_info_valid" = "This device is using key backup"; +"settings_key_backup_info_not_valid" = "This device is not using key backup"; +"settings_key_backup_info_progress" = "Backing up %@ keys..."; +"settings_key_backup_info_progress_done" = "All keys backed up"; +"settings_key_backup_info_trust_signature_unknown" = "Backup has a signature from unknown device with ID %@."; +"settings_key_backup_info_trust_signature_valid" = "Backup has a valid signature from this device"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Backup has a valid signature from verified device %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Backup has a valid signature from unverified device %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Backup has a invalid signature from verified device %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Backup has a invalid signature from unverified device %@"; +"settings_key_backup_button_create" = "Start a new backup"; + // Room Details "room_details_title" = "Room Details"; "room_details_people" = "Members"; diff --git a/Riot/Categories/UIControl.swift b/Riot/Categories/UIControl.swift new file mode 100644 index 000000000..a6323581a --- /dev/null +++ b/Riot/Categories/UIControl.swift @@ -0,0 +1,38 @@ +/* + Copyright 2019 New Vector 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 UIKit + +// Source: https://stackoverflow.com/a/44917661 +class ClosureSleeve { + let closure: () -> () + + init(attachTo: AnyObject, closure: @escaping () -> ()) { + self.closure = closure + objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN) + } + + @objc func invoke() { + closure() + } +} + +extension UIControl { + func vc_addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) { + let sleeve = ClosureSleeve(attachTo: self, closure: action) + addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents) + } +} diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 0ab2019e5..ecaaf2e4f 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1918,6 +1918,66 @@ internal enum VectorL10n { internal static var settingsIgnoredUsers: String { return VectorL10n.tr("Vector", "settings_ignored_users") } + /// SECURE MESSAGE + internal static var settingsKeyBackup: String { + return VectorL10n.tr("Vector", "settings_key_backup") + } + /// Start a new backup + internal static var settingsKeyBackupButtonCreate: String { + return VectorL10n.tr("Vector", "settings_key_backup_button_create") + } + /// Algorithm: %@ + internal static func settingsKeyBackupInfoAlgorithm(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_algorithm", p1) + } + /// No backup is present + internal static var settingsKeyBackupInfoNone: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_none") + } + /// This device is not using key backup + internal static var settingsKeyBackupInfoNotValid: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_not_valid") + } + /// Backing up %@ keys... + internal static func settingsKeyBackupInfoProgress(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_progress", p1) + } + /// All keys backed up + internal static var settingsKeyBackupInfoProgressDone: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_progress_done") + } + /// Backup has a invalid signature from unverified device %@ + internal static func settingsKeyBackupInfoTrustSignatureInvalidDeviceUnverified(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_invalid_device_unverified", p1) + } + /// Backup has a invalid signature from verified device %@ + internal static func settingsKeyBackupInfoTrustSignatureInvalidDeviceVerified(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_invalid_device_verified", p1) + } + /// Backup has a signature from unknown device with ID %@. + internal static func settingsKeyBackupInfoTrustSignatureUnknown(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_unknown", p1) + } + /// Backup has a valid signature from this device + internal static var settingsKeyBackupInfoTrustSignatureValid: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid") + } + /// Backup has a valid signature from unverified device %@ + internal static func settingsKeyBackupInfoTrustSignatureValidDeviceUnverified(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_unverified", p1) + } + /// Backup has a valid signature from verified device %@ + internal static func settingsKeyBackupInfoTrustSignatureValidDeviceVerified(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_verified", p1) + } + /// This device is using key backup + internal static var settingsKeyBackupInfoValid: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_valid") + } + /// Backup version: %@ + internal static func settingsKeyBackupInfoVersion(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_version", p1) + } /// LABS internal static var settingsLabs: String { return VectorL10n.tr("Vector", "settings_labs") diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift new file mode 100644 index 000000000..e1e646d07 --- /dev/null +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -0,0 +1,312 @@ +/* + Copyright 2019 New Vector 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 UIKit + +@objc protocol SettingsKeyBackupTableViewSectionDelegate: class { + func settingsKeyBackupTableViewSectionDidUpdate(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection) + + func settingsKeyBackupTableViewSection(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, textCellForRow: Int) -> MXKTableViewCellWithTextView + func settingsKeyBackupTableViewSection(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, buttonCellForRow: Int) -> MXKTableViewCellWithButton + + + func settingsKeyBackupTableViewSectionShowKeyBackupSetup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection) + func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showVerifyDevice deviceId:String) + func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) +} + +@objc class SettingsKeyBackupTableViewSection: NSObject { + + // MARK: - Properties + + @objc weak var delegate: SettingsKeyBackupTableViewSectionDelegate? + @objc var tableViewCells: [UITableViewCell] + + // MARK: Private + + // This view class holds the model because the model is in pure Swift + // whereas this class can be used from objC + private var viewModel: SettingsKeyBackupViewModelType! + + // MARK: - Public + + @objc init(withKeyBackup keyBackup: MXKeyBackup) { + self.tableViewCells = [] + self.viewModel = SettingsKeyBackupViewModel(keyBackup: keyBackup) + super.init() + self.viewModel.viewDelegate = self + + self.viewModel.process(viewAction: .load) + } + + @objc func reload() { + self.viewModel.process(viewAction: .load) + } + + // MARK: - Private + + private func render(viewState: SettingsKeyBackupViewState) { + + guard let delegate = self.delegate else { + return + } + + switch viewState { + case .checkingBackup: + self.renderLoading() + + case .noBackup: + self.renderNoKeyBackup() + + case .backup(let keyBackupVersion, let keyBackupVersionTrust): + self.renderKeyBackup(keyBackupVersion, keyBackupVersionTrust: keyBackupVersionTrust) + + case .backupAndRunning(let keyBackupVersion, let keyBackupVersionTrust, let backupProgress): + self.renderRunningKeyBackup(keyBackupVersion, keyBackupVersionTrust: keyBackupVersionTrust, backupProgress: backupProgress) + + case .backupButNotTrusted(let keyBackupVersion, let keyBackupVersionTrust): + self.renderNotTrustedKeyBackup(keyBackupVersion, keyBackupVersionTrust: keyBackupVersionTrust) + } + + delegate.settingsKeyBackupTableViewSectionDidUpdate(self) + } + + private func renderLoading() { + // TODO: loading wheel + self.tableViewCells = [] + } + + private func renderNoKeyBackup() { + guard let delegate = self.delegate else { + return + } + + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + infoCell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoNone + + self.tableViewCells = [infoCell] + + // Add buttons + self.tableViewCells = [infoCell] + self.buttonCellForCreate(fromCellIndex: self.tableViewCells.count) + } + + private func renderKeyBackup(_ keyBackupVersion:MXKeyBackupVersion, keyBackupVersionTrust:MXKeyBackupVersionTrust) { + + guard let delegate = self.delegate, + let keyBackupVersionVersion = keyBackupVersion.version else { + return + } + + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersionVersion) + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let backupStatus = VectorL10n.settingsKeyBackupInfoValid + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + + let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + // Add buttons + self.tableViewCells = [infoCell] + self.buttonCellsForRestoreAndDelete(keyBackupVersion, fromCellIndex: self.tableViewCells.count) + } + + private func renderRunningKeyBackup(_ keyBackupVersion:MXKeyBackupVersion, keyBackupVersionTrust:MXKeyBackupVersionTrust, backupProgress:Progress) { + + guard let delegate = self.delegate, + let keyBackupVersionVersion = keyBackupVersion.version else { + return + } + + let remaining = backupProgress.totalUnitCount - backupProgress.completedUnitCount + + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersionVersion) + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let backupStatus = VectorL10n.settingsKeyBackupInfoValid + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgress(String(remaining)) + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + + let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + // Add buttons + self.tableViewCells = [infoCell] + self.buttonCellsForRestoreAndDelete(keyBackupVersion, fromCellIndex: 1) + } + + + private func renderNotTrustedKeyBackup(_ keyBackupVersion:MXKeyBackupVersion, keyBackupVersionTrust:MXKeyBackupVersionTrust) { + + guard let delegate = self.delegate, + let keyBackupVersionVersion = keyBackupVersion.version else { + return + } + + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersionVersion) + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let backupStatus = VectorL10n.settingsKeyBackupInfoNotValid + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + + let strings = [version, algorithm, backupStatus] + backupTrust + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + self.tableViewCells = [infoCell] + + // Display a verify button for the last non verified device only + let deviceId = self.lastNonVerifiedDevice(keyBackupVersionTrust) + self.tableViewCells = self.tableViewCells + self.buttonCellForVerifyingDevice(deviceId, fromCellIndex: self.tableViewCells.count) + + // Add buttons + self.tableViewCells = self.tableViewCells + self.buttonCellsForRestoreAndDelete(keyBackupVersion, fromCellIndex: self.tableViewCells.count) + } + + + // MARK: - Data Computing + + private func stringForKeyBackupTrust(_ keyBackupVersionTrust: MXKeyBackupVersionTrust) -> [String] { + + return keyBackupVersionTrust.signatures.map { (signature) -> String in + guard let device = signature.device else { + return VectorL10n.settingsKeyBackupInfoTrustSignatureUnknown(signature.deviceId) + } + + let displayName = device.displayName ?? device.deviceId ?? "" + + if device.fingerprint == "" { // TODO + return VectorL10n.settingsKeyBackupInfoTrustSignatureValid + } + else if signature.valid && (device.verified == MXDeviceVerified) { + return VectorL10n.settingsKeyBackupInfoTrustSignatureValidDeviceVerified(displayName) + } + else if signature.valid && (device.verified != MXDeviceVerified) { + return VectorL10n.settingsKeyBackupInfoTrustSignatureValidDeviceUnverified(displayName) + } + else if !signature.valid && (device.verified == MXDeviceVerified) { + return VectorL10n.settingsKeyBackupInfoTrustSignatureInvalidDeviceVerified(displayName) + } + else if !signature.valid && (device.verified != MXDeviceVerified) { + return VectorL10n.settingsKeyBackupInfoTrustSignatureInvalidDeviceUnverified(displayName) + } + + return ""; + } + } + + private func lastNonVerifiedDevice(_ keyBackupVersionTrust:MXKeyBackupVersionTrust) -> String? + { + var lastNonVerifiedDeviceId: String? + for signature in keyBackupVersionTrust.signatures.reversed() { + + guard let device = signature.device else { + continue + } + + if device.verified != MXDeviceVerified + { + lastNonVerifiedDeviceId = device.deviceId + break + } + } + return lastNonVerifiedDeviceId + } + + // MARK: - Cells + + private func buttonCellForCreate(fromCellIndex: Int = 0) -> [MXKTableViewCellWithButton] { + + guard let delegate = self.delegate else { + return [] + } + + let verifyCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: self.tableViewCells.count) + + let btnTitle = "Start a new backup" + verifyCell.mxkButton.setTitle(btnTitle, for: .normal) + verifyCell.mxkButton.setTitle(btnTitle, for: .highlighted) + + verifyCell.mxkButton.vc_addAction { + self.viewModel.process(viewAction: .create) + } + + return [verifyCell] + } + + private func buttonCellForVerifyingDevice(_ deviceId: String?, fromCellIndex: Int = 0) -> [MXKTableViewCellWithButton] { + + guard let deviceId = deviceId, let delegate = self.delegate else { + return [] + } + + let verifyCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: self.tableViewCells.count) + + let btnTitle = "Verify..." + verifyCell.mxkButton.setTitle(btnTitle, for: .normal) + verifyCell.mxkButton.setTitle(btnTitle, for: .highlighted) + + verifyCell.mxkButton.vc_addAction { + self.viewModel.process(viewAction: .verify(deviceId)) + } + + return [verifyCell] + } + + private func buttonCellsForRestoreAndDelete(_ keyBackupVersion: MXKeyBackupVersion, fromCellIndex: Int = 0) -> [MXKTableViewCellWithButton] { + guard let delegate = self.delegate else { + return [] + } + + let restoreCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: fromCellIndex) + let restoreTitle = "Restore backup" + restoreCell.mxkButton.setTitle(restoreTitle, for: .normal) + restoreCell.mxkButton.setTitle(restoreTitle, for: .highlighted) + restoreCell.mxkButton.vc_addAction { + self.viewModel.process(viewAction: .restore(keyBackupVersion)) + } + + let deleteCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: fromCellIndex + 1) + let deleteTitle = "Delete backup" + deleteCell.mxkButton.setTitle(deleteTitle, for: .normal) + deleteCell.mxkButton.setTitle(deleteTitle, for: .highlighted) + deleteCell.mxkButton.tintColor = ThemeService.shared().theme.warningColor + deleteCell.mxkButton.vc_addAction { + // TODO: Ask confirmation + self.viewModel.process(viewAction: .delete(keyBackupVersion)) + } + + return [restoreCell, deleteCell] + } +} + +// MARK: - KeyBackupSetupRecoveryKeyViewModelViewDelegate +extension SettingsKeyBackupTableViewSection: SettingsKeyBackupViewModelViewDelegate { + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewSate: SettingsKeyBackupViewState) { + self.render(viewState: viewSate) + } + + func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) { + self.delegate?.settingsKeyBackupTableViewSectionShowKeyBackupSetup(self) + } + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showVerifyDevice deviceId: String) { + self.delegate?.settingsKeyBackup(self, showVerifyDevice: deviceId) + } + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupRecover keyBackupVersion: MXKeyBackupVersion) { + self.delegate?.settingsKeyBackup(self, showKeyBackupRecover: keyBackupVersion) + } +} diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift new file mode 100644 index 000000000..aab4be8e4 --- /dev/null +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift @@ -0,0 +1,25 @@ +/* + Copyright 2019 New Vector 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 UIKit + +enum SettingsKeyBackupViewAction { + case load + case create + case verify(String) + case restore(MXKeyBackupVersion) + case delete(MXKeyBackupVersion) +} diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift new file mode 100644 index 000000000..d93497fb7 --- /dev/null +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -0,0 +1,142 @@ +/* + Copyright 2019 New Vector 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 UIKit + +class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { + + // MARK: - Properties + weak var viewDelegate: SettingsKeyBackupViewModelViewDelegate? + + // MARK: Private + private let keyBackup: MXKeyBackup + + init(keyBackup: MXKeyBackup) { + self.keyBackup = keyBackup + self.registerKeyBackupVersionDidChangeStateNotification() + } + + private func registerKeyBackupVersionDidChangeStateNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(keyBackupDidStateChange), name: NSNotification.Name.mxKeyBackupDidStateChange, object: self.keyBackup) + } + + @objc private func keyBackupDidStateChange() { + self.checkKeyBackupState() + } + + func process(viewAction: SettingsKeyBackupViewAction) { + guard let viewDelegate = self.viewDelegate else { + return + } + + switch viewAction { + case .load: + self.viewDelegate?.settingsKeyBackupViewModel(self, didUpdateViewState: .checkingBackup) + self.checkKeyBackupState() + case .create: + viewDelegate.settingsKeyBackupViewModelShowKeyBackupSetup(self) + break + case .verify(let deviceId): + viewDelegate.settingsKeyBackup(self, showVerifyDevice: deviceId) + break + case .restore(let keyBackupVersion): + viewDelegate.settingsKeyBackup(self, showKeyBackupRecover: keyBackupVersion) + break + case .delete(let keyBackupVersion): + self.deleteKeyBackupVersion(keyBackupVersion) + break + } + } + + // MARK: - Private + + func checkKeyBackupState() { + + if let keyBackupVersion = self.keyBackup.keyBackupVersion { + + self.keyBackup.trust(for: keyBackupVersion, onComplete: { [weak self] (keyBackupVersionTrust) in + + guard let sself = self else { + return + } + + sself.computeState(withBackupVersionTrust:keyBackupVersionTrust) + }) + } + else { + computeState() + } + } + + func computeState(withBackupVersionTrust keyBackupVersionTrust:MXKeyBackupVersionTrust? = nil) { + + var viewState: SettingsKeyBackupViewState? + switch self.keyBackup.state { + + case MXKeyBackupStateUnknown, + MXKeyBackupStateCheckingBackUpOnHomeserver: + viewState = .checkingBackup + + case MXKeyBackupStateDisabled, MXKeyBackupStateEnabling: + viewState = .noBackup + + case MXKeyBackupStateNotTrusted: + guard let keyBackupVersion = self.keyBackup.keyBackupVersion, let keyBackupVersionTrust = keyBackupVersionTrust else { + return + } + viewState = .backupButNotTrusted(keyBackupVersion, keyBackupVersionTrust) + + case MXKeyBackupStateReadyToBackUp: + guard let keyBackupVersion = self.keyBackup.keyBackupVersion, let keyBackupVersionTrust = keyBackupVersionTrust else { + return + } + viewState = .backup(keyBackupVersion, keyBackupVersionTrust) + + case MXKeyBackupStateWillBackUp, MXKeyBackupStateBackingUp: + guard let keyBackupVersion = self.keyBackup.keyBackupVersion, let keyBackupVersionTrust = keyBackupVersionTrust else { + return + } + + // Get the backup progress before updating the state + self.keyBackup.backupProgress { [weak self] (progress) in + guard let sself = self else { + return + } + + sself.viewDelegate?.settingsKeyBackupViewModel(sself, didUpdateViewState: .backupAndRunning(keyBackupVersion, keyBackupVersionTrust, progress)) + } + default: + break + } + + if let vviewState = viewState { + self.viewDelegate?.settingsKeyBackupViewModel(self, didUpdateViewState: vviewState) + } + } + + func deleteKeyBackupVersion(_ keyBackupVersion: MXKeyBackupVersion) { + guard let keyBackupVersionVersion = keyBackupVersion.version else { + return + } + + self.keyBackup.deleteVersion(keyBackupVersionVersion, success: { + + }) { (Error) in + + } + + } +} diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift new file mode 100644 index 000000000..41b03dd77 --- /dev/null +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift @@ -0,0 +1,32 @@ +/* + Copyright 2019 New Vector 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 UIKit + +protocol SettingsKeyBackupViewModelViewDelegate: class { + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewSate: SettingsKeyBackupViewState) + + func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showVerifyDevice deviceId:String) + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) +} + +protocol SettingsKeyBackupViewModelType { + + var viewDelegate: SettingsKeyBackupViewModelViewDelegate? { get set } + + func process(viewAction: SettingsKeyBackupViewAction) +} diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift new file mode 100644 index 000000000..2e1ad30d6 --- /dev/null +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift @@ -0,0 +1,33 @@ +/* + Copyright 2019 New Vector 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 UIKit + +/// SettingsKeyBackup view state +/// +/// - checkingBackup: Load current backup on the homeserver +/// - checkError: Fail to load current backup data +/// - noBackup: There is no backup on the homeserver +/// - backup: There is a valid backup on the homeserver. All keys have been backed up to it +/// - backupAndRunning: There is a valid backup on the homeserver. Keys are being sent to it +/// - backupButNotVerified: There is a backup on the homeserver but it has not been verified yet +enum SettingsKeyBackupViewState { + case checkingBackup + case noBackup + case backup(MXKeyBackupVersion, MXKeyBackupVersionTrust) + case backupAndRunning(MXKeyBackupVersion, MXKeyBackupVersionTrust, Progress) + case backupButNotTrusted(MXKeyBackupVersion, MXKeyBackupVersionTrust) +} diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 18d7e3fb7..451c16661 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -48,6 +48,8 @@ #import "Riot-Swift.h" +#import "EncryptionInfoView.h" + NSString* const kSettingsViewControllerPhoneBookCountryCellId = @"kSettingsViewControllerPhoneBookCountryCellId"; enum @@ -63,8 +65,9 @@ enum SETTINGS_SECTION_OTHER_INDEX, SETTINGS_SECTION_LABS_INDEX, SETTINGS_SECTION_CRYPTOGRAPHY_INDEX, - SETTINGS_SECTION_FLAIR_INDEX, + SETTINGS_SECTION_KEYBACKUP_INDEX, SETTINGS_SECTION_DEVICES_INDEX, + SETTINGS_SECTION_FLAIR_INDEX, SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX, SETTINGS_SECTION_COUNT }; @@ -135,7 +138,11 @@ enum { typedef void (^blockSettingsViewController_onReadyToDestroy)(void); -@interface SettingsViewController () +@interface SettingsViewController () { // Current alert (if any). UIAlertController *currentAlert; @@ -227,6 +234,10 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); // The current pushed view controller UIViewController *pushedViewController; + + SettingsKeyBackupTableViewSection *keyBackupSection; + KeyBackupSetupCoordinatorBridgePresenter *keyBackupSetupCoordinatorBridgePresenter; + KeyBackupRecoverCoordinatorBridgePresenter *keyBackupRecoverCoordinatorBridgePresenter; } /** @@ -314,7 +325,13 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); { [self addMatrixSession:mxSession]; } - + + if (self.mainSession.crypto.backup) + { + keyBackupSection = [[SettingsKeyBackupTableViewSection alloc] initWithKeyBackup:self.mainSession.crypto.backup]; + keyBackupSection.delegate = self; + } + groupsDataSource = [[GroupsDataSource alloc] initWithMatrixSession:self.mainSession]; [groupsDataSource finalizeInitialization]; groupsDataSource.delegate = self; @@ -404,6 +421,9 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); [super destroy]; } + + keyBackupSetupCoordinatorBridgePresenter = nil; + keyBackupRecoverCoordinatorBridgePresenter = nil; } - (void)onMatrixSessionStateDidChange:(NSNotification *)notif @@ -1279,6 +1299,14 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); count = CRYPTOGRAPHY_COUNT; } } + else if (section == SETTINGS_SECTION_KEYBACKUP_INDEX) + { + // Check whether this section is visible. + if (self.mainSession.crypto) + { + count = keyBackupSection.tableViewCells.count; + } + } else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX) { count = 1; @@ -2205,6 +2233,13 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); cell = exportKeysBtnCell; } } + else if (section == SETTINGS_SECTION_KEYBACKUP_INDEX) + { + if (row < keyBackupSection.tableViewCells.count) + { + cell = keyBackupSection.tableViewCells[row]; + } + } else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX) { MXKTableViewCellWithButton *deactivateAccountBtnCell = [tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]]; @@ -2308,12 +2343,12 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); return NSLocalizedStringFromTable(@"settings_cryptography", @"Vector", nil); } } - else if (section == SETTINGS_SECTION_CRYPTOGRAPHY_INDEX) + else if (section == SETTINGS_SECTION_KEYBACKUP_INDEX) { // Check whether this section is visible if (self.mainSession.crypto) { - return NSLocalizedStringFromTable(@"settings_cryptography", @"Vector", nil); + return NSLocalizedStringFromTable(@"settings_key_backup", @"Vector", nil); } } else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX) @@ -4206,7 +4241,6 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); - (void)deactivateAccountViewControllerDidDeactivateWithSuccess:(DeactivateAccountViewController *)deactivateAccountViewController { NSLog(@"[SettingsViewController] Deactivate account with success"); - [[AppDelegate theDelegate] logoutSendingRequestServer:NO completion:^(BOOL isLoggedOut) { NSLog(@"[SettingsViewController] Complete clear user data after account deactivation"); @@ -4218,4 +4252,160 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); [deactivateAccountViewController dismissViewControllerAnimated:YES completion:nil]; } +#pragma mark - SettingsKeyBackupTableViewSectionDelegate + +- (void)settingsKeyBackupTableViewSectionDidUpdate:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection +{ + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:SETTINGS_SECTION_KEYBACKUP_INDEX] + withRowAnimation:UITableViewRowAnimationAutomatic]; +} + +- (MXKTableViewCellWithTextView *)settingsKeyBackupTableViewSection:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection textCellForRow:(NSInteger)textCellForRow +{ + return [self textViewCellForTableView:self.tableView atIndexPath:[NSIndexPath indexPathForRow:textCellForRow inSection:SETTINGS_SECTION_KEYBACKUP_INDEX]]; +} + +- (MXKTableViewCellWithButton *)settingsKeyBackupTableViewSection:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection buttonCellForRow:(NSInteger)buttonCellForRow +{ + MXKTableViewCellWithButton *cell = [self.tableView dequeueReusableCellWithIdentifier:[MXKTableViewCellWithButton defaultReuseIdentifier]]; + + if (!cell) + { + cell = [[MXKTableViewCellWithButton alloc] init]; + } + else + { + // Fix https://github.com/vector-im/riot-ios/issues/1354 + cell.mxkButton.titleLabel.text = nil; + } + + cell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; + [cell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; + + [cell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; + cell.mxkButton.accessibilityIdentifier = nil; + + return cell; +} + +- (void)settingsKeyBackupTableViewSectionShowKeyBackupSetup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection +{ + [self showKeyBackupSetup]; +} + +- (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showVerifyDevice:(NSString *)deviceId +{ + MXDeviceInfo *deviceInfo = [self.mainSession.crypto.deviceList storedDevice:self.mainSession.myUser.userId deviceId:deviceId]; + [self showDeviceInfo:deviceInfo]; +} + +- (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showKeyBackupRecover:(MXKeyBackupVersion *)keyBackupVersion +{ + [self showKeyBackupRecover:keyBackupVersion]; +} + +#pragma mark - MXKEncryptionInfoView + +- (void)showDeviceInfo:(MXDeviceInfo*)deviceInfo +{ + // Show it modally on the root view controller + // TODO: Improve it + UIViewController *rootViewController = [AppDelegate theDelegate].window.rootViewController; + if (rootViewController) + { + EncryptionInfoView *encryptionInfoView = [[EncryptionInfoView alloc] initWithDeviceInfo:deviceInfo andMatrixSession:self.mainSession]; + [encryptionInfoView onButtonPressed:encryptionInfoView.verifyButton]; + + encryptionInfoView.delegate = self; + + // Add shadow on added view + encryptionInfoView.layer.cornerRadius = 5; + encryptionInfoView.layer.shadowOffset = CGSizeMake(0, 1); + encryptionInfoView.layer.shadowOpacity = 0.5f; + + // Add the view and define edge constraints + [rootViewController.view addSubview:encryptionInfoView]; + + [rootViewController.view addConstraint:[NSLayoutConstraint constraintWithItem:encryptionInfoView + attribute:NSLayoutAttributeTop + relatedBy:NSLayoutRelationEqual + toItem:rootViewController.topLayoutGuide + attribute:NSLayoutAttributeBottom + multiplier:1.0f + constant:10.0f]]; + + [rootViewController.view addConstraint:[NSLayoutConstraint constraintWithItem:encryptionInfoView + attribute:NSLayoutAttributeBottom + relatedBy:NSLayoutRelationEqual + toItem:rootViewController.bottomLayoutGuide + attribute:NSLayoutAttributeTop + multiplier:1.0f + constant:-10.0f]]; + + [rootViewController.view addConstraint:[NSLayoutConstraint constraintWithItem:rootViewController.view + attribute:NSLayoutAttributeLeading + relatedBy:NSLayoutRelationEqual + toItem:encryptionInfoView + attribute:NSLayoutAttributeLeading + multiplier:1.0f + constant:-10.0f]]; + + [rootViewController.view addConstraint:[NSLayoutConstraint constraintWithItem:rootViewController.view + attribute:NSLayoutAttributeTrailing + relatedBy:NSLayoutRelationEqual + toItem:encryptionInfoView + attribute:NSLayoutAttributeTrailing + multiplier:1.0f + constant:10.0f]]; + [rootViewController.view setNeedsUpdateConstraints]; + } +} + +- (void)encryptionInfoView:(MXKEncryptionInfoView*)encryptionInfoView didDeviceInfoVerifiedChange:(MXDeviceInfo*)deviceInfo +{ + [keyBackupSection reload]; +} + +#pragma mark - KeyBackupRecoverCoordinatorBridgePresenter + +- (void)showKeyBackupSetup +{ + keyBackupSetupCoordinatorBridgePresenter = [[KeyBackupSetupCoordinatorBridgePresenter alloc] initWithSession:self.mainSession]; + + [keyBackupSetupCoordinatorBridgePresenter presentFrom:self animated:true]; + keyBackupSetupCoordinatorBridgePresenter.delegate = self; +} + +- (void)keyBackupSetupCoordinatorBridgePresenterDelegateDidCancel:(KeyBackupSetupCoordinatorBridgePresenter *)bridgePresenter { + [keyBackupSetupCoordinatorBridgePresenter dismissWithAnimated:true]; + keyBackupSetupCoordinatorBridgePresenter = nil; +} + +- (void)keyBackupSetupCoordinatorBridgePresenterDelegateDidSetupRecoveryKey:(KeyBackupSetupCoordinatorBridgePresenter *)bridgePresenter { + [keyBackupSetupCoordinatorBridgePresenter dismissWithAnimated:true]; + keyBackupSetupCoordinatorBridgePresenter = nil; + + [keyBackupSection reload]; +} + +#pragma mark - KeyBackupRecoverCoordinatorBridgePresenter + +- (void)showKeyBackupRecover:(MXKeyBackupVersion*)keyBackupVersion +{ + keyBackupRecoverCoordinatorBridgePresenter = [[KeyBackupRecoverCoordinatorBridgePresenter alloc] initWithSession:self.mainSession keyBackupVersion:keyBackupVersion]; + + [keyBackupRecoverCoordinatorBridgePresenter presentFrom:self animated:true]; + keyBackupRecoverCoordinatorBridgePresenter.delegate = self; +} + +- (void)keyBackupRecoverCoordinatorBridgePresenterDidCancel:(KeyBackupRecoverCoordinatorBridgePresenter *)bridgePresenter { + [keyBackupRecoverCoordinatorBridgePresenter dismissWithAnimated:true]; + keyBackupRecoverCoordinatorBridgePresenter = nil; +} + +- (void)keyBackupRecoverCoordinatorBridgePresenterDidRecover:(KeyBackupRecoverCoordinatorBridgePresenter *)bridgePresenter { + [keyBackupRecoverCoordinatorBridgePresenter dismissWithAnimated:true]; + keyBackupRecoverCoordinatorBridgePresenter = nil; +} + @end From 71f6b06f027e2adb83f7c1941c45c8dac9b37b07 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 09:45:03 +0100 Subject: [PATCH 133/244] key backup settings: add delete confirmation dialog --- Riot/Assets/en.lproj/Vector.strings | 3 ++ Riot/Generated/Strings.swift | 12 ++++++++ .../SettingsKeyBackupTableViewSection.swift | 13 ++++++-- .../SettingsKeyBackupViewAction.swift | 1 + .../SettingsKeyBackupViewModel.swift | 3 ++ .../SettingsKeyBackupViewModelType.swift | 1 + .../Modules/Settings/SettingsViewController.m | 30 +++++++++++++++++++ 7 files changed, 60 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 9ad236d78..f1b8659bf 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -435,6 +435,9 @@ "settings_key_backup_info_trust_signature_invalid_device_verified" = "Backup has a invalid signature from verified device %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "Backup has a invalid signature from unverified device %@"; "settings_key_backup_button_create" = "Start a new backup"; +"settings_key_backup_button_delete" = "Delete backup"; +"settings_key_backup_delete_confirmation_prompt_title" = "Delete Backup"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history"; // Room Details "room_details_title" = "Room Details"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index ecaaf2e4f..7f8c68f57 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1926,6 +1926,18 @@ internal enum VectorL10n { internal static var settingsKeyBackupButtonCreate: String { return VectorL10n.tr("Vector", "settings_key_backup_button_create") } + /// Delete backup + internal static var settingsKeyBackupButtonDelete: String { + return VectorL10n.tr("Vector", "settings_key_backup_button_delete") + } + /// Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history + internal static var settingsKeyBackupDeleteConfirmationPromptMsg: String { + return VectorL10n.tr("Vector", "settings_key_backup_delete_confirmation_prompt_msg") + } + /// Delete Backup + internal static var settingsKeyBackupDeleteConfirmationPromptTitle: String { + return VectorL10n.tr("Vector", "settings_key_backup_delete_confirmation_prompt_title") + } /// Algorithm: %@ internal static func settingsKeyBackupInfoAlgorithm(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_algorithm", p1) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index e1e646d07..332139a0f 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -26,6 +26,7 @@ import UIKit func settingsKeyBackupTableViewSectionShowKeyBackupSetup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection) func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showVerifyDevice deviceId:String) func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) + func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupDeleteConfirm keyBackupVersion:MXKeyBackupVersion) } @objc class SettingsKeyBackupTableViewSection: NSObject { @@ -56,6 +57,10 @@ import UIKit self.viewModel.process(viewAction: .load) } + @objc func delete(keyBackupVersion: MXKeyBackupVersion) { + self.viewModel.process(viewAction: .delete(keyBackupVersion)) + } + // MARK: - Private private func render(viewState: SettingsKeyBackupViewState) { @@ -281,13 +286,12 @@ import UIKit } let deleteCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: fromCellIndex + 1) - let deleteTitle = "Delete backup" + let deleteTitle = VectorL10n.settingsKeyBackupButtonDelete deleteCell.mxkButton.setTitle(deleteTitle, for: .normal) deleteCell.mxkButton.setTitle(deleteTitle, for: .highlighted) deleteCell.mxkButton.tintColor = ThemeService.shared().theme.warningColor deleteCell.mxkButton.vc_addAction { - // TODO: Ask confirmation - self.viewModel.process(viewAction: .delete(keyBackupVersion)) + self.viewModel.process(viewAction: .confirmDelete(keyBackupVersion)) } return [restoreCell, deleteCell] @@ -309,4 +313,7 @@ extension SettingsKeyBackupTableViewSection: SettingsKeyBackupViewModelViewDeleg func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupRecover keyBackupVersion: MXKeyBackupVersion) { self.delegate?.settingsKeyBackup(self, showKeyBackupRecover: keyBackupVersion) } + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupDeleteConfirm keyBackupVersion: MXKeyBackupVersion) { + self.delegate?.settingsKeyBackup(self, showKeyBackupDeleteConfirm: keyBackupVersion) + } } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift index aab4be8e4..f1748bf67 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift @@ -21,5 +21,6 @@ enum SettingsKeyBackupViewAction { case create case verify(String) case restore(MXKeyBackupVersion) + case confirmDelete(MXKeyBackupVersion) case delete(MXKeyBackupVersion) } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index d93497fb7..ee5abb4d9 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -55,6 +55,9 @@ class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { case .restore(let keyBackupVersion): viewDelegate.settingsKeyBackup(self, showKeyBackupRecover: keyBackupVersion) break + case .confirmDelete(let keyBackupVersion): + viewDelegate.settingsKeyBackup(self, showKeyBackupDeleteConfirm: keyBackupVersion) + break case .delete(let keyBackupVersion): self.deleteKeyBackupVersion(keyBackupVersion) break diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift index 41b03dd77..9fb17cdd4 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift @@ -22,6 +22,7 @@ protocol SettingsKeyBackupViewModelViewDelegate: class { func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showVerifyDevice deviceId:String) func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupDeleteConfirm keyBackupVersion:MXKeyBackupVersion) } protocol SettingsKeyBackupViewModelType { diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 451c16661..497be828e 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -4304,6 +4304,36 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> [self showKeyBackupRecover:keyBackupVersion]; } +- (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showKeyBackupDeleteConfirm:(MXKeyBackupVersion *)keyBackupVersion +{ + MXWeakify(self); + [currentAlert dismissViewControllerAnimated:NO completion:nil]; + + currentAlert = + [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"settings_key_backup_delete_confirmation_prompt_title", @"Vector", nil) + message:NSLocalizedStringFromTable(@"settings_key_backup_delete_confirmation_prompt_msg", @"Vector", nil) + preferredStyle:UIAlertControllerStyleAlert]; + + [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"] + style:UIAlertActionStyleCancel + handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + }]]; + + [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"remove", @"Vector", nil) + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + [self->keyBackupSection deleteWithKeyBackupVersion:keyBackupVersion]; + }]]; + + [currentAlert mxk_setAccessibilityIdentifier: @"SettingsVCDeleteKeyBackup"]; + [self presentViewController:currentAlert animated:YES completion:nil]; +} + #pragma mark - MXKEncryptionInfoView - (void)showDeviceInfo:(MXDeviceInfo*)deviceInfo From 428c001812347acc6e805b35d1fae377c8b17f47 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 10:19:27 +0100 Subject: [PATCH 134/244] key backup settings: Make it display loading wheel and error --- .../SettingsKeyBackupTableViewSection.swift | 14 ++++++++++++++ .../KeyBackup/SettingsKeyBackupViewModel.swift | 16 ++++++++++++---- .../SettingsKeyBackupViewModelType.swift | 1 + .../KeyBackup/SettingsKeyBackupViewState.swift | 8 ++++++++ Riot/Modules/Settings/SettingsViewController.m | 17 +++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index 332139a0f..7e489fba1 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -27,6 +27,9 @@ import UIKit func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showVerifyDevice deviceId:String) func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupDeleteConfirm keyBackupVersion:MXKeyBackupVersion) + + func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showActivityIndicator show:Bool) + func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showError error:Error) } @objc class SettingsKeyBackupTableViewSection: NSObject { @@ -303,6 +306,17 @@ extension SettingsKeyBackupTableViewSection: SettingsKeyBackupViewModelViewDeleg func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewSate: SettingsKeyBackupViewState) { self.render(viewState: viewSate) } + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsKeyBackupNetworkRequestViewState) { + switch networkRequestViewSate { + case .loading: + self.delegate?.settingsKeyBackup(self, showActivityIndicator: true) + case .loaded: + self.delegate?.settingsKeyBackup(self, showActivityIndicator: false) + case .error(let error): + self.delegate?.settingsKeyBackup(self, showError: error) + break + } + } func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) { self.delegate?.settingsKeyBackupTableViewSectionShowKeyBackupSetup(self) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index ee5abb4d9..2a099fb38 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -135,11 +135,19 @@ class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { return } - self.keyBackup.deleteVersion(keyBackupVersionVersion, success: { + self.viewDelegate?.settingsKeyBackupViewModel(self, didUpdateNetworkRequestViewState: .loading) - }) { (Error) in - - } + self.keyBackup.deleteVersion(keyBackupVersionVersion, success: { [weak self] () in + guard let sself = self else { + return + } + sself.viewDelegate?.settingsKeyBackupViewModel(sself, didUpdateNetworkRequestViewState: .loaded) + }, failure: { [weak self] error in + guard let sself = self else { + return + } + sself.viewDelegate?.settingsKeyBackupViewModel(sself, didUpdateNetworkRequestViewState: .error(error)) + }) } } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift index 9fb17cdd4..7f6264e03 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift @@ -18,6 +18,7 @@ import UIKit protocol SettingsKeyBackupViewModelViewDelegate: class { func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewSate: SettingsKeyBackupViewState) + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsKeyBackupNetworkRequestViewState) func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showVerifyDevice deviceId:String) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift index 2e1ad30d6..5b3ced337 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift @@ -31,3 +31,11 @@ enum SettingsKeyBackupViewState { case backupAndRunning(MXKeyBackupVersion, MXKeyBackupVersionTrust, Progress) case backupButNotTrusted(MXKeyBackupVersion, MXKeyBackupVersionTrust) } + +/// State representing a network request made by the module +/// Only SettingsKeyBackupViewAction.delete generates such states +enum SettingsKeyBackupNetworkRequestViewState { + case loading + case loaded + case error(Error) +} diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 497be828e..3fbc9b642 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -4334,6 +4334,23 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> [self presentViewController:currentAlert animated:YES completion:nil]; } +- (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showActivityIndicator:(BOOL)show +{ + if (show) + { + [self startActivityIndicator]; + } + else + { + [self stopActivityIndicator]; + } +} + +- (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showError:(NSError *)error +{ + [[AppDelegate theDelegate] showErrorAsAlert:error]; +} + #pragma mark - MXKEncryptionInfoView - (void)showDeviceInfo:(MXDeviceInfo*)deviceInfo From 2707971e686090de2a21bc89185872722b7c299d Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 15:45:43 +0100 Subject: [PATCH 135/244] key backup settings: Fix cell reuse mechanism --- .../SettingsKeyBackupTableViewSection.swift | 369 ++++++++++++------ .../SettingsKeyBackupViewModel.swift | 2 +- .../SettingsKeyBackupViewModelType.swift | 2 +- .../SettingsKeyBackupViewState.swift | 2 +- .../Modules/Settings/SettingsViewController.m | 10 +- 5 files changed, 244 insertions(+), 141 deletions(-) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index 7e489fba1..d1d3baa4f 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -37,7 +37,6 @@ import UIKit // MARK: - Properties @objc weak var delegate: SettingsKeyBackupTableViewSectionDelegate? - @objc var tableViewCells: [UITableViewCell] // MARK: Private @@ -45,10 +44,12 @@ import UIKit // whereas this class can be used from objC private var viewModel: SettingsKeyBackupViewModelType! + // Need to know the state to make `cellForRow` deliver cells accordingly + private var viewState: SettingsKeyBackupViewState = .checkingBackup + // MARK: - Public @objc init(withKeyBackup keyBackup: MXKeyBackup) { - self.tableViewCells = [] self.viewModel = SettingsKeyBackupViewModel(keyBackup: keyBackup) super.init() self.viewModel.viewDelegate = self @@ -56,6 +57,55 @@ import UIKit self.viewModel.process(viewAction: .load) } + @objc func numberOfRows() -> Int { + var numberOfRows: Int + + switch self.viewState { + case .checkingBackup: + numberOfRows = self.numberOfCheckingBackupRows() + case .noBackup: + numberOfRows = self.numberOfNoBackupRows() + case .backup(_, _): + numberOfRows = self.numberOfBackupRows() + case .backupAndRunning(_, _, _): + numberOfRows = self.numberOfBackupAndRunningRows() + case .backupNotTrusted(_, let keyBackupVersionTrust): + numberOfRows = self.numberOfBackupNotTrustedRows(keyBackupVersionTrust: keyBackupVersionTrust) + } + + return numberOfRows + } + + @objc func cellForRow(atRow row:Int) -> UITableViewCell { + var cell: UITableViewCell + + switch self.viewState { + case .checkingBackup: + cell = self.renderCheckingBackupCell(atRow:row) + + case .noBackup: + cell = self.renderNoBackupCell(atRow:row) + + case .backup(let keyBackupVersion, let keyBackupVersionTrust): + cell = self.renderBackupCell(atRow: row, + keyBackupVersion: keyBackupVersion, + keyBackupVersionTrust: keyBackupVersionTrust) + + case .backupAndRunning(let keyBackupVersion, let keyBackupVersionTrust, let backupProgress): + cell = self.renderBackupAndRunningCell(atRow:row, + keyBackupVersion: keyBackupVersion, + keyBackupVersionTrust: keyBackupVersionTrust, + backupProgress: backupProgress) + + case .backupNotTrusted(let keyBackupVersion, let keyBackupVersionTrust): + cell = self.renderBackupNotTrustedCell(atRow:row, + keyBackupVersion: keyBackupVersion, + keyBackupVersionTrust: keyBackupVersionTrust) + } + + return cell + } + @objc func reload() { self.viewModel.process(viewAction: .load) } @@ -64,125 +114,171 @@ import UIKit self.viewModel.process(viewAction: .delete(keyBackupVersion)) } - // MARK: - Private - private func render(viewState: SettingsKeyBackupViewState) { + // MARK: - Pseudo TableView datasource - guard let delegate = self.delegate else { - return - } - - switch viewState { - case .checkingBackup: - self.renderLoading() - - case .noBackup: - self.renderNoKeyBackup() - - case .backup(let keyBackupVersion, let keyBackupVersionTrust): - self.renderKeyBackup(keyBackupVersion, keyBackupVersionTrust: keyBackupVersionTrust) - - case .backupAndRunning(let keyBackupVersion, let keyBackupVersionTrust, let backupProgress): - self.renderRunningKeyBackup(keyBackupVersion, keyBackupVersionTrust: keyBackupVersionTrust, backupProgress: backupProgress) - - case .backupButNotTrusted(let keyBackupVersion, let keyBackupVersionTrust): - self.renderNotTrustedKeyBackup(keyBackupVersion, keyBackupVersionTrust: keyBackupVersionTrust) - } - - delegate.settingsKeyBackupTableViewSectionDidUpdate(self) + private func numberOfCheckingBackupRows() -> Int { + return 1 } - private func renderLoading() { + private func renderCheckingBackupCell(atRow: Int) -> UITableViewCell { // TODO: loading wheel - self.tableViewCells = [] + return UITableViewCell.init() } - private func renderNoKeyBackup() { + + private func numberOfNoBackupRows() -> Int { + return 1 + } + + private func renderNoBackupCell(atRow: Int) -> UITableViewCell { guard let delegate = self.delegate else { - return + return UITableViewCell.init() } - let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) - infoCell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoNone + let cell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + cell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoNone - self.tableViewCells = [infoCell] - - // Add buttons - self.tableViewCells = [infoCell] + self.buttonCellForCreate(fromCellIndex: self.tableViewCells.count) - } - - private func renderKeyBackup(_ keyBackupVersion:MXKeyBackupVersion, keyBackupVersionTrust:MXKeyBackupVersionTrust) { - - guard let delegate = self.delegate, - let keyBackupVersionVersion = keyBackupVersion.version else { - return - } - - let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) - - let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersionVersion) - let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) - let backupStatus = VectorL10n.settingsKeyBackupInfoValid - let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone - let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); - - let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust - infoCell.mxkTextView.text = strings.joined(separator: "\n") - - // Add buttons - self.tableViewCells = [infoCell] + self.buttonCellsForRestoreAndDelete(keyBackupVersion, fromCellIndex: self.tableViewCells.count) - } - - private func renderRunningKeyBackup(_ keyBackupVersion:MXKeyBackupVersion, keyBackupVersionTrust:MXKeyBackupVersionTrust, backupProgress:Progress) { - - guard let delegate = self.delegate, - let keyBackupVersionVersion = keyBackupVersion.version else { - return - } - - let remaining = backupProgress.totalUnitCount - backupProgress.completedUnitCount - - let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) - - let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersionVersion) - let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) - let backupStatus = VectorL10n.settingsKeyBackupInfoValid - let uploadStatus = VectorL10n.settingsKeyBackupInfoProgress(String(remaining)) - let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); - - let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust - infoCell.mxkTextView.text = strings.joined(separator: "\n") - - // Add buttons - self.tableViewCells = [infoCell] + self.buttonCellsForRestoreAndDelete(keyBackupVersion, fromCellIndex: 1) + return cell } - private func renderNotTrustedKeyBackup(_ keyBackupVersion:MXKeyBackupVersion, keyBackupVersionTrust:MXKeyBackupVersionTrust) { + private func numberOfBackupRows() -> Int { + return 3 + } - guard let delegate = self.delegate, - let keyBackupVersionVersion = keyBackupVersion.version else { - return + private func renderBackupCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust) -> UITableViewCell { + guard let delegate = self.delegate else { + return UITableViewCell.init() } - let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + var cell: UITableViewCell + switch row { + case 0: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) - let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersionVersion) - let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) - let backupStatus = VectorL10n.settingsKeyBackupInfoNotValid - let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let backupStatus = VectorL10n.settingsKeyBackupInfoValid + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); - let strings = [version, algorithm, backupStatus] + backupTrust - infoCell.mxkTextView.text = strings.joined(separator: "\n") + let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + infoCell.mxkTextView.text = strings.joined(separator: "\n") - self.tableViewCells = [infoCell] + cell = infoCell + + case 1: + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + + case 2: + cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) + + default: + cell = UITableViewCell.init() + } + + return cell + } + + + private func numberOfBackupAndRunningRows() -> Int { + return 3 + } + + private func renderBackupAndRunningCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust, backupProgress: Progress) -> UITableViewCell { + guard let delegate = self.delegate else { + return UITableViewCell.init() + } + + var cell: UITableViewCell + switch row { + case 0: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) + + let remaining = backupProgress.totalUnitCount - backupProgress.completedUnitCount + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let backupStatus = VectorL10n.settingsKeyBackupInfoValid + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgress(String(remaining)) + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + + let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + cell = infoCell + + case 1: + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + + case 2: + cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) + + default: + cell = UITableViewCell.init() + } + + return cell + } + + + private func numberOfBackupNotTrustedRows(keyBackupVersionTrust: MXKeyBackupVersionTrust) -> Int { + var numberOfRows = 3 + if self.lastNonVerifiedDevice(keyBackupVersionTrust) != nil { + numberOfRows += 1 + } + return numberOfRows + } + + private func renderBackupNotTrustedCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust) -> UITableViewCell { + guard let delegate = self.delegate else { + return UITableViewCell.init() + } // Display a verify button for the last non verified device only - let deviceId = self.lastNonVerifiedDevice(keyBackupVersionTrust) - self.tableViewCells = self.tableViewCells + self.buttonCellForVerifyingDevice(deviceId, fromCellIndex: self.tableViewCells.count) + let lastNonVerifiedDevice = self.lastNonVerifiedDevice(keyBackupVersionTrust) - // Add buttons - self.tableViewCells = self.tableViewCells + self.buttonCellsForRestoreAndDelete(keyBackupVersion, fromCellIndex: self.tableViewCells.count) + var cell: UITableViewCell + switch row { + case 0: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let backupStatus = VectorL10n.settingsKeyBackupInfoValid + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + + let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + cell = infoCell + + case 1: + if let lastNonVerifiedDevice = lastNonVerifiedDevice { + cell = self.buttonCellForVerifyingDevice(lastNonVerifiedDevice, atRow: row) + } + else { + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + } + + case 2: + if lastNonVerifiedDevice != nil { + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + } + else { + cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) + } + + case 3: + cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) + + default: + cell = UITableViewCell.init() + } + + return cell } @@ -235,77 +331,90 @@ import UIKit return lastNonVerifiedDeviceId } - // MARK: - Cells - private func buttonCellForCreate(fromCellIndex: Int = 0) -> [MXKTableViewCellWithButton] { + // MARK: - Button cells + + private func buttonCellForCreate(atRow row: Int) -> UITableViewCell { guard let delegate = self.delegate else { - return [] + return UITableViewCell.init() } - let verifyCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: self.tableViewCells.count) + let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) let btnTitle = "Start a new backup" - verifyCell.mxkButton.setTitle(btnTitle, for: .normal) - verifyCell.mxkButton.setTitle(btnTitle, for: .highlighted) + cell.mxkButton.setTitle(btnTitle, for: .normal) + cell.mxkButton.setTitle(btnTitle, for: .highlighted) - verifyCell.mxkButton.vc_addAction { + cell.mxkButton.vc_addAction { self.viewModel.process(viewAction: .create) } - return [verifyCell] + return cell } - private func buttonCellForVerifyingDevice(_ deviceId: String?, fromCellIndex: Int = 0) -> [MXKTableViewCellWithButton] { + private func buttonCellForVerifyingDevice(_ deviceId: String, atRow row: Int) -> UITableViewCell { - guard let deviceId = deviceId, let delegate = self.delegate else { - return [] + guard let delegate = self.delegate else { + return UITableViewCell.init() } - let verifyCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: self.tableViewCells.count) + let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) let btnTitle = "Verify..." - verifyCell.mxkButton.setTitle(btnTitle, for: .normal) - verifyCell.mxkButton.setTitle(btnTitle, for: .highlighted) + cell.mxkButton.setTitle(btnTitle, for: .normal) + cell.mxkButton.setTitle(btnTitle, for: .highlighted) - verifyCell.mxkButton.vc_addAction { + cell.mxkButton.vc_addAction { self.viewModel.process(viewAction: .verify(deviceId)) } - return [verifyCell] + return cell } - private func buttonCellsForRestoreAndDelete(_ keyBackupVersion: MXKeyBackupVersion, fromCellIndex: Int = 0) -> [MXKTableViewCellWithButton] { + private func buttonCellForRestore(keyBackupVersion: MXKeyBackupVersion, atRow row: Int) -> UITableViewCell { guard let delegate = self.delegate else { - return [] + return UITableViewCell.init() } - let restoreCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: fromCellIndex) - let restoreTitle = "Restore backup" - restoreCell.mxkButton.setTitle(restoreTitle, for: .normal) - restoreCell.mxkButton.setTitle(restoreTitle, for: .highlighted) - restoreCell.mxkButton.vc_addAction { + let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) + let btnTitle = "Restore backup" + cell.mxkButton.setTitle(btnTitle, for: .normal) + cell.mxkButton.setTitle(btnTitle, for: .highlighted) + cell.mxkButton.vc_addAction { self.viewModel.process(viewAction: .restore(keyBackupVersion)) } + return cell + } - let deleteCell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: fromCellIndex + 1) - let deleteTitle = VectorL10n.settingsKeyBackupButtonDelete - deleteCell.mxkButton.setTitle(deleteTitle, for: .normal) - deleteCell.mxkButton.setTitle(deleteTitle, for: .highlighted) - deleteCell.mxkButton.tintColor = ThemeService.shared().theme.warningColor - deleteCell.mxkButton.vc_addAction { + private func buttonCellForDelete(keyBackupVersion: MXKeyBackupVersion, atRow row: Int) -> UITableViewCell { + guard let delegate = self.delegate else { + return UITableViewCell.init() + } + + let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) + let btnTitle = VectorL10n.settingsKeyBackupButtonDelete + cell.mxkButton.setTitle(btnTitle, for: .normal) + cell.mxkButton.setTitle(btnTitle, for: .highlighted) + cell.mxkButton.tintColor = ThemeService.shared().theme.warningColor + cell.mxkButton.vc_addAction { self.viewModel.process(viewAction: .confirmDelete(keyBackupVersion)) } - return [restoreCell, deleteCell] + return cell } } + // MARK: - KeyBackupSetupRecoveryKeyViewModelViewDelegate extension SettingsKeyBackupTableViewSection: SettingsKeyBackupViewModelViewDelegate { - func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewSate: SettingsKeyBackupViewState) { - self.render(viewState: viewSate) + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewState: SettingsKeyBackupViewState) { + self.viewState = viewState + + // The tableview datasource will call `self.cellForRow()` + self.delegate?.settingsKeyBackupTableViewSectionDidUpdate(self) } + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsKeyBackupNetworkRequestViewState) { switch networkRequestViewSate { case .loading: diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index 2a099fb38..f04ea144c 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -100,7 +100,7 @@ class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { guard let keyBackupVersion = self.keyBackup.keyBackupVersion, let keyBackupVersionTrust = keyBackupVersionTrust else { return } - viewState = .backupButNotTrusted(keyBackupVersion, keyBackupVersionTrust) + viewState = .backupNotTrusted(keyBackupVersion, keyBackupVersionTrust) case MXKeyBackupStateReadyToBackUp: guard let keyBackupVersion = self.keyBackup.keyBackupVersion, let keyBackupVersionTrust = keyBackupVersionTrust else { diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift index 7f6264e03..20c59ba94 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift @@ -17,7 +17,7 @@ import UIKit protocol SettingsKeyBackupViewModelViewDelegate: class { - func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewSate: SettingsKeyBackupViewState) + func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewState: SettingsKeyBackupViewState) func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsKeyBackupNetworkRequestViewState) func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift index 5b3ced337..9751e402e 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewState.swift @@ -29,7 +29,7 @@ enum SettingsKeyBackupViewState { case noBackup case backup(MXKeyBackupVersion, MXKeyBackupVersionTrust) case backupAndRunning(MXKeyBackupVersion, MXKeyBackupVersionTrust, Progress) - case backupButNotTrusted(MXKeyBackupVersion, MXKeyBackupVersionTrust) + case backupNotTrusted(MXKeyBackupVersion, MXKeyBackupVersionTrust) } /// State representing a network request made by the module diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 3fbc9b642..df9e2e907 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1304,7 +1304,7 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> // Check whether this section is visible. if (self.mainSession.crypto) { - count = keyBackupSection.tableViewCells.count; + count = keyBackupSection.numberOfRows; } } else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX) @@ -2235,10 +2235,7 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> } else if (section == SETTINGS_SECTION_KEYBACKUP_INDEX) { - if (row < keyBackupSection.tableViewCells.count) - { - cell = keyBackupSection.tableViewCells[row]; - } + cell = [keyBackupSection cellForRowAtRow:row]; } else if (section == SETTINGS_SECTION_DEACTIVATE_ACCOUNT_INDEX) { @@ -4282,9 +4279,6 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> cell.mxkButton.titleLabel.font = [UIFont systemFontOfSize:17]; [cell.mxkButton setTintColor:ThemeService.shared.theme.tintColor]; - [cell.mxkButton removeTarget:self action:nil forControlEvents:UIControlEventTouchUpInside]; - cell.mxkButton.accessibilityIdentifier = nil; - return cell; } From b2062f22afacea1ce9e0f629f55fb332afe48b7f Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 16:58:41 +0100 Subject: [PATCH 136/244] key backup settings: Make it look like more to https://github.com/vector-im/riot-meta/issues/251#issuecomment-458566684 1/2 --- Riot/Assets/en.lproj/Vector.strings | 16 ++-- Riot/Generated/Strings.swift | 22 +++-- .../SettingsKeyBackupTableViewSection.swift | 82 ++++++++++++++----- 3 files changed, 87 insertions(+), 33 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index f1b8659bf..df7cc8491 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -335,7 +335,7 @@ "settings_flair" = "Show flair where allowed"; "settings_devices" = "DEVICES"; "settings_cryptography" = "CRYPTOGRAPHY"; -"settings_key_backup" = "SECURE MESSAGE"; +"settings_key_backup" = "SECURE MESSAGE RECOVERY"; "settings_deactivate_account" = "DEACTIVATE ACCOUNT"; "settings_sign_out" = "Sign Out"; @@ -421,21 +421,23 @@ "settings_deactivate_my_account" = "Deactivate my account"; -"settings_key_backup_info_none" = "No backup is present"; -"settings_key_backup_info_version" = "Backup version: %@"; +"settings_key_backup_info_none" = "Secure Message Recovery has not been set up."; +"settings_key_backup_info_version" = "Key Backup Version: %@"; "settings_key_backup_info_algorithm" = "Algorithm: %@"; -"settings_key_backup_info_valid" = "This device is using key backup"; -"settings_key_backup_info_not_valid" = "This device is not using key backup"; +"settings_key_backup_info_valid" = "Backup has a valid signature from this device."; +"settings_key_backup_info_not_valid" = "Secure Message Recovery is not active on this device."; "settings_key_backup_info_progress" = "Backing up %@ keys..."; -"settings_key_backup_info_progress_done" = "All keys backed up"; +"settings_key_backup_info_progress_done" = "All keys have been backed up"; // TO DEL "settings_key_backup_info_trust_signature_unknown" = "Backup has a signature from unknown device with ID %@."; "settings_key_backup_info_trust_signature_valid" = "Backup has a valid signature from this device"; "settings_key_backup_info_trust_signature_valid_device_verified" = "Backup has a valid signature from verified device %@"; "settings_key_backup_info_trust_signature_valid_device_unverified" = "Backup has a valid signature from unverified device %@"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "Backup has a invalid signature from verified device %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "Backup has a invalid signature from unverified device %@"; -"settings_key_backup_button_create" = "Start a new backup"; +"settings_key_backup_button_create" = "Set up Secure Message Recovery"; +"settings_key_backup_button_restore" = "Restore backup"; "settings_key_backup_button_delete" = "Delete backup"; +"settings_key_backup_button_verify" = "Verify"; "settings_key_backup_delete_confirmation_prompt_title" = "Delete Backup"; "settings_key_backup_delete_confirmation_prompt_msg" = "Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 7f8c68f57..e812c8f08 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1918,11 +1918,11 @@ internal enum VectorL10n { internal static var settingsIgnoredUsers: String { return VectorL10n.tr("Vector", "settings_ignored_users") } - /// SECURE MESSAGE + /// SECURE MESSAGE RECOVERY internal static var settingsKeyBackup: String { return VectorL10n.tr("Vector", "settings_key_backup") } - /// Start a new backup + /// Set up Secure Message Recovery internal static var settingsKeyBackupButtonCreate: String { return VectorL10n.tr("Vector", "settings_key_backup_button_create") } @@ -1930,6 +1930,14 @@ internal enum VectorL10n { internal static var settingsKeyBackupButtonDelete: String { return VectorL10n.tr("Vector", "settings_key_backup_button_delete") } + /// Restore backup + internal static var settingsKeyBackupButtonRestore: String { + return VectorL10n.tr("Vector", "settings_key_backup_button_restore") + } + /// Verify + internal static var settingsKeyBackupButtonVerify: String { + return VectorL10n.tr("Vector", "settings_key_backup_button_verify") + } /// Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history internal static var settingsKeyBackupDeleteConfirmationPromptMsg: String { return VectorL10n.tr("Vector", "settings_key_backup_delete_confirmation_prompt_msg") @@ -1942,11 +1950,11 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoAlgorithm(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_algorithm", p1) } - /// No backup is present + /// Secure Message Recovery has not been set up. internal static var settingsKeyBackupInfoNone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_none") } - /// This device is not using key backup + /// Secure Message Recovery is not active on this device. internal static var settingsKeyBackupInfoNotValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_not_valid") } @@ -1954,7 +1962,7 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoProgress(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_progress", p1) } - /// All keys backed up + /// All keys have been backed up internal static var settingsKeyBackupInfoProgressDone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_progress_done") } @@ -1982,11 +1990,11 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoTrustSignatureValidDeviceVerified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_verified", p1) } - /// This device is using key backup + /// Backup has a valid signature from this device. internal static var settingsKeyBackupInfoValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_valid") } - /// Backup version: %@ + /// Key Backup Version: %@ internal static func settingsKeyBackupInfoVersion(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_version", p1) } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index d1d3baa4f..7e2f45021 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -128,23 +128,35 @@ import UIKit private func numberOfNoBackupRows() -> Int { - return 1 + return 2 } - private func renderNoBackupCell(atRow: Int) -> UITableViewCell { + private func renderNoBackupCell(atRow row: Int) -> UITableViewCell { guard let delegate = self.delegate else { return UITableViewCell.init() } - let cell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) - cell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoNone + var cell: UITableViewCell + switch row { + case 0: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + infoCell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoNone + + cell = infoCell + + case 1: + cell = self.buttonCellForCreate(atRow: row) + + default: + cell = UITableViewCell.init() + } return cell } private func numberOfBackupRows() -> Int { - return 3 + return 5 } private func renderBackupCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust) -> UITableViewCell { @@ -157,21 +169,37 @@ import UIKit case 0: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) - let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") - let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) let backupStatus = VectorL10n.settingsKeyBackupInfoValid let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone - let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); - let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + let strings = [backupStatus, uploadStatus] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell case 1: - cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + + let strings = [version, algorithm] + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + cell = infoCell case 2: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + infoCell.mxkTextView.text = backupTrust.joined(separator: "\n") + + cell = infoCell + + case 3: + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + + case 4: cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) default: @@ -183,7 +211,7 @@ import UIKit private func numberOfBackupAndRunningRows() -> Int { - return 3 + return 5 } private func renderBackupAndRunningCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust, backupProgress: Progress) -> UITableViewCell { @@ -198,21 +226,37 @@ import UIKit let remaining = backupProgress.totalUnitCount - backupProgress.completedUnitCount - let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") - let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) let backupStatus = VectorL10n.settingsKeyBackupInfoValid let uploadStatus = VectorL10n.settingsKeyBackupInfoProgress(String(remaining)) - let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); - let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + let strings = [backupStatus, uploadStatus] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell case 1: - cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + + let strings = [version, algorithm] + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + cell = infoCell case 2: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + infoCell.mxkTextView.text = backupTrust.joined(separator: "\n") + + cell = infoCell + + case 3: + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + + case 4: cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) default: @@ -342,7 +386,7 @@ import UIKit let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) - let btnTitle = "Start a new backup" + let btnTitle = VectorL10n.settingsKeyBackupButtonCreate cell.mxkButton.setTitle(btnTitle, for: .normal) cell.mxkButton.setTitle(btnTitle, for: .highlighted) @@ -361,7 +405,7 @@ import UIKit let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) - let btnTitle = "Verify..." + let btnTitle = VectorL10n.settingsKeyBackupButtonVerify cell.mxkButton.setTitle(btnTitle, for: .normal) cell.mxkButton.setTitle(btnTitle, for: .highlighted) @@ -378,7 +422,7 @@ import UIKit } let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) - let btnTitle = "Restore backup" + let btnTitle = VectorL10n.settingsKeyBackupButtonRestore cell.mxkButton.setTitle(btnTitle, for: .normal) cell.mxkButton.setTitle(btnTitle, for: .highlighted) cell.mxkButton.vc_addAction { From 6de109b332194de1589ee756b453d3939b88324a Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 18:19:20 +0100 Subject: [PATCH 137/244] key backup settings: Make it look like more to https://github.com/vector-im/riot-meta/issues/251#issuecomment-458566684 2/2 Manage not trusted backup --- Riot/Assets/en.lproj/Vector.strings | 16 ++-- Riot/Generated/Strings.swift | 18 +++- .../SettingsKeyBackupTableViewSection.swift | 93 ++++++++++++------- 3 files changed, 85 insertions(+), 42 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index df7cc8491..2bc239527 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -427,13 +427,17 @@ "settings_key_backup_info_valid" = "Backup has a valid signature from this device."; "settings_key_backup_info_not_valid" = "Secure Message Recovery is not active on this device."; "settings_key_backup_info_progress" = "Backing up %@ keys..."; -"settings_key_backup_info_progress_done" = "All keys have been backed up"; // TO DEL -"settings_key_backup_info_trust_signature_unknown" = "Backup has a signature from unknown device with ID %@."; +"settings_key_backup_info_progress_done" = "All keys have been backed up"; +"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "To use Secure Message Recovery on this device, verify %@ now."; +"settings_key_backup_info_not_trusted_fix_action" = "To use Secure Message Recovery on this device, provide your passphrase or recovery key now."; + +"settings_key_backup_info_trust_signature_unknown" = "Backup has a signature from device with ID: %@"; "settings_key_backup_info_trust_signature_valid" = "Backup has a valid signature from this device"; -"settings_key_backup_info_trust_signature_valid_device_verified" = "Backup has a valid signature from verified device %@"; -"settings_key_backup_info_trust_signature_valid_device_unverified" = "Backup has a valid signature from unverified device %@"; -"settings_key_backup_info_trust_signature_invalid_device_verified" = "Backup has a invalid signature from verified device %@"; -"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Backup has a invalid signature from unverified device %@"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Backup has a valid signature from %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Backup has a signature from %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Backup has an invalid signature from %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Backup has an invalid signature from %@"; + "settings_key_backup_button_create" = "Set up Secure Message Recovery"; "settings_key_backup_button_restore" = "Restore backup"; "settings_key_backup_button_delete" = "Delete backup"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index e812c8f08..d2d49c760 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1954,6 +1954,14 @@ internal enum VectorL10n { internal static var settingsKeyBackupInfoNone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_none") } + /// To use Secure Message Recovery on this device, provide your passphrase or recovery key now. + internal static var settingsKeyBackupInfoNotTrustedFixAction: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_not_trusted_fix_action") + } + /// To use Secure Message Recovery on this device, verify %@ now. + internal static func settingsKeyBackupInfoNotTrustedFromVerifiableDeviceFixAction(_ p1: String) -> String { + return VectorL10n.tr("Vector", "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action", p1) + } /// Secure Message Recovery is not active on this device. internal static var settingsKeyBackupInfoNotValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_not_valid") @@ -1966,15 +1974,15 @@ internal enum VectorL10n { internal static var settingsKeyBackupInfoProgressDone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_progress_done") } - /// Backup has a invalid signature from unverified device %@ + /// Backup has an invalid signature from %@ internal static func settingsKeyBackupInfoTrustSignatureInvalidDeviceUnverified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_invalid_device_unverified", p1) } - /// Backup has a invalid signature from verified device %@ + /// Backup has an invalid signature from %@ internal static func settingsKeyBackupInfoTrustSignatureInvalidDeviceVerified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_invalid_device_verified", p1) } - /// Backup has a signature from unknown device with ID %@. + /// Backup has a signature from device with ID: %@ internal static func settingsKeyBackupInfoTrustSignatureUnknown(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_unknown", p1) } @@ -1982,11 +1990,11 @@ internal enum VectorL10n { internal static var settingsKeyBackupInfoTrustSignatureValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid") } - /// Backup has a valid signature from unverified device %@ + /// Backup has a signature from %@ internal static func settingsKeyBackupInfoTrustSignatureValidDeviceUnverified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_unverified", p1) } - /// Backup has a valid signature from verified device %@ + /// Backup has a valid signature from %@ internal static func settingsKeyBackupInfoTrustSignatureValidDeviceVerified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_verified", p1) } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index 7e2f45021..01319c60b 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -69,8 +69,8 @@ import UIKit numberOfRows = self.numberOfBackupRows() case .backupAndRunning(_, _, _): numberOfRows = self.numberOfBackupAndRunningRows() - case .backupNotTrusted(_, let keyBackupVersionTrust): - numberOfRows = self.numberOfBackupNotTrustedRows(keyBackupVersionTrust: keyBackupVersionTrust) + case .backupNotTrusted(_, _): + numberOfRows = self.numberOfBackupNotTrustedRows() } return numberOfRows @@ -267,12 +267,8 @@ import UIKit } - private func numberOfBackupNotTrustedRows(keyBackupVersionTrust: MXKeyBackupVersionTrust) -> Int { - var numberOfRows = 3 - if self.lastNonVerifiedDevice(keyBackupVersionTrust) != nil { - numberOfRows += 1 - } - return numberOfRows + private func numberOfBackupNotTrustedRows() -> Int { + return 6 } private func renderBackupNotTrustedCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust) -> UITableViewCell { @@ -280,42 +276,66 @@ import UIKit return UITableViewCell.init() } - // Display a verify button for the last non verified device only + // Is the device that created the device verifiable? + // ie, is it known and already stored in crytpo store? let lastNonVerifiedDevice = self.lastNonVerifiedDevice(keyBackupVersionTrust) + let lastUnVerifiableDevice = self.lastUnVerifiableDevice(keyBackupVersionTrust) var cell: UITableViewCell switch row { case 0: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) - let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") - let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) - let backupStatus = VectorL10n.settingsKeyBackupInfoValid - let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone - let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + let backupStatus = VectorL10n.settingsKeyBackupInfoNotValid - let strings = [version, algorithm, backupStatus, uploadStatus] + backupTrust + var fixAction: [String] = [] + if let lastNonVerifiedDevice = lastNonVerifiedDevice { + let deviceName = lastNonVerifiedDevice.displayName ?? lastNonVerifiedDevice.deviceId ?? "" + fixAction = [VectorL10n.settingsKeyBackupInfoNotTrustedFromVerifiableDeviceFixAction(deviceName)] + } + else if lastUnVerifiableDevice != nil { + fixAction = [VectorL10n.settingsKeyBackupInfoNotTrustedFixAction] + } + + let strings = [backupStatus] + fixAction infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell case 1: if let lastNonVerifiedDevice = lastNonVerifiedDevice { - cell = self.buttonCellForVerifyingDevice(lastNonVerifiedDevice, atRow: row) + cell = self.buttonCellForVerifyingDevice(lastNonVerifiedDevice.deviceId, atRow: row) + } + else if lastUnVerifiableDevice != nil { + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row, title: VectorL10n.settingsKeyBackupButtonVerify) } else { - cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + cell = UITableViewCell.init() } case 2: - if lastNonVerifiedDevice != nil { - cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) - } - else { - cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) - } + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") + let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + + let strings = [version, algorithm] + infoCell.mxkTextView.text = strings.joined(separator: "\n") + + cell = infoCell case 3: + let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + + let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); + infoCell.mxkTextView.text = backupTrust.joined(separator: "\n") + + cell = infoCell + + case 4: + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + + case 5: cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) default: @@ -357,9 +377,9 @@ import UIKit } } - private func lastNonVerifiedDevice(_ keyBackupVersionTrust:MXKeyBackupVersionTrust) -> String? + private func lastNonVerifiedDevice(_ keyBackupVersionTrust:MXKeyBackupVersionTrust) -> MXDeviceInfo? { - var lastNonVerifiedDeviceId: String? + var lastNonVerifiedDevice: MXDeviceInfo? for signature in keyBackupVersionTrust.signatures.reversed() { guard let device = signature.device else { @@ -368,13 +388,25 @@ import UIKit if device.verified != MXDeviceVerified { - lastNonVerifiedDeviceId = device.deviceId + lastNonVerifiedDevice = device break } } - return lastNonVerifiedDeviceId + return lastNonVerifiedDevice } + private func lastUnVerifiableDevice(_ keyBackupVersionTrust:MXKeyBackupVersionTrust) -> String? + { + var lastUnVerifiableDevice: String? + for signature in keyBackupVersionTrust.signatures.reversed() { + + if signature.device == nil { + lastUnVerifiableDevice = signature.deviceId + break + } + } + return lastUnVerifiableDevice + } // MARK: - Button cells @@ -416,15 +448,14 @@ import UIKit return cell } - private func buttonCellForRestore(keyBackupVersion: MXKeyBackupVersion, atRow row: Int) -> UITableViewCell { + private func buttonCellForRestore(keyBackupVersion: MXKeyBackupVersion, atRow row: Int, title: String = VectorL10n.settingsKeyBackupButtonRestore) -> UITableViewCell { guard let delegate = self.delegate else { return UITableViewCell.init() } let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) - let btnTitle = VectorL10n.settingsKeyBackupButtonRestore - cell.mxkButton.setTitle(btnTitle, for: .normal) - cell.mxkButton.setTitle(btnTitle, for: .highlighted) + cell.mxkButton.setTitle(title, for: .normal) + cell.mxkButton.setTitle(title, for: .highlighted) cell.mxkButton.vc_addAction { self.viewModel.process(viewAction: .restore(keyBackupVersion)) } From 42a91d7aa8b815fea9428aa2e007f2e564a847a0 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 18:41:00 +0100 Subject: [PATCH 138/244] key backup settings: Manage backup created from the device --- Riot/Assets/en.lproj/Vector.strings | 2 +- Riot/Generated/Strings.swift | 2 +- .../KeyBackup/SettingsKeyBackupTableViewSection.swift | 7 +++++-- Riot/Modules/Settings/SettingsViewController.m | 10 ++++++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 2bc239527..c069c110b 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -424,7 +424,7 @@ "settings_key_backup_info_none" = "Secure Message Recovery has not been set up."; "settings_key_backup_info_version" = "Key Backup Version: %@"; "settings_key_backup_info_algorithm" = "Algorithm: %@"; -"settings_key_backup_info_valid" = "Backup has a valid signature from this device."; +"settings_key_backup_info_valid" = "Secure Message Recovery has been correctly set up for this device."; "settings_key_backup_info_not_valid" = "Secure Message Recovery is not active on this device."; "settings_key_backup_info_progress" = "Backing up %@ keys..."; "settings_key_backup_info_progress_done" = "All keys have been backed up"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index d2d49c760..e6097da24 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1998,7 +1998,7 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoTrustSignatureValidDeviceVerified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_verified", p1) } - /// Backup has a valid signature from this device. + /// Secure Message Recovery has been correctly set up for this device. internal static var settingsKeyBackupInfoValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_valid") } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index 01319c60b..b0068586a 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -47,10 +47,13 @@ import UIKit // Need to know the state to make `cellForRow` deliver cells accordingly private var viewState: SettingsKeyBackupViewState = .checkingBackup + private var userDevice: MXDeviceInfo + // MARK: - Public - @objc init(withKeyBackup keyBackup: MXKeyBackup) { + @objc init(withKeyBackup keyBackup: MXKeyBackup, userDevice: MXDeviceInfo) { self.viewModel = SettingsKeyBackupViewModel(keyBackup: keyBackup) + self.userDevice = userDevice super.init() self.viewModel.viewDelegate = self @@ -357,7 +360,7 @@ import UIKit let displayName = device.displayName ?? device.deviceId ?? "" - if device.fingerprint == "" { // TODO + if device.fingerprint == self.userDevice.fingerprint { return VectorL10n.settingsKeyBackupInfoTrustSignatureValid } else if signature.valid && (device.verified == MXDeviceVerified) { diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index df9e2e907..13c295a0e 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -328,8 +328,14 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> if (self.mainSession.crypto.backup) { - keyBackupSection = [[SettingsKeyBackupTableViewSection alloc] initWithKeyBackup:self.mainSession.crypto.backup]; - keyBackupSection.delegate = self; + MXDeviceInfo *deviceInfo = [self.mainSession.crypto.deviceList storedDevice:self.mainSession.matrixRestClient.credentials.userId + deviceId:self.mainSession.matrixRestClient.credentials.deviceId]; + + if (deviceInfo) + { + keyBackupSection = [[SettingsKeyBackupTableViewSection alloc] initWithKeyBackup:self.mainSession.crypto.backup userDevice:deviceInfo]; + keyBackupSection.delegate = self; + } } groupsDataSource = [[GroupsDataSource alloc] initWithMatrixSession:self.mainSession]; From b53c6f77caafb08a8311c3957d1f3920e53360bb Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 18:48:35 +0100 Subject: [PATCH 139/244] key backup settings: Manage checking state --- Riot/Assets/en.lproj/Vector.strings | 1 + Riot/Generated/Strings.swift | 4 ++++ .../SettingsKeyBackupTableViewSection.swift | 12 +++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index c069c110b..6b4e7f22b 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -421,6 +421,7 @@ "settings_deactivate_my_account" = "Deactivate my account"; +"settings_key_backup_info_checking" = "Checking..."; "settings_key_backup_info_none" = "Secure Message Recovery has not been set up."; "settings_key_backup_info_version" = "Key Backup Version: %@"; "settings_key_backup_info_algorithm" = "Algorithm: %@"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index e6097da24..9878f73fa 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1950,6 +1950,10 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoAlgorithm(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_algorithm", p1) } + /// Checking... + internal static var settingsKeyBackupInfoChecking: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_checking") + } /// Secure Message Recovery has not been set up. internal static var settingsKeyBackupInfoNone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_none") diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index b0068586a..e6b04bcfc 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -124,9 +124,15 @@ import UIKit return 1 } - private func renderCheckingBackupCell(atRow: Int) -> UITableViewCell { - // TODO: loading wheel - return UITableViewCell.init() + private func renderCheckingBackupCell(atRow row: Int) -> UITableViewCell { + guard let delegate = self.delegate else { + return UITableViewCell.init() + } + + let cell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + cell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoChecking + + return cell } From 500391c380c62d68fc1da5bc6b09001c1c52a559 Mon Sep 17 00:00:00 2001 From: Nad Chishtie Date: Thu, 31 Jan 2019 17:59:26 +0000 Subject: [PATCH 140/244] Updated icon assets. --- .../riot_icon_callkit.png | Bin 2145 -> 1760 bytes .../riot_icon_callkit@2x.png | Bin 5119 -> 3539 bytes .../riot_icon_callkit@3x.png | Bin 5933 -> 5427 bytes .../Contacts/riot_icon.imageset/riot_icon.png | Bin 795 -> 920 bytes .../riot_icon.imageset/riot_icon@2x.png | Bin 1850 -> 1884 bytes .../riot_icon.imageset/riot_icon@3x.png | Bin 2790 -> 2802 bytes .../LaunchScreenRiot.png | Bin 13818 -> 25311 bytes .../animatedLogo-0.png | Bin 13818 -> 25311 bytes .../animatedLogo-1.png | Bin 16646 -> 25617 bytes .../animatedLogo-2.png | Bin 15915 -> 25571 bytes .../animatedLogo-3.png | Bin 9656 -> 23577 bytes .../animatedLogo-4.png | Bin 8221 -> 23595 bytes .../AppIcon.appiconset/Icon-1024.png | Bin 41486 -> 143985 bytes .../AppIcon.appiconset/Icon-20.png | Bin 1229 -> 721 bytes .../AppIcon.appiconset/Icon-20@2x-1.png | Bin 1281 -> 1634 bytes .../AppIcon.appiconset/Icon-20@2x.png | Bin 1281 -> 1634 bytes .../AppIcon.appiconset/Icon-20@3x.png | Bin 3811 -> 2414 bytes .../AppIcon.appiconset/Icon-29.png | Bin 909 -> 1105 bytes .../AppIcon.appiconset/Icon-29@2x-1.png | Bin 2205 -> 2347 bytes .../AppIcon.appiconset/Icon-29@2x.png | Bin 2205 -> 2347 bytes .../AppIcon.appiconset/Icon-29@3x.png | Bin 3673 -> 3384 bytes .../AppIcon.appiconset/Icon-40.png | Bin 1281 -> 1634 bytes .../AppIcon.appiconset/Icon-40@2x-1.png | Bin 3069 -> 3165 bytes .../AppIcon.appiconset/Icon-40@2x.png | Bin 3069 -> 3165 bytes .../AppIcon.appiconset/Icon-40@3x.png | Bin 4607 -> 4821 bytes .../AppIcon.appiconset/Icon-60@2x.png | Bin 4607 -> 4821 bytes .../AppIcon.appiconset/Icon-60@3x.png | Bin 7067 -> 8046 bytes .../AppIcon.appiconset/Icon-76.png | Bin 2800 -> 3045 bytes .../AppIcon.appiconset/Icon-76@2x.png | Bin 5921 -> 6540 bytes .../AppIcon.appiconset/Icon-83.5@2x.png | Bin 6609 -> 7300 bytes 30 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-1024.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20@2x-1.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20@2x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20@3x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29@2x-1.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29@2x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29@3x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-40.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-40@2x-1.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-40@2x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-40@3x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-60@2x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-60@3x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-76.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-76@2x.png mode change 100644 => 100755 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-83.5@2x.png diff --git a/Riot/Assets/Images.xcassets/Call/riot_icon_callkit.imageset/riot_icon_callkit.png b/Riot/Assets/Images.xcassets/Call/riot_icon_callkit.imageset/riot_icon_callkit.png index 250f0bc6477f968c31911604dafdf260c0f36f58..3698dba7ebcc577f59404423b4ab92a0beaf53f0 100644 GIT binary patch delta 1744 zcmV;>1~2*H5a11vB!2{FK}|sb0I`n?{9y$E00x&yL_t(o3GG;GY!p=#K6hsJ)pnQd zgHj#^OWLxjqL`eh_Vqypcs3a!-@P`@`g=%7q5aS@Ob>s zPk>D3_pNH`cMv*JD+65uKpeSr2vH^!Li{{Y{MN;ui)WrCQZ5}ceola^nr^J+2zQi# z;syc&;Rq=#;OUG)3$+c%-7Ub<>H^rbrWl&9h2X^b;glYm;K_0h zD_QRSv}e7Jk+H}Mu-GZc6*KJ_D)*K=y0KxY8(3^*8%}iZj!iRx;!nj(k`g888*fd) zG#gKMriccU?As&vd2bEM z$MU9jgePPXDBRW3wDX5@u~w1Iv2TEcsDBi$`@Gx7*0{t@fC!?fl#7yFx^Z=(E+kmh znN_T>-H{lT2+s{NeWNiYfUIJ?zM&M8vg~EI_WI3n7#L1~>eZ9yM&Ow`CzO}oyX|*| z;;`yTR|*Hy35G>s&K%F>6ft9>Kkp3YWR|RqP0Qz@r6UA)u!O1Lm~J2>!l~8~=zqN( zP2TqUMJ`O}>05TopP+=}e?7LDq;pS((J2FD`(5f8hp~vU4c5i{axn-CEAn8zCh1F9 z4}Bfsa9mVA$iSpqn!A`j*ac%h$6_v-oYh^}iS_iQD}+kdKAB7a6FLK{R-UUp<8fK0 zXD>8*u4`p8=cWKL;0sVV?GIdxMt>w|?+k-Y+exDYOW3)Fe^i9F&Jfhsx}d8+s^C60 zo_B7`rDqCIAxaFD(@6{$rEW{IlCXrU9mjqTz#sz1HLhSNV2?@hGKB@OR=4ggAIYWj zNMdktWxAEhWf1Ez#r)LJy06loOP28;3BamyN3wC4j6swUWQo2vN!h6b^nZ0m!aubI zgB-^NvF7FuMntA4%8OX5cTEQ5lunRcj%&RU?ytf4w!XpmRz>FC#~{& z=zhwKuhLB~i7JrmiKRB-+wJ-OzT8Rg{u?el#yz?8@EC1Gk-x)UaH(%^xoMu7(g_-Y zD4*+j2b0rPBVHyAkGh7^@P8YbbnW_)1H`hGun63%Xke^q{vgcvzu8zTx z1n?Z!p{}*h3;R4@JR8xQ!TT$28xD?A)A$%Q?iGPGFpE5I$$J^gT zUY{AC(a{NCW#gLyJhP)TB2#6{@#c}loq+BjlYh)lUmA-IhsAj7o|+~z184SB1g%&# zuw3^V$`Cksp>g41L*9L&t{E^Atl!_g90>in*lnTsM!+5nOCtW<oI97l5$y$6Zx= z^ah(?Dk+j__(P1h4N2J9IMHYq5bjW0WA!(=UdQDG$n3p*XdrJW6j`Kj(lXrmHc-B| m{q3qw11yh8k5AxXPvBoh9#=gm%7%FW0000-Mjamdw%^R-~c5dBw@yx`kVRvv*-No{p|Pr&hK~b0lv1cu)T6(ZKt2X z?ld9q=@OK#%?AJ!u3M8zsg5LdQm>GGI7BdHD^b!2WaeDG@t0}aw&C^Z)4LWhclt7T z`ny=P-k8ozdVhuD(gy-q9|yGY$zc7RaRAgxxW>Sm3AB@dml<#*keSn5aBw4nW9GCQ zkheClC_8|%ZAFNF8Vew7zeaKCyZ)D`E)H{39efAOw*#3uu9M;V#FLR0KM}4^Y%rU< z>s;-{85^T>?Ucg!`v7VS4sIMD95V;S)tkFU!9}wILw_k^A8&PnBy=kn2Bz_wbd->n zVz%|JlWWHWiC6s@vrjIo+EO5-2uPrm8O@8OCy}&B9R7!%?3jW8Kyk`%b6gVGzEEw* zVSF=U$I`BQ*oytg!PRmBIfyfUqWI9J6F%Lwmot{6Fg_1X&)-W%WkYz>jxTWw0S#$W ze$HTojDJ3fw!0`nb?0CAWQVUv=W2HqeAy#|zpratJ$BWI9AID%>V#AVJX%;;o*x`N z8+q@q>o_3usTW(_0@uuT(Q#o5W|2UP+lbn65w*>^g6uQfPghmB|2B1PtaV`(h>(IGw`$Z zk%q8Ocf~ZO&NHQWi6D17q-fORC^}T$u}xA~vuPDoho7kFOhiR-X=QW978Q?vybfTW+BW8NxXct*mak%9V|yniuc&Ld zynf(iUrwDbvcu(ajE_f(QW1{rA66_Q1H#0}@EwE=w#a@Zv|i))7djkPXW+<1s0pYH}O>lHmHiVaMN1 zbM;H$V7@2Qe)@V*<)-CeU>aBYn18m2wFcJ#Ko~7)`{j;i40J_sxiNepG`4wn-B4;0 z00CU%rYqGut9iPzP-n_SkETqpNrnSen{`v#z52S6|8v1;SP0<5j(3t_-0H|#26 zV1s%jBn?ovT-hG|%V$I7X9lQAfISc^rokV7aQqXM z^GN=vncF1MTax7DVD)S1AW8~k=Irh=z_4uy0?4aiB=01 zfp~0teb0U@X=+LJs}+{CPk#+b=(FD@dp!XQJ9k*P^#saQA|hOfHLg4nsyn&A{^-T% z1Nu8;$+iO{HcoFi`d-|&G7~huJ(u~>n29Nz(#Ab_X8>zCV*`GbHnCh|s>7`~cP;;5 z>uL}N4e+GwjR|u&13P-tQok8QZq`yLz#0HY+5uSGsoSlh%5tG{b%sM#_r@%v#@80dVP3Nh|kvAZaG*9!V;x3zRAhH;h@+f8BT zITihd1l?6CNRDVUBQ*s2Loj3Z*@D}&tlX@nD61&`oWQ2u^r>*;6%H_C#qOf$;-4++ zn1Tg|$`Q=SL1E>_VIcMb=WG(dAW41*V1df`enAp}%uO7$q9DpDijkL9{9S-82QcB< zJO2S-Noj@ua9)-lr4{~;myg2A4Q+jv-Z4HmtEi1JKfbpAd;2eGv#tQ74Nd9*0000< KMNUMnLSTa6dI9_Z diff --git a/Riot/Assets/Images.xcassets/Call/riot_icon_callkit.imageset/riot_icon_callkit@2x.png b/Riot/Assets/Images.xcassets/Call/riot_icon_callkit.imageset/riot_icon_callkit@2x.png index 33ba6e019c2f7bd58c4a7c5bc1ce4b676b721296..4db45b362129ba8d7611d95512940dc32758351c 100644 GIT binary patch delta 3537 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 LNkvXXu0mjfV%+8P literal 5119 zcmVI?dJdh6O2hj zK~#9!?Ob_y71i1Qy=P|by}36Dfq+Tasj|o}vLxEpVyl(C6hYR2B2=x`wtj>ihXe>q zv3>E=ZT~;>hq2*Zmd;$Pq{<;_1 z$vn@`5MgUVot)=I7uN+oZx8~qW(_4aq~rp&P`LP~lh0JWHskCBtcZT~hfCn>sY{T& zZVqNXyrdnxNPypZgv%^|0e}Gsh*l1WxF%3;bOIrw;#$qYj2sX?B%-YVA2R*Qm&re$ z5CDML`!*nXz~mnWfioUif)&rs!K^8Z7t0d!2^eg@Y^@yZH8s(o{iX%DLkNUbL-H!v zr;CET08Rq+U-`GA z&dlQ%#Z692{=c=D{qt!JPXlM)zqGk5@)xk=n%E)KNIRmQxEX9!tGr(_uQ=~7{ii}g zbtpD!?~KZv&~0F#>P^Y%uOIiCfes94!LgF&Wy!#j&9_fw{eu+f1IIKV6CRcL76;@# zHLk#5C_`I7=@(utr&6`Cf(XnwrU}I#9ny5jv>t=D{l#Y@)!eR*qGXQc3 zTdpE##O%If58S{e!O$gH*#$$GDCfv+Sg-&=g)21k?Zl7Jh2X|xhd=}G%HrQH}7 zHS8DrUoV)`Z|vlxv`rry(ptmdfvjN*fFZtUNBwKy%+ZOxI3N!})~*3sm<`QGb%@7L z97nI{bcmn{6%Ju5d7%5<*}(ztCSdkwSbJpG`doKmoMd#7kQ}1e$z(I;$^H}10>I+5 z*Vg!?QRzjVNs5hsbl(1#v8dmqdNkp&iM`;hJ%Qv@;P_oz2$y=*mR7`l-hecYgljHa zhp-!ljPCUFTmaZ~^h4X{WjXCF#&MG^R)|PI#4tEtA25;ieXmTjSgrvenQ+IV0r4M$ z8KByQ!lK3ex-)HS7zZCIV&mz#@K~Q7E6|pd3IHc0swu$#I>4GjsOq>*jX_@tUnE$yY`uO=DS6i?6sQI z%87)kM1UM$X(U?C?LR(m&EdCO=6VWpB{KlLloT6ZYfn;RCn5&7@F2_W!3lR0h?+eI zX-c$-Yn%00w^5nbShO_&tU9=DeZIdq&SI;J$%udI;FfXWHv3N=>^3-Od3tJ$N+Qo> zi7;Ep831(FQ<%p94o+ znEqS_5TUvL{y(?g`@qu&-?SC_OEUp<0b_nrT>PT?A#m@;77&yvv&v%v|IEMkid2F& ztu?5bT5ZBB;yI{_f=FBV8M~tNp59|f0RTMn-yJz;Jw>g89$QRZIAG#>09cu^Ij1;K z-U`66mLZY79_}?Huxx+Iwld2%i~u7kHr`e*P9$i94AI4fsKM=EdW`A^ga*SlIvU|o z;Rx4U)jGm#AqY`z01-@S;he9yWv-_v>u(3Qz6b!n?>V$}Gh0}$WM;{7-ReWz)&qcD zs3SC?fPgMvxzDv>L(rR89D4n`8WAnZz`uuk7 zpZbh!y=ecYT)$XF6K=hi03cKiIbUvin=@!C zfH&$#11r$!aA@1<!ApdCz-j-@T~c?;ESdJU{|!^3JDO<?DJpU*s*!r0}J+U+$(|DsE~+E0JaCZ-JQEI?NtOUlUE27pL=SOl2)g1_wR*s_Vu1tL&U zpsW}GB5a|GLJ9zcGdL{a<8^2l1b)L^(4|TJD>+$&sSdPpMeb|uYL@=ZBgWY@-7d7f zf&>C=MkS}G91jxX{8$x=VX=fy1|k3;u0{9TiHJ6f45&B zesbT-hZ*P-t~z%DaP)88v1tC@jgZV(cle#>r}p^uL&ZjUHhp7=V6a&cV@B4i6Z!5S zljP+>pYKw}>cl}IitVsM0t~i!EPp5f*n~;|!(_`|HG2a9CY${#+9JN&vx|rZNnmh9 z{F=-f5mpr|GX6nj0Z*}Hh9H7nsA`a;U` z^oyG@Zlf_o}<;cF^D=D_Cwrr2-XNzUVW4%Z0-TK*{h>XI|!-5Zp{_@QnVh30B zw2J?!lGJZCQqqM6Ngxr-D&x)7%pDg3I#L_HSreuYPn%P1}ymKmD zIZ=|^lYpBDgpz=J697DSc<1`u^79Zx_+^J%3WA=w$*yz0Vki}+{e0%moAdp}JxytW zi1QjGfdV3MrP()g@D~NMf?#GCFaaXSf&i=&Zt#(E$RZOkBoL}VY40Q|Fh$onThbi_glW#NWw}jHbAS=1xikPMvwSXQ)&O`2C~1%c z+7zYyO4$oRLS<$w-v9b|5Ic!ME;wS!Hs@^h9WMa_5?@aX2|&38>qr?u*qZa!Nn_!f z7Y<*L?rxGLnmfYZncDrHV}HwhvrCb$ycdDM;0G#YdCUL+LQ6-}ApqbteM-e5RSAO{ zCV@`H?xrhy)W|(KS&n)A$7KP)(mBt?c-@6*?(7R7h48IBW0jwQQorU;&FP~SMI!R9 zHeWv6bLcPtC<%DtES5HfM8GbzJpl06gPV^R`pVcQR2tv)&fK7E``w2006<<+?4*JQ zNnoFtP9^W>{r8gY^VeQdqTKYY&M5l4WL4%?!}40P;JFjM0_VL!@~Sh&Iuux+6vG)A z1pruk`0e$l-RJISW)8Q7eDU}#zd5$<$U9wfJ%#Owh*Y6m)JV&pSTT&eQ}5ZBD^2{D zA4t7y#3z|?&Rg7;0gy^C-z$VHs6KgB@mb2J?KZr(<3zS6UlItaqU8O#A-Q0Om> zGo)z~L;+1GdxB18#~*Utg&+_NajEBSXmMawk1Uv(Y(mjAQlSY2HbsS9QK6Jd$WMxc z9=9f1;82mZF|#B2(OD%0QI4j=6Vo;k0QfCqJ%ibyXkW~@b@VX+$oCXatr#QUUN&G- z(W>{KZkQVQjW8wT?Nj?(^@+Uk;J|jhFJWr=?C17)2(h(UBjfV{7#|g(&FC)APVY46 z05e1Er#zo!utqA)?mM9Zg_hFkOE>R06g}~KQ?d;WI!PiDoDgJ_{PKe zCz~;|0su#Srz6YGl-@{6EteP-g0;ICo~`-8wUR?y^8A(&tq@VD=9mrun3)c*>EBin zP-h8~v-G{MpuvuTRqeOLaJSAV{5+*{O1JZLI+muV;LSsyz#yw`#0Ww`#+gS}?cVZ8 zp09+1iB+-oi9Vy&0>IM;w;V6Ty0&`#m5+k~vJB?+zIEM@U`y7S zJfkdtoHtIuKBW~=fT!yNCag_L+e8-2=t6&42SG#(N?JT%(xJKUy@AEQy02jq7_K=_ zXrz^XXR_G_DiCLHwqQEzXs`tzbA$hNAtQ0-V`~8*RC7j^2Hce!(?2C}^4z_zU~%ky zXwVw?{C{`ip`JrJU+uny53kH9KkvJRL>;{}U=y&?OZqHHSlvMz9px`I+_@%OAi!%# z`K#pHrg-bBkJpvJhk6bH0Bp(rgpQZwxGa|4nAxhTF2W|z=I zZ=JolLV|GN=y|9+4XA@!l#yliP3#~4nV!B0df)MNm@v7{7}@dm%3L2;rnFQcpbF*U zAqAX6qCr}nzV`!C2-cx8_}AnNPK=w9J@>`cbxPj%8c0{c(ddwfaWa@nx`_5ssW!3Bwl-T()(= z2l{9odaC}zA@G%>|Hko>oJ(^09?R#lr0i$0Y<-Evg#yaJrZ9J&uW@qWJ0nEqU2})) z&Gb~g&cc}QWiCAN<~uJpy{o#u`4%&+Wu_O|q8F9erZ3P>oQG@sLgHoMFc@zo4%U^& z2I)U+6TXB?mdQzRQ$DJCZbru$VbsNS96(GRi@T#t!EaY>*HdQ>)3I#3-taZB8p(!l zZE{?Zy`qeO3D+mJhLl;u^bWNpui+4Q8B}P;2h3P`J?fXhuE&QyX-m5A=^rP7%eL!y z>@FQdcoM+r>mZ_wUC^}oZ~PH6M=x!d1a8Uxq*mouy{lvScHIr&y1Xa|#_HLlmNZ$G zI;&w4SUHWW4gTj&9m}`t2N?A5^=P9N2(125ns6ol@^2k~8oCHVmFoZ;xDFz2n=w>( z{%8pVfWPjThhO z-7?jH7Yxt$PGEB1sR1zW2LO|;^_Ax}p-v|dl^foc=e#8uC(F)e`Yq$QB(O_$V8*TY zPN*p3svz(jK>5{`J8O6%7H*#D17Q$=x>yg*KkY<*{fvQ%vI+paW`Li`+;FXJIx+O8|KN*uP`ER^Y>mS`H+|POA0}(WToKK-YCF-==>= zKx!Qj_~L6RdX3W-HO?2!d3PL#rUqj_}1>!g=w#}cBvt!iv#5#5SV$?qPWSM z^}Vk^kDXYfHq02BbQ6(v5Wuy*uH|RomKEFeqxD8$&0KKlzF9vWB5@VL{)IXmwOvj2^rnKrL zXRd#m0=?T9%ujokV7YpN#8`mGOwqb4_boc zx8@+>H@Z!lvbPY*SYjT*K%0t(`6V%Jh2V{r#Nm}YbR%Jqj^%IZ_`yN{AO($RL?ar} hh(hM_y9b!Y~pK|oR(!I74dZWKo82I+1jBnO7; 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 ZA>cnoV_}q)|0pPinzEKs%`5AO{{ey=bs_)& literal 5933 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 XG?6~;(8$ib00000NkvXXu0mjfIj5tb delta 771 zcmV+e1N{7$2b%_vB!2;OQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z3ljhU3ljkVnw%H_000McNliru;0zrPH!WkAXdM6m02y>eSad^gZEa<4bO1wgWnpw> zWFU8GbZ8()Nlj2!fese{00MSNL_t(I%hi-iZ%t7chM#rWw|^dWY3o|on3y3##6%b{ z5FwG6xc&g9n2;tyf|waFlco|9F;JI(AQ6{=NDN4&sM`s3s@?nSz1PKnLmfTZA#1YM zx8C(VdGqDXf`5I9=8L0yPOb2T?Zx^va(*mlZd*vQpwf`Nac(#>`Gee*myz=N$#r|p z_#seGw|wcs$@Koqs_KMQ%$fI>zBuAl3dxzitKw z?ICSD7o(*_35E5RuVqTCLI6r<38W&H0mfU5GsG%f*?NW(L_i>kWI*UOco2vmem&nS zp;|heC{NL_XW+&Yiq|P&S4_vYMTESo03B<72bN@-X5SB90TVmK4w&J zyu?)tGJlh!g>;20uTBaKWxz<0lBWf(W`0jrt)zNukkDzW`N&i2#KlR0?Lk7IG@?zS z7AAk_`O8sW_dkD?+j7_G4g1C>ogsjAmKk9Mxv87?Z&J*M`Y+LW%7?X19@drtFQzm@ zfKgK)twv)zob-Eu;U>8PTspG7XZDnV0vs@8-+Y(Xfb)QDda@Ka)B1Dx4rrVkn?HB+ zgas}Dwe`-d9(+5Vnqz(L>AY<~a%002ovPDHLkV1oTu BV*3C9 diff --git a/Riot/Assets/Images.xcassets/Contacts/riot_icon.imageset/riot_icon@2x.png b/Riot/Assets/Images.xcassets/Contacts/riot_icon.imageset/riot_icon@2x.png index 84691d7b42b9aec460da5a51b7618199a80c3123..b333a6523935ce874239a519d02541dd3deae79a 100644 GIT binary patch delta 1869 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 diff --git a/Riot/Assets/Images.xcassets/LaunchScreenRiot.imageset/LaunchScreenRiot.png b/Riot/Assets/Images.xcassets/LaunchScreenRiot.imageset/LaunchScreenRiot.png index ee42954c7826c78416f53af792ee022405d706df..e8d8215074fec8b6c50b94618fe35af2f44ecf6c 100644 GIT binary patch literal 25311 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 T^B6||yQ}bgM8yR*O?6Y09uMFh(bZt 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 KxoR21!2bbT_1QE4 literal 16646 zcmeHuWm6na)Gq`G?jg8qaMwU^cXzko?iL&Z1a}F9;IO#tVgZ7?!?F-8xCXb}$-kak z_Y*wtE>%-Z&rVODKIinY{&k$XsvIU72^t(69HxT2v?d%J{I7o(%4^_B@O*a$@Q>I_ zM&C=z)z-_`!ovnm!rIl+hDyQN!p=t1#=_d)eZ=NH9GrNCg0zIT-|BIJvlF>qz=j;C z%+zU)L(%EXM`dVG7W&2%4f+-_we}st2#JER784o~(D;4yH}W^cJByxK8zueT12}H==BA*mO*aS znft2q=@I=({a;3+Mxvx{CrmoMwmSlEU5Y5?eRh+wHoEiUE+4Kr1aY6eCs{fiO%;)H z^4<=hos-^2_>ucl6Z}G&)O-&WLcI2Xn01}CZeuH-W~a@m{Pg__?Kzt~8CerJRsMNv z`#U!4F-GBcJam-p(IEYdA7a41K?|^`_tuOSvx9k*c@v5H-H`NW8az=rUtyS>6Eb%5 zJU00{eSkRbEmmr**meB+6Z+tuDS;`4zdeU)aai`bp6uLHAxP3T$I5iVOy@k~19dNo z+q218PtbAUwpn-J(2T}2#@LzhNZ)Mx=B6mRLL~iQB@W0RnDwEn)&)ZzT)O>fV#0fsSKj=Dmh{dAmia_*@GiV( z1utFqP{vm3ZcLe!S6w$7p+>34J@lh^mbAm7Slddm^nFvMmI<`4#l!NBf^K2m&rVum zAnsBff%m7%$IH2Khl6KnPyw>~=eA@fM^+R0NRH0XmZj$oXSoC%DUkZ?25SsFd|lVw z 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 F{|A_OBv1eV diff --git a/Riot/Assets/SharedImages.xcassets/AnimatedLogo/animatedLogo-2.imageset/animatedLogo-2.png b/Riot/Assets/SharedImages.xcassets/AnimatedLogo/animatedLogo-2.imageset/animatedLogo-2.png index 1d81e737e37511b8df56cc081dfc2c90d96deadd..714008e4c4f005d578ca2b0706eb5da304031a3d 100644 GIT binary patch literal 25571 zcmeEu1#cT|*L1+)q=5z+W@ct)riL26!woYtGcz;S;WW(5%yAlQn3+EJmA-%RNM2d8 zY{`3eues*T%-Kj4C215yJVXcx2ozZv2{i}^$en)&JS_MV-^K1!@EgEFR8bTHqCOt! z%@_s(LIgrqLiD=_`Kx9WBTKz22Acp&RK*TtQd5|6fKV8GW}Ti3w?KVSrj4_ww_0yF*bD+54qm}lw-mDQmIMNd z^lJdr7hHWCq+j_xLdBwad6X!u;@_MIT7{Gl@ubxZuykc-e^@|?MYs_Kd(ldCCAes= z|AqhbjtJo~P2Nq|qC#aR9CWOX?#!L|BM2V=0WSin`^2x}D1XdwoEoh?`25zcBbRAs z>`0o03n^+#VTD6~YFm@jip#Zrs4(H-zBVzTl!+xO03RT71O6*5tKZV6n6pU)w&UfB z;%_E@rVI@R^CVJ`42o)w0+SMe>jW)Y>8J&^8MM+EEGJNq*8hIg`!pI}QhPJha1eIo z7i=NNts_Dafd&T^B=PkU)bn3saA$LduqyweLcBK77dCN0)_y-6#h_$y~m|y!{jY4U+*%?sJVi!8QzA>*trkt*7Y)->&tI^pW-AmFt72{Bg9Px;(zb zm|Z$qaO;@aTdf@5U_0~PV~hovt@E;{)0W7oxh1({Nb+L&(eNB+z2aPty*bamumy>c zBDO*iVD50hzIkrjLpQ_dIY#w2QpoN4E~u&~T2>J4FTvLYa)#JGMmwYDf&gd&ipcyGS1v? zk*V^T+n%G!XN9l0HIv0?Ojq-uPjj9@`^#T+e7K=6s--aS-zOQL8;nN{bwx1q$?6ue zl#f=hKi4eC$bcjeFg`Fzqf#kTj5>o8Q}MTnMUaWLye-XU4`XH4cG+^!)L$ZP2ga81 zl%tq)Y)Xa)EGn;OarxX!@^UlU$X6!f*hh9%NeOyrDj0dt+M-mGvEaXN{+Ls4>2Pa2 zm+_|`UC@W6*}0Io%P$PL_vx2AC|`o}B)jw0?0%@DYf$+knjAhiIJ7XDX#A|he*w_jX;2v4l(8O8y9RC>EBGDbupvl|iUOMR5adTyux zxc65L7KJW&o6inXuBd<3Uj^Y_ll~X#^Jky;Cyzsx(glwcj^`TRX75pS{sHku{^1Jt zQkX8zI5iRE2jdI$C$?`{$NpO`kCuw=nR=qz%*HeON^9V0_6qOCyf@8`JO$J%j+Azw zBO;Ghc>U5uslPdNjxs=xrjMoiTP*H~En30J|_xn9w(!w=fCVw8& z&DqobLop$+1*w)4VMaJDdhNrA72n3TX~PDjZP2y5lt3p&ie?1m^RYVBXdeQP7626o zF*vP}()0a=g_)PS_U3$ZX1KJW+A7iATOKP&ekP)1x1R@}IZePTY$6j$cu}&2)bY+LYKO zR_ZoV_3K=+JyXSQ_L;yY>fd9@iQJ^{55F2ADufJyibET{X`=+~5VzP%RJ4aw9rj;K zdA*KhC77EbEU8ArS8L+KD*nzY!@hhDd%sEt^UBT#LRnun!a z&im;@9h>2b!aE<7Gb@)hIW1{mzEVMXa61t`+zn^RdJQl0mMCpGTM#e+Xya;i;hFKt zSCRKN)=a$`njy9>V6@4>l0;QOn4$SWsFF9a$a}u&-xfVQnJ+PYMgojWYmo8U>{#o+ z-_TBrTc)8@?8<`?_AT7@6TQNk|LAqXv)Vg zkbZCziCar*+b6cg?IAPOQO=xg9 z;CD|e{=l9+amijbs%!Mnh&DzY|M}U7x55a~^_!nYP++CIDvl^5sZr z5!b#FZaM&ow3rh9`@UvOwMTtZ+Q`*~3?hZip_F!~K& zSgdJfXuYEkbLpAzercRUytUT`svuvKkiKLr)9za}ats>ELLffLQLSfKTzaKV$;T2~ zv6Ei21qL^F9Pegcz2h4GLbLCuB3a!!7+u@5e89ONacz?_5;eb>-y5)@)PLBuE$xD) z57w)vQsDxgWksdSRX@}816Qp|dTOCJcxN)LL?>wedNs0fi4$?li@&7;3Ic$pMX^@4 z?N?SGq=-K3in_Wt)K%oNm$d_C0-6L?t}a$TKPKbS$p!0f2Ly`gctBLvi?ITlXX;hs zi+_UsrmOrZf$m5%Hb;Q*zJ!}Tk=rUCWl)0`llN=(ej~DBXl8C|P{*>40+;f2^=Z+b3WD_A6r@aru%1HRRE* zYIja*;qCf-?L}VY#>ubuRvK3pd47@D<971L@+*HAi!uqD6k6lBO}^z%D}zQCeA~i*%#p+y48+LYvw8UP|gM{p;^jU1DzaZo;mw zMHDw(3Kw{V0m0u4KW_TqDd7!r8}sQ+AC-OFDr=d%m*KowU8~QDUv}3EA2Iw_}^l?MlMGrX{ z&~d}^P9eCPTox$*-yT7Y^*Fxn7CAgvXy z$fqs$GvMZ4e2D@VaTTC&WZ71<|Ju1rcUV3?3m0mhR?N+vjiRAo!&pRfdHB!W-!Om#JcECaTi^Jif`Hw9uHO4 zi$Z!d)a*8U=9B~>w&s0jBpx-?sA_22yewCqNBNn*?*!NmQ7Ev($8;FI+Wqb@n_|rI zUhF)YcmcY`|IEeIS{xHLp&}^lOENtH>;+?U^Pl}EC8~I>Ja|$>|KNjEjr3^FW6OPY zb5s3CZj=hT$DFb!DU}74UyKI49H9$_C#+jx6Hs)ZNM?Nwp}GSF^A`%jog@if#st}Qg^7@AV5TeZ)C7CD^ zAJ}CzTz;q?583tJ(%*q%_#gci@zYcUvMBoKG`8^3+9|$1BEtGf6TjVV*EaFAhpChZ zHzRJ!oo!vV<}K|kF=*}?af>9Q%$AursqFu z{hQX3hgEvzS+Q*dq9HB9uGY>n2k05|fgiA%JpHtI<_j^=x$; zBb6?B%CHm(Rd>y%l`$8w1%FLNNTA7xLTLv*aQ`*f0Ql=95D`GSS4XdBI}p(F{9GQd zttkTP3nef93}foFuc!a4iJSR*Ly7`WON79z>rqX|KwKp*Mw?G%#TEEd zQuPu>u}L{d2vb$d?C|mndi=Ho>-Q}*X>-sWhMYnOGJ8O3Ab!fYaM7DJQ*2o5 zL#PR*s?#=caV?aMa6NH0eC66GNBkK@q)5s2mmc1Q8UkiBSEhC5Oran)Rz~eqs|g?4 z2RT>dA;2Joy+Qb(j=HjY;5C_@|G7sFM>)T|mAIP9J$sru#L{*BjGMWdb`y_JKLrpt zNCg2?gWIEsYU4z-UO!Vh7DRytA0-0peo)up-3d_1v~AG7`u zxjHsr@KD8Ja_t;#oLEj7I%rC1q`Vv_S!5_5&MUYuD>T2pVn7f7>6;Rlm=nmn^maa z;bN=lEzUma${CY@DFj*S1E=&&j@&%HG%xr~-|efPH*0kup;*tm1PUk7az{KKw%Cz2&eNB}q>(~^cWUWZ=vSxCJaI;Yp%_V$Iw!q-Nah-;(Rag1w=4-C-y2#0J zflP>j*3s->N16IeUt|}D@6*zw<>kaivy2DrOFsB8wxyy762U+ZfLcbT!mNW;%8*S? z-x3K15~7T-NhhG7#M^h6;F|n3RS`zA@Eg(u{-i5ua!&h!sFMJ)UYhYXmm+!`Y4Xf zTkq9-@im{*mzfKGN$OU@LU!-d zr;0CzfkdV%7Ln9PQzWj7)N}onxg(akZ698?|9|(5T;?7{g6hMN`85#U_dxW#CsuIO zD@0rAgJpBj;MDun$I*O6mGua8zm0KIo87KwTI8J1w$btVZ=&#bj3H0#mn@Eymss4A z+WsrAPdFSdOLS6JS+IOWJtjh>#_ffAnJu#`rKl-gmMk@uE7JC_hv{*~bJhEcW@K&9 zn(iia`^C1}C;Bm65HhVnss$k$Xfi^6C=}o^L;s$H zX)y5QPc;?+8yEt{w45vP3?4!i_KuIeaEiEI?8NUnilDbO-O9^RNJv?iyQz1d#iQ7S zI3Acq5deFvK96J%8JXlCcIR;_={ni(Fi>g#bg5w#iVZ9$;{y1KzX_*ON#u<8(;u*a z5#_SGJY1J|UuQ7GUAn35arn97*d70iZv&UQ1mPa5ELeCt{^3LS!Oi-Iuwu1>a!4Rp)k|WuUKO?xQ@La{%gBw z7go-y=l(*u--fW#!tY|Hqku-)3;M2VIp%4pWojv5Dj-rv1FZ zIKQE8^R55FP7jXR=9p2XFJf))c$FXS>omS9!yHPNF=mQAW&rv2gw zd$08N>IgS&=>m;Gf6IRkrX_Q;_#?B0>w?`w$@9}4eV~Iu<)`Tcy!wBNv2Xo>Ugn=P zcRF?VdqaU>EzXOBjs|AE)fwsG8!&&fjV>36T;@tE7$9JE72M=(-K{9Xl>#%ASTp|- z_&L%7f^3Dc?6JHisaIR0&lke=Q;2s>v;*XmLz<3lnak~)wu9hehOp9Vi-TA3?XMOG z*0lwj;a z9%U8ND?~I`hc_FuPZCpTU-PWiyt0#O=3@?d3|sRac;nWTj9KHP8TdZ4Z$E+8!x@gM z5iS)|mypp)VBk{5Q`?K7Ggf8z*N|1Tj6sm7tGPDLrmfw&=0llTJhkg&5NBAd+N{OC zIGdS&D-`5|b3#W=iu+F=IijBz5UFEdvum+ zMH;7$h7kQY3=Bb^s%m3bb-Br~w2iKC<|F0O2alKy0?iT2LX?H-jHquD3bFqy3BDcS z++n2FZh{qglOq29dk&X42KC_*rf{F!lOL%ij{8ELl-7`A_wft&v2UZAo1PdU9D(?J z0@D6BHN$Sb0%sMaYmk=>v_4NB&&q&nnlQ#C^_AcLEJREY*&O!Cm105jHCfkn_`OZ; zhrpYQwJSNv_5%YU@5ls@C#=kkwrCUSHDgD4o4 zqXrT(lNGsre3;DcPtk`ocMY3=xLy3#%dHhhtC1AZk)pSD*_zU4M8R2uUb3@Bn4Y&x zFXX>Kv}10_nMH#K1c8-i0zi#QLsi#reBox1R}Nyit~8nf;fwJemb6?(R=hH?3b;O1 zXX>o7>JV{Ym-M+}?Ycm{5RVSpXU#*rfI-G9ejeMcVE#iyMAiES`I0aw{y_SAF5>#Xl!z!{Fnwjqv>wtxV z`=eR~?-&4DgfJw{&bQdWABZ^)E3O=_Ly9FiC=^bAN2GyvUOSqsZ_i z&7s`XF@b4(*ledr?g{NbR6N_oWE7ylYVjgnQ=E>2e1{p|(auJq7s?oGYPg`trWuR{ zW*HP2B!B~48%~F!Tn>j_v^*5hc0Gsf5^m|u9p_$h>+HT6JIiV80}dJNef6GWyH4H8 zc_}&e2GRw0Rds6{Q$`6v9ak&CqrO{U5Nf1Y@8%$js#n5}Q`G^dSq^8$J80RKS3w%I zsXTRm{b=#)VO#1zX?9vDNX%Y_&wJ;)ieybf=1g`{Y;53}m7Cnev`m!q)<2^A^-Vun zfU3Ly+8uS_Tep;&r)#6wUw$t%!U|Sls)KsZqlO&*8WMU_h(IGS$AJ^4kMc|%Dpwmk zS#sFnAoPBP$lY>}BBbyrUj4aJ)%f&#TthwVdZ5=qZKRwGw{tVzJ>QEnNn^N_iBoCq z-CGsJ3T?IXn{@H?=k3AVZ}@K_#V6YHJCy_cDRscJ3r(C{&r6C*EIj&Q{guPSCK3~MTsI(sL$DGYb z8Ed`XXJ8(;e61Jaq&ndfzUTYi5pFSb%we=?q-MwS?wQk|<}W?v>yK?irM|U1kfz%E zGgSuHWa$>V5=gQ}p9b_83=CKTHp zX}$5WSMl2Bmo_J?1=MDZ7Qgbe9!tB)VRy!RSw=uhn@S_x#3vs2`1}#MNeU0%SVkF& zQYF8C{89NuH1#G@4JV9)Z=y5ARmgk^olR@B%O8}gJASY<5ibS!LI)Z6?H>n3|0~0h zyp^9y-4mvO@7c!Z>SFqMn|(ZZIFP=_*K^EThoh*=n?3LOsdf}s=ZxEl8XKU7cETBv zem%mJVfu_;pTe4!38ncu;Hn#cWA?>FJQ)3t8eh+B6)o^jR^O)xq;v*v^2~Bl7(fkJh+WOvgQ~>H2`JwZ*OfCU4qiH3?zq1AZv=Z}zp(5-JptEk zwU0t?TAK8Kj3 z)S5+i<4f9n#yA@jr7Sz8VI)pOXSsXs4$?lT$U55Y3x&7BEzN|jg(hB`uAb0_hWFq{ zO4Ce`YQ!R)5v`P<_ex_Iws7l{7-p7KDhV1E7)kJIez~NFd@Mmk86}Y-KkhFLbvKIu zHW2FR%r>3JdM!|TK3o48g;83W(W|LLtxp6eM*jDC+s;7`U7fkZ+k8WY%NgZIb)nbC zgd;vJ)zc-qly~jpZ@c98EcwFk_6jW(CMc`X}X^=F}4Aj0jXC&i zCUHh?wbhC>-R2KH^-^kpCITPKnVoa;ji+sB!W{d89~L~8(-D)_A&FWCXnUY6irJt#Ff-eUnF#-Yhax>7QKzp ze8qHNi=%rnMSz;9j?Sye(0u{=C_TX%LU9uDPG~8#k5;PEb&pGuE8+f!!2gNt?R)wQ zTeFwfhtjAsSo{;ssJf=|I}XRnh^|s~Q;)gmu}5q81?hnH&!!HG#`)&Puee_bKfON< zxsZMQ7rRWaV$02(DzPbC&Z!8U&@yOM$ot3K)uN zos5Iqow=h^>vSw_n}&tz>|kq5Tk-RrgefybV~pPxZsp3;j?x77+;BT|oqu-znp%)C9`#_X-{ zKPXJEYIV#-^_h%AcNS*?JYkt%bVR2;#tJSZ4{^`-h=A8jz)l7f-7mD%^=!WwCiL&U zo;#B~jaR}E+rc;IMNsi69MA6Gap?RY>R#z&ZRf~lb4q;Fd{+4=&rWe?&cY2d6c`)# z6Za_(Vr`RBEawtd+d8L<6Wy-uhpEm^A7XBTHISPuw=7W4P^f%=gZ2D-5;yjmsGO7b zUn2Mr36TtXBhE$}`=3aa>oPbE<(Z(?Q`@5{Q6vEVrMh*n=%MD1^`OXH?KIsNEFi~n zz4DpmFNoFOANg1F4=1kfHS8duj7h?@4Z&^bDE1HZP6c_*bf@{qX*=uzi@-3qn zP}01YEBu3c!kT^8zN!}gjHcu|=@$5`@(hFm?R8OvI3%Kp+F#txyBVuHn=GxDT2DPP zFmVR@Hv{fK=C-O7K@ji&F_ALfCj2fUAq(r!f?UXsPEE9Waac1JbL`bC#!^fN&x@*= z+oap{DG$9koPPPBs;AuqAY1pT4X)MunzgQ%v905bpOUU}1OG6B@hi^;ea#_T;BTSq zKR<0e)d*kPH(|E{iXuIQ7%r|f5Ma4IS7f`rlfBcXys2h}(*QU@hq(H7B*ME_Cs)UN zX39sdTuAvhYIB|+C8_82N+xjzolU#)S3_y3ukdAR=XIK!h4GUSVeGu=p+f6K;XD!>PZ=Nexsp=u2+1_4t=Z`!h#NE>wye6mM~({-)atl ztOE!9w!6|~a*cL9)NACXcpZB{38HrPq3BE98kG2Q85e&$ivVb-^gPBi`j*4HolXQ%EI8-B$XC?{f(m+s^RW1TaX3}j#g z+RoZ2g}&smU@aRoSH8~rLM<4@oKrnBfifSsbtATK8N?hus1az?p$qkQ!MVAwYU) zNKojcvpc+v-z^x}9X2)4t*9|l!4i44=H6se7VBUS1_;-3)!B2kr~eHxrnc26A#t2ZzoCd;k?a?HbgSnx>bCZZeYX*K4?X{OFo@{LZ%vdPZz)lNqPMOe%;y8e?>+Ha+TzjnN zq@&<$V@J@n_L5`pg$&&MM7+LAnwQ93)|N;&P8F1mp$3%ofNl zXEHQ#fPwKKgq(4rd@Ek(u?QP9KWqA<74xRV>OTw$_?s*`qlfQq0-E|MVmU0<6I3WP zM(jL7yM+P1BBGe^A#(q6ZLNBiFXZ?JTNTwNlVay{M*4FVCHfWYhFy~<7O`u<6OU-~ zGNuw90xTZv$`t0pQ8uih0?maccxs-IuAv$^@t>v~^eO$<-KfsxENCu-05QsfX-mz; zF^w~VPdj}=->}EVnCm4<-WftJ_pB7bf|XJm$4{;DfajQ#!rw^WBq2+tyn`lvOD(%< zCDj<>ITS2*1&Y~o38mG-Oe>MVTD(kIb9o<3R~TxN5JjE2-|?zftLhZHVeO5^krg#l z+s8lZTGUu#f0!;>b3QwF>W82R845=hfVtRmm($>bxC)78P z?Wx+w>fYu;*Oue8^*B&*dVv3t`Tm)LB7}P?t(iURoLYBFrFV?02w|OAv?Zole#P9? z@Il!*_p$-Sp-{^!eMYIZapNdjU&!#zMgH<(Epcm}(m#4+?!Y;0!o<3HW8plEb@Md! ztL$i`52`hjry#c#m5EkNkXon7k#aYg&^G$XnSHSNC%46ZuSc{;oA3Jv@am!Ae#4d5 zIjP&&UOlzu?Uzb#RmYk0+uobLSd_2=&LmM`jCTD@)$3*Q<_Q! zd*$6Py@o(#jmhdKML$=+??e(Q*<)Uh$N5h`b%(CcI{O(=uDcP8P{Emu!5|R{_?RwR zI>q0od}MC?RzoVS=M|bY-Nmq03nrPXdj5T#yarjE$_jZY{U`lhXAY(vK%#oc0&%bHkGN^c&Jl_sHwdY_lX&_nR{U(r;i^);B9=fCirsz|Nmr_Um_~)O0&lFGl^$ zp{w`tB$4wc%E|APb?6o`73^6>>ZuvJTbO&=!hj|1Rhv8KMpom4jta8YJJ963cq}kO zt3AOt^<%O|fEig3H`W?$YF$3fg9f~W+(7Y*rji)&oyq|g?E~g}o@=GJTNKJrSiDF8I#hy?|Ct4z?=`gH2@ccw}y5Ns6VZJlD5ez+G&+%F5pb z?L~_|9*MkFr`0BnhjxizD%~Tj~|<^J?ZuaGMjoQokX*$U2I zt2NUTkB>unLG--D;mOF=>yUEPpN@qEACAN?az<*lRmxufT-5%_KG&Kq*jO`$sAobs zaDzhsbKF@=uwOcfh{ZY?WwU2-hgY!L$6#y)sVcg9>gG9$*-%?3NH32VH>{y%S(^wP zYT2vHWKw*s!gnOb2!Q%XfY}Zd8ASN~^wMc^NpR*-DSr-U$X{d<$+vA`jcU7De0~a6 zT$+yS6~4>Q{6zTib=i78iOXuRq~1`V$r{sp?%LG}M=9@x!IfMemIZ>#LBazmShqvf(YyW< z$MZ`B!zpCTxcvBW`dTM1ebHw)Tgq())a3y-rAzXs2`kInZKY-0v*WD1(d8Uk+mA=_ zU;mC~zw-Hr#{c#tIEXnTE?kEON^SYLL_PXXiQ(ZV+!I?6hLaw}Em=SM>!5$nyr<0E zvk+h#(C6)Gn009F8FpSo@O$wJ*Ba*!89AT@=X=9bA54FCJnu0Xrg?45Z{|h|@e5oEai$Nrgb$Gi?=m^y9tD9bGTq=cHu60YyVUZ__w%Ad z_AGLSz6Z+9x3_3_x683Ot)BYezgfEFD&XA5KrQFaO}OD!wY~;{-vXzpv-XI9M8_LL z2=xfM{?S*+;8<}f&TRc`-S!IoaZZ5>pKV2A52+fz+f?#+{55Ck@*%SiHP~-Y&#iOj zjX*sE{U@ma$%Ltp0N0Ok1%Lzxe27>LUB$iz|YIH+02Kps>gT5*8 z#9c$JV(%FxF@Gti3FEi`g4^WPGe_V^Kl}$I`Q1T3GLIOEs^S|$lfGrCV!Z7R!i19nQNul(I4(uPQ`fX{xw1BCRAiDyyA) zXH7hmQ4EYg@n&yJ&cz}IC9JIq zh#k2yngvXe6~YeVopPe5EadDX>Q~*NH(IW1kYCbOVO2*@Zk1$mN2iedQ*t4ZbZVuIE~7X8UY*)3Wrv6o z>aM@F{>b`m%7>E4#kNmmAmE$#<@@Dg8u8S))-$k0ji>FFr-PWQbsCFn5L&!*HSyNz6#-M^M;9jB|HGBa_!W-AJF3 zVyr$tx+fVtyGb=VpKrK0y(UhpLUw@$G-syD?=1>OK)h3IOl-`qRbXdGe^y&q9$&-9 z=-Imx{sSg31iTsKIEcdrqS~wujkrx(NXyDb;2^XDJ+pzR9IgLdY+o*PD9>KEqPoRj z+<5Nn7dl=KFG<1^6Q8u4_`cp2(Wd45I*5P&4=l$j)m+PYS}l2kjT9{#vr1R~4 z^Vel+kA5@}67zZ!+!G3_WK$bNh8rw_7EN1u>)r@}eWD%cU>A}=HK&5%2jD@VHT1`7 zJZt|eAVr$qwNWj-SAKD097N)}0%W=)*bEU&KS91KfNg4C}{#X4ZQGmv`%_tYr3H2+MwUweK$h2t@c>B z6pz}WCj~NgX0kbx?QOGhR8GlPn%%1NPu1o>pV|A))NK2603m5f60`w35#;s5^amvx z2ETsHoIbLve~~NyLLdEih$vX@d@S~M^E`=b7oqVh0_OWlXpQ(nwUmA#~!LSJ%NLa46i8&iYJw-iUV`3kp0bgk z05B3E9s<5PE~<%`m-?h)NWtg!g1wi8eKT(D<=tnsnJ+f0m97l^dB8lH3OXJ)T4C@~ zFaTL|!QP^1{W z7%mYzDhytLlnGgFq44RI#6Kn0cKJU&530R>A3ZaEFy!Ym)zEDc@}Z;vAWy;P(Q>g` zQe)cQSU`(J84>5bzS)$GmAy0oR=fYji_}>?kJpl^2tnLa0RS`^2XH1(=?YRo>RS0+ zATeeu$}0clseSmv1a7WCR@`LWt{|57^x@H9y=-bao$2jS5Fg3ilAV;52~d(!1lD9n zp3){IlO*u%T~n}^F@e$1EC`!4=Di349%D2wq3u#X?Qbr>li|J+9Sfa*jF?X_9S~P- zDca&pj%0Qjj~Q<7JfGsLLVr6O6moJ0!FZ0KE96k?uJPJJqdP?*NNzO+@f;L3*xThT+kK zcaJ^TDt{l6V-rt9MUc7Cd;L?63X)CIk#-}-eKkhjeg?zYSv=ajiQJ9=J#xq>29HW( zc8XaWR*=(g)t<|gN}A3)hB2m|QMuJ03vTL>>dbvqrN;~_OehOYi{uAABPzWgxTMlC z@D-HmXP;7#T+E{OKp*ytI7OyBp_wo(Kf4x;n;95<&6{>!D0qs07VJLpUdXZWM%!UX zBIg`HL+kzAi_7nEm0oyegAR1ldgsHWzS^B@X+z2kZss8nwZ)lg1*dlXLOA-Vjnt4Z z9llGSFFq9eT_VS&L3kUi%8j3<3XNVe{i0zxS6q1ihgdJjr^=bU zYjYLb7P;k*IR)S;i@QuW+N4LHPgND&H{o=lJwr4Zn13dSs@reDF1;)l@AiAFIzH>l z7zZ>F5%jCy0-cy|R8w#JZy9>?1>OGq`JU29`Kk8$WoY^H=3-><6r_+0qSmk)a=OZj zY`pVESLJ)b9M%}W9Xb;qZc!vuQ9Dlxr%AonCy7n?Yw{w6;!2My;$iXX{-v*`3Oq{Z zEQ|1e~06t=68_^C82{k#x*Fc!0>ARRzA@N$2Cx-2)vsv z$D}l6=ewWMn6qzaFMY=grEo0-UloAl&iq*uCm$$x0C>4)4f}3D+Xg1^tRN&gJ5$&| z3bFt}qbZ~H&fOp_6T$t1cMfX9ckIiArB>-qNs(6s8Ikjuic`@*y{1P= z|0CZa$#QWY(_wPjr-^&Q!kSt6vI+-Y5`NejVXT*Wy%PAm zD!gr5koGyyH_KL{bE*cf_lMrr?fGj*H3EYHxlo{qbK{ zw&hAP)YjDKoKfbYa3`;GGd^Bo(t70=U>;SK?fydGLLU^5{eN-O9EI$;#S_k%0tUHS zqBA9av-@*X`9qVXoLUv=3)olhE;4(TgXi@I`u@_JbDRx?X`WxbU+*Ixmu*XP{=9=H zRmv}A;cHts^h(^dx~g1T3abu)y~WSX^q+WQUug{o57G>cN;e99)QO}pApYed|HGb> zyhU1wSj1>r5|0<{vN|k3)YYH-@~m{uBey}f6Uwq2TzYY+v1#9#A5XO=&W_~B-MVnt zV@u&)-8R&Cf}<{n+>lI|j5;*&@t_Ii|%F8@FouTa~N!vnp zhsBoHNv^F0hb}Ea^!#EcX=*#!@&=TyQw3b`>vQz#`z9bQdD-mIXbqqhI|*yyzl7nU z17&O7+Pf#h;s}PT)8jf{m%95MSYsee5y^8yo$;}j&1GDMIj|wmwTX5d0mdbLHW7^U ze(vcpKg~oEM2bMj&qlJy(UKJpCpq*%K#<4%dlrDxdFEO<+)N2mnM{1`$`s*@O;I-S z@7Nq2E5A_nFI?MxMQK?l)5o`nj&sJ1psuF&s|X=-wRd!Fu!uok+If4t*}#vI&6;~V zvWb{AB~sRaJn=pj173M*U}y=O49y0)ttUao4+rPe)Iu( zcBV1q@q)n440YbKm(9FpQ%yUIpBAfYGVPo&o4Ogo^ClcH!@V4g^u7kNVB$m)Px%*K zL;@?3Jb~TIXrE48krbV$Y%97<`eu+?uQeCnH`)!Okg4hIaSDI9)Bj#Uf(ZIxCpvtv|j&(y`{ zp#FoSYOE!VwsxKHkVD9lKFvg(dP)K(Y~9avRdwVjvY` zSKjv9f>%;lesIMYa{qt6dm9cPzrpC0EpJH6XU956q7(zq0IDkr%T{9!K|?TtB_QL$ zj3$KSgeG#l<*c_xV}ubAd2nr>7&#Ef=plui6~jiml7#RV=&m4{b^=I&*diO?9vX7= zDj5)z5d*lWqrDIfy} zNdpWU2XU)Y(wjzlw_T=e)z$NYhah-LrQdAd-{y(1laY1<0uKIBQ@;ojBMYd1^4o_A z@Pr`r(UF>DWZC=Ra*qiX01*iI*Do1C!#YM%F?K+H;j4L&WZ9>tJN)&-inE>s6x& z*a9^YBIDcpHv+U;DGllr05k|l|9>cfF4k^_5Tnl%>h&ckoq-+&jsI_kx+-;#1!X1) z61+Be+NMrJ8rJEVvLKE^aV%eU+=3&>6~3;g;ZsYf)ilnPB8Y;-ND;iZFB9O%V37o# zeF$1@5-vbZ#@euwl9c8mKMzK?rar{UdRtPEK>Zt(XUK0nIlS>Kef+-vtDjg=WU(k4 z0a1H^yH-%qGAYp%9ZJhkI0-h6_&;+PkiQxWaZDqZ6Wr2u80#B05o{ zM=zs9OO%K%B7857wfCN9zwdgV zvep_a1@Do;mt?{=)@#@Q5~x3@Nq-e&sB>2)84*zF=QnrE$?@T};ODNYn(5;QL{U{S zuHmO6$;nFbNhf1$CB{bYyGZ2P$^og{A6@y}?5Ba3S37mzK+1%$fG;}q0EJ&DF-zE0 zUgfy4W$mL^W3vTTtYT_Cm;rQ=otO@fTiDp~wxh)A}h*|%&p@Yrx)$#O59$-p`OVS2wy;Q;!9 zKX}M(uv<)Pyi|)?NyggWG7PT^KEaaS6@A+!k=zxub}Jv(;BymYF=rn;AC;?n6sI>f zD3Ohc1U=NhFeR`yRaQ`yY_1-8=XNWke~h3sGM)(@K0D4AeA{Qf{$!Mid%Z|tRo?C%{Mwsi=gpD&r} z4u&xSV?XWRm06J@0O0de#^PPqIr_~850FE#LEJ!ADyE3fxQG`3C68sR?%hYvM^oq8 zAH`wq2l`VJ{3bGaPP9YsD!D=*ho{pO7pwuBP^zn!gmB?r?QB1Ubr(JnDIXFlUyKzI z?OS%M<6bQ4>_L%#Z_OV@af{wgp}yQL`Bvbeg)wfVM%bL=s&PvztULnBjdSW}2E*mA zcRtp;tc@MN8RR+%IWOgJ`D} zjo1(ZLT>^kS*^6&Oe7t(R-hnY;{#wihrz_7L^9wGm4nIP`;0LoZfs2J27KeF5A^J^ z6HH{HKq%Z4VnSBsevgT+M!+mOZ=f|%A{qoLCb}Z|rx6^50FyrF?vSfdh=@kBRNPI- zJy%d%Bf&3P$H{3pK^-VXfav`+E`rie=rI_$+|f$3;i`(Im($AQy|5d6H!3WRPn=BL z3XR=*Fb7?w3pN;Dfc4!KOIRcP>;-R{ zy}(9G9RBJbCVU(sF%`?+jMq3s4&eg>?&>$c)o5vOjBMWJ(vR*W#vJXdemWLur)C^3 zVX>83D`?2|NE|!xi*74#SsiOF7m>tF{hFKS+4!~;-&VP$XyHY+nR+iV%lCtvBN4gE zNZ%!drIPb=V;X^3%g;B?+Yk!5QKNpY7stz`IWU0>vqxiu=<0#YBMv4Ylvq~sdDa{i z9{b}Dt>Q1LC_LFe$WWHLNL63U8aYQ1xjj4#l*h3l8 z4>Yr~Y}X~5lg`o)j!^VkAi<&iGwE8-?YR=DnpJ6CH>pG4gesjXzNBx*{GF=_{yjot z-5^=Ok)zyegxtp{kCrPxz%8E%WfaQ(d{SCVvDm4(pSM z2V`Bq*=2L6CtZ)B3|uhvLRZ80OqA43K)O;!(&g3$av$AlMJ$Ne_>1`$1{phTRmz>p zm}Vy^%o4Nt)2nV;b8HEtPjSVWw13Ni6wcQ;w6*oLdkn`eDEsWu z_UTKh%X%+oicn!>P(3L&blyyvB4%zU1O!Fx_+$v>3|T9uBNKDoD`fBANIC`f-@Fv7 zbj|r~;P+nNu(5dW8V-m8*}MkItxZ~#@Hvf>Sx`~~Wq8oNxK>^1HrP9Q6Q%h7W$x*; zhpSPh`HGYlW8dk%i(U(7(7C^Gh9fmVRaktQ+qbMghOPbto;%(Z6J zFuWR!UbJYfSg5kIqNL=`iKYQ|AoQzp6QNv|>)SEpti&alkl9g*si$#I#URvMmdP9dj8#R(eUAG9-NK4? zGky0mAN=XQmq;tb?ITn#^w3!TApsW13aA4~u^GejNCTR8s0AuAqnC3uV@enGR1tm- z>IB=ezkwRv@-`Bn3`!70f*r3!t`>Y~#1LBkeAyqYBB^iP{Bc$Q&?JoktL2jg^c6?E zUaNrzCuN)J7R)E^7rFWzRFt@q-Nyml@xbq~Sz`sL;}8`SeX5q5P7?6_({{xAd#Mt5 z(ois;vOmzB!(qw}pJdV2Ha#T(YZSdIH8-uSKQ;tJ#m`LW;#Kxqdg66N=2u$;n&|n zoT{kT179(b5dfi<y_0BClUUphAdC&pZ8&69I&fHJXY#k0OAa zvIpZ|n!T)+D{Wd>4x=X|no+|B83zI+3wkPkpe!!Ku?40?`>x?Wvx1jz{!+oh39(c= z-;R^gVFhsAwXQ+>`pG6ZiFcel)yp^U&*tb_s9%at$KvSv%N_zZ3bG5KU~KIH66FJQZPl~b-k#LW6Zrs{Ucxtg*|c+gOvIUX$<`?Z zNA*bo_fl_+)NLXYf}{C6=5ThnJQxmDM+L~@%L5T9X+LiV*A;#&{<}W?E!s@?)=hz{ z#cqR|q-Yj7y8W{(EJiuFCkEsh_mi8^UGe7-rXA6PS)8SfYSh`J#xW@mlLO!xcsrId z*xfPHG=o*pCxY0Xwqo`sM?>Ehk)6pEtgKOa8$&r6L08|ufG40@O*dAG1g!Q{6-H)j zwc_IktGQbz&pxLGMjb8NnG$(EHq)d4MYC-yPc|~Eh$NS~{F;BQ;~+W{?n5&C!}!)i zQaH0k7SPXm-`~>^3H_K+E>-GB_0)zv3S{^;36k)s;LSl1K8dOpu4G~_7$7hn$dE&w z*Kn{L$SZ~gYHAx`Tv25C(wNaRvjO9YsqL~yZ_mEKqb4(407Y=3ZfnsM-`PgVr1a8a z{bIUDbvGs@p?HRCx6+6N9$xo>N%1PmnG*}p>|c{+FLW9^A0?FLN*8iCwKmdLHf(rL zB)|~VAs1Z=EZhRZTXr-Sj!&)mFWg>rS!QPs-~@le7l5k-h>k3sIeM#4bmObiMa;^c zcD~4mo|}ytQyeE_b`Ub{O#BT2!0fRzqD{MLDEhIm0@l@!3#%$myjSiQq2lqoi+Aos z2_Mvv!Z{1Q%dD6dMJN>AZVL}CuJQO-s-Ypn#@$vJ{B37!ib(DYv%NiFzS4?0kSSr( z&F=MQe<#Drem}L){jkc$<-~X}@R~^#9mVY>tmq;bgyi(oD*1~Y zx_Fd#mJ^=wvcx0lW%>Exd)s<~2O$uJorDn3`ST4@=1*HyLiAFl>PmE!?mR=u4F1nE>R|i++Qb5Mm}xWIou)<&-V|+aNQCy=)-CMuZy`gPEWe5r7(exG;_=is+#oO z(H{L6qW^6@5feaSpB2_g|2jXuzoUd@C0xMI*-eu8`s+L5R)9Zb6cc*W8xmBHa*ALW zo^d=TMo%e@poSvun-N&zE#QXsg$~w0Jfwf@)-j53hix^MDoaLI2(js^Veyh~iyPne zE7!%(9lm`RU1z;*X0V(vRex z>E`ip{ks<;aW}GbygCdwp1#v17aPC$&f>x8`X&P1NoawX{61B^NxV3~cD0%7kW^Q3 zcF=+p0CV`b{G61L%hf3ow<-4ZHs78Mr#u!8S`$DOqSZE!)B6bA;*!!JfZTtR&&Tai z^Vg5IlwE+^(mku$&(O&y#n$j3 zaF+sg~orKqz3`Jr0&(v@6}UJKZJX$?#C&a zndjgF(>AfEnmLIivx_O)RY`!tL3w$G#?q-TvvlRRy##y^(?ud6gWPe|{)*vx<Y+usbdD>&+% zyf^%wK`=HQ@G=uPb9~<%G1$}8S?oquMmJX`y{4Im(P-uxna3?(gfG?OeZbi8FhASf zT{KYSM86xqw%raxs` zKBjo2gPS(lq6vZQP-@d^FT7BkxSRJTJvF!OHfmDCnt_@ak znNM8w5E_>=K)$VHag|kma`E2hC6D@?+S=QJA|g?Cr;F^F%DYMd#S+Q@M3P=W{N#Cs z*T2%QBqD05h82~x@cfPMEO8)QdbU4zxm-ioG{Zs}+;RF!nzU-@Wq<1~5*ZsRQ23M> zlLUu$Sb9%Bd10`M4#?3ETUVa35ITPf^Cb*!P!ZYu1Y>6&PWugTt*h^-Irb_@6T?=8 zp%3mvl9OZ|=f5y1*|_LhG}8Wr7y-U)H09U zvzXblNNH~DwfV!JuzHv5a@t>c^8m^($y;q-UW3<(DbEPlTd!Xa+#d2NUR?6}^!-qh za~fmq7aO(k%TW&T_vB^~)L^sYTmPWm+P(>gm+dZo$BnnwKY*Gg=BVl!jvz6m)0uyZ zg+D)r@N1=LDi^Za{3@P4KKrbmt?%1mFhH~d-aEvS3Z(xPZpwT4$f>M)?oI!X5VG6I z=Pf2`I_h2b#a`C`2j6W7$HmD^0c5Iv#D?#wtE z=^NjCciwrRa!U)In0q`VLXqp7!JI~6JbXo|Xs+J3&2fF^ADF@*zd*G9xJ@SrMEbQw zkcGk%ZO`v~;2T6eUY9S5HcKSY!BMAjc=31P*~!$>MKK#S;<0N6*-Y%Z!FoDnU5!oJ zmAoZ;+;f_dK`BhjFRfpJ8pDiA^$_$Fx(OwB;BU_xSB0iO{B!)P81QZAG$IkkrEbCD z`uB9^p`#J{AsCDF`P$+hTpa2|LaaQ+kj<@4xzi4QQ|P$TWpH|!X3FpU?oSoGKbYI-~b z(8wigyuQ*t0~vXS-Ru7!|E5A0-*`wG=ey#!bE`CF%0O3d+P2#J&FYWpJ3fK#CuWDB zxeIDU9w|P@T%^h*IajLbrLSNlc;}c6k^*gTeS0Ls4#`9;KQ=78IC1YUpS?10kr{W~ zNN5>3TthI(pkwJdfF%4WmN`!=;IY;a5oscV277W3?=9ciFSD(50#a5**er0S#|^fT~vJB3kG z#p!!U6D&C0?a6ea&Fx4Dy`M0&0!qNoRh!eH77QXKw)op&b27j|5R)I0;Cfre4e{$g z_#2-`H3(#vm#>rGwbMe>CHIXw@oZq-S<6{z^~5~Zx0PB~z+s9-$p!TKJ~$4Yx7|oR z!hQXtTkzQZsvbIP>{B!HhJ~|44A@CBea}~x3tm|Ia&}3tWZ@HuP?i7PRCs@9E2Quv zk6SO<)H^82x70n+JjIbgRU|Y@X_!$9P*1X^b~aY8G?s?iBh}~orWOv$)k{91$=Wm) zMy`@#E{7uT%TfLV56j!r!V!UfZ5DD6#(YqJVbqXP=0GvGAB!eSj&-$zv&HkSiMewE z-j$|ntbflgStXe+8>>byl4!OA?p#jO41SCAZYG)ALD#A=-Hh}qKL(|ZJ%;xGjsqHF zP#*umz~lsWH=0qqKf=h0E%PIg?`5sFF`lt9eeL(2~#gts||S+^V&sGF&8 ze~YHRaC~yQDl5e}o~x8f4eXoYbKbV~geH2k7%!hJO_h0?6VbBKM#R)qKusAChNk1N znf&9=>#PNf*Uc84C7OKajC1vGm82|TvffR4eZ8$tMUu*)?=MCRU-X;}3rmO&_*w5; zn`S_ovWq?lEh&fozU#NazFrD=iAw~er-pHQ+g^CNjuA(k=ADkog_%f_0~2`Z?>U>d zs2|Su`R_7ajL9K!t}v`JIbQ@J4+W7J*Xwp0KR+G&<&B7{I5^uTuAZQetN@+g1TCGA zJ(u`+dOH<~xIoiX4v^A}kBMIBbha}gLun9UL(Is7LmT=k94=a-fPV2}q+l>)$o$V| zU1@$B)K!NJA`{Y6f*6;k6K2;IuV0g{E5~U09UnNPe4&J5hL4;l{+<*^+;$r5EPf1cFA^~#{Dz{?$T#pfk;{5penDIh} z9)+fMRc%GQGt^+*9Qy{%J^XfJ;~>t8JCZbO(>eTW!r=wlXQQWp19i!2h`5%th5rTU zaWQ}*n06`*avFoqh151ih5mZ89;E@sF%V~{8{seJnadvu)3>-w5_G=Ezee-16Zf)a z{!{Lb74b%^JOE596~tNbwKJ`*xticw{d?&{G1&pcyNxqSLuWLS=N^DE>cq z656KKjUrkzt)K@G6SZd=uO;D5x1L%93Q|63p{w=bF#FY%KhThzgM5shNeb#{91;$- zz-E38qW+|Rzoyo!hc4v)&JXEPPbW`Cp%^!T+h$aY%y)ROiE$WmbL!zWQT2)}VOyp^ zSSIoxkJ14zVF6ersR>Pk`F#D7Ejq5?k-M$tgZ`~_)o3A30f=O8#>T&O=JVF| z;&y>`o~qndRUa*6!gxy0A$S(=<_aT4@A&9tH;3*$))0!4Qg zoOlhV8mr$(kChmq2iyZk-uv;D*P#ldmzu?&H?-avEz1?yBM7(&tyMm|2;253paH zu(K_%821;5eIeJb#;_I*-&|+-O5DQa492?siJ0Sa37P@J#*;4YU$V3wqAo#CzRV1w zd}CDSjeoWEKd>u5rWjmyGZgYxu*fhyrjltWk2EK?njCy!@wt}w=WQ%aNSGln5ib2E zxlZ-Be!V|xon*^v;O;`VhxraC3`rj+Tm*eiVNk%VL+|o^bD1T@ZM=jh%Y7u3!l=HS zJJH2ELHI468bu3~Vr`Vvo#IC}~8rfi0SlQyA>4987->7ugjB#(myFGH;n1B_hZ6mmi zijgORHd=TLLuyk_hH?i>TJ8-f2u;Qtl@%&q5^5%9Mc_bg-E&bZF0*z z@q7P;``dLbmrKq*XYc*?`#ukm>Z%Hac+_}kXlR6rFJ)h&p`kC|{e|2EKk=VzP6q!x zaF^3{*KoFS_cC*{M3b^`Hn(I@bTqTJd~IoF;p5t8DT;%epX!>_i%Ew2m}I>#D^$2%-HT#G1wZCTDZhJ(aY0-l z_1G+-=81ZA!bG?@R?6lhy6QkVrjO8WMW*)|KYxAESlF@=eV8uD7N4N_YHe39b+iAm zhs3b)W`@UU)9EQDkxexH=A!@U%x%-OG5s()IQakn^Z!r+lB#4>7-)ghtBc7<`FtLk zcRw5yC2J!Xt-CD zKWy>qyNo~83O0AYb|1PO$m0|E_IWwazUJ*!I~gA-LFXy_$WruMss}&G3a&UER^9H$ z^I`fJhx6^;pZyDdOD^enZ;brKm~3wrueW@l4qp44eC6NV2OJ;h9W9|5^3;#K)&6^t zSvEpxxb*8rWACJq*=wJ)#m`odyzp{(;bM;5>+Rw%^li_*_|(RJ6J*q1>hD=U{PH#7 zYe!v-d=H)xn?M&2-!=abi-+)yK$mNv3&CS=9~SG@*MEP$uT&ebrF1wk%*Dljb6}D* zKYtkz^phTUfBEocg3BV8a*RB8|KWc}zpCPyCCK&GoO$57X=%5vwr;0gNY}Y{6=){! zn`5vq{;Dcqz@yaIgck^;bmy=4>Vu7fuX`ET7a9o{NmAfHYMki=8<l3pofQaki4jQhxK zuLOE=eu~6xf=~ZC@DL}la5ZXq5dCzs4-LY*=6FEi+c?r|P8;d`oTv2j61k^XEqf>Z zZD-k_YUBB-cK>F9B9wBsh7y?>$HM5IOUYq?rOR}L-}1$;V(je21B0H_i-#PB-bZmf zjNR%h8Td$S!Yr42^N-hJybe>dMV+_pRNJoOtQX2|&zlXh3|?M|$nbca*Vzo%VCIJ9 z`*|E+;y29?SZh4mR~Yv97b0goa^tBG8+B=OT+(qVWY#fk-r@Fe_S(GY;UV+!eUa{` zW1J}P>!Wg3n5KO!TX*XHNS$X`)8kxtoH)0dpq013t=Ae#=&))OVaaE)xZiO)i%d3x)8^8MsiMJJ~=-{1euHeYvX^8UxcOkc+v zQA?mXhvn(F*QYp_Sw6qrCYUn#3PzE;VQ;OociuW7gWp!Y_pTxFt&f`@Q9}9SN4Ot1 z1fPnt88rhtswXx_!=egle0!dGaAW<@uLH5{<4giwJQ>;?U^HY?8hZ~NF}J;Bv{gx= z@OQ9`K4a_z+r4yhKK+w&$f&s+6Y=Mdvqbp|`pm|Sx8ineM`=II`wo-aA5u{G6Xq&J zJmPs7DFf88A@Y`Yuf1$0O?bhtc@1yQ%jf#N>^&aV5xdvX74j(NRlU9S=sR;SL!d|@ z{&Eq8y*&^$W{Xy?Ff??cg}-!kKN~OMpPTmGR^GQ|Mh1As&hbCZDx}xIZ4zA7doyMq zo$L*1a=7Pw_4ntBMm+KTgAfdc)?K^v_em7{CQe?pFcm4Et9m!bEnk~qg^8qqK_)z5 z{9MY;{u3^SJOrwCmn&obz`#gnvjw)spvI1dG4JVcbIiIF(OC;Ciz#7s!P1eH8ER^hi*#V;mtJBB z*W)xTT{$5&d5Tdkuakdl)3`d~Y#jn!&iT-qq9Rh0Vf|Pz!sU0=bcA!7{lTHHx03J733F>g$K^* z`7^uD%uu-1WG`9|IL`P?LgKeuk(qwUS|ZPwE|^}D3TSi ztpoeNB1{iYKV+AAb;`fz#c)ujJ%%U5fBF9H{=TR3p}%oUKG*dZs4rBOBNw^BYcIlP z%XtxMlJtH_^r~NLJXv1}-ZcfUfA@TP6)rC!GS_%Jr6^8_^)qRRN7S`aL*sn{V{&Ce z9{2{(kf81;&`|iyc%F%#t{0D9ud})whxZCyx`yi5` zbz|BYDG7x9ihe6=@>2HKv6R8ZE13A#Sm|jV9}i`{6m6(@g-NANDIaY@Xp`Esm`Qyo|LY?;aHvh378 zV5xGZsjgN)N{8_%&59^ZB~*7Nq35^#n0<(`K8w<6Y<7ijq^oiQ_A9c3ZnMg-1e}K z2#ThPGdtKvITTHV^Ne&9jfe~PJbc(2Fb7kJ^*EfMPiOSL_}l^`|yS=>Mu>+Njxoh$UQ)>B!dYqkm}g=~z2z*xA$Q zX6^L8#x9p()b}aB?c5P(tta;_9=BH=_`ejB4s`rcnpm{K5xHr&T5@rb#UJ;NhPY54;d-)CQLl= zCpN+QnYEW`&_jh?M*d?vOwcVoWla7N5O{h=DFRg%5+Fka6PBiiI^lh`*UewW6OZqt z=d$iA(!gzYz}Tvy5TyRl|G3r)(mGz{z8mhOk!|wJ&^3MdM}7%po#RNk z>V{kYJF0fS3hE2?noJy4L_y8anCo)H9^9NXzv>jCTM)UrDtb__LTWGra_4D2K?q5% z4wiIry6~E&WWn$E&BqE@R_F|^=X~A71s1Ip`Jc$5{s_~nXn6VDh^0$DDI2wS`zRpI z1M=5$2!V$)7mihY9#$aQrh>(FK-5aOxr6@jDAF*nb(k>Kzy7MGp2eY(Rv7`1zr?CCxPD1}rxI|!O z```I?s{9Y0(*ni|g!4tk|FlEy8!N~2&O*EVvYuxcrNG2-CYnf#hCZC3e;m`6n03=I zoz(64RS`Ww)I^0LX~Q_7#ld#WfSeebYhp}4$&JWYd)kLiygV2|LCz?~m!~chDBz?q z&@eD7`2_0A_S?+t&g~2&3sjxg62}hRK70Zvv2IVP*j>32vgU`5%&IEEkiRi<`K2oq zg~suk)+jC$a)kc+2$rEiTm&($rl9v8DU^;Vq+Z*-`+}LfK>+*6Wxx`JCS>}A!c4Fn zxT%~Aezo^xn~b*xC!{`d9=7m&LZR*OIS87v~Y z9qncUjcE=zH}lc4rM1YHVwkcLb&q5WvN%4_169aOba|aO_d9+qZp`R*o4}GDGP%!A zy!|K_c_Ocx-Z4M*OMd@mlj-xvYc$9=)#nuZe2@pc5(3uRUNcH?fzxMrA?*1c3(=#| z$_qNEl678%H@*qOiePQjW%e*w>tN3BqyZ92lGDU|=ps9D|E!0}&b;BGeKoX|oG=jW zvP!hJm4V9HyxK`)===+~i#&=8Gnc>oGC6e0@BBljA455+zN#({o!Hdm;A7Ss;@6e@ znTEyVbt(dz`Dx>E)VU+MM{iWB%P;4IDTucoxb=vO_;`nW2J8P2n;MR4r+>UV0YehY z!b^^$6zB*w^4jpGSViVqjpE5DI)wM}=EM5dEv{v(H($ycfk)Y4!W=o=jAdo`^6 zx9K?M1*)PJQBUs}Rt#d(UQNlI7j9u$YqUlNUV6U-7cTO^u`L;rYAo|Wye$aVCcpaxql$&m~zAF$vvoc{ZE~j$pyUs6ODw zt8sb>7HT_bl#LqPleRTr>2HGf@`j%i&?Tawhsj3ZC!2Dk!fr$X;WY69Gk3iDKf^TK_Pidvd*Ew(8(o?DYn;#7 zNQ8~KE`(JUEK7iw#NMr|+w(t+g4LkD2j%9YtRSy-+a$OfZZk*{}!T*V+ zXILA<*)U!fM-_uL?To-+0b)sU(ulniiyk@g(?K)wc2bSh(M}zzNE1qiRzXdQneopO zmb_%s6*YU6g>#x5N1)8S)AUc_K_;)8-@VV(R8+b#{Ee96J;b|vg3&gI8{|A~(V^w6 zABBqOD+3T7slc9W=Zl)9ogY97fk`uP`w1RBbKV%;d4I45oH7#ZVJ$QuO+Z7j(sk){ zbBW~pK3~0=PhD$^dZ%t{c$%hUMjPiOpMLm1nqww&oA_*0%cjr z9R@-+870uuk>3l;*rECT+g10+zE#WVo=kM9JbW{jniJBznLqtb9XJuF`4I^@f5lTJ zc%ldOv{MMv^R<)@$(Y72mV<^rCTHLJ&oD3a4Z=^i8`#Z&_NJXQOmb`SLX?<}nzd^X zJI%&{^F>2-x#;Nkc=$})%C1`IJ$}!%Tu)!_P;1%ja7WJ_4SRr`15}P9ZE5IL&!R0n zh%3StyLge`kXItAbYSYwh?RC4Qco?`8$j}5 z-7T1`Y6>JLfbgDiRWizEK5qXTfTWmzIZ^I3{0*mE9wne%qm2?M_p^0(wjJBlD=jD) zp|j8ep7euqMisi!h;$M^5})`NZ~mw2Sqw(T)?EFgXFQ@@7xAE~uglHldW83a$&Ra% zJoWcLz)%j69W`Lrlhqz(SDC~O4Bgh{ zmfk2y#~1>q^HbWURD&hI(?1{blB6DTN+KZSlV#I=I74qkHtg{WW!y&sj25n?^EFs;M_> z>d91YiZg}5$#uU^Ma2HBW`1>aY4V-VXung}_DIDZpxuah!Dfbyi9xVcR@|PM-H^O` z`~F69N4Mkkgpc5?=u22=Y`Oa`V+j{ouE(9k$3bwJ@ZaG!*x9z)96U^vq6dKUiC*NLnOl7sBBlr!;7tPP-8?w&qDD`$EpMc&5Gy~L}1)}r<-%(|Z zSv%mK4WMxyk4M9=OY9p+V^^UZ(3xR;7*J_TNY^=ab&klcACWlwVm4U=f&}LVxGgN~ zE~;3&i_Z#D_y_wu(&pWI8Hnb^IKI0+EU{*<5-DfcEJ)bU)!4Fnaq`wfyCC zK`|%L))-lo%@`f>~e^a=HmPd zIODWO_8<6BuAkmIuYvy2Sd~CG9;R;VsJs1Ft@$D>=}#GP<>|rN<$m_j0n11{wW@v) zN>yr$N<)k(#0TVR=t38l;nkL$zULXQ9RwA0ZF7uTu`?g-ZVOIDRCGJ0y}7ZO;PTBs z9839z64*QHx8n1SeN)PRSGbfGkBV&AEEEZE#Fcl9JKFh(+X>)s97?|#8!067Jy)`R zEE%|hzKaqB73>VCaL9e{ve1q(_}??Ck*|pf>MAI&fGT`+kmj_@iap)afn~+cX;SEc zruScJjXmq%bZ1?*B1*|jva8>tl;D2U3e4k0%5+lU9RCnwiEFw(-kqX=5H{fa`+jwGwxh0#b`btzy6^4`nl`FwJ zB4zvj*C?Fq`)}fhUZc3UF08WSYJ%mKT&iZ)ZIn@maAO~p?j2Ki|Bf}FZ_#PB2c4E#;4rR^3DVCXA?bv3(rjrVP{F$tqV@!H5KhuuG3EH9_b&bG|U+4 zxyh8udUTz7AFa!~XS!arGe7HIZy~*I;`^Qh?kH;U?i(2P28|jtsBD&p0?WPEdk*Z4 zpgZx>2Bab`U!Gi(ZfqkNZ-x9FJI)_^ctwzdDU@^E(|(A{#OT_RT^Sqb>uXA?+|w`c znk*SKyF4nuAaX~r+|Q9WON*7+1lhEIuUw|nOZ38RrhZy}Fxdf;uVoRC2zmnOlEG z-A0f+P522p0xm>Oet<{|ezx>0b~kH*(uBuzTb~TS2+J_`G4Ud4yt=CI)o#4*&mNMi zvu2dDS}xHG7b)xiP)-_P1jK=_0OPR-15=zV1fJ=O@6aWF@JU`{GzA@4JQ_<)E9CJpo?-`;P zvvkQfqj%du(36K=<=hu^Y;mItMYh1<<|ggp5d zL^T0BdKsyVW1{KnV!s+jKkr=izC3CmdLbETAO!~nX4#M4FvcT&ZB_#PD|sQCK!XAZiRe5t@8+yzj6MVBH*?H9JRH}i81jaYdl7#`90} z^!T?6h|&7UCg+89ZAdrR@t*WjadPT5?jNpvr20tz%{{yo97K*7WxmKQu@mS_jEp$e z;y|G4_IP`_@Gba&6DU}2K}LfUbOGtX6%2SFo`Yl#^(~Q`evLwu`xTE@^ONp@@XpHI zF|@&10 zj$a*htm}LKR~Z1e6r*=clXLcvZz*nhlbUQUrVu`6PgQ)_RI7ImT`qc4-&?d*V1fAG zdgq?QG41at0qdg<9xoLz`KSuq!Pa*LAzz4cKu&v3QL(C5-#|l~qDdRIS&lH_&Faph z%ypLLHCEt0BAms0-|dliSY+JAae;BUjV<$mZW`3+_zI1^`g$7L(o0RSQO6qv1EZ1N z9F8No;Ci-;(F>9WP%V}yz>(mtjdzj)yQ{Tvy z`a0t915Bl{mN5sT0}J7QbMajpUj{pb~xW^TX69hLkyu^ss;R{dBmkrBw7d zZ{H?Ex`-kB59&f!aI+!n&odQE7r$dk1SG{_pbJu(l-Nx0?{0H~x?=RRYkErAV#S^- zCeNNz6D~h63;CN!4*x4sordFA=h@QtyQ|19^o#a}~aSJKQ`?v4r^b-9L5iYW#~%>qkKOoYQ+h)0CN->$0Gx2B0*E5=@qx{`&7^{v*HLWR@0@N2ra`_@R)3 z|CnbqZGfg0ZH6ECr=$;U)oQzVO;eghlVpB|nqbwj*?fIqJE9AgbeMVGW_R|Qge)myC|xGS%s&h> zmP0tO?s21HKt|C=lz;|o0&-omv^eKEHr#xNFy1@aeHH1PF1G-?!H4ipD)@=pO_dM3 z#j7wK83g>Asp&gZiJttxO+er?B(xIVdjD^ zG**ClwS@el+)<`X&-j@dG$l$8SDzX@lP2osD63O0phw3bAmkEST7Im;%Dgkl0%pHl zzR-)d3WX;!7qD{1VtG4tPF9`+K`^OoXBJL+%-f3$_$9{KYEM(mW|V z<(t$ntIP7VG6KuJg=Q<5yve6viZ<_o?9}{h+*Z&x*%>&2(FGXWrpbB!37sasQ1W8> za_A#&yg*)t+dUz_V1VoYZG;6yoHffJgk)>t@Fi$x!k`V4`) zLrH9^8+QWNBt7`SUqb4;%ecdFq#qrSFMv4j`utJXSk19^uKH4W5%!Hd=wNk{MNwq+ z>h7Hukrv0FfyR5}l|Y~uh-pobkenu_16Wd7Nw}KV?fpnb+O%=Iqdzg6g5};X0|mNv z1)w>H`!fZC0tTqd6Vd+8*OlufOp)U?)r1sjR334c4~R`)hUaZKK3L)g9<7}?JL!i3BFhm-Y?L1 z~m$XrVddH?JuRZt8?E17`vCV@senBpT)I}7+bLVlfu zO~10m$o+dIPP2m1Wf!uSNge3+jC>qH@A3F%3BT#mB-2#$TVQ$^&Q^n`3_vQ|*XhzE7b#LV8PA@h{B);KYWHuZ@qnS1fWAIxuJgQ-wdh-YSHnf8ANc^;t>>_Jrdv{wY z`mmf=a)tH~Ctx#Y?k_@YZ`fq%%L^PBUN>n8B@!mz$xI(7hkQxuG$Ip?7Cw~0IIEd{ zC$zL24j+lRlj(18os>^cRLlo-6y{fB)#k6ajuZKNOn=Cb&G-HX@5$pyeGqwqM(N(& z``}|n=y{HcVAAOwGdMjkj91rmhg> zIxz;k7tFOw#}f3(WI5#lElXpdi?lUr5T%0f9mtZIe!KVpx! zNjV&(P$wl;w!ClO1B0dP7P*Jcvg7Qc<^YVyj!?85TWa3lyLL#6BnyHl&$VY=G`3^4 zc`MjHg#ftlJ%FTB-Xy)$aCE&K4FwsW$M80!kE~N^bhjbv%5BJ*71B+5kZH;Q;6KCo z(B4zHrW>cgvB#Vis;i4jx)-_Nt*oqvly8;@cRsLv( z272l4q8qJ&Axh|%^PQV_>VU~3D+++*y+j2&jjg>>4*v@c7DHXyxYFfd0!%avhxc{L zwaqp#@mY51r5qz8tz5OVSL8Ck=N9_z&u@8U&c zXqCzVGTl*E(g)#oUz>#DK)qLKl5IBcl-1ys1{Oes@1q8?T0kh`QmD0vT zAvqQ!a2<}p*jEU0tC(D=z`1*1$|C>h4tou~IcfBi-cRoU2o~X2i%=Y`%61GPK8$(L zttc?F{{#@zoT9C5H$abs2N{n*z9af-fi1g#qw_hBhg7TCBV|k~(BL6}hIPXYvTGx~ zRhf=bC;;=Qp7SUk+c2%jOvV)K%?TB!_K)9jhtoye>|!xZ7~%ob|KHfqGz>>`zDPVJ zJtLZ^Wpcei6w`bCA(#w8eO0y;T%DtLW^fc8XPebnkDAl*pck>}QRSbTSLe~PMgobE zpJnAJAK;;JE)RlwGm7CNszQ+1ZZ5hZ!dj)_RTb=`PQcA+U0z2JyB-)Zhy&u8e{f=H zXh69Z>?6|wSDz1W2$ohQ8u79NcwI^0$-o^DS5emZo9PI^aIu^h<5$%j3wcV~;12jX zX;N*(XG{Q$mwdAHux^OhH~JpFw0kyY(o6s(SJ%A7aDI~x6z;%(t2xq@|)-_0o_toMbo#m`l zg+Y@#_jHIuHF0*$e#|GBt0Ox;?pMC4$CI+}9^#OUQ+eg0Ype~GVaykmlJ`Bmg zL#eO)k!Y8B0N(jG7q=vWbu)4bIJ18GB<1?dDG>+Y5P}hswn2&fcmAGQ9>8lVC}P4WLdw!uzJBYOyTz@i#Y1OSp{=i!wHO>XUbZ`CL5 zsfNcj4x@LD0^u!?0YMBmq%y+0eA0+WAbf_{woTij`(77K0gDu?G+RFbG5#w&jWcsV zD=2GpNbYcOz#fs0ZmP@U;e!R6b(U%O6qFSH{ym-;kw=JAeIR?3g@Rj*i-#@A7%tTIktM|VV9o@YlW>Cf>kO~Wx9s;F?m z7>%(F3$>%{N9(F;Q1n=k#3A9@a8PW@!9ghwMz4T+HYW*37O}jdeoEV2prlR9i9@qd z(qTVAu^eRfww9U#saa#k@dBn#hl~wI?&E8PiQfPL(@UQ% zaNNjIbi`8+DNZ1#=%E7EZbmmN`K3(WBXvSn)Bq^vBeC+W2fO<`fWn(4X&{JQIZ)RC zbVzV@h8@A?!trskz=f*bYaQ__46tpUW|h6Cg$qOKLs^3nKbXV}u#NwEs)O zltcI3twac*G9c>};gkc^mj%(+@G02YP9spAxuhN*3Zz|!iT#t6SPAq8LwjZE!e@B? zIoiBhm1+3a0PB^P7vK!zulnglF2LGtEe z6)p@AlR$>V#Z@IiKau-aD~xKS>v!U@2;hPPtAC5}o(8exQ?R9-Ms(yi&Ax`t!P?Lp zuvf500}tEhGul+0l=gMVSiK{?Uf-G({Oy@kfVvj?bw2U#hG*mX?E@;cJVbJPo}UgdAiC_skOmx&MoJsAEzIG<7=->~IWFnxglVn@Rl2irU( zhaD`iDd{%bd=3OuDS=*fd95I8RIXUyV=NTzdSw*tTcf!8=Za)-iXqpvT- z+`@L(jLI#ug2_qXiyh}mg<+I~|t* zeJr2qZTtAGSfrPlIn7C@E8sAuzxEop-QgZM|02hSGf=Lg#d)C`U>X^v+QW$-@LZcG zRET)FXjCG=tS0M&4PXm1WeE(?Ru`*$jo3VI-= zYdJ5FKj>F`hiJd*9SwN7(7$HpAg81X8tn9RoPnU&u~CwYHBf|sd=TlKa%n@Y zV8fVID1UMs5`FdVh{-$s@*m+g1YIL05kt&iOH+B&tdSQV|A z{_RsG4@W>pXv%&kW0$51XuFKLKKwmk8^(Y*i$X2FeA2Aj1abKjA>yh{6Z+%WC$V8* z`yZV;;tB{C=RQnF!uC0h>_>LJfa!g#j+|QGeC4#~yr=0^%c z=MC1BocH)E=92hSH1~{yZ@y}#$BeCI?Coya<1U*|Ea^)!;sj;q2Bi$!o6iJcU)*1R zwHmA7tncHxy}+1OesdR>Jh;u`3(c$BPCtM1g)V!}79;1S>~^@7LAE9P8#W#nS?||z zYwYoYZHRlG)2zvK%eGA{yX_v!JINL)dN6OND_u4(!)8)hupF==Vr&(ktU{&k*OA6$ zH0xSeJ+28VPCz`wcsCAf$a+Q0M`5J%%Pq;2AoTgOjg1wZ$9?`+ZD?L1r@aGrH739u zyQ}t_wh{js>ba9*-fm+|M+ZGOS~Cs5-?8-)uJ)AX*(Wvg^(?R0g|YSm1FnX)?g!{j zw$K!Ih5Y2hS1JsXzeR2e=@F+Fzj0=8ulp0ysn1d=PoCmW;up!58mrcs)`0vnWNq9R zwqX%OpBXD8iFJ=U5dQ@|kt|X(^Kh&|R}eNTD~kMH`MJTjf1fU?(+Me4{(a{g9aKm( zD-pht4Eg2|L!(z)i7v{dLj9Zua0y5h8@K#QU8?=QEH_2ygZJe{bx4<9c3N-Vl)EPd z(R|`e>GCE;D!yS`{WlTWoYLfMS1g@-+B4&_2Uu_MY5})@P_2BS1L=aS91Rt=8|wR< zH4jN#)@eYfG~q%ibqbNJW5%B)C?!5RIA5?t-l)(Jn_Sj2V{lk^D3;DE_RR27xRe~A z=uI*jE)&PmQyF?R@;(3;EM?4Mj%t+eJe<6WQ;u*Bpipi!XpeA)ZA@D@5UQCHzCo`Q zz$aA*(@vRRFVEV3C%{E}U}!ArDzfQR7Lm+2HnvOgk(p7l;nm?Lvh63e>ZH=Eneg>;uGi?Wpg}^QsHB!}9z1141$9 zT6+OWE&;LK(|_3HiSX;z>kh3Ix`iCskT!H*BPyInwUVt)3CHG@U$FHx2|}(*$!2mo zEhb9IT`{w4S891_4AiR|@L>V5J%{-AROn7>cg>Eh$?!;v3H1bjBQog|AjZDd8|djT zPtXx%yKiW5OmR+@-th8*Ob3GdNun;JBin@O;EG!LjDt)Sv{-TJ;U-Y~4U6^#tNNLy zqJly!FU1hV{kfBXu|cW4j8vy&Rp(0~O2y&(_PI%N`ycTol=KB1Sikx5oe!>81$4;J zmVJy6H*u>ITOp{6{M~%k07=Ve;&*s%{CURT=s31s9XRWpdrVlryNmSuQb%v9S`wW%e2qRhHoaLkck17y znic-$&>rEW5GbOW#BqNmxJxsrd}EQP%!qS9R$8PlLW+>Xr;IqROiz>EVZQem>;K{J lv;O~2-$@{lV)YiE7wt0tnp!jIfbQ-`igK#5<

{|84Mu^a#Z diff --git a/Riot/Assets/SharedImages.xcassets/AnimatedLogo/animatedLogo-3.imageset/animatedLogo-3.png b/Riot/Assets/SharedImages.xcassets/AnimatedLogo/animatedLogo-3.imageset/animatedLogo-3.png index dc6e5e75e0e577988c9430870b586230d2dee0fa..f5e02a9bb690122cb2626cf76f5f5464f3c927b8 100644 GIT binary patch literal 23577 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 Mzfe~!kvH}KFIEilIsgCw literal 9656 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 diff --git a/Riot/Assets/SharedImages.xcassets/AnimatedLogo/animatedLogo-4.imageset/animatedLogo-4.png b/Riot/Assets/SharedImages.xcassets/AnimatedLogo/animatedLogo-4.imageset/animatedLogo-4.png index 15418f9847700747c55a790c7249eb80e94022c7..dfe41a33001bf374feef334c85a9134aaca81f2b 100644 GIT binary patch literal 23595 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 Gy!{X4+H(&8 literal 8221 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

-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 e?&I#M{S^-dT*+Tj28_M{00007S diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29@2x.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29@2x.png old mode 100644 new mode 100755 index 89b7a290c4a2ff02cc1508f1e5accb84528f03d1..1074e04a92404d554a524102c1ebf2b4a8b05ea7 GIT binary patch literal 2347 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 delta 2204 zcmV;N2xIrF5}gr{8Gix*003^;-G2Z800DDSM?wIu&K&6g000SaNLh0L01FcU01FcV z0GgZ_00007bV*G`2jC103_CX>@2H zM@dakSAh-}000OINkl& zAOPkRm?cm}0DtZ9$nISG`X3)&Z7etAkO2f>hM-BE%;s=b z+1h_2{2+)7q84ao+$tT-kC$`@!53dr*k@GZ3IEftF5bBGMI5qCxAX&<@%IjyW0~!U zWg^lrWt}99I8z8Ylo_5KK2p}R_=TYR!j)3~=kxo&{(t4~62`X~0z>CyDfiwuAkX;( z1ONi4VnVS(Adb?c5xeWmA2M=tm7~Xt6L2RVdP!&S+Wys#u5Zf<0FbF{-&{*h>B^|F zb#{dm5=adzS=FlOxdP2B`OQB*xYB0+>GHHr)K`MrSZa3l6`5-(rJ3?p_e}(kIBPL~ zIcRp2uz##OV`gDFY+hOUk|6YE

-&ZX7ZeC*AwFEe}NQCTBnpsfd^gEznHBVJTBGJSl~aICG)5Tvoof@bWsVsF$e zR?XsqS6}oSlU8Ne$jx_FKU=+fVf^($;v$OhQ43syAl>d5K@d$DHR>Th+!7{mM%7Ey zu?SrbTgyQc8HKW*jl850yTe9aMdWsK{_W8d8de4ugb_rCbmOg(VyjyRz=uuqd|48Z z%766P#$_7t=%Kgz(5n%IC#*68a4~2Qh|0RtNkX4T14#_uMXY6 zco(#}U;-eZWvTI6Ha?}5hYF5n%5B1g@RN8oT3-wrV@9#0JBxm!&HTJ(ufSF(3G>e6w9WjyX4#6~Nx~tTrAS!~TVWdagS-1ks3C2{vJdC+gpO?TBrtK2 zc6cZyKmctt0Hn)AOU=QmCq&&67(w{3}$wp#x@p&hyeirmm(Ez8WMyJg+^%t0K^bSJcJMsgcHFf zkO(3nB}TZHvYyB&1qLo0E-5pxmU=2C3c>+r1Y#9oF9{Ju z2m&rrQ>C=Ob9Z34HZf*0WA)FLYnPXjS_uBXxb+*I_0bjbZeil!Xp}NH2^`f_5OI^h zB9sdmiDaCX`%KLSfGee3PeLX*UkGa#=UF>?u3q9Ip7+S#F)j|*4Npj!(|@cmWr^T< z&58v}QeH8#1C46ko`)({d>++mjYl8k+~Rn}z*;(HzAq0B3Gi+LW83Ywh?;qz!RQ*kuol~lr; zti`-AeT?X>tfxNj)|<)BUw@aEY{eZB1)4DkUG(cY&7P|q>Awnk;d2)%hy;XOrx$7EF{0{ zq3d32R&DUkOujldd{o(u`0(P+00C?;*H7XN;>3zTQ2~#5&v?E1uYV;a&t_hqK0kU= z*`-kOQd`YS!Z!0*%9-HOA(^={QhWbBZ^rPl`*!A7Nq6>IBh#=lVV5VZp-E?G>eOWJ zXbB?NbAqEK@8)0r-LqUBJT3$fLs*a9hhA+yUgNU{tkT|En~>K&y79&3Tf2QRG5`fq zN)V^XRA55K55Ro(T&o%Ap$Jdjt zYb~W*U0D0%w|~3vv-4Kg+{OA|& zm`?9G3*6x1Z!XolD_XByJ%?cAVC8%7d`HoG=UKiR-2CTlo`3K?z?EG*iSGl>ge9kw_j5+t?@7r0c=de)_4RUq~L^@FunMxpathHm`=aI{T zfX6yfB#=DiI?*-@;t-5Z4PW^A`JPTp4cgDy*DtO{)RLYJIb(tsX(o~BytlgG*AYZH zH4~*Q7JSSqZhxzL9((h(nbXtV$1hh))T9H$RS`K|o`wLd1g(r>OxcwZb%u=WlwBbR zEd{NT?i|T&e{vbNap9-uMh;fs4kE6ZG2XcFU6l^B_$g3(Zukh7V!>YvQAs^jay7c=`7w#_lZXl)9OcoLQ9d~!Q001GS z%lu~4X|n(Un4?yK+NMJLsa~X%-n!pdYBp;vk;-f-Qy9)WMF*i>yq$piUyJPH?&I#` e?&I#M{S^-dT*+Tj28_M{0000v#1!Q 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 literal 3673 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 a0RI4jNX$^Rx!!I70000_CX>@2H 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 literal 3069 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 literal 3069 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 diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-60@2x.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-60@2x.png old mode 100644 new mode 100755 index 8b4ed1d35a561f9aa2ce67cab7ef19b9be7350d9..475467f8de574f2c3a83bbdca5f01dbf726ec2b8 GIT binary patch literal 4821 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 literal 7067 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 SJN@u+29TFgftE@cef=*ch|EI( diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-76.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-76.png old mode 100644 new mode 100755 index b5bbc9f95fd9b03e08c0c188df2d29837af2053c..99615b99e4ff014c2c2ef52f11b5b1b5976feceb GIT binary patch literal 3045 zcmaJ@XIK)98U<%Aaw4u$3)9?*`f2XmGewPDU_&c+=E$8UA(iIMaFZ!$r4o(|H;SVy z70taDesCb*&0K69aLSokXywHmWggZ|Ui(_#T64 z5^}S}kqCnqf8Q;RkA9n17^v+O9(#c}KGrxysdOE4r`t-X4)^(e0p|!i+QN5qk@$DS zWnAE0;UiJcgw1WCfWHDn$r(nqE5c2E(oKDK)0Y=b1301A#~S*D{UnGkpWwxfS7KC~ z8eSP3*Wi3sm53?+-TO!1En^RgcHJKUah~)pGPn6-M*m%8CZ>6xJ2!b#9w=@F7n`x- z$aESs_q+dd!yh4YxO4|P>K09K+_iwQuKfC0!l)2|g-CRYia{K>OA+a=W@4I6z$7`> zN`^Wa9wxP6m;TacO}(!gBUtAbFa6v;zK>Vw!=8a13el3z>N;O8i|?MgEl3LcPY`4# zW8*JH4*^t0fiV#D+K$<)Wb?MbYPLNtsaR~}U3B@4EqLOb)oj!EQO#i_8NN_%J{Df& zjX@)W3NQ`kx>r{TkFl--&6ieLPhJ3(sLBp+g@qCgC*T_7jmyd#dL_KpSIzrpK0A5y z;bE4QQ=$<$i<{?pk`F(5*#Z)@C1Hs9Jcv+ZI3+P^ZzKN{jMZjS0D@|1)jFzA-J0+# zetY>jRy?*OMK(|iLp|E3F=V%t$9%zH%&1^6pi4@80^*vYr^d8Sf;q*SYLH!gx6N&wU!wK2z7dg+_$;n;nDfa03UB#3UAi4 zt52Q`@4wYk?zIqO$p=Gp)n~h!4gXD0i6q+^g?3l}P2u=z^RWhg>R4Vv$6~i>v)@gLi1~%Rs0YC<7Bd| zW1u(hug=-`TzNINM|D|ql&yg)4}e3ME$)#JAChbG3KOaLKCauc|)Gnr}qePVToz&Y})!=7T0t9{*2t~LPHTG11>@_%Le;N1QB)mocC_1x?8JP1;U4Y?a z-aY?=g`CziKvxR)UI_aYcA?{Oh4i1^Z$arj%z8ad>fZkTU3H}Iq!}YLHvA3Fq|nB+ zNML;+jQ6GqCaZJMcucwEfz~wR9T4qhVEyiDPh*A>Z!O}~k8p|{>8CDQy+v8QgO_Ao zZH>AKVf`bAHrBfJhppui62!)hS_>IW*wRjHP=r3Z!8EuL_@+Rr-J#hgE^5kNMsM=9 z%AKM=(4QIZdIdjrG^eig@m+uALsZD)wZJY^&sPkv46_k3w=%izSXZ6*xmKp(QT4#8 zXv>p@+n+{sOCR6}kxPw&VUXvxO}4?M_Vcu-rWbDUW*P<+Bjjra6!yFmW)jgcf!E?* zT4MWJUij{3AMDy)lM?<$-9!}fK-A<@&t44SHoJk{CRqa+ulB`(R9Uo4EJo2!pdc7T zIk$I-XsNbmf3LO>RS)JblhZaj5&wj zu8z#;NjnBEM4~Gs|2%Vg>k1)ZzSneQu%sZ)gUhkA(k7W;HRDBdho#V zr^F4@gg2i%j`>GUf8Bs&UivzJvHc!J5aNJM0hmQ74P!A$DGBY^>%vgMWea~O9S&oq z2_6Ph=?%2iWRRjq46<;5&%Z=zS%wUC0ZA5ZhTD68KK%)ou5aIdoX0)%&lA?NrD{6IGjg6 z%z@4td?w0O`6;ygcI7N+X|xe@&4uY6LT9LIhvzI+e{2A%@PfQSBDq@zz3FPjqLN}7wRWvJ8+@3xmQfmW4{c@oJ0#3L@golwoK|QA}};_v6v-Gd-Nz6J9Vgs zms+`eP?fKNqQ1}$XdacuE@?X{n@rCQ!*#&yAxFZ60GdSmHhmV6PeO*TsQ_8gO(MFa z`Bv;5vxa2XGo^x92~XjhLu`C|9tfHCX}a(FkS7ZV@0zFbyp=$YD5z9#L=_gwoH+5t>np~ieDfu!XK1=@#n?BuCcQFxaM&P1jyx}2q@S+pD z@;Wd56F$PycTlAW3?bB%Kk@mqJ?my|)Zj?boTw*wogJ1Oq)H?BTgpm^MxE&9&o-O= zVjoj{P@U!g^sNVnX7#;P>Dut-9=~}AW3f_>i0`t34I|qqqWy%V3jA% ztiPU&poLkZC4GL0k66VL8{m7zK`f%~9k)+o{oCkPG4=>4VG>CDKz6)G*(P)Px#32;bRa{vGf6951U69E94oEQKA00(qQO+^Rb3=9i97v_Ryg#Z8m8FWQhbVF}# zZDnqB07G(RVRU6=Aa`kWXdp*PO;A^X4i^9b3SCJ=K~#9!?VH(?T}2(oe|`Gw+ufI0 zlT0SF7)$~&5GW%MC15I)7)z)?QCMPGR>_0@1(v+|Wcg%SmQn=*7M6u57KjLi24s^Z z5HijrnVHOf@7(q5TelCFCCf}Q_fEVS;Qp##Zrwh8&ZmFB?*8@n^g)zT_^cZPp9AYa zb|5>D9mo!32eJeCIfrD|dA(V+j=wf`W@64XEGjZgo@a&?q~J?lhyV$g(>OUJ={;&X zC&dv$8xAt?!{;A=>E)+i4ZQH&CK28fW51FBwuy&UIcYT6w>vY~t)wnHBx)@|_Z;t` z2Opa}erB}_;wE+QdplWiRhLoU0>_Jy63W@wgO2h{oT+0 z@ct_&E?zCUBRhQGPFR~eoyae_M#-y3lputz%?{ntcMXr(D+W3C=EOq}KDL&c(vcoK zsI2xcMvQ=28H*YxDx8P_g)~~UD@C_P0kTs3$k2@`QNJ>f5B>D9vHwi0Y3|-C3rD(F ziw6Rq+?r?Dj2KIcI!25Yx>LrIM?#qu?j8B+`a`$rcnE`V@`LHM)}HmQ()t;8<%Nm> z@uI*C+^TQcp*v@n3T~}eP9+3&INp1zzG#K+!(-2Xcl1C`PPBEMwCj%N_-m|8yvR4* zh>{Bnp#&pFVa1#jACC2m#QPGw8jx_(T$;9u7??r5OJzkT^dB96(F)wQdJ;9+Ehp-8 zh~QP0N)R!xadJvfC05v?bF^iSKxbyDfS}Mo4rG}Gzt1d-A-6*JdM$xU;eA^6W`;|;WP`Byb@|PbSu3B4(^Q1Q*pYOYI4gd{Aw^=Y#(8tco7@nyGO^Gz>GrUZS# zt`zL*qE+ou5^aJ6jJDmkqwwX%bw9CCsj@~0%yEB+eSzLgi!X&JqtrVJ`*I%f@?Wd zkfLx=cMP0)DIq4yZie9bYRwb5C z30g|fmYk{?IyxuISTIA^jywT#BIXU^_#_Y*4gl=X^P{lY-AS7uW1Jl0l?yk@6ZQF$ zTTcm^%1KL3)d_u_lLgF~q3cH>0B{To00AKi%Qm{kCrv|MK8>gOl&cYe0gV8FMGOE$ zlr)Ab05tX}3_<`vfqZ-eLdg{rvYMtWc?JN8m=lx0Kfp#*b*WD zw)v!|P2sxeRF^&DyfJBoE&`O7;*Cid0AyAKfQA$zU=9F$@?p?69L_N;&#)U5(h6Mw zpyhxZGsv_{jSyIbQe5h)oOB)MM1I9HCCtmL;FHh|eFR8hg+{`F5hE~cHLw6cO$ z$-Ed(3p$O+%wJDdUs;5+1{5s?#qr77iwoSr4BgCiD@g>f?A9rO&Pgo7M&Lx0Xq=1? zvH}kPx|QTc6qg0e$%vnQc&vK#9Kw&yuejFZGx`L?IK_*CqFV!itP}@;vS$E5oR z2y6h@tmih?I$3b4CAUri!WT;JiPA+C1SmZ@mG95YDMmy|jF)vz@}i*ZnHVuiL3JYE ziF^j3p?J^6@?=DbPeQ-!y04ZmEtCZ0gGb)6T!&-WekBV4^LCj6O^Z54xZ&O{dj7)2 z_KJBjBgE4Dhf?C)Taz=O6pU`w%j`8`?l?PKMs zbLSPai5?>KJS zvF@9DceYh`y|{%ma>8?@XJJH#H|CpdXY!9@e4;nfP>+(jbK5>fMoxurx#c{qN z)=8a{`jpHkzlVT75X?Mts@Zm)d*p?oT?1X4a~si<4KqV`$*D97dwrbklbRmkLHNYa z{}lS+#)UKjd(JL5%Dh)$4y8e8`gZe^i+_9c#f=!QXKMx9lbia~3;;kslD75>xQn;MmhA2{oD7BG(7_m^29Hma!hAqLY_aPB7_eA z@Q{{Jn{B9CtUdLsXEv@U&oecqeCvVRTR4~W_Dk=*`>*#mAmqw6x@YLR+jh5b;h%r~ ztY>?l4oCnv_?=raJ?W;`q^kASOYePZAO(rP>&JIswrSmMd~HW-uH?jXw)GA5?7wqg zvn?(!l-mS}fdK#t6afPWg@l~73n2i2fPs(ne7yP`v;W)s`bT=3o5~1n6J$(K0l0SOoEazu#}`HM~k05nbn051vvAilcv#9-#GAAM7hnn=MD*?5~E2lPCAB#QPb zX$CP1PUTp6>O^(Mi-H)h=)4lps2(^xW_#3&O)%;1^1Ju%Y!jr$ zN&9GRS-S(k6S zcmK5qu4(y@I$G!VlU@{@sLV_oONQ^T49-Zgkwo8m?p|~a%A{iWBFXp3LOPAD4Z!8 zs+pcYOC&A(s)R=Y?Y3VCr~PugY;7*mn`#0=a)ys;T58^XImv_%Nnb3$?=a%xVMLq) zAGLqsZ<4*p>R^x$r$~EU?1l>`qSAyt{@VF)kXc6@@iL6~e@U|EMll5o*c|=*R@k`n zzOQsP6?|B_?AmYmI4u@W=`1bQ-!t;rcl?Mn(aqZQkNU}(^wgkCdJtv0xe)Q-)ws78 zcIVegp8g58poVzx{4{#-d$ighZ?x(lwv$@6SZF>8Qk z=;JVWq#%HoGXO4<%3&Q8EozUq)XYhW344!iwTyY{Gjea26 zg11L%euAfBEGXG_Q;Vk|m2)>c@+vxMk#=>VyZ?O5s}VykbcI-lj*X!kkY?|BWZUg|`Nl1-vts(aIrn zuY32yS!bZSRvb!Z?vWlzIuOyjb>tuz=Ta)Xg&ZM>PCh3jxHC0#c9?tYug~6Qp4_n+ zG*v99Un}6B1dS={miMShjTS+IUV)q5%H+&Ao0>*9xjKjU#Kia$Mv1g&LoQUzTYRj? zsHcd^%dg%ObRNf2QZNhB@)4&}d9EdCSP1j%es-n9CZCe9mQYpMpyS{hYChthgc_!Z zoK7|+NPWB9K8>#TWD9wvrl(KlKkysT(Beq-mvzrN; z*Vh%B)STLCYVs^66Ah=OIr90{b@0T$%FLwm?0To5n7uwl6JspXpq*5Q2eAs#e4Svx zjN%k3^HgP5CNdu#t{t8k%@@=j`J^f0o?f}pkhTY+%4D{12hK_lsE)rdvkC7wG5W7hMf__*~C|tH{-LVwB(hQK`ZhvsQ`+;y^ZVVxc*o%^J5$ zBayo6mQCJ8w9?iEctS%l#~C*;)sHMQ;|6O5LoGp|{i%-ZrhbSmneS~4xEV5nF4uAX z+`#a=B0n1?57W`emxnDB%kuCFTGmfy6v1ltt6o+u6(Z9bfx)RrHqR~oLQmGd~)=EiV z2r1U}hq-F&dFEdr%ysj^$w2pwm40Tb(`W<$dI|-6h@>XDaL}x2a#kn_=KFx>JDq8r z5eoZEQ^~$2T{5D}&GD`OWsa!7{sbSCRbX>*C?hLVI02YtsgNk58}=9CWLZD8o8Rt= zeg4V{hwLcp`Ebbh+-_rGA+zr@-9jfCK`lY&|MZAr=ui|JM!mm-FBdw))bcIa`F30N zz3rv-stb{k*kXX?7x%e89E?P;ZnA48>s+~Zo~0A!@|m?G{W5K?+Zuv@zH{L98H&VUG%eMoT?M8sJBa zC<)i8+GVXJpMRBtb(nxO@18VrIA&n@1?C zm})ns*VevFY+nw0_k5)hXAD)w+1(1AiS)DY6qnC@Y5Fqj9H8(2{z>}L*bi;Tmm*96 zGZu{NvW!jtaQRc=vTI(@an_0Ky&+F4k|`CW?sv;_758Ivk&jOcJPG-tL`tRBmFBzI z<`$j3_268PKWK!tKLF;1Vnad|hx}Ic&n4P~FPj)n39A(8SbLtE4t+rH0l?sY8{647 zH!UJdlN!?HR5a^0g4vyxpMO64%)Lo%4;yS?T>Td*+xYTEW1;8n<1n}Ioo}U~8D>v% z+Rl9~ZRo1z(TfTLsFflQ*VN?nG5H=b*F1BIA=^=(t@-3CkZxEhxAx_V8oH_V#>8^4 zil%a_Nx#32md%}JkK5TjNspvlh&B;UacKiT2GUD&Lf=K!H9Kh{{$bZ{a<;5>6p0^v zTP9I^O>kGOPvR->AK9pFl9Yy{l`x}ea)~znKArb|w4wDlGNuuJvvq!L`umH>hKXsk z9gBcWQj=EQ2?bm|xGVUGxCms=Dv)#SoE+U$!3UNLD&Zs#wOmc9I}xYO+yb;cy~edH zB{J96d(9yQTuszc$Yl{Wb2|IBLbC=;4^fA1C-vAkra##tE6cPpO`5?{{}rQJ4$v2` zQU|A-b_|30hTQ_Ow%`A($_r@(POFUvfd=>FG zjjiy5-oTV%>4fB$C=iRSBwHmnR|DhZ~T3&SsfQ1R#no( zN-o>CB}o2AB6bM!Y><7-K7+EGcR67hAE>o)F(|!L?KpCg-}mO-&?7rxYJz+;q4;M zZ8OAqr!<(w*!1bmjosVvAE^5`Pon6RPheN_d^M`rjN}n@5B3vBTvAJCs8n-_Dt*C9 zb142f91;&@E9FKhXVGI8uV~!9;$K`;0QcBk(pJ8dES5DRMt$*neJ#Qq|CC6a2&IDWu4a~n1q>FSCO4snDZTIB6MMt%`BuVmhL+1G*S$kNmF zoHrK<;CU&OW6VwP#OkOdm$9yDuBG%($HPHZ_hC!0#iK3}0-!syFuHqc;23S9{XI2) zPH^{*md$E)@O4)yUjas7giO1xxz`hZU zs$q&hbN>L6PKhOKU+`@Y`TmLt)F{yYb?m3|(TDv2(hty^@)&uPV^XZvN=`-7#I9%! z&4u)0S)Qu?adFK?wpf1UouX`D3~Hz38+(`Y-GOH3G3B&FjpNxpX%|8IF)`b;D}mG% zEp=FaOLhl0VtspWnDltd*B#2)Qd&ctn>0;*hBlQf21MIrh!V1>NgNN-$#&_usAmwS z^a`L%_7gF&2q^p0lk`C#2RGpqm53Mz!x2`=Blz=btHER;M(HhRK*UKAVffGURSwaK z7iE)hb^1?Y+Rnc!z0kf*qPVtq1r^}!9?s}SyE%R!1z4Fm7vpi;O+lSp_xay`c|HHv zIjZZJ4*x_#*2?_MpnmLWk^5VfDae>vjPL$GuMOEK$6dafZ~m1&8)JByF!>X$RwknZ z;4onE%qkH|_BBbl+xl@JA2)9|AgeONKWFvZLv&wGL8zZQ_aQ)t_qOnk{XOEpZX|I$i6*6$#izl>0W~ywH(olM9hU$J( zZ-DmqjywYo&BlRT`W$r@utWRPzTy#6nw_vfplUH0suR0TXUDrWgz;2#OPEt_ zf2P>UrI>|p)3A3$c#b@5-YI!DNx8QC{k$S~aeEr~8$IbxWVFqCW(m`DrhdI}+D^{I zUD$+iTl4pyQuWR902`X#rubZx%n2f>t zX;radz2&U@yxmy<;!4_Zr*e*QyGdbKz{RCsfdeDQnf;?p_ZMS!wj1s#KFBe3hji9? zQ->C32Am8@2^mfOqsjgf(ak0Bihp|T3%0sbH?jE{$3Pi;j|DFw7S~dCpMJd#e@-+q z<|pP}ep26CVqF5x;c=qy@d@hn4<=oPc+%DCdRN?s4=0@Qoj*`OLviuoGR_lk3P_Pq zs%HFuExQLE$(k@}G8$hu>!!nU^ABZK@_}QU5~r^%ipYtxI{cpt)N9+Y5)$LR;|0h5 zIxzq=nuxuYYsVA-)K z>uaY@wXq4H_V+;U$t5Z#3>0ZKFxhTA@PsYvsiaVUvvcQEI?qU2eVa;v*a-8S z8ETZ#J`Qq3=#Q-O`zdnjuLV=jsOe^sT;iCIdPy<`I5c}>LlDykP8~+N#zA`F?q$M) z26Vsgo;eJ7TxHc1LA)`Sn2dhYMXA!SxA9F*dU9iBe3v}b>x8iNW>sE5AtYUzVy(&o z86PV$vAWiyoY>x0Gbx$4^x8(Rtlm)7W;b-0g<#>c7*q+qVmFnc$W_z)q!iXf+@PP zXHi7tN?OPOD<%n8zPU~x&|o-ka-P}0ceYAs#*;-&hKP2 zX_s=@Jx|ojX!kl6ssiZ=nrz@* z;`~VB5yU#J8xBqm+bdX!Pkuwyad;m4=Az+6o0i7o`y^4;O=`z1O196C$i|z}ImVPf&ULD=-1ggef}X(nSv8(VYW(|VmSN7^En~h!=y}VFmcKesE&=U%@7{&xMu;W&M+m;8IVzlS zzJx4wbThL_jr|7+vc|?*WM`;OU%55>l~%$u1$?olRo&IC^yinkntGA6)549+2Z2b4 zU1SfnHknEu7#VwR$qw9*6U|cdLFvJAH7u%2m=x+~*XY&03^E~L532pjs( z#yM}m6Gyc|_oIoldmV7_T_&mao+n03XY0`CZs|h7W#h|B5pMR literal 5921 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 literal 6609 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 E0l72v6#xJL From 4c4a1f372b78be2bf4ffb360eea547a81f00f65e Mon Sep 17 00:00:00 2001 From: Nad Chishtie Date: Thu, 31 Jan 2019 18:33:42 +0000 Subject: [PATCH 141/244] Updated more icon assets. --- .../Common/logo.imageset/logo.png | Bin 7060 -> 6829 bytes .../Common/logo.imageset/logo@2x.png | Bin 25066 -> 14226 bytes .../Common/logo.imageset/logo@3x.png | Bin 38641 -> 22233 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Riot/Assets/Images.xcassets/Common/logo.imageset/logo.png b/Riot/Assets/Images.xcassets/Common/logo.imageset/logo.png index 93f2f59d64b0a7e33e9565f75970342cf4ebf70e..eea53f0e7ddc4a794abc6adb17c228b95aad7987 100644 GIT binary patch literal 6829 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 bsRsTZ2ZhuNwC==c00000NkvXXu0mjfct97& literal 7060 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 literal 25066 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 LNkvXXu0mjfii}_+ diff --git a/Riot/Assets/Images.xcassets/Common/logo.imageset/logo@3x.png b/Riot/Assets/Images.xcassets/Common/logo.imageset/logo@3x.png index ed1628eed102f837daa49cc8a94d76a669ce2497..2907add844c779d340fde25da884a8589e02c963 100644 GIT binary patch literal 22233 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 literal 38641 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 z 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 N002ovPDHLkV1nFHqrU(E From 2860f705ab58c03894e23ebcb14496d08abbe7cf Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 19:44:37 +0100 Subject: [PATCH 142/244] Add key backup setup banner srtings --- Riot/Assets/en.lproj/Vector.strings | 5 +++++ Riot/Generated/Strings.swift | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index a1b7a6015..8732cbf15 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -709,3 +709,8 @@ "key_backup_recover_success_info" = "Backup Restored!"; "key_backup_recover_done_action" = "Done"; + +// MARK: Key backup setup banner + +"key_backup_setup_banner_title_part1" = "Set up Secure Message Recovery"; +"key_backup_setup_banner_title_part2" = " to never lose encrypted messages"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 0ab2019e5..4603d84d3 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -730,6 +730,14 @@ internal enum VectorL10n { internal static var keyBackupRecoverTitle: String { return VectorL10n.tr("Vector", "key_backup_recover_title") } + /// Set up Secure Message Recovery + internal static var keyBackupSetupBannerTitlePart1: String { + return VectorL10n.tr("Vector", "key_backup_setup_banner_title_part1") + } + /// to never lose encrypted messages + internal static var keyBackupSetupBannerTitlePart2: String { + return VectorL10n.tr("Vector", "key_backup_setup_banner_title_part2") + } /// Set up Secure Message Recovery in case you lose or log out of this device. internal static var keyBackupSetupIntroInfo: String { return VectorL10n.tr("Vector", "key_backup_setup_intro_info") From b2795e19de9715e47637480d35cbd9ab2468a211 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 19:45:00 +0100 Subject: [PATCH 143/244] Add key backup banner close image --- .../close_banner.imageset/Contents.json | 23 ++++++++++++++++++ .../close_banner.imageset/close_banner.png | Bin 0 -> 234 bytes .../close_banner.imageset/close_banner@2x.png | Bin 0 -> 412 bytes .../close_banner.imageset/close_banner@3x.png | Bin 0 -> 557 bytes Riot/Generated/Images.swift | 1 + 5 files changed, 24 insertions(+) create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner.png create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner@2x.png create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner@3x.png diff --git a/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/Contents.json b/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/Contents.json new file mode 100644 index 000000000..ad1c76684 --- /dev/null +++ b/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "close_banner.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "close_banner@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "filename" : "close_banner@3x.png", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner.png b/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner.png new file mode 100644 index 0000000000000000000000000000000000000000..45b45ddde6dd9e6921c134f556cfdd0eba66500c GIT binary patch literal 234 zcmeAS@N?(olHy`uVBq!ia0vp^AT}2V8<6ZZI=>f4F%}28J29*~C-V}>S>oy97$PB= zJHe3ekO7bDM(bh?F%>bjV@6XrzdCS;NoYt5b9ZDLUSFnvC{uKz;>Q2=8--85{1)}) z+2^v|RcHRKIsA3!x)3`q6}9il-`9Eb@$$Q^RGIp2&-TwEYHo+UeL`kRWiY;do$9Wa zvr#Cg%u#HrnnDe4hRx2`$-ladW<>K(b=j(Ue@;|-Mn%OIZPP@*o`(CZBDKtAUwe&w gnuM6#4mbZ~l5j8bdD$7d1?XM|Pgg&ebxsLQ09F@O<^TWy literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner@2x.png b/Riot/Assets/Images.xcassets/KeyBackup/close_banner.imageset/close_banner@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..d7e5f1cfbb7aeb6078512eeeb5da4776a5dd67d9 GIT binary patch literal 412 zcmV;N0b~A&P)Px$R!KxbR5%fxlrc^NF%U&(ydX9Li6SjcE`mfwL_wK`3veVZK$DUJktz}=p`e5! zQqU%Xc<{HdSV>+Fm;e+@;BlR;TAFK5n6CH8IxA%9~uZKV% z9%q-bktZVg9@h29zzmp(oZF2&L(mrpEj;i#$}xOqGPznJGh+TCk<-4=0D}i!Fgz<{ zvnwza-{i{Iw65Ci(1bx%(zJjuX$I|G_`wb^2gN$}H|$w%OZEc0P-=)>Ls&b&0pwut zWr16$eIcO%=44D`42^S#9(ZxVMooH!$HfDJ)c*@30a3YvG8shx0000Px$=Sf6CR7efQmpx7cF%X6A?7|h0(jZZA3nC$M0@@Tbh=LM{Qy@`NAR3CaIYAH- z+=2p$CQ_~dyBNP&Ch;bAc4o5zODj9}%=z4YE<=2;^;d__; zxf@RpOj+DOb2r<$Iv<^U^zehA&Yc>3Me%z7I6Xvt7m2jICTV+p4v@fgfa@2gcdIqt6!I;zBELN|h?@HWs!a1$Ku>-*HsuzH&oV{)h=$|)9=wRVn~ za_)PN?XVpsP}qyWFpR-bzf5u{e8gZF176zV#W@#5=|yaBp1Ew$G`!H@6gjK8DV4|i z>QctZdNG)Xx<03sE=E9mv53G74R09?Z?(WUDBZ=<2#!IqdNHS&%Lgbk8Xc2H9-FX* zP6`@s8Hvq8FeoI!8bOUMv!mcPLRz0SuvUO0K(6tvfi;dHFf2o35*U9g v{1r2y&ku#>mSIRLCoQkZ`ou~Z|3&=|w^gU`cvI2F00000NkvXXu0mjfpe6LY literal 0 HcmV?d00001 diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index 8329ce49c..5e9e81d69 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -59,6 +59,7 @@ internal enum Asset { internal static let priorityHigh = ImageAsset(name: "priorityHigh") internal static let priorityLow = ImageAsset(name: "priorityLow") internal static let createRoom = ImageAsset(name: "create_room") + internal static let closeBanner = ImageAsset(name: "close_banner") internal static let importFilesButton = ImageAsset(name: "import_files_button") internal static let revealPasswordButton = ImageAsset(name: "reveal_password_button") internal static let shield = ImageAsset(name: "shield") From f77d9cc8591b481364135ee4eab05e375fe197e0 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 19:50:22 +0100 Subject: [PATCH 144/244] Create KeyBackupBannerPreferences to handle key backup banner display preferences --- .../Banners/KeyBackupBannersPreferences.swift | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift diff --git a/Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift b/Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift new file mode 100644 index 000000000..106997d28 --- /dev/null +++ b/Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift @@ -0,0 +1,46 @@ +/* + Copyright 2018 New Vector 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 Foundation + +/// Key backup banner user preferences. +@objcMembers +final class KeyBackupBannerPreferences: NSObject { + + // MARK: - Constants + + private enum UserDefaultsKeys { + static let hideSetupBanner = "KeyBackupBannersManagerHideSetupBanner" + } + + static let shared = KeyBackupBannerPreferences() + + // MARK: - Public + + /// Indicate to show key backup setup if needed. + var hideSetupBanner: Bool { + get { + return UserDefaults.standard.bool(forKey: UserDefaultsKeys.hideSetupBanner) + } + set { + UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.hideSetupBanner) + } + } + + func reset() { + self.hideSetupBanner = false + } +} From c0cf84921e9e79ca99e895e9a95e6707cf49b605 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 19:50:58 +0100 Subject: [PATCH 145/244] Create key backup setup banner cell --- Riot.xcodeproj/project.pbxproj | 28 +++++++ .../Setup/KeyBackupSetupBannerCell.swift | 78 +++++++++++++++++++ .../Setup/KeyBackupSetupBannerCell.xib | 73 +++++++++++++++++ 3 files changed, 179 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift create mode 100644 Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 940d86d1a..f8a9afc02 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -33,6 +33,7 @@ 92726A471F58737A004AD26F /* IntentHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 92726A461F58737A004AD26F /* IntentHandler.m */; }; 92726A4B1F58737A004AD26F /* SiriIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 92726A431F58737A004AD26F /* SiriIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 92726A511F587410004AD26F /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92726A501F587410004AD26F /* Intents.framework */; }; + B104C2942203773C00D9F496 /* KeyBackupBannersPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = B104C2932203773B00D9F496 /* KeyBackupBannersPreferences.swift */; }; B1098BDF21ECE09F000DDA48 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDA21ECE09E000DDA48 /* Strings.swift */; }; B1098BE121ECE09F000DDA48 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDC21ECE09E000DDA48 /* Images.swift */; }; B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */; }; @@ -53,6 +54,8 @@ B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */; }; B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0B21ED07E4000DDA48 /* Presentable.swift */; }; B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */; }; + B10B3B5B2201DD740072C76B /* KeyBackupSetupBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10B3B592201DD740072C76B /* KeyBackupSetupBannerCell.swift */; }; + B10B3B5C2201DD740072C76B /* KeyBackupSetupBannerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B10B3B5A2201DD740072C76B /* KeyBackupSetupBannerCell.xib */; }; B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */; }; B1107ECA2200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */; }; B110871921EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */; }; @@ -496,6 +499,7 @@ 92726A481F58737A004AD26F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 92726A4F1F587393004AD26F /* SiriIntents.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SiriIntents.entitlements; sourceTree = ""; }; 92726A501F587410004AD26F /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; + B104C2932203773B00D9F496 /* KeyBackupBannersPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupBannersPreferences.swift; sourceTree = ""; }; B1098BDA21ECE09E000DDA48 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; B1098BDC21ECE09E000DDA48 /* Images.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = ""; }; B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiotDefaults.swift; sourceTree = ""; }; @@ -516,6 +520,8 @@ B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; B1098C0B21ED07E4000DDA48 /* Presentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = ""; }; B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = ""; }; + B10B3B592201DD740072C76B /* KeyBackupSetupBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupBannerCell.swift; sourceTree = ""; }; + B10B3B5A2201DD740072C76B /* KeyBackupSetupBannerCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KeyBackupSetupBannerCell.xib; sourceTree = ""; }; B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverSuccessViewController.swift; sourceTree = ""; }; B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverSuccessViewController.storyboard; sourceTree = ""; }; B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewController.swift; sourceTree = ""; }; @@ -1219,6 +1225,7 @@ children = ( B1098C0221ECFEAF000DDA48 /* Setup */, B1FDF56421F726AD00BA3834 /* Recover */, + B1107ECB2201BE800038014B /* Banners */, ); path = KeyBackup; sourceTree = ""; @@ -1296,6 +1303,24 @@ path = Success; sourceTree = ""; }; + B1107ECB2201BE800038014B /* Banners */ = { + isa = PBXGroup; + children = ( + B104C2932203773B00D9F496 /* KeyBackupBannersPreferences.swift */, + B1107ECC2201BEAF0038014B /* Setup */, + ); + path = Banners; + sourceTree = ""; + }; + B1107ECC2201BEAF0038014B /* Setup */ = { + isa = PBXGroup; + children = ( + B10B3B592201DD740072C76B /* KeyBackupSetupBannerCell.swift */, + B10B3B5A2201DD740072C76B /* KeyBackupSetupBannerCell.xib */, + ); + path = Setup; + sourceTree = ""; + }; B110871E21F098EF003554A5 /* ActivityIndicator */ = { isa = PBXGroup; children = ( @@ -3180,6 +3205,7 @@ 3284A35120A07C210044F922 /* postMessageAPI.js in Resources */, B1B557A220EF58AD00210D55 /* ContactTableViewCell.xib in Resources */, B1B558EB20EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib in Resources */, + B10B3B5C2201DD740072C76B /* KeyBackupSetupBannerCell.xib in Resources */, B1B5581820EF625800210D55 /* PreviewRoomTitleView.xib in Resources */, B1B5583020EF66BA00210D55 /* RoomIdOrAliasTableViewCell.xib in Resources */, B1B558BF20EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib in Resources */, @@ -3514,6 +3540,7 @@ B1B5574120EE6C4D00210D55 /* RecentsViewController.m in Sources */, B1D250D82118AA0A000F4E93 /* RoomPredecessorBubbleCell.m in Sources */, B1B5577120EE702800210D55 /* StickerPickerViewController.m in Sources */, + B104C2942203773C00D9F496 /* KeyBackupBannersPreferences.swift in Sources */, B1B5572020EE6C4D00210D55 /* ContactsTableViewController.m in Sources */, B1B5581920EF625800210D55 /* RoomTitleView.m in Sources */, B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */, @@ -3525,6 +3552,7 @@ B1B5571E20EE6C4D00210D55 /* ContactDetailsViewController.m in Sources */, B1798302211B13B3001FD722 /* OnBoardingManager.swift in Sources */, B1B5573520EE6C4D00210D55 /* GroupDetailsViewController.m in Sources */, + B10B3B5B2201DD740072C76B /* KeyBackupSetupBannerCell.swift in Sources */, B1098BFA21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModel.swift in Sources */, B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */, F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */, diff --git a/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift b/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift new file mode 100644 index 000000000..aaca7c2c3 --- /dev/null +++ b/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift @@ -0,0 +1,78 @@ +/* + Copyright 2019 New Vector 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 UIKit + +@objc protocol KeyBackupSetupBannerCellDelegate: class { + func keyBackupSetupBannerCellDidTapCloseAction(_ cell: KeyBackupSetupBannerCell) +} + +@objcMembers +final class KeyBackupSetupBannerCell: MXKTableViewCell { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var shieldImageView: UIImageView! + @IBOutlet private weak var informationLabel: UILabel! + @IBOutlet private weak var closeButton: UIButton! + + // MARK: Public + + weak var delegate: KeyBackupSetupBannerCellDelegate? + + // MARK: - Overrides + + override class func defaultReuseIdentifier() -> String { + return String(describing: self) + } + + override class func nib() -> UINib { + return UINib(nibName: String(describing: self), bundle: nil) + } + + override func customizeRendering() { + super.customizeRendering() + + let theme = ThemeService.shared().theme + + self.shieldImageView.tintColor = theme.textPrimaryColor + self.closeButton.tintColor = theme.textPrimaryColor + + let attributedTitle = NSMutableAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart1, attributes: [.foregroundColor: theme.tintColor]) + attributedTitle.append(NSAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart2, attributes: [.foregroundColor: theme.textPrimaryColor])) + self.informationLabel.attributedText = attributedTitle + } + + // MARK: - Life cycle + + override func awakeFromNib() { + super.awakeFromNib() + + let shieldImage = Asset.Images.shield.image.withRenderingMode(.alwaysTemplate) + self.shieldImageView.image = shieldImage + + let closeImage = Asset.Images.closeBanner.image.withRenderingMode(.alwaysTemplate) + self.closeButton.setImage(closeImage, for: .normal) + } + + // MARK: - Actions + + @IBAction private func closeButtonAction(_ sender: Any) { + self.delegate?.keyBackupSetupBannerCellDidTapCloseAction(self) + } +} diff --git a/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib b/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib new file mode 100644 index 000000000..e2eb36af0 --- /dev/null +++ b/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib @@ -0,0 +1,73 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From bc527cd09798571479ec1dd24d53018f9599f86e Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 19:52:32 +0100 Subject: [PATCH 146/244] Handle key backup setup banner display --- .../Recents/DataSources/RecentsDataSource.h | 12 ++ .../Recents/DataSources/RecentsDataSource.m | 144 +++++++++++++++++- Riot/Modules/Home/HomeViewController.m | 100 +++++++++++- 3 files changed, 247 insertions(+), 9 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h index 6d710889c..9acb5c13a 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h @@ -32,6 +32,15 @@ typedef enum : NSUInteger } RecentsDataSourceMode; +/** + List the different key backup banners that could be displayed. + */ +typedef NS_ENUM(NSInteger, KeyBackupBanner) +{ + KeyBackupBannerNone, + KeyBackupBannerSetup, + KeyBackupBannerRecover +}; /** Action identifier used when the user tapped on the directory change button. @@ -46,6 +55,7 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; */ @interface RecentsDataSource : MXKInterleavedRecentsDataSource +@property (nonatomic) NSInteger keyBackupBannerSection; @property (nonatomic) NSInteger directorySection; @property (nonatomic) NSInteger invitesSection; @property (nonatomic) NSInteger favoritesSection; @@ -61,6 +71,8 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; @property (nonatomic, readonly) NSArray* lowPriorityCellDataArray; @property (nonatomic, readonly) NSArray* serverNoticeCellDataArray; +@property (nonatomic, readonly) KeyBackupBanner keyBackupBanner; + /** Set the delegate by specifying the selected display mode. */ diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 9f8472f13..d0f5b3bdd 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -40,7 +40,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSourceTapOnDirectoryServerChange"; -@interface RecentsDataSource() +@interface RecentsDataSource() { NSMutableArray* invitesCellDataArray; NSMutableArray* favoriteCellDataArray; @@ -60,10 +60,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Timer to not refresh publicRoomsDirectoryDataSource on every keystroke. NSTimer *publicRoomsTriggerTimer; } + +@property (nonatomic, assign, readwrite) KeyBackupBanner keyBackupBanner; + @end @implementation RecentsDataSource -@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection; +@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, keyBackupBannerSection; @synthesize hiddenCellIndexPath, droppingCellIndexPath, droppingCellBackGroundView; @synthesize invitesCellDataArray, favoriteCellDataArray, peopleCellDataArray, conversationCellDataArray, lowPriorityCellDataArray, serverNoticeCellDataArray; @@ -79,6 +82,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou serverNoticeCellDataArray = [[NSMutableArray alloc] init]; conversationCellDataArray = [[NSMutableArray alloc] init]; + + _keyBackupBanner = KeyBackupBannerNone; + keyBackupBannerSection = -1; directorySection = -1; invitesSection = -1; favoritesSection = -1; @@ -111,6 +117,16 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { _recentsDataSourceMode = recentsDataSourceMode; + // Register to key backup state changes only on in home mode. + if (recentsDataSourceMode == RecentsDataSourceModeHome) + { + [self registerKeyBackupStateDidChangeNotification]; + } + else + { + [self unregisterKeyBackupStateDidChangeNotification]; + } + [self forceRefresh]; } @@ -132,6 +148,75 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return stickyHeader; } +#pragma mark - Key backup setup banner + +- (void)registerKeyBackupStateDidChangeNotification +{ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBackupStateDidChangeNotification:) name:kMXKeyBackupDidStateChangeNotification object:nil]; +} + +- (void)unregisterKeyBackupStateDidChangeNotification +{ + [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXKeyBackupDidStateChangeNotification object:nil]; +} + +- (void)keyBackupStateDidChangeNotification:(NSNotification*)notification +{ + [self forceRefresh]; +} + +- (void)updateKeyBackupBanner +{ + KeyBackupBanner keyBackupBanner = KeyBackupBannerNone; + + if (self.recentsDataSourceMode == RecentsDataSourceModeHome) + { + KeyBackupBannerPreferences *keyBackupBannersPreferences = KeyBackupBannerPreferences.shared; + + switch (self.mxSession.crypto.backup.state) { + case MXKeyBackupStateDisabled: + // Show key backup setup banner only if user has not hidden it once. + if (keyBackupBannersPreferences.hideSetupBanner) + { + keyBackupBanner = KeyBackupBannerNone; + } + else + { + keyBackupBanner = KeyBackupBannerSetup; + } + break; + case MXKeyBackupStateNotTrusted: + case MXKeyBackupStateWrongBackUpVersion: + // TODO: Show key backup recover banner. + keyBackupBanner = KeyBackupBannerNone; + break; + default: + keyBackupBanner = KeyBackupBannerNone; + break; + } + } + + self.keyBackupBanner = keyBackupBanner; +} + +- (void)hideKeyBackupBanner:(KeyBackupBanner)keyBackupBanner +{ + KeyBackupBannerPreferences *keyBackupBannersPreferences = KeyBackupBannerPreferences.shared; + + switch (keyBackupBanner) { + case KeyBackupBannerSetup: + keyBackupBannersPreferences.hideSetupBanner = YES; + break; + case KeyBackupBannerRecover: + // TODO: Hide key backup recover banner. + break; + default: + break; + } + + [self forceRefresh]; +} + #pragma mark - - (MXKSessionRecentsDataSource *)addMatrixSession:(MXSession *)mxSession @@ -246,7 +331,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou // Check whether all data sources are ready before rendering recents if (self.state == MXKDataSourceStateReady) { - directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = invitesSection = serverNoticeSection = -1; + keyBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = invitesSection = serverNoticeSection = -1; + + if (self.keyBackupBanner != KeyBackupBannerNone) + { + self.keyBackupBannerSection = sectionsCount++; + } if (invitesCellDataArray.count > 0) { @@ -300,7 +390,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou NSUInteger count = 0; - if (section == favoritesSection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_FAVORITES)) + if (section == self.keyBackupBannerSection && self.keyBackupBanner != KeyBackupBannerNone) + { + count = 1; + } + else if (section == favoritesSection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_FAVORITES)) { count = favoriteCellDataArray.count; } @@ -345,7 +439,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (CGFloat)heightForHeaderInSection:(NSInteger)section { - if (section == directorySection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_DIRECTORY)) + if (section == self.keyBackupBannerSection) + { + return 0.0; + } + else if (section == directorySection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_DIRECTORY)) { return RECENTSDATASOURCE_DIRECTORY_SECTION_HEADER_HEIGHT; } @@ -515,6 +613,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame { + // No header view in key backup banner section + if (section == self.keyBackupBannerSection) + { + return nil; + } + UIView *sectionHeader = [[UIView alloc] initWithFrame:frame]; sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; NSInteger sectionBitwise = 0; @@ -807,7 +911,24 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return [[UITableViewCell alloc] init]; } - if (indexPath.section == directorySection) + if (indexPath.section == self.keyBackupBannerSection) + { + UITableViewCell* cell; + + switch (self.keyBackupBanner) { + case KeyBackupBannerSetup: { + KeyBackupSetupBannerCell* keyBackupSetupBannerCell = [tableView dequeueReusableCellWithIdentifier:KeyBackupSetupBannerCell.defaultReuseIdentifier forIndexPath:indexPath]; + keyBackupSetupBannerCell.delegate = self; + cell = keyBackupSetupBannerCell; + } + break; + default: + break; + } + + return cell; + } + else if (indexPath.section == directorySection) { NSIndexPath *indexPathInPublicRooms = [NSIndexPath indexPathForRow:indexPath.row inSection:0]; return [_publicRoomsDirectoryDataSource tableView:tableView cellForRowAtIndexPath:indexPathInPublicRooms]; @@ -1109,7 +1230,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou _missedDirectDiscussionsCount = _missedHighlightDirectDiscussionsCount = 0; _missedGroupDiscussionsCount = _missedHighlightGroupDiscussionsCount = 0; - directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1; + keyBackupBannerSection = directorySection = favoritesSection = peopleSection = conversationSection = lowPrioritySection = serverNoticeSection = invitesSection = -1; + + [self updateKeyBackupBanner]; if (displayedRecentsDataSourceArray.count > 0) { @@ -1592,4 +1715,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou } } +#pragma mark - KeyBackupSetupBannerCellDelegate + +- (void)keyBackupSetupBannerCellDidTapCloseAction:(KeyBackupSetupBannerCell * _Nonnull)cell +{ + [self hideKeyBackupBanner:self.keyBackupBanner]; +} + @end diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index b8873d2b9..51145c258 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -27,7 +27,7 @@ #import "MXRoom+Riot.h" -@interface HomeViewController () +@interface HomeViewController () { RecentsDataSource *recentsDataSource; @@ -40,6 +40,10 @@ // We store this value to prevent the collection view from scrolling to the beginning (observed on iOS < 10). CGFloat selectedCollectionViewContentOffset; } + +@property (nonatomic, strong) KeyBackupSetupCoordinatorBridgePresenter *keyBackupSetupCoordinatorBridgePresenter; +@property (nonatomic, strong) KeyBackupSetupBannerCell *keyBackupSetupBannerPrototypeCell; + @end @implementation HomeViewController @@ -71,6 +75,9 @@ // Register table view cell used for rooms collection. [self.recentsTableView registerClass:TableViewCellWithCollectionView.class forCellReuseIdentifier:TableViewCellWithCollectionView.defaultReuseIdentifier]; + + // Register key backup banner cells + [self.recentsTableView registerNib:KeyBackupSetupBannerCell.nib forCellReuseIdentifier:KeyBackupSetupBannerCell.defaultReuseIdentifier]; // Change the table data source. It must be the home view controller itself. self.recentsTableView.dataSource = self; @@ -137,6 +144,26 @@ } } +- (KeyBackupSetupBannerCell *)keyBackupSetupBannerPrototypeCell +{ + if (!_keyBackupSetupBannerPrototypeCell) + { + _keyBackupSetupBannerPrototypeCell = [self.recentsTableView dequeueReusableCellWithIdentifier:KeyBackupSetupBannerCell.defaultReuseIdentifier]; + } + return _keyBackupSetupBannerPrototypeCell; +} + +- (void)presentKeyBackupSetup +{ + KeyBackupSetupCoordinatorBridgePresenter *keyBackupSetupCoordinatorBridgePresenter = [[KeyBackupSetupCoordinatorBridgePresenter alloc] initWithSession:self.mainSession]; + keyBackupSetupCoordinatorBridgePresenter.delegate = self; + + [keyBackupSetupCoordinatorBridgePresenter presentFrom:self animated:YES]; + + self.keyBackupSetupCoordinatorBridgePresenter = keyBackupSetupCoordinatorBridgePresenter; +} + + #pragma mark - Override RecentsViewController - (void)displayList:(MXKRecentsDataSource *)listDataSource @@ -262,7 +289,8 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if ((indexPath.section == recentsDataSource.conversationSection && !recentsDataSource.conversationCellDataArray.count) - || (indexPath.section == recentsDataSource.peopleSection && !recentsDataSource.peopleCellDataArray.count)) + || (indexPath.section == recentsDataSource.peopleSection && !recentsDataSource.peopleCellDataArray.count) + || (indexPath.section == recentsDataSource.keyBackupBannerSection)) { return [recentsDataSource tableView:tableView cellForRowAtIndexPath:indexPath]; } @@ -338,6 +366,33 @@ { return [recentsDataSource cellHeightAtIndexPath:indexPath]; } + else if (indexPath.section == recentsDataSource.keyBackupBannerSection) + { + CGFloat height = 0.0; + UITableViewCell *sizingCell; + + switch (recentsDataSource.keyBackupBanner) { + case KeyBackupBannerSetup: + { + sizingCell = self.keyBackupSetupBannerPrototypeCell; + } + break; + default: + break; + } + + if (sizingCell) + { + [sizingCell layoutIfNeeded]; + + CGSize fittingSize = UILayoutFittingCompressedSize; + fittingSize.width = CGRectGetWidth(tableView.frame); + + height = [sizingCell systemLayoutSizeFittingSize:fittingSize withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel].height; + } + + return height; + } // Retrieve the fixed height of the collection view cell used to display a room. CGFloat height = [RoomCollectionViewCell defaultCellSize].height + 1; @@ -352,6 +407,33 @@ return height; } +- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section +{ + // No header in key banner section + if (section == recentsDataSource.keyBackupBannerSection) + { + return 0.0; + } + else + { + return [super tableView:tableView heightForHeaderInSection:section]; + } +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath +{ + if (indexPath.section == recentsDataSource.keyBackupBannerSection) + { + switch (recentsDataSource.keyBackupBanner) { + case KeyBackupBannerSetup: + [self presentKeyBackupSetup]; + break; + default: + break; + } + } +} + #pragma mark - UICollectionViewDataSource - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section @@ -597,4 +679,18 @@ [self leaveEditedRoom]; } +#pragma mark - KeyBackupSetupCoordinatorBridgePresenterDelegate + +- (void)keyBackupSetupCoordinatorBridgePresenterDelegateDidCancel:(KeyBackupSetupCoordinatorBridgePresenter * _Nonnull)keyBackupSetupCoordinatorBridgePresenter +{ + [keyBackupSetupCoordinatorBridgePresenter dismissWithAnimated:YES]; + self.keyBackupSetupCoordinatorBridgePresenter = nil; +} + +- (void)keyBackupSetupCoordinatorBridgePresenterDelegateDidSetupRecoveryKey:(KeyBackupSetupCoordinatorBridgePresenter * _Nonnull)keyBackupSetupCoordinatorBridgePresenter +{ + [keyBackupSetupCoordinatorBridgePresenter dismissWithAnimated:YES]; + self.keyBackupSetupCoordinatorBridgePresenter = nil; +} + @end From 7313fae3d5ace1a0afd66d108e7f2286b7c8b00d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 19:53:12 +0100 Subject: [PATCH 147/244] Reset key backup banner preferences on logout --- Riot/AppDelegate.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 19e32e3a4..7f67cc7b0 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -2671,6 +2671,9 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // Clear cache [MXMediaManager clearCache]; + // Reset key backup banner preferences + [KeyBackupBannerPreferences.shared reset]; + #ifdef MX_CALL_STACK_ENDPOINT // Erase all created certificates and private keys by MXEndpointCallStack for (MXKAccount *account in MXKAccountManager.sharedManager.accounts) From 25c69eb44c3221e11d36ba8b31274b4afd5875f9 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 20:00:38 +0100 Subject: [PATCH 148/244] Key backup: Fix some recovery setup bugs --- .../Setup/KeyBackupSetupCoordinatorBridgePresenter.swift | 2 +- .../Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift | 3 +-- .../RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift index fc38b477e..6a0fdb48e 100644 --- a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift @@ -72,6 +72,6 @@ extension KeyBackupSetupCoordinatorBridgePresenter: KeyBackupSetupCoordinatorDel } func keyBackupSetupCoordinatorDidSetupRecoveryKey(_ keyBackupSetupCoordinator: KeyBackupSetupCoordinatorType) { - self.delegate?.keyBackupSetupCoordinatorBridgePresenterDelegateDidCancel(self) + self.delegate?.keyBackupSetupCoordinatorBridgePresenterDelegateDidSetupRecoveryKey(self) } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift index 9b2d74f13..704c0b614 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift @@ -38,8 +38,7 @@ final class KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordin init(session: MXSession) { self.session = session - let keyBackup = MXKeyBackup(matrixSession: session) - let keyBackupSetupPassphraseViewModel = KeyBackupSetupPassphraseViewModel(keyBackup: keyBackup) + let keyBackupSetupPassphraseViewModel = KeyBackupSetupPassphraseViewModel(keyBackup: self.session.crypto.backup) let keyBackupSetupPassphraseViewController = KeyBackupSetupPassphraseViewController.instantiate(with: keyBackupSetupPassphraseViewModel) self.keyBackupSetupPassphraseViewModel = keyBackupSetupPassphraseViewModel self.keyBackupSetupPassphraseViewController = keyBackupSetupPassphraseViewController diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift index fdc2104b2..6039a24dd 100644 --- a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyCoordinator.swift @@ -35,8 +35,7 @@ final class KeyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoord // MARK: - Setup init(session: MXSession, megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { - let keyBackup = MXKeyBackup(matrixSession: session) - let keyBackupSetupRecoveryKeyViewModel = KeyBackupSetupRecoveryKeyViewModel(keyBackup: keyBackup, megolmBackupCreationInfo: megolmBackupCreationInfo) + let keyBackupSetupRecoveryKeyViewModel = KeyBackupSetupRecoveryKeyViewModel(keyBackup: session.crypto.backup, megolmBackupCreationInfo: megolmBackupCreationInfo) let keyBackupSetupRecoveryKeyViewController = KeyBackupSetupRecoveryKeyViewController.instantiate(with: keyBackupSetupRecoveryKeyViewModel) self.keyBackupSetupRecoveryKeyViewModel = keyBackupSetupRecoveryKeyViewModel self.keyBackupSetupRecoveryKeyViewController = keyBackupSetupRecoveryKeyViewController From 269d41d5476bb43e9cdab590c495bf189a03a635 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 31 Jan 2019 20:00:55 +0100 Subject: [PATCH 149/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 325cbf2c4..f53440bda 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,7 @@ Improvements: * Clean up iOS version checking (#2190). * Key backup: Implement setup screen (#2198). * Key backup: Implement recover screen (#2196). + * Key backup: Implement setup reminder (#2211). Bug fix: * Use white scroll bar on dark themes (#2158). From 2df27b3460f640efe8e42a7ee9b257dcacceb196 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 20:02:01 +0100 Subject: [PATCH 150/244] CHANGES.rst --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 325cbf2c4..8079b8088 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -9,6 +9,7 @@ Improvements: * Clean up iOS version checking (#2190). * Key backup: Implement setup screen (#2198). * Key backup: Implement recover screen (#2196). + * Key backup: Add a dedicated section to settings (#2193). Bug fix: * Use white scroll bar on dark themes (#2158). From 0bbf046ed4e5e5d10635fd8fcd4f36ab55d747f3 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 21:15:50 +0100 Subject: [PATCH 151/244] key backup settings: Fix Steve's comment --- .../KeyBackup/SettingsKeyBackupTableViewSection.swift | 9 ++++----- .../Settings/KeyBackup/SettingsKeyBackupViewModel.swift | 6 +++--- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index e6b04bcfc..3bed6ca45 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -32,7 +32,7 @@ import UIKit func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showError error:Error) } -@objc class SettingsKeyBackupTableViewSection: NSObject { +@objc final class SettingsKeyBackupTableViewSection: NSObject { // MARK: - Properties @@ -68,11 +68,11 @@ import UIKit numberOfRows = self.numberOfCheckingBackupRows() case .noBackup: numberOfRows = self.numberOfNoBackupRows() - case .backup(_, _): + case .backup: numberOfRows = self.numberOfBackupRows() - case .backupAndRunning(_, _, _): + case .backupAndRunning: numberOfRows = self.numberOfBackupAndRunningRows() - case .backupNotTrusted(_, _): + case .backupNotTrusted: numberOfRows = self.numberOfBackupNotTrustedRows() } @@ -507,7 +507,6 @@ extension SettingsKeyBackupTableViewSection: SettingsKeyBackupViewModelViewDeleg self.delegate?.settingsKeyBackup(self, showActivityIndicator: false) case .error(let error): self.delegate?.settingsKeyBackup(self, showError: error) - break } } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index f04ea144c..8187fc89f 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -16,7 +16,7 @@ import UIKit -class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { +final class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { // MARK: - Properties weak var viewDelegate: SettingsKeyBackupViewModelViewDelegate? @@ -44,7 +44,7 @@ class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { switch viewAction { case .load: - self.viewDelegate?.settingsKeyBackupViewModel(self, didUpdateViewState: .checkingBackup) + viewDelegate?.settingsKeyBackupViewModel(self, didUpdateViewState: .checkingBackup) self.checkKeyBackupState() case .create: viewDelegate.settingsKeyBackupViewModelShowKeyBackupSetup(self) @@ -66,7 +66,7 @@ class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { // MARK: - Private - func checkKeyBackupState() { + private func checkKeyBackupState() { if let keyBackupVersion = self.keyBackup.keyBackupVersion { From 3599d97e148d2b718e4c9a8c543a941e94ca9a81 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 31 Jan 2019 21:22:10 +0100 Subject: [PATCH 152/244] key backup settings: Fix Steve's comment --- .../Settings/KeyBackup/SettingsKeyBackupViewModel.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index 8187fc89f..ab80e90ab 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -44,7 +44,7 @@ final class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { switch viewAction { case .load: - viewDelegate?.settingsKeyBackupViewModel(self, didUpdateViewState: .checkingBackup) + viewDelegate.settingsKeyBackupViewModel(self, didUpdateViewState: .checkingBackup) self.checkKeyBackupState() case .create: viewDelegate.settingsKeyBackupViewModelShowKeyBackupSetup(self) @@ -84,7 +84,7 @@ final class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { } } - func computeState(withBackupVersionTrust keyBackupVersionTrust:MXKeyBackupVersionTrust? = nil) { + private func computeState(withBackupVersionTrust keyBackupVersionTrust:MXKeyBackupVersionTrust? = nil) { var viewState: SettingsKeyBackupViewState? switch self.keyBackup.state { @@ -130,7 +130,7 @@ final class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { } } - func deleteKeyBackupVersion(_ keyBackupVersion: MXKeyBackupVersion) { + private func deleteKeyBackupVersion(_ keyBackupVersion: MXKeyBackupVersion) { guard let keyBackupVersionVersion = keyBackupVersion.version else { return } From 578417cd4cd4c2c3fddf6d788ef98434b2568883 Mon Sep 17 00:00:00 2001 From: sergio Date: Tue, 30 Oct 2018 00:29:56 +0000 Subject: [PATCH 153/244] Translated using Weblate (Russian) Currently translated at 100.0% (520 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index c3ef0320e..4d5019b38 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -557,3 +557,4 @@ "settings_labs_room_members_lazy_loading" = "Ленивая подгрузка собеседников"; "settings_labs_room_members_lazy_loading_error_message" = "Ваш сервер не поддерживает ленивую подгрузку собеседников. Попробуйте позже."; "homeserver_connection_lost" = "Невозможно соединиться с этим сервером."; +"auth_accept_policies" = "Пожалуйста ознакомьтесь и подтвердите согласие с политикой этого сервера:"; From fa07c4cc858eed857456b48afa6cadfec4b7f37e Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 1 Feb 2019 09:33:31 +0100 Subject: [PATCH 154/244] Add key backup recover banner strings --- Riot/Assets/en.lproj/Vector.strings | 5 +++++ Riot/Generated/Strings.swift | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 3f90b3a44..84f0010bf 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -740,3 +740,8 @@ "key_backup_setup_banner_title_part1" = "Set up Secure Message Recovery"; "key_backup_setup_banner_title_part2" = " to never lose encrypted messages"; + +// MARK: Key backup recover banner + +"key_backup_recover_banner_title_part1" = "Run Secure Message Recovery"; +"key_backup_recover_banner_title_part2" = " to read encrypted message history on this device"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 2b3911452..54e1ba16b 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -662,6 +662,14 @@ internal enum VectorL10n { internal static var join: String { return VectorL10n.tr("Vector", "join") } + /// Run Secure Message Recovery + internal static var keyBackupRecoverBannerTitlePart1: String { + return VectorL10n.tr("Vector", "key_backup_recover_banner_title_part1") + } + /// to read encrypted message history on this device + internal static var keyBackupRecoverBannerTitlePart2: String { + return VectorL10n.tr("Vector", "key_backup_recover_banner_title_part2") + } /// Done internal static var keyBackupRecoverDoneAction: String { return VectorL10n.tr("Vector", "key_backup_recover_done_action") From 5288743bccbdd2ad281656f8105dfcf045c3eb53 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 1 Feb 2019 09:35:54 +0100 Subject: [PATCH 155/244] Handle key backup recover banner preferences --- .../Banners/KeyBackupBannerPreferences.swift | 77 +++++++++++++++++++ .../Banners/KeyBackupBannersPreferences.swift | 46 ----------- 2 files changed, 77 insertions(+), 46 deletions(-) create mode 100644 Riot/Modules/KeyBackup/Banners/KeyBackupBannerPreferences.swift delete mode 100644 Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift diff --git a/Riot/Modules/KeyBackup/Banners/KeyBackupBannerPreferences.swift b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerPreferences.swift new file mode 100644 index 000000000..eb4a2b06b --- /dev/null +++ b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerPreferences.swift @@ -0,0 +1,77 @@ +/* + Copyright 2018 New Vector 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 Foundation + +/// Key backup banner user preferences. +@objcMembers +final class KeyBackupBannerPreferences: NSObject { + + // MARK: - Constants + + private enum UserDefaultsKeys { + static let hideSetupBanner = "KeyBackupBannerPreferencesHideSetupBanner" + static let hiddenRecoverBannerKeyBackupVersions = "KeyBackupBannerPreferencesHiddenRecoverBannerKeyBackupVersions" + } + + static let shared = KeyBackupBannerPreferences() + + // MARK: - Properties + private var hiddenRecoverBannerKeyBackupVersions: [String] { + get { + return UserDefaults.standard.stringArray(forKey: UserDefaultsKeys.hiddenRecoverBannerKeyBackupVersions) ?? [] + } + set { + UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.hiddenRecoverBannerKeyBackupVersions) + } + } + + // MARK: - Public + + /// Remember to hide key backup setup banner. + var hideSetupBanner: Bool { + get { + return UserDefaults.standard.bool(forKey: UserDefaultsKeys.hideSetupBanner) + } + set { + UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.hideSetupBanner) + } + } + + /// Remember to hide key backup recover banner for specific key backup version. + /// + /// - Parameter keyBackupVersion: Key backup version recover banner to hide. + func hideRecoverBanner(for keyBackupVersion: String) { + guard self.hiddenRecoverBannerKeyBackupVersions.contains(keyBackupVersion) == false else { + return + } + self.hiddenRecoverBannerKeyBackupVersions.append(keyBackupVersion) + } + + /// Check if key backup recover banner should be hidden for key backup version. + /// + /// - Parameter keyBackupVersion: Key backup version to check. + /// - Returns: true if recover banner should be hidden. + func isRecoverBannerHidden(for keyBackupVersion: String) -> Bool { + return self.hiddenRecoverBannerKeyBackupVersions.contains(keyBackupVersion) + } + + /// Reset key backup banner preferences to default values + func reset() { + self.hideSetupBanner = false + self.hiddenRecoverBannerKeyBackupVersions = [] + } +} diff --git a/Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift b/Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift deleted file mode 100644 index 106997d28..000000000 --- a/Riot/Modules/KeyBackup/Banners/KeyBackupBannersPreferences.swift +++ /dev/null @@ -1,46 +0,0 @@ -/* - Copyright 2018 New Vector 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 Foundation - -/// Key backup banner user preferences. -@objcMembers -final class KeyBackupBannerPreferences: NSObject { - - // MARK: - Constants - - private enum UserDefaultsKeys { - static let hideSetupBanner = "KeyBackupBannersManagerHideSetupBanner" - } - - static let shared = KeyBackupBannerPreferences() - - // MARK: - Public - - /// Indicate to show key backup setup if needed. - var hideSetupBanner: Bool { - get { - return UserDefaults.standard.bool(forKey: UserDefaultsKeys.hideSetupBanner) - } - set { - UserDefaults.standard.set(newValue, forKey: UserDefaultsKeys.hideSetupBanner) - } - } - - func reset() { - self.hideSetupBanner = false - } -} From 3850d9a523a1d9f072d2534ede6e3c8c20478c09 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 1 Feb 2019 09:51:01 +0100 Subject: [PATCH 156/244] Use one key backup banner for recover and setup cases --- Riot.xcodeproj/project.pbxproj | 32 +++++++------------ ...erCell.swift => KeyBackupBannerCell.swift} | 32 ++++++++++++++++--- ...BannerCell.xib => KeyBackupBannerCell.xib} | 6 +--- Riot/SupportingFiles/Riot-Bridging-Header.h | 1 + 4 files changed, 41 insertions(+), 30 deletions(-) rename Riot/Modules/KeyBackup/Banners/{Setup/KeyBackupSetupBannerCell.swift => KeyBackupBannerCell.swift} (60%) rename Riot/Modules/KeyBackup/Banners/{Setup/KeyBackupSetupBannerCell.xib => KeyBackupBannerCell.xib} (96%) diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index d67a06dfb..e09eab269 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -39,7 +39,7 @@ 92726A471F58737A004AD26F /* IntentHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 92726A461F58737A004AD26F /* IntentHandler.m */; }; 92726A4B1F58737A004AD26F /* SiriIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 92726A431F58737A004AD26F /* SiriIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 92726A511F587410004AD26F /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92726A501F587410004AD26F /* Intents.framework */; }; - B104C2942203773C00D9F496 /* KeyBackupBannersPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = B104C2932203773B00D9F496 /* KeyBackupBannersPreferences.swift */; }; + B104C2942203773C00D9F496 /* KeyBackupBannerPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = B104C2932203773B00D9F496 /* KeyBackupBannerPreferences.swift */; }; B1098BDF21ECE09F000DDA48 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDA21ECE09E000DDA48 /* Strings.swift */; }; B1098BE121ECE09F000DDA48 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDC21ECE09E000DDA48 /* Images.swift */; }; B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */; }; @@ -60,8 +60,8 @@ B1098C0D21ED07E4000DDA48 /* NavigationRouter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */; }; B1098C1021ED07E4000DDA48 /* Presentable.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0B21ED07E4000DDA48 /* Presentable.swift */; }; B1098C1121ED07E4000DDA48 /* NavigationRouterType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */; }; - B10B3B5B2201DD740072C76B /* KeyBackupSetupBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10B3B592201DD740072C76B /* KeyBackupSetupBannerCell.swift */; }; - B10B3B5C2201DD740072C76B /* KeyBackupSetupBannerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B10B3B5A2201DD740072C76B /* KeyBackupSetupBannerCell.xib */; }; + B10B3B5B2201DD740072C76B /* KeyBackupBannerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B10B3B592201DD740072C76B /* KeyBackupBannerCell.swift */; }; + B10B3B5C2201DD740072C76B /* KeyBackupBannerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B10B3B5A2201DD740072C76B /* KeyBackupBannerCell.xib */; }; B1107EC82200B0720038014B /* KeyBackupRecoverSuccessViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */; }; B1107ECA2200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */; }; B110871921EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */; }; @@ -511,7 +511,7 @@ 92726A481F58737A004AD26F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 92726A4F1F587393004AD26F /* SiriIntents.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SiriIntents.entitlements; sourceTree = ""; }; 92726A501F587410004AD26F /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; - B104C2932203773B00D9F496 /* KeyBackupBannersPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupBannersPreferences.swift; sourceTree = ""; }; + B104C2932203773B00D9F496 /* KeyBackupBannerPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupBannerPreferences.swift; sourceTree = ""; }; B1098BDA21ECE09E000DDA48 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; B1098BDC21ECE09E000DDA48 /* Images.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = ""; }; B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiotDefaults.swift; sourceTree = ""; }; @@ -532,8 +532,8 @@ B1098C0821ED07E4000DDA48 /* NavigationRouter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouter.swift; sourceTree = ""; }; B1098C0B21ED07E4000DDA48 /* Presentable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Presentable.swift; sourceTree = ""; }; B1098C0C21ED07E4000DDA48 /* NavigationRouterType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationRouterType.swift; sourceTree = ""; }; - B10B3B592201DD740072C76B /* KeyBackupSetupBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupBannerCell.swift; sourceTree = ""; }; - B10B3B5A2201DD740072C76B /* KeyBackupSetupBannerCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KeyBackupSetupBannerCell.xib; sourceTree = ""; }; + B10B3B592201DD740072C76B /* KeyBackupBannerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupBannerCell.swift; sourceTree = ""; }; + B10B3B5A2201DD740072C76B /* KeyBackupBannerCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = KeyBackupBannerCell.xib; sourceTree = ""; }; B1107EC72200B0720038014B /* KeyBackupRecoverSuccessViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverSuccessViewController.swift; sourceTree = ""; }; B1107EC92200B09F0038014B /* KeyBackupRecoverSuccessViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupRecoverSuccessViewController.storyboard; sourceTree = ""; }; B110871821EF8077003554A5 /* KeyBackupSetupRecoveryKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupRecoveryKeyViewController.swift; sourceTree = ""; }; @@ -1330,21 +1330,13 @@ B1107ECB2201BE800038014B /* Banners */ = { isa = PBXGroup; children = ( - B104C2932203773B00D9F496 /* KeyBackupBannersPreferences.swift */, - B1107ECC2201BEAF0038014B /* Setup */, + B104C2932203773B00D9F496 /* KeyBackupBannerPreferences.swift */, + B10B3B592201DD740072C76B /* KeyBackupBannerCell.swift */, + B10B3B5A2201DD740072C76B /* KeyBackupBannerCell.xib */, ); path = Banners; sourceTree = ""; }; - B1107ECC2201BEAF0038014B /* Setup */ = { - isa = PBXGroup; - children = ( - B10B3B592201DD740072C76B /* KeyBackupSetupBannerCell.swift */, - B10B3B5A2201DD740072C76B /* KeyBackupSetupBannerCell.xib */, - ); - path = Setup; - sourceTree = ""; - }; B110871E21F098EF003554A5 /* ActivityIndicator */ = { isa = PBXGroup; children = ( @@ -3231,7 +3223,7 @@ 3284A35120A07C210044F922 /* postMessageAPI.js in Resources */, B1B557A220EF58AD00210D55 /* ContactTableViewCell.xib in Resources */, B1B558EB20EF768F00210D55 /* RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib in Resources */, - B10B3B5C2201DD740072C76B /* KeyBackupSetupBannerCell.xib in Resources */, + B10B3B5C2201DD740072C76B /* KeyBackupBannerCell.xib in Resources */, B1B5581820EF625800210D55 /* PreviewRoomTitleView.xib in Resources */, B1B5583020EF66BA00210D55 /* RoomIdOrAliasTableViewCell.xib in Resources */, B1B558BF20EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib in Resources */, @@ -3567,7 +3559,7 @@ B1B5574120EE6C4D00210D55 /* RecentsViewController.m in Sources */, B1D250D82118AA0A000F4E93 /* RoomPredecessorBubbleCell.m in Sources */, B1B5577120EE702800210D55 /* StickerPickerViewController.m in Sources */, - B104C2942203773C00D9F496 /* KeyBackupBannersPreferences.swift in Sources */, + B104C2942203773C00D9F496 /* KeyBackupBannerPreferences.swift in Sources */, B1B5572020EE6C4D00210D55 /* ContactsTableViewController.m in Sources */, B1B5581920EF625800210D55 /* RoomTitleView.m in Sources */, B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */, @@ -3579,7 +3571,7 @@ B1B5571E20EE6C4D00210D55 /* ContactDetailsViewController.m in Sources */, B1798302211B13B3001FD722 /* OnBoardingManager.swift in Sources */, B1B5573520EE6C4D00210D55 /* GroupDetailsViewController.m in Sources */, - B10B3B5B2201DD740072C76B /* KeyBackupSetupBannerCell.swift in Sources */, + B10B3B5B2201DD740072C76B /* KeyBackupBannerCell.swift in Sources */, B1098BFA21ECFE65000DDA48 /* KeyBackupSetupPassphraseViewModel.swift in Sources */, B1B5575220EE6C4D00210D55 /* RoomKeyRequestViewController.m in Sources */, F083BD1E1E7009ED00A9B29C /* AppDelegate.m in Sources */, diff --git a/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift similarity index 60% rename from Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift rename to Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift index aaca7c2c3..e0f2ca6ab 100644 --- a/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.swift +++ b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift @@ -16,12 +16,12 @@ import UIKit -@objc protocol KeyBackupSetupBannerCellDelegate: class { - func keyBackupSetupBannerCellDidTapCloseAction(_ cell: KeyBackupSetupBannerCell) +@objc protocol KeyBackupBannerCellDelegate: class { + func keyBackupBannerCellDidTapCloseAction(_ cell: KeyBackupBannerCell) } @objcMembers -final class KeyBackupSetupBannerCell: MXKTableViewCell { +final class KeyBackupBannerCell: MXKTableViewCell { // MARK: - Properties @@ -33,7 +33,7 @@ final class KeyBackupSetupBannerCell: MXKTableViewCell { // MARK: Public - weak var delegate: KeyBackupSetupBannerCellDelegate? + weak var delegate: KeyBackupBannerCellDelegate? // MARK: - Overrides @@ -70,9 +70,31 @@ final class KeyBackupSetupBannerCell: MXKTableViewCell { self.closeButton.setImage(closeImage, for: .normal) } + // MARK: - Public + + func configure(for banner: KeyBackupBanner) { + let attributedTitle: NSAttributedString? + let theme = ThemeService.shared().theme + + switch banner { + case .setup: + let setupAttributedTitle = NSMutableAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart1, attributes: [.foregroundColor: theme.tintColor]) + setupAttributedTitle.append(NSAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart2, attributes: [.foregroundColor: theme.textPrimaryColor])) + attributedTitle = setupAttributedTitle + case .recover: + let recoverAttributedTitle = NSMutableAttributedString(string: VectorL10n.keyBackupRecoverBannerTitlePart1, attributes: [.foregroundColor: theme.tintColor]) + recoverAttributedTitle.append(NSAttributedString(string: VectorL10n.keyBackupRecoverBannerTitlePart2, attributes: [.foregroundColor: theme.textPrimaryColor])) + attributedTitle = recoverAttributedTitle + case .none: + attributedTitle = nil + } + + self.informationLabel.attributedText = attributedTitle + } + // MARK: - Actions @IBAction private func closeButtonAction(_ sender: Any) { - self.delegate?.keyBackupSetupBannerCellDidTapCloseAction(self) + self.delegate?.keyBackupBannerCellDidTapCloseAction(self) } } diff --git a/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib similarity index 96% rename from Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib rename to Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib index e2eb36af0..fa630ec0a 100644 --- a/Riot/Modules/KeyBackup/Banners/Setup/KeyBackupSetupBannerCell.xib +++ b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib @@ -1,17 +1,13 @@ - - - - - + diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index 37a5b6f37..3d91a54f2 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -9,3 +9,4 @@ #import "RiotNavigationController.h" #import "ThemeService.h" #import "TableViewCellWithCheckBoxAndLabel.h" +#import "RecentsDataSource.h" From 898809d8812b6cfec846ff7ae66c9ec939a212fc Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 1 Feb 2019 09:51:57 +0100 Subject: [PATCH 157/244] Handle key backup recover banner display --- .../Recents/DataSources/RecentsDataSource.m | 73 ++++++++++++++----- Riot/Modules/Home/HomeViewController.m | 67 ++++++++++------- 2 files changed, 95 insertions(+), 45 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index d0f5b3bdd..597560053 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -40,7 +40,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSourceTapOnDirectoryServerChange"; -@interface RecentsDataSource() +@interface RecentsDataSource() { NSMutableArray* invitesCellDataArray; NSMutableArray* favoriteCellDataArray; @@ -173,6 +173,8 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou { KeyBackupBannerPreferences *keyBackupBannersPreferences = KeyBackupBannerPreferences.shared; + NSString *keyBackupVersion = self.mxSession.crypto.backup.keyBackupVersion.version; + switch (self.mxSession.crypto.backup.state) { case MXKeyBackupStateDisabled: // Show key backup setup banner only if user has not hidden it once. @@ -187,8 +189,15 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou break; case MXKeyBackupStateNotTrusted: case MXKeyBackupStateWrongBackUpVersion: - // TODO: Show key backup recover banner. - keyBackupBanner = KeyBackupBannerNone; + // Show key backup recover banner only if user has not hidden it for the gieven versiopn. + if (keyBackupVersion && [keyBackupBannersPreferences isRecoverBannerHiddenFor:keyBackupVersion]) + { + keyBackupBanner = KeyBackupBannerNone; + } + else + { + keyBackupBanner = KeyBackupBannerRecover; + } break; default: keyBackupBanner = KeyBackupBannerNone; @@ -208,7 +217,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou keyBackupBannersPreferences.hideSetupBanner = YES; break; case KeyBackupBannerRecover: - // TODO: Hide key backup recover banner. + { + NSString *keyBackupVersion = self.mxSession.crypto.backup.keyBackupVersion.version; + if (keyBackupVersion) + { + [keyBackupBannersPreferences hideRecoverBannerFor:keyBackupVersion]; + } + } break; default: break; @@ -901,6 +916,36 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return sectionHeader; } +//- (void)configureKeyBackupBannerCell:(KeyBackupBannerCell*)keyBackupBannerCell forKeyBackupBanner:(KeyBackupBanner)keyBackupBanner { +// +// NSAttributedString *attributedTitle; +// +// id theme = ThemeService.shared.theme; +// +// switch (keyBackupBanner) { +// case KeyBackupBannerSetup: +// { +// NSMutableAttributedString *setupAttributedTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_setup_banner_title_part1", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.tintColor}]; +// [setupAttributedTitle appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_setup_banner_title_part2", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.textPrimaryColor }]]; +// +// attributedTitle = setupAttributedTitle; +// } +// break; +// case KeyBackupBannerRecover: +// { +// NSMutableAttributedString *setupAttributedTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_recover_banner_title_part1", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.tintColor}]; +// [setupAttributedTitle appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_recover_banner_title_part2", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.textPrimaryColor }]]; +// +// attributedTitle = setupAttributedTitle; +// } +// break; +// default: +// break; +// } +// +// [keyBackupBannerCell fillWith:attributedTitle]; +//} + - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // Sanity check @@ -913,20 +958,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (indexPath.section == self.keyBackupBannerSection) { - UITableViewCell* cell; - - switch (self.keyBackupBanner) { - case KeyBackupBannerSetup: { - KeyBackupSetupBannerCell* keyBackupSetupBannerCell = [tableView dequeueReusableCellWithIdentifier:KeyBackupSetupBannerCell.defaultReuseIdentifier forIndexPath:indexPath]; - keyBackupSetupBannerCell.delegate = self; - cell = keyBackupSetupBannerCell; - } - break; - default: - break; - } - - return cell; + KeyBackupBannerCell* keyBackupBannerCell = [tableView dequeueReusableCellWithIdentifier:KeyBackupBannerCell.defaultReuseIdentifier forIndexPath:indexPath]; + [keyBackupBannerCell configureFor:self.keyBackupBanner]; + keyBackupBannerCell.delegate = self; + return keyBackupBannerCell; } else if (indexPath.section == directorySection) { @@ -1717,7 +1752,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou #pragma mark - KeyBackupSetupBannerCellDelegate -- (void)keyBackupSetupBannerCellDidTapCloseAction:(KeyBackupSetupBannerCell * _Nonnull)cell +- (void)keyBackupBannerCellDidTapCloseAction:(KeyBackupBannerCell * _Nonnull)cell { [self hideKeyBackupBanner:self.keyBackupBanner]; } diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 51145c258..2d47f630c 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -27,7 +27,7 @@ #import "MXRoom+Riot.h" -@interface HomeViewController () +@interface HomeViewController () { RecentsDataSource *recentsDataSource; @@ -42,7 +42,8 @@ } @property (nonatomic, strong) KeyBackupSetupCoordinatorBridgePresenter *keyBackupSetupCoordinatorBridgePresenter; -@property (nonatomic, strong) KeyBackupSetupBannerCell *keyBackupSetupBannerPrototypeCell; +@property (nonatomic, strong) KeyBackupRecoverCoordinatorBridgePresenter *keyBackupRecoverCoordinatorBridgePresenter; +@property (nonatomic, strong) KeyBackupBannerCell *keyBackupBannerPrototypeCell; @end @@ -77,7 +78,7 @@ [self.recentsTableView registerClass:TableViewCellWithCollectionView.class forCellReuseIdentifier:TableViewCellWithCollectionView.defaultReuseIdentifier]; // Register key backup banner cells - [self.recentsTableView registerNib:KeyBackupSetupBannerCell.nib forCellReuseIdentifier:KeyBackupSetupBannerCell.defaultReuseIdentifier]; + [self.recentsTableView registerNib:KeyBackupBannerCell.nib forCellReuseIdentifier:KeyBackupBannerCell.defaultReuseIdentifier]; // Change the table data source. It must be the home view controller itself. self.recentsTableView.dataSource = self; @@ -144,13 +145,13 @@ } } -- (KeyBackupSetupBannerCell *)keyBackupSetupBannerPrototypeCell +- (KeyBackupBannerCell *)keyBackupBannerPrototypeCell { - if (!_keyBackupSetupBannerPrototypeCell) + if (!_keyBackupBannerPrototypeCell) { - _keyBackupSetupBannerPrototypeCell = [self.recentsTableView dequeueReusableCellWithIdentifier:KeyBackupSetupBannerCell.defaultReuseIdentifier]; + _keyBackupBannerPrototypeCell = [self.recentsTableView dequeueReusableCellWithIdentifier:KeyBackupBannerCell.defaultReuseIdentifier]; } - return _keyBackupSetupBannerPrototypeCell; + return _keyBackupBannerPrototypeCell; } - (void)presentKeyBackupSetup @@ -163,6 +164,19 @@ self.keyBackupSetupCoordinatorBridgePresenter = keyBackupSetupCoordinatorBridgePresenter; } +- (void)presentKeyBackupRecover +{ + MXKeyBackupVersion *keyBackupVersion = self.mainSession.crypto.backup.keyBackupVersion; + if (keyBackupVersion) + { + KeyBackupRecoverCoordinatorBridgePresenter *keyBackupRecoverCoordinatorBridgePresenter = [[KeyBackupRecoverCoordinatorBridgePresenter alloc] initWithSession:self.mainSession keyBackupVersion:keyBackupVersion]; + keyBackupRecoverCoordinatorBridgePresenter.delegate = self; + + [keyBackupRecoverCoordinatorBridgePresenter presentFrom:self animated:YES]; + + self.keyBackupRecoverCoordinatorBridgePresenter = keyBackupRecoverCoordinatorBridgePresenter; + } +} #pragma mark - Override RecentsViewController @@ -369,27 +383,17 @@ else if (indexPath.section == recentsDataSource.keyBackupBannerSection) { CGFloat height = 0.0; - UITableViewCell *sizingCell; + KeyBackupBannerCell *sizingCell = self.keyBackupBannerPrototypeCell; - switch (recentsDataSource.keyBackupBanner) { - case KeyBackupBannerSetup: - { - sizingCell = self.keyBackupSetupBannerPrototypeCell; - } - break; - default: - break; - } + [sizingCell configureFor:recentsDataSource.keyBackupBanner]; + + [sizingCell layoutIfNeeded]; + + CGSize fittingSize = UILayoutFittingCompressedSize; + fittingSize.width = CGRectGetWidth(tableView.frame); + + height = [sizingCell systemLayoutSizeFittingSize:fittingSize withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel].height; - if (sizingCell) - { - [sizingCell layoutIfNeeded]; - - CGSize fittingSize = UILayoutFittingCompressedSize; - fittingSize.width = CGRectGetWidth(tableView.frame); - - height = [sizingCell systemLayoutSizeFittingSize:fittingSize withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel].height; - } return height; } @@ -429,6 +433,7 @@ [self presentKeyBackupSetup]; break; default: + [self presentKeyBackupRecover]; break; } } @@ -693,4 +698,14 @@ self.keyBackupSetupCoordinatorBridgePresenter = nil; } +- (void)keyBackupRecoverCoordinatorBridgePresenterDidCancel:(KeyBackupRecoverCoordinatorBridgePresenter * _Nonnull)keyBackupRecoverCoordinatorBridgePresenter { + [keyBackupRecoverCoordinatorBridgePresenter dismissWithAnimated:YES]; + self.keyBackupRecoverCoordinatorBridgePresenter = nil; +} + +- (void)keyBackupRecoverCoordinatorBridgePresenterDidRecover:(KeyBackupRecoverCoordinatorBridgePresenter * _Nonnull)keyBackupRecoverCoordinatorBridgePresenter { + [keyBackupRecoverCoordinatorBridgePresenter dismissWithAnimated:YES]; + self.keyBackupRecoverCoordinatorBridgePresenter = nil; +} + @end From 210eb3159bbcb7ac3dc5d3d5e62c4c719b318ebd Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 1 Feb 2019 09:58:36 +0100 Subject: [PATCH 158/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 40f773e6f..68d3c8604 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -11,6 +11,7 @@ Improvements: * Key backup: Implement recover screen (#2196). * Key backup: Add a dedicated section to settings (#2193). * Key backup: Implement setup reminder (#2211). + * Key backup: Implement recover reminder (#2206). Bug fix: * Use white scroll bar on dark themes (#2158). From 4173bf8dc60e3ea45ae2d3df63ab73fd3472dc5c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 1 Feb 2019 10:15:39 +0100 Subject: [PATCH 159/244] Fix Manu's comments --- .../Recents/DataSources/RecentsDataSource.m | 32 +------------------ Riot/Modules/Home/HomeViewController.m | 4 ++- 2 files changed, 4 insertions(+), 32 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 597560053..fe15bcfaa 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -189,7 +189,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou break; case MXKeyBackupStateNotTrusted: case MXKeyBackupStateWrongBackUpVersion: - // Show key backup recover banner only if user has not hidden it for the gieven versiopn. + // Show key backup recover banner only if user has not hidden it for the given version. if (keyBackupVersion && [keyBackupBannersPreferences isRecoverBannerHiddenFor:keyBackupVersion]) { keyBackupBanner = KeyBackupBannerNone; @@ -916,36 +916,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return sectionHeader; } -//- (void)configureKeyBackupBannerCell:(KeyBackupBannerCell*)keyBackupBannerCell forKeyBackupBanner:(KeyBackupBanner)keyBackupBanner { -// -// NSAttributedString *attributedTitle; -// -// id theme = ThemeService.shared.theme; -// -// switch (keyBackupBanner) { -// case KeyBackupBannerSetup: -// { -// NSMutableAttributedString *setupAttributedTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_setup_banner_title_part1", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.tintColor}]; -// [setupAttributedTitle appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_setup_banner_title_part2", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.textPrimaryColor }]]; -// -// attributedTitle = setupAttributedTitle; -// } -// break; -// case KeyBackupBannerRecover: -// { -// NSMutableAttributedString *setupAttributedTitle = [[NSMutableAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_recover_banner_title_part1", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.tintColor}]; -// [setupAttributedTitle appendAttributedString:[[NSAttributedString alloc] initWithString:NSLocalizedStringFromTable(@"key_backup_recover_banner_title_part2", @"Vector", nil) attributes:@{ NSForegroundColorAttributeName: theme.textPrimaryColor }]]; -// -// attributedTitle = setupAttributedTitle; -// } -// break; -// default: -// break; -// } -// -// [keyBackupBannerCell fillWith:attributedTitle]; -//} - - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // Sanity check diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 2d47f630c..5d7230044 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -432,9 +432,11 @@ case KeyBackupBannerSetup: [self presentKeyBackupSetup]; break; - default: + case KeyBackupBannerRecover: [self presentKeyBackupRecover]; break; + default: + break; } } } From c09d3fb6578e48dac2d02c411dd2e0f54ee0fc08 Mon Sep 17 00:00:00 2001 From: Osoitz Date: Mon, 21 Jan 2019 21:08:54 +0000 Subject: [PATCH 160/244] Translated using Weblate (Basque) Currently translated at 100.0% (520 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/eu/ --- Riot/Assets/eu.lproj/Vector.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/eu.lproj/Vector.strings b/Riot/Assets/eu.lproj/Vector.strings index 9077f5bde..e1e15fe99 100644 --- a/Riot/Assets/eu.lproj/Vector.strings +++ b/Riot/Assets/eu.lproj/Vector.strings @@ -39,7 +39,7 @@ "bug_report_description" = "Azaldu akatsa. Zer egin duzu? Zer uste zenuen gertatuko zela? Zer gertatu da benetan?"; "bug_report_logs_description" = "Arazoak aztertzeari begira, bezero honen egunkariak arazte-txosten honekin batera bidaliko dira. Goiko testua besterik ez baduzu bidali nahi, desmarkatu:"; "rage_shake_prompt" = "Telefonoa amorruz astintzen zabiltzala dirudi. Akats baten berri eman nahi duzu?"; -"bug_report_prompt" = "Azken aldian aplikazioa kraskatu da. Kraskatze txostena bidali nahi duzu?"; +"bug_report_prompt" = "Azken aldian aplikazioa kraskatu da. Kraskatze-txostena bidali nahi duzu?"; "auth_register" = "Erregistratu"; // Authentication "auth_login" = "Hasi saioa"; @@ -409,7 +409,7 @@ "no_voip_title" = "Deia jasotzen"; "no_voip" = "%@ zu deitzen ari da baina %@(e)k ez ditu deiak onartzen oraindik.\nJakinarazpen hau ezikusi dezakezu eta deia beste gailu batetik hartu, edo deia baztertu."; // Crash report -"google_analytics_use_prompt" = "%@ hobetzen lagundu nahi duzu kraskatze era erabilera-txosten anonimoak automatikoki bidaliz?"; +"google_analytics_use_prompt" = "%@ hobetzen lagundu nahi duzu kraskatze-txosten era erabilera datu anonimoak automatikoki bidaliz?"; "e2e_need_log_in_again" = "Berriro hasi behar duzu saioa muturretik muturrerako zifratzerako gailu honek gakoak sortzeko eta gako publikoa zure hasiera zerbitzarira bidali behar duzu.\nHau behin bakarrik egin behar duzu, barkatu eragozpenak."; "bug_crash_report_title" = "Kraskatze-txostena"; "bug_crash_report_description" = "Azaldu zer zeunden egiten programa kraskatu aurretik:"; From 598c2a86af9348852c164e30b7f025c479f5c010 Mon Sep 17 00:00:00 2001 From: Juho Ylikorpi Date: Tue, 8 Jan 2019 22:08:57 +0000 Subject: [PATCH 161/244] Translated using Weblate (Finnish) Currently translated at 5.1% (27 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/fi/ --- Riot/Assets/fi.lproj/Vector.strings | 30 ++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/fi.lproj/Vector.strings b/Riot/Assets/fi.lproj/Vector.strings index 8b1378917..713e12ab2 100644 --- a/Riot/Assets/fi.lproj/Vector.strings +++ b/Riot/Assets/fi.lproj/Vector.strings @@ -1 +1,29 @@ - +// Titles +"title_home" = "Koti"; +"title_favourites" = "Suosikit"; +"title_people" = "Ihmiset"; +"title_rooms" = "Huoneet"; +"title_groups" = "Yhteisöt"; +"warning" = "Varoitus"; +// Actions +"view" = "Näytä"; +"next" = "Seuraava"; +"back" = "Takaisin"; +"continue" = "Jatka"; +"create" = "Luo"; +"start" = "Aloita"; +"leave" = "Poistu"; +"remove" = "Poista"; +"invite" = "Kutsu"; +"retry" = "Yritä uudelleen"; +"on" = "On"; +"off" = "Off"; +"cancel" = "Peruuta"; +"save" = "Tallenna"; +"join" = "Liity"; +"decline" = "Kiellä"; +"accept" = "Hyväksy"; +"preview" = "Esikatselu"; +"camera" = "Kamera"; +"voice" = "Ääni"; +"video" = "Video"; From 9c497f7b818608096b060a5596c1e34b95b985a2 Mon Sep 17 00:00:00 2001 From: Karol Kosek Date: Sun, 13 Jan 2019 01:23:36 +0000 Subject: [PATCH 162/244] Translated using Weblate (Polish) Currently translated at 87.5% (455 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/pl/ --- Riot/Assets/pl.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/pl.lproj/Vector.strings b/Riot/Assets/pl.lproj/Vector.strings index 234ae0357..86071d940 100644 --- a/Riot/Assets/pl.lproj/Vector.strings +++ b/Riot/Assets/pl.lproj/Vector.strings @@ -487,3 +487,4 @@ // Media picker "media_picker_library" = "Biblioteka"; "large_badge_value_k_format" = "%.1fK"; +"bug_crash_report_title" = "Raport o awarii"; From 5966c540e367b8a57c7fdd58617d3508018af596 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 1 Feb 2019 04:29:57 +0000 Subject: [PATCH 163/244] Translated using Weblate (Russian) Currently translated at 100.0% (520 of 520 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index 4d5019b38..55e217940 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -404,7 +404,7 @@ "unknown_devices_alert" = "Эта комната содержит устройства, которые еще не были проверены.\nЭто означает, что нет гарантии, что устройства принадлежат пользователям, тем, за кого они сами себя выдают.\nПеред продолжением рекомендуется пройти процедуру проверки для каждого устройства, но при желании можно повторно отправить сообщение без проверки."; "room_preview_try_join_an_unknown_room" = "Вы пытаетесь получить доступ к %@. Хотите присоединиться к обсуждению?"; "settings_config_no_build_info" = "Нет информации о выпуске"; -"settings_sign_out_e2e_warn" = "Будут утеряны сквозные ключи шифрования. Это означает, что вы больше не сможете читать старые сообщения в зашифрованных комнатах на этом устройстве."; +"settings_sign_out_e2e_warn" = "Будут утеряны ключи сквозного шифрования. Это означает, что вы больше не сможете читать старые сообщения в зашифрованных комнатах на этом устройстве."; "settings_remove_email_prompt_msg" = "Вы действительно хотите удалить адрес электронной почты %@?"; "settings_remove_phone_prompt_msg" = "Вы действительно хотите удалить номер телефона %@?"; "settings_pin_rooms_with_missed_notif" = "Закрепить комнаты с пропущенными уведомлениями"; @@ -550,8 +550,8 @@ "room_resource_limit_exceeded_message_contact_2_link" = "обратитесь к администратору сервиса"; "room_resource_limit_exceeded_message_contact_3" = " для продолжения его использования."; "room_event_action_view_decrypted_source" = "Посмотреть расшифрованные исходники"; -"room_resource_usage_limit_reached_message_1_default" = "Этот сервер превысил один из лимитов ресурсов, так что "; -"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Этот сервер превысил месячный лимит активных пользователей, так что "; +"room_resource_usage_limit_reached_message_1_default" = "Превышен один из ресурсных лимитов сервера, по этому "; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Сервер достиг ежемесячного ограничения активных пользователей, так что "; "room_resource_usage_limit_reached_message_2" = "некоторые пользователи не смогут залогиниться."; "room_resource_usage_limit_reached_message_contact_3" = " что бы увеличить лимит."; "settings_labs_room_members_lazy_loading" = "Ленивая подгрузка собеседников"; From 99d1677069f8546182b63730f69875cea6740c86 Mon Sep 17 00:00:00 2001 From: Juho Ylikorpi Date: Tue, 8 Jan 2019 22:11:40 +0000 Subject: [PATCH 164/244] Translated using Weblate (Finnish) Currently translated at 3.8% (1 of 26 strings) Translation: Riot iOS/Riot iOS (Push) Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios-push/fi/ --- Riot/Assets/fi.lproj/Localizable.strings | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/fi.lproj/Localizable.strings b/Riot/Assets/fi.lproj/Localizable.strings index 8b1378917..3e339a60d 100644 --- a/Riot/Assets/fi.lproj/Localizable.strings +++ b/Riot/Assets/fi.lproj/Localizable.strings @@ -1 +1,2 @@ - +/* New message from a specific person, not referencing a room */ +"MSG_FROM_USER" = "Viesti käyttäjältä %@"; From 4ba4193f817d9113b8e212895ddfa96ed512fdcc Mon Sep 17 00:00:00 2001 From: Karol Kosek Date: Wed, 9 Jan 2019 22:22:40 +0000 Subject: [PATCH 165/244] Translated using Weblate (Polish) Currently translated at 73.0% (19 of 26 strings) Translation: Riot iOS/Riot iOS (Push) Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios-push/pl/ --- Riot/Assets/pl.lproj/Localizable.strings | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Riot/Assets/pl.lproj/Localizable.strings b/Riot/Assets/pl.lproj/Localizable.strings index 03f3655bb..77a3fa5b0 100644 --- a/Riot/Assets/pl.lproj/Localizable.strings +++ b/Riot/Assets/pl.lproj/Localizable.strings @@ -22,3 +22,17 @@ "MSGS_FROM_TWO_PLUS_USERS" = "%@ nowych wiadomości od %@, %@ i innych"; /* Look, stuff's happened, alright? Just open the app. */ "MSGS_IN_TWO_PLUS_ROOMS" = "%@ nowych wiadomości w %@, %@ i innych"; +/* New action message from a specific person, not referencing a room. */ +"IMAGE_FROM_USER" = "%@ wysłał(a) Tobie zdjęcie %@"; +/* New action message from a specific person in a named room. */ +"IMAGE_FROM_USER_IN_ROOM" = "%@ wysłał(a) Tobie zdjęcie %@ w %@"; +/* Multiple unread messages from a specific person, not referencing a room */ +"MSGS_FROM_USER" = "%@ nowych wiadomości w %@"; +/* Multiple messages in two rooms */ +"MSGS_IN_TWO_ROOMS" = "%@ nowych wiadomości w %@ i %@"; +/* A user has invited you to a named room */ +"USER_INVITE_TO_NAMED_ROOM" = "%@ zaprosił(a) Ciebie do %@"; +/* A user has invited you to an (unamed) group chat */ +"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ zaprosił(a) Ciebie do rozmowy grupowej"; +/* A user has invited you to a chat */ +"USER_INVITE_TO_CHAT" = "%@ zaprosił(a) Ciebie do rozmowy"; From 09f9c416ae00a0e9521731a812588b8a20587c4d Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 1 Feb 2019 12:21:10 +0000 Subject: [PATCH 166/244] Translated using Weblate (Russian) Currently translated at 100.0% (587 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index 55e217940..c2712a2bf 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -558,3 +558,70 @@ "settings_labs_room_members_lazy_loading_error_message" = "Ваш сервер не поддерживает ленивую подгрузку собеседников. Попробуйте позже."; "homeserver_connection_lost" = "Невозможно соединиться с этим сервером."; "auth_accept_policies" = "Пожалуйста ознакомьтесь и подтвердите согласие с политикой этого сервера:"; +"settings_key_backup_info_checking" = "Проверка ..."; +"settings_key_backup_info_none" = "Безопасное восстановление сообщений не настроено."; +"settings_key_backup" = "БЕЗОПАСНОЕ ВОССТАНОВЛЕНИЕ СООБЩЕНИЙ"; +"settings_key_backup_info_version" = "Версия ключа резервного копирования: %@"; +"settings_key_backup_info_algorithm" = "Алгоритм: %@"; +"settings_key_backup_info_valid" = "Безопасное восстановление сообщений успешно настроено для этого устройства."; +"settings_key_backup_info_not_valid" = "Безопасное восстановление сообщений не активно на этом устройстве."; +"settings_key_backup_info_progress" = "Резервное копирование ключей %@..."; +"settings_key_backup_info_progress_done" = "Все ключи сохранены"; +"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Для Безопасного Восстановления Сообщений на этом устройстве, проверьте %@."; +"settings_key_backup_info_not_trusted_fix_action" = "Для Безопасного Восстановления Сообщений на этом устройстве, требуется пароль или ключ восстановления."; +"settings_key_backup_info_trust_signature_unknown" = "Резервная копия подписана устройством с идентификатором: %@"; +"settings_key_backup_info_trust_signature_valid" = "Резервная копия имеет валидную подпись этого устройства"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Резервная копия имеет валидную подпись %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Резервная копия подписана %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Резервная копия имеет невалидную подпись %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Резервная копия имеет невалидную подпись %@"; +"settings_key_backup_button_create" = "Настройка Безопасного Восстановления Сообщений"; +"settings_key_backup_button_restore" = "Восстановить резервную копию"; +"settings_key_backup_button_delete" = "Удалить резервную копию"; +"settings_key_backup_button_verify" = "Проверить"; +"settings_key_backup_delete_confirmation_prompt_title" = "Удалить резервную копию"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Удалить резервную копию ключей шифрования с сервера? Вы больше не сможете использовать ключ восстановления для чтения истории зашифрованных сообщений."; +"room_does_not_exist" = "%@ не существует"; +"key_backup_setup_title" = "Восстановление Сообщений"; +"key_backup_setup_skip_action" = "Пропустить"; +"key_backup_setup_skip_alert_title" = "Вы уверены?"; +"key_backup_setup_skip_alert_message" = "Вы можете потерять зашифрованные сообщения, если выйдете из системы или потеряете свое устройство."; +"key_backup_setup_skip_alert_skip_action" = "Пропустить"; +"key_backup_setup_intro_title" = "Никогда не теряйте зашифрованных сообщений"; +"key_backup_setup_intro_info" = "Настройте Безопасное Восстановление Сообщений на случай утери устройства или выхода из него."; +"key_backup_setup_intro_setup_action" = "Настроить"; +"key_backup_setup_passphrase_info" = "Защитите зашифрованную историю сообщений парольной фразой.\n\nОн понадобится вам, если вы выйдете из системы или потеряете доступ к этому устройству."; +"key_backup_setup_passphrase_passphrase_title" = "Ввод"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Введите парольную фразу"; +"key_backup_setup_passphrase_passphrase_valid" = "Отлично!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Попробуйте добавить слово"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Подтвердить"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Повторите парольную фразу"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Отлично!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Парольные фразы не совпадает"; +"key_backup_setup_passphrase_set_passphrase_action" = "Задать парольную фразу для восстановления"; +"key_backup_setup_recovery_key_recovery_key_title" = "Ключ для восстановления"; +"key_backup_setup_recovery_key_make_copy_action" = "Сделать копию"; +"key_backup_setup_recovery_key_made_copy_action" = "Я сделал копию"; +"key_backup_recover_title" = "Безопасные Сообщения"; +"key_backup_recover_empty_backup_title" = "Пустая резервная копия"; +"key_backup_recover_empty_backup_message" = "Нет ключа для восстановления"; +"key_backup_recover_from_passphrase_info" = "Используйте парольную фразу восстановления для разблокировки истории безопасных сообщений."; +"key_backup_recover_from_passphrase_passphrase_title" = "Ввод"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Введите парольную фразу"; +"key_backup_recover_from_passphrase_recover_action" = "Разблокировать историю"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Не знаете вашу парольную фразу для восстановления? Вы можете "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "используйте ключ восстановления"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Используйте ключ восстановления для разблокировки истории безопасных сообщений."; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Ввод"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Введите ключ восстановления"; +"key_backup_recover_from_recovery_key_recover_action" = "Разблокировать историю"; +"key_backup_recover_success_info" = "Резервная копия восстановлена!"; +"key_backup_recover_done_action" = "Готово"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Потеряли ключ восстановления? В настройках вы можете создать новый."; +"key_backup_setup_banner_title_part1" = "Настройка Безопасного Восстановления Сообщений"; +"key_backup_recover_banner_title_part1" = "Запуск Безопасного Восстановления Сообщений"; +"key_backup_recover_banner_title_part2" = " для чтения истории зашифрованных сообщений на этом устройстве"; +"key_backup_setup_banner_title_part2" = " чтобы никогда не потерять зашифрованные сообщения"; +"key_backup_setup_recovery_key_info" = "Сделайте копию ключа восстановления и сохраните его в надёжном месте.\n\nКак сеть безопасности, вы можете использовать ее для восстановления истории зашифрованных сообщений, если вы забыли свою фразу-пароль восстановления."; From 9cf0909ca0bfc8c51481cb2820b08f379c8a747a Mon Sep 17 00:00:00 2001 From: Nad Chishtie Date: Fri, 1 Feb 2019 12:28:58 +0000 Subject: [PATCH 167/244] Updated weird stray upscaled icon asset. --- .../AppIcon.appiconset/Icon-1024.png | Bin 143985 -> 58674 bytes 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-1024.png diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-1024.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-1024.png old mode 100755 new mode 100644 index 6815c4ff42746111e1d07a6475aae9196a9e0c09..ecd3015a3035b1e25ed8b50c108f3d30d6175105 GIT binary patch literal 58674 zcmeFZWn7foyFNbiFv!p$f|5g*geVdcLx*&ifC&OhN!N^ph|--S9Rf;7!x$(X(me`D zskAiw*SOC)zwuSK|_z9uyV3k3`Yqt@0^Glszs;C~S? znX!vZ=)y=uam-HXqdK|vZ){Z=M-6x?MN`;Knaub9!D*QeApCs zBSy{Wyl}i)d+cqqi4AKXHi5{vq@>l`OTEs$LhUhZ+$yI z8XHl6eyliGO`Ers+Xq7m>z|;ya|(aO(bN(Fne;Syttzx^?oow%uGTFCoiO9OLiL4G zjMW8^C=3kx-#_S_uwT(Tkv&}h=l2-21_l9>hW_Kj;4@6fXxJN6+XH$yf({M)Uq2XN zlO+FpVd8q0C^UqBh#FA;Kc7Wt!Q5&8?@k=BFmf2>LtSS2|5z76hl1l3{_pNEq!2Ic zJW}$S+W+1I_!_Y3o&S8pe>eTFrT@oI|8;D(21`yd3JyOqPOAmbjIytyt19l4>CrkuOyUKq4Fs3=Sygjxoto0jhm zEWbK2DEczUD1Lm6=1dahGjw4UZyfSj;VrbK!UJQ%qo|=BZm#WZ%E+Q;@jBPkwVZQq zGnB}jc-&J@xy7-(GBi(hgR1S9vh?30wPh4EGH~+OSmBmQQh~vD5L*$4ISZfXwR&sW z%%V;=&89FP@ywq7E%i`@3xnZ-ZVO+hGYQA+oQAd&xKdatJ156?IQDODql^ehr37wb z#@IE*ATS0bnw9iu!VT>4Tk^5M%VL2BQSH+gJ^Tv-Z8hQ=`&ul+d+FX7;OZN7$HAVn z=g@PH%41M(Rx@#5KoZ7ugSO8#QZZN){{a+w$EK2%cn3jf6q1 z3{GVP%i}-4azV3?uPDcEBY^uKFi%s z4h4>hqLaY3zMQYP?UCSWV=KzaY^vj5$m^hxd*yFc453HC2}xT0`Ur@B?J$OZZ@7nJ ztbplH4zcTehg2IxVoQFQwGHzP33C}HSef7xn+FVt=@a{%G8!frLgfU9hLO63(z{tQ z5`r_+V79~Y%y0^uRSbq0mO zyF#-|LjI=RzfO9}?3UPcx_xA3G=X(rGYX0d#fbdSxY&+Kvlwins6Imd*IUN{PttWZ zW(HrvD

UMB6f!l``Awe9YXxMh@Ouq6GhN|Jh`{Fn>+ii}nttSa{__kH3M5e+?eJ z!}lEq4$ll-KEFe<{o&*!a6O$$fZtOgWA-n9Ax58U&m6;^atr``&xrU(Ue;-Es zfQKu*z6*kfjS1ZY9(w}?SLWC1)Dj)t&l0^8Ee36xN)m<>q*D6fyd<76vzC90%|HB# zgBs5Fl4$60P>pEB!-(SWuo&Ez-a@qJx%yBjlBCj)__ePai_bGrrxLo)J9 zToBrbYB-oHw_A?s=lys@IWXr6mPLhPrAp6uuI|g#1$*ljcaG_yLbZE{oXSHHG=!>s zo9Bp>5nHo9NIqP;nBm!&Bzna5rDp@;b3U`KRjBr1`ITZW%Fq;E≫U_((}$@B=D< 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 Date: Fri, 1 Feb 2019 22:31:45 +0000 Subject: [PATCH 168/244] Translated using Weblate (French) Currently translated at 100.0% (587 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/fr/ --- Riot/Assets/fr.lproj/Vector.strings | 67 +++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index 844d41785..9366082e7 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -557,3 +557,70 @@ "room_resource_usage_limit_reached_message_2" = "quelques utilisateurs ne pourront pas se connecter."; "room_resource_usage_limit_reached_message_contact_3" = " pour augmenter cette limite."; "auth_accept_policies" = "Veuillez lire et accepter les politiques de ce serveur d'accueil :"; +"settings_key_backup" = "Récupération de message sécurisée"; +"settings_key_backup_info_checking" = "Vérification…"; +"settings_key_backup_info_none" = "La récupération de messages sécurisée n'a pas été configurée."; +"settings_key_backup_info_version" = "Version de sauvegarde de clé : %@"; +"settings_key_backup_info_algorithm" = "Algorithme : %@"; +"settings_key_backup_info_valid" = "La récupération de messages sécurisée a été correctement configurée pour cet appareil."; +"settings_key_backup_info_not_valid" = "La récupération de messages sécurisée n'est pas activée sur cet appareil."; +"settings_key_backup_info_progress" = "Sauvegarde de %@ clés…"; +"settings_key_backup_info_progress_done" = "Toutes les clés ont été sauvegardées"; +"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Pour utiliser la récupération de messages sécurisée sur cet appareil, vérifiez %@ maintenant."; +"settings_key_backup_info_not_trusted_fix_action" = "Pour utiliser la récupération de messages sécurisée sur cet appareil, fournissez votre phrase de passe ou votre clé de récupération maintenant."; +"settings_key_backup_info_trust_signature_unknown" = "La sauvegarde a une signature de l'appareil ayant pour identifiant : %@"; +"settings_key_backup_info_trust_signature_valid" = "La sauvegarde a une signature valide depuis cet appareil"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "La sauvegarde a une signature valide depuis %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "La sauvegarde a une signature depuis %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "La sauvegarde a une signature non valide depuis %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "La sauvegarde a une signature non valide depuis %@"; +"settings_key_backup_button_create" = "Configurer la récupération de messages sécurisée"; +"settings_key_backup_button_restore" = "Restaurer la sauvegarde"; +"settings_key_backup_button_delete" = "Supprimer la sauvegarde"; +"settings_key_backup_button_verify" = "Vérifier"; +"settings_key_backup_delete_confirmation_prompt_title" = "Supprimer la sauvegarde"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Supprimer vos clés de chiffrement sauvegardées sur le serveur ? Vous ne pourrez plus utiliser votre clé de récupération pour lire l'historique des messages chiffrés"; +"room_does_not_exist" = "%@ n'existe pas"; +"key_backup_setup_title" = "Récupération de messages"; +"key_backup_setup_skip_action" = "Passer"; +"key_backup_setup_skip_alert_title" = "En êtes-vous certain(e) ?"; +"key_backup_setup_skip_alert_message" = "Vous pourriez perdre vos messages sécurisés si vous vous déconnectez ou si vous perdez votre appareil."; +"key_backup_setup_skip_alert_skip_action" = "Passer"; +"key_backup_setup_intro_title" = "Ne perdez jamais vos messages chiffrés"; +"key_backup_setup_intro_info" = "Configurer la récupération de messages sécurisée au cas où vous perdez cet appareil ou que vous vous déconnectez."; +"key_backup_setup_intro_setup_action" = "Configurer"; +"key_backup_setup_passphrase_info" = "Protégez votre historique de messages chiffrés avec une phrase de passe de récupération.\n\nVous en aurez besoin si vous vous déconnectez ou si vous n'avez plus accès à cet appareil."; +"key_backup_setup_passphrase_passphrase_title" = "Saisir"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Saisir la phrase de passe"; +"key_backup_setup_passphrase_passphrase_valid" = "Super !"; +"key_backup_setup_passphrase_passphrase_invalid" = "Essayez d'ajouter un mot"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Confirmer"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Confirmer la phrase de passe"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Super !"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Les phrases de passe ne correspondent pas"; +"key_backup_setup_passphrase_set_passphrase_action" = "Définir la phrase de passe de récupération"; +"key_backup_setup_recovery_key_info" = "Faites une copie de cette clé de récupération et conservez-la en lieu sûr.\n\nPar mesure de précaution, vous pouvez l'utiliser pour restaurer votre historique de messages chiffrés si vous oubliez votre phrase de passe de récupération."; +"key_backup_setup_recovery_key_recovery_key_title" = "Clé de récupération"; +"key_backup_setup_recovery_key_make_copy_action" = "En faire une copie"; +"key_backup_setup_recovery_key_made_copy_action" = "J'en ai fait une copie"; +"key_backup_recover_title" = "Messages sécurisés"; +"key_backup_recover_empty_backup_title" = "Sauvegarde vide"; +"key_backup_recover_empty_backup_message" = "Il n'y a aucune clé à restaurer"; +"key_backup_recover_from_passphrase_info" = "Utilisez votre phrase de passe de récupération pour déverrouiller votre historique de messages sécurisés"; +"key_backup_recover_from_passphrase_passphrase_title" = "Saisir"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Saisir la phrase de passe"; +"key_backup_recover_from_passphrase_recover_action" = "Déverrouiller l'historique"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Vous ne connaissez pas votre phrase de passe de récupération ? Vous pouvez "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "utiliser votre clé de récupération"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Utiliser votre clé de récupération pour déverrouiller l'historique de vos messages sécurisés"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Saisir"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Saisir la clé de récupération"; +"key_backup_recover_from_recovery_key_recover_action" = "Déverrouiller l'historique"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Vous avez perdu votre clé de récupération ? Vous pouvez en configurer une autre dans les réglages."; +"key_backup_recover_success_info" = "Sauvegarde restaurée !"; +"key_backup_recover_done_action" = "Effectué"; +"key_backup_setup_banner_title_part1" = "Configurer la récupération de messages sécurisée"; +"key_backup_setup_banner_title_part2" = " pour ne jamais perdre vos messages chiffrés"; +"key_backup_recover_banner_title_part1" = "Lancer la récupération de messages sécurisée"; +"key_backup_recover_banner_title_part2" = " pour lire l'historique des messages chiffrés sur cet appareil"; From 6d38085287ac786332a1c8b5ece366bf6745b398 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Sat, 2 Feb 2019 08:27:07 +0000 Subject: [PATCH 169/244] Translated using Weblate (Albanian) Currently translated at 99.4% (584 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/sq/ --- Riot/Assets/sq.lproj/Vector.strings | 69 ++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index acbcfbe0d..7255a8210 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -547,9 +547,76 @@ "deactivate_account_forget_messages_information_part1" = "Të lutem, harro krejt mesazhet që kamë dërguar, kur të çaktivizohet llogaria ime ("; "deactivate_account_forget_messages_information_part3" = ": kjo do të bëjë që përdorues të ardhshëm të shohin një pamje jo të plotë të bisedave)"; "rerequest_keys_alert_message" = "Ju lutemi, niseni Riot-in në një tjetër pajisje që mundet të shfshehtëzojë mesazhin, që kështu të mund të dërgojë kyçet te kjo pajisje."; -"room_event_action_redact" = "Redaktojeni"; +"room_event_action_redact" = "Hiqe"; "e2e_need_log_in_again" = "Që të prodhohen kyçe fshehtëzimi skaj-më-skaj për këtë pajisje, lypset të ribëni hyrjen dhe të parashtroni kyçin publik te shërbyesi juaj homë.\nKjo duhet vetëm një herë; na ndjeni për belanë."; "room_action_send_sticker" = "Dërgoni ngjitës"; "settings_flair" = "Shfaq simbole, kur lejohet"; "room_details_flair_section" = "Shfaq simbole për bashkësi"; "auth_accept_policies" = "Ju lutemi, shqyrtoni dhe pranoni rregullat e këtij shërbyesi Home:"; +"settings_key_backup" = "RIKTHIM MESAZHESH TË SIGURT"; +"settings_key_backup_info_checking" = "Po kontrollohet…"; +"settings_key_backup_info_none" = "Rikthimi i Mesazheve të Sigurt s’është rregulluar."; +"settings_key_backup_info_version" = "Version Kopjeruajtjeje Kyçesh: %@"; +"settings_key_backup_info_algorithm" = "Algoritëm: %@"; +"settings_key_backup_info_valid" = "Rikthimi i Mesazheve të Sigurt për këtë pajisje është rregulluar si duhet."; +"settings_key_backup_info_not_valid" = "Rikthimi i Mesazheve të Sigurt s’është aktiv në këtë pajisje."; +"settings_key_backup_info_progress" = "Po kopjeruhen kyçet për %@…"; +"settings_key_backup_info_progress_done" = "U kopjeruajtën krejt kyçet"; +"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Për të përdorur Rikthim Mesazhesh të Sigurt në këtë pajisje, verifikoni tani %@."; +"settings_key_backup_info_not_trusted_fix_action" = "Për të përdorur Rikthim Mesazhesh të Sigurt në këtë pajisje, jepni tani një frazëkalim ose një kyç rikthimesh."; +"settings_key_backup_info_trust_signature_unknown" = "Kopjeruajtja ka një nënshkrim nga një pajisje me ID: %@"; +"settings_key_backup_info_trust_signature_valid" = "Kopjeruajtja ka një nënshkrim të vlefshëm prej kësaj pajisjeje"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Kopjeruajtja ka një nënshkrim të vlefshëm prej %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Kopjeruajtja ka nënshkrim nga %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Kopjeruajtja ka një nënshkrim të pavlefshëm prej %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Kopjeruajtja ka një nënshkrim të pavlefshëm prej %@"; +"settings_key_backup_button_create" = "Rregulloni Rikthim Mesazhesh të Sigurt"; +"settings_key_backup_button_restore" = "Riktheje kopjeruajtjen"; +"settings_key_backup_button_delete" = "Fshije kopjeruajtjen"; +"settings_key_backup_button_verify" = "Verifikoje"; +"settings_key_backup_delete_confirmation_prompt_title" = "Fshije Kopjeruajtjen"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Të fshihen nga shërbyesi kyçet e kopjeruajtur të fshehtëzimit? S’do të jeni më në gjendje të përdorni kyçin tuaj të rimarrjeve për lexim historiku mesazhesh të fshehtëzuar"; +"room_does_not_exist" = "%@ nuk ekziston"; +"key_backup_setup_title" = "Rikthim Mesazhesh"; +"key_backup_setup_skip_action" = "Anashkaloje"; +"key_backup_setup_skip_alert_title" = "A jeni i sigurt?"; +"key_backup_setup_skip_alert_message" = "Nëse dilni nga llogaria, ose nëse humbni pajisjen tuaj, mund të humbni mesazhe të sigurt."; +"key_backup_setup_skip_alert_skip_action" = "Anashkaloje"; +"key_backup_setup_intro_title" = "Mos humbni kurrë mesazhe të fshehtëzuar"; +"key_backup_setup_intro_info" = "Ujdisni Rikthim të Mesazheve të Sigurt, për raste kur humbni ose bëni daljen nga kjo pajisje."; +"key_backup_setup_intro_setup_action" = "Rregulloje"; +"key_backup_setup_passphrase_info" = "Sigurojeni historikun tuaj të mesazheve të fshehtëzuar me një Frazëkalim Rikthimesh.\n\nDo t’ju duhet, nëse dilni nga llogaria, ose nëse nuk hyni dot në pajisje."; +"key_backup_setup_passphrase_passphrase_title" = "Jepeni"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Jepni frazëkalimin"; +"key_backup_setup_passphrase_passphrase_valid" = "Bukur!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Provoni të shtoni një fjalë"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Ripohojeni"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Ripohoni frazëkalimin"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Bukur!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Frazëkalimet nuk përputhen"; +"key_backup_setup_passphrase_set_passphrase_action" = "Caktoni frazëkalim rikthimi"; +"key_backup_setup_recovery_key_info" = "Bëni një kopje të këtij Kyçi Rikthimesh dhe ruajeni diku.\n\nSi rrjet sigurie, mund ta përdorni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar, nëse harroni Frazëkalimin e Rikthimeve."; +"key_backup_setup_recovery_key_recovery_key_title" = "Kyç Rikthimesh"; +"key_backup_setup_recovery_key_make_copy_action" = "Bëni një Kopje"; +"key_backup_setup_recovery_key_made_copy_action" = "Kam bërë një kopje"; +"key_backup_recover_title" = "Mesazhe të Sigurt"; +"key_backup_recover_empty_backup_title" = "Kopjeruajtje e zbrazët"; +"key_backup_recover_empty_backup_message" = "S’ka kyç për rikthim"; +"key_backup_recover_from_passphrase_info" = "Që të shkyçni historikun e mesazheve tuaj të sigurt përdorni frazëkalimin tuaj të rikthimeve"; +"key_backup_recover_from_passphrase_passphrase_title" = "Jepeni"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Jepni Frazëkalimin"; +"key_backup_recover_from_passphrase_recover_action" = "Shkyçeni Historikun"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Nuk e dini frazëkalimin tuaj të rikthimeve? Mundeni të "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "përdorni kyçin tuaj të rikthimeve"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Përdorni kyçin tuaj të rikthimeve për të shkyçur historikun tuaj të mesazheve të sigurt"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Jepeni"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Jepni Kyç Rikthimi"; +"key_backup_recover_from_recovery_key_recover_action" = "Shkyçe Historikun"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Humbët kyçin tuaj të rikthimit? Te rregullimet mund të caktoni një të ri."; +"key_backup_recover_success_info" = "Kopjeruajtja u Rikthye!"; +"key_backup_recover_done_action" = "U bë"; +"key_backup_setup_banner_title_part1" = "Rregulloni Rikthim Mesazhesh të Sigurt"; +"key_backup_setup_banner_title_part2" = " që të mos humbni kurrë mesazhe të fshehtëzuar"; +"key_backup_recover_banner_title_part1" = "Xhironi Rikthim Mesazhesh të Sigurt"; +"key_backup_recover_banner_title_part2" = " që të lexoni historik mesazhesh të fshehtëzuar në këtë pajisje"; From 237ed876220c1f959df9299e29951525b74c15ca Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Sat, 2 Feb 2019 08:29:06 +0000 Subject: [PATCH 170/244] Translated using Weblate (Albanian) Currently translated at 99.4% (584 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/sq/ --- Riot/Assets/sq.lproj/Vector.strings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index 7255a8210..1626f5cb4 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -575,7 +575,7 @@ "settings_key_backup_button_delete" = "Fshije kopjeruajtjen"; "settings_key_backup_button_verify" = "Verifikoje"; "settings_key_backup_delete_confirmation_prompt_title" = "Fshije Kopjeruajtjen"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Të fshihen nga shërbyesi kyçet e kopjeruajtur të fshehtëzimit? S’do të jeni më në gjendje të përdorni kyçin tuaj të rimarrjeve për lexim historiku mesazhesh të fshehtëzuar"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Të fshihen nga shërbyesi kyçet e kopjeruajtur të fshehtëzimit? S’do të jeni më në gjendje të përdorni kyçin tuaj të rikthimeve për lexim historiku mesazhesh të fshehtëzuar"; "room_does_not_exist" = "%@ nuk ekziston"; "key_backup_setup_title" = "Rikthim Mesazhesh"; "key_backup_setup_skip_action" = "Anashkaloje"; @@ -594,7 +594,7 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Ripohoni frazëkalimin"; "key_backup_setup_passphrase_confirm_passphrase_valid" = "Bukur!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Frazëkalimet nuk përputhen"; -"key_backup_setup_passphrase_set_passphrase_action" = "Caktoni frazëkalim rikthimi"; +"key_backup_setup_passphrase_set_passphrase_action" = "Caktoni frazëkalim rikthimesh"; "key_backup_setup_recovery_key_info" = "Bëni një kopje të këtij Kyçi Rikthimesh dhe ruajeni diku.\n\nSi rrjet sigurie, mund ta përdorni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar, nëse harroni Frazëkalimin e Rikthimeve."; "key_backup_setup_recovery_key_recovery_key_title" = "Kyç Rikthimesh"; "key_backup_setup_recovery_key_make_copy_action" = "Bëni një Kopje"; @@ -613,7 +613,7 @@ "key_backup_recover_from_recovery_key_recovery_key_title" = "Jepeni"; "key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Jepni Kyç Rikthimi"; "key_backup_recover_from_recovery_key_recover_action" = "Shkyçe Historikun"; -"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Humbët kyçin tuaj të rikthimit? Te rregullimet mund të caktoni një të ri."; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Humbët kyçin tuaj të rikthimeve? Te rregullimet mund të caktoni një të ri."; "key_backup_recover_success_info" = "Kopjeruajtja u Rikthye!"; "key_backup_recover_done_action" = "U bë"; "key_backup_setup_banner_title_part1" = "Rregulloni Rikthim Mesazhesh të Sigurt"; From 381c9a593eb457b7b3e592f4392d79ddd3547440 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 4 Feb 2019 15:49:49 +0100 Subject: [PATCH 171/244] Enhance tap on room predecessor cell used to go back to the old version of the room (Fix issue #2179) --- Riot/Assets/en.lproj/Vector.strings | 2 +- Riot/Generated/Strings.swift | 2 +- Riot/Modules/Room/RoomViewController.m | 19 +++++++++++++++++-- .../BubbleCells/RoomPredecessorBubbleCell.m | 2 ++ Riot/Utils/EventFormatter.m | 5 +---- 5 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 84f0010bf..51fc91508 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -278,7 +278,7 @@ "room_replacement_information" = "This room has been replaced and is no longer active."; "room_replacement_link" = "The conversation continues here."; "room_predecessor_information" = "This room is a continuation of another conversation."; -"room_predecessor_link" = "Click here to see older messages."; +"room_predecessor_link" = "Tap here to see older messages."; "room_resource_limit_exceeded_message_contact_1" = " Please "; "room_resource_limit_exceeded_message_contact_2_link" = "contact your service administrator"; "room_resource_limit_exceeded_message_contact_3" = " to continue using this service."; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 54e1ba16b..e190a7515 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1570,7 +1570,7 @@ internal enum VectorL10n { internal static var roomPredecessorInformation: String { return VectorL10n.tr("Vector", "room_predecessor_information") } - /// Click here to see older messages. + /// Tap here to see older messages. internal static var roomPredecessorLink: String { return VectorL10n.tr("Vector", "room_predecessor_link") } diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 61298913f..88c18349e 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -2005,8 +2005,23 @@ } else if (tappedEvent) { - // Highlight this event in displayed message - [self selectEventWithId:tappedEvent.eventId]; + if (tappedEvent.eventType == MXEventTypeRoomCreate) + { + // Handle tap on RoomPredecessorBubbleCell + MXRoomCreateContent *createContent = [MXRoomCreateContent modelFromJSON:tappedEvent.content]; + NSString *predecessorRoomId = createContent.roomPredecessorInfo.roomId; + + if (predecessorRoomId) + { + // Show predecessor room + [[AppDelegate theDelegate] showRoom:predecessorRoomId andEventId:nil withMatrixSession:self.mainSession]; + } + } + else + { + // Highlight this event in displayed message + [self selectEventWithId:tappedEvent.eventId]; + } } // Force table refresh diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m index dbcb44b50..9099d6815 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m @@ -42,6 +42,8 @@ static CGFloat const kCustomBackgroundCornerRadius = 5.0; { [super awakeFromNib]; + // Disable text selection and link interaction + self.messageTextView.selectable = NO; self.customBackgroundView.layer.masksToBounds = YES; } diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 562e86d3a..8709609dd 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -349,16 +349,13 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; - (NSAttributedString*)roomCreatePredecessorAttributedStringWithPredecessorRoomId:(NSString*)predecessorRoomId { - NSString *predecessorRoomPermalink = [MXTools permalinkToRoom:predecessorRoomId]; - NSDictionary *roomPredecessorReasonAttributes = @{ NSFontAttributeName : self.defaultTextFont }; NSDictionary *roomLinkAttributes = @{ NSFontAttributeName : self.defaultTextFont, - NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle), - NSLinkAttributeName : predecessorRoomPermalink, + NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle) }; NSMutableAttributedString *roomPredecessorAttributedString = [NSMutableAttributedString new]; From 9a401e5fc8e5c634e90f955daed0e842c1b65cbf Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 4 Feb 2019 16:03:11 +0100 Subject: [PATCH 172/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 68d3c8604..0cc6b8a13 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,6 +20,7 @@ Bug fix: * Registration: improve scrolling on the reCaptcha screen (#2165). * Infinite loading wheel when taping on a fake room alias (#679). * Ban and kick reasons are silently discarded (#2162). + * Room Version Upgrade: Clicking the link in the room continuation event to go back to the old version of the room doesn't work (#2179) Changes in 0.7.11 (2019-01-08) =============================================== From c5d2602ae06dc7fa19079418cc14b3e505c30bd1 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 4 Feb 2019 16:08:02 +0100 Subject: [PATCH 173/244] Update changes --- CHANGES.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.rst b/CHANGES.rst index 0cc6b8a13..7074e23e0 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -20,7 +20,7 @@ Bug fix: * Registration: improve scrolling on the reCaptcha screen (#2165). * Infinite loading wheel when taping on a fake room alias (#679). * Ban and kick reasons are silently discarded (#2162). - * Room Version Upgrade: Clicking the link in the room continuation event to go back to the old version of the room doesn't work (#2179) + * Room Version Upgrade: Clicking the link in the room continuation event to go back to the old version of the room doesn't work (#2179). Changes in 0.7.11 (2019-01-08) =============================================== From 89c80925dee7e95811c2fb4a9f3f5439a9404470 Mon Sep 17 00:00:00 2001 From: Slavi Pantaleev Date: Tue, 5 Feb 2019 09:30:23 +0000 Subject: [PATCH 174/244] Translated using Weblate (Bulgarian) Currently translated at 100.0% (587 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/bg/ --- Riot/Assets/bg.lproj/Vector.strings | 69 ++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/bg.lproj/Vector.strings b/Riot/Assets/bg.lproj/Vector.strings index b8a0b49b5..02f38588e 100644 --- a/Riot/Assets/bg.lproj/Vector.strings +++ b/Riot/Assets/bg.lproj/Vector.strings @@ -221,7 +221,7 @@ "room_delete_unsent_messages" = "Изтрий неизпратените съобщения"; "room_event_action_copy" = "Копирай"; "room_event_action_quote" = "Цитирай"; -"room_event_action_redact" = "Изтрий"; +"room_event_action_redact" = "Премахни"; "room_event_action_more" = "Още"; "room_event_action_share" = "Сподели"; "room_event_action_permalink" = "Permalink"; @@ -556,3 +556,70 @@ "room_resource_usage_limit_reached_message_2" = "някои потребители няма да могат да влязат."; "room_resource_usage_limit_reached_message_contact_3" = " за да увеличите този лимит."; "auth_accept_policies" = "Моля, прегледайте и приемете политиките на този сървър:"; +"settings_key_backup" = "ЗАЩИТЕНО ВЪЗСТАНОВЯВАНЕ НА СЪОБЩЕНИЯ"; +"settings_key_backup_info_checking" = "Проверка..."; +"settings_key_backup_info_none" = "Възстановяването на Защитени Съобщения все още не е настроено."; +"settings_key_backup_info_version" = "Версия на резервното копие на ключовете: %@"; +"settings_key_backup_info_algorithm" = "Алгоритъм: %@"; +"settings_key_backup_info_valid" = "Възстановяване на Защитени Съобщения беше настроено за това устройство."; +"settings_key_backup_info_not_valid" = "Възстановяването на Защитени Съобщения не е активно на това устройство."; +"settings_key_backup_info_progress" = "Правене на резервно копие на %@ ключа..."; +"settings_key_backup_info_progress_done" = "Беше направено резервно копие на всички ключове"; +"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "За да използвате Възстановяване на Защитени Съобщения на това устройство, потвърдете %@ сега."; +"settings_key_backup_info_not_trusted_fix_action" = "За да използвате Възстановяване на Защитени Съобщения на това устройство, въведете паролата си или ключа за възстановяване."; +"settings_key_backup_info_trust_signature_unknown" = "Резервното копие има подпис от устройство с идентификатор: %@"; +"settings_key_backup_info_trust_signature_valid" = "Резервното копие има валиден подпис от текущото устройство"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Резервното копие има валиден подпис от %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Резервното копие има валиден подпис от %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Резервното копие има невалиден подпис от %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Резервното копие има невалиден подпис от %@"; +"settings_key_backup_button_create" = "Настройка на Възстановяване на Защитени Съобщения"; +"settings_key_backup_button_restore" = "Възстанови резервното копие"; +"settings_key_backup_button_delete" = "Изтрий резервното копие"; +"settings_key_backup_button_verify" = "Потвърди"; +"settings_key_backup_delete_confirmation_prompt_title" = "Изтриване на резервно копие"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Да се изтрие ли резервното копие на ключовете за шифроване от сървъра? Вече няма да може да използвате ключа за възстановяване за да прочетете шифрованата история на съобщенията"; +"room_does_not_exist" = "%@ не съществува"; +"key_backup_setup_title" = "Възстановяване на Съобщения"; +"key_backup_setup_skip_action" = "Пропусни"; +"key_backup_setup_skip_alert_title" = "Сигурни ли сте?"; +"key_backup_setup_skip_alert_message" = "Може да загубите защитени съобщения, ако излезете от профила или загубите устройството си."; +"key_backup_setup_skip_alert_skip_action" = "Пропусни"; +"key_backup_setup_intro_title" = "Никога не губете шифровани съобщения"; +"key_backup_setup_intro_info" = "Настройте Възстановяване на Защитени Съобщения за да си помогнете, ако излезете от профила или загубите това устройство."; +"key_backup_setup_intro_setup_action" = "Настрой"; +"key_backup_setup_passphrase_info" = "Защитете историята на шифрованите съобщения посредством парола за възстановяване.\n\nЩе Ви е необходима, ако излезете от профила си или загубите достъп до това устройство."; +"key_backup_setup_passphrase_passphrase_title" = "Въвеждане"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Въведете парола"; +"key_backup_setup_passphrase_passphrase_valid" = "Чудесно!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Пробвайте да добавите дума"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Потвърждение"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Въведете паролата отново"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Чудесно!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Паролите не съвпадат"; +"key_backup_setup_passphrase_set_passphrase_action" = "Настрой парола за възстановяване"; +"key_backup_setup_recovery_key_info" = "Направете копие на ключа за възстановяване и го пазете на безопасно място.\n\nАко в бъдеще забравите паролата, може да използвате ключа вместо нея, за да възстановите шифрованите съобщения."; +"key_backup_setup_recovery_key_recovery_key_title" = "Ключ за възстановяване"; +"key_backup_setup_recovery_key_make_copy_action" = "Направи копие"; +"key_backup_setup_recovery_key_made_copy_action" = "Направих копие"; +"key_backup_recover_title" = "Защитени Съобщения"; +"key_backup_recover_empty_backup_title" = "Празно резервно копие"; +"key_backup_recover_empty_backup_message" = "Няма ключ за възстановяване"; +"key_backup_recover_from_passphrase_info" = "Използвайте паролата за възстановяване за да отключите историята на защитените съобщения"; +"key_backup_recover_from_passphrase_passphrase_title" = "Въвеждане"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Въведи парола"; +"key_backup_recover_from_passphrase_recover_action" = "Отключи историята"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Не си спомняте паролата за възстановяване? Можете да "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "използвате ключа за възстановяване"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Използвайте ключа за възстановяване за да отключите историята на защитените съобщения"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Въвеждане"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Въведете ключ за възстановяване"; +"key_backup_recover_from_recovery_key_recover_action" = "Отключи историята"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Загубили сте ключа си за възстановяване? Може да създадете нов от Настройки."; +"key_backup_recover_success_info" = "Резервното копие бе възстановено!"; +"key_backup_recover_done_action" = "Готово"; +"key_backup_setup_banner_title_part1" = "Настройка на Възстановяване на Защитени Съобщения"; +"key_backup_setup_banner_title_part2" = " за да не губите шифровани съобщения"; +"key_backup_recover_banner_title_part1" = "Стартирайте Възстановяване на Защитени Съобщения"; +"key_backup_recover_banner_title_part2" = " за да четете шифрованата история на съобщенията на това устройство"; From 5f4a7e8baa7e4d0b5861b39cebc3475d422594ab Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 6 Feb 2019 16:05:36 +0100 Subject: [PATCH 175/244] Improve image processing in ShareExtensionManager and fix issue #2168 --- .../Managers/ShareExtensionManager.m | 300 +++++++++++++----- 1 file changed, 226 insertions(+), 74 deletions(-) diff --git a/RiotShareExtension/Managers/ShareExtensionManager.m b/RiotShareExtension/Managers/ShareExtensionManager.m index 27927a0c8..2c5d05340 100644 --- a/RiotShareExtension/Managers/ShareExtensionManager.m +++ b/RiotShareExtension/Managers/ShareExtensionManager.m @@ -239,8 +239,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } else if ([(NSObject *)itemProviderItem isKindOfClass:[UIImage class]]) { + // An application can share directly an UIImage. + // The most common case is screenshot sharing without saving to file. + // As screenshot using PNG format when they are saved to file we also use PNG format when saving UIImage to NSData. UIImage *image = (UIImage*)itemProviderItem; - imageData = UIImageJPEGRepresentation(image, 1.0); + imageData = UIImagePNGRepresentation(image); } if (imageData) @@ -364,15 +367,10 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) for (NSData *imageData in self.pendingImages) { - @autoreleasepool + if ([self isImageOrientationNotUpOrUndeterminedForImageData:imageData]) { - UIImage *image = [UIImage imageWithData:imageData]; - - if (image && image.imageOrientation != UIImageOrientationUp) - { - isAPendingImageNotOrientedUp = YES; - break; - } + isAPendingImageNotOrientedUp = YES; + break; } } @@ -555,6 +553,145 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) return YES; } +- (NSString*)utiFromImageTypeItemProvider:(NSItemProvider*)itemProvider +{ + NSString *uti; + + NSString *utiPNG = (__bridge NSString *)kUTTypePNG; + NSString *utiJPEG = (__bridge NSString *)kUTTypeJPEG; + + if ([itemProvider hasItemConformingToTypeIdentifier:utiPNG]) + { + uti = utiPNG; + } + else if ([itemProvider hasItemConformingToTypeIdentifier:utiJPEG]) + { + uti = utiJPEG; + } + else + { + uti = itemProvider.registeredTypeIdentifiers.firstObject; + } + + return uti; +} + +- (NSString*)utiFromImageData:(NSData*)imageData +{ + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); + NSString *uti = (NSString*)CGImageSourceGetType(imageSource); + CFRelease(imageSource); + return uti; +} + +- (NSString*)mimeTypeFromUTI:(NSString*)uti +{ + return (__bridge_transfer NSString *) UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti, kUTTagClassMIMEType); +} + +- (BOOL)isResizingSupportedForImageData:(NSData*)imageData +{ + NSString *imageUTI = [self utiFromImageData:imageData]; + return [self isResizingSupportedForUTI:imageUTI]; +} + +- (BOOL)isResizingSupportedForUTI:(NSString*)imageUTI +{ + if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG] || [imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) + { + return YES; + } + return NO; +} + +- (CGSize)imageSizeFromImageData:(NSData*)imageData +{ + CGFloat width = 0.0f; + CGFloat height = 0.0f; + + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); + + CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); + + CFRelease(imageSource); + + if (imageProperties != NULL) + { + CFNumberRef widthNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth); + CFNumberRef heightNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight); + CFNumberRef orientationNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); + + if (widthNumber != NULL) + { + CFNumberGetValue(widthNumber, kCFNumberCGFloatType, &width); + } + + if (heightNumber != NULL) + { + CFNumberGetValue(heightNumber, kCFNumberCGFloatType, &height); + } + + // Check orientation and flip size if required + if (orientationNumber != NULL) + { + int orientation; + CFNumberGetValue(orientationNumber, kCFNumberIntType, &orientation); + + // For orientation from kCGImagePropertyOrientationLeftMirrored to kCGImagePropertyOrientationLeft flip size + if (orientation >= 5) + { + CGFloat tempWidth = width; + width = height; + height = tempWidth; + } + } + + CFRelease(imageProperties); + } + + return CGSizeMake(width, height); +} + +- (NSNumber*)cgImageimageOrientationNumberFromImageData:(NSData*)imageData +{ + NSNumber *orientationNumber; + + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); + + CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); + + CFRelease(imageSource); + + if (imageProperties != NULL) + { + CFNumberRef orientationNum = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); + + // Check orientation and flip size if required + if (orientationNum != NULL) + { + orientationNumber = (__bridge NSNumber *)orientationNum; + } + + CFRelease(imageProperties); + } + + return orientationNumber; +} + +- (BOOL)isImageOrientationNotUpOrUndeterminedForImageData:(NSData*)imageData +{ + BOOL isImageNotOrientedUp = YES; + + NSNumber *cgImageOrientationNumber = [self cgImageimageOrientationNumberFromImageData:imageData]; + + if (cgImageOrientationNumber && cgImageOrientationNumber.unsignedIntegerValue == (NSUInteger)kCGImagePropertyOrientationUp) + { + isImageNotOrientedUp = NO; + } + + return isImageNotOrientedUp; +} + #pragma mark - Notifications - (void)onMediaLoaderStateDidChange:(NSNotification *)notification @@ -630,7 +767,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) NSString *mimeType; CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fileUrl pathExtension] , NULL); - mimeType = (__bridge_transfer NSString *) UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType); + mimeType = [self mimeTypeFromUTI:(__bridge NSString *)uti]; CFRelease(uti); __weak typeof(self) weakSelf = self; @@ -674,72 +811,29 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) { NSItemProvider *itemProvider = itemProviders[index]; NSData *imageData = imageDatas[index]; - UIImage *image = [UIImage imageWithData:imageData]; - - if (!image) - { - NSLog(@"[ShareExtensionManager] loadItemForTypeIdentifier: failed."); - if (failureBlock) - { - failureBlock(nil); - } - return; - } - - // Prepare the image - UIImage *convertedImage; - CGSize newImageSize; - - switch (self.imageCompressionMode) { - case ImageCompressionModeSmall: - newImageSize = CGSizeMake(MXKTOOLS_SMALL_IMAGE_SIZE, MXKTOOLS_SMALL_IMAGE_SIZE); - break; - case ImageCompressionModeMedium: - newImageSize = CGSizeMake(MXKTOOLS_MEDIUM_IMAGE_SIZE, MXKTOOLS_MEDIUM_IMAGE_SIZE); - break; - case ImageCompressionModeLarge: - newImageSize = CGSizeMake(self.actualLargeSize, self.actualLargeSize); - break; - default: - newImageSize = CGSizeZero; - break; - } - - if (CGSizeEqualToSize(newImageSize, CGSizeZero)) - { - // No resize to make - // Make sure the uploaded image orientation is up - convertedImage = [MXKTools forceImageOrientationUp:image]; - } - else - { - // Resize the image and set image in right orientation too - convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize]; - } + NSString *imageUTI; NSString *mimeType; - if ([itemProvider hasItemConformingToTypeIdentifier:(__bridge NSString *)kUTTypePNG]) + + // Try to get UTI plus mime type from NSItemProvider + imageUTI = [self utiFromImageTypeItemProvider:itemProvider]; + + if (imageUTI) { - mimeType = @"image/png"; - if (convertedImage != image) - { - imageData = UIImagePNGRepresentation(convertedImage); - } + mimeType = [self mimeTypeFromUTI:imageUTI]; } - else if ([itemProvider hasItemConformingToTypeIdentifier:(__bridge NSString *)kUTTypeJPEG]) + + if (!mimeType) { - mimeType = @"image/jpeg"; - if (convertedImage != image) + // Try to get UTI plus mime type from image data + + imageUTI = [self utiFromImageData:imageData]; + + if (imageUTI) { - imageData = UIImageJPEGRepresentation(convertedImage, 0.9); + mimeType = [self mimeTypeFromUTI:imageUTI]; } } - else - { - // Other image types like GIF - NSString *imageFileName = itemProvider.registeredTypeIdentifiers[0]; - mimeType = (__bridge_transfer NSString *) UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)imageFileName, kUTTagClassMIMEType); - } // Sanity check if (!mimeType) @@ -752,20 +846,78 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) return; } + CGSize imageSize; + + // Only resize JPEG or PNG files + if ([self isResizingSupportedForUTI:imageUTI]) + { + UIImage *convertedImage; + CGSize newImageSize; + + switch (self.imageCompressionMode) { + case ImageCompressionModeSmall: + newImageSize = CGSizeMake(MXKTOOLS_SMALL_IMAGE_SIZE, MXKTOOLS_SMALL_IMAGE_SIZE); + break; + case ImageCompressionModeMedium: + newImageSize = CGSizeMake(MXKTOOLS_MEDIUM_IMAGE_SIZE, MXKTOOLS_MEDIUM_IMAGE_SIZE); + break; + case ImageCompressionModeLarge: + newImageSize = CGSizeMake(self.actualLargeSize, self.actualLargeSize); + break; + default: + newImageSize = CGSizeZero; + break; + } + + if (CGSizeEqualToSize(newImageSize, CGSizeZero)) + { + // No resize to make + // Make sure the uploaded image orientation is up + if ([self isImageOrientationNotUpOrUndeterminedForImageData:imageData]) + { + UIImage *image = [UIImage imageWithData:imageData]; + convertedImage = [MXKTools forceImageOrientationUp:image]; + } + } + else + { + // Resize the image and set image in right orientation too + convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize]; + } + + if (convertedImage) + { + if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG]) + { + imageData = UIImagePNGRepresentation(convertedImage); + } + else if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) + { + imageData = UIImageJPEGRepresentation(convertedImage, 0.9); + } + + imageSize = convertedImage.size; + } + else + { + imageSize = [self imageSizeFromImageData:imageData]; + } + } + else + { + imageSize = [self imageSizeFromImageData:imageData]; + } + UIImage *thumbnail = nil; // Thumbnail is useful only in case of encrypted room if (room.summary.isEncrypted) { - thumbnail = [MXKTools reduceImage:convertedImage toFitInSize:CGSizeMake(800, 600)]; - if (thumbnail == convertedImage) - { - thumbnail = nil; - } + thumbnail = [MXKTools resizeImageWithData:imageData toFitInSize:CGSizeMake(800, 600)]; } __weak typeof(self) weakSelf = self; - [room sendImage:imageData withImageSize:convertedImage.size mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { + [room sendImage:imageData withImageSize:imageSize mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { if (!--count && weakSelf) { From cb5bc8ddf29720c6efbeb01e101b02106a6b18ac Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 6 Feb 2019 17:22:06 +0100 Subject: [PATCH 176/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 7074e23e0..95e43e552 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -21,6 +21,7 @@ Bug fix: * Infinite loading wheel when taping on a fake room alias (#679). * Ban and kick reasons are silently discarded (#2162). * Room Version Upgrade: Clicking the link in the room continuation event to go back to the old version of the room doesn't work (#2179). + * Share extension: Fail to send screenshot (#2168). Changes in 0.7.11 (2019-01-08) =============================================== From 1eccc618698d52ab9243b26fd9c298ef01cf82e9 Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 6 Feb 2019 17:34:16 +0100 Subject: [PATCH 177/244] Key backup: Check backup update on the homeserver when opening the home or the settings screen in order to display the right banner and settings. --- Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m | 3 +++ .../Settings/KeyBackup/SettingsKeyBackupViewModel.swift | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index fe15bcfaa..846ab732e 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -152,6 +152,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (void)registerKeyBackupStateDidChangeNotification { + // Check homeserver update in background + [self.mxSession.crypto.backup forceRefresh:nil failure:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBackupStateDidChangeNotification:) name:kMXKeyBackupDidStateChangeNotification object:nil]; } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index ab80e90ab..0ec986fa2 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -68,6 +68,9 @@ final class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { private func checkKeyBackupState() { + // Check homeserver update in background + self.keyBackup.forceRefresh(nil, failure: nil) + if let keyBackupVersion = self.keyBackup.keyBackupVersion { self.keyBackup.trust(for: keyBackupVersion, onComplete: { [weak self] (keyBackupVersionTrust) in From e6bca99af66650446cd7a7844370f735ea17edaf Mon Sep 17 00:00:00 2001 From: Szimszon Date: Wed, 6 Feb 2019 21:02:27 +0000 Subject: [PATCH 178/244] Translated using Weblate (Hungarian) Currently translated at 100.0% (587 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/hu/ --- Riot/Assets/hu.lproj/Vector.strings | 69 ++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index c73c95ff1..aec3efb48 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -222,7 +222,7 @@ "room_delete_unsent_messages" = "Elküldetlen üzenetek törlése"; "room_event_action_copy" = "Másol"; "room_event_action_quote" = "Idéz"; -"room_event_action_redact" = "Kitakar"; +"room_event_action_redact" = "Töröl"; "room_event_action_more" = "További"; "room_event_action_share" = "Megosztás"; "room_event_action_permalink" = "Állandó hivatkozás"; @@ -562,3 +562,70 @@ "room_resource_usage_limit_reached_message_2" = "néhány felhasználó nem tud majd bejelentkezni."; "room_resource_usage_limit_reached_message_contact_3" = " hogy korlátot megemeljék."; "auth_accept_policies" = "A Matrix szerver felhasználási feltételeit kérlek nézd át és fogadd el:"; +"settings_key_backup" = "BIZTONSÁGOS ÜZENET VISSZAÁLLÍTÁS"; +"settings_key_backup_info_checking" = "Ellenőrzés..."; +"settings_key_backup_info_none" = "A Biztonságos Üzenet Visszaállítás nincs beállítva."; +"settings_key_backup_info_version" = "Kulcs mentés verzió: %@"; +"settings_key_backup_info_algorithm" = "Algoritmus: %@"; +"settings_key_backup_info_valid" = "Biztonságos Üzenet Visszaállítás megfelelően van beállítva ezen az eszközön."; +"settings_key_backup_info_not_valid" = "A Biztonságos Üzenet Visszaállítás nincs aktiválva ezen az eszközön."; +"settings_key_backup_info_progress" = "%@ kulcsok mentése..."; +"settings_key_backup_info_progress_done" = "Minden kulcs elmentve"; +"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "A Biztonságos Üzenet Visszaállítás használatához ellenőrizd ezt: %@."; +"settings_key_backup_info_not_trusted_fix_action" = "Ha a Biztonságos Üzenete Visszaállítást ezen az eszközön használni szeretnéd, akkor most add meg a jelmondatodat vagy a visszaállítási kulcsot."; +"settings_key_backup_info_trust_signature_unknown" = "A mentés aláírással rendelkezik az alábbi eszköz azonosítóval: %@"; +"settings_key_backup_info_trust_signature_valid" = "A mentés érvényes aláírással rendelkezik ettől az eszköztől"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "A mentés érvényes aláírással rendelkezik ettől: %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "A mentés rendelkezik aláírással ettől: %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "A mentésnek érvénytelen aláírása van ettől: %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "A mentésnek érvénytelen aláírása van ettől: %@"; +"settings_key_backup_button_create" = "Biztonságos Üzenet Visszaállítás beállítása"; +"settings_key_backup_button_restore" = "Mentés visszaállítás"; +"settings_key_backup_button_delete" = "Mentés törlése"; +"settings_key_backup_button_verify" = "Ellenőrzés"; +"settings_key_backup_delete_confirmation_prompt_title" = "Mentés törlése"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Letörlöd az elmentett titkosítási kulcsokat a szerverről? Ezután már nem tudod használni a visszaállítási kulcsodat, hogy elolvasd a régi titkosított üzeneteidet"; +"room_does_not_exist" = "%@ nem létezik"; +"key_backup_setup_title" = "Üzenet Visszaállítás"; +"key_backup_setup_skip_action" = "Kihagy"; +"key_backup_setup_skip_alert_title" = "Biztos?"; +"key_backup_setup_skip_alert_message" = "Ha kilépsz vagy elhagyod az eszközöd nem férsz majd hozzá a biztonságos üzeneteidhez."; +"key_backup_setup_skip_alert_skip_action" = "Kihagy"; +"key_backup_setup_intro_title" = "Soha ne veszítsd el a titkosított üzeneteidet"; +"key_backup_setup_intro_info" = "Kilépéshez vagy ha elvesztenéd ezt az eszközt, állítsd be a Biztonságos Üzenet Visszaállítást."; +"key_backup_setup_intro_setup_action" = "Beállítás"; +"key_backup_setup_passphrase_info" = "Helyezd biztonságba a titkosított üzeneteidet a Visszaállítási Jelmondattal.\n\nSzükséged lesz rá, ha kilépsz vagy elveszted az eszközöd."; +"key_backup_setup_passphrase_passphrase_title" = "Bead"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Jelmondat bevitele"; +"key_backup_setup_passphrase_passphrase_valid" = "Szuper!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Próbálj hozzáadni egy szót"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Megerősítés"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Jelmondat megerősítése"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Szuper!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "A jelmondatok nem egyeznek meg"; +"key_backup_setup_passphrase_set_passphrase_action" = "Visszaállítási jelmondat beállítása"; +"key_backup_setup_recovery_key_info" = "Erről a Visszaállítási Kulcsról készíts egy másolatot és őrizd meg biztonságos helyen.\n\nEz egy további biztosíték, amivel újra hozzáférhetsz a titkosított üzeneteidhez ha elfelejtenéd a Visszaállítási Jelmondatot."; +"key_backup_setup_recovery_key_recovery_key_title" = "Visszaállítási Kulcs"; +"key_backup_setup_recovery_key_make_copy_action" = "Másolat készítése"; +"key_backup_setup_recovery_key_made_copy_action" = "Készítettem másolatot"; +"key_backup_recover_title" = "Biztonságos Üzenetek"; +"key_backup_recover_empty_backup_title" = "Üres mentés"; +"key_backup_recover_empty_backup_message" = "Nincs mentendő kulcs"; +"key_backup_recover_from_passphrase_info" = "Használd a visszaállítási jelmondatot, hogy újra hozzáférj a biztonságos üzeneteidhez"; +"key_backup_recover_from_passphrase_passphrase_title" = "Bevitel"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Jelmondat bevitele"; +"key_backup_recover_from_passphrase_recover_action" = "Újra hozzáférés a régi üzenetekhez"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Nem emlékszel a visszaállítási jelmondatodra? Használhatod a "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "visszaállítási kulcsot"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Használd a visszaállítási kulcsod, hogy újra hozzáférhess a biztonságos üzeneteidhez"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Bevitel"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Visszaállítási Kulcs megadása"; +"key_backup_recover_from_recovery_key_recover_action" = "Hozzáférés a régi üzenetekhez"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Elvesztetted a visszaállítási kulcsod? A beállításokban készíthetsz egy újat."; +"key_backup_recover_success_info" = "Mentés visszaállítva!"; +"key_backup_recover_done_action" = "Kész"; +"key_backup_setup_banner_title_part1" = "Biztonságos Üzenet Visszaállítás beállítása"; +"key_backup_setup_banner_title_part2" = " , hogy sose veszítsd el a titkosított üzeneteidet"; +"key_backup_recover_banner_title_part1" = "Biztonságos Üzenet Visszaállítás futtatása"; +"key_backup_recover_banner_title_part2" = " , hogy elolvashasd a titkosított üzeneteidet ezen az eszközön"; From e68e18c1b5d18c7ed3f5fdbc1780beae998bdf91 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 11:04:51 +0100 Subject: [PATCH 179/244] [Share extension] Support rich item sharing (e.g. URL + text + image). Fix issue #2224. --- .../Managers/ShareExtensionManager.m | 163 ++++++++++++++---- 1 file changed, 128 insertions(+), 35 deletions(-) diff --git a/RiotShareExtension/Managers/ShareExtensionManager.m b/RiotShareExtension/Managers/ShareExtensionManager.m index 2c5d05340..81ce90a5e 100644 --- a/RiotShareExtension/Managers/ShareExtensionManager.m +++ b/RiotShareExtension/Managers/ShareExtensionManager.m @@ -156,9 +156,33 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) NSString *UTTypeFileUrl = (__bridge NSString *)kUTTypeFileURL; NSString *UTTypeMovie = (__bridge NSString *)kUTTypeMovie; + BOOL areAllAttachmentsImages = [self areAllAttachmentsImages]; + __weak typeof(self) weakSelf = self; [self resetPendingData]; + + __block NSError *firstRequestError = nil; + __block NSMutableArray *returningExtensionItems = [NSMutableArray new]; + dispatch_group_t requestsGroup = dispatch_group_create(); + + void (^requestSuccess)(NSExtensionItem*) = ^(NSExtensionItem *extensionItem) { + if (extensionItem && ![returningExtensionItems containsObject:extensionItem]) + { + [returningExtensionItems addObject:extensionItem]; + } + + dispatch_group_leave(requestsGroup); + }; + + void (^requestFailure)(NSError*) = ^(NSError *requestError) { + if (requestError && !firstRequestError) + { + firstRequestError = requestError; + } + + dispatch_group_leave(requestsGroup); + }; for (NSExtensionItem *item in self.shareExtensionContext.inputItems) { @@ -166,6 +190,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) { if ([itemProvider hasItemConformingToTypeIdentifier:UTTypeFileUrl]) { + dispatch_group_enter(requestsGroup); + [itemProvider loadItemForTypeIdentifier:UTTypeFileUrl options:nil completionHandler:^(NSURL *fileUrl, NSError * _Null_unspecified error) { // Switch back on the main thread to handle correctly the UI change @@ -174,7 +200,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (weakSelf) { typeof(self) self = weakSelf; - [self sendFileWithUrl:fileUrl toRoom:room extensionItem:item failureBlock:failureBlock]; + [self sendFileWithUrl:fileUrl + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; } }); @@ -183,6 +213,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } else if ([itemProvider hasItemConformingToTypeIdentifier:UTTypeText]) { + dispatch_group_enter(requestsGroup); + [itemProvider loadItemForTypeIdentifier:UTTypeText options:nil completionHandler:^(NSString *text, NSError * _Null_unspecified error) { // Switch back on the main thread to handle correctly the UI change @@ -191,7 +223,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (weakSelf) { typeof(self) self = weakSelf; - [self sendText:text toRoom:room extensionItem:item failureBlock:failureBlock]; + [self sendText:text + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; } }); @@ -200,6 +236,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } else if ([itemProvider hasItemConformingToTypeIdentifier:UTTypeURL]) { + dispatch_group_enter(requestsGroup); + [itemProvider loadItemForTypeIdentifier:UTTypeURL options:nil completionHandler:^(NSURL *url, NSError * _Null_unspecified error) { // Switch back on the main thread to handle correctly the UI change @@ -208,7 +246,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (weakSelf) { typeof(self) self = weakSelf; - [self sendText:url.absoluteString toRoom:room extensionItem:item failureBlock:failureBlock]; + [self sendText:url.absoluteString + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; } }); @@ -217,6 +259,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } else if ([itemProvider hasItemConformingToTypeIdentifier:UTTypeImage]) { + dispatch_group_enter(requestsGroup); + itemProvider.isLoaded = NO; [itemProvider loadItemForTypeIdentifier:UTTypeImage options:nil completionHandler:^(id _Nullable itemProviderItem, NSError * _Null_unspecified error) @@ -249,16 +293,37 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (imageData) { [self.pendingImages addObject:imageData]; + + if (!areAllAttachmentsImages) + { + CGSize imageSize = [self imageSizeFromImageData:imageData]; + self.imageCompressionMode = ImageCompressionModeNone; + self.actualLargeSize = MAX(imageSize.width, imageSize.height); + + [self sendImages:self.pendingImages + withProviders:item.attachments + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; + } } else { NSLog(@"[ShareExtensionManager] sendContentToRoom: failed to loadItemForTypeIdentifier. Error: %@", error); + dispatch_group_leave(requestsGroup); } - if ([self areAttachmentsFullyLoaded]) + // Only prompt for image resize only if all items are images + if (areAllAttachmentsImages && [self areAttachmentsFullyLoaded]) { UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:^{ - [self sendImages:self.pendingImages withProviders:item.attachments toRoom:room extensionItem:item failureBlock:failureBlock]; + [self sendImages:self.pendingImages + withProviders:item.attachments + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; }]; if (compressionPrompt) @@ -271,6 +336,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } else if ([itemProvider hasItemConformingToTypeIdentifier:UTTypeVideo]) { + dispatch_group_enter(requestsGroup); + [itemProvider loadItemForTypeIdentifier:UTTypeVideo options:nil completionHandler:^(NSURL *videoLocalUrl, NSError * _Null_unspecified error) { // Switch back on the main thread to handle correctly the UI change @@ -279,7 +346,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (weakSelf) { typeof(self) self = weakSelf; - [self sendVideo:videoLocalUrl toRoom:room extensionItem:item failureBlock:failureBlock]; + [self sendVideo:videoLocalUrl + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; } }); @@ -288,6 +359,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } else if ([itemProvider hasItemConformingToTypeIdentifier:UTTypeMovie]) { + dispatch_group_enter(requestsGroup); + [itemProvider loadItemForTypeIdentifier:UTTypeMovie options:nil completionHandler:^(NSURL *videoLocalUrl, NSError * _Null_unspecified error) { // Switch back on the main thread to handle correctly the UI change @@ -296,7 +369,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (weakSelf) { typeof(self) self = weakSelf; - [self sendVideo:videoLocalUrl toRoom:room extensionItem:item failureBlock:failureBlock]; + [self sendVideo:videoLocalUrl + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; } }); @@ -305,6 +382,22 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } } } + + dispatch_group_notify(requestsGroup, dispatch_get_main_queue(), ^{ + [self resetPendingData]; + + if (firstRequestError) + { + if (failureBlock) + { + failureBlock(firstRequestError); + } + } + else + { + [self completeRequestReturningItems:returningExtensionItems completionHandler:nil]; + } + }); } - (BOOL)hasImageTypeContent @@ -553,6 +646,21 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) return YES; } +- (BOOL)areAllAttachmentsImages +{ + for (NSExtensionItem *item in self.shareExtensionContext.inputItems) + { + for (NSItemProvider *itemProvider in item.attachments) + { + if (![itemProvider hasItemConformingToTypeIdentifier:(__bridge NSString *)kUTTypeImage]) + { + return NO; + } + } + } + return YES; +} + - (NSString*)utiFromImageTypeItemProvider:(NSItemProvider*)itemProvider { NSString *uti; @@ -723,7 +831,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) #pragma mark - Sharing -- (void)sendText:(NSString *)text toRoom:(MXRoom *)room extensionItem:(NSExtensionItem *)extensionItem failureBlock:(void(^)(NSError *error))failureBlock +- (void)sendText:(NSString *)text toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock { [self didStartSendingToRoom:room]; if (!text) @@ -736,12 +844,10 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) return; } - __weak typeof(self) weakSelf = self; [room sendTextMessage:text success:^(NSString *eventId) { - if (weakSelf) + if (successBlock) { - typeof(self) self = weakSelf; - [self completeRequestReturningItems:@[extensionItem] completionHandler:nil]; + successBlock(); } } failure:^(NSError *error) { NSLog(@"[ShareExtensionManager] sendTextMessage failed."); @@ -752,7 +858,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) }]; } -- (void)sendFileWithUrl:(NSURL *)fileUrl toRoom:(MXRoom *)room extensionItem:(NSExtensionItem *)extensionItem failureBlock:(void(^)(NSError *error))failureBlock +- (void)sendFileWithUrl:(NSURL *)fileUrl toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock { [self didStartSendingToRoom:room]; if (!fileUrl) @@ -770,13 +876,10 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) mimeType = [self mimeTypeFromUTI:(__bridge NSString *)uti]; CFRelease(uti); - __weak typeof(self) weakSelf = self; - [room sendFile:fileUrl mimeType:mimeType localEcho:nil success:^(NSString *eventId) { - if (weakSelf) + if (successBlock) { - typeof(self) self = weakSelf; - [self completeRequestReturningItems:@[extensionItem] completionHandler:nil]; + successBlock(); } } failure:^(NSError *error) { NSLog(@"[ShareExtensionManager] sendFile failed."); @@ -788,7 +891,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } -- (void)sendImages:(NSMutableArray *)imageDatas withProviders:(NSArray*)itemProviders toRoom:(MXRoom *)room extensionItem:(NSExtensionItem *)extensionItem failureBlock:(void(^)(NSError *error))failureBlock +- (void)sendImages:(NSMutableArray *)imageDatas withProviders:(NSArray*)itemProviders toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock { if (imageDatas.count == 0) { @@ -803,7 +906,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) [self didStartSendingToRoom:room]; - __block NSUInteger count = imageDatas.count; +// __block NSUInteger count = imageDatas.count; for (NSInteger index = 0; index < imageDatas.count; index++) { @@ -915,18 +1018,11 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) thumbnail = [MXKTools resizeImageWithData:imageData toFitInSize:CGSizeMake(800, 600)]; } - __weak typeof(self) weakSelf = self; - [room sendImage:imageData withImageSize:imageSize mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { - - if (!--count && weakSelf) + if (successBlock) { - typeof(self) self = weakSelf; - - [self resetPendingData]; - [self completeRequestReturningItems:@[extensionItem] completionHandler:nil]; + successBlock(); } - } failure:^(NSError *error) { NSLog(@"[ShareExtensionManager] sendImage failed."); @@ -941,7 +1037,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } } -- (void)sendVideo:(NSURL *)videoLocalUrl toRoom:(MXRoom *)room extensionItem:(NSExtensionItem *)extensionItem failureBlock:(void(^)(NSError *error))failureBlock +- (void)sendVideo:(NSURL *)videoLocalUrl toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock { [self didStartSendingToRoom:room]; if (!videoLocalUrl) @@ -964,13 +1060,10 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) UIImage *videoThumbnail = [[UIImage alloc] initWithCGImage:imageRef]; CFRelease(imageRef); - __weak typeof(self) weakSelf = self; - [room sendVideo:videoLocalUrl withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { - if (weakSelf) + if (successBlock) { - typeof(self) self = weakSelf; - [self completeRequestReturningItems:@[extensionItem] completionHandler:nil]; + successBlock(); } } failure:^(NSError *error) { NSLog(@"[ShareExtensionManager] sendVideo failed."); From 307ef4c788022e66df47de003febe6eea480ed0d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 11:06:47 +0100 Subject: [PATCH 180/244] [Share extension] Add NSExtensionActivationDictionaryVersion to plist. By the way enable sharing with Apple Notes application. --- RiotShareExtension/SupportingFiles/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RiotShareExtension/SupportingFiles/Info.plist b/RiotShareExtension/SupportingFiles/Info.plist index d3c06698d..a1557d323 100644 --- a/RiotShareExtension/SupportingFiles/Info.plist +++ b/RiotShareExtension/SupportingFiles/Info.plist @@ -26,6 +26,8 @@ NSExtensionActivationRule + NSExtensionActivationDictionaryVersion + 2 NSExtensionActivationSupportsImageWithMaxCount 5 NSExtensionActivationSupportsMovieWithMaxCount From 5b53a96134d026641ccf02089b2a957b5b1c00a1 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 11:12:49 +0100 Subject: [PATCH 181/244] Update changes --- CHANGES.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGES.rst b/CHANGES.rst index 95e43e552..38b0fe745 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,6 +22,8 @@ Bug fix: * Ban and kick reasons are silently discarded (#2162). * Room Version Upgrade: Clicking the link in the room continuation event to go back to the old version of the room doesn't work (#2179). * Share extension: Fail to send screenshot (#2168). + * Share extension: Handle rich item sharing (image + text + URL) (#2224). + * Share extension: Sharing pages from Firefox only shares their title (#2163). Changes in 0.7.11 (2019-01-08) =============================================== From 149e399b846bdf81d03b8e0cc864584feaa168cb Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 14:43:21 +0100 Subject: [PATCH 182/244] [Share extension] Improve dispatch_group usage when sending only images. --- .../Managers/ShareExtensionManager.m | 341 ++++++++++-------- 1 file changed, 197 insertions(+), 144 deletions(-) diff --git a/RiotShareExtension/Managers/ShareExtensionManager.m b/RiotShareExtension/Managers/ShareExtensionManager.m index 81ce90a5e..7816130e0 100644 --- a/RiotShareExtension/Managers/ShareExtensionManager.m +++ b/RiotShareExtension/Managers/ShareExtensionManager.m @@ -149,6 +149,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) - (void)sendContentToRoom:(MXRoom *)room failureBlock:(void(^)(NSError *error))failureBlock { + [self resetPendingData]; + NSString *UTTypeText = (__bridge NSString *)kUTTypeText; NSString *UTTypeURL = (__bridge NSString *)kUTTypeURL; NSString *UTTypeImage = (__bridge NSString *)kUTTypeImage; @@ -157,10 +159,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) NSString *UTTypeMovie = (__bridge NSString *)kUTTypeMovie; BOOL areAllAttachmentsImages = [self areAllAttachmentsImages]; - - __weak typeof(self) weakSelf = self; - - [self resetPendingData]; + NSMutableArray *pendingImagesItemProviders = [NSMutableArray new]; // Used to keep NSItemProvider associated to pending images (used only when all items are images). __block NSError *firstRequestError = nil; __block NSMutableArray *returningExtensionItems = [NSMutableArray new]; @@ -184,6 +183,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) dispatch_group_leave(requestsGroup); }; + __weak typeof(self) weakSelf = self; + for (NSExtensionItem *item in self.shareExtensionContext.inputItems) { for (NSItemProvider *itemProvider in item.attachments) @@ -292,20 +293,23 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) if (imageData) { - [self.pendingImages addObject:imageData]; - - if (!areAllAttachmentsImages) + if (areAllAttachmentsImages) + { + [self.pendingImages addObject:imageData]; + [pendingImagesItemProviders addObject:itemProvider]; + } + else { CGSize imageSize = [self imageSizeFromImageData:imageData]; self.imageCompressionMode = ImageCompressionModeNone; self.actualLargeSize = MAX(imageSize.width, imageSize.height); - [self sendImages:self.pendingImages - withProviders:item.attachments - toRoom:room - successBlock:^{ - requestSuccess(item); - } failureBlock:requestFailure]; + [self sendImageData:imageData + withProvider:itemProvider + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; } } else @@ -315,20 +319,27 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } // Only prompt for image resize only if all items are images - if (areAllAttachmentsImages && [self areAttachmentsFullyLoaded]) + if (areAllAttachmentsImages) { - UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:^{ - [self sendImages:self.pendingImages - withProviders:item.attachments - toRoom:room - successBlock:^{ - requestSuccess(item); - } failureBlock:requestFailure]; - }]; - - if (compressionPrompt) + if ([self areAttachmentsFullyLoaded]) { - [self.delegate shareExtensionManager:self showImageCompressionPrompt:compressionPrompt]; + UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:^{ + [self sendImageDatas:self.pendingImages + withProviders:pendingImagesItemProviders + toRoom:room + successBlock:^{ + requestSuccess(item); + } failureBlock:requestFailure]; + }]; + + if (compressionPrompt) + { + [self.delegate shareExtensionManager:self showImageCompressionPrompt:compressionPrompt]; + } + } + else + { + dispatch_group_leave(requestsGroup); } } } @@ -890,10 +901,135 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } keepActualFilename:YES]; } - -- (void)sendImages:(NSMutableArray *)imageDatas withProviders:(NSArray*)itemProviders toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock +- (void)sendImageData:(NSData *)imageData withProvider:(NSItemProvider*)itemProvider toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock { - if (imageDatas.count == 0) + [self didStartSendingToRoom:room]; + + NSString *imageUTI; + NSString *mimeType; + + // Try to get UTI plus mime type from NSItemProvider + imageUTI = [self utiFromImageTypeItemProvider:itemProvider]; + + if (imageUTI) + { + mimeType = [self mimeTypeFromUTI:imageUTI]; + } + + if (!mimeType) + { + // Try to get UTI plus mime type from image data + + imageUTI = [self utiFromImageData:imageData]; + + if (imageUTI) + { + mimeType = [self mimeTypeFromUTI:imageUTI]; + } + } + + // Sanity check + if (!mimeType) + { + NSLog(@"[ShareExtensionManager] sendImage failed. Cannot determine MIME type of %@", itemProvider); + if (failureBlock) + { + failureBlock(nil); + } + return; + } + + CGSize imageSize; + NSData *finalImageData; + + // Only resize JPEG or PNG files + if ([self isResizingSupportedForUTI:imageUTI]) + { + UIImage *convertedImage; + CGSize newImageSize; + + switch (self.imageCompressionMode) { + case ImageCompressionModeSmall: + newImageSize = CGSizeMake(MXKTOOLS_SMALL_IMAGE_SIZE, MXKTOOLS_SMALL_IMAGE_SIZE); + break; + case ImageCompressionModeMedium: + newImageSize = CGSizeMake(MXKTOOLS_MEDIUM_IMAGE_SIZE, MXKTOOLS_MEDIUM_IMAGE_SIZE); + break; + case ImageCompressionModeLarge: + newImageSize = CGSizeMake(self.actualLargeSize, self.actualLargeSize); + break; + default: + newImageSize = CGSizeZero; + break; + } + + if (CGSizeEqualToSize(newImageSize, CGSizeZero)) + { + // No resize to make + // Make sure the uploaded image orientation is up + if ([self isImageOrientationNotUpOrUndeterminedForImageData:imageData]) + { + UIImage *image = [UIImage imageWithData:imageData]; + convertedImage = [MXKTools forceImageOrientationUp:image]; + } + } + else + { + // Resize the image and set image in right orientation too + convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize]; + } + + if (convertedImage) + { + if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG]) + { + finalImageData = UIImagePNGRepresentation(convertedImage); + } + else if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) + { + finalImageData = UIImageJPEGRepresentation(convertedImage, 0.9); + } + + imageSize = convertedImage.size; + } + else + { + finalImageData = imageData; + imageSize = [self imageSizeFromImageData:imageData]; + } + } + else + { + finalImageData = imageData; + imageSize = [self imageSizeFromImageData:imageData]; + } + + UIImage *thumbnail = nil; + // Thumbnail is useful only in case of encrypted room + if (room.summary.isEncrypted) + { + thumbnail = [MXKTools resizeImageWithData:imageData toFitInSize:CGSizeMake(800, 600)]; + } + + [room sendImage:finalImageData withImageSize:imageSize mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { + if (successBlock) + { + successBlock(); + } + } failure:^(NSError *error) { + + NSLog(@"[ShareExtensionManager] sendImage failed."); + if (failureBlock) + { + failureBlock(error); + } + + }]; +} + +- (void)sendImageDatas:(NSMutableArray *)imageDatas withProviders:(NSArray*)itemProviders toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock +{ + if (imageDatas.count == 0 || imageDatas.count != itemProviders.count) { NSLog(@"[ShareExtensionManager] sendImages: no images to send."); @@ -906,135 +1042,52 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) [self didStartSendingToRoom:room]; -// __block NSUInteger count = imageDatas.count; + dispatch_group_t requestsGroup = dispatch_group_create(); + __block NSError *firstRequestError; - for (NSInteger index = 0; index < imageDatas.count; index++) + NSUInteger index = 0; + + for (NSData *imageData in imageDatas) { @autoreleasepool { + dispatch_group_enter(requestsGroup); + NSItemProvider *itemProvider = itemProviders[index]; - NSData *imageData = imageDatas[index]; - NSString *imageUTI; - NSString *mimeType; - - // Try to get UTI plus mime type from NSItemProvider - imageUTI = [self utiFromImageTypeItemProvider:itemProvider]; - - if (imageUTI) - { - mimeType = [self mimeTypeFromUTI:imageUTI]; - } - - if (!mimeType) - { - // Try to get UTI plus mime type from image data + [self sendImageData:imageData withProvider:itemProvider toRoom:room successBlock:^{ + dispatch_group_leave(requestsGroup); + } failureBlock:^(NSError *error) { - imageUTI = [self utiFromImageData:imageData]; - - if (imageUTI) + if (error && !firstRequestError) { - mimeType = [self mimeTypeFromUTI:imageUTI]; - } - } - - // Sanity check - if (!mimeType) - { - NSLog(@"[ShareExtensionManager] sendImage failed. Cannot determine MIME type of %@", itemProvider); - if (failureBlock) - { - failureBlock(nil); - } - return; - } - - CGSize imageSize; - - // Only resize JPEG or PNG files - if ([self isResizingSupportedForUTI:imageUTI]) - { - UIImage *convertedImage; - CGSize newImageSize; - - switch (self.imageCompressionMode) { - case ImageCompressionModeSmall: - newImageSize = CGSizeMake(MXKTOOLS_SMALL_IMAGE_SIZE, MXKTOOLS_SMALL_IMAGE_SIZE); - break; - case ImageCompressionModeMedium: - newImageSize = CGSizeMake(MXKTOOLS_MEDIUM_IMAGE_SIZE, MXKTOOLS_MEDIUM_IMAGE_SIZE); - break; - case ImageCompressionModeLarge: - newImageSize = CGSizeMake(self.actualLargeSize, self.actualLargeSize); - break; - default: - newImageSize = CGSizeZero; - break; - } - - if (CGSizeEqualToSize(newImageSize, CGSizeZero)) - { - // No resize to make - // Make sure the uploaded image orientation is up - if ([self isImageOrientationNotUpOrUndeterminedForImageData:imageData]) - { - UIImage *image = [UIImage imageWithData:imageData]; - convertedImage = [MXKTools forceImageOrientationUp:image]; - } - } - else - { - // Resize the image and set image in right orientation too - convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize]; - } - - if (convertedImage) - { - if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG]) - { - imageData = UIImagePNGRepresentation(convertedImage); - } - else if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) - { - imageData = UIImageJPEGRepresentation(convertedImage, 0.9); - } - - imageSize = convertedImage.size; - } - else - { - imageSize = [self imageSizeFromImageData:imageData]; - } - } - else - { - imageSize = [self imageSizeFromImageData:imageData]; - } - - UIImage *thumbnail = nil; - // Thumbnail is useful only in case of encrypted room - if (room.summary.isEncrypted) - { - thumbnail = [MXKTools resizeImageWithData:imageData toFitInSize:CGSizeMake(800, 600)]; - } - - [room sendImage:imageData withImageSize:imageSize mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { - if (successBlock) - { - successBlock(); - } - } failure:^(NSError *error) { - - NSLog(@"[ShareExtensionManager] sendImage failed."); - if (failureBlock) - { - failureBlock(error); + firstRequestError = error; } + dispatch_group_leave(requestsGroup); }]; - } + + index++; } + + dispatch_group_notify(requestsGroup, dispatch_get_main_queue(), ^{ + + if (firstRequestError) + { + if (failureBlock) + { + failureBlock(firstRequestError); + } + } + else + { + if (successBlock) + { + successBlock(); + } + } + }); } - (void)sendVideo:(NSURL *)videoLocalUrl toRoom:(MXRoom *)room successBlock:(dispatch_block_t)successBlock failureBlock:(void(^)(NSError *error))failureBlock From 64d9a17575e58d91807ee2a5e1fbe37faae995b0 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 15:16:52 +0100 Subject: [PATCH 183/244] [Share extension] Fix unloaded theme --- .../Modules/Main/SharePresentingViewController.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/RiotShareExtension/Modules/Main/SharePresentingViewController.m b/RiotShareExtension/Modules/Main/SharePresentingViewController.m index 13c7390e8..ef57eba3c 100644 --- a/RiotShareExtension/Modules/Main/SharePresentingViewController.m +++ b/RiotShareExtension/Modules/Main/SharePresentingViewController.m @@ -17,6 +17,13 @@ #import "SharePresentingViewController.h" #import "ShareViewController.h" #import "ShareExtensionManager.h" +#import "ThemeService.h" + +#ifdef IS_SHARE_EXTENSION +#import "RiotShareExtension-Swift.h" +#else +#import "Riot-Swift.h" +#endif @interface SharePresentingViewController () @@ -35,6 +42,9 @@ sharedManager.primaryViewController = self; sharedManager.shareExtensionContext = self.extensionContext; + // Set up current theme + ThemeService.shared.themeId = RiotSettings.shared.userInterfaceTheme; + [self presentShareViewController]; } From 5ece93816ef53ccd76e193f3ec156ea4f02533f9 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 15:17:58 +0100 Subject: [PATCH 184/244] Handle section header tint color update when theme change in SegmentedViewController --- .../Common/SegmentedViewController/SegmentedViewController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index b992f663e..7823d8c67 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -135,8 +135,6 @@ // Setup `MXKViewControllerHandling` properties self.enableBarTintColorStatusChange = NO; - - self.sectionHeaderTintColor = ThemeService.shared.theme.tintColor; } - (void)viewDidLoad @@ -183,6 +181,8 @@ self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; + + self.sectionHeaderTintColor = ThemeService.shared.theme.tintColor; } - (UIStatusBarStyle)preferredStatusBarStyle From de562d8a1ec8bee86b887d7a03bdebed3463f37d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 8 Feb 2019 15:25:17 +0100 Subject: [PATCH 185/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 95e43e552..00e2798af 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -22,6 +22,7 @@ Bug fix: * Ban and kick reasons are silently discarded (#2162). * Room Version Upgrade: Clicking the link in the room continuation event to go back to the old version of the room doesn't work (#2179). * Share extension: Fail to send screenshot (#2168). + * Share extension: Fix unloaded theme (PR #2235). Changes in 0.7.11 (2019-01-08) =============================================== From 03c32903fa64f45ddc6adab10a4f901fabee1e21 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 12 Feb 2019 18:54:39 +0100 Subject: [PATCH 186/244] Reskin: Update colors #2237 --- Riot/Managers/Theme/Theme.swift | 2 +- Riot/Managers/Theme/Themes/BlackTheme.swift | 5 ++- Riot/Managers/Theme/Themes/DarkTheme.swift | 36 +++++++++---------- Riot/Managers/Theme/Themes/DefaultTheme.swift | 26 +++++++------- 4 files changed, 36 insertions(+), 33 deletions(-) diff --git a/Riot/Managers/Theme/Theme.swift b/Riot/Managers/Theme/Theme.swift index 43ad45c28..2e5394af9 100644 --- a/Riot/Managers/Theme/Theme.swift +++ b/Riot/Managers/Theme/Theme.swift @@ -17,7 +17,7 @@ import UIKit /// Provide color constant values defined by the designer -/// https://app.zeplin.io/project/5b857c64b1747a2c472290da/screen/5bf2cc89a4a6973f47883c6e +/// https://app.zeplin.io/project/5c122fa790c5b4241ffa6be7/screen/5c619592daff2f1241d82e75 @objc protocol Theme { var backgroundColor: UIColor { get } diff --git a/Riot/Managers/Theme/Themes/BlackTheme.swift b/Riot/Managers/Theme/Themes/BlackTheme.swift index 0a42eae34..74ea1d52e 100644 --- a/Riot/Managers/Theme/Themes/BlackTheme.swift +++ b/Riot/Managers/Theme/Themes/BlackTheme.swift @@ -20,6 +20,9 @@ class BlackTheme: DarkTheme { override init() { super.init() - self.backgroundColor = UIColor.black + self.backgroundColor = UIColor(rgb: 0x000000) + self.baseColor = UIColor(rgb: 0x060708) + self.headerBackgroundColor = UIColor(rgb: 0x090A0C) + self.headerBorderColor = UIColor(rgb: 0x0D0F12) } } diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index 51be91c26..6292bec3c 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -21,35 +21,35 @@ import UIKit @objcMembers class DarkTheme: NSObject, Theme { - var backgroundColor: UIColor = UIColor(rgb: 0x212224) + var backgroundColor: UIColor = UIColor(rgb: 0x181B21) - var baseColor: UIColor = UIColor(rgb: 0x292E37) - var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) + var baseColor: UIColor = UIColor(rgb: 0x15171B) + var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xEDF3FF) + var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xEDF3FF) - var searchBackgroundColor: UIColor = UIColor(rgb: 0x3E434B) - var searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) + var searchBackgroundColor: UIColor = UIColor(rgb: 0x181B21) + var searchTextColor: UIColor = UIColor(rgb: 0x61708B) - var headerBackgroundColor: UIColor = UIColor(rgb: 0x303540) - var headerBorderColor: UIColor = UIColor(rgb: 0x2E2F31) - var headerTextPrimaryColor: UIColor = UIColor(rgb: 0x96A1B7) + var headerBackgroundColor: UIColor = UIColor(rgb: 0x181B21) + var headerBorderColor: UIColor = UIColor(rgb: 0x22262E) + var headerTextPrimaryColor: UIColor = UIColor(rgb: 0xA1B2D1) var headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) - var textPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) - var textSecondaryColor: UIColor = UIColor(rgb: 0xD8D8D8) + var textPrimaryColor: UIColor = UIColor(rgb: 0xEDF3FF) + var textSecondaryColor: UIColor = UIColor(rgb: 0xA1B2D1) - var tintColor: UIColor = UIColor(rgb: 0x7AC9A1) + var tintColor: UIColor = UIColor(rgb: 0x03B381) var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - var notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) - var notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) + var notificationSecondaryColor: UIColor = UIColor(rgb: 0x61708B) + var notificationPrimaryColor: UIColor = UIColor(rgb: 0xFF4B55) - var warningColor: UIColor = UIColor(rgb: 0xF56679) + var warningColor: UIColor = UIColor(rgb: 0xFF4B55) var avatarColors: [UIColor] = [ - UIColor(rgb: 0x7AC9A1), - UIColor(rgb: 0x76DDD7), - UIColor(rgb: 0x1E7DDC)] + UIColor(rgb: 0x03B381), + UIColor(rgb: 0x368BD6), + UIColor(rgb: 0xAC3BA8)] var statusBarStyle: UIStatusBarStyle = .lightContent var scrollBarStyle: UIScrollViewIndicatorStyle = .white diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index b0470785b..4d01ce5d7 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -23,33 +23,33 @@ class DefaultTheme: NSObject, Theme { var backgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) - var baseColor: UIColor = UIColor(rgb: 0x2E3648) + var baseColor: UIColor = UIColor(rgb: 0x27303A) var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xFFFFFF) var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) var searchBackgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) - var searchTextColor: UIColor = UIColor(rgb: 0xACB3C2) + var searchTextColor: UIColor = UIColor(rgb: 0x61708B) // Name in the associated palette is Search Placeholder - var headerBackgroundColor: UIColor = UIColor(rgb: 0xF1F5F8) - var headerBorderColor: UIColor = UIColor(rgb: 0xEAEEF2) - var headerTextPrimaryColor: UIColor = UIColor(rgb: 0x72708B) + var headerBackgroundColor: UIColor = UIColor(rgb: 0xF2F5F8) + var headerBorderColor: UIColor = UIColor(rgb: 0xE9EDF1) + var headerTextPrimaryColor: UIColor = UIColor(rgb: 0x61708B) var headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) - var textPrimaryColor: UIColor = UIColor(rgb: 0x383838) + var textPrimaryColor: UIColor = UIColor(rgb: 0x2E2F32) var textSecondaryColor: UIColor = UIColor(rgb: 0x9E9E9E) - var tintColor: UIColor = UIColor(rgb: 0x7AC9A1) + var tintColor: UIColor = UIColor(rgb: 0x03B381) var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) - var notificationSecondaryColor: UIColor = UIColor(rgb: 0x7AC9A1) - var notificationPrimaryColor: UIColor = UIColor(rgb: 0xF56679) + var notificationSecondaryColor: UIColor = UIColor(rgb: 0x61708B) + var notificationPrimaryColor: UIColor = UIColor(rgb: 0xFF4B55) - var warningColor: UIColor = UIColor(rgb: 0xF56679) + var warningColor: UIColor = UIColor(rgb: 0xFF4B55) var avatarColors: [UIColor] = [ - UIColor(rgb: 0x7AC9A1), - UIColor(rgb: 0x76DDD7), - UIColor(rgb: 0x1E7DDC)] + UIColor(rgb: 0x03B381), + UIColor(rgb: 0x368BD6), + UIColor(rgb: 0xAC3BA8)] var statusBarStyle: UIStatusBarStyle = .lightContent var scrollBarStyle: UIScrollViewIndicatorStyle = .default From 29aa20f810ea8a908c243d0df3a1bd2cc07b7008 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 12 Feb 2019 19:06:22 +0100 Subject: [PATCH 187/244] Reskin: Use same color names as in https://app.zeplin.io/project/5c122fa790c5b4241ffa6be7/screen/5c619592daff2f1241d82e75 --- Riot/Managers/Theme/Theme.swift | 10 +++++----- Riot/Managers/Theme/Themes/DarkTheme.swift | 9 +++++---- Riot/Managers/Theme/Themes/DefaultTheme.swift | 9 +++++---- .../Modules/Common/Recents/Views/RecentTableViewCell.m | 2 +- .../Communities/Views/GroupInviteTableViewCell.m | 2 +- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 4 ++-- .../KeyBackupSetupPassphraseViewController.swift | 4 ++-- Riot/Modules/People/Views/InviteRecentTableViewCell.m | 2 +- Riot/Modules/Room/RoomViewController.m | 4 ++-- Riot/Modules/TabBar/MasterTabBarController.m | 6 +++--- Riot/Utils/EventFormatter.m | 2 +- 11 files changed, 28 insertions(+), 26 deletions(-) diff --git a/Riot/Managers/Theme/Theme.swift b/Riot/Managers/Theme/Theme.swift index 2e5394af9..e576d7441 100644 --- a/Riot/Managers/Theme/Theme.swift +++ b/Riot/Managers/Theme/Theme.swift @@ -27,7 +27,7 @@ import UIKit var baseTextSecondaryColor: UIColor { get } var searchBackgroundColor: UIColor { get } - var searchTextColor: UIColor { get } + var searchPlaceholderColor: UIColor { get } var headerBackgroundColor: UIColor { get } var headerBorderColor: UIColor { get } @@ -41,10 +41,10 @@ import UIKit var unreadRoomIndentColor: UIColor { get } - /// Color for notifications for unread messages - var notificationSecondaryColor: UIColor { get } - /// Color for notifications for mention messages - var notificationPrimaryColor: UIColor { get } + var lineBreakColor: UIColor { get } + + var noticeColor: UIColor { get } + var noticeSecondaryColor: UIColor { get } /// Color for errors or warnings var warningColor: UIColor { get } diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index 6292bec3c..3dc3bf5f9 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -28,7 +28,7 @@ class DarkTheme: NSObject, Theme { var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xEDF3FF) var searchBackgroundColor: UIColor = UIColor(rgb: 0x181B21) - var searchTextColor: UIColor = UIColor(rgb: 0x61708B) + var searchPlaceholderColor: UIColor = UIColor(rgb: 0x61708B) var headerBackgroundColor: UIColor = UIColor(rgb: 0x181B21) var headerBorderColor: UIColor = UIColor(rgb: 0x22262E) @@ -40,9 +40,10 @@ class DarkTheme: NSObject, Theme { var tintColor: UIColor = UIColor(rgb: 0x03B381) var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) + var lineBreakColor: UIColor = UIColor(rgb: 0x61708B) - var notificationSecondaryColor: UIColor = UIColor(rgb: 0x61708B) - var notificationPrimaryColor: UIColor = UIColor(rgb: 0xFF4B55) + var noticeColor: UIColor = UIColor(rgb: 0xFF4B55) + var noticeSecondaryColor: UIColor = UIColor(rgb: 0x61708B) var warningColor: UIColor = UIColor(rgb: 0xFF4B55) @@ -74,7 +75,7 @@ class DarkTheme: NSObject, Theme { func applyStyle(onSearchBar searchBar: UISearchBar) { searchBar.barStyle = .black - searchBar.tintColor = self.searchTextColor; + searchBar.tintColor = self.searchPlaceholderColor; searchBar.barTintColor = self.headerBackgroundColor; searchBar.layer.borderWidth = 1; searchBar.layer.borderColor = self.headerBorderColor.cgColor; diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index 4d01ce5d7..a521a6b28 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -28,7 +28,7 @@ class DefaultTheme: NSObject, Theme { var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xFFFFFF) var searchBackgroundColor: UIColor = UIColor(rgb: 0xFFFFFF) - var searchTextColor: UIColor = UIColor(rgb: 0x61708B) // Name in the associated palette is Search Placeholder + var searchPlaceholderColor: UIColor = UIColor(rgb: 0x61708B) var headerBackgroundColor: UIColor = UIColor(rgb: 0xF2F5F8) var headerBorderColor: UIColor = UIColor(rgb: 0xE9EDF1) @@ -40,9 +40,10 @@ class DefaultTheme: NSObject, Theme { var tintColor: UIColor = UIColor(rgb: 0x03B381) var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) + var lineBreakColor: UIColor = UIColor(rgb: 0xEEEFEF) - var notificationSecondaryColor: UIColor = UIColor(rgb: 0x61708B) - var notificationPrimaryColor: UIColor = UIColor(rgb: 0xFF4B55) + var noticeColor: UIColor = UIColor(rgb: 0xFF4B55) + var noticeSecondaryColor: UIColor = UIColor(rgb: 0x61708B) var warningColor: UIColor = UIColor(rgb: 0xFF4B55) @@ -74,7 +75,7 @@ class DefaultTheme: NSObject, Theme { func applyStyle(onSearchBar searchBar: UISearchBar) { searchBar.barStyle = .default - searchBar.tintColor = self.searchTextColor; + searchBar.tintColor = self.searchPlaceholderColor; searchBar.barTintColor = self.headerBackgroundColor; searchBar.layer.borderWidth = 1; searchBar.layer.borderColor = self.headerBorderColor.cgColor; diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 7ab19dda2..4eb05500b 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -109,7 +109,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { - self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor; + self.missedNotifAndUnreadIndicator.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor; self.missedNotifAndUnreadBadgeBgView.hidden = NO; self.missedNotifAndUnreadBadgeBgView.backgroundColor = self.missedNotifAndUnreadIndicator.backgroundColor; diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index 0152d8382..16fea90a2 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -58,7 +58,7 @@ NSString *const kGroupInviteTableViewCellRoomKey = @"kGroupInviteTableViewCellRo self.leftButton.backgroundColor = ThemeService.shared.riotColorBlue; self.rightButton.backgroundColor = ThemeService.shared.riotColorBlue; - self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; + self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.noticeColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index 1d9cb0f54..d555ee4c9 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -126,7 +126,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; if (0 < roomCellData.notificationCount) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = roomCellData.highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor; self.missedNotifAndUnreadBadgeLabel.text = roomCellData.notificationCountStringValue; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; @@ -147,7 +147,7 @@ static const CGFloat kDirectRoomBorderWidth = 3.0; else if (roomCellData.roomSummary.room.summary.membership == MXMembershipInvite) { self.missedNotifAndUnreadBadgeBgView.hidden = NO; - self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; + self.missedNotifAndUnreadBadgeBgView.backgroundColor = ThemeService.shared.theme.noticeColor; self.missedNotifAndUnreadBadgeLabel.text = @"!"; [self.missedNotifAndUnreadBadgeLabel sizeToFit]; diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift index 5f933f147..e66faad15 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift @@ -237,7 +237,7 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { textColor = self.theme.tintColor } else { text = VectorL10n.keyBackupSetupPassphrasePassphraseInvalid - textColor = self.theme.notificationPrimaryColor + textColor = self.theme.noticeColor } self.passphraseAdditionalLabel.text = text @@ -254,7 +254,7 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { textColor = self.theme.tintColor } else { text = VectorL10n.keyBackupSetupPassphraseConfirmPassphraseInvalid - textColor = self.theme.notificationPrimaryColor + textColor = self.theme.noticeColor } self.confirmPassphraseAdditionalLabel.text = text diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index 993ed2a89..b9a7de18b 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -63,7 +63,7 @@ NSString *const kInviteRecentTableViewCellRoomKey = @"kInviteRecentTableViewCell self.leftButton.backgroundColor = ThemeService.shared.theme.tintColor; self.rightButton.backgroundColor = ThemeService.shared.theme.tintColor; - self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; + self.noticeBadgeView.backgroundColor = ThemeService.shared.theme.noticeColor; } - (void)onDeclinePressed:(id)sender diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 88c18349e..ff76347df 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4245,11 +4245,11 @@ // Set the right background color if (highlightCount) { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationPrimaryColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.noticeColor; } else { - missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.notificationSecondaryColor; + missedDiscussionsBadgeLabelBgView.backgroundColor = ThemeService.shared.theme.noticeSecondaryColor; } if (!missedDiscussionsButton || [leftBarButtonItems indexOfObject:missedDiscussionsButton] == NSNotFound) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 49a94f664..d926c8781 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -798,15 +798,15 @@ // Use a middle dot to signal missed notif in favourites [self setMissedDiscussionsMark:(recentsDataSource.missedFavouriteDiscussionsCount? @"\u00B7": nil) onTabBarItem:TABBAR_FAVOURITES_INDEX - withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor)]; + withBadgeColor:(recentsDataSource.missedHighlightFavouriteDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)]; // Update the badge on People and Rooms tabs [self setMissedDiscussionsCount:recentsDataSource.missedDirectDiscussionsCount onTabBarItem:TABBAR_PEOPLE_INDEX - withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor)]; + withBadgeColor:(recentsDataSource.missedHighlightDirectDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)]; [self setMissedDiscussionsCount:recentsDataSource.missedGroupDiscussionsCount onTabBarItem:TABBAR_ROOMS_INDEX - withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.notificationPrimaryColor : ThemeService.shared.theme.notificationSecondaryColor)]; + withBadgeColor:(recentsDataSource.missedHighlightGroupDiscussionsCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor)]; } - (void)setMissedDiscussionsCount:(NSUInteger)count onTabBarItem:(NSUInteger)index withBadgeColor:(UIColor*)badgeColor diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 8709609dd..44d3feac1 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -220,7 +220,7 @@ NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor; self.subTitleTextColor = ThemeService.shared.theme.textSecondaryColor; self.prefixTextColor = ThemeService.shared.theme.textSecondaryColor; - self.bingTextColor = ThemeService.shared.theme.notificationPrimaryColor; + self.bingTextColor = ThemeService.shared.theme.noticeColor; self.encryptingTextColor = ThemeService.shared.theme.tintColor; self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; self.errorTextColor = ThemeService.shared.theme.warningColor; From 2742a13b919cc823415afa353dc9ac01664317b8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Tue, 12 Feb 2019 19:24:08 +0100 Subject: [PATCH 188/244] RoomVC: Remove the beta warning modal when opening an e2e room #2239 --- CHANGES.rst | 1 + Riot/Modules/Room/RoomViewController.m | 29 -------------------------- 2 files changed, 1 insertion(+), 29 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index e0efdbf65..17139e6d7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -5,6 +5,7 @@ Improvements: * Theming: Create ThemeService to make theming easier. Use it to reskin Riot. * Use modern literals and array/dictionary syntax where possible (PR #2160). * Add SwiftGen pod in order to generate Swift constants for assets (#2177). + * RoomVC: Remove the beta warning modal when opening an e2e room (#2239). * RoomVC: `Redact` has been renamed to `Remove` to match riot/web (#2134). * Clean up iOS version checking (#2190). * Key backup: Implement setup screen (#2198). diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 88c18349e..a1ed57167 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -567,35 +567,6 @@ } }]; [self refreshMissedDiscussionsCount:YES]; - - // Warn about the beta state of e2e encryption when entering the first time in an encrypted room - MXKAccount *account = [[MXKAccountManager sharedManager] accountForUserId:self.roomDataSource.mxSession.myUser.userId]; - if (account && !account.isWarnedAboutEncryption && self.roomDataSource.room.summary.isEncrypted) - { - [currentAlert dismissViewControllerAnimated:NO completion:nil]; - - __weak __typeof(self) weakSelf = self; - currentAlert = [UIAlertController alertControllerWithTitle:NSLocalizedStringFromTable(@"warning", @"Vector", nil) - message:NSLocalizedStringFromTable(@"room_warning_about_encryption", @"Vector", nil) - preferredStyle:UIAlertControllerStyleAlert]; - - [currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - account.warnedAboutEncryption = YES; - } - - }]]; - - [currentAlert mxk_setAccessibilityIdentifier:@"RoomVCEncryptionAlert"]; - [self presentViewController:currentAlert animated:YES completion:nil]; - } } - (void)viewDidDisappear:(BOOL)animated From 214af86039a78e5fec97fc99f04de9795077e61c Mon Sep 17 00:00:00 2001 From: manuroe Date: Wed, 13 Feb 2019 09:39:32 +0100 Subject: [PATCH 189/244] Reskin: Replace separatorColor with lineBreakColor, the color introduced in the new uniformed palette --- Riot/Managers/Theme/Theme.swift | 3 --- Riot/Managers/Theme/Themes/DarkTheme.swift | 1 - Riot/Managers/Theme/Themes/DefaultTheme.swift | 1 - .../Passphrase/KeyBackupSetupPassphraseViewController.swift | 2 +- .../RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift | 2 +- 5 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Riot/Managers/Theme/Theme.swift b/Riot/Managers/Theme/Theme.swift index e576d7441..839f4641c 100644 --- a/Riot/Managers/Theme/Theme.swift +++ b/Riot/Managers/Theme/Theme.swift @@ -77,9 +77,6 @@ import UIKit /// Color to tint the search background image var matrixSearchBackgroundImageTintColor: UIColor { get } - - /// Color of separator (when table view is not used) - var separatorColor: UIColor { get } // MARK: - Customisation methods diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index 3dc3bf5f9..cd57acefd 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -60,7 +60,6 @@ class DarkTheme: NSObject, Theme { var selectedBackgroundColor: UIColor? = UIColor.black var overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0x7E7E7E) - var separatorColor: UIColor = UIColor(rgb: 0x2E2F31) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index a521a6b28..3a14b3f95 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -60,7 +60,6 @@ class DefaultTheme: NSObject, Theme { var selectedBackgroundColor: UIColor? = nil // Use the default selection color var overlayBackgroundColor: UIColor = UIColor(white: 0.7, alpha: 0.5) var matrixSearchBackgroundImageTintColor: UIColor = UIColor(rgb: 0xE7E7E7) - var separatorColor: UIColor = UIColor(rgb: 0xEAEEF2) func applyStyle(onNavigationBar navigationBar: UINavigationBar) { navigationBar.tintColor = self.baseTextPrimaryColor; diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift index e66faad15..ac074b90a 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift @@ -147,7 +147,7 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { attributes: [.foregroundColor : theme.placeholderTextColor]) self.updatePassphraseAdditionalLabel() - self.formSeparatorView.backgroundColor = theme.separatorColor + self.formSeparatorView.backgroundColor = theme.lineBreakColor self.confirmPassphraseTitleLabel.textColor = theme.textPrimaryColor theme.applyStyle(onTextField: self.confirmPassphraseTextField) diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift index 0e154c506..9f7ba38be 100644 --- a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewController.swift @@ -101,7 +101,7 @@ final class KeyBackupSetupRecoveryKeyViewController: UIViewController { self.recoveryKeyTitleLabel.textColor = theme.textPrimaryColor self.recoveryKeyLabel.textColor = theme.textPrimaryColor - self.separatorView.backgroundColor = theme.separatorColor + self.separatorView.backgroundColor = theme.lineBreakColor theme.applyStyle(onButton: self.makeCopyButton) From d9ad8d6b0dbd90b7506fd92ce7f22bfbacee52b9 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 13:06:14 +0100 Subject: [PATCH 190/244] Update key backup logo image --- .../Contents.json | 9 ++++++--- .../key_backup_logo.imageset/key_backup_logo.png | Bin 0 -> 1592 bytes .../key_backup_logo@2x.png | Bin 0 -> 3229 bytes .../key_backup_logo@3x.png | Bin 0 -> 4923 bytes .../KeyBackup/shield.imageset/shield.png | Bin 1588 -> 0 bytes .../KeyBackup/shield.imageset/shield@2x.png | Bin 3171 -> 0 bytes .../KeyBackup/shield.imageset/shield@3x.png | Bin 5149 -> 0 bytes Riot/Generated/Images.swift | 2 +- 8 files changed, 7 insertions(+), 4 deletions(-) rename Riot/Assets/Images.xcassets/KeyBackup/{shield.imageset => key_backup_logo.imageset}/Contents.json (57%) create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/key_backup_logo.png create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/key_backup_logo@2x.png create mode 100644 Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/key_backup_logo@3x.png delete mode 100644 Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield.png delete mode 100644 Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield@2x.png delete mode 100644 Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield@3x.png diff --git a/Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/Contents.json b/Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/Contents.json similarity index 57% rename from Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/Contents.json rename to Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/Contents.json index dc15151e8..f96088786 100644 --- a/Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/Contents.json @@ -2,22 +2,25 @@ "images" : [ { "idiom" : "universal", - "filename" : "shield.png", + "filename" : "key_backup_logo.png", "scale" : "1x" }, { "idiom" : "universal", - "filename" : "shield@2x.png", + "filename" : "key_backup_logo@2x.png", "scale" : "2x" }, { "idiom" : "universal", - "filename" : "shield@3x.png", + "filename" : "key_backup_logo@3x.png", "scale" : "3x" } ], "info" : { "version" : 1, "author" : "xcode" + }, + "properties" : { + "template-rendering-intent" : "template" } } \ No newline at end of file diff --git a/Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/key_backup_logo.png b/Riot/Assets/Images.xcassets/KeyBackup/key_backup_logo.imageset/key_backup_logo.png new file mode 100644 index 0000000000000000000000000000000000000000..ebdda3c65a05ff5e7968921736e29684e6fa9d91 GIT binary patch literal 1592 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 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield.png b/Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield.png deleted file mode 100644 index 7b52cc78e6e259b2991b9f1d049d2153087d179c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1588 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 diff --git a/Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield@3x.png b/Riot/Assets/Images.xcassets/KeyBackup/shield.imageset/shield@3x.png deleted file mode 100644 index f63740a27605a833f7301dca587f4e43049eb902..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5149 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 IsG}nO2aPGE5&!@I diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index 5e9e81d69..78ad0f5a7 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -61,8 +61,8 @@ internal enum Asset { internal static let createRoom = ImageAsset(name: "create_room") internal static let closeBanner = ImageAsset(name: "close_banner") internal static let importFilesButton = ImageAsset(name: "import_files_button") + internal static let keyBackupLogo = ImageAsset(name: "key_backup_logo") internal static let revealPasswordButton = ImageAsset(name: "reveal_password_button") - internal static let shield = ImageAsset(name: "shield") internal static let launchScreenRiot = ImageAsset(name: "LaunchScreenRiot") internal static let cameraCapture = ImageAsset(name: "camera_capture") internal static let cameraPlay = ImageAsset(name: "camera_play") From a28520e249d77e31a5dd40d70072366c9821f245 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 13:09:48 +0100 Subject: [PATCH 191/244] Update key backup strings --- Riot/Assets/en.lproj/Vector.strings | 42 +++++++----- Riot/Generated/Strings.swift | 100 ++++++++++++++++++---------- 2 files changed, 90 insertions(+), 52 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 51fc91508..e60d5dc40 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -671,8 +671,7 @@ // MARK: Key backup setup -"key_backup_setup_title" = "Message Recovery"; -"key_backup_setup_skip_action" = "Skip"; +"key_backup_setup_title" = "Key Backup"; "key_backup_setup_skip_alert_title" = "Are you sure?"; "key_backup_setup_skip_alert_message" = "You may lose secure messages if you log out or lose your device."; @@ -681,13 +680,14 @@ // Intro "key_backup_setup_intro_title" = "Never lose encrypted messages"; -"key_backup_setup_intro_info" = "Set up Secure Message Recovery in case you lose or log out of this device."; -"key_backup_setup_intro_setup_action" = "Set up"; - +"key_backup_setup_intro_info" = "Messages in encrypted rooms are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.\n\nSecurely back up your keys to avoid losing them."; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Start using Key Backup"; +"key_backup_setup_intro_setup_action_with_existing_backup" = "Use Key Backup"; // Passphrase -"key_backup_setup_passphrase_info" = "Secure your encrypted message history with a Recovery Passphrase.\n\nYou’ll need it if you log out, or lose access to this device."; +"key_backup_setup_passphrase_title" = "Secure your backup with a Passphrase"; +"key_backup_setup_passphrase_info" = "We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.\n\nFor maximum security, this should be different from your account password."; "key_backup_setup_passphrase_passphrase_title" = "Enter"; "key_backup_setup_passphrase_passphrase_placeholder" = "Enter passphrase"; "key_backup_setup_passphrase_passphrase_valid" = "Great!"; @@ -696,14 +696,24 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Confirm passphrase"; "key_backup_setup_passphrase_confirm_passphrase_valid" = "Great!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passphrase doesn’t match"; -"key_backup_setup_passphrase_set_passphrase_action" = "Set recovery passphrase"; +"key_backup_setup_passphrase_set_passphrase_action" = "Set Passphrase"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Or, secure your backup with a Recovery Key, saving it somewhere safe."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Advanced) Set up with Recovery Key"; -// Recovery key +// Success -"key_backup_setup_recovery_key_info" = "Make a copy of this Recovery Key and keep it safe.\n\nAs a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase."; -"key_backup_setup_recovery_key_recovery_key_title" = "Recovery Key"; -"key_backup_setup_recovery_key_make_copy_action" = "Make a Copy"; -"key_backup_setup_recovery_key_made_copy_action" = "I've made a copy"; +"key_backup_setup_success_title" = "Success!"; + +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Your keys are being backed up.\n\nYour recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your passphrase.\n\nKeep your recovery key somewhere very secure, like a password manager (or a safe)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Save Recovery Key"; +"key_backup_setup_success_from_passphrase_done_action" = "Done"; + +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Your keys are being backed up.\n\nMake a copy of this recovery key and keep it safe."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Recovery Key"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Make a Copy"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "I've made a copy"; // MARK: Key backup recover @@ -738,10 +748,10 @@ // MARK: Key backup setup banner -"key_backup_setup_banner_title_part1" = "Set up Secure Message Recovery"; -"key_backup_setup_banner_title_part2" = " to never lose encrypted messages"; +"key_backup_setup_banner_title" = "Never lose encrypted messages"; +"key_backup_setup_banner_subtitle" = "Start using Key Backup"; // MARK: Key backup recover banner -"key_backup_recover_banner_title_part1" = "Run Secure Message Recovery"; -"key_backup_recover_banner_title_part2" = " to read encrypted message history on this device"; +"key_backup_recover_banner_title" = "Never lose encrypted messages"; +"key_backup_recover_banner_subtitle" = "Use Key Backup"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index e190a7515..23743efc8 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -662,13 +662,13 @@ internal enum VectorL10n { internal static var join: String { return VectorL10n.tr("Vector", "join") } - /// Run Secure Message Recovery - internal static var keyBackupRecoverBannerTitlePart1: String { - return VectorL10n.tr("Vector", "key_backup_recover_banner_title_part1") + /// Use Key Backup + internal static var keyBackupRecoverBannerSubtitle: String { + return VectorL10n.tr("Vector", "key_backup_recover_banner_subtitle") } - /// to read encrypted message history on this device - internal static var keyBackupRecoverBannerTitlePart2: String { - return VectorL10n.tr("Vector", "key_backup_recover_banner_title_part2") + /// Never lose encrypted messages + internal static var keyBackupRecoverBannerTitle: String { + return VectorL10n.tr("Vector", "key_backup_recover_banner_title") } /// Done internal static var keyBackupRecoverDoneAction: String { @@ -738,21 +738,25 @@ internal enum VectorL10n { internal static var keyBackupRecoverTitle: String { return VectorL10n.tr("Vector", "key_backup_recover_title") } - /// Set up Secure Message Recovery - internal static var keyBackupSetupBannerTitlePart1: String { - return VectorL10n.tr("Vector", "key_backup_setup_banner_title_part1") + /// Start using Key Backup + internal static var keyBackupSetupBannerSubtitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_banner_subtitle") } - /// to never lose encrypted messages - internal static var keyBackupSetupBannerTitlePart2: String { - return VectorL10n.tr("Vector", "key_backup_setup_banner_title_part2") + /// Never lose encrypted messages + internal static var keyBackupSetupBannerTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_banner_title") } - /// Set up Secure Message Recovery in case you lose or log out of this device. + /// Messages in encrypted rooms are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.\n\nSecurely back up your keys to avoid losing them. internal static var keyBackupSetupIntroInfo: String { return VectorL10n.tr("Vector", "key_backup_setup_intro_info") } - /// Set up - internal static var keyBackupSetupIntroSetupAction: String { - return VectorL10n.tr("Vector", "key_backup_setup_intro_setup_action") + /// Use Key Backup + internal static var keyBackupSetupIntroSetupActionWithExistingBackup: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_setup_action_with_existing_backup") + } + /// Start using Key Backup + internal static var keyBackupSetupIntroSetupActionWithoutExistingBackup: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_setup_action_without_existing_backup") } /// Never lose encrypted messages internal static var keyBackupSetupIntroTitle: String { @@ -774,7 +778,7 @@ internal enum VectorL10n { internal static var keyBackupSetupPassphraseConfirmPassphraseValid: String { return VectorL10n.tr("Vector", "key_backup_setup_passphrase_confirm_passphrase_valid") } - /// Secure your encrypted message history with a Recovery Passphrase.\n\nYou’ll need it if you log out, or lose access to this device. + /// We'll store an encrypted copy of your keys on our server. Protect your backup with a passphrase to keep it secure.\n\nFor maximum security, this should be different from your account password. internal static var keyBackupSetupPassphraseInfo: String { return VectorL10n.tr("Vector", "key_backup_setup_passphrase_info") } @@ -794,29 +798,21 @@ internal enum VectorL10n { internal static var keyBackupSetupPassphrasePassphraseValid: String { return VectorL10n.tr("Vector", "key_backup_setup_passphrase_passphrase_valid") } - /// Set recovery passphrase + /// Set Passphrase internal static var keyBackupSetupPassphraseSetPassphraseAction: String { return VectorL10n.tr("Vector", "key_backup_setup_passphrase_set_passphrase_action") } - /// Make a copy of this Recovery Key and keep it safe.\n\nAs a safety net, you can use it to restore your encrypted message history if you forget your Recovery Passphrase. - internal static var keyBackupSetupRecoveryKeyInfo: String { - return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_info") + /// (Advanced) Set up with Recovery Key + internal static var keyBackupSetupPassphraseSetupRecoveryKeyAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_setup_recovery_key_action") } - /// I've made a copy - internal static var keyBackupSetupRecoveryKeyMadeCopyAction: String { - return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_made_copy_action") + /// Or, secure your backup with a Recovery Key, saving it somewhere safe. + internal static var keyBackupSetupPassphraseSetupRecoveryKeyInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_setup_recovery_key_info") } - /// Make a Copy - internal static var keyBackupSetupRecoveryKeyMakeCopyAction: String { - return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_make_copy_action") - } - /// Recovery Key - internal static var keyBackupSetupRecoveryKeyRecoveryKeyTitle: String { - return VectorL10n.tr("Vector", "key_backup_setup_recovery_key_recovery_key_title") - } - /// Skip - internal static var keyBackupSetupSkipAction: String { - return VectorL10n.tr("Vector", "key_backup_setup_skip_action") + /// Secure your backup with a Passphrase + internal static var keyBackupSetupPassphraseTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_passphrase_title") } /// You may lose secure messages if you log out or lose your device. internal static var keyBackupSetupSkipAlertMessage: String { @@ -830,7 +826,39 @@ internal enum VectorL10n { internal static var keyBackupSetupSkipAlertTitle: String { return VectorL10n.tr("Vector", "key_backup_setup_skip_alert_title") } - /// Message Recovery + /// Done + internal static var keyBackupSetupSuccessFromPassphraseDoneAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_passphrase_done_action") + } + /// Your keys are being backed up.\n\nYour recovery key is a safety net - you can use it to restore access to your encrypted messages if you forget your passphrase.\n\nKeep your recovery key somewhere very secure, like a password manager (or a safe). + internal static var keyBackupSetupSuccessFromPassphraseInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_passphrase_info") + } + /// Save Recovery Key + internal static var keyBackupSetupSuccessFromPassphraseSaveRecoveryKeyAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_passphrase_save_recovery_key_action") + } + /// Your keys are being backed up.\n\nMake a copy of this recovery key and keep it safe. + internal static var keyBackupSetupSuccessFromRecoveryKeyInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_recovery_key_info") + } + /// I've made a copy + internal static var keyBackupSetupSuccessFromRecoveryKeyMadeCopyAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_recovery_key_made_copy_action") + } + /// Make a Copy + internal static var keyBackupSetupSuccessFromRecoveryKeyMakeCopyAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_recovery_key_make_copy_action") + } + /// Recovery Key + internal static var keyBackupSetupSuccessFromRecoveryKeyRecoveryKeyTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_from_recovery_key_recovery_key_title") + } + /// Success! + internal static var keyBackupSetupSuccessTitle: String { + return VectorL10n.tr("Vector", "key_backup_setup_success_title") + } + /// Key Backup internal static var keyBackupSetupTitle: String { return VectorL10n.tr("Vector", "key_backup_setup_title") } From fafcd09e10c8cf989c398dda8f2160c735a105ef Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 13:31:15 +0100 Subject: [PATCH 192/244] Update KeyBackupBannerCell and handle safe area when compute cell size --- Riot/Modules/Home/HomeViewController.m | 13 +++- .../Banners/KeyBackupBannerCell.swift | 31 ++++----- .../KeyBackup/Banners/KeyBackupBannerCell.xib | 65 ++++++++++++------- 3 files changed, 67 insertions(+), 42 deletions(-) diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 5d7230044..8a63a4559 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -390,11 +390,20 @@ [sizingCell layoutIfNeeded]; CGSize fittingSize = UILayoutFittingCompressedSize; - fittingSize.width = CGRectGetWidth(tableView.frame); + CGFloat tableViewWidth = CGRectGetWidth(tableView.frame); + CGFloat safeAreaWidth; + + if (@available(iOS 11.0, *)) { + // Take safe area into account + safeAreaWidth = MAX(tableView.safeAreaInsets.left, tableView.safeAreaInsets.right); + } else { + safeAreaWidth = 0; + } + + fittingSize.width = tableViewWidth - safeAreaWidth; height = [sizingCell systemLayoutSizeFittingSize:fittingSize withHorizontalFittingPriority:UILayoutPriorityRequired verticalFittingPriority:UILayoutPriorityFittingSizeLevel].height; - return height; } diff --git a/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift index e0f2ca6ab..c2945d375 100644 --- a/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift +++ b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.swift @@ -28,7 +28,8 @@ final class KeyBackupBannerCell: MXKTableViewCell { // MARK: Outlets @IBOutlet private weak var shieldImageView: UIImageView! - @IBOutlet private weak var informationLabel: UILabel! + @IBOutlet private weak var titleLabel: UILabel! + @IBOutlet private weak var subtitleLabel: UILabel! @IBOutlet private weak var closeButton: UIButton! // MARK: Public @@ -53,9 +54,8 @@ final class KeyBackupBannerCell: MXKTableViewCell { self.shieldImageView.tintColor = theme.textPrimaryColor self.closeButton.tintColor = theme.textPrimaryColor - let attributedTitle = NSMutableAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart1, attributes: [.foregroundColor: theme.tintColor]) - attributedTitle.append(NSAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart2, attributes: [.foregroundColor: theme.textPrimaryColor])) - self.informationLabel.attributedText = attributedTitle + self.titleLabel.textColor = theme.textPrimaryColor + self.subtitleLabel.textColor = theme.tintColor } // MARK: - Life cycle @@ -63,7 +63,7 @@ final class KeyBackupBannerCell: MXKTableViewCell { override func awakeFromNib() { super.awakeFromNib() - let shieldImage = Asset.Images.shield.image.withRenderingMode(.alwaysTemplate) + let shieldImage = Asset.Images.keyBackupLogo.image.withRenderingMode(.alwaysTemplate) self.shieldImageView.image = shieldImage let closeImage = Asset.Images.closeBanner.image.withRenderingMode(.alwaysTemplate) @@ -73,23 +73,24 @@ final class KeyBackupBannerCell: MXKTableViewCell { // MARK: - Public func configure(for banner: KeyBackupBanner) { - let attributedTitle: NSAttributedString? - let theme = ThemeService.shared().theme + + let title: String? + let subtitle: String? switch banner { case .setup: - let setupAttributedTitle = NSMutableAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart1, attributes: [.foregroundColor: theme.tintColor]) - setupAttributedTitle.append(NSAttributedString(string: VectorL10n.keyBackupSetupBannerTitlePart2, attributes: [.foregroundColor: theme.textPrimaryColor])) - attributedTitle = setupAttributedTitle + title = VectorL10n.keyBackupSetupBannerTitle + subtitle = VectorL10n.keyBackupSetupBannerSubtitle case .recover: - let recoverAttributedTitle = NSMutableAttributedString(string: VectorL10n.keyBackupRecoverBannerTitlePart1, attributes: [.foregroundColor: theme.tintColor]) - recoverAttributedTitle.append(NSAttributedString(string: VectorL10n.keyBackupRecoverBannerTitlePart2, attributes: [.foregroundColor: theme.textPrimaryColor])) - attributedTitle = recoverAttributedTitle + title = VectorL10n.keyBackupRecoverBannerTitle + subtitle = VectorL10n.keyBackupRecoverBannerSubtitle case .none: - attributedTitle = nil + title = nil + subtitle = nil } - self.informationLabel.attributedText = attributedTitle + self.titleLabel.text = title + self.subtitleLabel.text = subtitle } // MARK: - Actions diff --git a/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib index fa630ec0a..6e933fc4d 100644 --- a/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib +++ b/Riot/Modules/KeyBackup/Banners/KeyBackupBannerCell.xib @@ -1,36 +1,49 @@ + + + + - - + + - + - - + + - - + + - + + + + + + + - - - + + - - + + + + - + - + + - + - + From 1bbf657ddb7f22661703fe150216694f244f16bd Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 13:36:35 +0100 Subject: [PATCH 193/244] Create new key backup setup success view controllers --- Riot.xcodeproj/project.pbxproj | 24 ++ Riot/Generated/Storyboards.swift | 10 + ...essFromPassphraseViewController.storyboard | 180 +++++++++++++ ...pSuccessFromPassphraseViewController.swift | 149 +++++++++++ ...ssFromRecoveryKeyViewController.storyboard | 245 ++++++++++++++++++ ...SuccessFromRecoveryKeyViewController.swift | 181 +++++++++++++ 6 files changed, 789 insertions(+) create mode 100644 Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift create mode 100644 Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard create mode 100644 Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index e09eab269..c9c72362a 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -40,6 +40,10 @@ 92726A4B1F58737A004AD26F /* SiriIntents.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 92726A431F58737A004AD26F /* SiriIntents.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 92726A511F587410004AD26F /* Intents.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 92726A501F587410004AD26F /* Intents.framework */; }; B104C2942203773C00D9F496 /* KeyBackupBannerPreferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = B104C2932203773B00D9F496 /* KeyBackupBannerPreferences.swift */; }; + B1057789221304EC00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1057788221304EB00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift */; }; + B105778B221304FA00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B105778A221304FA00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.storyboard */; }; + B105778D2213051E00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B105778C2213051E00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.swift */; }; + B105778F2213052A00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = B105778E2213052A00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard */; }; B1098BDF21ECE09F000DDA48 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDA21ECE09E000DDA48 /* Strings.swift */; }; B1098BE121ECE09F000DDA48 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDC21ECE09E000DDA48 /* Images.swift */; }; B1098BE321ECE09F000DDA48 /* RiotDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */; }; @@ -512,6 +516,10 @@ 92726A4F1F587393004AD26F /* SiriIntents.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = SiriIntents.entitlements; sourceTree = ""; }; 92726A501F587410004AD26F /* Intents.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Intents.framework; path = System/Library/Frameworks/Intents.framework; sourceTree = SDKROOT; }; B104C2932203773B00D9F496 /* KeyBackupBannerPreferences.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyBackupBannerPreferences.swift; sourceTree = ""; }; + B1057788221304EB00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupSuccessFromPassphraseViewController.swift; sourceTree = ""; }; + B105778A221304FA00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupSetupSuccessFromPassphraseViewController.storyboard; sourceTree = ""; }; + B105778C2213051E00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupSetupSuccessFromRecoveryKeyViewController.swift; sourceTree = ""; }; + B105778E2213052A00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard; sourceTree = ""; }; B1098BDA21ECE09E000DDA48 /* Strings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = ""; }; B1098BDC21ECE09E000DDA48 /* Images.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = ""; }; B1098BDE21ECE09E000DDA48 /* RiotDefaults.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RiotDefaults.swift; sourceTree = ""; }; @@ -1225,6 +1233,17 @@ name = Pods; sourceTree = ""; }; + B1057787221304A200334B1E /* Success */ = { + isa = PBXGroup; + children = ( + B1057788221304EB00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift */, + B105778A221304FA00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.storyboard */, + B105778C2213051E00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.swift */, + B105778E2213052A00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard */, + ); + path = Success; + sourceTree = ""; + }; B1098BD921ECE09E000DDA48 /* Generated */ = { isa = PBXGroup; children = ( @@ -1263,6 +1282,7 @@ B1098C0521ECFF5B000DDA48 /* Intro */, B1098C0321ECFECC000DDA48 /* Passphrase */, B1098C0621ED00A9000DDA48 /* RecoveryKey */, + B1057787221304A200334B1E /* Success */, ); path = Setup; sourceTree = ""; @@ -3121,6 +3141,7 @@ B1B558BC20EF768F00210D55 /* RoomMembershipBubbleCell.xib in Resources */, B1B5571F20EE6C4D00210D55 /* ContactDetailsViewController.xib in Resources */, B1B558E220EF768F00210D55 /* RoomIncomingTextMsgBubbleCell.xib in Resources */, + B105778B221304FA00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.storyboard in Resources */, B1664DA220F4F95800808783 /* Localizable.strings in Resources */, B169328720F3954A00746532 /* SharedImages.xcassets in Resources */, B1664DA120F4F94F00808783 /* InfoPlist.strings in Resources */, @@ -3209,6 +3230,7 @@ B1B557D220EF5E3500210D55 /* MediaAlbumTableCell.xib in Resources */, B1B558C520EF768F00210D55 /* RoomOutgoingEncryptedTextMsgBubbleCell.xib in Resources */, B1B5582B20EF666100210D55 /* DirectoryRecentTableViewCell.xib in Resources */, + B105778F2213052A00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard in Resources */, B1B5590F20EF782800210D55 /* TableViewCellWithPhoneNumberTextField.xib in Resources */, B1B5578520EF564900210D55 /* GroupTableViewCellWithSwitch.xib in Resources */, B1B557B320EF5AEF00210D55 /* EventDetailsView.xib in Resources */, @@ -3425,6 +3447,7 @@ B169330820F3CA0E00746532 /* ContactsDataSource.m in Sources */, B1B5574B20EE6C4D00210D55 /* MediaAlbumContentViewController.m in Sources */, B1B5598820EFC3E000210D55 /* WidgetManager.m in Sources */, + B1057789221304EC00334B1E /* KeyBackupSetupSuccessFromPassphraseViewController.swift in Sources */, B16932B120F3AC9200746532 /* RoomSearchDataSource.m in Sources */, B16932A320F3A21C00746532 /* main.m in Sources */, B1B5574520EE6C4D00210D55 /* StartChatViewController.m in Sources */, @@ -3578,6 +3601,7 @@ B1B558E620EF768F00210D55 /* RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, B1098BFB21ECFE65000DDA48 /* KeyBackupSetupCoordinatorType.swift in Sources */, B1098BF721ECFE65000DDA48 /* PasswordStrength.swift in Sources */, + B105778D2213051E00334B1E /* KeyBackupSetupSuccessFromRecoveryKeyViewController.swift in Sources */, B1B557D820EF5EA900210D55 /* RoomActivitiesView.m in Sources */, B1B5596620EF9E9B00210D55 /* RoomTableViewCell.m in Sources */, B1B558D020EF768F00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, diff --git a/Riot/Generated/Storyboards.swift b/Riot/Generated/Storyboards.swift index 27244bb99..564284896 100644 --- a/Riot/Generated/Storyboards.swift +++ b/Riot/Generated/Storyboards.swift @@ -42,6 +42,16 @@ internal enum StoryboardScene { internal static let initialScene = InitialSceneType(storyboard: KeyBackupSetupRecoveryKeyViewController.self) } + internal enum KeyBackupSetupSuccessFromPassphraseViewController: StoryboardType { + internal static let storyboardName = "KeyBackupSetupSuccessFromPassphraseViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupSetupSuccessFromPassphraseViewController.self) + } + internal enum KeyBackupSetupSuccessFromRecoveryKeyViewController: StoryboardType { + internal static let storyboardName = "KeyBackupSetupSuccessFromRecoveryKeyViewController" + + internal static let initialScene = InitialSceneType(storyboard: KeyBackupSetupSuccessFromRecoveryKeyViewController.self) + } } // swiftlint:enable explicit_type_interface identifier_name line_length type_body_length type_name diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.storyboard new file mode 100644 index 000000000..23350ef8a --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.storyboard @@ -0,0 +1,180 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift new file mode 100644 index 000000000..c7e15b64d --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift @@ -0,0 +1,149 @@ +/* + Copyright 2019 New Vector 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 UIKit + +protocol KeyBackupSetupSuccessFromPassphraseViewControllerDelegate: class { + func keyBackupSetupSuccessFromPassphraseViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromPassphraseViewController) +} + +final class KeyBackupSetupSuccessFromPassphraseViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var keyBackupLogoImageView: UIImageView! + @IBOutlet private weak var titleLabel: UILabel! + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var saveRecoveryKeyButtonBackgroundView: UIView! + @IBOutlet private weak var saveRecoveryKeyButton: UIButton! + + @IBOutlet private weak var doneButtonBackgroundView: UIView! + @IBOutlet private weak var doneButton: UIButton! + + // MARK: Private + + private var theme: Theme! + private var recoveryKey: String! + + // MARK: Public + + weak var delegate: KeyBackupSetupSuccessFromPassphraseViewControllerDelegate? + + // MARK: - Setup + + class func instantiate(with recoveryKey: String) -> KeyBackupSetupSuccessFromPassphraseViewController { + let viewController = StoryboardScene.KeyBackupSetupSuccessFromPassphraseViewController.initialScene.instantiate() + viewController.theme = ThemeService.shared().theme + viewController.recoveryKey = recoveryKey + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupSetupTitle + + self.setupViews() + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Hide back button + self.navigationItem.setHidesBackButton(true, animated: animated) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + + let keybackupLogoImage = Asset.Images.keyBackupLogo.image.withRenderingMode(.alwaysTemplate) + self.keyBackupLogoImageView.image = keybackupLogoImage + + self.titleLabel.text = VectorL10n.keyBackupSetupSuccessTitle + self.informationLabel.text = VectorL10n.keyBackupSetupSuccessFromPassphraseInfo + + self.saveRecoveryKeyButton.setTitle(VectorL10n.keyBackupSetupSuccessFromPassphraseSaveRecoveryKeyAction, for: .normal) + self.doneButton.setTitle(VectorL10n.keyBackupSetupSuccessFromPassphraseDoneAction, for: .normal) + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.keyBackupLogoImageView.tintColor = theme.textPrimaryColor + self.titleLabel.textColor = theme.textPrimaryColor + self.informationLabel.textColor = theme.textPrimaryColor + + self.saveRecoveryKeyButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.saveRecoveryKeyButton) + + self.doneButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.doneButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func shareRecoveryKey() { + + // Set up activity view controller + let activityItems: [Any] = [ self.recoveryKey ] + let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) + + // Configure source view when activity view controller is presented with a popover + if let popoverPresentationController = activityViewController.popoverPresentationController { + popoverPresentationController.sourceView = self.saveRecoveryKeyButton + popoverPresentationController.sourceRect = self.saveRecoveryKeyButton.bounds + popoverPresentationController.permittedArrowDirections = [.down, .up] + } + + self.present(activityViewController, animated: true) + } + + // MARK: - Actions + + @IBAction private func saveRecoveryKeyButtonAction(_ sender: Any) { + self.shareRecoveryKey() + } + + @IBAction private func doneButtonAction(_ sender: Any) { + self.delegate?.keyBackupSetupSuccessFromPassphraseViewControllerDidTapDoneAction(self) + } +} diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard new file mode 100644 index 000000000..7ba44ec68 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.storyboard @@ -0,0 +1,245 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift new file mode 100644 index 000000000..5aada7321 --- /dev/null +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift @@ -0,0 +1,181 @@ +/* + Copyright 2019 New Vector 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 UIKit + +protocol KeyBackupSetupSuccessFromRecoveryKeyViewControllerDelegate: class { + func keyBackupSetupSuccessFromRecoveryKeyViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromRecoveryKeyViewController) +} + +final class KeyBackupSetupSuccessFromRecoveryKeyViewController: UIViewController { + + // MARK: - Properties + + // MARK: Outlets + + @IBOutlet private weak var keyBackupLogoImageView: UIImageView! + @IBOutlet private weak var titleLabel: UILabel! + @IBOutlet private weak var informationLabel: UILabel! + + @IBOutlet private weak var recoveryKeySectionBackgroundView: UIView! + + @IBOutlet private weak var recoveryKeyTitleLabel: UILabel! + @IBOutlet private weak var recoveryKeyLabel: UILabel! + + @IBOutlet private weak var separatorView: UIView! + + @IBOutlet private weak var makeACopyButton: UIButton! + + @IBOutlet private weak var madeACopyButtonBackgroundView: UIView! + @IBOutlet private weak var madeACopyButton: UIButton! + + // MARK: Private + + private var theme: Theme! + private var recoveryKey: String! + private var hasMadeARecoveryKeyCopy: Bool = false + + // MARK: Public + + weak var delegate: KeyBackupSetupSuccessFromRecoveryKeyViewControllerDelegate? + + // MARK: - Setup + + class func instantiate(with recoveryKey: String) -> KeyBackupSetupSuccessFromRecoveryKeyViewController { + let viewController = StoryboardScene.KeyBackupSetupSuccessFromRecoveryKeyViewController.initialScene.instantiate() + viewController.theme = ThemeService.shared().theme + viewController.recoveryKey = recoveryKey + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + self.title = VectorL10n.keyBackupSetupTitle + + self.setupViews() + self.registerThemeServiceDidChangeThemeNotification() + self.update(theme: self.theme) + } + + override func viewWillAppear(_ animated: Bool) { + super.viewWillAppear(animated) + + // Hide back button + self.navigationItem.setHidesBackButton(true, animated: animated) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return self.theme.statusBarStyle + } + + // MARK: - Private + + private func setupViews() { + + let keybackupLogoImage = Asset.Images.keyBackupLogo.image.withRenderingMode(.alwaysTemplate) + self.keyBackupLogoImageView.image = keybackupLogoImage + + self.titleLabel.text = VectorL10n.keyBackupSetupSuccessTitle + self.informationLabel.text = VectorL10n.keyBackupSetupSuccessFromRecoveryKeyInfo + + self.recoveryKeyTitleLabel.text = VectorL10n.keyBackupSetupSuccessFromRecoveryKeyRecoveryKeyTitle + self.recoveryKeyLabel.text = self.recoveryKey + + self.makeACopyButton.setTitle(VectorL10n.keyBackupSetupSuccessFromRecoveryKeyMakeCopyAction, for: .normal) + self.madeACopyButton.setTitle(VectorL10n.keyBackupSetupSuccessFromRecoveryKeyMadeCopyAction, for: .normal) + + self.updateDoneButton() + } + + private func update(theme: Theme) { + self.theme = theme + + self.view.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = self.navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + + self.keyBackupLogoImageView.tintColor = theme.textPrimaryColor + + self.titleLabel.textColor = theme.textPrimaryColor + self.informationLabel.textColor = theme.textPrimaryColor + + self.recoveryKeySectionBackgroundView.backgroundColor = theme.backgroundColor + + self.recoveryKeyTitleLabel.textColor = theme.textPrimaryColor + self.recoveryKeyLabel.textColor = theme.textPrimaryColor + + self.separatorView.backgroundColor = theme.separatorColor + + theme.applyStyle(onButton: self.makeACopyButton) + + self.madeACopyButtonBackgroundView.backgroundColor = theme.backgroundColor + theme.applyStyle(onButton: self.madeACopyButton) + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + private func shareRecoveryKey() { + + // Set up activity view controller + let activityItems: [Any] = [ self.recoveryKey ] + let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) + + activityViewController.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in + + // Enable made copy button only if user has selected an activity item and has setup recovery key without passphrase + if completed { + self.hasMadeARecoveryKeyCopy = true + self.updateDoneButton() + } + } + + // Configure source view when activity view controller is presented with a popover + if let popoverPresentationController = activityViewController.popoverPresentationController { + popoverPresentationController.sourceView = self.makeACopyButton + popoverPresentationController.sourceRect = self.makeACopyButton.bounds + popoverPresentationController.permittedArrowDirections = [.down, .up] + } + + self.present(activityViewController, animated: true) + } + + private func updateDoneButton() { + self.madeACopyButton.isEnabled = self.hasMadeARecoveryKeyCopy + } + + // MARK: - Actions + + @IBAction private func saveRecoveryKeyButtonAction(_ sender: Any) { + self.shareRecoveryKey() + } + + @IBAction private func doneButtonAction(_ sender: Any) { + self.delegate?.keyBackupSetupSuccessFromRecoveryKeyViewControllerDidTapDoneAction(self) + } +} From 8f1caabe01d825a1b2e278092e79912478c4009c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 13:41:04 +0100 Subject: [PATCH 194/244] Update KeyBackupSetupIntroViewController --- ...yBackupSetupIntroViewController.storyboard | 163 ++++++++++++------ .../KeyBackupSetupIntroViewController.swift | 36 +++- 2 files changed, 141 insertions(+), 58 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard index cde9fb81e..8cf1b867c 100644 --- a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard @@ -1,6 +1,10 @@ + + + + @@ -9,74 +13,126 @@ - + - + - - + + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - - - - - - - - - - - + - - - - - - + + + + + - + - - - - - - - - - + + + + + + + @@ -84,7 +140,10 @@ - + + + + diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift index f4424e0cd..7f2d0616b 100644 --- a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift @@ -27,6 +27,7 @@ final class KeyBackupSetupIntroViewController: UIViewController { // MARK: Outlets + @IBOutlet private weak var keyBackupLogoImageView: UIImageView! @IBOutlet private weak var titleLabel: UILabel! @IBOutlet private weak var informationLabel: UILabel! @@ -36,6 +37,7 @@ final class KeyBackupSetupIntroViewController: UIViewController { // MARK: Private private var theme: Theme! + private var isABackupAlreadyExists: Bool = false // MARK: Public @@ -43,9 +45,10 @@ final class KeyBackupSetupIntroViewController: UIViewController { // MARK: - Setup - class func instantiate() -> KeyBackupSetupIntroViewController { + class func instantiate(isABackupAlreadyExists: Bool) -> KeyBackupSetupIntroViewController { let viewController = StoryboardScene.KeyBackupSetupIntroViewController.initialScene.instantiate() viewController.theme = ThemeService.shared().theme + viewController.isABackupAlreadyExists = isABackupAlreadyExists return viewController } @@ -71,16 +74,20 @@ final class KeyBackupSetupIntroViewController: UIViewController { // MARK: - Private private func setupViews() { - let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.keyBackupSetupSkipAction, style: .plain) { [weak self] in - if let sself = self { - sself.delegate?.keyBackupSetupIntroViewControllerDidCancel(sself) - } + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.showSkipAlert() } self.navigationItem.rightBarButtonItem = cancelBarButtonItem + let keybackupLogoImage = Asset.Images.keyBackupLogo.image.withRenderingMode(.alwaysTemplate) + self.keyBackupLogoImageView.image = keybackupLogoImage + self.titleLabel.text = VectorL10n.keyBackupSetupIntroTitle self.informationLabel.text = VectorL10n.keyBackupSetupIntroInfo - self.setUpButton.setTitle(VectorL10n.keyBackupSetupIntroSetupAction, for: .normal) + + let setupTitle = self.isABackupAlreadyExists ? VectorL10n.keyBackupSetupIntroSetupActionWithExistingBackup : VectorL10n.keyBackupSetupIntroSetupActionWithoutExistingBackup + + self.setUpButton.setTitle(setupTitle, for: .normal) } private func update(theme: Theme) { @@ -92,6 +99,8 @@ final class KeyBackupSetupIntroViewController: UIViewController { theme.applyStyle(onNavigationBar: navigationBar) } + self.keyBackupLogoImageView.tintColor = theme.textPrimaryColor + self.titleLabel.textColor = theme.textPrimaryColor self.informationLabel.textColor = theme.textPrimaryColor @@ -103,6 +112,21 @@ final class KeyBackupSetupIntroViewController: UIViewController { NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) } + private func showSkipAlert() { + let alertController = UIAlertController(title: VectorL10n.keyBackupSetupSkipAlertTitle, + message: VectorL10n.keyBackupSetupSkipAlertMessage, + preferredStyle:.alert) + + alertController.addAction(UIAlertAction(title: VectorL10n.continue, style: .cancel, handler: { action in + })) + + alertController.addAction(UIAlertAction(title: VectorL10n.keyBackupSetupSkipAlertSkipAction , style: .default, handler: { action in + self.delegate?.keyBackupSetupIntroViewControllerDidCancel(self) + })) + + self.present(alertController, animated: true, completion: nil) + } + // MARK: - Actions @objc private func themeDidChange() { From 4f7adadc1d3fad76be50b567a25501ada0f99afe Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 13:46:05 +0100 Subject: [PATCH 195/244] Update key backup setup passphrase scene --- .../KeyBackupSetupPassphraseCoordinator.swift | 13 ++- ...BackupSetupPassphraseCoordinatorType.swift | 3 +- .../KeyBackupSetupPassphraseViewAction.swift | 1 + ...upSetupPassphraseViewController.storyboard | 84 ++++++++++++++----- ...yBackupSetupPassphraseViewController.swift | 22 ++++- .../KeyBackupSetupPassphraseViewModel.swift | 59 ++++++++++--- ...eyBackupSetupPassphraseViewModelType.swift | 3 +- .../Passphrase/PasswordStrengthView.swift | 43 +++++----- 8 files changed, 164 insertions(+), 64 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift index 704c0b614..ea0d2b549 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinator.swift @@ -57,11 +57,16 @@ final class KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordin // MARK: - KeyBackupSetupPassphraseViewModelCoordinatorDelegate extension KeyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseViewModelCoordinatorDelegate { + + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) { + self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCreateBackupFromPassphraseWithResultingRecoveryKey: recoveryKey) + } + + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromRecoveryKey recoveryKey: String) { + self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCreateBackupFromRecoveryKey: recoveryKey) + } + func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) { self.delegate?.keyBackupSetupPassphraseCoordinatorDidCancel(self) } - - func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { - self.delegate?.keyBackupSetupPassphraseCoordinator(self, didCompleteWithMegolmBackupCreationInfo: megolmBackupCreationInfo) - } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift index 889be08f5..f94722adb 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift @@ -17,7 +17,8 @@ import Foundation protocol KeyBackupSetupPassphraseCoordinatorDelegate: class { - func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseCoordinatorDidCancel(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType) } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift index 9f74ae331..b6919a730 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewAction.swift @@ -19,6 +19,7 @@ import Foundation /// KeyBackupSetupPassphraseViewController view actions exposed to view model enum KeyBackupSetupPassphraseViewAction { case setupPassphrase + case setupRecoveryKey case skip case skipAlertSkip case skipAlertContinue diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard index a72291f90..2e7a05579 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.storyboard @@ -22,22 +22,28 @@ - + - + + - + @@ -46,13 +52,13 @@ You’ll need it if you log out, or lose access to this device. - + @@ -103,7 +109,7 @@ You’ll need it if you log out, or lose access to this device. @@ -140,13 +146,13 @@ You’ll need it if you log out, or lose access to this device. - + @@ -176,7 +182,7 @@ You’ll need it if you log out, or lose access to this device. @@ -208,15 +214,15 @@ You’ll need it if you log out, or lose access to this device. - + - - + - + + + + + + - - + + + + + + + @@ -296,6 +333,9 @@ You’ll need it if you log out, or lose access to this device. + + + diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift index ac074b90a..c9d51ff90 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewController.swift @@ -29,6 +29,8 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { // MARK: Outlets @IBOutlet private weak var scrollView: UIScrollView! + + @IBOutlet private weak var titleLabel: UILabel! @IBOutlet private weak var informationLabel: UILabel! @IBOutlet private weak var formBackgroundView: UIView! @@ -51,6 +53,9 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { @IBOutlet private weak var setPassphraseButtonBackgroundView: UIView! @IBOutlet private weak var setPassphraseButton: UIButton! + @IBOutlet private weak var setUpRecoveryKeyInfoLabel: UILabel! + @IBOutlet private weak var setUpRecoveryKeyButton: UIButton! + // MARK: Private private var isFirstViewAppearing: Bool = true @@ -138,6 +143,7 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { theme.applyStyle(onNavigationBar: navigationBar) } + self.titleLabel.textColor = theme.textPrimaryColor self.informationLabel.textColor = theme.textPrimaryColor self.formBackgroundView.backgroundColor = theme.backgroundColor @@ -157,6 +163,9 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { self.setPassphraseButton.backgroundColor = theme.backgroundColor theme.applyStyle(onButton: self.setPassphraseButton) + + self.setUpRecoveryKeyInfoLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onButton: self.setUpRecoveryKeyButton) } private func registerThemeServiceDidChangeThemeNotification() { @@ -168,14 +177,15 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { } private func setupViews() { - let skipBarButtonItem = MXKBarButtonItem(title: VectorL10n.keyBackupSetupSkipAction, style: .plain) { [weak self] in - self?.skipButtonAction() + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.cancel, style: .plain) { [weak self] in + self?.cancelButtonAction() } - self.navigationItem.rightBarButtonItem = skipBarButtonItem + self.navigationItem.rightBarButtonItem = cancelBarButtonItem self.scrollView.keyboardDismissMode = .interactive + self.titleLabel.text = VectorL10n.keyBackupSetupPassphraseTitle self.informationLabel.text = VectorL10n.keyBackupSetupPassphraseInfo self.passphraseTitleLabel.text = VectorL10n.keyBackupSetupPassphrasePassphraseTitle @@ -360,7 +370,11 @@ final class KeyBackupSetupPassphraseViewController: UIViewController { self.viewModel.process(viewAction: .setupPassphrase) } - private func skipButtonAction() { + @IBAction private func setUpRecoveryKeyButtonAction(_ sender: Any) { + self.viewModel.process(viewAction: .setupRecoveryKey) + } + + private func cancelButtonAction() { self.viewModel.process(viewAction: .skip) } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift index 06bc6f0df..ea2fd4752 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModel.swift @@ -26,6 +26,7 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel private let passwordStrengthManager: PasswordStrengthManager private let keyBackup: MXKeyBackup private let coordinatorDelegateQueue: OperationQueue + private var createKeyBackupOperation: MXHTTPOperation? // MARK: Public @@ -63,12 +64,18 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel self.coordinatorDelegateQueue = OperationQueue.vc_createSerialOperationQueue(name: "\(type(of: self)).coordinatorDelegateQueue") } + deinit { + self.createKeyBackupOperation?.cancel() + } + // MARK: - Public func process(viewAction: KeyBackupSetupPassphraseViewAction) { switch viewAction { case .setupPassphrase: self.setupPassphrase() + case .setupRecoveryKey: + self.setupRecoveryKey() case .skip: self.coordinatorDelegateQueue.vc_pause() self.viewDelegate?.keyBackupSetupPassphraseViewModelShowSkipAlert(self) @@ -82,30 +89,58 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel // MARK: - Private - func setupPassphrase() { + private func setupPassphrase() { guard let passphrase = self.passphrase else { return } - self.viewDelegate?.keyBackupSetupPassphraseViewModel(self, didUpdateViewState: .loading) + self.update(viewState: .loading) self.keyBackup.prepareKeyBackupVersion(withPassword: passphrase, success: { [weak self] (megolmBackupCreationInfo) in guard let sself = self else { return } - sself.viewDelegate?.keyBackupSetupPassphraseViewModel(sself, didUpdateViewState: .loaded) - - sself.coordinatorDelegateQueue.addOperation { - DispatchQueue.main.async { - sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCompleteWithMegolmBackupCreationInfo: megolmBackupCreationInfo) + sself.createKeyBackupOperation = sself.keyBackup.createKeyBackupVersion(megolmBackupCreationInfo, success: { (_) in + + sself.update(viewState: .loaded) + + sself.coordinatorDelegateQueue.addOperation { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCreateBackupFromPassphraseWithResultingRecoveryKey: megolmBackupCreationInfo.recoveryKey) + } } - } + + }, failure: { (error) in + self?.update(viewState: .error(error)) + }) }, failure: { [weak self] error in + self?.update(viewState: .error(error)) + }) + } + + private func setupRecoveryKey() { + self.update(viewState: .loading) + + self.keyBackup.prepareKeyBackupVersion(withPassword: nil, success: { [weak self] (megolmBackupCreationInfo) in guard let sself = self else { return - } - sself.viewDelegate?.keyBackupSetupPassphraseViewModel(sself, didUpdateViewState: .error(error)) + } + + sself.createKeyBackupOperation = sself.keyBackup.createKeyBackupVersion(megolmBackupCreationInfo, success: { (_) in + + sself.update(viewState: .loaded) + + sself.coordinatorDelegateQueue.addOperation { + DispatchQueue.main.async { + sself.coordinatorDelegate?.keyBackupSetupPassphraseViewModel(sself, didCreateBackupFromRecoveryKey: megolmBackupCreationInfo.recoveryKey) + } + } + }, failure: { (error) in + self?.update(viewState: .error(error)) + }) + }, failure: { [weak self] error in + self?.update(viewState: .error(error)) }) } @@ -119,4 +154,8 @@ final class KeyBackupSetupPassphraseViewModel: KeyBackupSetupPassphraseViewModel } return self.passwordStrengthManager.passwordStrength(for: password) } + + private func update(viewState: KeyBackupSetupPassphraseViewState) { + self.viewDelegate?.keyBackupSetupPassphraseViewModel(self, didUpdateViewState: viewState) + } } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift index 40d94da38..2f4b2dfaa 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift @@ -22,7 +22,8 @@ protocol KeyBackupSetupPassphraseViewModelViewDelegate: class { } protocol KeyBackupSetupPassphraseViewModelCoordinatorDelegate: class { - func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) + func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift index aa498124f..e7931e50e 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/PasswordStrengthView.swift @@ -19,6 +19,16 @@ import Reusable final class PasswordStrengthView: UIView, NibOwnerLoadable { + // MARK: - Constants + + private enum StrengthColors { + static let gray = UIColor(rgb: 0x9E9E9E) + static let red = UIColor(rgb: 0xF56679) + static let orange = UIColor(rgb: 0xFFC666) + static let yellow = UIColor(rgb: 0xF8E71C) + static let green = UIColor(rgb: 0x7AC9A1) + } + // MARK: - Properties // MARK: Outlets @@ -32,15 +42,6 @@ final class PasswordStrengthView: UIView, NibOwnerLoadable { private var strengthViews: [UIView] = [] - private let strengthViewDefaultColor = UIColor(rgb: 0x9E9E9E) - - private var strengthViewColors: [Int: UIColor] = [ - 0: UIColor(rgb: 0xF56679), - 1: UIColor(rgb: 0xFFC666), - 2: UIColor(rgb: 0xF8E71C), - 3: UIColor(rgb: 0x7AC9A1) - ] - // MARK: Public var strength: PasswordStrength = .tooGuessable { @@ -88,44 +89,42 @@ final class PasswordStrengthView: UIView, NibOwnerLoadable { private func updateStrengthColors() { let strengthViewIndex: Int + let color: UIColor switch self.strength { case .tooGuessable, .veryGuessable: strengthViewIndex = 0 + color = StrengthColors.red case .somewhatGuessable: strengthViewIndex = 1 + color = StrengthColors.orange case .safelyUnguessable: strengthViewIndex = 2 + color = StrengthColors.yellow case .veryUnguessable: strengthViewIndex = 3 + color = StrengthColors.green } - self.color(until: strengthViewIndex) + self.color(until: strengthViewIndex, with: color) } - private func color(until strengthViewIndex: Int) { + private func color(until strengthViewIndex: Int, with color: UIColor) { var index: Int = 0 for strenghView in self.strengthViews { - let color: UIColor + let strenghViewBackgroundColor: UIColor if index <= strengthViewIndex { - color = self.color(for: index) + strenghViewBackgroundColor = color } else { - color = self.strengthViewDefaultColor + strenghViewBackgroundColor = StrengthColors.gray } - strenghView.backgroundColor = color + strenghView.backgroundColor = strenghViewBackgroundColor index+=1 } } - - private func color(for index: Int) -> UIColor { - guard let color = self.strengthViewColors[index] else { - return self.strengthViewDefaultColor - } - return color - } } From cbb9dff74bf1d4620d9414c8c12bcdfb1ce9132f Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 14:08:49 +0100 Subject: [PATCH 196/244] Update KeyBackupSetupCoordinator, handle new success controllers --- .../Setup/KeyBackupSetupCoordinator.swift | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift index 4a36f4e3d..8c07dd39c 100644 --- a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift @@ -44,8 +44,9 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { func start() { // Set key backup setup intro as root controller + let isABackupAlreadyExists = !(self.session.crypto.backup?.state == MXKeyBackupStateDisabled) - let keyBackupSetupIntroViewController = KeyBackupSetupIntroViewController.instantiate() + let keyBackupSetupIntroViewController = KeyBackupSetupIntroViewController.instantiate(isABackupAlreadyExists: isABackupAlreadyExists) keyBackupSetupIntroViewController.delegate = self self.navigationRouter.setRootModule(keyBackupSetupIntroViewController) } @@ -67,16 +68,18 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { } } - private func showRecoveryKey(with megolmBackupCreationInfo: MXMegolmBackupCreationInfo, animated: Bool) { + private func showSetupRecoveryKeySuccess(with recoveryKey: String, animated: Bool) { + + let viewController = KeyBackupSetupSuccessFromRecoveryKeyViewController.instantiate(with: recoveryKey) + viewController.delegate = self + self.navigationRouter.push(viewController, animated: animated, popCompletion: nil) + } + + private func showSetupPassphraseSuccess(with recoveryKey: String, animated: Bool) { - let keyBackupSetupRecoveryKeyCoordinator = KeyBackupSetupRecoveryKeyCoordinator(session: self.session, megolmBackupCreationInfo: megolmBackupCreationInfo) - keyBackupSetupRecoveryKeyCoordinator.delegate = self - keyBackupSetupRecoveryKeyCoordinator.start() - - self.add(childCoordinator: keyBackupSetupRecoveryKeyCoordinator) - self.navigationRouter.push(keyBackupSetupRecoveryKeyCoordinator, animated: animated) { [weak self] in - self?.remove(childCoordinator: keyBackupSetupRecoveryKeyCoordinator) - } + let viewController = KeyBackupSetupSuccessFromPassphraseViewController.instantiate(with: recoveryKey) + viewController.delegate = self + self.navigationRouter.push(viewController, animated: animated, popCompletion: nil) } } @@ -94,8 +97,12 @@ extension KeyBackupSetupCoordinator: KeyBackupSetupIntroViewControllerDelegate { // MARK: - KeyRecoveryPassphraseCoordinatorDelegate extension KeyBackupSetupCoordinator: KeyBackupSetupPassphraseCoordinatorDelegate { - func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCompleteWithMegolmBackupCreationInfo megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { - self.showRecoveryKey(with: megolmBackupCreationInfo, animated: true) + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) { + self.showSetupPassphraseSuccess(with: recoveryKey, animated: true) + } + + func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromRecoveryKey recoveryKey: String) { + self.showSetupRecoveryKeySuccess(with: recoveryKey, animated: true) } func keyBackupSetupPassphraseCoordinatorDidCancel(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType) { @@ -103,13 +110,16 @@ extension KeyBackupSetupCoordinator: KeyBackupSetupPassphraseCoordinatorDelegate } } -// MARK: - KeyBackupSetupRecoveryKeyCoordinatorDelegate -extension KeyBackupSetupCoordinator: KeyBackupSetupRecoveryKeyCoordinatorDelegate { - func keyBackupSetupRecoveryKeyCoordinatorDidCreateBackup(_ keyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType) { +// MARK: - KeyBackupSetupSuccessFromPassphraseViewControllerDelegate +extension KeyBackupSetupCoordinator: KeyBackupSetupSuccessFromPassphraseViewControllerDelegate { + func keyBackupSetupSuccessFromPassphraseViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromPassphraseViewController) { self.delegate?.keyBackupSetupCoordinatorDidSetupRecoveryKey(self) } - - func keyBackupSetupRecoveryKeyCoordinatorDidCancel(_ keyBackupSetupRecoveryKeyCoordinator: KeyBackupSetupRecoveryKeyCoordinatorType) { - self.delegate?.keyBackupSetupCoordinatorDidCancel(self) +} + +// MARK: - KeyBackupSetupSuccessFromRecoveryKeyViewControllerDelegate +extension KeyBackupSetupCoordinator: KeyBackupSetupSuccessFromRecoveryKeyViewControllerDelegate { + func keyBackupSetupSuccessFromRecoveryKeyViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromRecoveryKeyViewController) { + self.delegate?.keyBackupSetupCoordinatorDidSetupRecoveryKey(self) } } From 765859b6b10a5c329a32f138e59465f9fd9c19c0 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 14:09:41 +0100 Subject: [PATCH 197/244] Update key backup logo on key backup recover screens --- ...verFromPassphraseViewController.storyboard | 22 +++++++++---------- ...pRecoverFromPassphraseViewController.swift | 2 +- ...kupRecoverFromRecoveryKeyCoordinator.swift | 1 - ...erFromRecoveryKeyViewController.storyboard | 4 ++-- ...RecoverFromRecoveryKeyViewController.swift | 2 +- ...kupRecoverSuccessViewController.storyboard | 18 +++++++-------- ...eyBackupRecoverSuccessViewController.swift | 2 +- 7 files changed, 25 insertions(+), 26 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.storyboard b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.storyboard index a4cf7f0e5..e3c1c08e6 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.storyboard +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.storyboard @@ -22,26 +22,26 @@ - + - + - - + + - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift deleted file mode 100644 index 930151d2c..000000000 --- a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModel.swift +++ /dev/null @@ -1,90 +0,0 @@ -/* - Copyright 2019 New Vector 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 Foundation - -final class KeyBackupSetupRecoveryKeyViewModel: KeyBackupSetupRecoveryKeyViewModelType { - - // MARK: - Properties - - // MARK: Private - - private let megolmBackupCreationInfo: MXMegolmBackupCreationInfo - private let keyBackup: MXKeyBackup - private let coordinatorDelegateQueue: OperationQueue - private var createKeyBackupOperation: MXHTTPOperation? - - // MARK: Public - - let recoveryKey: String - - weak var viewDelegate: KeyBackupSetupRecoveryKeyViewModelViewDelegate? - weak var coordinatorDelegate: KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate? - - // MARK: - Setup - - init(keyBackup: MXKeyBackup, megolmBackupCreationInfo: MXMegolmBackupCreationInfo) { - self.megolmBackupCreationInfo = megolmBackupCreationInfo - self.recoveryKey = megolmBackupCreationInfo.recoveryKey - self.keyBackup = keyBackup - self.coordinatorDelegateQueue = OperationQueue.vc_createSerialOperationQueue(name: "\(type(of: self)).coordinatorDelegateQueue") - } - - deinit { - self.createKeyBackupOperation?.cancel() - } - - // MARK: - Public - - func process(viewAction: KeyBackupSetupRecoveryKeyViewAction) { - switch viewAction { - case .madeCopy: - self.createBackup() - case .skip: - self.coordinatorDelegateQueue.vc_pause() - self.viewDelegate?.keyBackupSetupPassphraseViewModelShowSkipAlert(self) - case.skipAlertContinue: - self.coordinatorDelegateQueue.vc_resume() - case.skipAlertSkip: - self.coordinatorDelegateQueue.cancelAllOperations() - self.coordinatorDelegate?.keyBackupSetupRecoveryKeyViewModelDidCancel(self) - } - } - - // MARK: - Private - - func createBackup() { - self.viewDelegate?.keyBackupSetupRecoveryKeyViewModel(self, didUpdateViewState: .loading) - - self.keyBackup.createKeyBackupVersion(self.megolmBackupCreationInfo, success: { [weak self] (keyBackupVersion) in - guard let sself = self else { - return - } - sself.viewDelegate?.keyBackupSetupRecoveryKeyViewModel(sself, didUpdateViewState: .loaded) - - sself.coordinatorDelegateQueue.addOperation { - DispatchQueue.main.async { - sself.coordinatorDelegate?.keyBackupSetupRecoveryKeyViewModelDidCreateBackup(sself) - } - } - }, failure: { [weak self] error in - guard let sself = self else { - return - } - sself.viewDelegate?.keyBackupSetupRecoveryKeyViewModel(sself, didUpdateViewState: .error(error)) - }) - } -} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift deleted file mode 100644 index 5b9da8a52..000000000 --- a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewModelType.swift +++ /dev/null @@ -1,38 +0,0 @@ -/* - Copyright 2019 New Vector 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 Foundation - -protocol KeyBackupSetupRecoveryKeyViewModelViewDelegate: class { - func keyBackupSetupRecoveryKeyViewModel(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType, didUpdateViewState viewSate: KeyBackupSetupRecoveryKeyViewState) - func keyBackupSetupPassphraseViewModelShowSkipAlert(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) -} - -protocol KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate: class { - func keyBackupSetupRecoveryKeyViewModelDidCreateBackup(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) - func keyBackupSetupRecoveryKeyViewModelDidCancel(_ viewModel: KeyBackupSetupRecoveryKeyViewModelType) -} - -/// Protocol describing the view model used by `KeyBackupSetupRecoveryKeyViewController` -protocol KeyBackupSetupRecoveryKeyViewModelType { - - var recoveryKey: String { get } - - var viewDelegate: KeyBackupSetupRecoveryKeyViewModelViewDelegate? { get set } - var coordinatorDelegate: KeyBackupSetupRecoveryKeyViewModelCoordinatorDelegate? { get set } - - func process(viewAction: KeyBackupSetupRecoveryKeyViewAction) -} diff --git a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift b/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift deleted file mode 100644 index 71331f3a7..000000000 --- a/Riot/Modules/KeyBackup/Setup/RecoveryKey/KeyBackupSetupRecoveryKeyViewState.swift +++ /dev/null @@ -1,24 +0,0 @@ -/* - Copyright 2019 New Vector 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 Foundation - -/// KeyBackupSetupRecoveryKeyViewController view state -enum KeyBackupSetupRecoveryKeyViewState { - case loading - case loaded - case error(Error) -} From 03175e0d3121a1ba3dfa35caee0a0d3d69f21072 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 15:26:51 +0100 Subject: [PATCH 199/244] Use new lineBreakColor in KeyBackupSetupSuccessFromRecoveryKeyViewController --- .../KeyBackupSetupSuccessFromRecoveryKeyViewController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift index 5aada7321..6f474f753 100644 --- a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift @@ -124,7 +124,7 @@ final class KeyBackupSetupSuccessFromRecoveryKeyViewController: UIViewController self.recoveryKeyTitleLabel.textColor = theme.textPrimaryColor self.recoveryKeyLabel.textColor = theme.textPrimaryColor - self.separatorView.backgroundColor = theme.separatorColor + self.separatorView.backgroundColor = theme.lineBreakColor theme.applyStyle(onButton: self.makeACopyButton) From 3ce00a671f4f9fb9b7f0f9321f31c94212ea1643 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 13 Feb 2019 15:31:43 +0100 Subject: [PATCH 200/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index 17139e6d7..c281197da 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -13,6 +13,7 @@ Improvements: * Key backup: Add a dedicated section to settings (#2193). * Key backup: Implement setup reminder (#2211). * Key backup: Implement recover reminder (#2206). + * Key backup: Update key backup setup UI and UX (PR #2243). Bug fix: * Use white scroll bar on dark themes (#2158). From 3d6b46c71c0665111b67ef66b6b10e20525d6782 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 12:28:56 +0100 Subject: [PATCH 201/244] Key backup: Update SDK api break --- .../KeyBackupRecoverFromPassphraseViewModel.swift | 10 ++-------- .../KeyBackupRecoverFromRecoveryKeyViewModel.swift | 8 +------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift index d20572b4b..4717bcebb 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift @@ -17,7 +17,6 @@ import Foundation enum KeyBackupRecoverFromPassphraseViewModelError: Error { - case missingKeyBackupVersion } final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphraseViewModelType { @@ -72,14 +71,9 @@ final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphr return } - guard let keyBackupVersion = self.keyBackupVersion.version else { - self.update(viewState: .error(KeyBackupRecoverFromPassphraseViewModelError.missingKeyBackupVersion)) - return - } - self.update(viewState: .loading) - self.currentHTTPOperation = self.keyBackup.restore(keyBackupVersion, withPassword: passphrase, room: nil, session: nil, success: { [weak self] (totalKeys, _) in + self.currentHTTPOperation = self.keyBackup.restore(self.keyBackupVersion, withPassword: passphrase, room: nil, session: nil, success: { [weak self] (totalKeys, _) in guard let sself = self else { return } @@ -91,7 +85,7 @@ final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphr guard let sself = self else { return } - sself.update(viewState: .error(error)) + sself.update(viewState: .error(error)) }) } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift index 0fefec573..68452c0c9 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift @@ -17,7 +17,6 @@ import Foundation enum KeyBackupRecoverFromRecoveryKeyViewModelError: Error { - case missingKeyBackupVersion } final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecoveryKeyViewModelType { @@ -72,14 +71,9 @@ final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecove return } - guard let keyBackupVersion = self.keyBackupVersion.version else { - self.update(viewState: .error(KeyBackupRecoverFromRecoveryKeyViewModelError.missingKeyBackupVersion)) - return - } - self.update(viewState: .loading) - self.currentHTTPOperation = self.keyBackup.restore(keyBackupVersion, withRecoveryKey: recoveryKey, room: nil, session: nil, success: { [weak self] (totalKeys, _) in + self.currentHTTPOperation = self.keyBackup.restore(self.keyBackupVersion, withRecoveryKey: recoveryKey, room: nil, session: nil, success: { [weak self] (totalKeys, _) in guard let sself = self else { return } From 217c603fa1739bdfe8e4b0e3e5983db92923baa2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 12:35:16 +0100 Subject: [PATCH 202/244] Key recovery: Do not show anymore an error for empty backup --- Riot/Assets/en.lproj/Vector.strings | 2 -- Riot/Generated/Strings.swift | 8 -------- ...BackupRecoverFromPassphraseViewController.swift | 14 +++----------- .../KeyBackupRecoverFromPassphraseViewModel.swift | 6 ++---- .../KeyBackupRecoverFromPassphraseViewState.swift | 2 +- ...ackupRecoverFromRecoveryKeyViewController.swift | 14 +++----------- .../KeyBackupRecoverFromRecoveryKeyViewModel.swift | 7 +++---- .../KeyBackupRecoverFromRecoveryKeyViewState.swift | 2 +- 8 files changed, 13 insertions(+), 42 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index e60d5dc40..80cc33a07 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -718,8 +718,6 @@ // MARK: Key backup recover "key_backup_recover_title" = "Secure Messages"; -"key_backup_recover_empty_backup_title" = "Empty backup"; -"key_backup_recover_empty_backup_message" = "There is no key to restore"; // Recover from passphrase diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 23743efc8..fc11075f1 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -674,14 +674,6 @@ internal enum VectorL10n { internal static var keyBackupRecoverDoneAction: String { return VectorL10n.tr("Vector", "key_backup_recover_done_action") } - /// There is no key to restore - internal static var keyBackupRecoverEmptyBackupMessage: String { - return VectorL10n.tr("Vector", "key_backup_recover_empty_backup_message") - } - /// Empty backup - internal static var keyBackupRecoverEmptyBackupTitle: String { - return VectorL10n.tr("Vector", "key_backup_recover_empty_backup_title") - } /// Use your recovery passphrase to unlock your secure message history internal static var keyBackupRecoverFromPassphraseInfo: String { return VectorL10n.tr("Vector", "key_backup_recover_from_passphrase_info") diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift index 40fd523dc..2d0464031 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift @@ -163,8 +163,8 @@ final class KeyBackupRecoverFromPassphraseViewController: UIViewController { switch viewState { case .loading: self.renderLoading() - case .loaded(totalKeys: let totalKeys): - self.renderLoaded(with: totalKeys) + case .loaded: + self.renderLoaded() case .error(let error): self.render(error: error) } @@ -175,16 +175,8 @@ final class KeyBackupRecoverFromPassphraseViewController: UIViewController { self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) } - private func renderLoaded(with totalKeys: UInt) { + private func renderLoaded() { self.activityPresenter.removeCurrentActivityIndicator(animated: true) - - if totalKeys == 0 { - self.errorPresenter.presentError(from: self, - title: VectorL10n.keyBackupRecoverEmptyBackupTitle, - message: VectorL10n.keyBackupRecoverEmptyBackupMessage, - animated: true, - handler: nil) - } } private func render(error: Error) { diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift index 4717bcebb..d048b2c1c 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift @@ -77,10 +77,8 @@ final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphr guard let sself = self else { return } - sself.update(viewState: .loaded(totalKeys: totalKeys)) - if totalKeys > 0 { - sself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(sself) - } + sself.update(viewState: .loaded) + sself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(sself) }, failure: { [weak self] error in guard let sself = self else { return diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift index 34789954f..c470c0320 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewState.swift @@ -19,6 +19,6 @@ import Foundation /// KeyBackupRecoverFromPassphraseViewController view state enum KeyBackupRecoverFromPassphraseViewState { case loading - case loaded(totalKeys: UInt) + case loaded case error(Error) } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift index 9b6670945..1da22c4a9 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift @@ -161,8 +161,8 @@ final class KeyBackupRecoverFromRecoveryKeyViewController: UIViewController { switch viewState { case .loading: self.renderLoading() - case .loaded(totalKeys: let totalKeys): - self.renderLoaded(with: totalKeys) + case .loaded: + self.renderLoaded() case .error(let error): self.render(error: error) } @@ -173,16 +173,8 @@ final class KeyBackupRecoverFromRecoveryKeyViewController: UIViewController { self.activityPresenter.presentActivityIndicator(on: self.view, animated: true) } - private func renderLoaded(with totalKeys: UInt) { + private func renderLoaded() { self.activityPresenter.removeCurrentActivityIndicator(animated: true) - - if totalKeys == 0 { - self.errorPresenter.presentError(from: self, - title: VectorL10n.keyBackupRecoverEmptyBackupTitle, - message: VectorL10n.keyBackupRecoverEmptyBackupMessage, - animated: true, - handler: nil) - } } private func render(error: Error) { diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift index 68452c0c9..ca5cb0f52 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift @@ -77,10 +77,9 @@ final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecove guard let sself = self else { return } - sself.update(viewState: .loaded(totalKeys: totalKeys)) - if totalKeys > 0 { - sself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(sself) - } + sself.update(viewState: .loaded) + sself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(sself) + }, failure: { [weak self] error in guard let sself = self else { return diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift index 57042fe11..e772a887f 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewState.swift @@ -19,6 +19,6 @@ import Foundation /// KeyBackupRecoverFromRecoveryKeyViewController view state enum KeyBackupRecoverFromRecoveryKeyViewState { case loading - case loaded(totalKeys: UInt) + case loaded case error(Error) } From 1ab6506a39c982a33bbca9d33ce3a7643cd4b551 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 12:48:54 +0100 Subject: [PATCH 203/244] Key recovery: Trust on decrypt #2223 --- ...BackupRecoverFromPassphraseViewModel.swift | 21 ++++++++++++++++--- ...ackupRecoverFromRecoveryKeyViewModel.swift | 20 +++++++++++++++--- 2 files changed, 35 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift index d048b2c1c..92b76e96e 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift @@ -73,12 +73,27 @@ final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphr self.update(viewState: .loading) - self.currentHTTPOperation = self.keyBackup.restore(self.keyBackupVersion, withPassword: passphrase, room: nil, session: nil, success: { [weak self] (totalKeys, _) in + self.currentHTTPOperation = self.keyBackup.restore(self.keyBackupVersion, withPassword: passphrase, room: nil, session: nil, success: { [weak self] (_, _) in guard let sself = self else { return } - sself.update(viewState: .loaded) - sself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(sself) + + // Trust on decrypt + sself.currentHTTPOperation = sself.keyBackup.trust(sself.keyBackupVersion, trust: true, success: { [weak sself] () in + guard let ssself = sself else { + return + } + + ssself.update(viewState: .loaded) + ssself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(ssself) + + }, failure: { [weak sself] error in + guard let ssself = sself else { + return + } + ssself.update(viewState: .error(error)) + }) + }, failure: { [weak self] error in guard let sself = self else { return diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift index ca5cb0f52..0bdd512e4 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift @@ -73,12 +73,26 @@ final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecove self.update(viewState: .loading) - self.currentHTTPOperation = self.keyBackup.restore(self.keyBackupVersion, withRecoveryKey: recoveryKey, room: nil, session: nil, success: { [weak self] (totalKeys, _) in + self.currentHTTPOperation = self.keyBackup.restore(self.keyBackupVersion, withRecoveryKey: recoveryKey, room: nil, session: nil, success: { [weak self] (_, _) in guard let sself = self else { return } - sself.update(viewState: .loaded) - sself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(sself) + + // Trust on decrypt + sself.currentHTTPOperation = sself.keyBackup.trust(sself.keyBackupVersion, trust: true, success: { [weak sself] () in + guard let ssself = sself else { + return + } + + ssself.update(viewState: .loaded) + ssself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(ssself) + + }, failure: { [weak sself] error in + guard let ssself = sself else { + return + } + ssself.update(viewState: .error(error)) + }) }, failure: { [weak self] error in guard let sself = self else { From d5f6cd932d899ca028eda1c6caca5d5f56154803 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 13:14:00 +0100 Subject: [PATCH 204/244] Key recovery: Show errors on invalid passphrase or recovery key --- Riot/Assets/en.lproj/Vector.strings | 5 +++++ Riot/Generated/Strings.swift | 16 ++++++++++++++++ ...ckupRecoverFromPassphraseViewController.swift | 14 +++++++++++++- ...kupRecoverFromRecoveryKeyViewController.swift | 14 +++++++++++++- 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 80cc33a07..7d011f333 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -719,6 +719,11 @@ "key_backup_recover_title" = "Secure Messages"; +"key_backup_recover_invalid_passphrase_title" = "Incorrect Recovery Passphrase"; +"key_backup_recover_invalid_passphrase" = "Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase."; +"key_backup_recover_invalid_recovery_key_title" = "Recovery Key Mismatch"; +"key_backup_recover_invalid_recovery_key" = "Backup could not be decrypted with this key: please verify that you entered the correct recovery key."; + // Recover from passphrase "key_backup_recover_from_passphrase_info" = "Use your recovery passphrase to unlock your secure message history"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index fc11075f1..22a9c2ac3 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -722,6 +722,22 @@ internal enum VectorL10n { internal static var keyBackupRecoverFromRecoveryKeyRecoveryKeyTitle: String { return VectorL10n.tr("Vector", "key_backup_recover_from_recovery_key_recovery_key_title") } + /// Backup could not be decrypted with this passphrase: please verify that you entered the correct recovery passphrase. + internal static var keyBackupRecoverInvalidPassphrase: String { + return VectorL10n.tr("Vector", "key_backup_recover_invalid_passphrase") + } + /// Incorrect Recovery Passphrase + internal static var keyBackupRecoverInvalidPassphraseTitle: String { + return VectorL10n.tr("Vector", "key_backup_recover_invalid_passphrase_title") + } + /// Backup could not be decrypted with this key: please verify that you entered the correct recovery key. + internal static var keyBackupRecoverInvalidRecoveryKey: String { + return VectorL10n.tr("Vector", "key_backup_recover_invalid_recovery_key") + } + /// Recovery Key Mismatch + internal static var keyBackupRecoverInvalidRecoveryKeyTitle: String { + return VectorL10n.tr("Vector", "key_backup_recover_invalid_recovery_key_title") + } /// Backup Restored! internal static var keyBackupRecoverSuccessInfo: String { return VectorL10n.tr("Vector", "key_backup_recover_success_info") diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift index 2d0464031..8230cd89c 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift @@ -181,7 +181,19 @@ final class KeyBackupRecoverFromPassphraseViewController: UIViewController { private func render(error: Error) { self.activityPresenter.removeCurrentActivityIndicator(animated: true) - self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + + if (error as NSError).domain == MXKeyBackupErrorDomain + && (error as NSError).code == Int(MXKeyBackupErrorInvalidRecoveryKeyCode.rawValue) { + + self.errorPresenter.presentError(from: self, + title: VectorL10n.keyBackupRecoverInvalidPassphraseTitle, + message: VectorL10n.keyBackupRecoverInvalidPassphrase, + animated: true, + handler: nil) + } + else { + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } } // MARK: - Actions diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift index 1da22c4a9..d29f3a027 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift @@ -179,7 +179,19 @@ final class KeyBackupRecoverFromRecoveryKeyViewController: UIViewController { private func render(error: Error) { self.activityPresenter.removeCurrentActivityIndicator(animated: true) - self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + + if (error as NSError).domain == MXKeyBackupErrorDomain + && (error as NSError).code == Int(MXKeyBackupErrorInvalidRecoveryKeyCode.rawValue) { + + self.errorPresenter.presentError(from: self, + title: VectorL10n.keyBackupRecoverInvalidRecoveryKeyTitle, + message: VectorL10n.keyBackupRecoverInvalidRecoveryKey, + animated: true, + handler: nil) + } + else { + self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) + } } private func showFileSelection() { From 8d01a11a5bc68ae5f0740214787b77a3424f3e5d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 16:01:33 +0100 Subject: [PATCH 205/244] Add sign out warning strings --- Riot/Assets/en.lproj/Vector.strings | 20 ++++++++++++++-- Riot/Generated/Strings.swift | 36 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index e60d5dc40..d70ea117a 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -746,12 +746,28 @@ "key_backup_recover_success_info" = "Backup Restored!"; "key_backup_recover_done_action" = "Done"; -// MARK: Key backup setup banner +// MARK: Key backup banners + +// Setup "key_backup_setup_banner_title" = "Never lose encrypted messages"; "key_backup_setup_banner_subtitle" = "Start using Key Backup"; -// MARK: Key backup recover banner +// Recover "key_backup_recover_banner_title" = "Never lose encrypted messages"; "key_backup_recover_banner_subtitle" = "Use Key Backup"; + +// MARK: Sign out + +"sign_out_existing_key_backup_alert_title" = "Are you sure you want to sign out?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Sign out"; + +"sign_out_non_existing_key_backup_alert_title" = "You’ll lose access to your secure messages if you sign out now"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Start using Key Backup"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "I don't want my encrypted messages"; + +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "You'll lose your encrypted messages"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "You'll lose access to your encrypted messages unless you back up your keys before signing out."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Sign out"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Backup"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 23743efc8..2b8c0e54b 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2250,6 +2250,42 @@ internal enum VectorL10n { internal static var shareExtensionFailedToEncrypt: String { return VectorL10n.tr("Vector", "share_extension_failed_to_encrypt") } + /// Sign out + internal static var signOutExistingKeyBackupAlertSignOutAction: String { + return VectorL10n.tr("Vector", "sign_out_existing_key_backup_alert_sign_out_action") + } + /// Are you sure you want to sign out? + internal static var signOutExistingKeyBackupAlertTitle: String { + return VectorL10n.tr("Vector", "sign_out_existing_key_backup_alert_title") + } + /// I don't want my encrypted messages + internal static var signOutNonExistingKeyBackupAlertDiscardKeyBackupAction: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_alert_discard_key_backup_action") + } + /// Start using Key Backup + internal static var signOutNonExistingKeyBackupAlertSetupKeyBackupAction: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_alert_setup_key_backup_action") + } + /// You’ll lose access to your secure messages if you sign out now + internal static var signOutNonExistingKeyBackupAlertTitle: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_alert_title") + } + /// Backup + internal static var signOutNonExistingKeyBackupSignOutConfirmationAlertBackupAction: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action") + } + /// You'll lose access to your encrypted messages unless you back up your keys before signing out. + internal static var signOutNonExistingKeyBackupSignOutConfirmationAlertMessage: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_sign_out_confirmation_alert_message") + } + /// Sign out + internal static var signOutNonExistingKeyBackupSignOutConfirmationAlertSignOutAction: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action") + } + /// You'll lose your encrypted messages + internal static var signOutNonExistingKeyBackupSignOutConfirmationAlertTitle: String { + return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_sign_out_confirmation_alert_title") + } /// Start internal static var start: String { return VectorL10n.tr("Vector", "start") From 59cf9837e6650e276a4cc2c7979d31639d07bfe8 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 16:03:07 +0100 Subject: [PATCH 206/244] Create a sign out alert presenter --- Riot.xcodeproj/project.pbxproj | 12 ++ .../SignOut/SignOutAlertPresenter.swift | 109 ++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index c5ab6dc52..7c1a36f6f 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -372,6 +372,7 @@ B1B9194C2118984300FE25B5 /* RoomPredecessorBubbleCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = B1B9194A2118984300FE25B5 /* RoomPredecessorBubbleCell.xib */; }; B1CA3A2721EF6914000D1D89 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2621EF6913000D1D89 /* UIViewController.swift */; }; B1CA3A2921EF692B000D1D89 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2821EF692B000D1D89 /* UIView.swift */; }; + B1CE9EFD22148703000FAE6A /* SignOutAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CE9EFC22148703000FAE6A /* SignOutAlertPresenter.swift */; }; B1D250D82118AA0A000F4E93 /* RoomPredecessorBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D250D72118AA0A000F4E93 /* RoomPredecessorBubbleCell.m */; }; B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752521EE4E620067973F /* KeyboardAvoider.swift */; }; B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752621EE4E620067973F /* KeyboardNotification.swift */; }; @@ -1024,6 +1025,7 @@ B1B9194A2118984300FE25B5 /* RoomPredecessorBubbleCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RoomPredecessorBubbleCell.xib; sourceTree = ""; }; B1CA3A2621EF6913000D1D89 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; B1CA3A2821EF692B000D1D89 /* UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; + B1CE9EFC22148703000FAE6A /* SignOutAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignOutAlertPresenter.swift; sourceTree = ""; }; B1D250D62118AA0A000F4E93 /* RoomPredecessorBubbleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoomPredecessorBubbleCell.h; sourceTree = ""; }; B1D250D72118AA0A000F4E93 /* RoomPredecessorBubbleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoomPredecessorBubbleCell.m; sourceTree = ""; }; B1D4752521EE4E620067973F /* KeyboardAvoider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardAvoider.swift; sourceTree = ""; }; @@ -1647,6 +1649,7 @@ B1B5567B20EE6C4C00210D55 /* Language */, B1B5567820EE6C4C00210D55 /* PhoneCountry */, B1B5568020EE6C4C00210D55 /* DeactivateAccount */, + B1CE9EFB22148681000FAE6A /* SignOut */, ); path = Settings; sourceTree = ""; @@ -2696,6 +2699,14 @@ path = Analytics; sourceTree = ""; }; + B1CE9EFB22148681000FAE6A /* SignOut */ = { + isa = PBXGroup; + children = ( + B1CE9EFC22148703000FAE6A /* SignOutAlertPresenter.swift */, + ); + path = SignOut; + sourceTree = ""; + }; B1D4752421EE4E620067973F /* KeyboardAvoiding */ = { isa = PBXGroup; children = ( @@ -3461,6 +3472,7 @@ B14F142F22144F6500FA0595 /* KeyBackupRecoverFromRecoveryKeyViewModelType.swift in Sources */, B1B558E120EF768F00210D55 /* RoomMembershipCollapsedBubbleCell.m in Sources */, B1B5571A20EE6C4D00210D55 /* SettingsViewController.m in Sources */, + B1CE9EFD22148703000FAE6A /* SignOutAlertPresenter.swift in Sources */, B1B5594720EF7BD000210D55 /* RoomCollectionViewCell.m in Sources */, B1B558C120EF768F00210D55 /* RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m in Sources */, B1B5573E20EE6C4D00210D55 /* RiotNavigationController.m in Sources */, diff --git a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift new file mode 100644 index 000000000..2caa517b4 --- /dev/null +++ b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift @@ -0,0 +1,109 @@ +/* + Copyright 2019 New Vector 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 UIKit + +@objc protocol SignOutAlertPresenterDelegate: class { + func signOutAlertPresenterDidTapSignOutAction(_ presenter: SignOutAlertPresenter) + func signOutAlertPresenterDidTapBackupAction(_ presenter: SignOutAlertPresenter) +} + +@objcMembers +final class SignOutAlertPresenter: NSObject { + + // MARK: - Properties + + // MARK: Private + + private weak var presentingViewController: UIViewController? + + // MARK: Public + + var isABackupExist: Bool = false + weak var delegate: SignOutAlertPresenterDelegate? + + // MARK: - Public + + func present(from viewController: UIViewController, animated: Bool) { + self.presentingViewController = viewController + + if self.isABackupExist { + self.presentExistingBackupAlert(animated: animated) + } else { + self.presentNonExistingBackupAlert(animated: animated) + } + } + + // MARK: - Private + + private func presentExistingBackupAlert(animated: Bool) { + let alertContoller = UIAlertController(title: VectorL10n.signOutExistingKeyBackupAlertTitle, + message: nil, + preferredStyle: .actionSheet) + + let signoutAction = UIAlertAction(title: VectorL10n.signOutExistingKeyBackupAlertSignOutAction, style: .destructive) { (_) in + self.delegate?.signOutAlertPresenterDidTapSignOutAction(self) + } + + let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: nil) + + alertContoller.addAction(signoutAction) + alertContoller.addAction(cancelAction) + + self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + } + + private func presentNonExistingBackupAlert(animated: Bool) { + let alertContoller = UIAlertController(title: VectorL10n.signOutNonExistingKeyBackupAlertTitle, + message: nil, + preferredStyle: .actionSheet) + + let doNotWantKeyBackupAction = UIAlertAction(title: VectorL10n.signOutNonExistingKeyBackupAlertDiscardKeyBackupAction, style: .destructive) { (_) in + self.presentNonExistingBackupSignOutConfirmationAlert(animated: true) + } + + let setUpKeyBackupAction = UIAlertAction(title: VectorL10n.signOutNonExistingKeyBackupAlertSetupKeyBackupAction, style: .default) { (_) in + self.delegate?.signOutAlertPresenterDidTapBackupAction(self) + } + + let cancelAction = UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: nil) + + alertContoller.addAction(doNotWantKeyBackupAction) + alertContoller.addAction(setUpKeyBackupAction) + alertContoller.addAction(cancelAction) + + self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + } + + private func presentNonExistingBackupSignOutConfirmationAlert(animated: Bool) { + let alertContoller = UIAlertController(title: VectorL10n.signOutNonExistingKeyBackupSignOutConfirmationAlertTitle, + message: VectorL10n.signOutNonExistingKeyBackupSignOutConfirmationAlertMessage, + preferredStyle: .alert) + + let signOutAction = UIAlertAction(title: VectorL10n.signOutNonExistingKeyBackupSignOutConfirmationAlertSignOutAction, style: .destructive) { (_) in + self.delegate?.signOutAlertPresenterDidTapSignOutAction(self) + } + + let setUpKeyBackupAction = UIAlertAction(title: VectorL10n.signOutNonExistingKeyBackupSignOutConfirmationAlertBackupAction, style: .default) { (_) in + self.delegate?.signOutAlertPresenterDidTapBackupAction(self) + } + + alertContoller.addAction(signOutAction) + alertContoller.addAction(setUpKeyBackupAction) + + self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + } +} From 55c6608e1df1be96f0b1d1bb24f0c9a7fcd82a90 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 16:04:08 +0100 Subject: [PATCH 207/244] Handle sign out alert present present in SettingsViewController --- .../Modules/Settings/SettingsViewController.m | 59 ++++++++++++------- 1 file changed, 39 insertions(+), 20 deletions(-) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 13c295a0e..3c7e23ef7 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -142,7 +142,8 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); SettingsKeyBackupTableViewSectionDelegate, MXKEncryptionInfoViewDelegate, KeyBackupSetupCoordinatorBridgePresenterDelegate, -KeyBackupRecoverCoordinatorBridgePresenterDelegate> +KeyBackupRecoverCoordinatorBridgePresenterDelegate, +SignOutAlertPresenterDelegate> { // Current alert (if any). UIAlertController *currentAlert; @@ -250,7 +251,9 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> */ @property (nonatomic) BOOL newPhoneEditingEnabled; -@property (weak, nonatomic) DeactivateAccountViewController *deactivateAccountViewController; +@property (nonatomic, weak) DeactivateAccountViewController *deactivateAccountViewController; +@property (nonatomic, strong) SignOutAlertPresenter *signOutPresenter; +@property (nonatomic, weak) UIButton *signOutButton; @end @@ -353,6 +356,9 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> }]; [self userInterfaceThemeDidChange]; + + self.signOutPresenter = [SignOutAlertPresenter new]; + self.signOutPresenter.delegate = self; } - (void)userInterfaceThemeDidChange @@ -2702,24 +2708,9 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> - (void)onSignout:(id)sender { - // Feedback: disable button and run activity indicator - UIButton *button = (UIButton*)sender; - button.enabled = NO; - [self startActivityIndicator]; - - __weak typeof(self) weakSelf = self; - - [[AppDelegate theDelegate] logoutWithConfirmation:YES completion:^(BOOL isLoggedOut) { - - if (!isLoggedOut && weakSelf) - { - typeof(self) self = weakSelf; - - // Enable the button and stop activity indicator - button.enabled = YES; - [self stopActivityIndicator]; - } - }]; + self.signOutButton = (UIButton*)sender; + self.signOutPresenter.isABackupExist = !(self.mainSession.crypto.backup.state == MXKeyBackupStateDisabled); + [self.signOutPresenter presentFrom:self animated:YES]; } - (void)onRemove3PID:(NSIndexPath*)path @@ -4455,4 +4446,32 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> keyBackupRecoverCoordinatorBridgePresenter = nil; } +#pragma mark - SignOutAlertPresenterDelegate + +- (void)signOutAlertPresenterDidTapBackupAction:(SignOutAlertPresenter * _Nonnull)presenter +{ + [self showKeyBackupSetup]; +} + +- (void)signOutAlertPresenterDidTapSignOutAction:(SignOutAlertPresenter * _Nonnull)presenter +{ + // Prevent user to perform user interaction in settings when sign out + // TODO: Prevent user interaction in all application (navigation controller and split view controller included) + self.view.userInteractionEnabled = NO; + self.signOutButton.enabled = NO; + + [self startActivityIndicator]; + + MXWeakify(self); + + [[AppDelegate theDelegate] logoutWithConfirmation:NO completion:^(BOOL isLoggedOut) { + MXStrongifyAndReturnIfNil(self); + + [self stopActivityIndicator]; + + self.view.userInteractionEnabled = YES; + self.signOutButton.enabled = YES; + }]; +} + @end From c270305089974e2ea8a1deb90f56e57b103d347e Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 16:17:27 +0100 Subject: [PATCH 208/244] Fix a sign out warning wording --- Riot/Assets/en.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index d70ea117a..3d1ac3fe5 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -763,7 +763,7 @@ "sign_out_existing_key_backup_alert_title" = "Are you sure you want to sign out?"; "sign_out_existing_key_backup_alert_sign_out_action" = "Sign out"; -"sign_out_non_existing_key_backup_alert_title" = "You’ll lose access to your secure messages if you sign out now"; +"sign_out_non_existing_key_backup_alert_title" = "You’ll lose access to your encrypted messages if you sign out now"; "sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Start using Key Backup"; "sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "I don't want my encrypted messages"; From 6c670547e95845874dd67c109ce3195502cffe6a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 16:22:41 +0100 Subject: [PATCH 209/244] Update strings --- Riot/Generated/Strings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 2b8c0e54b..1f0697334 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2266,7 +2266,7 @@ internal enum VectorL10n { internal static var signOutNonExistingKeyBackupAlertSetupKeyBackupAction: String { return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_alert_setup_key_backup_action") } - /// You’ll lose access to your secure messages if you sign out now + /// You’ll lose access to your encrypted messages if you sign out now internal static var signOutNonExistingKeyBackupAlertTitle: String { return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_alert_title") } From 6f45e9713fdac3cb00bcde7905e40c82b13589f7 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 16:22:50 +0100 Subject: [PATCH 210/244] Update changes --- CHANGES.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.rst b/CHANGES.rst index c281197da..95e90e606 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -14,6 +14,7 @@ Improvements: * Key backup: Implement setup reminder (#2211). * Key backup: Implement recover reminder (#2206). * Key backup: Update key backup setup UI and UX (PR #2243). + * Key backup: Logout warning (#2245). Bug fix: * Use white scroll bar on dark themes (#2158). From 2921cac3002c1c4fde7a8feff9723267adc7d944 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 17:28:29 +0100 Subject: [PATCH 211/244] Key recovery: Trust on decrypt Fixed Steve's comments --- ...eyBackupRecoverFromPassphraseViewModel.swift | 13 ++----------- ...yBackupRecoverFromRecoveryKeyViewModel.swift | 17 ++++------------- 2 files changed, 6 insertions(+), 24 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift index 92b76e96e..264db3063 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModel.swift @@ -16,9 +16,6 @@ import Foundation -enum KeyBackupRecoverFromPassphraseViewModelError: Error { -} - final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphraseViewModelType { // MARK: - Properties @@ -88,17 +85,11 @@ final class KeyBackupRecoverFromPassphraseViewModel: KeyBackupRecoverFromPassphr ssself.coordinatorDelegate?.keyBackupRecoverFromPassphraseViewModelDidRecover(ssself) }, failure: { [weak sself] error in - guard let ssself = sself else { - return - } - ssself.update(viewState: .error(error)) + sself?.update(viewState: .error(error)) }) }, failure: { [weak self] error in - guard let sself = self else { - return - } - sself.update(viewState: .error(error)) + self?.update(viewState: .error(error)) }) } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift index 0bdd512e4..4ad042002 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModel.swift @@ -16,9 +16,6 @@ import Foundation -enum KeyBackupRecoverFromRecoveryKeyViewModelError: Error { -} - final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecoveryKeyViewModelType { // MARK: - Properties @@ -87,18 +84,12 @@ final class KeyBackupRecoverFromRecoveryKeyViewModel: KeyBackupRecoverFromRecove ssself.update(viewState: .loaded) ssself.coordinatorDelegate?.keyBackupRecoverFromRecoveryKeyViewModelDidRecover(ssself) - }, failure: { [weak sself] error in - guard let ssself = sself else { - return - } - ssself.update(viewState: .error(error)) + }, failure: {[weak sself] error in + sself?.update(viewState: .error(error)) }) - }, failure: { [weak self] error in - guard let sself = self else { - return - } - sself.update(viewState: .error(error)) + }, failure: {[weak self] error in + self?.update(viewState: .error(error)) }) } From d2cfad625893235272542c751bd912aff7503bca Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 17:30:53 +0100 Subject: [PATCH 212/244] Key recovery: Trust on decrypt Fixed Steve's comments --- .../KeyBackupRecoverFromPassphraseViewController.swift | 3 +-- .../KeyBackupRecoverFromRecoveryKeyViewController.swift | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift index 8230cd89c..018d0255f 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewController.swift @@ -190,8 +190,7 @@ final class KeyBackupRecoverFromPassphraseViewController: UIViewController { message: VectorL10n.keyBackupRecoverInvalidPassphrase, animated: true, handler: nil) - } - else { + } else { self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) } } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift index d29f3a027..ac097bc27 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewController.swift @@ -188,8 +188,7 @@ final class KeyBackupRecoverFromRecoveryKeyViewController: UIViewController { message: VectorL10n.keyBackupRecoverInvalidRecoveryKey, animated: true, handler: nil) - } - else { + } else { self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil) } } From 51f2312ccd2d042f4fddc361d977d560416ae4f2 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 17:47:59 +0100 Subject: [PATCH 213/244] Backup settings: Update wording and rendering to match riot-web Verify button has been removed and replaced by "Use key backup", which makes a restore, because we trust on decrypt now. --- Riot/Assets/en.lproj/Vector.strings | 24 ++--- Riot/Generated/Strings.swift | 40 ++++---- .../SettingsKeyBackupTableViewSection.swift | 97 +++++++------------ .../SettingsKeyBackupViewAction.swift | 1 - .../SettingsKeyBackupViewModel.swift | 3 - .../SettingsKeyBackupViewModelType.swift | 1 - .../Modules/Settings/SettingsViewController.m | 8 +- 7 files changed, 66 insertions(+), 108 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 7d011f333..b6ff2bf72 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -335,7 +335,7 @@ "settings_flair" = "Show flair where allowed"; "settings_devices" = "DEVICES"; "settings_cryptography" = "CRYPTOGRAPHY"; -"settings_key_backup" = "SECURE MESSAGE RECOVERY"; +"settings_key_backup" = "KEY BACKUP"; "settings_deactivate_account" = "DEACTIVATE ACCOUNT"; "settings_sign_out" = "Sign Out"; @@ -421,16 +421,16 @@ "settings_deactivate_my_account" = "Deactivate my account"; +"settings_key_backup_info" = "Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages."; "settings_key_backup_info_checking" = "Checking..."; -"settings_key_backup_info_none" = "Secure Message Recovery has not been set up."; +"settings_key_backup_info_none" = "Your keys are not being backed up from this device."; +"settings_key_backup_info_signout_warning" = "Back up your keys before signing out to avoid losing them."; "settings_key_backup_info_version" = "Key Backup Version: %@"; "settings_key_backup_info_algorithm" = "Algorithm: %@"; -"settings_key_backup_info_valid" = "Secure Message Recovery has been correctly set up for this device."; -"settings_key_backup_info_not_valid" = "Secure Message Recovery is not active on this device."; +"settings_key_backup_info_valid" = "This device is backing up your keys."; +"settings_key_backup_info_not_valid" = "This device is not backing up your keys."; "settings_key_backup_info_progress" = "Backing up %@ keys..."; -"settings_key_backup_info_progress_done" = "All keys have been backed up"; -"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "To use Secure Message Recovery on this device, verify %@ now."; -"settings_key_backup_info_not_trusted_fix_action" = "To use Secure Message Recovery on this device, provide your passphrase or recovery key now."; +"settings_key_backup_info_progress_done" = "All keys backed up"; "settings_key_backup_info_trust_signature_unknown" = "Backup has a signature from device with ID: %@"; "settings_key_backup_info_trust_signature_valid" = "Backup has a valid signature from this device"; @@ -439,12 +439,12 @@ "settings_key_backup_info_trust_signature_invalid_device_verified" = "Backup has an invalid signature from %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "Backup has an invalid signature from %@"; -"settings_key_backup_button_create" = "Set up Secure Message Recovery"; -"settings_key_backup_button_restore" = "Restore backup"; -"settings_key_backup_button_delete" = "Delete backup"; -"settings_key_backup_button_verify" = "Verify"; +"settings_key_backup_button_create" = "Start using Key Backup"; +"settings_key_backup_button_restore" = "Restore from Backup"; +"settings_key_backup_button_delete" = "Delete Backup"; +"settings_key_backup_button_use" = "Use key backup"; "settings_key_backup_delete_confirmation_prompt_title" = "Delete Backup"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Are you sure? You will lose your encrypted messages if your keys are not backed up properly."; // Room Details "room_details_title" = "Room Details"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 22a9c2ac3..a91ff531f 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -1970,27 +1970,27 @@ internal enum VectorL10n { internal static var settingsIgnoredUsers: String { return VectorL10n.tr("Vector", "settings_ignored_users") } - /// SECURE MESSAGE RECOVERY + /// KEY BACKUP internal static var settingsKeyBackup: String { return VectorL10n.tr("Vector", "settings_key_backup") } - /// Set up Secure Message Recovery + /// Start using Key Backup internal static var settingsKeyBackupButtonCreate: String { return VectorL10n.tr("Vector", "settings_key_backup_button_create") } - /// Delete backup + /// Delete Backup internal static var settingsKeyBackupButtonDelete: String { return VectorL10n.tr("Vector", "settings_key_backup_button_delete") } - /// Restore backup + /// Restore from Backup internal static var settingsKeyBackupButtonRestore: String { return VectorL10n.tr("Vector", "settings_key_backup_button_restore") } - /// Verify - internal static var settingsKeyBackupButtonVerify: String { - return VectorL10n.tr("Vector", "settings_key_backup_button_verify") + /// Use key backup + internal static var settingsKeyBackupButtonUse: String { + return VectorL10n.tr("Vector", "settings_key_backup_button_use") } - /// Delete your backed up encryption keys from the server? You will no longer be able to use your recovery key to read encrypted message history + /// Are you sure? You will lose your encrypted messages if your keys are not backed up properly. internal static var settingsKeyBackupDeleteConfirmationPromptMsg: String { return VectorL10n.tr("Vector", "settings_key_backup_delete_confirmation_prompt_msg") } @@ -1998,6 +1998,10 @@ internal enum VectorL10n { internal static var settingsKeyBackupDeleteConfirmationPromptTitle: String { return VectorL10n.tr("Vector", "settings_key_backup_delete_confirmation_prompt_title") } + /// Encrypted messages are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages. + internal static var settingsKeyBackupInfo: String { + return VectorL10n.tr("Vector", "settings_key_backup_info") + } /// Algorithm: %@ internal static func settingsKeyBackupInfoAlgorithm(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_algorithm", p1) @@ -2006,19 +2010,11 @@ internal enum VectorL10n { internal static var settingsKeyBackupInfoChecking: String { return VectorL10n.tr("Vector", "settings_key_backup_info_checking") } - /// Secure Message Recovery has not been set up. + /// Your keys are not being backed up from this device. internal static var settingsKeyBackupInfoNone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_none") } - /// To use Secure Message Recovery on this device, provide your passphrase or recovery key now. - internal static var settingsKeyBackupInfoNotTrustedFixAction: String { - return VectorL10n.tr("Vector", "settings_key_backup_info_not_trusted_fix_action") - } - /// To use Secure Message Recovery on this device, verify %@ now. - internal static func settingsKeyBackupInfoNotTrustedFromVerifiableDeviceFixAction(_ p1: String) -> String { - return VectorL10n.tr("Vector", "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action", p1) - } - /// Secure Message Recovery is not active on this device. + /// This device is not backing up your keys. internal static var settingsKeyBackupInfoNotValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_not_valid") } @@ -2026,10 +2022,14 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoProgress(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_progress", p1) } - /// All keys have been backed up + /// All keys backed up internal static var settingsKeyBackupInfoProgressDone: String { return VectorL10n.tr("Vector", "settings_key_backup_info_progress_done") } + /// Back up your keys before signing out to avoid losing them. + internal static var settingsKeyBackupInfoSignoutWarning: String { + return VectorL10n.tr("Vector", "settings_key_backup_info_signout_warning") + } /// Backup has an invalid signature from %@ internal static func settingsKeyBackupInfoTrustSignatureInvalidDeviceUnverified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_invalid_device_unverified", p1) @@ -2054,7 +2054,7 @@ internal enum VectorL10n { internal static func settingsKeyBackupInfoTrustSignatureValidDeviceVerified(_ p1: String) -> String { return VectorL10n.tr("Vector", "settings_key_backup_info_trust_signature_valid_device_verified", p1) } - /// Secure Message Recovery has been correctly set up for this device. + /// This device is backing up your keys. internal static var settingsKeyBackupInfoValid: String { return VectorL10n.tr("Vector", "settings_key_backup_info_valid") } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index 3bed6ca45..549928268 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -24,7 +24,6 @@ import UIKit func settingsKeyBackupTableViewSectionShowKeyBackupSetup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection) - func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showVerifyDevice deviceId:String) func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) func settingsKeyBackup(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, showKeyBackupDeleteConfirm keyBackupVersion:MXKeyBackupVersion) @@ -130,7 +129,12 @@ import UIKit } let cell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) - cell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoChecking + + let info = VectorL10n.settingsKeyBackupInfo + let checking = VectorL10n.settingsKeyBackupInfoChecking + + let strings = [info, "", checking] + cell.mxkTextView.text = strings.joined(separator: "\n") return cell } @@ -149,7 +153,13 @@ import UIKit switch row { case 0: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) - infoCell.mxkTextView.text = VectorL10n.settingsKeyBackupInfoNone + + let noBackup = VectorL10n.settingsKeyBackupInfoNone + let info = VectorL10n.settingsKeyBackupInfo + let signoutWarning = VectorL10n.settingsKeyBackupInfoSignoutWarning + + let strings = [noBackup, "", info, "", signoutWarning] + infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell @@ -178,10 +188,10 @@ import UIKit case 0: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + let info = VectorL10n.settingsKeyBackupInfo let backupStatus = VectorL10n.settingsKeyBackupInfoValid - let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone - let strings = [backupStatus, uploadStatus] + let strings = [info, "", backupStatus] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell @@ -191,8 +201,9 @@ import UIKit let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgressDone - let strings = [version, algorithm] + let strings = [version, algorithm, uploadStatus] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell @@ -233,12 +244,10 @@ import UIKit case 0: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: 0) - let remaining = backupProgress.totalUnitCount - backupProgress.completedUnitCount - + let info = VectorL10n.settingsKeyBackupInfo let backupStatus = VectorL10n.settingsKeyBackupInfoValid - let uploadStatus = VectorL10n.settingsKeyBackupInfoProgress(String(remaining)) - let strings = [backupStatus, uploadStatus] + let strings = [info, "", backupStatus] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell @@ -246,10 +255,13 @@ import UIKit case 1: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + let remaining = backupProgress.totalUnitCount - backupProgress.completedUnitCount + let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") let algorithm = VectorL10n.settingsKeyBackupInfoAlgorithm(keyBackupVersion.algorithm) + let uploadStatus = VectorL10n.settingsKeyBackupInfoProgress(String(remaining)) - let strings = [version, algorithm] + let strings = [version, algorithm, uploadStatus] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell @@ -277,7 +289,7 @@ import UIKit private func numberOfBackupNotTrustedRows() -> Int { - return 6 + return 5 } private func renderBackupNotTrustedCell(atRow row: Int, keyBackupVersion: MXKeyBackupVersion, keyBackupVersionTrust: MXKeyBackupVersionTrust) -> UITableViewCell { @@ -285,44 +297,21 @@ import UIKit return UITableViewCell.init() } - // Is the device that created the device verifiable? - // ie, is it known and already stored in crytpo store? - let lastNonVerifiedDevice = self.lastNonVerifiedDevice(keyBackupVersionTrust) - let lastUnVerifiableDevice = self.lastUnVerifiableDevice(keyBackupVersionTrust) - var cell: UITableViewCell switch row { case 0: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) + let info = VectorL10n.settingsKeyBackupInfo let backupStatus = VectorL10n.settingsKeyBackupInfoNotValid + let signoutWarning = VectorL10n.settingsKeyBackupInfoSignoutWarning - var fixAction: [String] = [] - if let lastNonVerifiedDevice = lastNonVerifiedDevice { - let deviceName = lastNonVerifiedDevice.displayName ?? lastNonVerifiedDevice.deviceId ?? "" - fixAction = [VectorL10n.settingsKeyBackupInfoNotTrustedFromVerifiableDeviceFixAction(deviceName)] - } - else if lastUnVerifiableDevice != nil { - fixAction = [VectorL10n.settingsKeyBackupInfoNotTrustedFixAction] - } - - let strings = [backupStatus] + fixAction + let strings = [info, "", backupStatus, "", signoutWarning] infoCell.mxkTextView.text = strings.joined(separator: "\n") cell = infoCell case 1: - if let lastNonVerifiedDevice = lastNonVerifiedDevice { - cell = self.buttonCellForVerifyingDevice(lastNonVerifiedDevice.deviceId, atRow: row) - } - else if lastUnVerifiableDevice != nil { - cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row, title: VectorL10n.settingsKeyBackupButtonVerify) - } - else { - cell = UITableViewCell.init() - } - - case 2: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) let version = VectorL10n.settingsKeyBackupInfoVersion(keyBackupVersion.version ?? "") @@ -333,7 +322,7 @@ import UIKit cell = infoCell - case 3: + case 2: let infoCell: MXKTableViewCellWithTextView = delegate.settingsKeyBackupTableViewSection(self, textCellForRow: row) let backupTrust = self.stringForKeyBackupTrust(keyBackupVersionTrust); @@ -341,10 +330,10 @@ import UIKit cell = infoCell - case 4: - cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row) + case 3: + cell = self.buttonCellForRestore(keyBackupVersion: keyBackupVersion, atRow: row, title: VectorL10n.settingsKeyBackupButtonUse) - case 5: + case 4: cell = self.buttonCellForDelete(keyBackupVersion: keyBackupVersion, atRow: row) default: @@ -438,25 +427,6 @@ import UIKit return cell } - private func buttonCellForVerifyingDevice(_ deviceId: String, atRow row: Int) -> UITableViewCell { - - guard let delegate = self.delegate else { - return UITableViewCell.init() - } - - let cell:MXKTableViewCellWithButton = delegate.settingsKeyBackupTableViewSection(self, buttonCellForRow: row) - - let btnTitle = VectorL10n.settingsKeyBackupButtonVerify - cell.mxkButton.setTitle(btnTitle, for: .normal) - cell.mxkButton.setTitle(btnTitle, for: .highlighted) - - cell.mxkButton.vc_addAction { - self.viewModel.process(viewAction: .verify(deviceId)) - } - - return cell - } - private func buttonCellForRestore(keyBackupVersion: MXKeyBackupVersion, atRow row: Int, title: String = VectorL10n.settingsKeyBackupButtonRestore) -> UITableViewCell { guard let delegate = self.delegate else { return UITableViewCell.init() @@ -513,12 +483,11 @@ extension SettingsKeyBackupTableViewSection: SettingsKeyBackupViewModelViewDeleg func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) { self.delegate?.settingsKeyBackupTableViewSectionShowKeyBackupSetup(self) } - func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showVerifyDevice deviceId: String) { - self.delegate?.settingsKeyBackup(self, showVerifyDevice: deviceId) - } + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupRecover keyBackupVersion: MXKeyBackupVersion) { self.delegate?.settingsKeyBackup(self, showKeyBackupRecover: keyBackupVersion) } + func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupDeleteConfirm keyBackupVersion: MXKeyBackupVersion) { self.delegate?.settingsKeyBackup(self, showKeyBackupDeleteConfirm: keyBackupVersion) } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift index f1748bf67..7d6e05166 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewAction.swift @@ -19,7 +19,6 @@ import UIKit enum SettingsKeyBackupViewAction { case load case create - case verify(String) case restore(MXKeyBackupVersion) case confirmDelete(MXKeyBackupVersion) case delete(MXKeyBackupVersion) diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift index 0ec986fa2..c8a265684 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModel.swift @@ -49,9 +49,6 @@ final class SettingsKeyBackupViewModel: SettingsKeyBackupViewModelType { case .create: viewDelegate.settingsKeyBackupViewModelShowKeyBackupSetup(self) break - case .verify(let deviceId): - viewDelegate.settingsKeyBackup(self, showVerifyDevice: deviceId) - break case .restore(let keyBackupVersion): viewDelegate.settingsKeyBackup(self, showKeyBackupRecover: keyBackupVersion) break diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift index 20c59ba94..f7cc5e3bf 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift @@ -21,7 +21,6 @@ protocol SettingsKeyBackupViewModelViewDelegate: class { func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsKeyBackupNetworkRequestViewState) func settingsKeyBackupViewModelShowKeyBackupSetup(_ viewModel: SettingsKeyBackupViewModelType) - func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showVerifyDevice deviceId:String) func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupRecover keyBackupVersion:MXKeyBackupVersion) func settingsKeyBackup(_ viewModel: SettingsKeyBackupViewModelType, showKeyBackupDeleteConfirm keyBackupVersion:MXKeyBackupVersion) } diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 13c295a0e..377b220de 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -4293,12 +4293,6 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> [self showKeyBackupSetup]; } -- (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showVerifyDevice:(NSString *)deviceId -{ - MXDeviceInfo *deviceInfo = [self.mainSession.crypto.deviceList storedDevice:self.mainSession.myUser.userId deviceId:deviceId]; - [self showDeviceInfo:deviceInfo]; -} - - (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showKeyBackupRecover:(MXKeyBackupVersion *)keyBackupVersion { [self showKeyBackupRecover:keyBackupVersion]; @@ -4321,7 +4315,7 @@ KeyBackupRecoverCoordinatorBridgePresenterDelegate> self->currentAlert = nil; }]]; - [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"remove", @"Vector", nil) + [currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"settings_key_backup_button_delete", @"Vector", nil) style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { MXStrongifyAndReturnIfNil(self); From e6f29cf47df15543ff5c64af4d6ded06cd542c9a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 18:04:25 +0100 Subject: [PATCH 214/244] Add sign out warning backup in progress strings --- Riot/Assets/en.lproj/Vector.strings | 6 +++++- Riot/Generated/Strings.swift | 12 ++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 3d1ac3fe5..c68394be1 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -758,7 +758,7 @@ "key_backup_recover_banner_title" = "Never lose encrypted messages"; "key_backup_recover_banner_subtitle" = "Use Key Backup"; -// MARK: Sign out +// MARK: Sign out warning "sign_out_existing_key_backup_alert_title" = "Are you sure you want to sign out?"; "sign_out_existing_key_backup_alert_sign_out_action" = "Sign out"; @@ -771,3 +771,7 @@ "sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "You'll lose access to your encrypted messages unless you back up your keys before signing out."; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Sign out"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Backup"; + +"sign_out_key_backup_in_progress_alert_title" = "Key backup in progress. If you sign out now you’ll lose access to your encrypted messages."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "I don't want my encrypted messages"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "I'll wait"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 1f0697334..1b6ff7c1d 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2258,6 +2258,18 @@ internal enum VectorL10n { internal static var signOutExistingKeyBackupAlertTitle: String { return VectorL10n.tr("Vector", "sign_out_existing_key_backup_alert_title") } + /// I'll wait + internal static var signOutKeyBackupInProgressAlertCancelAction: String { + return VectorL10n.tr("Vector", "sign_out_key_backup_in_progress_alert_cancel_action") + } + /// I don't want my encrypted messages + internal static var signOutKeyBackupInProgressAlertDiscardKeyBackupAction: String { + return VectorL10n.tr("Vector", "sign_out_key_backup_in_progress_alert_discard_key_backup_action") + } + /// Key backup in progress. If you sign out now you’ll lose access to your encrypted messages. + internal static var signOutKeyBackupInProgressAlertTitle: String { + return VectorL10n.tr("Vector", "sign_out_key_backup_in_progress_alert_title") + } /// I don't want my encrypted messages internal static var signOutNonExistingKeyBackupAlertDiscardKeyBackupAction: String { return VectorL10n.tr("Vector", "sign_out_non_existing_key_backup_alert_discard_key_backup_action") From 31419276ee08fe332c1eefc5238929f38a33b547 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 14 Feb 2019 18:06:37 +0100 Subject: [PATCH 215/244] Update SignOutAlertPresenter to handle backup in progress case --- .../Modules/Settings/SettingsViewController.m | 11 ++++--- .../SignOut/SignOutAlertPresenter.swift | 31 +++++++++++++++---- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 3c7e23ef7..a312ad352 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -252,7 +252,7 @@ SignOutAlertPresenterDelegate> @property (nonatomic) BOOL newPhoneEditingEnabled; @property (nonatomic, weak) DeactivateAccountViewController *deactivateAccountViewController; -@property (nonatomic, strong) SignOutAlertPresenter *signOutPresenter; +@property (nonatomic, strong) SignOutAlertPresenter *signOutAlertPresenter; @property (nonatomic, weak) UIButton *signOutButton; @end @@ -357,8 +357,8 @@ SignOutAlertPresenterDelegate> }]; [self userInterfaceThemeDidChange]; - self.signOutPresenter = [SignOutAlertPresenter new]; - self.signOutPresenter.delegate = self; + self.signOutAlertPresenter = [SignOutAlertPresenter new]; + self.signOutAlertPresenter.delegate = self; } - (void)userInterfaceThemeDidChange @@ -2709,8 +2709,9 @@ SignOutAlertPresenterDelegate> - (void)onSignout:(id)sender { self.signOutButton = (UIButton*)sender; - self.signOutPresenter.isABackupExist = !(self.mainSession.crypto.backup.state == MXKeyBackupStateDisabled); - [self.signOutPresenter presentFrom:self animated:YES]; + + MXKeyBackupState backupState = self.mainSession.crypto.backup.state; + [self.signOutAlertPresenter presentFor:backupState from:self animated:YES]; } - (void)onRemove3PID:(NSIndexPath*)path diff --git a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift index 2caa517b4..34074f043 100644 --- a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift +++ b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift @@ -32,18 +32,20 @@ final class SignOutAlertPresenter: NSObject { // MARK: Public - var isABackupExist: Bool = false weak var delegate: SignOutAlertPresenterDelegate? // MARK: - Public - func present(from viewController: UIViewController, animated: Bool) { + func present(for keyBackupState: MXKeyBackupState, from viewController: UIViewController, animated: Bool) { self.presentingViewController = viewController - - if self.isABackupExist { - self.presentExistingBackupAlert(animated: animated) - } else { + + switch keyBackupState { + case MXKeyBackupStateUnknown, MXKeyBackupStateDisabled, MXKeyBackupStateCheckingBackUpOnHomeserver: self.presentNonExistingBackupAlert(animated: animated) + case MXKeyBackupStateWillBackUp, MXKeyBackupStateBackingUp: + self.presentBackupInProgressAlert(animated: animated) + default: + self.presentExistingBackupAlert(animated: animated) } } @@ -106,4 +108,21 @@ final class SignOutAlertPresenter: NSObject { self.presentingViewController?.present(alertContoller, animated: true, completion: nil) } + + private func presentBackupInProgressAlert(animated: Bool) { + let alertContoller = UIAlertController(title: VectorL10n.signOutKeyBackupInProgressAlertTitle, + message: nil, + preferredStyle: .actionSheet) + + let discardKeyBackupAction = UIAlertAction(title: VectorL10n.signOutKeyBackupInProgressAlertDiscardKeyBackupAction, style: .destructive) { (_) in + self.delegate?.signOutAlertPresenterDidTapSignOutAction(self) + } + + let cancelAction = UIAlertAction(title: VectorL10n.signOutKeyBackupInProgressAlertCancelAction, style: .cancel, handler: nil) + + alertContoller.addAction(discardKeyBackupAction) + alertContoller.addAction(cancelAction) + + self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + } } From ca8edeb3790d2d88304957a35c66238094505de3 Mon Sep 17 00:00:00 2001 From: manuroe Date: Thu, 14 Feb 2019 19:20:50 +0100 Subject: [PATCH 216/244] reskin: Fix dark theme colors --- Riot/Managers/Theme/Themes/DarkTheme.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index cd57acefd..89d3cc92b 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -23,15 +23,15 @@ class DarkTheme: NSObject, Theme { var backgroundColor: UIColor = UIColor(rgb: 0x181B21) - var baseColor: UIColor = UIColor(rgb: 0x15171B) + var baseColor: UIColor = UIColor(rgb: 0x1B1F25) var baseTextPrimaryColor: UIColor = UIColor(rgb: 0xEDF3FF) var baseTextSecondaryColor: UIColor = UIColor(rgb: 0xEDF3FF) var searchBackgroundColor: UIColor = UIColor(rgb: 0x181B21) var searchPlaceholderColor: UIColor = UIColor(rgb: 0x61708B) - var headerBackgroundColor: UIColor = UIColor(rgb: 0x181B21) - var headerBorderColor: UIColor = UIColor(rgb: 0x22262E) + var headerBackgroundColor: UIColor = UIColor(rgb: 0x22262E) + var headerBorderColor: UIColor = UIColor(rgb: 0x181B21) var headerTextPrimaryColor: UIColor = UIColor(rgb: 0xA1B2D1) var headerTextSecondaryColor: UIColor = UIColor(rgb: 0xC8C8CD) From 8c1ea9c7ab201799c2be5a417cf67a3bc0b39317 Mon Sep 17 00:00:00 2001 From: Osoitz Date: Mon, 11 Feb 2019 20:29:38 +0000 Subject: [PATCH 217/244] Translated using Weblate (Basque) Currently translated at 90.8% (533 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/eu/ --- Riot/Assets/eu.lproj/Vector.strings | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/eu.lproj/Vector.strings b/Riot/Assets/eu.lproj/Vector.strings index e1e15fe99..abfccc664 100644 --- a/Riot/Assets/eu.lproj/Vector.strings +++ b/Riot/Assets/eu.lproj/Vector.strings @@ -7,7 +7,7 @@ "bug_report_send" = "Bidali"; "room_event_action_copy" = "Kopiatu"; "room_event_action_resend" = "Birbidali"; -"room_event_action_redact" = "Ezabatu"; +"room_event_action_redact" = "Kendu"; "room_event_action_quote" = "Aipua"; "room_event_action_share" = "Partekatu"; "later" = "Geroago"; @@ -421,7 +421,7 @@ "room_ongoing_conference_call_with_close" = "Konferentzia deia abian. elkartu %@ edo %@ gisa. %@."; "room_ongoing_conference_call_close" = "Itxi"; "room_conference_call_no_power" = "Baimena behar duzu konferentzia deia kudeatzeko gela honetan"; -"settings_labs_create_conference_with_jitsi" = "Sortu konferentzia deia jitsi erabiliz"; +"settings_labs_create_conference_with_jitsi" = "Sortu konferentzia deia Jitsi erabiliz"; "call_already_displayed" = "Badago de bat abian."; "call_jitsi_error" = "Hutsegitea konferentzia deia elkartzean."; // Widget @@ -559,3 +559,16 @@ "room_resource_usage_limit_reached_message_2" = "erabiltzaile batzuk ezin izango dute saioa hasi."; "room_resource_usage_limit_reached_message_contact_3" = " muga hau areagotzeko."; "auth_accept_policies" = "Irakurri eta onartu hasiera-zerbitzariaren baldintzak:"; +"settings_key_backup" = "MEZU SEGURUEN BERRESKURATZEA"; +"settings_key_backup_info_checking" = "Egiaztatzen..."; +"settings_key_backup_info_none" = "Ez da ezarri mezu seguruen berreskuratzea."; +"settings_key_backup_info_version" = "Gakoen babes-kopiaren bertsioa: %@"; +"settings_key_backup_info_algorithm" = "Algoritmoa: %@"; +"settings_key_backup_button_restore" = "Berrezarri babes-kopia"; +"settings_key_backup_button_delete" = "Ezabatu babes-kopia"; +"settings_key_backup_button_verify" = "Egiaztatu"; +"settings_key_backup_delete_confirmation_prompt_title" = "Ezabatu babes-kopia"; +"settings_key_backup_info_progress" = "%@ gakoen babes-kopia egiten..."; +"settings_key_backup_info_progress_done" = "Gako guztien babes-kopia egin da"; +"settings_key_backup_info_valid" = "Mezu seguruen berreskuratzea ongi ezarri da gailu honetan."; +"settings_key_backup_info_not_valid" = "Mezu seguruen berreskuratzea ez dago aktibo gailu honetan."; From 0ec9ae9a580d6c31358a4c3e27e4bbe9b1921339 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 1 Feb 2019 12:26:12 +0000 Subject: [PATCH 218/244] Translated using Weblate (Russian) Currently translated at 100.0% (587 of 587 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index c2712a2bf..74abee167 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -580,7 +580,7 @@ "settings_key_backup_button_delete" = "Удалить резервную копию"; "settings_key_backup_button_verify" = "Проверить"; "settings_key_backup_delete_confirmation_prompt_title" = "Удалить резервную копию"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Удалить резервную копию ключей шифрования с сервера? Вы больше не сможете использовать ключ восстановления для чтения истории зашифрованных сообщений."; +"settings_key_backup_delete_confirmation_prompt_msg" = "Удалить резервную копию ключей шифрования с сервера? Вы больше не сможете использовать ключ восстановления для чтения истории зашифрованных сообщений"; "room_does_not_exist" = "%@ не существует"; "key_backup_setup_title" = "Восстановление Сообщений"; "key_backup_setup_skip_action" = "Пропустить"; @@ -606,14 +606,14 @@ "key_backup_recover_title" = "Безопасные Сообщения"; "key_backup_recover_empty_backup_title" = "Пустая резервная копия"; "key_backup_recover_empty_backup_message" = "Нет ключа для восстановления"; -"key_backup_recover_from_passphrase_info" = "Используйте парольную фразу восстановления для разблокировки истории безопасных сообщений."; +"key_backup_recover_from_passphrase_info" = "Используйте парольную фразу восстановления для разблокировки истории безопасных сообщений"; "key_backup_recover_from_passphrase_passphrase_title" = "Ввод"; "key_backup_recover_from_passphrase_passphrase_placeholder" = "Введите парольную фразу"; "key_backup_recover_from_passphrase_recover_action" = "Разблокировать историю"; "key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Не знаете вашу парольную фразу для восстановления? Вы можете "; "key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "используйте ключ восстановления"; "key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; -"key_backup_recover_from_recovery_key_info" = "Используйте ключ восстановления для разблокировки истории безопасных сообщений."; +"key_backup_recover_from_recovery_key_info" = "Используйте ключ восстановления для разблокировки истории безопасных сообщений"; "key_backup_recover_from_recovery_key_recovery_key_title" = "Ввод"; "key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Введите ключ восстановления"; "key_backup_recover_from_recovery_key_recover_action" = "Разблокировать историю"; @@ -624,4 +624,4 @@ "key_backup_recover_banner_title_part1" = "Запуск Безопасного Восстановления Сообщений"; "key_backup_recover_banner_title_part2" = " для чтения истории зашифрованных сообщений на этом устройстве"; "key_backup_setup_banner_title_part2" = " чтобы никогда не потерять зашифрованные сообщения"; -"key_backup_setup_recovery_key_info" = "Сделайте копию ключа восстановления и сохраните его в надёжном месте.\n\nКак сеть безопасности, вы можете использовать ее для восстановления истории зашифрованных сообщений, если вы забыли свою фразу-пароль восстановления."; +"key_backup_setup_recovery_key_info" = "Сделайте копию ключа восстановления и надёжно сохраните его.\n\nЕго можно будет использовать для восстановления истории зашифрованных сообщений, на случай если вы забудете парольную фразу восстановления."; From 2ca6d35c3e89ee4636d8983c06382c598a439651 Mon Sep 17 00:00:00 2001 From: sergio Date: Thu, 14 Feb 2019 21:16:05 +0000 Subject: [PATCH 219/244] Translated using Weblate (Russian) Currently translated at 100.0% (608 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 62 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index 74abee167..ef2186500 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -544,7 +544,7 @@ "room_replacement_information" = "Эта комната была заменена и больше не активна."; "room_replacement_link" = "Этот разговор продолжается здесь."; "room_predecessor_information" = "Эта комната является продолжением другого разговора."; -"room_predecessor_link" = "Нажмите здесь, чтобы просмотреть старые сообщения."; +"room_predecessor_link" = "Коснитесь здесь, чтобы просмотреть старые сообщения."; "room_recents_server_notice_section" = "СИСТЕМНЫЕ ПРЕДУПРЕЖДЕНИЯ"; "room_resource_limit_exceeded_message_contact_1" = " Пожалуйста "; "room_resource_limit_exceeded_message_contact_2_link" = "обратитесь к администратору сервиса"; @@ -559,12 +559,12 @@ "homeserver_connection_lost" = "Невозможно соединиться с этим сервером."; "auth_accept_policies" = "Пожалуйста ознакомьтесь и подтвердите согласие с политикой этого сервера:"; "settings_key_backup_info_checking" = "Проверка ..."; -"settings_key_backup_info_none" = "Безопасное восстановление сообщений не настроено."; -"settings_key_backup" = "БЕЗОПАСНОЕ ВОССТАНОВЛЕНИЕ СООБЩЕНИЙ"; +"settings_key_backup_info_none" = "Ваши ключи не копируются с этого устройства."; +"settings_key_backup" = "РЕЗЕРВНАЯ КОПИЯ КЛЮЧЕЙ"; "settings_key_backup_info_version" = "Версия ключа резервного копирования: %@"; "settings_key_backup_info_algorithm" = "Алгоритм: %@"; -"settings_key_backup_info_valid" = "Безопасное восстановление сообщений успешно настроено для этого устройства."; -"settings_key_backup_info_not_valid" = "Безопасное восстановление сообщений не активно на этом устройстве."; +"settings_key_backup_info_valid" = "Это устройство делает резервное копирование ваших ключей."; +"settings_key_backup_info_not_valid" = "Это устройство не делает резервного копирования ваших ключей."; "settings_key_backup_info_progress" = "Резервное копирование ключей %@..."; "settings_key_backup_info_progress_done" = "Все ключи сохранены"; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Для Безопасного Восстановления Сообщений на этом устройстве, проверьте %@."; @@ -575,22 +575,22 @@ "settings_key_backup_info_trust_signature_valid_device_unverified" = "Резервная копия подписана %@"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "Резервная копия имеет невалидную подпись %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "Резервная копия имеет невалидную подпись %@"; -"settings_key_backup_button_create" = "Настройка Безопасного Восстановления Сообщений"; -"settings_key_backup_button_restore" = "Восстановить резервную копию"; +"settings_key_backup_button_create" = "Использовать резервное копирование ключей"; +"settings_key_backup_button_restore" = "Восстановить из резервной копии"; "settings_key_backup_button_delete" = "Удалить резервную копию"; "settings_key_backup_button_verify" = "Проверить"; "settings_key_backup_delete_confirmation_prompt_title" = "Удалить резервную копию"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Удалить резервную копию ключей шифрования с сервера? Вы больше не сможете использовать ключ восстановления для чтения истории зашифрованных сообщений"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Вы уверены? Зашифрованные сообщения будут утеряны, если не сделать резервную копию должным образом."; "room_does_not_exist" = "%@ не существует"; -"key_backup_setup_title" = "Восстановление Сообщений"; +"key_backup_setup_title" = "Резервное копирование ключей"; "key_backup_setup_skip_action" = "Пропустить"; "key_backup_setup_skip_alert_title" = "Вы уверены?"; "key_backup_setup_skip_alert_message" = "Вы можете потерять зашифрованные сообщения, если выйдете из системы или потеряете свое устройство."; "key_backup_setup_skip_alert_skip_action" = "Пропустить"; "key_backup_setup_intro_title" = "Никогда не теряйте зашифрованных сообщений"; -"key_backup_setup_intro_info" = "Настройте Безопасное Восстановление Сообщений на случай утери устройства или выхода из него."; +"key_backup_setup_intro_info" = "Сообщения в зашифрованных комнатах защищены сквозным шифрованием. Только вы и получатель(и) имеют ключи для чтения этих сообщений.\n\nСохраните ключи надежно, чтобы не потерять их."; "key_backup_setup_intro_setup_action" = "Настроить"; -"key_backup_setup_passphrase_info" = "Защитите зашифрованную историю сообщений парольной фразой.\n\nОн понадобится вам, если вы выйдете из системы или потеряете доступ к этому устройству."; +"key_backup_setup_passphrase_info" = "Мы будем хранить зашифрованную копию ваших ключей на нашем сервере. Для безопасности, защитите резервную копию парольной фразой.\n\nДля обеспечения максимальной безопасности он должен отличаться от пароля учетной записи."; "key_backup_setup_passphrase_passphrase_title" = "Ввод"; "key_backup_setup_passphrase_passphrase_placeholder" = "Введите парольную фразу"; "key_backup_setup_passphrase_passphrase_valid" = "Отлично!"; @@ -599,7 +599,7 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Повторите парольную фразу"; "key_backup_setup_passphrase_confirm_passphrase_valid" = "Отлично!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Парольные фразы не совпадает"; -"key_backup_setup_passphrase_set_passphrase_action" = "Задать парольную фразу для восстановления"; +"key_backup_setup_passphrase_set_passphrase_action" = "Установить парольную фразу"; "key_backup_setup_recovery_key_recovery_key_title" = "Ключ для восстановления"; "key_backup_setup_recovery_key_make_copy_action" = "Сделать копию"; "key_backup_setup_recovery_key_made_copy_action" = "Я сделал копию"; @@ -625,3 +625,41 @@ "key_backup_recover_banner_title_part2" = " для чтения истории зашифрованных сообщений на этом устройстве"; "key_backup_setup_banner_title_part2" = " чтобы никогда не потерять зашифрованные сообщения"; "key_backup_setup_recovery_key_info" = "Сделайте копию ключа восстановления и надёжно сохраните его.\n\nЕго можно будет использовать для восстановления истории зашифрованных сообщений, на случай если вы забудете парольную фразу восстановления."; +"key_backup_setup_success_title" = "Успешно!"; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Сохранить ключ восстановления"; +"key_backup_setup_success_from_passphrase_done_action" = "Готово"; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Ключ восстановления"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Сделать копию"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Я сделал копию"; +"key_backup_recover_invalid_passphrase_title" = "Неверная парольная фраза для восстановления"; +"key_backup_recover_invalid_recovery_key_title" = "Несоответствующий ключ восстановления"; +"key_backup_setup_banner_title" = "Не теряйте зашифрованные сообщения"; +"key_backup_setup_banner_subtitle" = "Начать использовать ключ восстановления"; +"key_backup_recover_banner_title" = "Не теряйте зашифрованные сообщения"; +"key_backup_recover_banner_subtitle" = "Использовать ключ восстановления"; +"sign_out_existing_key_backup_alert_title" = "Вы уверены, что хотите выйти?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Выйти"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Начать использовать ключ восстановления"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Резервная копия"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Выйти"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Я подожду"; +"settings_key_backup_button_use" = "Использовать ключ восстановления"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Начать использовать ключ восстановления"; +"key_backup_setup_intro_setup_action_with_existing_backup" = "Использовать ключ восстановления"; +"settings_key_backup_info" = "Зашифрованные сообщения защищены сквозным шифрованием. Только вы и получатель(и) имеют ключи для чтения этих сообщений."; +"settings_key_backup_info_signout_warning" = "Перед выходом сделайте резервную копию ключей, чтобы не потерять их."; +"key_backup_setup_passphrase_title" = "Защитите резервную копию парольной фразой"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Или защитите резервную копию с помощью ключа восстановления, сохранив его в безопасном месте."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Расширенный) Настройка с ключом восстановления"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Выполняется резервная копия ключей.\n\nКлюч восстановления это страховка — вы можете использовать его для восстановления доступа к вашим зашифрованным сообщениям, если забыли пароль.\n\nХраните ключ восстановления в очень надежном месте, например, в менеджере паролей (или сейфе)."; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Выполняется резервная копия ключей.\n\nСохраните его в безопасном месте."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Мне не нужны мои зашифрованные сообщения"; +"sign_out_key_backup_in_progress_alert_title" = "Идет процесс резервного копирования. Если вы выйдете сейчас, то потеряете доступ к зашифрованным сообщениям."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Вы потеряете доступ к зашифрованным сообщениям, если не сделаете резервное копирование ключей перед выходом."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Зашифрованные сообщения будут утеряны"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Мне не нужны мои зашифрованные сообщения"; +"sign_out_non_existing_key_backup_alert_title" = "Вы потеряете доступ к зашифрованным сообщениям если выйдете сейчас"; +"key_backup_recover_invalid_passphrase" = "Невозможно расшифровать резервную копию с помощью этой парольной фразы: убедитесь, что вы ввели верную парольную фразу для восстановления."; +"key_backup_recover_invalid_recovery_key" = "Невозможно расшифровать резервную копию с помощью этого ключа: убедитесь, что вы ввели верный ключ восстановления."; From bad744417ac3a475f4c8832aa3f0ca0452145c22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20C?= Date: Thu, 14 Feb 2019 22:25:56 +0000 Subject: [PATCH 220/244] Translated using Weblate (French) Currently translated at 100.0% (608 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/fr/ --- Riot/Assets/fr.lproj/Vector.strings | 62 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index 9366082e7..ae9f29fad 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -543,7 +543,7 @@ "room_replacement_information" = "Ce salon a été remplacé et n'est plus actif."; "room_replacement_link" = "La conversation continue ici."; "room_predecessor_information" = "Ce salon est la suite d'une autre conversation."; -"room_predecessor_link" = "Cliquer ici pour voir les vieux messages."; +"room_predecessor_link" = "Appuyer ici pour voir les vieux messages."; "settings_labs_room_members_lazy_loading" = "Chargement différé des participants des salons"; "settings_labs_room_members_lazy_loading_error_message" = "Votre serveur d'accueil ne prend pas en charge le chargement différé des participants des salons. Réessayez plus tard."; "room_event_action_view_decrypted_source" = "Voir la source déchiffrée"; @@ -557,13 +557,13 @@ "room_resource_usage_limit_reached_message_2" = "quelques utilisateurs ne pourront pas se connecter."; "room_resource_usage_limit_reached_message_contact_3" = " pour augmenter cette limite."; "auth_accept_policies" = "Veuillez lire et accepter les politiques de ce serveur d'accueil :"; -"settings_key_backup" = "Récupération de message sécurisée"; +"settings_key_backup" = "SAUVEGARDE DE CLÉS"; "settings_key_backup_info_checking" = "Vérification…"; -"settings_key_backup_info_none" = "La récupération de messages sécurisée n'a pas été configurée."; +"settings_key_backup_info_none" = "Vos clés ne sont pas sauvegardées depuis cet appareil."; "settings_key_backup_info_version" = "Version de sauvegarde de clé : %@"; "settings_key_backup_info_algorithm" = "Algorithme : %@"; -"settings_key_backup_info_valid" = "La récupération de messages sécurisée a été correctement configurée pour cet appareil."; -"settings_key_backup_info_not_valid" = "La récupération de messages sécurisée n'est pas activée sur cet appareil."; +"settings_key_backup_info_valid" = "Cet appareil sauvegarde vos clés."; +"settings_key_backup_info_not_valid" = "Cet appareil ne sauvegarde pas vos clés."; "settings_key_backup_info_progress" = "Sauvegarde de %@ clés…"; "settings_key_backup_info_progress_done" = "Toutes les clés ont été sauvegardées"; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Pour utiliser la récupération de messages sécurisée sur cet appareil, vérifiez %@ maintenant."; @@ -574,22 +574,22 @@ "settings_key_backup_info_trust_signature_valid_device_unverified" = "La sauvegarde a une signature depuis %@"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "La sauvegarde a une signature non valide depuis %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "La sauvegarde a une signature non valide depuis %@"; -"settings_key_backup_button_create" = "Configurer la récupération de messages sécurisée"; -"settings_key_backup_button_restore" = "Restaurer la sauvegarde"; +"settings_key_backup_button_create" = "Commencer à utiliser la sauvegarde des clés"; +"settings_key_backup_button_restore" = "Restaurer depuis la sauvegarde"; "settings_key_backup_button_delete" = "Supprimer la sauvegarde"; "settings_key_backup_button_verify" = "Vérifier"; "settings_key_backup_delete_confirmation_prompt_title" = "Supprimer la sauvegarde"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Supprimer vos clés de chiffrement sauvegardées sur le serveur ? Vous ne pourrez plus utiliser votre clé de récupération pour lire l'historique des messages chiffrés"; +"settings_key_backup_delete_confirmation_prompt_msg" = "En êtes-vous sûr(e) ? Vous perdrez vos messages chiffrés si vos clés ne sont pas sauvegardées correctement."; "room_does_not_exist" = "%@ n'existe pas"; -"key_backup_setup_title" = "Récupération de messages"; +"key_backup_setup_title" = "Sauvegarde de clés"; "key_backup_setup_skip_action" = "Passer"; "key_backup_setup_skip_alert_title" = "En êtes-vous certain(e) ?"; "key_backup_setup_skip_alert_message" = "Vous pourriez perdre vos messages sécurisés si vous vous déconnectez ou si vous perdez votre appareil."; "key_backup_setup_skip_alert_skip_action" = "Passer"; "key_backup_setup_intro_title" = "Ne perdez jamais vos messages chiffrés"; -"key_backup_setup_intro_info" = "Configurer la récupération de messages sécurisée au cas où vous perdez cet appareil ou que vous vous déconnectez."; +"key_backup_setup_intro_info" = "Les messages des salons chiffrés sont sécurisés avec un chiffrement de bout en bout. Seuls vous et le(s) destinataire(s) avez les clés pour lire ces messages.\n\nSauvegardez vos clés de façon sécurisée pour éviter de les perdre."; "key_backup_setup_intro_setup_action" = "Configurer"; -"key_backup_setup_passphrase_info" = "Protégez votre historique de messages chiffrés avec une phrase de passe de récupération.\n\nVous en aurez besoin si vous vous déconnectez ou si vous n'avez plus accès à cet appareil."; +"key_backup_setup_passphrase_info" = "Nous conserverons une copie chiffrée de vos clés sur notre serveur. Protégez votre sauvegarde avec une phrase de passe pour qu'elle soit sécurisée.\n\nPour une sécurité maximale, elle devrait être différente du mot de passe de votre compte."; "key_backup_setup_passphrase_passphrase_title" = "Saisir"; "key_backup_setup_passphrase_passphrase_placeholder" = "Saisir la phrase de passe"; "key_backup_setup_passphrase_passphrase_valid" = "Super !"; @@ -598,7 +598,7 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Confirmer la phrase de passe"; "key_backup_setup_passphrase_confirm_passphrase_valid" = "Super !"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Les phrases de passe ne correspondent pas"; -"key_backup_setup_passphrase_set_passphrase_action" = "Définir la phrase de passe de récupération"; +"key_backup_setup_passphrase_set_passphrase_action" = "Définir la phrase de passe"; "key_backup_setup_recovery_key_info" = "Faites une copie de cette clé de récupération et conservez-la en lieu sûr.\n\nPar mesure de précaution, vous pouvez l'utiliser pour restaurer votre historique de messages chiffrés si vous oubliez votre phrase de passe de récupération."; "key_backup_setup_recovery_key_recovery_key_title" = "Clé de récupération"; "key_backup_setup_recovery_key_make_copy_action" = "En faire une copie"; @@ -624,3 +624,41 @@ "key_backup_setup_banner_title_part2" = " pour ne jamais perdre vos messages chiffrés"; "key_backup_recover_banner_title_part1" = "Lancer la récupération de messages sécurisée"; "key_backup_recover_banner_title_part2" = " pour lire l'historique des messages chiffrés sur cet appareil"; +"settings_key_backup_info" = "Les messages chiffrés sont sécurisés avec un chiffrement de bout en bout. Seuls vous et le(s) destinataire(s) avez les clés pour lire ces messages."; +"settings_key_backup_info_signout_warning" = "Sauvegardez vos clés avant de vous déconnecter pour éviter de les perdre."; +"settings_key_backup_button_use" = "Utiliser la sauvegarde de clés"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Commencer à utiliser la sauvegarde de clés"; +"key_backup_setup_intro_setup_action_with_existing_backup" = "Utiliser la sauvegarde de clés"; +"key_backup_setup_passphrase_title" = "Protégez votre sauvegarde avec une phrase de passe"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Sinon, protégez votre sauvegarde avec une clé de récupération, en la conservant dans un endroit sûr."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Avancé) Configurer avec la clé de récupération"; +"key_backup_setup_success_title" = "Terminé !"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Vos clés sont en cours de sauvegarde.\n\nVotre clé de récupération est une mesure de précaution. Vous pouvez l'utiliser pour restaurer l'accès à vos messages chiffrés si vous oubliez votre phrase de passe.\n\nConservez votre clé de récupération dans un lieu très sûr, comme un gestionnaire de mots de passe (ou un coffre-fort)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Sauvegarder la clé de récupération"; +"key_backup_setup_success_from_passphrase_done_action" = "Terminé"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Vos clés sont en cours de sauvegarde.\n\nFaites une copie de cette clé de récupération et conservez-la en lieu sûr."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Clé de récupération"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "En faire une copie"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "J'ai fait une copie"; +"key_backup_recover_invalid_passphrase_title" = "Phrase de passe de récupération incorrecte"; +"key_backup_recover_invalid_passphrase" = "La sauvegarde n'a pas pu être déchiffrée avec cette phrase de passe : vérifiez que vous avez saisi la bonne phrase de passe de récupération."; +"key_backup_recover_invalid_recovery_key_title" = "La clé de récupération ne correspond pas"; +"key_backup_recover_invalid_recovery_key" = "La sauvegarde n'a pas pu être déchiffrée avec cette clé : vérifiez que vous avez saisi la bonne clé de récupération."; +"key_backup_setup_banner_title" = "Ne perdez jamais vos messages chiffrés"; +"key_backup_setup_banner_subtitle" = "Commencez à utiliser la sauvegarde de clés"; +"key_backup_recover_banner_title" = "Ne perdez jamais vos messages chiffrés"; +"key_backup_recover_banner_subtitle" = "Utilisez la sauvegarde de clés"; +"sign_out_existing_key_backup_alert_title" = "Voulez-vous vraiment vous déconnecter ?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Se déconnecter"; +"sign_out_non_existing_key_backup_alert_title" = "Vous n'aurez plus accès à vos messages chiffrés si vous vous déconnectez maintenant"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Commencer à utiliser la sauvegarde de clés"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Je ne veux pas de mes messages chiffrés"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Vous perdrez vos messages chiffrés"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Vous n'aurez plus accès à vos messages chiffrés sauf si vous sauvegardez vos clés avant de vous déconnecter."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Se déconnecter"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Sauvegarde"; +"sign_out_key_backup_in_progress_alert_title" = "Sauvegarde de clés en cours. Si vous vous déconnectez maintenant vous n'aurez plus accès à vos messages chiffrés."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Je ne veux plus de mes messages chiffrés"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Je vais patienter"; From 1f7f41f91a9b315cde3df10ea37d376d2c65dec8 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Fri, 15 Feb 2019 09:23:29 +0000 Subject: [PATCH 221/244] Translated using Weblate (Albanian) Currently translated at 99.5% (605 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/sq/ --- Riot/Assets/sq.lproj/Vector.strings | 62 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index 1626f5cb4..31538a2ad 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -553,13 +553,13 @@ "settings_flair" = "Shfaq simbole, kur lejohet"; "room_details_flair_section" = "Shfaq simbole për bashkësi"; "auth_accept_policies" = "Ju lutemi, shqyrtoni dhe pranoni rregullat e këtij shërbyesi Home:"; -"settings_key_backup" = "RIKTHIM MESAZHESH TË SIGURT"; +"settings_key_backup" = "KOPJERUAJTE KYÇI"; "settings_key_backup_info_checking" = "Po kontrollohet…"; -"settings_key_backup_info_none" = "Rikthimi i Mesazheve të Sigurt s’është rregulluar."; +"settings_key_backup_info_none" = "Kyçet tuaj nuk po kopjeruhen nga kjo pajisje."; "settings_key_backup_info_version" = "Version Kopjeruajtjeje Kyçesh: %@"; "settings_key_backup_info_algorithm" = "Algoritëm: %@"; -"settings_key_backup_info_valid" = "Rikthimi i Mesazheve të Sigurt për këtë pajisje është rregulluar si duhet."; -"settings_key_backup_info_not_valid" = "Rikthimi i Mesazheve të Sigurt s’është aktiv në këtë pajisje."; +"settings_key_backup_info_valid" = "Kjo pajisje po bën kopjeruajtje të kyçeve tuaja."; +"settings_key_backup_info_not_valid" = "Kjo pajisje nuk po bën kopjeruajtje të kyçeve tuaja."; "settings_key_backup_info_progress" = "Po kopjeruhen kyçet për %@…"; "settings_key_backup_info_progress_done" = "U kopjeruajtën krejt kyçet"; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Për të përdorur Rikthim Mesazhesh të Sigurt në këtë pajisje, verifikoni tani %@."; @@ -570,22 +570,22 @@ "settings_key_backup_info_trust_signature_valid_device_unverified" = "Kopjeruajtja ka nënshkrim nga %@"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "Kopjeruajtja ka një nënshkrim të pavlefshëm prej %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "Kopjeruajtja ka një nënshkrim të pavlefshëm prej %@"; -"settings_key_backup_button_create" = "Rregulloni Rikthim Mesazhesh të Sigurt"; -"settings_key_backup_button_restore" = "Riktheje kopjeruajtjen"; -"settings_key_backup_button_delete" = "Fshije kopjeruajtjen"; +"settings_key_backup_button_create" = "Fillo të përdorësh Kopjeruajtje Kyçesh"; +"settings_key_backup_button_restore" = "Riktheje prej Kopjeruajtje"; +"settings_key_backup_button_delete" = "Fshije Kopjeruajtjen"; "settings_key_backup_button_verify" = "Verifikoje"; "settings_key_backup_delete_confirmation_prompt_title" = "Fshije Kopjeruajtjen"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Të fshihen nga shërbyesi kyçet e kopjeruajtur të fshehtëzimit? S’do të jeni më në gjendje të përdorni kyçin tuaj të rikthimeve për lexim historiku mesazhesh të fshehtëzuar"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Jeni i sigurt? Do të humbni mesazhet tuaj të fshehtëzuar, nëse kopjeruajtja për kyçet tuaj nuk bëhet si duhet."; "room_does_not_exist" = "%@ nuk ekziston"; -"key_backup_setup_title" = "Rikthim Mesazhesh"; +"key_backup_setup_title" = "Kopjeruajtje Kyçi"; "key_backup_setup_skip_action" = "Anashkaloje"; "key_backup_setup_skip_alert_title" = "A jeni i sigurt?"; "key_backup_setup_skip_alert_message" = "Nëse dilni nga llogaria, ose nëse humbni pajisjen tuaj, mund të humbni mesazhe të sigurt."; "key_backup_setup_skip_alert_skip_action" = "Anashkaloje"; "key_backup_setup_intro_title" = "Mos humbni kurrë mesazhe të fshehtëzuar"; -"key_backup_setup_intro_info" = "Ujdisni Rikthim të Mesazheve të Sigurt, për raste kur humbni ose bëni daljen nga kjo pajisje."; +"key_backup_setup_intro_info" = "Mesazhet në dhoma të fshehtëzuara sigurohen me fshehtëzim skaj-më-skaj. Vetëm ju dhe marrësi(t) keni kyçet për leximin e këtyre mesazheve.\n\nBëni një kopjeruajtje të sigurt të kyçeve tuaj, për të shmangur humbjen e tyre."; "key_backup_setup_intro_setup_action" = "Rregulloje"; -"key_backup_setup_passphrase_info" = "Sigurojeni historikun tuaj të mesazheve të fshehtëzuar me një Frazëkalim Rikthimesh.\n\nDo t’ju duhet, nëse dilni nga llogaria, ose nëse nuk hyni dot në pajisje."; +"key_backup_setup_passphrase_info" = "Do të depozitojmë një kopje të fshehtëzuar të kyçeve tuaj në shërbyesin tonë. Mbrojeni kopjeruajtjen tuaj me një frazëkalim, për ta mbajtur të parrezikuar.\n\nPër maksimumin e sigurisë, ky duhet të jetë i ndryshëm nga fjalëkalimi juaj për llogarinë."; "key_backup_setup_passphrase_passphrase_title" = "Jepeni"; "key_backup_setup_passphrase_passphrase_placeholder" = "Jepni frazëkalimin"; "key_backup_setup_passphrase_passphrase_valid" = "Bukur!"; @@ -594,7 +594,7 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Ripohoni frazëkalimin"; "key_backup_setup_passphrase_confirm_passphrase_valid" = "Bukur!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Frazëkalimet nuk përputhen"; -"key_backup_setup_passphrase_set_passphrase_action" = "Caktoni frazëkalim rikthimesh"; +"key_backup_setup_passphrase_set_passphrase_action" = "Caktoni Frazëkalim"; "key_backup_setup_recovery_key_info" = "Bëni një kopje të këtij Kyçi Rikthimesh dhe ruajeni diku.\n\nSi rrjet sigurie, mund ta përdorni për të rikthyer historikun e mesazheve tuaj të fshehtëzuar, nëse harroni Frazëkalimin e Rikthimeve."; "key_backup_setup_recovery_key_recovery_key_title" = "Kyç Rikthimesh"; "key_backup_setup_recovery_key_make_copy_action" = "Bëni një Kopje"; @@ -620,3 +620,41 @@ "key_backup_setup_banner_title_part2" = " që të mos humbni kurrë mesazhe të fshehtëzuar"; "key_backup_recover_banner_title_part1" = "Xhironi Rikthim Mesazhesh të Sigurt"; "key_backup_recover_banner_title_part2" = " që të lexoni historik mesazhesh të fshehtëzuar në këtë pajisje"; +"settings_key_backup_info" = "Mesazhet e fshehtëzuar sigurohen me fshehtëzim skaj-më-skaj. Vetëm ju dhe marrësi(t) kanë kyçet për të lexuar këto mesazhe."; +"settings_key_backup_info_signout_warning" = "Kopjeruajini kyçet tuaj, përpara se të dilni, që të shmangni humbjen e tyre."; +"settings_key_backup_button_use" = "Përdor kopjeruajtje kyçesh"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Fillo të përdorësh Kopjeruajtje Kyçesh"; +"key_backup_setup_intro_setup_action_with_existing_backup" = "Përdor Kopjeruajtje Kyçesh"; +"key_backup_setup_passphrase_title" = "Sigurojeni kopjeruajtjen tuaj me një Frazëkalim"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Ose, sigurojeni kopjeruajtjen tuaj me një Kyç Rikthimesh, duke e ruajtur këtë diku të parrezikuar."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Të mëtejshme) Rregullojeni me një Kyç Rikthimesh"; +"key_backup_setup_success_title" = "Sukses!"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Po bëhet kopjeruajtja për kyçet tuaj.\n\nKyçi juaj i rikthimeve është një lloj rrjeti sigurie - mund ta përdorni për të rifituar hyrje te mesazhet tuaj të fshehtëzuar, nëse harroni frazëkalimin tuaj.\n\nMbajeni kyçin tuaj të rikthimeve diku shumë të sigurt, bie fjala, nën një përgjegjës fjalëkalimesh (ose në një kasafortë)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Ruani Kyç Rikthimesh"; +"key_backup_setup_success_from_passphrase_done_action" = "U krye"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Po bëhet kopjeruajtja për kyçet tuaj.\n\nBëni një kopje të këtij kyçi rikthimesh dhe mbajeni të parrezikuar."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Kyç Rikthimesh"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Bëni një Kopje"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Kam bërë një kopje"; +"key_backup_recover_invalid_passphrase_title" = "Frazëkalim Rikthimi i Pasaktë"; +"key_backup_recover_invalid_passphrase" = "S’u shfshehtëzua dot kopjeruajtja me këtë frazëkalim: ju lutemi, verifikoni që dhatë frazëkalimin e duhur të rikthimeve."; +"key_backup_recover_invalid_recovery_key_title" = "Mospërputhje Kyçesh Rikthimi"; +"key_backup_recover_invalid_recovery_key" = "Nuk u shfshehtëzua dot kopjeruajtja me këtë kyç: ju lutemi, verifikoni që dhatë kyçin e duhur të rikthimeve."; +"key_backup_setup_banner_title" = "Mos humbni kurrë mesazhe të fshehtëzuar"; +"key_backup_setup_banner_subtitle" = "Fillo të përdorësh Kopjeruajtje Kyçesh"; +"key_backup_recover_banner_title" = "Mos humbni kurrë mesazhe të fshehtëzuar"; +"key_backup_recover_banner_subtitle" = "Përdor Kopjeruajtje Kyçesh"; +"sign_out_existing_key_backup_alert_title" = "Jeni i sigurt se doni të dilni?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Dilni"; +"sign_out_non_existing_key_backup_alert_title" = "Nëse dilni tani nga llogaria, do të humbni mesazhet tuaj të sigurt"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Fillo të përdorësh Kopjeruajtje Kyçesh"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Nuk i dua mesazhet e mia të fshehtëzuar"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Do të humbni mesazhet tuaj të fshehtëzuar"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Do të humbni hyrjen te mesazhet tuaj të fshehtëzuar, veç në bëfshi kopjeruajtje të kyçeve tuaj, përpara se të dilni nga llogaria."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Dilni"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Kopjeruajtje"; +"sign_out_key_backup_in_progress_alert_title" = "Kopjeruajtja e kyçeve po kryhet. Nëse dilni tani nga llogaria, do të humbni hyrjen te mesazhet tuaj të fshehtëzuar."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Nuk i dua mesazhet e mia të fshehtëzuar"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Do të pres"; From c5f92052591f05d89068bdbb1b87c8ea17bf9562 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 15 Feb 2019 12:42:07 +0100 Subject: [PATCH 222/244] Fix sign out warning presentation on iPad --- .../Modules/Settings/SettingsViewController.m | 6 ++++- .../SignOut/SignOutAlertPresenter.swift | 24 +++++++++++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 6beb5db68..769fbad20 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -2711,7 +2711,11 @@ SignOutAlertPresenterDelegate> self.signOutButton = (UIButton*)sender; MXKeyBackupState backupState = self.mainSession.crypto.backup.state; - [self.signOutAlertPresenter presentFor:backupState from:self animated:YES]; + [self.signOutAlertPresenter + presentFor:backupState + from:self + sourceView:self.signOutButton + animated:YES]; } - (void)onRemove3PID:(NSIndexPath*)path diff --git a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift index 34074f043..a29a8bc5a 100644 --- a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift +++ b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift @@ -29,6 +29,7 @@ final class SignOutAlertPresenter: NSObject { // MARK: Private private weak var presentingViewController: UIViewController? + private weak var sourceView: UIView? // MARK: Public @@ -36,7 +37,8 @@ final class SignOutAlertPresenter: NSObject { // MARK: - Public - func present(for keyBackupState: MXKeyBackupState, from viewController: UIViewController, animated: Bool) { + func present(for keyBackupState: MXKeyBackupState, from viewController: UIViewController, sourceView: UIView?, animated: Bool) { + self.sourceView = sourceView self.presentingViewController = viewController switch keyBackupState { @@ -65,7 +67,7 @@ final class SignOutAlertPresenter: NSObject { alertContoller.addAction(signoutAction) alertContoller.addAction(cancelAction) - self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + self.present(alertController: alertContoller, animated: animated) } private func presentNonExistingBackupAlert(animated: Bool) { @@ -87,7 +89,7 @@ final class SignOutAlertPresenter: NSObject { alertContoller.addAction(setUpKeyBackupAction) alertContoller.addAction(cancelAction) - self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + self.present(alertController: alertContoller, animated: animated) } private func presentNonExistingBackupSignOutConfirmationAlert(animated: Bool) { @@ -106,7 +108,7 @@ final class SignOutAlertPresenter: NSObject { alertContoller.addAction(signOutAction) alertContoller.addAction(setUpKeyBackupAction) - self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + self.present(alertController: alertContoller, animated: animated) } private func presentBackupInProgressAlert(animated: Bool) { @@ -123,6 +125,18 @@ final class SignOutAlertPresenter: NSObject { alertContoller.addAction(discardKeyBackupAction) alertContoller.addAction(cancelAction) - self.presentingViewController?.present(alertContoller, animated: true, completion: nil) + self.present(alertController: alertContoller, animated: animated) + } + + private func present(alertController: UIAlertController, animated: Bool) { + + // Configure source view when alert controller is presented with a popover + if let sourceView = self.sourceView, let popoverPresentationController = alertController.popoverPresentationController { + popoverPresentationController.sourceView = sourceView + popoverPresentationController.sourceRect = sourceView.bounds + popoverPresentationController.permittedArrowDirections = [.down, .up] + } + + self.presentingViewController?.present(alertController, animated: animated, completion: nil) } } From 034649d949530c482180df345f184d5f497fd5f4 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Fri, 15 Feb 2019 12:28:40 +0000 Subject: [PATCH 223/244] Translated using Weblate (Hungarian) Currently translated at 100.0% (608 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/hu/ --- Riot/Assets/hu.lproj/Vector.strings | 62 +++++++++++++++++++++++------ 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index aec3efb48..0e2d505b9 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -246,7 +246,7 @@ "room_replacement_information" = "Ezt a szobát lecserélték és már nem aktív."; "room_replacement_link" = "A beszélgetés itt folytatódik."; "room_predecessor_information" = "Ez a szoba egy másik megbeszélés folytatása."; -"room_predecessor_link" = "Kattints ide a régi üzenetek megtekintéséhez."; +"room_predecessor_link" = "Koppints ide a régi üzenetek megtekintéséhez."; // Unknown devices "unknown_devices_alert_title" = "A szoba ismeretlen eszközöket tartalmaz"; "unknown_devices_alert" = "A szobában vannak ellenőrizetlen eszközök.\nEz azt jelenti, hogy nem garantálható, hogy az eszköz azé akiének mondja magát.\nJavasoljuk, hogy menj végig az ellenőrzési folyamaton mielőtt folytatod, de ha azt szeretnéd újraküldheted az üzenetet ellenőrzés nélkül is."; @@ -562,13 +562,13 @@ "room_resource_usage_limit_reached_message_2" = "néhány felhasználó nem tud majd bejelentkezni."; "room_resource_usage_limit_reached_message_contact_3" = " hogy korlátot megemeljék."; "auth_accept_policies" = "A Matrix szerver felhasználási feltételeit kérlek nézd át és fogadd el:"; -"settings_key_backup" = "BIZTONSÁGOS ÜZENET VISSZAÁLLÍTÁS"; +"settings_key_backup" = "KULCS MENTÉS"; "settings_key_backup_info_checking" = "Ellenőrzés..."; -"settings_key_backup_info_none" = "A Biztonságos Üzenet Visszaállítás nincs beállítva."; +"settings_key_backup_info_none" = "A kulcsaid nem kerülnek elmentésre erről az eszközről."; "settings_key_backup_info_version" = "Kulcs mentés verzió: %@"; "settings_key_backup_info_algorithm" = "Algoritmus: %@"; -"settings_key_backup_info_valid" = "Biztonságos Üzenet Visszaállítás megfelelően van beállítva ezen az eszközön."; -"settings_key_backup_info_not_valid" = "A Biztonságos Üzenet Visszaállítás nincs aktiválva ezen az eszközön."; +"settings_key_backup_info_valid" = "Ez az eszköz elmenti a kulcsaidat."; +"settings_key_backup_info_not_valid" = "Ez az eszköz nem menti el a kulcsaidat."; "settings_key_backup_info_progress" = "%@ kulcsok mentése..."; "settings_key_backup_info_progress_done" = "Minden kulcs elmentve"; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "A Biztonságos Üzenet Visszaállítás használatához ellenőrizd ezt: %@."; @@ -579,22 +579,22 @@ "settings_key_backup_info_trust_signature_valid_device_unverified" = "A mentés rendelkezik aláírással ettől: %@"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "A mentésnek érvénytelen aláírása van ettől: %@"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "A mentésnek érvénytelen aláírása van ettől: %@"; -"settings_key_backup_button_create" = "Biztonságos Üzenet Visszaállítás beállítása"; -"settings_key_backup_button_restore" = "Mentés visszaállítás"; +"settings_key_backup_button_create" = "Kulcs mentés használata"; +"settings_key_backup_button_restore" = "Visszaállítás mentésből"; "settings_key_backup_button_delete" = "Mentés törlése"; "settings_key_backup_button_verify" = "Ellenőrzés"; "settings_key_backup_delete_confirmation_prompt_title" = "Mentés törlése"; -"settings_key_backup_delete_confirmation_prompt_msg" = "Letörlöd az elmentett titkosítási kulcsokat a szerverről? Ezután már nem tudod használni a visszaállítási kulcsodat, hogy elolvasd a régi titkosított üzeneteidet"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Biztos vagy benne? Elveszted a titkosított üzeneteidet ha a kulcsok nincsenek megfelelően elmentve."; "room_does_not_exist" = "%@ nem létezik"; -"key_backup_setup_title" = "Üzenet Visszaállítás"; +"key_backup_setup_title" = "Kulcs Mentés"; "key_backup_setup_skip_action" = "Kihagy"; "key_backup_setup_skip_alert_title" = "Biztos?"; "key_backup_setup_skip_alert_message" = "Ha kilépsz vagy elhagyod az eszközöd nem férsz majd hozzá a biztonságos üzeneteidhez."; "key_backup_setup_skip_alert_skip_action" = "Kihagy"; "key_backup_setup_intro_title" = "Soha ne veszítsd el a titkosított üzeneteidet"; -"key_backup_setup_intro_info" = "Kilépéshez vagy ha elvesztenéd ezt az eszközt, állítsd be a Biztonságos Üzenet Visszaállítást."; +"key_backup_setup_intro_info" = "Titkosított szobákban az üzenetek végponttól-végpontig vannak titkosítva. Csak te és a címzettek rendelkeznek a kulcsokkal az üzenetek visszafejtéséhez.\n\nMentsd el megfelelően a kulcsaidat, hogy ne veszítsd el őket."; "key_backup_setup_intro_setup_action" = "Beállítás"; -"key_backup_setup_passphrase_info" = "Helyezd biztonságba a titkosított üzeneteidet a Visszaállítási Jelmondattal.\n\nSzükséged lesz rá, ha kilépsz vagy elveszted az eszközöd."; +"key_backup_setup_passphrase_info" = "A kulcsaid titkosított másolatát elmentjük a szerverünkre. Védd a mentést jelmondattal.\n\nA maximális biztonság érdekében ez a jelmondat különbözzön a felhasználói fiókhoz használttól."; "key_backup_setup_passphrase_passphrase_title" = "Bead"; "key_backup_setup_passphrase_passphrase_placeholder" = "Jelmondat bevitele"; "key_backup_setup_passphrase_passphrase_valid" = "Szuper!"; @@ -603,7 +603,7 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Jelmondat megerősítése"; "key_backup_setup_passphrase_confirm_passphrase_valid" = "Szuper!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "A jelmondatok nem egyeznek meg"; -"key_backup_setup_passphrase_set_passphrase_action" = "Visszaállítási jelmondat beállítása"; +"key_backup_setup_passphrase_set_passphrase_action" = "Jelmondat beállítása"; "key_backup_setup_recovery_key_info" = "Erről a Visszaállítási Kulcsról készíts egy másolatot és őrizd meg biztonságos helyen.\n\nEz egy további biztosíték, amivel újra hozzáférhetsz a titkosított üzeneteidhez ha elfelejtenéd a Visszaállítási Jelmondatot."; "key_backup_setup_recovery_key_recovery_key_title" = "Visszaállítási Kulcs"; "key_backup_setup_recovery_key_make_copy_action" = "Másolat készítése"; @@ -629,3 +629,41 @@ "key_backup_setup_banner_title_part2" = " , hogy sose veszítsd el a titkosított üzeneteidet"; "key_backup_recover_banner_title_part1" = "Biztonságos Üzenet Visszaállítás futtatása"; "key_backup_recover_banner_title_part2" = " , hogy elolvashasd a titkosított üzeneteidet ezen az eszközön"; +"settings_key_backup_info" = "Titkosított üzenetek végponttól-végpontig vannak titkosítva. Csak te és a címzettek rendelkeznek a visszafejtéshez szükséges kulcsokkal."; +"settings_key_backup_info_signout_warning" = "Mentsd el a kulcsaidat a kilépés előtt, hogy ne veszítsd el őket."; +"settings_key_backup_button_use" = "Kulcs mentés használata"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Kulcs mentés használata"; +"key_backup_setup_intro_setup_action_with_existing_backup" = "Használd a Kulcs mentést"; +"key_backup_setup_passphrase_title" = "Védd a mentést jelmondattal"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Vagy védd a mentést egy Visszaállítási Kulccsal és tedd el egy biztonságos helyre."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Haladó) Visszaállítási Kulcs beállítása"; +"key_backup_setup_success_title" = "Sikerült!"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "A kulcsaid elmentésre kerülnek.\n\nA Visszaállítási Kulcs egy olyan biztonsági elem amivel akkor is visszaállíthatod a hozzáférésed a titkosított üzenetekhez ha a jelmondatot elfelejted.\n\nA Visszaállítási kulcsot biztonságos helyen tárold, mint pl. egy jelszókezelőben (vagy széfben)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Visszaállítási Kulcs beállítása"; +"key_backup_setup_success_from_passphrase_done_action" = "Kész"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "A kulcsaid elmentésre kerülnek.\n\nMásold ki a Visszaállítási Kulcsot és tárold biztonságos helyen."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Visszaállítási Kulcs"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Készíts másolatot"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Készítettem másolatot"; +"key_backup_recover_invalid_passphrase_title" = "Helytelen Visszaállítási Jelmondat"; +"key_backup_recover_invalid_passphrase" = "A mentést nem lehet visszafejteni ezzel a jelmondattal: kérlek ellenőrizd, hogy a megfelelő visszaállítási jelmondatot adtad-e meg."; +"key_backup_recover_invalid_recovery_key_title" = "A Visszaállítási Kulcsok nem egyeznek meg"; +"key_backup_recover_invalid_recovery_key" = "A mentést nem lehet ezzel a kulccsal visszafejteni: kérlek ellenőrizd, hogy a megfelelő kulcsot adtad-e meg."; +"key_backup_setup_banner_title" = "Soha ne veszítsd el a titkosított üzeneteidet"; +"key_backup_setup_banner_subtitle" = "Kulcs mentés használata"; +"key_backup_recover_banner_title" = "Soha ne veszítsd el a titkosított üzeneteidet"; +"key_backup_recover_banner_subtitle" = "Kulcs mentés használata"; +"sign_out_existing_key_backup_alert_title" = "Biztos, hogy ki szeretnél jelentkezni?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Kijelentkezés"; +"sign_out_non_existing_key_backup_alert_title" = "Elveszted a hozzáférést a titkosított üzeneteidhez ha most kijelentkezel"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Kulcs mentés használatának megkezdése"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Nincs szükségem a titkosított üzeneteimre"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Elveszted minden titkosított üzenetedet"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Elveszted minden titkosított üzenetedet ha nem mented el a kulcsaidat kijelentkezés előtt."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Kijelentkezés"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Mentés"; +"sign_out_key_backup_in_progress_alert_title" = "Kulcsok mentése folyamatban van. Ha most kijelentkezel akkor elveszted a titkosított üzeneteidet."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Nincs szükségem a titkosított üzeneteimre"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Inkább várok"; From 17e4ad0918b766681a96b1232861acad1e0ab734 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 15 Feb 2019 13:45:09 +0100 Subject: [PATCH 224/244] Fix: Jump to first unread message doesn't show up #2218 --- Riot/Modules/Room/RoomViewController.m | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 4a4c71014..48a97ecb5 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -656,11 +656,13 @@ [expandedHeader layoutIfNeeded]; } } + + self.edgesForExtendedLayout = UIRectEdgeAll; // Adjust the top constraint of the bubbles table CGRect frame = expandedHeader.bottomBorderView.frame; self.expandedHeaderContainerHeightConstraint.constant = frame.origin.y + frame.size.height; - + self.bubblesTableViewTopConstraint.constant = self.expandedHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top; self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.expandedHeaderContainerHeightConstraint.constant; } @@ -683,17 +685,23 @@ [previewHeader layoutIfNeeded]; } } - + + self.edgesForExtendedLayout = UIRectEdgeAll; + // Adjust the top constraint of the bubbles table CGRect frame = previewHeader.bottomBorderView.frame; self.previewHeaderContainerHeightConstraint.constant = frame.origin.y + frame.size.height; - + self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.mxk_adjustedContentInset.top; self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant; } else { - self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top; + // In non expanded header mode, the navigation bar is opaque + // The table view must not display behind it + self.edgesForExtendedLayout = UIRectEdgeLeft | UIRectEdgeBottom | UIRectEdgeRight; + + self.jumpToLastUnreadBannerContainerTopConstraint.constant = self.bubblesTableView.mxk_adjustedContentInset.top; // no expanded } [self refreshMissedDiscussionsCount:YES]; From f2be256ce31e6ee16453ea1d81d069e5e12c9305 Mon Sep 17 00:00:00 2001 From: Nad Chishtie Date: Fri, 15 Feb 2019 13:55:36 +0000 Subject: [PATCH 225/244] Updated assets to use new palette. --- .../call_audio_mute_on_icon.png | Bin 956 -> 890 bytes .../call_audio_mute_on_icon@2x.png | Bin 2157 -> 2013 bytes .../call_audio_mute_on_icon@3x.png | Bin 3385 -> 3220 bytes .../call_chat_icon.png | Bin 372 -> 370 bytes .../call_chat_icon@2x.png | Bin 744 -> 722 bytes .../call_chat_icon@3x.png | Bin 1111 -> 1106 bytes .../call_hangup_icon.png | Bin 963 -> 1200 bytes .../call_hangup_icon@2x.png | Bin 2140 -> 2757 bytes .../call_hangup_icon@3x.png | Bin 3381 -> 4436 bytes .../call_speaker_on_icon.png | Bin 662 -> 615 bytes .../call_speaker_on_icon@2x.png | Bin 1387 -> 1331 bytes .../call_speaker_on_icon@3x.png | Bin 2102 -> 2001 bytes .../call_video_mute_on_icon.png | Bin 879 -> 817 bytes .../call_video_mute_on_icon@2x.png | Bin 1919 -> 1803 bytes .../call_video_mute_on_icon@3x.png | Bin 3064 -> 2867 bytes .../camera_switch.imageset/camera_switch.png | Bin 1029 -> 967 bytes .../camera_switch@2x.png | Bin 2162 -> 1997 bytes .../camera_switch@3x.png | Bin 3194 -> 3007 bytes .../Common/back_icon.imageset/back_icon.png | Bin 1142 -> 602 bytes .../back_icon.imageset/back_icon@2x.png | Bin 2070 -> 1289 bytes .../back_icon.imageset/back_icon@3x.png | Bin 3266 -> 2308 bytes .../placeholder.imageset/placeholder.png | Bin 838 -> 853 bytes .../placeholder.imageset/placeholder@2x.png | Bin 1779 -> 1735 bytes .../placeholder.imageset/placeholder@3x.png | Bin 3218 -> 3193 bytes .../remove_icon.imageset/remove_icon.png | Bin 578 -> 692 bytes .../remove_icon.imageset/remove_icon@2x.png | Bin 1435 -> 1799 bytes .../remove_icon.imageset/remove_icon@3x.png | Bin 863 -> 965 bytes .../selection_tick.png | Bin 621 -> 675 bytes .../selection_tick@2x.png | Bin 1112 -> 1187 bytes .../selection_tick@3x.png | Bin 1695 -> 1840 bytes .../selection_untick.png | Bin 1324 -> 769 bytes .../selection_untick@2x.png | Bin 2336 -> 1665 bytes .../selection_untick@3x.png | Bin 3785 -> 2927 bytes .../add_group_participant.png | Bin 2018 -> 2090 bytes .../add_group_participant@2x.png | Bin 4307 -> 4588 bytes .../add_group_participant@3x.png | Bin 6492 -> 7309 bytes .../create_group.imageset/create_group.png | Bin 2935 -> 1702 bytes .../create_group.imageset/create_group@2x.png | Bin 5773 -> 3998 bytes .../create_group.imageset/create_group@3x.png | Bin 1133 -> 6377 bytes .../remove_icon_blue.png | Bin 571 -> 708 bytes .../remove_icon_blue@2x.png | Bin 1343 -> 1918 bytes .../remove_icon_blue@3x.png | Bin 871 -> 965 bytes .../E2E/e2e_blocked.imageset/e2e_blocked.png | Bin 323 -> 287 bytes .../e2e_blocked.imageset/e2e_blocked@2x.png | Bin 511 -> 529 bytes .../e2e_blocked.imageset/e2e_blocked@3x.png | Bin 726 -> 733 bytes .../directChatOff.imageset/directChatOff.png | Bin 2045 -> 1426 bytes .../directChatOff@2x.png | Bin 4491 -> 3471 bytes .../directChatOff@3x.png | Bin 5090 -> 4964 bytes .../directChatOn.imageset/directChatOn.png | Bin 1905 -> 1205 bytes .../directChatOn.imageset/directChatOn@2x.png | Bin 3462 -> 2542 bytes .../directChatOn.imageset/directChatOn@3x.png | Bin 3221 -> 3267 bytes .../favourite.imageset/favourite.png | Bin 1159 -> 1005 bytes .../favourite.imageset/favourite@2x.png | Bin 2481 -> 1869 bytes .../favourite.imageset/favourite@3x.png | Bin 3914 -> 2770 bytes .../favouriteOff.imageset/favouriteOff.png | Bin 1256 -> 1193 bytes .../favouriteOff.imageset/favouriteOff@2x.png | Bin 2946 -> 2757 bytes .../favouriteOff.imageset/favouriteOff@3x.png | Bin 4672 -> 4440 bytes .../leave.imageset/leave.png | Bin 419 -> 401 bytes .../leave.imageset/leave@2x.png | Bin 697 -> 665 bytes .../leave.imageset/leave@3x.png | Bin 860 -> 853 bytes .../notifications.imageset/notifications.png | Bin 1136 -> 1072 bytes .../notifications@2x.png | Bin 2530 -> 2400 bytes .../notifications@3x.png | Bin 4042 -> 3820 bytes .../notificationsOff.png | Bin 1420 -> 1490 bytes .../notificationsOff@2x.png | Bin 3139 -> 3803 bytes .../notificationsOff@3x.png | Bin 5019 -> 5403 bytes .../priorityHigh.imageset/priorityHigh.png | Bin 427 -> 420 bytes .../priorityHigh.imageset/priorityHigh@2x.png | Bin 839 -> 778 bytes .../priorityHigh.imageset/priorityHigh@3x.png | Bin 1440 -> 1327 bytes .../priorityLow.imageset/priorityLow.png | Bin 436 -> 431 bytes .../priorityLow.imageset/priorityLow@2x.png | Bin 849 -> 791 bytes .../priorityLow.imageset/priorityLow@3x.png | Bin 1429 -> 1344 bytes .../Home/create_room.imageset/create_room.png | Bin 1479 -> 1170 bytes .../create_room.imageset/create_room@2x.png | Bin 3119 -> 3005 bytes .../create_room.imageset/create_room@3x.png | Bin 5157 -> 4868 bytes .../create_direct_chat.png | Bin 3170 -> 1649 bytes .../create_direct_chat@2x.png | Bin 5715 -> 3798 bytes .../create_direct_chat@3x.png | Bin 1595 -> 6070 bytes .../Room/Activities/error.imageset/error.png | Bin 666 -> 703 bytes .../Activities/error.imageset/error@2x.png | Bin 1231 -> 1419 bytes .../Activities/error.imageset/error@3x.png | Bin 1775 -> 1893 bytes .../newmessages.imageset/newmessages.png | Bin 731 -> 763 bytes .../newmessages.imageset/newmessages@2x.png | Bin 1255 -> 1445 bytes .../newmessages.imageset/newmessages@3x.png | Bin 1896 -> 2228 bytes .../scrolldown.imageset/scrolldown.png | Bin 869 -> 878 bytes .../scrolldown.imageset/scrolldown@2x.png | Bin 1618 -> 1677 bytes .../scrolldown.imageset/scrolldown@3x.png | Bin 2485 -> 2401 bytes .../Activities/scrollup.imageset/scrollup.png | Bin 852 -> 847 bytes .../scrollup.imageset/scrollup@2x.png | Bin 1533 -> 1661 bytes .../scrollup.imageset/scrollup@3x.png | Bin 2367 -> 2352 bytes .../Activities/typing.imageset/typing.png | Bin 834 -> 803 bytes .../Activities/typing.imageset/typing@2x.png | Bin 1704 -> 1684 bytes .../Activities/typing.imageset/typing@3x.png | Bin 2722 -> 2470 bytes .../upload_icon.imageset/upload_icon.png | Bin 554 -> 524 bytes .../upload_icon.imageset/upload_icon@2x.png | Bin 1182 -> 1120 bytes .../upload_icon.imageset/upload_icon@3x.png | Bin 1900 -> 1799 bytes .../voice_call_icon.png | Bin 1021 -> 971 bytes .../voice_call_icon@2x.png | Bin 2447 -> 2300 bytes .../voice_call_icon@3x.png | Bin 3826 -> 3683 bytes .../add_participant.png | Bin 2105 -> 1099 bytes .../add_participant@2x.png | Bin 4418 -> 2258 bytes .../add_participant@3x.png | Bin 6709 -> 3245 bytes .../Room/apps-icon.imageset/apps-icon.png | Bin 578 -> 651 bytes .../Room/apps-icon.imageset/apps-icon@2x.png | Bin 977 -> 1220 bytes .../Room/apps-icon.imageset/apps-icon@3x.png | Bin 1043 -> 1259 bytes .../details_icon.imageset/details_icon.png | Bin 254 -> 245 bytes .../details_icon.imageset/details_icon@2x.png | Bin 517 -> 485 bytes .../details_icon.imageset/details_icon@3x.png | Bin 809 -> 823 bytes .../members_list_icon.png | Bin 1083 -> 448 bytes .../members_list_icon@2x.png | Bin 1666 -> 903 bytes .../members_list_icon@3x.png | Bin 1988 -> 1222 bytes .../remove_icon_pink.png | Bin 520 -> 697 bytes .../remove_icon_pink@2x.png | Bin 1219 -> 1704 bytes .../remove_icon_pink@3x.png | Bin 811 -> 962 bytes .../settings_icon.imageset/settings_icon.png | Bin 1173 -> 1099 bytes .../settings_icon@2x.png | Bin 2539 -> 2359 bytes .../settings_icon@3x.png | Bin 4035 -> 3790 bytes 117 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Riot/Assets/Images.xcassets/Call/call_audio_mute_on_icon.imageset/call_audio_mute_on_icon.png b/Riot/Assets/Images.xcassets/Call/call_audio_mute_on_icon.imageset/call_audio_mute_on_icon.png index 6b01ab28585e8b801a93c31dc948c0bc5c67b67d..013c41d5c99ad9d9ac3acad8b94c5d3cad4d46d3 100644 GIT binary patch delta 867 zcmV-p1DyQ42l@t(B!2{FK}|sb0I`n?{9y$E00S{eL_t(I5uKGwXp~nJ$N%Tvd1)bC z_$tk!(v>s|g9{fv5g*MajtP>5QfSp~iaQZaP0Wo6L`ZdG3ATkUirqvKof%!I3vGqA zB4|UQ(S;zQD7a9;nn|4R9{=Bjd3>KUUF5=W&%NiI-~G=$XMgSp{%<&!Fl%H#pz9fy z;^!|f_z|7%O|vx9%z^RVWp<6+fS|>fFziw4rCqeZbxgQVo8={%IZP(~eW1Z0cAmIa ziSfW$O!oh2llG?o*v5UW_{ww6bvITxe&j=eEJ3ygt0s02O_A~hlYOhIdo)aL@Q@Yx zva!PSqSXq$TYsMrv+r1&SWT7F;l3#h4p8i#U}knhW1vBXaWgSUZOOZY$f9t=6x?^5 zc6h?jGxEGKu$J1~@+v0peh{ENDCs7`UWUO711by^9w2Nkn9;51ajz>UM}hg{SrpC9 zinHN7?ow=@uT|A}ee=0Ze~{%}{#uERRN27nrsky;=YM;1!7a8Kxx{AiA~=KD#R}1V z^>I;!^`5wW&b3&@Wfgru+y$znuxJ~GDG`NnMs+>eyTr8Mx+j2~KBa_VBq@pW6>kg8`7Nt)alPnjNIkgc7K7&cL;&t&K5oyQ7u}@4!{vhKQ zD*LvYCVy-duT!u=s|ub~_i03c9{zV@(Sf}uUl5`umAXx3rwBV)P0IJTiONd+jeABD z9pdp@)kh;*l;ZSN$+R6s;dm!+sh!MM1lmw3516y5bO-moVI%LwXIL&qdsvw*^}vWi z^qddauww>xf+rvLMYM&%HkBH+$XzmR|VYWGpuqc|*F&jZ7U(a2dJlsd6%=vF+?=G;Ct_?X2Rj{D+kWAlSwP}!J& zTU^@S2v$xo@*n4>|0DI#1p8>j`?s6XJ$%33u~0kVOS%DF!w(kl(wvMy=U;J^AlNyuE|yYWz5}Xy9&K(;lKlVx002ovPDHLkV1nb}u`B=p delta 934 zcmV;X16lm~2D}H5B!2;OQb$4nuFf3k000AaNklh|M_*(S$!h&y9tt( z1CW7;S43mOz`)|Qν2C7>%kxbQj3;{-UOp*}*0jwELd62%QoY}~&z@mslEy`0nY zWs$xYpzTV<;-{6EzOCuh-=s>8QC?+?%8&;?eItOWPBni)RU z-yJuPEb-&LHGi2-eMZvVQno@jI~4^KV`_qGBSM;_9cAAg&z~4e?IfU&Ye}pqOGpx{ z0V$`FsJ2AN3lcRYvhma&kg&QI#EPEQ#N)DrYH}r;n}u9iKR2nR4z-p0V)18Q?5qg6 z7XqYAa=slg=DxqLxqZgpI6#;j8(c@moQvd4`}iws_kXQnW5S;4;5!rbHL&JMZh9RD z9rFVNT_%tlgp;fH!SLESd9rrGo;t z#OPqm{D0K@I!c&?ykTc`)?~3FAt5|Kr`Tjb%?-Ys7W20CR>5{JA>iRuEcu0>=wTXH zn?-EmQXlw!Zw*waNx0w&YTLhb(^Ft&Qy#7{*_^-ffBrd#GBDXnzo~rR}tlq-{dzo2shh6jwi@H8!qN z$627lc5HW94!w@!{=`T6{LM&Rb7}Vi>~;%wFUzVS5~*8-4fFrX+j5Xc+76ZMl?u)4 z)=Dbk&jR5)?&EqsbvNJLFD26d9?8tmyHd)%2(+8AA5|2)Wo-RTZ>eEInccM&oJ3bLT@lil6|_swFA+_)o`FWZY9{a zIMtH;I*f(i1qXjZX5tURY!f#kS@AXH`yDBhSTQ_(x_C@1= z%$6XW7to;!nrZ6+n`$+esqw!30%R3wOA^j{#Q*>R07*qo IM6N<$g1ijOHUIzs diff --git a/Riot/Assets/Images.xcassets/Call/call_audio_mute_on_icon.imageset/call_audio_mute_on_icon@2x.png b/Riot/Assets/Images.xcassets/Call/call_audio_mute_on_icon.imageset/call_audio_mute_on_icon@2x.png index 82744e7b9727772f2cb67a021410357e30404d79..215a080fcaf60ef55103a2a65b273e968a0e6186 100644 GIT binary patch delta 1999 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 delta 345 zcmV-f0jB=)0`vlqB!2;OQb$4nuFf3k0003lNklbF5XQf6HzFfh!_-A&rnN zW`=?J?YAEbL$~X%(MVH(8I*BIq2Ou6;+BSyhJG-xw7<*O|(e%9dOQa-0A7w-D&p!(cM^T?Lzp(GdL91^A}fG; z9EL^ms%6*ilNtBfU*s8NAA1l7&h_;jQH@v;Ho z0hF9G4%$d~u~O*uQh0jfkYTTLIq?S5jK}8U-E$3^dEef41~G+y%ZXik4Qy|d;3;4l rgV3xl49@_*?Y6X~mjvu)y)6F#8Q)j+7%SpK00000NkvXXu0mjfUzeqQ diff --git a/Riot/Assets/Images.xcassets/Call/call_chat_icon.imageset/call_chat_icon@2x.png b/Riot/Assets/Images.xcassets/Call/call_chat_icon.imageset/call_chat_icon@2x.png index dbb70a713fec2a7852f99e67ca0d5142401ccb5b..13fefb36cb5fcaeb91a8adbcce75ecbdc5839b71 100644 GIT binary patch delta 698 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 YPD?&|%GrWXz(Rt-)78&qol`;+07tF&1ONa4 delta 1090 zcma*e`8V4K008i>YtlSdh+**_9U`t$ikhQo5>zV$(KU`>nW3alA_QIcbrh+`dm8r@ z=LE0PQ9|`;b*?#LA*3rA<|sxM`sBGX-Ts2TeSZJUL*7A3%t57;U|$Ttn>F4A09BYD z?j|u^Nm`4K4A`@}Aj?kNx0i5zLrPlf!+jFOe}i{sZH zI8hhJ6!1_BwYt^1j(|0VHg$dtjXSTo&4V`jpk}?){#=i+IXQ1=!ef!QgymvR%HsR} z5la}YD*?r2n;zv*UB|F?{i%|Qi;!6~L(#qvSS2987eC76yw=`qE2?BdVAH_xMKmC3 zNuAps#CDLoh73BBlMgDNakX?SOfLDSE`bP7|3eqdwcQmWE0J;V`S42mXo5&ie_6NC zQ4SSFvNFYJevc!8vSqO7p)4(-XUD8FMg&a4+gyd`l5BoAtT{vyd;8Ipp^iT(!dl3i zvg`Hd_OP?~k>IfMSYQjm0HvIFdHB{kJo{&zXmeU2ItJpvzV6-Vplaw>_a#U$R4y_P zfT1*$d~~@Gcs^kEBt#X8&3Za&^wP88x8+EwEJ+ zQUDDSI54{~{iEcE8{MpLis2iYUfsYV$xL{M4~_;ukyBZ*SG&Sw4ef}@HH#@cxY8&)kpaH5N3XD!zR0tj|{X8unE))2k-7*JH1~fkPG=z&56Bm=%vp#CaMb7GdIG$ zc!aNhZB(-s8>L;@A-_zZ+s=PvjL)2EmMzT(B+h^)pyHe_L>%>17cng>7|idBpYD{o z(Z{^q?{!OnxlgX!@J|Li@^9A;tG_6pB%aD;q+<_-k>~T=9%x%FEh}eQWUT_uncb<4 zGQwAyTvr2B_+x{sQ=LqGr$n-Gm|~ChDI?NEJvOOel5QeRtIR6cp0tZ`LMl4}E=ffN z%^-qmTZS7w-N$ddFmZ^w=$gj;vP&|o8!Bu&Ryx}Z4vJ5?ht?YW%X~wcIdT$4sc|GQ zhN*qUEl1O`o}exZ2m8J@P$b!Tu}$if-Th;xY0G}F4Gz~!h|5h`gc8Lf9!(IBi_@=n zV|PF3-yL#!J5@#s88|sQ>$a#q5vVK%5I(9qfW9@~Sq!zEP@Gfg&~ZfF8{1_vUbNdW z_olawEs9GL9-ax9T(vl7oz_yyGLjypOJJ<|CL&e`U|h8%_r7fL<9B-5F&rx+6w=fc t?jEI-RyFGo=~LQ+MmK~vTQOI0Sqg2m_SNFhaOy+gUw+;JI36ZC=O4#%31R>M diff --git a/Riot/Assets/Images.xcassets/Call/call_hangup_icon.imageset/call_hangup_icon.png b/Riot/Assets/Images.xcassets/Call/call_hangup_icon.imageset/call_hangup_icon.png index 65359e9d8a145b3cf035bb99eb4b81630d499c87..159cf2ea3213cc033d2fd2025709b6a311e68e40 100644 GIT binary patch literal 1200 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 diff --git a/Riot/Assets/Images.xcassets/Call/call_hangup_icon.imageset/call_hangup_icon@2x.png b/Riot/Assets/Images.xcassets/Call/call_hangup_icon.imageset/call_hangup_icon@2x.png index f9d21fb6f33551db1b22e1c949ab6011cfe77ed4..ca996ebbf5587a73c0e66cee09f267c59f82d26d 100644 GIT binary patch literal 2757 zcmV;$3Oe+=00004XF*Lt006O% z3;baP000VnNklXg<;%M@|gJP_C_^TSUaUwJ5-s{@^IRc0!mv64cYxq zzkB~p_RsGA|Na{m+B@^-|L?u$oO`}|&pr2?yJ2!sq@?N#mOho%tm%_QO@=6A_3 z>bbRXn+p*am4uz7OQ3oxiDwNI9&bx0^bog%9<%Mg1RW_sh~J+_JoraY{$5iDIYUCP z63HGi=zTor$;(0V@GA62i6UR*aPxbYK;M)@_!3*CFgS!f(gL%Y1hWzJucPkhD&Ez6 zI)Qez1cF~eTNR1-LA+-t^k1@Szm?D{;2E+Lqff-le~9-?m`abHe3ukf4t2qib&@_1WE9MV^dWefxiz%g^+;`v?EwC^<}L8u z?V2x(gmDl|C8k`?$nRrQVe|9am`;oJzRIG4N|cla$2f_!f*7R#K?vn&B7vvLuy9951oLIC278ubY2tD-lw~EC zKf?*~8C4d1bLr zQcJ@k8`6F=b|gkL+K$+%ojXDwqko^K@ff!{(WdJI0E9ZUCPw!thZ~lfdoMMoWhLYd zO(Oc7NKKu#RSGnTht8!XO+lbMg!pUg0pLOH>c#jTheNAUkoIeegNSm6*~61$>{xSu z^dohyU~oTlmbZz~=J{zb@AA&cuGw*+%3Ae+EH2m7jr#Hhmx{M4<0J`kEgXrsv} zv)u|Xm*4ZO_8=r1>Fmk--0~_q`D!qqZlorxVh|?OjR?6GE3hdO8Q3rJA|*3EMLD@g zAW)8(#Yc(15mNr&^#y%0EB#nrDPxg)cE~C#1wi;zdbw` zX{qy>!SWwXE0k~Yy8A1|6~l3|?*a8~curBoD25x|?~Xf}DhUMa@hvQ^3IK;7S6H6R zVremWgIVK6QeHjT(qsE6(}FipUfy01sI%m6$O@+~%P9u?%Cls6`BK!wZSiTYf_ET4+h})b0VJB-K?d-&)Z$1Xo zLD1X)1y*oN!%9bb6?v+_O&wY!xNP8I@PEw!P@tVf7tM$TicVrO?sEj8q+uqj$g56N zgF%0AQ*fA)X$?s$wf@0H~J#n6wXf~ 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 S`p!`R0000SK;2G1!Z@;bShr+L%& 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 XV!+Dh;1HUG00000NkvXXu0mjfKdCk` diff --git a/Riot/Assets/Images.xcassets/Call/call_speaker_on_icon.imageset/call_speaker_on_icon@2x.png b/Riot/Assets/Images.xcassets/Call/call_speaker_on_icon.imageset/call_speaker_on_icon@2x.png index 0dec0daaeea2c86eb902cc1b314448dd46cce981..e77a0fe96f018a68539f0b7a06b1c737b0e41e1c 100644 GIT binary patch delta 1312 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 a9 diff --git a/Riot/Assets/Images.xcassets/Call/call_speaker_on_icon.imageset/call_speaker_on_icon@3x.png b/Riot/Assets/Images.xcassets/Call/call_speaker_on_icon.imageset/call_speaker_on_icon@3x.png index f65eebb867a2c3135eacdf98c02de68e121e426e..17aa6b00c2927c1878314dd7b2df3ffabf8adb8e 100644 GIT binary patch delta 2000 zcmV;>2QT=x5YZ2i7k@wq1^@s6uAHIc00004XF*Lt006O%3;baP000MwNkl5exk%^bI>m3KwC@IBGA!tmZz0u}H9ac{z z>e3ms$n)lEx0%*N0tPfk~DJCLr%uh?#FX%8pA z_nWvsE5YWt{o2Oc$${ zGW_HFzAhs~ICZNZH$>Y&LLT=5Bs6Gp=TY&RcYS-61!cO22Coe3Nzkit63G0do14ey z5(&(E`aEL0%9nlVbu5i@y&o8!a8etZPBYh@^K`jVr-z8zvi?rKh`ZZ$n}$1C?TB*qT+~*wxChRHL=tPvJEO{rX}jODDSeQSAIa!g!AVihjl& z(ZLJ;(qu|>ab6jwCS7je0(3bk__->xgAT|rOs1dcf%Pg1BN(N1FA*a_1r=c=Z}n_W(h zsuHKitw(9g((b-}FH)y43+{^D6ALL)ezRxSN`j~9s`cLTo1_tY(fzyRu)Z%`2?iqD zHP$N-CrBAmo?UQ=m|gWfT>bz9gO@L*NPors9>}CRtWLu#I4Oi8=Fx$bLs<$A5dh-MaPDb5j2r@s$PL30?}+efNy8;#)$D$tNQp6p?@VJ zUld+SodPj6ctijkHdhe~5-S7J0aI9RQ;yRyY%Q2H-d2nYBoTB{evC=;PYY5QelwH@4ym) zpE;HnP25YRvSEZ>T|isU;1XdM1b;@3LDG&AWFiJz{DL^qR1krM<62&0;V%4(xw{UIDZdYIrWdtT#NZuEoe7|l?}y%LqxdhJ1xv?Oq56UWhzU> z?_J}|UM1oOES;uVYf^DNyN7o{2t?v?R}_lW0US)5Kv()cgTriqHP1pbv;*FNjCQQB zN3_P`0|wmY-RQD45-z@dM*!tW@hT=sX_rhvYZL95h(n&jk)di%WPf_sL8|fLcLf5A zaTb#iRajBZCgKZew^>OiG!sl+$A+>%d`nSPM_QcckSo!+!!jBbnohgn%C|cFY-c`z zcs4ZDMh3J-Id>?91SDI9WFo=c_lQ zzC2UcST3Ick~|EF3xB$i7Ld>I;h{k|)l!3)d@>A^+@-TRiVe{7AmiE2YOka1==0~6 zW0iOV+1iDeNL%N`gocuTavTYyKDsb|m<&%R*mhV%l6EvYtb}Si&g)0000C literal 2102 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 YS`&T(K=vA=`2YX_07*qoM6N<$g5eK)b^rhX delta 856 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 DN_3=I diff --git a/Riot/Assets/Images.xcassets/Call/call_video_mute_on_icon.imageset/call_video_mute_on_icon@3x.png b/Riot/Assets/Images.xcassets/Call/call_video_mute_on_icon.imageset/call_video_mute_on_icon@3x.png index 1f721ca0facc232d2e2be3072ec003261fd8b155..ccdebb76020e60c837ec55452122ce849aba2597 100644 GIT binary patch literal 2867 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 R_9g%T002ovPDHLkV1l-OU;zLC literal 3064 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 T??o8Y00000NkvXXu0mjfW4GQi delta 1007 zcmV3{E@d;1V9j(VlH9uZF= z;FD%41oQ{TMwa4>??j$`d)W-P-jC}Ivv;o&Y$3#Ekm|9p+aEK-9la7P$a27kNU$qB zI{zXB0@4ht`!_A1KHBq?Kyex5>NBCT=HK!5;|VQoqZ0HVtkqq!)nRiH_Wj z;N-Rk9Co|&Cx4LC87lLAxiM~L*TlMaW`lDIrL2Vb?dgrUY3D<6#qD3!{8$(3t+W9K zfzZAYc+b8Nay8bP#7y1wO7K+y*lz^jUa@m8onzi6maFf&#N=xOrN_sN!2gHujVoQ- zvmDvKfRqjBjrCEev{By*!}X3vd-8|e{u^4*GuE{Oa({A80FoOKN{DctlV?;3Uk{Wu zP8t#zIC%5DJq9t0j|X}_x)4mj>7 zr+>4g0DnuIqtmeDBLgnqMcvk(_l{?|N9pZA6z}FfUic}yo7ZE^-YqG>U7M{Fu;g#D z)Lm@^_+B1OA0J4tek`g?Qg{aR*-O-p0*0)GMl;dyySVO-dk^`mHs*&@hF0fa~T z#zq|D5))iNS3|@G;9iy<}ezg zZh!w>&(EJ#fX(qO3T)q%S5#B11kdv?o#kU$#Mkn3yle&U&P|qUk}J@*%F?i;fW{Pl zy5;H&NtYygABpw|#DEYm%msYRg&gL);+y3a*dKQJULlYlSz4VzmK4y*G^rJUvsJ@Y z9l4Jl+6Ok>WWtk44u7;3aMQk|CgUacX;N!T5UXtxAIXF)lN>4N+Ug3N d89dPX=U;TYO5rCT?#TcE002ovPDHLkV1k&&>6-um diff --git a/Riot/Assets/Images.xcassets/Call/camera_switch.imageset/camera_switch@2x.png b/Riot/Assets/Images.xcassets/Call/camera_switch.imageset/camera_switch@2x.png index 9b21264dd71d6f26793a7a29a1ac2ec6b747bbe3..b09dc61f8e24e36db7d6d13a26c666dcbaff92ea 100644 GIT binary patch literal 1997 zcmV;;2Qv7HP)paBsDiePseqhL@BkpKoz5fO!82-N^BCzG1oEKB0n~YnG2R%j({`oQS*hd%3M~BEX&)ziM#1w?_I$=D7gmeF zV#}nYH53phpa@7V%ZgdabZe&p7WZUeG9Q6}%TiVhp+L?dmy+sbHwV5@4CadM0!{`i z`C+Bc>K)Z(11}WsGh)vuMaLvl_fopJ;!;FHb~CP-Ker<%wgFbRFv?<+z_r%0m}bKA zhatZY6wXVCqzObL;CYJg9k@_WSbe`dNLfwLqv0-7MOa4EQ;Jj=9`GC$WR7aMgR|CV zyS)|4o`f~I9zp3Jsi+^;I3je*6vUKSu>K0Te~Ap2_oZ>K7d2<3+Tim=5+zet#{xOs zsMk3ZN+qSH+J3Rlao;8~T7?3!ggu53y3acpg^o#LMc$>|$O?2ZP_9G^|yIWbncL7UtlayEHQeep?Muj2`);kDcK7c5P zz+#s|i=|CNX_WZOWxuAghcX}K#NTr#fLYZOruNteXb6KF1>r`10RK>y&~!p@aVNA5 zaR)_j&S^V>=ItbDB1iBTsMVK@Ub(J;Ymhn^D|%B`6<32iSmTueE?u~FcP+zBVN{SY z06G8TnE5m)(F0poDuPZi*5VoL7<*-ezM#?KS2sf4@-oHFVJ!Txt{%6Y8{`jVjv@cT zt+jZNrt;gm%pk_*V9cAU+A0-@zM`tjla?1231uIWN(opgR7q~RzebXrn0lP7&4?k- z#@?wgb2#tSgSoFU2yeNpkKsqSGZsw#b_`lD7l)K4dmQ=P=>ID`o&k(baORx;M_c!Y@jxeR7Lf%C$b zaXp&-YS8T?zC_xl#D|Y!e2~+d`zSZ|ZsKVUJgZ#uiIhS>n}G>fOZj7K1;0eR zHEHr>$uxMt;VPP9(-atY)53(<dqY6)itVo2)y%F-1p>CJc`F0U%eXRWJwM z4IsC?BXg?Pz1zMG@S9un4Ghv+oBq?_&A5I3%RWl!*q5a3#p%sMm-qpiD0JT5s*4%$ zVT&UH+086ZRG#WUFG!+Qu8`wkMD5E`DLL6o6%j9ayk4>^aLC1-qJ_gQ$HdyWX&fo` zxRTodvl+KXq{mjYKQ<2P(@@95Md?hPxi94#9A}HHq@>^R{LS)uf401y?@|BGBF`Sq z*)|sv8)Y>EUJs+#yH%qx>W>eWGppX6R084;SsEUSjP8f}*;Q%%ZSGr)fw#jyeT-bZ z`U;A%JPKt7T&Xl}(K&gs6iJM#@}ju@#`btE*BE%6y-C}ij0vdFg7qZ^j-s0=m*lRJU$mdfy=R0^Xdp2m!VgNo$SgF1(0GjB_ zQ7g6lRm3=p=P9XjYfOL#`FI{L%szx=FoyKDn5b->-;;+#F89z0Ow;ff3t|9%t`=o> z&70ZkV#-~8%7Dm#wTp?XrLcZ<44A#I#jH6yW+%X z)JLVN7>kS1OtgnNr#bH};`X%^dVX~TSGD>MZw+l*a3}Y8N5HUYSO(qT2dS{=S+o`5 z|9AEgyRy9sa4jLx7ln_ZyXumgPHB1YHFX=EdlYH!(VC=dSvR-OUrQ8C9Q%LpO`Nzk z-;E>SoQ|RhE$G$e(KrAAyiuIkN>A&6w-dipEb^|kw}}^#Mx1gWqwTS5?ICKK#<2Qkwf<$Vg fJgDBn#}oN4`d@68SIZ(z00000NkvXXu0mjf09D0| literal 2162 zcmV-&2#xoNP)Px-EJ;K`RA>e5T78UE)fKExqF*OmBwzgyNkEUOuErs3LGP5kmS8WjE2U-e^aRcnkSWB(7McWwG20?5VW@mTb zym$M%v%GO+hS~SnyUBLx&BA@}+;h)8=iGD8x#zqgHVLgY6$_}09%95BIistIG5oo0 ze1tQ0j4}SKX^cL-Wx)d%z@jDKia*0;9=I}SLX zBepEQ^f+ZtH)E?B{4x@)(+__VjK&Oe`sJw}Xf27!!e8cVh` ztbW5CrOMdS6wsdRT+B&5NW=-dbw^LIWas6K)U9Ar1(QFPDZF5x4<5gtbAA+_WbS84U0+!wccW4iP@^at!Q8cA^~igJ z13z-d!uZ&U#^`X)%B|p>4P%{fd#dZs@n<>1n6Luc(p}9sqst-u*-=jS9Bho{oGtAR ztG8kGUpQH7#Viir($cr_YIhXMV}HsAH0_Fd)HyR}l}9aw`Yq3ugmaHwskOKjN(3T_ zQY^WUP&)Pk6n;Cjuz!fMEl#P^sL$NKFnr>C{Ja8MQn4>Zy-BTZ|*Fw6p8{s{vaJWzYU3?BHqaZwy^w%QXep zy;S!bCRtI?*;`C!vYsb=4=83#;mS@VL#u39YkJeyW?$()2Em^c!rSnQJ+T{9raXsm z_j>5ahR;>Rl`tsH0@@Blec~#NP}&tr#;Ul&HR8%ou*>ki#f_iFjqV^!|9#{QgTN7{ zI2Wn&Vwi;2#)OG3VyY*N1Zx>W>>q5n>|UAzGTv*dYQbIJsug+)0_0z8hDGSHEbH;1 z_kO>B_uacq8*cZ_`+i!j&HBtryd$GzV>>_QpI&O~k9{N25PsFhmDx*EfS(zD#t>vm z8XvJZe-O9CSjkWkp!b$XGI;HTCH2r{*NEJrO$OpB={$#6S&Dz3$ljZ; z0~FABWci`kMdSbl0woX96o727tOeLBLJ6(4U%X}OO$VZm{mx6buNmRQh4ti{$XEOt z6OK|^bIiRCel2?F~Bhb|M3xBn@_Im8Dj%c8nxslYig=+?<+HRNQM~VV` zXG}%$ve%IDA){59s#o2I#X8F^cp+FmnNnxeW@|`Cy+BvEPbbE8J!g6ho#C13YEGf} z{7B!0Xj}|j$`KF|09oLX0t3YF#j~rM-|*!#XHd2Ok5$Y+;A6gjd5HZ(C;BVXwLj@h z>(`jpM;iUEu!f`uDGCt0Aluty^Mp%J13qWnZ@)X~cho=l0ncQYBGkQkA$)vk&R%Hj zV&T#hkU941Gf+cuIct5WKlV*GjK#mQ=Hy6b6c-)-i8XzifYdvHAT3P+;+DrPs|5*6 zP7oHw5mX*`v?M#l&CPKW7oXvbaVzMQ)F_GbscQj3!g#RbFuF%i2}C3qTd_{uSZ>QCW;t8$iwrIf!2r8-64xv>xPEU zzPNkQ!zDYpBK@mtz1$my(uA@Kc|U}Pe;rdEd`ro^{2CMZPr3pGFY(~2$FS?CP<#KG z2#o>;A+E=n_-&21HjB#dAvnze0MEdC)&XZ8#;+@}5zgPXOx~oZ^h0EVcY};{3y|gm zgpkE85sW-#G4@q#;6IDuBBh0(jp$d3Isy8-^1>G(iCstA%Ce^y^vsXEb@ts?RzP7r zNR6diz@#Za$b+iRYj0ZCT-**L5J>z~rgB6242#%9M(zewf}8CRn8Lxv>%$>#vaZSm z+>cJm5h!LO73?rljERD1tT`3?5V9c zQ5im120kIsq${A9yWT+fZM=(rQ>IPo5tuSkR$%1+3aFr*OJWEXz>f<_n-9l6eaEglglubte5hFO7rmCt=GN+d z{bq!vrMjvgMKwdfr(Y}j=@;%KJMABHV)GeWp6s0EXUaNUx^Kdz^{VM7J)|OBqd5J| oB5QkM?*|*i52U7}oUUd1FB{*#teszu0000007*qoM6N<$f~c1>M*si- diff --git a/Riot/Assets/Images.xcassets/Call/camera_switch.imageset/camera_switch@3x.png b/Riot/Assets/Images.xcassets/Call/camera_switch.imageset/camera_switch@3x.png index 10eba70c61c2d536f2474a462422130fab700d14..445b5c6337292a1478957f6c4aa1cd67c53b7d68 100644 GIT binary patch literal 3007 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 B#M}S? literal 3194 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 diff --git a/Riot/Assets/Images.xcassets/Common/back_icon.imageset/back_icon.png b/Riot/Assets/Images.xcassets/Common/back_icon.imageset/back_icon.png index e922a69d16cd04725242a576a7c53dba3895c038..789f53946b55329a6054be768b9a89048e5ab958 100644 GIT binary patch delta 577 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 diff --git a/Riot/Assets/Images.xcassets/Common/back_icon.imageset/back_icon@3x.png b/Riot/Assets/Images.xcassets/Common/back_icon.imageset/back_icon@3x.png index 32cdf4b606d1763e7878e5c4954051a4fccb3e29..ef8620069663358c7152477969d245f0839078ff 100644 GIT binary patch delta 2296 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 diff --git a/Riot/Assets/Images.xcassets/Common/placeholder.imageset/placeholder.png b/Riot/Assets/Images.xcassets/Common/placeholder.imageset/placeholder.png index 9630bb3c829ce7bdbea3e61af4d6467a7bf46363..72db98d7ef70b4e7076c343880a686a4373ce855 100644 GIT binary patch delta 830 zcmV-E1Ht^p2Gs_TB!2{FK}|sb0I`n?{9y$E00Rt3L_t(o3C)?iZWBQihR=)kBOrdqXK%vm$F^@qc4b(pMsVYo(8e17rU7 zb?zGU=K|e%Sv`7aYd!m#=^!&kEYvA#> zMx-qdqvI+y{U3BMx~QA-N|btv%qvwYt(wP*9iZVmW+2aHEBZ63++@(bXO|nzm3M%= zKdF+L)2!W(2Y;uJW$X2?vbxGayU{JJRSy}~%L>o)JtpFjF}5X}(buASi$Mvg1Sg!Stq|MQB5y>X;Cg+Sbt})W$WzFqlk1ufuwiHLZ-}9 ziAR%d@$;-ZPFCr>{<(u;yS>Bh)_GLx#&&3sY%H0`#<&CJ0fP@=hJ;NC7Wal$U&4e; zsA6Mp!?l9*WY~d>8mE`*VPk?0jG8C&&_T(l-Sr`GQZlmZgZC&I)8#2}mjX}owirAn z7;!!hAAgjLI=Od;?Nc(c>kq@mB%M0YCXTzIgHmO2$2{G8`D0quqprqLT`{c}8|m_7 z1NLgd=0K?hIhmy{H&wKg9-McXJ@F`2HfTW=%h#8UOsN7m+?gm?VNX4+k7BZ=^m5nE zat%R~+n(LY5|;iC@hrQ6lI08(59S0iAOx%BLx0+Rr|@|o$t~1-K{-XQHa{U@-G5zI z9K-L(oDA;fmAw&i+1hH<~$d5^y_rv&P@>BhI@E;p| zSU1Ll|9q1N=CjlJAz%dzPJL>&wVkQ$_7dQT&4gjPLBvDt-7TAe&*6gO0DwpDY+Nt2f+HK+_&z zy0<7VEjNN-dTDg(Te{U%{v+tE=QD?o4WD>KMjj~O5tosFtrMX=7MlC9vHkGH?U`SB zc5*@Qtv)$UgMR}rndw@dk%P7=@GIKcz4>(P{`V|fnV{ou7tS9duIP($D(mL|S}(L! zCn+yop8V*t>jbrsOt1A(7hN}Xu1;!op{p*~eJ=$bxAkP#A@TRQh_P+RrM%GsiWdhl z*|o==g0V$}nlf0HM0*Qp@pNgn(=Se9?959r*qJ8LBY%!jJ5O@qt9Ck?Xz$r2rmluG z&P4NU>`^7>#!1elWQyN*b&F zgMzVtJb&u;w12hmC{BvLr>bclX}tyoWB+)RNWOUOPQa;vVf2K(;yWl*7Q4-xc(<^j zE7Xvmz_Ph`X>u4bN>*m^lQL$rpwNOe5CZ>LmC3R-_oLWBLksc^6iktr7J5_(Ay}zb zfBFJz4|kR+B#J?C+7ppEUqB(AMJG@&#h@tE)_<$hRu^AdP-J6PT|3U zH$78JR4kL7-79HjZyzY2`$8lGDAY8lYPxi7q1=@O*)c=O!}u*RngjwY9zi!^7Gq#6 zm)saJWrCsu;-t2|eVqb&+=;160ry}VW29p;0*rEJj7E*g-20CWNmyKa|M?~jj5212 tP$#ODMS1vVRRsSsL>b%DYrIn^(o`C$R4Fk5ZN5>MzYrDp@&)^VeaC{E`tK?-$JR0k4=4sG2eTGR$?#Z$JqFDy|wm!zg<9oK)Cp;+-P(E(R1Z z)!5i|H1nfH3K`b4X#O|!*4B$fpyt0RQ8R~S`T~=TfOO^72;K7;zW2sm+)?~;)$>9l2);A-=-(m!a9XpLdwnmf3iigjerq7LPVw(DPP=Ui~r*3Qm)p3g#?S>afZeZl!)snD^g-+w#8R17HP08})A z<7ob)+ov|%T^=vuM3B(X5jFl4{JnI&W=3fMU~=mDg1Pr}a=M%A?X`ErnJ@13 zQ_*65sI3HY87#$DnAbmKiyoFR8np8`Gsn;u5imUkuVlMu9Bc|dlEkX|!= delta 1763 zcmV<91|0dv4f73m>hz3k2H?cUBNxylO@Du!T9S}e){ad$kQV;I?B-kwEyhTD%WL4>G$c; zQK|WtA;vt9Z9TMM@aL>$XYShu&J8`;?(*}k3lj)=4|ISoS%Effp|eeVAKi3b&RU7Z zl%H-|Z+}x4@Jh2?KvO^mPVMP*u3veCdf+D(6AW#25$vS@@5ODyoAyklm6;l7-?#5| z6?xmI1oNS^g|$?A!OoP#%;O{XzHm8By;A`N%;k=An%;KSrYWRV)6!ek_!ZxOI1SXq zHzhQ4Sf(j3VFb_>Iz#uQMv(|8Za}kr=F)EFDt~I!wLy05$v|~264$T~#j}~i`H4tABTs1{V9W6O!B66pj|GZ1AUyC=q8s9bm~xFqtp1ty z#JadQs=7@ceFk19EzHndzyeI-`qR2VG0@T4uahANy&>LHW}}v>Z1Na_E4XZ;Wk!wE zx_{*tOQTei9_v;O{V6RJi|C{mds-F0p0}iv37G@eF;ZB)Zn5SZ) zm^WvI8~<3asotkl}{CXcm71y;C7CzUQBNMOGk6Tq^cNjA9>YpJA#V&RsB*%(~C6krF2xGsTW6q;-zEf~7-Go@;U}!z|In(viC@%u+i)ZE5EUStxB?v4H|nSpNI(d6f4LzM1{FG_jD5>4I$)%EKTOR`Yfh-wc#1c)Up z^pYNFRti|654~VfXd*x?9qc#PB!A9$F<|Ln^S<#UGywoh2c8f#$unLISjt(>XU`4& zs>`c_sZ`-j;)C^rx63yrnv)+j6@)Im1BMbPe01m%Y^t1qp#%ztCzz}^6-HLQ!43=| zM*@}JW60r2R>8*RCw74c9tjj6;627zAQ=^}W>*0US3LAye>J0Q^Rg2&$$xHE^9oR` zZ=}B9n0Z99X$)q;+E7TU0L2OX8d2l-5w=GX0>Upd3)9X4inZeKYZP9#p*R9yRlU9* zY3Be%1e`?S+a8Sxs94ni#l9OjiE1p)>=a-W-J=8|H9!#wk6U!dPvvU^`HVS;jbx-y zSP2w+7~yeCk={lT0kBc+^M3>!B~V;|`!dQphOj-V35c;Wo9ehQ9J@)uIv@x^AwLLMC=t!)OX)Av{s(6?u&3Rok8uD1002ovPDHLk FV1k97UNQgx diff --git a/Riot/Assets/Images.xcassets/Common/placeholder.imageset/placeholder@3x.png b/Riot/Assets/Images.xcassets/Common/placeholder.imageset/placeholder@3x.png index fba0bea39c0c1b2b8f22a33f4c521bf1ba9788c1..856f6268ce37ee833ce26ad203d898fd11bb6993 100644 GIT binary patch delta 3188 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 RaYO(B002ovPDHLkV1ljrjA8%) delta 840 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 delta 1091 zcmV-J1ibsB3D^jbB!2;OQb$4nuFf3k000CMNklp-<>xz@6F769niUR?vL}i=iQ%Y1eGVEcVXhFP=DeqN!83vr3C-sNlGXZ z>Zc+~^Lv^MvB;{Y)2#y^_?^|I3AZ0y`sc?_D=97!iEbgNF-Qwa(Gv5{3PU}dY#V$T zq%O(^0%mU>;|jNh5T}9~(v??Ay%jg^$>)}9!4)K1q(>ncJp+Bhpi<`&T*xLu7`2y*vlKj zFgiAm={#Vp29!vCjAzXH={hFj`Vr^qkvAl;bX5;5I)8+T2&SB5J&a933h^$NRXr&~ zspIzMlJ&44k=K*z!DT-?*i2wdG@fK93}|^+%AUAkx5*^kZ0V%_ zJ?*}rt;3cD%;!MriW3;HH(ENVxpo(wsNd%kT68m`zxN0I_Xh*o}Mj#cB%@} zn0(Sae18{YMWb+o{q}o_UafrfGzwOkxhZ%SF1J82*wG))Y0dcSZGvw#m~^<(L@J@c zT7)UdJ4d9zA;MxcNtNv3oyl6yUnNY~j4=kr?KYrvHy)x}`!7&SZG&sg2w?f{DwM=k z+|{Zk1F+|IAEvE|Bn|C7qlJzH7A(vv*}aGx_R1Mi*0U*)lft%Gxh#+Fqa4BY{o9_d1(bQ}e>C65%6F zR#6q8b)JqCmWjZM1H9lHa+;5DfkIB`QD?&ea(Ws%TSE0LH;ND!-=xiTn8&i3wG9P% z>VG_q`eDObOeP~QYb*%NS<2x5H$z7Qn`6x0>G~EXUY8T(!|*t`qba-z=I|YYhEuHr z?NHU&dL9=eOkeUP6rO&u{Dn435B=IG1y8WqN^?ly1-DW}5$%jpo{_*ZlYL_bQx+I6 z2zl}ZTt&J%M6Fs(Ihs6RGs40lPlSnbMSm)jG8xS9Yktf)4;W~OWhr3{RR%L>6%3o> zYRD}BhI0Dw;63i)7}Avx*am~nc6M3QWtw4EB}e0mWMUY=vu?0pEDDSQ|J5f00Gs28 zL!RX>d1%W`%(l(2s`qCwPY*kdSf9NFe@zM}4#z{_ts*t-TxXs3bm>6Ab_3=x;XHU8 z??7EaPk9Wv#73WxVa(`O0o#V#vm{_gWA2}BtwL$;RH&bB{{aCr>uGwNRvQ2S002ov JPDHLkV1hy~2}A$@ diff --git a/Riot/Assets/Images.xcassets/Common/selection_tick.imageset/selection_tick@3x.png b/Riot/Assets/Images.xcassets/Common/selection_tick.imageset/selection_tick@3x.png index 540ad7380484654537276f89930b613b91914266..643cfeafb47dd734c0ff605e5e42130a10f68498 100644 GIT binary patch delta 1825 zcmV++2j2Lf4X_T7B!2{FK}|sb0I`n?{9y$E00!qtL_t(|0p(mG#!D!S6ZdHncNDMI=8hsUo7=3_5DUfiB8lpa+ zhA5Cie4qyK(jrKpJ3Bl6-|WohboMgW&g?EH+0Hp<&N=`8eSiC(`@aE6zLvky zm1NN5XjQdZ6MxjtO7BUh)t;M+x-Lc~BN8H-4sD;2)3kLYXbl-gIx6L=wj+ebWPg%M zr*{l3-f+HZSr0Em5i#L-&*;G$e|NJ5yuwPQJjjc_h@c#U_+V_y`0l^j*Zvn&Kwu)& z-nW-i-q^(!Fe#|;Nb3pl2Pxtuz4MLzLE80A#Ejk#n}2@S2Y0ftwLt{NP^V|QI`;MR zoi7jhk>!gBb1=;6`?)JTd1=}c5$UhC&dm$`Ad}GQrO}!xBWOS|)Fs-ot{>fWawWpDgm3GP1RFV%!IrVW z%`$iuTYouVOt88`eOZDGiLDqIfJM%B#w!wm*+Juhv2Ml$Co(zBt6X3KCOKPm6_<{dqNPVsyMO zAp(1cnprkGl#L|GTLKfKqp@LK!`wyYvS)aJOn+trF{xA!AOi@?d!Z9@W>=K~}Yv-K^Q zM0E2RBhRxd6ZvKm6bj714i(IFs>W$PT=w-tKW+3SiF+JsPaL=*K=3U=v0Qb^?gH| z&z%U}bVhBSqTmK9bW1TcAd>)*n`S;rTiPBAEgc*vxP}YeQVb0^Nw7tNj2EWPv6F$G z;6TA$WT4tHR;ok-R5S2mfFRGO?`kVrfn47U8MQzHbOr}%YDN1*X5?8JgrE2?*RIe_U898) z?klN=u5x$NXgcs`snJy<;ink7gMX~7D#XWXX4T@Wx{-TLe&IKMa`2)rGTcabB7$YJ z9}H==`BgQy=g2j6We3hH$N8!3EbEmFHxfpAV07vYAI|L3P20?i95{1wfzX?;_b!|? zQdhGYml+wOn>=v;AIor zYKjDavay>)z^#|hv->@xbtzbl3}@A(EWy-+F`L*qVG;q~X5N$UaVi-m?S+g)Nnmim zZ2NVaL;x^+n|VUj!hmf+WB# zfSuW8jH;Z_KRY_0u4uoL^XAF-VB_;l1S+7PO;g8W)mh6^YY%jE8xw2-?5F3hVOOx9jrMa# zUlw7LfF~9vSgP{6edkDQ)MQyzi}IUEtaa*w_XOe2)S{~nSDKvy{qBTD!&`C zxOsMB?8c5+b}kPpFA^eb;aGs()<2TBiLjq=>%Fc2ZGugN^BP$X|48G1cmfkTE?F+& P00000NkvXXu0mjfV0mc? delta 1679 zcmV;A25|YX4xbH>B!2;OQb$4nuFf3k000JANkltB_PyPG9mw0=dGqJ@{eQff*_qkjMo=5VfeT*@ zc9-STf@qkec!aC0kPsV5(j6rD4?)r*pD&V>3w$+0LQYGfE6X+Uh9J@xI}d8$_JX37i7n<|LI7bk{<)iX|( zJU}D{gDPx3PJhmlEzU@LY2xJe@xPic&nY1l5HDRm@ldyr?+QtWxXE{?Wn5%AQZ7qD zr}*R8S5F?f8kyGM%cel=KR?mi+gGkKfVUVxmqC5$Cy{c6fqZ=9daZhPWc)_b3KD~O z`RC8~3CsFakhm{t$GS{l=HuUY$%*Zfp>v=YKxw>F?ig+!A6uNrkP>V@o+P zKY#P>sj)Yg;?xxj1O`JYl_!M|PsFLD-D#ziztC!JU!1|z7{uWVpKTH4(s!-98>Ed( z&dS>Ao|8LX`^}_eBM=8Ko!H)0l2Z&}qe-FpNh23lR>kP)r;c1~WK%;BZcF%~co4L7 zxxg)BSAV0H5eY&~kh;o06{kCB@%|%sla<=es4>IxXVKTVJ78ceJ_IP@SuSf)nzTUQ zF%$%Dk$Jy6__Rb`LJKs7B?{~sm@HXV>6@@jMUJ=a)fa*$UF$%&)8^mvGGj~|I%c3e z9e>n69beZq)Y>5@)8@1xpgjD*(C9CFO^d)PvVTnSN@fcvzjdv;=7m~~#ISeOx~4^R z3He^fLjYV}DJ!iW(DfFf<_x9sADpN?`w1Q+GC9S5#%k?BJ-4X02(`0RFbH>b-%cg& z^@##&Rhr$*4hY_3bhg(L6`4t3lu+dti86+SatvpM2 z^M7&co%c5ZLkv3FT@Y%wIg{Ttex+UrI(IWLw05U!@RqwSG|$H%2-;o^Bld{lY8QC; z(o+_xZHsHe(mqB(&~<(N&n23g|5aZaAD3!!$ifpS;~W_!Y$XIp0t1Vi(r`xljH+!l z1Q-DZmisKy$f$NFY6k?RiJ!+}ux#qNWPhvRv<-qIpkncqI(HkgZH9og$42fN?qm5@ z{j@R5Z94?m#|*edqz_`a_uiQDo#dH7K-J8^nNTG%J2=zcfvxmTWt3jrye&9ENNi>h zTzk+p7DH@{9SsQ2Z+4yrjtx9+3?pj@V1TZX3J5O*P0$2J<`7^kGvF4Xe3rEBiGPl} zH*Kl61b+chFmeF_1~UVU5i@?{<6d9B_9xB%cRe&)5RBYFaIBu;t|6yG6&QYTZRKD3 zXy%+TjGRH>t|6zp;KCPs=^6k?!#G+QqyF3a0#Xp6Wo#&w>9M{cwW$)Ah$EA(BE!mS z6b}X#{1_W0H2q$~i0URI_YCI>0)MoDfdywy<;Q5Mwm~`*7-2=UyCuL5Xa@slLdDLU zVa6qiPXZ$g2uho)U4ei{YZAdxdE&sx3<3+#+7$@p)=TWsnsP9KktGD~7_*LccNbgv zHnUrA${bX2Q82QFz~(`->(}j!5gZ5KW}aa!w+lw*5b($kn%z(bfoFiWpnuc)i?olr zWz6vmG;;_n4u0JFxhJ%)@tU{@x^~dZh zEOT+Xm)!+A}ik!L=1 zHUxo0c;5l8{>ADh>cy2^Chuw(gFr%1g{yxN22j|jUP~~1dnXnM1%HFbjJf%nJM(;N zg>A60(U<@|-jI0Tw$omBG#VqkB{R=3sZKmg`fY6oQ@-NA25cT7&{%;fNAbcl9_(vN5 Z1JMU0oTZLS`Tzg`00>D%PDHLkV1feUB(4Ae diff --git a/Riot/Assets/Images.xcassets/Common/selection_untick.imageset/selection_untick.png b/Riot/Assets/Images.xcassets/Common/selection_untick.imageset/selection_untick.png index 48317db9fac31b63e4c5b1559b653a8fe828f5ed..62ba9621a37fbdfd08f13197b84f2d5a1ec99c0a 100644 GIT binary patch delta 730 zcmV<00ww*d3V{ZYGk*fONkla#>7=C6>6OARo3b7%28)89XV`+D*X+p4T zo9Ln&u_4jMR4sfZtVD!%E6AM{2#25^wsa!|DdlXUr@t$*s z6PPg(Y4|>OGk>!tOg55Pcbr>{rXFVr`jp~Am)o@X3g*TST1lpiF;~<2g=w{mG1fR) zjHKc(22f3092)a>51_X7$!84Pd0GyG`B7J+ijV{&n|$4!j(BBwvUR&pelxL6cY}~$ z{PO%|i=?*QKn{72sSZHZB~}tAnry|=GPUUPdh{P5`+sWoKSL|XnD3$XwfM#0?O!F; z$p$PlfxJ^p%V=(ZH=jGfY2oupyR_`Q7FL~#EkpkmRyKDEu!`RnW^u_Xp%}r=P>-uv ztx3dIS1iS3jLA~KdaSF})&#PeG5I545z{L53Ct5qj;Pq?MPCuMoEEl9N{XeJR{7Mg z{A!S;_J3p64bWW}7ENm5&=N9sZlqh15gqn=FEff+IFp2i#F#T4D}(5pe35|_`ZnN! zgvifVn6z6teHJI9fGsU|X>bkPJp*b-KvBnADzlNlXL3;bX0)lqofCa?;slJGqSvdy zA3qlsD!-q&pE4Sgt$88B0eIYt2ctT}Dz91rM^kgWMiS`{ghCz(EuVKMYd(}GD@hZj z`N6=Y#js-qqXdp;(RE}iJyrE*s;#es4HbT-D|Qj-!iUOjN?)4&2H6uW3esLU9RL6T M07*qoM6N<$g5rW)ivR!s literal 1324 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 literal 2336 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 DcMosS literal 3785 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 diff --git a/Riot/Assets/Images.xcassets/Communities/add_group_participant.imageset/add_group_participant.png b/Riot/Assets/Images.xcassets/Communities/add_group_participant.imageset/add_group_participant.png index 6b6424eb93fdc2bf9288b7c10a332f9a9351b588..d98356fe5bc7c9669ba47fdac2bd8541a8535040 100644 GIT binary patch delta 2077 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 BLk0i< diff --git a/Riot/Assets/Images.xcassets/Communities/add_group_participant.imageset/add_group_participant@3x.png b/Riot/Assets/Images.xcassets/Communities/add_group_participant.imageset/add_group_participant@3x.png index 3bd549600ebd7a2c98048c2bdf273e1dd9d53038..d6813615c8b10ff63020dccf380540ac50fcba82 100644 GIT binary patch literal 7309 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 literal 6492 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 b=0(SgYB6nIhzarQ1E3(QB2)LyEaZOx&SWi< diff --git a/Riot/Assets/Images.xcassets/Communities/create_group.imageset/create_group.png b/Riot/Assets/Images.xcassets/Communities/create_group.imageset/create_group.png index f0faaf5f96299c24771a9f418bf996ced43d443c..b5c41a287550177a33fb6222eb4288a5c1d95b7d 100644 GIT binary patch literal 1702 zcmV;X23h%uP)l7E1ifX=5B8RU}7+QX>btGr#l_8D_cgzbWiXy!cu6k;QrSx>9PNBC(f^ zZmsB=Bqm9T^F(wm)kJ50emC=1Me;mO4h2xhmt)Oyxp_c2qJ-GbwLp64QD!z7Y`_r1 z`l>nIbY}Riwz)C|xtgVl z0;uCB)i8H8`<`Kl54pCagHo-c)o82`bWY?wR?H4Q2rffh5PpQV=$FnE+;_vX?rEEEsDDQbLad$4nz~hf)j-Nh6 z3!dd23Y2Bo?oWPu^4{X&DXuloJIIV&64$0H>r$yh7vF#CW~s`R3}|Ox_GRv8&hlq- zsTZqmd79$!Rp;fN%#Wq$QPS;qXMgq}_cw#_g99Y^LybYx2LFhB1A3wV`cYx1Z&-Ar zfANtk*$5l7Ek0HA)x)Vb z7?*L5WlTB0uyJX?>v+0j6T|dD3FAU!N63z*RFKFcZW3~j)3jto4Z_3|bE~?61Fm|i zWSlf@F9f{;5N733n|Kzg9L^DJhV8}D3z`_#b7p38w-{-amn@3aT&rWswX~$4SiYWA zP=m18RljiXC#bZ^ApeKhH3-Y3Gk0dkIBTs}0`uBLBR0|U;QBUe`PQyMSVKFQrhw7>IXzM!h!7E$!2k~kKumBV2 zpaCt;i8r`|vTIW{m5au;mBh0=8;~NkFB*zPM+w91WX-)ql9^3|xw9)A7ML>l9TjhTsL57hdE8EPiTp8nPvriqcoT=CbgweCgrvk$`UL3hI0A`!1?vh+3@W4DH&{}xz*O^ z8TD3-w;^*Mq_E7I1V;jDOk$I^V_uTT(^N4k^$zv~h9d#6;XX)>IOZma-212z3Eu~v zZiF?`iZ5nn0yYwkAtdNRd@Tt_bNGXRjUGw!-iCAGTqeF!;Vc8~HK0_p_?Ac1Mtsc) zT5~esNd&3(qvu_H*T3V%`&Wa$lwWz6`D1d6fGJ8jBXGah@+!w&&i9vko_-DG>_?bz zDdI;RRRaVd;myjukQC;Fg_WY47!KfX#Xl2PMjii7EV0lCY(Ut}0Dr4G2BS>}18Zjo z5^O*?fHN9*OF6{rGf>WCkhi`75O!9<87-e(UoqIee0LeFF93uDcvK(R~j+Jeq&ec49p#Q3X zP(b@rNqLxs)zD-X4t4Udm#>&FKpGNz=J6PTH<{N0BwpiTTl{z%!ghN$j{~n@x@H<* zb2(T4DlZvT&R@_q$A>GXrDsWia8lwHZlQDeMZ1L?W1NNn&=orS>2r$BF1ZF-0+Lr# zSR_1tlb4%#075oA^^(`)_yLu?V95t1)TrbYUH(9!lzzz@JIlZyM7umxx~m^AdE*D2 we0Ld&?MvR=@bR55H9nqwme-nM^P0f_0Uxw)>QZL`h5!Hn07*qoM6N<$g8W}Vwg3PC literal 2935 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 diff --git a/Riot/Assets/Images.xcassets/Communities/create_group.imageset/create_group@3x.png b/Riot/Assets/Images.xcassets/Communities/create_group.imageset/create_group@3x.png index bd54711b523a3c3ba9e739f9bbfd53493567a9fb..5d32979785e238480402f162fccac3b1b44d32d7 100644 GIT binary patch literal 6377 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 diff --git a/Riot/Assets/Images.xcassets/Communities/remove_icon_blue.imageset/remove_icon_blue.png b/Riot/Assets/Images.xcassets/Communities/remove_icon_blue.imageset/remove_icon_blue.png index 8d8376b96f0df0b180973cf5c37d0e8b847ac3c4..020dbaa1ce1699c62dff6e651a211fc1b031aa3b 100644 GIT binary patch delta 684 zcmV;d0#p6F1jGf9B!2{FK}|sb0I`n?{9y$E00MhSL_t(Y4XswoZqq;%y>~or7O((> zRDpO1fp}FEn%9aCp{RvYc8EO?bRADDjc`s$fe!>KXC5?s(}-ta%vz@%o%mZ42G_!R4v2?9>uRUD zdlwljQ>>l0Z23|H9Hs7uj;n8$?@xRlg(&xMD+iW%3J8Z$>x!dVbCp8+r(lqBVe-A| zxU&HI3w6&43x8isEp4AnN{}rz@?CI%jo(dmi@|xmN5GAZdzaoR2j&ckOu=dr5(Y=a zC*H~#e8-uuEnfb?m|VON`Az>hRcu_8HmuUCV>A*OuD-B@fHUGA0v=34;vFbj&xWm> zakz9tgzFR@<4DV>s^V zoTSKV;R6lE+{`s~BmsZK5*AXvqEH;6?k560NI7$Wb*@zFhEabP1ArivbSSQQqZ+sHc{AZwUgMc9eIacR}+Vn$TMeXjmQQU1XH@in&Ai znu{{7Fwo!_AH3_R8IvcJjE@EXT99$Qr3-pC&Ly~lV8hxhVN~sD%J@y?Lg5d@^^j(+ SIBj<$E*;_pK#>M_bSbtCBw-arJb%Qx-~oUjByN_X+@rud z{AmWsTJ0{L-F4^j%y(qZ=VMEfX0yN>lr`_{FS>ASr`ZdEimI*~UMHODun5(pmW^~6{vPNBzMyOv@5ZiBT>yRq;|L$yfo!MQw7?$F2OOg; zd1r48fOlgTsDGA$pTI^ z@Kx{Zzq{*Fzn}r+wRiS=i^sCtEW9D0C?ss?UaRn?fCi8&l(KjBM_pU`T7|a+03@~R zNkpo^V<1DBS79LZyf?IErCIpBfB<=h$R}VB_zLs@rGL=#rMtGY4G55NL=J#~Fm#Ht z=$*a2Z>=c;P?1N#gWS-=y7Tq{Ik%L6GvF`qw5YpGq+4F0Iv3+E6YG{(cbQnX#JWpj z-4g3AiFHe?RwULfu@H%MORT#je4q=vCDvU=ppxtPa=YQ7UFWDS=H8RHMpf5=!*EMC ko&HsX3LDP@CyH+U2Z>Q0uA|o=9smFU07*qoM6N<$f-`FPmH+?% diff --git a/Riot/Assets/Images.xcassets/Communities/remove_icon_blue.imageset/remove_icon_blue@2x.png b/Riot/Assets/Images.xcassets/Communities/remove_icon_blue.imageset/remove_icon_blue@2x.png index 385e5141659030dc7cb98ce1e388d1adb4be7254..42335606cb51f056d0b71262eebf9bca46da6675 100644 GIT binary patch delta 1903 zcmV-#2ax!`3jPj|B!2{FK}|sb0I`n?{9y$E00%WmL_t(&1JP&N(@3wRD8rsPzl5f38GX*Pz-JhZ7B^xBo;*_Ax1(6M`KL zhsBN#fAvkOA8t=gV{oG4_I<>Ji1meUy>;3@E z*l^mww8k^z-I}|eGd7ho~;}Es-$)e7I=h!IqP^ zsl2R(aSrf_M}IJZuY(Ez|IL|5nha_^ob%UxALf<4?kDRJlF`epSTS zy7utCfUE2H7k$3kmrnUKt%@@~6$4~PRT1m~P2>H(seezM8ET&($t#N14A5lrN(wwX zr|WEEFw}9FwXM*NhJXDJcgOT-6EyLaSrdZuD$d#Js!4Y&9!gCZk{7%IpdU9&9?_>u z#Ps@LB=8*zJYxhIxIpTu*%Ykg+`C%ge6irHEY%{ebHUnr!|bzCJN9({U*pPr>Q-37 zTr+q8J%6V&u_4%d=`i!pyCtzDRYMh_wX?1Z5ov`x>@{lw6ICJt)Omg4xl(F^%*O3g z>#^26Gk8PtdaNnf8#rVJPnazlpbC0O6E5zp!$eE0nqW5s(|3q}qMw9z&gzf%cIMxN zrMj zIEuQhg+!-Bde9noSQ8?~uAo%czWTnO@y-aIMx~sEN`pLCj_tZRV!`u&dbn>K=A42> zo0A6QzQ~+Lm5+Fn z31zw2UP%);1Y41cf0@mk49P2=Cd`RLD)o@V#)MuMdiVaLsLcsHjZPbdQqx+$=)~^U zufgHO9vp0avK6a&0AQuJoGs0i0FvZYrEDX{KPJZ-Z-h$ZHuZ+X<^i6@=A{9-sDC^s z;1911&;-+)!@YdBT@xgE$|~cDnVbo4qzAf=XhWegL$ooCuzX5ewp3;-oIkd+Z^D9Q zr#M$D5c%%KCXxvt#?DkV5ra>hmOeq3kusMChqc-~q<4-9y&)JnYb0jb)=k%5kOt&L zGIzrLVd(%(2+WWuZc@0692qRPv3~>1R?aJo zW}1vb?A7p%Z9?Y<)Ai#*T!TI~2cvp1V^hz}$ZGb?Wc*vIKkW4LEFp4@=k+pAdwyv&D+=krz;o3JEc9yj6=#H-XOSSCFE`F;PNTU+$j_9#Amm5euJCSBWC&ocI6mvlMmo@eQ6Ve@lN=; zYrBFJIEHIq(wXDDjo8#4-Ea9dFx})sQAcTqF2Y+F)Axb1HfXWd!VAsZuF(Jb0K*!H zH;M~-jJ*>Kb{s5(Xf4%-XcJxG9^CxIXAtmB2)!S8KMnWNl@(7sS<}|z^922TKb*ju pg<_-~Ia%LY-)*mq0rZ^vZ85R~h(RTGI9}fR z4^!=tD4f5zAd>b;DuQi_mo5IoQt&%~rNDK>ZpprhJ6ms0G4S&uX*=*V;3V~f^*UsS zQt$wCFbZZ`8-EWDKR8vucb~twFp@q5Rsa!TX7((o;DBF%Y|6~Qc*C4l#Y4k0rU3Kv zU5WXn-su&?E;uDgjPwPd%;8*&t!7#^X-bSU-yi#29RqHA zN^CHvHSy5!^hsjA7wGg(M-bhZor&8QC07149{P2znSZ^7*&4tyKe&b1sl<-mm+n*o zzc7+w;2H1qDq^c#G!VBhO7MV|gLoUW7lAD6*AR!4*pZ+?l)$${(tcoxmo_7a9hePt zceLIqf9UQCptJ3oq&-OA=F~)&IXxe;CJN^-&X1%Xpxpz1711jfoy>y&p8}o|U6`%% zl(>O7tbfEliI=yI1z`Rl@I=}w%g-f50kfaGJ6enWPhD;RB_;L)KX^*a##nDo&&7ko z4>XbamNe&=c;H77eR9#MJn$72$S5(}%r;`S7RUnr8}YFcJJe83q}?Wx4y53-c&;F} z$lOre@n}-%6>h=+I@@kY`Uv~nE1jtDmA?=l$VI1{1-_{PAdy7TEX)>E z_{L0N9(R&y&AdanW`R$An>a1lyk~m40KU-7JGM0gd^)81fMwq4O<-0|i`}clK7Vh< z_0%y4_MI%WZ+{cocXFY9o6x?Kh4yVi`%W&jZxh;gvckFH1tEQ# z(7uz4q_z(CTRUdT z^oRr7RQlrtN`0Hnn4OqR<|_oT3+YIDJslJJw5VdQ0mNs2ZvhnyyC4_!PbDSrIdkGY i8Lp^eykps8H~$4Q?ACy7JQtn-0000xV}G diff --git a/Riot/Assets/Images.xcassets/Communities/remove_icon_blue.imageset/remove_icon_blue@3x.png b/Riot/Assets/Images.xcassets/Communities/remove_icon_blue.imageset/remove_icon_blue@3x.png index f20566ed6bf814e8609390d13ef74e8d3564f256..b4979003909f8bdd9d89632c93f18fec21f10a4f 100644 GIT binary patch delta 943 zcmV;g15o_u2E_-EB!2{FK}|sb0I`n?{9y$E00VqUL_t(|0p;AWj?*w00ASl4I1oZ& z;|UPbU2j0A@)B%FY5VP!bcffwKjdX*5+@(PSdhye+bpE%%> zk~DGb-@hHliyJ#}>`#f?%D>E+N=HXxbZ-0{7z}?T$@tU5?SHSTst@_-cz%~Lewe0k ze|E5SqQ=bg4+@8~-TW9}(I+H{157+(obe1KO_OwAA#wIUj-u-cQV~ZDy@K3*)acY6Oj)Z~J2-H<1EF3MMt|4LKXajWx2^*&sQ0Pc5 za9RU}isTB%2q-ipmpH~ip&+@&u>$gqM1f-sC0cwkMb|7x3KmvJfb;=g?{;pe9 z*W;D0Ec@U!TW(2j-Hm<8uDm3pEXpmY5;`1t$C{3)4&mimNVT`4#gSbh1(G*3N215^ z0%V5d2Y<&K&=N`TlPt_+Lmt`dd`0WJ@(Ub)bC zo}&}U=O8%_z27;75qk{1AqQ%Wqntb;kpdaxctj$bgLH5>gLk2Y1Cjvg;ACNwlj(GE zJG7Wd=dYM9PVv8$){jY|Ims!I367d>LP2r{WPgJb5|R@j44hDq(19>7>I0xH&$4yj~Ay1Rr$K*IO)yz2U{PO z-(sss{lHOBD@X+#S-%952NFqcOC@(+@+cJ(DEr|fN RhGzf(002ovPDHLkV1h56nZ*DA delta 848 zcmV-W1F!tW2j>QmB!2;OQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru;S3fH4iR0Y8R`H40_RCYK~#9!<=VfC6G0RQ@b7oz zI13T%v=ZddLbR|j)fK0$oe)#lh}IU8D{OKx7B<1s#?~U3!he6jBZZyCg#%Mv5UeaN zARIQAkR1z?xaZ}P&F=i3SMKtL-Oub>hM7l9qF$E*oBbxpTkC6U<(HdRe<7l%?;boO zxkF;RwzbikUKeQ`k`)3sk4K}AZ@&Dv6crBe3cxujWwX)gSEl!v#z`khpcliJG{Yg8 zdi#WAwYIg4@9z)`HOi0Ud0132v zhutdwCVan3Bp*OrSdb7zxn;%~?7e80%VYja3?FG#oJj?x2M8A_56&r|P?7TD%moS! zsR+)QK%pQN#aRgCJCX{Vr9i$Sslv$wBpo;_1G$Q%3nv$l zYe+hAas#=7q#LIYkZmLrIE8_1A(_Ha0%RJ=B#ts5Q%I(9lmh8SvVo%7uQt zv{Yit*Eu@(lN|p^uZCkAi9X=iL=ukSe0HrJP`H94f%dn--V@h)Cg}=JdY$9axf@-> zQMsSwG?0od3m1^+Dvm2ibQ#A5B)X1c8;L&P*ndQ#FF3Z4=o5|&B>IM98i_vQm_(wl zIHr*3GmZ%)`i`R;i6P+VL}Dm7x{w$Wjt(S-hNBvZA>yb+VyHN(kQg$K3M7V(Qxu6Y z;1oe(EI4_Q7!yt&Btdc~CL92$-@o=X%L(pqG<+{eYy&ch1t&9-#1WCaCIB=#{fd;b z2}w}IfU~sRB#y}OquRY2`?JzYBgKL<7b%5vY8}+*^eYKusdw0|#)5MKiQ{)f@^p#= a0Dl1U!KY`Euu*(DTV+^~UO zz5sYCQooQ-K)%75my||N)kqIB4!dY!E7?GED-4dfV?z7rLVU*eo8ZntAkP9ng#`I^ z$l&(;4_He*Wf_KMpN+m`!a5-17FPl7qW7JuB_;^XTN9S6=C9n5ky6>tNWrpGU6rsb zBdzOvOBa@rXDcxh%d`bqYqnyF;|FdCppR1*>ItK4xs`vv#tWlEM|%ROP#gdN002ov JPDHLkV1g#>Z?XUY delta 296 zcmV+@0oVSY0>c83B!2;OQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru;0pv01vmT79 z4Tn|Nb?2fw2AX+%Q;}^P$IH=v{{Rqx^K{yH+4ccw^POuY%Lcvm`Yy-CqGqM(1!(b~ z@L8{SjGZL20y03$PLi2XkqHG+k%=YXX&&@fEBPj#d|&g0Jwr(>g$U?=HvJq4A|tAs uqV1x(F`458Kp|Mb4>QLJ${()mYrFvjBT!}5SA}f=0000nM_trk(|8B$$te_nxQ*@eR;5h-tGD?nAtlUOb-vn{@n3w&mg zfmiJqZ$uV2XtP1V#5b7DJD`d`FZ`R?xl0|Z#-UT zwP|+DfEJl7%FsHPT{Vfq1tWcoKjlg)90Xg-Oi|1L0G`3R4HePv1@6W!HI tTv?}?s!OUxw7e#qxu0}mLo4EM%QwG~uND6hGJOC5002ovPDHLkV1fyp;#L3v delta 485 zcmVORFRDpKi-j3vl``wE(oY=t~P#Xg3_Nfzz{L4wVTxDmTZNq_d~Hg}E-C!iA3OgqzW zc?P~S=l(h8iZzVR&UU<6EI7pMBT@qZvkB5qgWDhto89iO_Z(Ukylc1XE`;yE2~cA_ z3!tBQ|Lx1w)$ET6#;sN?>BeA-0tkMa+1DsdhcDyql{`t#kp@NO00vt~gK?6audHC) zYQ;!{w@Lqk41cquWhKhxACT^WZOUPe+2<%tr_X;YU6v>Z*v_5k$LVQ9&OL5$T8gr; zEZcSRKCVCxP?Ptu!>mbFm^Ev_-l}iW^|gw)#z|r;!h23ouc`n+-BB^lU{=`{z^n#5 z0G~Eo)1o{$q)}z-BaNJeFw9#nrC+oVhVG!(n*jX^5?=HVdcBFuFT@2fFHt_vozJZ~ zO4BK3$3RwsJj3ibO4I49fs^;|&Oau}fX>UQ_J2p_vXbEaKG5CpbS;2x@P7ZT{M}bY bna`FdFUZB!2{FK}|sb0I`n?{9y$E00NXrL_t(o3C);2ZxcZfhG#Y|KqyV5 zv`C18Kt~Y;#D`J<0<2Wg@e`w5NR#ZM0^y)lXrH{ z)}C$d1AFaT>FmAR*?FJ4+uhkYrjkYOMHgs+?i15ZBDswJ^M6FV=-kLL>fcG|0LLdf zp||`l{#HhUix>+<3-qw}h}bkpIYka?Pro+lU|z_Oz}ycUan)QZ{EROH*u`w zIm>RB13b|Nw_kq9vim2HtgoM;bIZ@r`Eizm|7dH`&+azw?ED$mcPx-Rh?X%n+BjCn zb(;8^&>qHEoqylN-CKA)syzLm6L0u19ByCjOD zCIIQSvnoZ74F>g5RdAH0hC#g#psQI>xw9jybD1`<80ztEnLa^n!D2L3vDraTr2@`1 zbb!Sqd4E%<;?!>=Icmpfup=T4OY7<4?u$rDi z3P`WpOcEI-p!Phw=~i7TJ(9Jm$Ow>Lv{1jgw?0t~F{WAs-@_@i>T1c|30CHFjN^5` r6Me8ELKMKFH?0p=KA6@+f6_YzwN2&?*YWo)00000NkvXXu0mjf4m3>l delta 702 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 literal 4491 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 MC_U8*W$Up20J2shK>z>% diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/directChatOff.imageset/directChatOff@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/directChatOff.imageset/directChatOff@3x.png index 176f89edce8e93a11f287021a8f9695bf445001b..8759d79fcf1dfb8831cbc06e2f478fb19c78a6c3 100644 GIT binary patch literal 4964 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

_$av)fE~zk3m1?xw269 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 diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/directChatOn.imageset/directChatOn.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/directChatOn.imageset/directChatOn.png index f751c6c066413a27dd7c3b7cb8ce8b1e4e4e76f5..1d093e3e9ddef65081a85c59c0cb7c013ee177f0 100644 GIT binary patch delta 1170 zcmV;D1a15A4z&r8Gk*kZNkldP7pV3 z6Sd7kML`H+*QNL%dbKDD?nIYTs6t7s$t0j4h%Tg}sOX~YLeUmCMHj6Vv`yx}$M2l` z-^tA6pMR!ya_RKHuk)SnJnp$SMEy4JUE9`Kzmb;w9keiWH-8;}acle9{;X|WG2n`| z)umYgPR->uvFLYa%+H9(y%=vMW>t2PNluE;Twppvd;CAtDzl2Trq`Q50-E>NyNupt z=Ev8dv`&b8m*+H1kN6+^A<^#ERv_)G+tu<9pWl#W{D~@u+)m!T0CTko(|?3ucJ-L9sep zcMr_&k8AapA1ah9nM&mfUMOF|cRM_Buv1~@xI2NVIb-bDrIiqf_m<$qFLrITPAEp=lXzym*R(x3Hl zvnCG&xRwdsP)wD6$_b>c%Nok7Y&|?zO(1VvK-m9|6j+n6?*`^7AbFs3RYK(i(vg{Z z>n~t@Zvc$b-ft6%M^5MrVsWYvyW(SL1tdr~W&m)dTGST@E(nk;(WCy4|5pc!V@P{n zt3&OlsDB0Ot>s=MP#u@y{vqu9GlZ45jqqJ3yXI1P2%?!{wH*CCmjeL)1t=rB)QyCe zW)L0LJpnQ_`TFm@?t>}cNwK?Sb=b}InEA1?St_D z#^h#QYHfBK;@E=SPw>b4`QBGPz*hXL_yk%S%MJ%&P` z=PZZtK>49K2^u~NVUk=+ASs{s_qdFYG1Kk3*{sv51|}AQgwXNTaKNl!8Nq}~ESEUY zbbmhK)f-7)lSF$CXu_$h7G`$38h@tBv2!KHm}}~VD&@*0?$N!foKVYolpG(;>aR{? zS(^8ZZbnOtsF|?~FKu(#@Yh(l5sH@qXvZpUzw-apb9yPMWG?wW)Rp5+U6@NAV6z+( znHzdUhl~I2q9@)wuQ?Fke!@F!BY!G- z5*YY5y%kBe(>0@aD!v^LlCf=gzidgT(u&EzwMRf9)*G{yIk^pY%ZW&U!xsFBw^_HS zixQD_;$W~y##^)#3816#ffq1uPq}ppgS{*9_bc8N!k1PFoIQUc+_dR_JRwI=no8ep kx_MwNK+EOqwBr2-Yl78i^h@MS01E&B07*qoM6N<$g52Rl@Bjb+ literal 1905 zcmY*a2~?6<8~&Kokkp}EN6QE^rzQb$OGHXV2PQ1VCG?p4Mx%&;f=dpr<&q|vyOyO{ zS(a8t+PIZw?xs?1In6ZcsJNG?nFH0||Nr-#_b$)-+~>LPJ@=fOWP9Rgd5Ag$004O+ z0Z$f>FiC)A#62@2VnsYi`J3CA13*>!j*p(wlB73*Yy$uh2LON@4*=_8h&u%Up(p^D z_5c7(E&!;~3v2DL;)E=n;LHSo9g30w0r`b$0045PI#5^?8xqDlI0)hC6YS-S-~`dd zYyiM=Fyd*DFUu3g2@0e!F&s1aX9h+*m%vCk>@$V+s~MbPV+*qkX86Jk5e5hp90!5H zU|5EaABK##{<>YfGJ^-OSab{$$!4<=Y<)y9!yl<s-V7?8MGdCGB)Xnn!J#ZOI9y`%t$jHsi|Y4ZCmQo>S>ghbk_=K0fkJ-M z7H`E$P|QgN)mQ8+(Z}gwKQsRi`|5*5O3eS~FkdSDjEYOeL9obg*M@_TnsuB3KsuI) zH+P`OK0I|iz|~O=m%fop;u+mca4EY&xMM^i6}Xh8T#r2u4e3{sEhFtJ*B;^@q?wx2 zwZXVU!~#;u=`6hJAvpNu`G+m}51a_0`&^(8rkZQ02l6(KJfATHKqGH8Dn-?gosUY;pKt;*ZpD?94Mgln)qqt6VLSy{( zdJObxPx}#)G|0XL9rhSX8s<^)I}d03@6TE5FWNkcucdZV>uG>gWQ?lAxN-TgepmP8 zTeC2Ka+w#1A-oqywDQr$#MC)q(2cZjL;N2zoErqTlCgt zoaI#oyLIpji;@pYR@F%$j|!>#ntX#d$(wWb^(H`4bw-IuaTvbxUGsDmDRcJ9!+*9N za17B~E)HPDUr@`9BlV`$o;lUdwNqW^`{L6vgD#kwglf)tLG4fspYYyHj~g(E=m<5v z!0Ob$E)B~$8+BT1*V+BsQDo8j|5?g$_C&ef1uq!XNjipz=uM4|TRxQ>xx6>e?}7Etw>5we z5o?wB)IzaNCVKD}`KD!UYTsh2vUXUvc3SewN0$UT2g1IOhM3%s0b8w~P`~*&iCxt+ zpQ5tPm z`|~~Ar3&&iR1lv*9hn-`lqJs+7Hg&kdKlLz-mJKgBJ8;yTe{;5K7Bv;uj zq&n~1CV42X>RHrXy33?uAgnY2?%TeqU^9#R5E73*=m-T2`pPm#*0V-<3Cz2o?ibRJ zdZAD$q2rUBx}~>T@eCG*1dR1-C5CPHd%on9wvE|qSnj;h7}WJAPB)z=Ov@-3&i9gmlqNUCC;J8-yd_GkbvJ5VTXGb7 zjHmN|np6L@J-%h7v4_8*C$QQd_i2PO<-KuZRQYV@l#rGi&dVn4oaQyiyFH5c!00zl zgKxh*Dgw%;Y$@3-m!b=!c6xH%W_7263T!|S#Fnw#kFmD;|6mTwsqDQYa}4>%>cxGB z<1JN(A>NivQiJz&YGi%->|J}C$%fpcTNM72_e~T2i(7>i+O=Riz@)5iN{4g^WzbQ5 bx$R?vEi&+sYESN4$;U>tI)SgW@QD2v<$OsS diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/directChatOn.imageset/directChatOn@2x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/directChatOn.imageset/directChatOn@2x.png index aa575b59a7aba4e90e9325108d23348c70bfdc29..0a60d421bcb531738deb848926e7bbebf14c0f68 100644 GIT binary patch literal 2542 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 Ef=u}HegFUf literal 3462 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

L0{}v0YYya!4}rwlrf&uktnj2=+e9h5eNuF*Ns^ WOUPm$>U$1z2>00004XF*Lt006O% z3;baP000bnNkl5?8UDLx_jd2a1p^m^$ZuGHNp`shpy8x;H}MaF{~4@1t=>h}Dyg|2T20PaH!05yZ#v+(X^Cmg8@c*;PpL z6biT!)G$S8BIj%Y2{D^7nl6Yng2BpEfC(X>#_S)0#C9gwtCkgeo)$lJj7*c`&rX#t zSMm7=ce8np!D%6J_Cw)&PM3jn4p5Z-C+-ZQI&NE$epnlaq9F(ir*{ zAS3xZ?mf?7k%fTm7NomUr3DCa`zSH>39h0AQe4r;bu<2cW1Tqtds_Cr4?OXK-sTS6 z4s$$bbUU>2tH^Y$luBwU?iqB|lK&3H#->BVvBCH#krwiJ7t!ChV`3vMHKi*TcrXIb zL1rNBYZQx3H5FJdAwZcmog;)y>Ud|&T zj8bj&z6;_$Sj}zwg26}CJ_r$)07Pg`Kd@3`8HEys4?@61nkdRD#MQGK=10W*hVAss z&cOWP0VSKrh_C0T%?iV2ErN@O0qi(QOIB0A4OX^1Ie8ci?1KR}?isW|fEkK$)wp;C zRPXY5ZQ&tww|}`hWf$8IZ-IadLp~Qy)-8%L1+025s4Ek9P)(KVbL-?yKe*6ZIILHq z4xXnNEii3WY&ln1y8yx*r{_4}jsFMj;9?MF9$JmLiZ!Q$pdJeJ3Po5zv+V11v!@+g zfH@b9*hMa*3?r@u9#GR}bHQipW>c@=TkdZHu+zLu7P3iDe1hi?%)^C*;ZGH(BQ!BXWFu?T^ZbPP%(V%HTDaLS4({<*fb!-79;3Bx{ zTC0{$VF#xrMx*~YW$HpD0(aOKh=-t{_W z8BP~7zL+Z2I_;%TbDP(ngs=F&Vg(nfiX~CvO`ZJf16S51CJuthZk-I~jFu2b(Yt(I zXMS42g{9gJ=8ouOFlV$F9mgWR!qr?jy1URQ6eYL-_Au7{s`X@A%2coB9;3fu%KBeg zILk2+n6o!%v01p9OShSF`KAQ;aE`I@l^ys!fT^CnzKA4AtXFf9fi3#}gi-y!CdsRC zqXfNZou+4WGpHS0`rNv`!WJ(>8+vpz8w5S@`978aZo|q)?QMmAaDjkrS=*q!zY7A4 z0BHW&>gf%nrUe2nEnc_Bvc)gZNECFZ0{s2k7W4!y`EDSMa4_J?zPUwzM|b!KYB6#E z8t027_==%{*g#hIAzy?BNes6%z_7`zdk-b~VPHDh`<)kLdGCFv^IqCm?6Q2$vh7Ex z`P(n)q@9XZZorkfKiT<~xM}WTtjQV+LC3-dM-#zJd``u5rtz?`$53orY_cAv=5;S; znm*g_1Jjh047Hi#umR;;P|{_v3e^C4z^+MYDs+L|-;wz*jL&0sclQQb`q0sod#cAL?wWOu!iYoK!jE;N)xMH4r$Jf7%d$aE@%o(Vt$ zU;YFe{vHbPAf}-9!#`eLx4Dfqtzy=y%!~mcG|uZ`U%6C$vIKCu-(5D{_OncYQuEqBsCRy^ zdcb{ZO&t$~??DTF4H%m2W!^7?L8R{oxfePqE#P@EinfM~rGoOVK{9y>Jlvio7 zqbROMvrnLguBWXJT$>7$RPo8HM6$2j%rXoWu0jiY7ZPF6J085Ht>T8mHBl}!fd9mJ z@SU`azksgukoJEJ&E^7FDz_J4v(8$Wf(a5lnYp~G(w6tbDM-1zGD7Y#aF1t*TG~%b z#=big8$2|#P;Omfkg*0Cd_(~#Gas(NrjilzHW>!pO_9bSZ3ava?k2N=lkpW~_(_%N zh`uuR85~@88*RO>J{=B&gNqZEc!+MsK=zl@5gJkN8C%Xp__OI`9u!>oc`H!+Z%#*K zq`ilEh`=UZPaWo<0H+3b>-~)&vdC*^M;eHO%8SmE!P%|!#66=^eU}nk*x6MWFZj4j zDE&UPoLO}NQ)N6H;(^H=UR{pbojgD}69TsOQ?&6a&e&skIYqvWyClMb?ajPLmq30P zKJK)7#jUglE?R>Bd$#7r>Y@f?cK}kypOs($WLSq1u*nnyor~!_Okcyhv#=Z(Ay zE}sT7a4o=$CL>mg8;Ah3t{l2|12y%!%Ba2=2=2u+j&teLG9)O4p(7xwd0F_z{<9j~ zWCOt^s~)G`e+i{Av~ICWW~AT9J;UtlI0|FH$y8^+ecHt7M4`)IUn@sCRGG>jZqz(9K9B0^oJFWvi zGmEP}DqXWf04R^e2~X$C)EvM2F%>S@x!I8_rBVoZO#@IJPaD1w!N{V6a*>`KszfWS zE9~w#syi2py&0Q;Wq(C`dT3$6s<;s~#Ow)}$q|hh4R_ZesMn=yh6vy%ag=Gmwaj3= zGK7(Efx#L)mx3Pz5(c}*U~$(J4kscC&2@h5$q(^TS`PveQzk}XHiy;W&)KFV)f#_t z5pXGFhyZ}IBz{gZ*aBSflNmxJxM6UEOF;_)m~dq7tZuxgQJO2u2H62NSDt`vlL%q+ z8xAUCGeJ<=UaUhc1z!l@*9n2=e*o{15Y|H8i;V%>;55ttQCEw7WiYZ6N109AvGuAW zZeOt`j84QNR1u9E BAQ%7u literal 3221 zcmV;G3~KXPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01FcU01FcV0GgZ_00007bV*G`2jK)6 z2`)AQF?(nL000?uMObu0Z*6U5Zgc=ca%Ew3Wn>_CX>@2HM@dakSAh-}000Z{Nkl?TO8GfE`mJC}02$F&#TX8{XWs4pClyQ z``!2X-t~U(JAlRD*|PSOexE^t1U-Gh3>Mb<2Nc%&`xn;w2TWfugY90cp*(G$lW8aT zIv=VEmbU%;y{CRc*O|ln*+`cVSp*#jYnK4ILN%Iz7C=$-#{_o6rWys(EP_VS;l_>m z%Z^4}zh*tErY+A9&=Cr2%HbR_l;IC|Ii#O!Bpmkn3Mx-1=MkI$pkD|7{is0R5RDAGNuDt@zK6M$>J{Lfxny7`M9*MO3sp8>a50HE-dNBY}y`Yr`= z1%R&uI30j90k>%cuou9)5cyNU?X58ThpN2NuO0!OEo(7u_AR)F#FE-FyS6*$3UDpS zc>qS4{!|1I8f#6&dOr}6&02Kj#=O#?u?Z>|a4(Us1OXAXubN}n;^KPWFe-Hgh#~ClEX+B9)bS-Xph42mr8_j^1yAie7%GzZ#Uij^vF19431c20dw;5;@p=LimN7?sKU@*^iUF+$4Mfq?x2MnHz&A zUi);Ai*18)902a)DS9IbBM^*yDPpF!kNMcbN+$t9sw zMMo*g13Yy;1l(Sf1pR$USqS0=v+!Y4X>L00ZwVvJuFE zb&*Z*0!xOW!(Q~Mtcz!y3!pEojkZndsq%Km0y` zV-_dCmdq$9={vOe&5CUVrdd?@Awd2dnCx9>*-`|6odB9FO2A$byl?4J1O?jx?6xQY z2L!Uil9_NDM89cW0^~ET!$C_E(75mLHVFQ0Ine_U@Pl9HFW=#5C{J3KP0|UdUT}LO zfNcOivsCH@d_=)J$-Yn0@_@+u;HqiMp|!k1#Tg{NV;vQcmvt!o41lDbkV{#jR2=lL zAo&my({Pb&?1RY70k^k0**8kr!7M;t6Om^vviqNe$m?cJw!8+o@4TCnt{HVD6{~Ub zKChm1zMmo-zN#|6v>_GuOWEPv;Qc=r5^q3c9ga6lq#GJ3@(7jsI8H)oT>>HqxV?LX zSSOJ8k$&$AjzRDT0RDj6yFXPoP1)(_lAz%WnsDHh3>6( zdk+FeKSL^d#Zp=>_U?Zc{?m-pe#Q0WGhtIdBRD(O0~#k}Q!4yd5!OGh%rD&v0INi> zCPhm~sR;_beY~tvnP0jUTHh}sFSoNN%*_)?v-uGDE3{r65k3Iyd-dT|CVZ*I32mwk zzPV7mo!~S?pC6JWuW>(sXC;kY8g4!^2L-_EKnkQ%9cG#RS zM#AP^M}Vi^A0_k~YWxEnPD~^)6~H%y7)S7%NX=2k{|c}ZBJTlshl08<_8blV@v@s+ z+FP$>35cCgRaEC6tn8Qo;YOVgt=}>PL^9ui z+uIs$miGhIIDi+EvKYqXt2BeWE5ZPP7Z?uj3>1_$#(S2uCLng^+tLr8WYeC*IV#Jx zh>CXr9GMoP?l`oq5iMo9IrRL%F+&cl%l&TB9Cp$(;g&CsU1jUzc%Di<3h>Ny+3P0Z z3m~!K=oBdWl*{qN;ZF};68Xm!@?m;wfG6lfmD||;MQ@a!rJU+V1m^)5gY-Y9E`Wpp zI!tm20r*HnHZ}d_rMs(t_WN+69dyD7h|GRlSX<`EvN`4`s!|e{v}U$eK^VqS#MmzW zy(03Q)_8bhzIS`;W@DB6)cXaP7~vZOjuzLKyRqnAP;TSer7#!&Nfzn!`w9BX=0=7c>#|8e0r z_!WSaARmYpzG&+UJgOuv1ZR@!9+%xYf7&y58JV+tDLg@6Y6*zeBi;+*CPeiEiw0=* z{xDOtBsyX-2oxx#9vGiH>e3$Z0TGq+1S_0?tW@M}0KV4A7~9g?5c6FB3Tu69NbA2< z7cA4=8FSX<9qOqwgukf%F(;tsD{`et_>u8ry-xThZ7{#7JKLtzFPw_AuB-W_G3Km` zO&nb!z_Vp-TbApj!%eEY0h}45QN2?59X#ViD)qxGNB;|eu2)jKL_ojUm$Yg@`FM~^ z2uwi+0Jwl;v8UcQ+FU#83_5iT;xV@cz zx6oyCQ4*}U1;lMJrY8dfH4s@HaC@jPTpVG?1Pfwr&`dFape_ zSDUi0G$mRZV%g@qWMZnLk7~0!#led1o1jSTyJUO7CM_)&Q7IqLHa|yT6t6Pf_9r5! z1s(wJRk@ewZfihf_v<4^T_l$Q7!gBWM)>h@9*OTOWmEz>DpRPF+5V!J)+jpc=K#1A zfGZ>0PN5GW3$+f9h}4R@Oh9D!tHC+BwA+_}?30memx9v)0In-)@C^pcokCqr#IznQ z#Eme`Ovs>9u#swoQq1kP4=AkLFhrD^&NOZ*N@o=yFapBKi?;b(?Y+W`OTh7w!?v?& zOgzt^`&sf_r<0?*qycRQkp$ygkBw*0eFo-18AoyAb=$We1#Nq55OKoD;S9P60nPwq zJP^O(yIlfQmSZBwi5U@|vIznNc}4Xb&h4TT<`@9uG9v8u&KHwA9!q5#6YuY$GTEpS zDlrkp=Q(E3y`4|f_v6vd2;?XNBDL%5H!I8eZ*`A34u!}*_|SQ z;8{4{I43X~6*B0$2@0Dmi9(!`etQ~lTD*)pgYMKJI!1dwpeg1unRmb4gDqyWOQ#4B z$d1;gX%}FDj~z^ZI05{R!rh%BKpzX;rLr8ak(dNz&i*987P&-pZObRSpYD{Ex@^^A z3|ly*FUhP-IGPv+L`!33{?cPjBFO4!8dtLCWPa5VJBjiC#o{Kv?n$7v00000NkvXX Hu0mjfTUpWP diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favourite.imageset/favourite.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favourite.imageset/favourite.png index 2eaa7af25dda7bbe68f5a357f1209b594a69ce99..a073830ac4452d1a53a5806368bf94d1f517faae 100644 GIT binary patch delta 983 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 Ef`*kiWB>pF diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favourite.imageset/favourite@2x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favourite.imageset/favourite@2x.png index 3ef541b4621c7218ad9a7cf213864312f69c67cb..9fb29fbe1e636384bf043293741bf58879fbe304 100644 GIT binary patch literal 1869 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 diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favourite.imageset/favourite@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favourite.imageset/favourite@3x.png index 6a957e632a341fb02f99cdc2526b834d78b7a1a4..032c4c6cffe0baeab2c997c9a4982a30e7ab260b 100644 GIT binary patch literal 2770 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 diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favouriteOff.imageset/favouriteOff.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favouriteOff.imageset/favouriteOff.png index fd86162d3a278ba107d3527ce93e5547aa3efa4b..fd5c8bd532f9333e2ec0bfaa8d5793df18679dcb 100644 GIT binary patch delta 1173 zcmV;G1Zw-}38@K?B!2{FK}|sb0I`n?{9y$E00dx3L_t(Y4XsyQY*a-QK4-PS)M z7?cVLnrN`GCiY25d=O(Iy1TW-CPqUvQJ^aRB&I^UWCu!%4;U2^f2tuSfRQCFrCUNI zkrXve2?3*~YGQ1n!YWZz`atS-XU1=q?$YhO-R`}0UhbVU=YRX=n=>=#p35{_OUW8i zv|2c{1THmN>u*WvF>2cW{cMney>IhEs;FAw7`np{En>sxR5mk2&0W912d3i2#a;CJ zJC+KrXeZ_;FgRq`{0!?QCceuUb2~GSs;t>bkIEqzHYJw{L+glm1C#mDFnvdw(j;gZ z8GaaiV~Wfsihs)E)3L=O2I9*FhlZi`6Fotl)FS_y?o3h&(ZH=_OdCjd=~&{8!g&9d zJB8yM19niGOq^of=L=)@CHa^`)pZewd>aegqa%r}`SB|vK;k%|Z$PqEMH74T4xZ1$ zZPy5K)oF<7(NVdRk{z{9b>&%Q%&M8Ibm1+QYcLOl#D5ZbMaQHo&mVbjW`bUXy-F94v5oFkr%ag`rAMWfw z&fWa9f4TsOfh~1FJ%ew|D;8Z?xiZ;SeD!wFq4=!G7L=fbB%uJi}AGv}Eigu2& zF>w(J^;1$_T|TQ1Ph@B0r2{~WsEGV9kGvuR78R8}*p?qe7%G#pGVk=iJl|he;WY3h zqJMo+PmDe{ofC7q8jAtB58+y%(&EiX@t5!iyp?HE5u8 zEt1%zv!r%^t{9n#^3%r|fPg_`=&U+z)_6g^M3B9$!2MrF)W nL?eXX#QRVftqCf?(*6fY5}a-klnxX$00000NkvXXu0mjfTthi> delta 1236 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 diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favouriteOff.imageset/favouriteOff@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/favouriteOff.imageset/favouriteOff@3x.png index f2113cef03f08e19ea2bc5e6c96f7ec97bf299e9..0785e80fb6b43e9b0f41a0752733bbf9c2f62032 100644 GIT binary patch literal 4440 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 literal 697 zcmV;q0!ICbP)Px%b4f%&RA>d&+CNJJF%$ssq*q&tt~#lMjw&v75(EW5fU|#~UBtx?BZ!KFh#-O} zIJl~af~a&8bkGl=lUOK9y?F05wXN5?OY&YX-V!KBl3(AwaCsNbysKE+ykLxv3nuQW zmFm>a_|h}{Zu7NpyV37(=ah3czyv!^!DL0bG6M+C_)t2RKAFE<>#-S8xL)m(2yfmu zZ{l;7%Ly0GSGrkO?i4UKM+Okg$(}(Z08w_`>HYlTYYhS*+cB*WF!u(C&6qGmAjC#Y z6rv@>CQKYeD8vR#Ttp-!NsJ02792;g5!w(; z3622sIKAW$K3FjNS1NEn6^K>`WFi0a22cd`e~+f%p~ z>-w`p#Ok&U2|$>WHe;L;`6}?0450h7uEH-3%SljDWh+?pX1Ol`E5!7}OjILO}7X z_P7xi0ns2)2x<%pBrbvyV+>J6P+^Q9x(Eu4HpCQxjnRT&Auut@5Nre%MhQZNz`(?Y zP$Nt+v0hQW5gGr(Bju|&V74ZfUvyq)A|vvP;Dgi%85L+7_cPI7n?oT&)$auUeel!%-o5Kt=T*O5%S1C>9hn fggEgIqC9*7jj`9Dk9=aL00000NkvXXu0mjfn^+y= diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/leave.imageset/leave@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/leave.imageset/leave@3x.png index 90d97382f03a45c1e2e65454a49c7d1cae534f18..d0b772d2475acff9ff690bcca8c1770bfcc344d8 100644 GIT binary patch literal 853 zcmV-b1FHOqP)bK}5kN&CtcvWerN1NnTg`X3_R_c$lb@F_T@rAbNE&Mk$yxlVtLh#=LF}X8O4S*Q*qXe_Od%TtH-MiZ7?N%tVNegbse4aHi!WuS(U{uk5s-Ox=<5iEYF za3ob&yintj)L`*JO-E9J#RC{OO%MTYdL`dw literal 860 zcmV-i1Ec(jP)002k`1^@s6zS;;x00001b5ch_0Itp) z=>Px&7D+@wRCodH+)a+tFc=14yHhsYf-?*U0I@@2iNppp1B18*5~qL+gOFguhRtvW zgkWaH7FHaB1&Q(Jj;pktv`+l}C9b9Bzl!tJaa84%t?}jPdv$+yV86gJ6z9y@yTg+c zSPUBqoILsQ`tID$&W*J<;qskx=l06M9$!{(tg!$TO37gBP@d{f-86S1769$RJVF=L z``a&mwXuo^+XfYIV6s+{8%rFF5{d##42&9z3X2_#1Bw!h4U7wl8jBo^6N&?i42&C!3kw}g z0*Vt04NMA(8!H=35=sIqob%|is%FMMgB2(#Q2}WvsAt!EL)b@IY#%TUP=FzY70#Uk zrUgnGYbTf{C=FPhV7041wDVCh_5*1a_>x4CybaseyU~aFUjLsDlFb(fE%H&4P*4vo zSfMWKeV8UFsLO0oAr({CG|k7*qE@P7zxo#Sdu5Z*iW;m|XMT0-Ekzz4U!0!$HSxPZ z1y&0xgk7OC_bu#G402v!d$RbcE`1EAD^v0`OFsQ_ccLVywnW5Gg%5(Oj2B7hPDBgG&D#t zjDrDc2)iz;F0-%!);RYvdOn47qWYZ^tV6&3b2h%&1rH6~ zZ9IP*iX*{aS2o~WHJ4}_h6_2GYYk#sJx>g9}D?Dc}C9*c^WP}Rz zYjk6I5-d^B7%W%OV@VFp^r^}*Bj`)QCJGYR7gXFANe<2Q1(^AgxMj^?fx^&TreyzU z4xEl6#|4bMaYsGkh8cRD{wn6lqxHa>u#bA#?5cXd8w7c9pWs>gtRC2^&7k|7DRE`J zUtEy40)In#nY)UydSI)zE0@Pq7^zI|QQw##@45lb?kD8!#VF{e+WEIHFt?7Q7f(k0 zV}i`A8y(!fDByp!MfQ4-O;L{j1V`-yT+Rh3PlOk2TZ)@JH_D8)5Tn}`)(Ec)8XrSY z{Q&s`;Z5G2^78u?2F`~jli6A$tO|N1yPgC02Y=@$ch?5mRR?A4AlDMFH2hM?Dfo2T zeJ1Ol2t*&|o8)Y}gkn5gQsetS2Z1g%FqsY!bejOLg;^#BY===;{w={_dE62lV68W-nRU>KM~q?-&*vik^Nn&-OHfZHDMDQG{>O zQ?!2x)Sbfg+3%AgK3$OB^~Ds2x5H?Kf`5+0ruvEceAVr&$EMlW&tV#%)^85mSHxf^ zMY_3E^EtyFh|b|dYnVT>p@y5SjwRMcU@p@)o@5X>?#ZAXuVN3{r6!|W0&&M1`9{ZD zT2ilQ*Q&wCB={&K;T7~EtF^9w$Ntc6rnDqjB`j@UY{YvsY=^T(ZrAB%gld?702EXg VKyAd%{paoMUTI^}t#26KcexZ;y!9e_9TJ8hAfTjuBgg`;D zfx@-r17J)|8WT09qzRIv$KCCYv&GlEd%Wx2K{t7CXLf%xzkl7G-PuJbpo9m%T3{CW z)+xmM1c9NDCS@Ys-?8GAKl62i`2cHscX}63Ej`dle7uP%cEIlhB64tSCuLaDvMuI5s+JD+?cvr%OT3=<#^qEZ8SZ?hVSJjOyW=i~~P)@~fsCd_N4GHc8eRs-v#S4T|3lT*nAyw#@@$=*n zeh(d%3Zp#mGa9Q)2H~xyTYsH(9)9f6m45)nQXb_}1}@{CMTA(wwV#iW2?R-YoMy+9 zyy>no?xIpKjG!)#|K2y~w&SxB+Q}`MciIO$`V?m)9yke5Bv1&my&|;B!sM!F&S5TK z+wh?`1mZ59O@OKNi<_4aOL$fv^HsDxm%Y`Wkyx!pw>p(h|7@CG0146dU}#ihT2zN3 z%Q+}*>2&HRHygLMLYH)-0PNv-b!%rlyRD?u#`fT*!*0&q+6p4n4#GoS%S?~wSuN{X hcT~N4Nz3_`{{R9BawD?Vj)MRI002ovPDHLkV1jRZD`@}# diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/notifications.imageset/notifications@2x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/notifications.imageset/notifications@2x.png index 2903605f3ecb2102a741f47bb1a3599153a835b0..f8384254fdc9e674362f0c0479465dfe23720ced 100644 GIT binary patch literal 2400 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%0A4G&!&efdO_m3h!_- z@u?MRVQ7p52nucA$w(eBlrj4VuE`PT?1!Uh+9f;u0BMGitrj1Gbj7dH4IN-kzO!I+ zZw50I%z_C_tFIdN}tnZx zdYdj2Y|cckYrupQZuKTX@ZGm8tHQ0UYIex>7M#_QUCw|07*qoM6N<$f>dqD5&!@I diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/notificationsOff.imageset/notificationsOff.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/notificationsOff.imageset/notificationsOff.png index daf218e4ee47eab31ddec654ef1ea3fe7e141f45..251ee225ab547e16a265fc1f66e96e164c0bedb8 100644 GIT binary patch delta 1472 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 YKU7n~Fa$7v;Q#;t07*qoM6N<$g2i7MzyJUM diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/notificationsOff.imageset/notificationsOff@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/notificationsOff.imageset/notificationsOff@3x.png index 0591b69fb9e80dff4b8ba227345185896015092f..da6a19b1edc73aef0a252af7a2825fced7692d42 100644 GIT binary patch literal 5403 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 FV1hHZQTG4< literal 5019 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 delta 401 zcmV;C0dD@J1FHj&B!2;OQb$4nuFf3k0004HNklA! zC=~};%%dWGfRSH%GcE@(CZ3(`#K^$7fq{{Mmskt`GcbJp|M!2`0@KuO*z|xcR+e7F zz{se~`2YVOpqgj@K0OUw;Mnj3Sv}Q#4z+kK(30Q({{346#DD7<7#Ke=@=0$%4*^DG zmr%-vSqu!xpZ7jJiBRB^t_GR;_3o|~9u>F64F4H~{(pKJ01E-C`5a_1ud>WKn8gPi z8$iJg2CKtX|NU}jS1eHOJrkeIMpy_?&2pf{%l_n78>!G*Hc3U?SWE z5~rHwAj9r|e195=&0>%o7&J8eo4@I443PcW_{>aJs3>iygtN2jK^T|mEFg)bb8~>X zhcxi|-(T*{Ch6Zu(}k)UZ23H+6so3rR4Z`vs2bf;@ vwPOz#8jFtH)DHGJtwNXa@Bah%%mx4hVUoHVFu3ag015yANkvXXu0mjfyu`p~ diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/priorityHigh.imageset/priorityHigh@2x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/priorityHigh.imageset/priorityHigh@2x.png index b86c2445a3b36facb092b8cc24b10d9bcaad657e..b9121080db7aae396e4c3bad837075d6139ddd24 100644 GIT binary patch literal 778 zcmV+l1NHogP)G5iTdccjCzWU4d^@)f#__Y7VYsGLKPx&0ZBwbRA>e5na^tzK@`W|Y_^Flc<~^p_4luPE@D+kXbWxp2LykIwBQdAPhNBN zELhrHC@;_X)6Jt+;Z$c-4!Fd780akdi z9E@MQw_+9E01q#Y4T6V_0kCeXj!x`2@bCD26!#CmbmA|33}{VDVy@>J`rxoyEtLaS z;Wfj#4bUPE19p&sHXcYs^@gM^9@Il)0l!E${5_AIAJ@Dc$vYoMPRR4ywI=v>7DTRH zOFuj8l}dB?oGY+inHtNl57>n_!GH5%yi?X>M{c#491itrBpHlW?8FezU9c}<3~z+a z7NKvtC$cX4n7I5TTMy5?`n#J8v6J%pRxSC-O+a@-XA%=Vi?dh*bT~bZ^BTZ}KVr^R zb5Hj}*MV6q&?V0Kw@L*9FD?vy-3pxaP_KtZkaQtm>aAD08AvFf{Z$&k(fffhc1+hH z*-Ck`;J4;Sj!2~ibTMD$!2(R;1U`bI|H0A74qeND@sdf**3z%(Pns3;MYIJx`ooah5j3! zzh}&ZznvOAEv}OS_jSN)6B<(0OwQ6hEg@UArt+l_&JzZ_2lw}A%SeG^KFhd1%~mtn z{&?{5Mk^S*=LLM_#|GZ>{1xscmeJo>2JQAk#$K%BaxJ%;6fwo^rtjRo_ONg_9h-KHcJ{>OWnuEoS`S2{)t#-~wNQ#r`iHK%TVq1VmDeiuaX+=Q#) z*d#*Lc5do_brO2GpF~Y@wO4n)*d!v<6ep35%_Q)Z?_0*%-hSn4lX=(Xe*j7*K=CTa Rf8qcD002ovPDHLkV1h(|jjsRz diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/priorityHigh.imageset/priorityHigh@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/priorityHigh.imageset/priorityHigh@3x.png index a9e126e2dcfea7b732f6638705c6a25238b5386d..0007d53cacd9a1754a968577be4cc36c2b0788e3 100644 GIT binary patch literal 1327 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 delta 410 zcmV;L0cHNL1GEE>B!2;OQb$4nuFf3k0004QNkl2-TA%(P%XQG9n#F{y3 zIk6!{Rdu7OovOh}tYM?6o!F3~s=CqCPH}K1o}07HVSfWSB!BT5*3iI|bawU<<1;f^ zshZlA_+^&ib3o{-Q07EG>BavU8N|<;r2nRxOl_RRhC)zpYi|qfB*hpWBmXBKO-}f zD&v1fk$<0__`@s)>7!b(!yK_Xtl`(^yHA3EmT@vMF@-R(Fh>C8MA0n&ubGw6vyA&tv1o7w%!!4>Q$|$s+fY8R?->+J$M$cUPQ!$ zj?nr?cr1ug5UD|1Xr*Tl#k0R#TNMPwOR;3L^L%f^))o?)EE#wqJCN*Ve!Tg9-gmMy zkN|XO@yq6=ypqW8Nis;s7#vHg!%I4_lgC9)*Op20%r%*SH{l8mgE6+r{?58}uhU_{ zTy~aLg@L=$=@eSwN^~MAb=pZ<6$VY6R%nV7NvYFL(yB0MdiGXmiW5nZ)9KmUNp5uo zO`qPn{BWlxb=qBSbwy5{*5!vgHL26?a;qzHdiK`khdVXt+1p)ibw!Sx)*#6%n!fV;h6iwaZ^yUWg*~kKp6FXScK&|9k~siS z4RlzcD@62>#hvwgaH%ce0-VKH40?eG)@>NbZ+4^x8cJrvZUy-W9AGE{e|%>!vEu@q zf%$FVfbvkB`Xur6K#Q8m>2JHh`?HIX1Uv>tJRdnMz$NoprjViwS`@|L03Z0%keACW zwFJHguuP#3T2u-6-^vIvI3k{D8ax8V1%58D!}QfcaB-)@5?YE*Xi+BMmh!v6XU$=0 zs$1r6=lqNS!?_x8H4o!cU+VQmcyVvkL+=r98OQ2%XjdHz`H2KK!wK`WrI>T(sOP~l z>pQ{U&$o7qF2SVv?Ux^LJ^;ePeFOpa4lM9)G`ttEj6psWth)x5iKMW~O}jz^{AZhL zt)|KMI^et&{gTn4-R$2623WHcj5KmMo=xxajupyv!hE-t3NLkfj|iu|EWD1JcL7)V zDcxX6$NlB%S+X}c*v8IE7x&TfwsgH^mt!%dhd&~4f_JIk`{*rxM)`Y*Ehby z#!X6Fp4~m-?dx4;$4`nvPUfl&VWe4L8Pj>tqPhmo{|lvF8w6uenqHIYZYhaO`v;CP VDTiaH5nTWP002ovPDHLkV1iAgc%}dV literal 849 zcmV-X1FrmuP)Px&3rR#lRA>e5na^tzK@`W|^hXk6lE&gi@mjs=CZa~g1iZ8&h)|HCpdo3gDB^#R zt9bAr3bvt%^;f~8R4Y{?D1xZ*?9a9~DhQR9qHTWdI4|qQP;8sTOnjj;kZg8m=FRu> zzAw9*EP!f_mw}VX!BKowqr9b>NmS-AU|rQ}X{vT&qt7ckjwSOi87wCeoWt|j-INa^ z5xt!8GRG*#V_Nv2%nVbDy=EO(;M7V{wjSlU>K!@&7_VBl?XIUd#m9-$pB%RK?TPdu%i z&htDzBjlvOZ|(}Ga_OAkfM*_r?|E`%eYMUT&{lN10L}D_|C+b&1I8l-j)I1L{hv$W zZT8mjYT*As!(Mb6p@(*y`iN^_BL|M6On46P4jA)T?X49#zZx`Ia1%bim<=GjC{?Xo zc!YMgS;iPcr}?K`j_)sZ8e?N4>9`@yaDD+6{H5^S&!X*S|I%&n>3JtYi<9;q0~-9- zcZMgHj>CO%^#BOI80ds%HXwF4?p`CNFKWgDoNSZ2=Ci=hJZD zjxY2*n2d^?01Rm%hS1#JJ|-?#zSW>{jscz=oR$rZi(wN=e@x7!+>Zm1oN=VQ_rJkA zZ7@@q{d2};LW>2avN;}D&S`Ts(xq;S#O;W7=1WG`{UUX5g!C{BHnrUF_I)kDb9f_4dYgG1%Nw0W==kpbN%Qzh+d`?Y zG=O5?v6ojjT3B;JIKLJ3iLcKjPiF(=LgSo<1V`b&;YY=f8fzLByKZTxr||e%Y7J}N be=+G7h_N-7@h~ZT00000NkvXXu0mjfkG`4l diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/priorityLow.imageset/priorityLow@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/priorityLow.imageset/priorityLow@3x.png index 11b8e8cfcda3ed06d8e8c51d664e484845261c7c..17a6cca8cf047061477a32362a5824addb004040 100644 GIT binary patch literal 1344 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 diff --git a/Riot/Assets/Images.xcassets/Home/create_room.imageset/create_room.png b/Riot/Assets/Images.xcassets/Home/create_room.imageset/create_room.png index 54f1920c84688157b4365c0f0365775f1890aab9..e8ee4dd19029ba680db0e3ebeb40b65c55267fac 100644 GIT binary patch delta 1149 zcmV-@1cLj=3z7+tB!2{FK}|sb0I`n?{9y$E00c=%L_t(&1?8JNY|}s($G`8Aw4@XX z@eoKbz(9jwWB>*RMqUy~sAYti8E6GmqC5pNGi#}kK%#|_fuUt!ENWmVLo0!J2&s_J zHu3TO&rO;*PHVd%*vCmt?X!LN|K)t|f0+J4*grYak)NJANPn6RYo;6%a8q}?S`AhP8UX}Wm zjgo2fXSgV@_3hm5+=H<7I27pmvHRQSo#InzJPt({yY?qV^hBr1p80j+@~5Dw1qRKG z4jphvKa-YpXVAp|>U~Tzium;6$-%cl@(EP8I>v^29e+))V*?2?`NE+I+FAmd9=&;` z?C8hsua80G>nyZE<7#)W`094NxYbuKmxotNBo5b8iu)E$430F@(iGIxNxZIYZ&{m3 zT`iuAis?wRI_q0U(Yl(3Coz!t5_A@tq22E*X#hn(i7q5o4UeC4zc^{2pdAd}%MGCU zX&DUs<9~kAD>BSEw1dI>OkEu{!@APqyX4eMFHYs0iW)EQFjXxl{+gd~4#4oHVJum03>}%1pKFfkdgOB_>lsrbIDm{{HjpXNieA zSvHBq@T0J)d&@RV-c5;OWuRST< z$PjE`RQZqZF^RUVZq|N>U0_t?H~_Uf2&2NftKF0`&J#wN+1L*XMrBseEiY0qDtDW} zc2eHJspmK51+!uP76rZ41A+ADP!t({&n#5Ox_(z}ic6baEz+A?0TrYKDy1Ie-d1RG z(|_POSp(K{txGVbDG8%=FFYGlc`cI#M(JK;1J?2YMrC%IEe8doBBdrQ=alxA##L@t z4?qhR!xrF+P}op~XTVlauz}GG7+{RB7u03@zZS=g#YNm7)|IL-RqQ*}u`Vnw0_s=< z>nt%Dq$;Rc(H4t~HK4*$S)~V46%;4%@qb9CQ^awygKRPxmSu`MQ0zXz$FqDnnMYu# z-AMyQ9VjATR+6R|gNQ^1Xa|E=d;=&tSD2M#*fit4IritG8QT3^WeuQ!fg=lMrDWAt zF>8qCW^OWHP{6|7ky3OX$4Lm#+RTvx{Y^n}5xyN})sN#i2WVW$V+8GH2)G)AYj&)1 z9>vewz{ONbU067NO`L5jhd`i6BI%~bz@UKrFKny;MZjL8@gmu5OmI(Z2iwcyudg&^%#}`*=Y{-10PwD#A2P_5Y8{3FmZnXz?IWlpMgS* P00000NkvXXu0mjf%D*%M delta 1461 zcmV;m1xoso3C9bNB!2;OQb$4nuFf3k000GnNkl7%Q6oB8%dgJ_5X{B<> zfkR1AIS_&?<&YBPK5|Xl{oZI2vxb| z5D6!gLn{b9aLA>Hwu%$myEBjX+^$(~lJ$D!Z0sG$+L@i%d4KQQH$QJ?#{xDXoXlr; zpfEnSwLYi;`{>uB01Ole_)MOlt3Uw;fRZ2z^ji{A-b$c4_f;zWsM%_IU z@+-!9bwN+eXYW~B?WtGMR_2?+xPLK~e#uV<-=>?%XK%DRB*R&#_He5U1)8DuUj}{9 z@8MR;?xpsx*7s0w00O!0fr3Q4I+&U$&-&?5N(h9JjS=@Tp zfEJ;gYq`17t!>aajV-Ip;tEyJFk>y(Mhm6@20c`Ben+u5kBIq||9z<<9;0$H`fM#2&-P$3RSBAA4{vi;Wc52QrUHR4j-LFqgDl0-w?jy<9NPVz=C?S)$L#H{S| zTFm%#he5)uq2RSBVA}7kigtS6EbPVY6ROr)*r8+%5ke=~Ea(Yc4br(7^f8lz!P8@RIYt{IQuy0JKG8-PO@&#q6_vbI% z>(YsqK2WtP?fXBznhAfPib1)8Wq)DcY{h2GIu%H_dXUVqW-#KL-f%UQIkZCUpAK@g z%mBr@uueabZeD%YOV@3>?uU-tJ-^SijNeReL!eyI+w`rm z6N+x408=_QLnIf7rx#_ z>-cPklEZX<*5uE0-ZDYbbk>RXb(BSLv@>9*e;)kwL6GO_l?kOxy-K+sCuHdiS@?i~ z&`1C5=`m;k6XO4mJ+#+KPA(<_9UE6Pf)>bqTOteIwsrDsqy4X*KAis_BEc&Nu&DDZ P00000NkvXXu0mjf0Vv)5 diff --git a/Riot/Assets/Images.xcassets/Home/create_room.imageset/create_room@2x.png b/Riot/Assets/Images.xcassets/Home/create_room.imageset/create_room@2x.png index 6ec374de13e191b5610a54bced743d09107cb30d..5344e7b50087cb795a7f8a1939d50e73b14b6fae 100644 GIT binary patch delta 2999 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∾2yjDW>`cr~5wig=%s zhVGiK^Ye2a82(mjT{WPFgIi<$FMl<1G1No?t+fgkLCz3$Y?jf^%i*4H4d1GFu}ro@WU$9HL5F04A+7j(d5nQqJKv(G!22yqYweYXb$T^hg-w>eybv4sk6MiZEf;t>pPzOGVw z_{%CaaLoQ&*{>;}W{0qQk=oKV`v3GZLYyiMXRU;p zx8@c~GAc&&j0`b diff --git a/Riot/Assets/Images.xcassets/Home/create_room.imageset/create_room@3x.png b/Riot/Assets/Images.xcassets/Home/create_room.imageset/create_room@3x.png index b085c20e5a36e55360c2d55c1e55ef2c7e8b1c52..23094a5d31bd48b8ac9cd0b820f1a3863aca7ffa 100644 GIT binary patch literal 4868 zcmV+f6Z`CmP){$tE}CU}CJwESp65jaisJVSEv5`K6A?hgYkSn*moieAi-T*zU%99peL{ z(HIMI&Vo!4-xo|&an7s20Q?c~hgV@36Bvfq_~XNji(!sOCg2Yq*{~3aFo}OH1PjR? z7P>c3|Jm_|hN$`&{gqV#p7pK^Z_Yb=z!w_qujMg*mk>&jaUKNVY6N4mnP9T1l5iG< z0{I-^?q@=TIF~}gBR&nztT}yl-m-|PX*%mUy5mZ4eMh&>7qM6){1@FQxOf0+(y5lJUTk8V zUFCwGfF?^1_jr0Di`Jhh)}+&(cMZ6K?vCo{7+V4V{jY*Tn&Y&B%Hi*MXjbf&y=-r| zscj%f+_Jb`*5KZFY}>SJk;qc0Syw?DwI14yWu0GWk7EY=peEiu#pgSCdBM6XWkIP% zCd#fLHwhtibhR&n7aXWr#iP&+2x#QH{DU|Pg9e8{gWYY-8;)+`Tq&namkqesU3KdE zspZfV_$|C(K~Dhvk_y0!9rjSXQde2GuUxv@91rfCBX9V>RIWUwFl8;&uCtPbMMn(< zIQv3k()Qb>Y44n0{M@KU495gH7Tg)#J1U2w-#rcO*B7AedW&New}YdcUx0S->?E zyDm1Zxo!uS^7X-S;Hm=z1EJM0^0WrpZ`1S5FvXvsz$Iux>FK<15DX{!{^V)Aqk-k=%wgDG=44{i^FSKQ6XgNw@ zrB;Angh}%&?9%g4^8W&GKCIlixgCaTy9wG-!aZTTCnNm9)mKcz^3H zk!b8)sA(UxBD0i+F$zG?6;Vm#Q!HDPQqVMO8MxlA zj@2=)>;Y)Knx0Uga}|Ix#j?dRwki{rfGZzv?@$!wHGsAxZECB;bagsVwphkk)>i0X zI!O4hP=(ft+)x^}P(YHT=f|4cUN_SjQ^Cb{PojBXYC2{LM79f10KPW%2x( zp4Rnrhu#V(_)tw^&Xf}X3nw6`E^N1 zjb`-o8vb&IBVy{{0zvB>z|8U#7(f<~38RxRw8q7`2cu)rzk`!BjB9jBIosZ#-z(o^ zd^+8P+)Xxk(u(v(8swR{y^*apm3P zy+&lkkfuU>5;)GMg%w=sM+#(CK!J4}nv9r?UNpG)xlLFJ|C1(xXD%(eld1r}7?1)# zEcP>?qH4%Z@Dbgp2t&J;KDS9N8amIWfS7^IAUoM&<+@i?8@KOnX(N0M`ioqN(0x)M zO@Zo@=T0!?&&Q9ah3md7xTzo?X|EG8@i$1RsDC-SJ*9}{rU0~eJ@*&7ZbL!P;R-V> zCjLOsmK#f!=10N>UsRR~NVXtwPrCq#kz_M1nSBIna$f6%bX4l{oWyF0UFlG0<=y`FOOfxsq_q(A%1ZGHRN&H0zKU6THdN77IWa29*B|z-KtLB~xxaDMqmhz*bh(()X%!?ZcL{#>LI=2-;#xgPzx|0924F zb2%Q!3N8-EsXI32FhaLU0V5Sa=5h@MX9f4v$jKG7&8U$@Lbh}%09)It>}83Z5nP-v zDHOIY%d>Qg6fjKzWG~yC-Hb11p3cq9P}_Ez<{23#1#&6CSxc;CW0zL6j5RJ}e3jM% z6h;bIr$A-~HEY}(k8PWFb#(MwsBr_05qm3;!l()^e$NhlWp(!Un!Izn z0?24`?FALw(7?I7L6i!&3q$$0y#f`X!TwtGQU#YYai{HFCI?9YP=LqyT_}VKF03MA z_y%gEGAUq&0zxQ3w5x&(FJ|h683~b1QovXRxLV1^!R3O$HCA1+W|jg8Rwev?9p*gF zHY**nO9~jN0J4hAN*{;&?trF(=9dsgCP=nO0Yel3R*_jL8l(2DA%c<-%M?InCC&+4 z%M_=C3{e1?m7sg!HbbnD5mLY+1&~?jRp3Cx2b40I-V8O2-=-qOcS7 z=Ps3jvh6ShkX2+hK08csYUetv0Nv{@@5j8y!DT|daIYAYbH^wkgj&g};6j%e)wqr+ zId?mnWK{)Mc*LjfmV{%N1Wn3`RQ5(MiQ*X+qh@vEsJo@Pq|hO z%D5vGfT7+#WEGuFyqv)qXFZPao}6^A0ut*@W_}!8u1ExKQWZMdQh`)P$H9H9W$tOH zb+6jeV{(cV05(-d6H1JOdyp@SalucJLZpBl6+kwT(WGzV;9>x*^i0i#q%w50l>+H( zP6XHEA#iO~T;xnr0iMR@1aKpZ)}Mih=aZ4?NDA0Qf%6GA$K9C#E`~yX?w;|xbV3T) zKmi!$-JR~nByeRffXiXAa{7@1c2EFVl)Y?kx+{~w4L7w7z?{dv^oVp#3Y0~aRm?=_5a5r(TaEWcp^dN&_8}bh>oH7mNP#>Q z*q>la_ak|Mi&p*q!1M5;Mq5njmY5=DSAY-4naUn3{chgijy&?>HMbQlJn8 zkR@a)-)Hj%7Za$fsDBe?rsIc|^dkidRsb17mI^UY5V-1a9QQl}31*xGQHV42jH?t- z7%-G;Xg8B01%ZpkqAjf-aY<^=WSGK9fouvOJIGMBIN9zM3@#dNUEJCM{cp60NH&G( z-XsN(8DwYDjXVO10vG2?`lY~f=w-N=N17DX)e7*7$V|4mwtD0#3S3O!dh^oyRb%XKS&}(DUW305X#AKtm=)3;`F7Ki+)jX86~1 zJX1mx?rsH;4P?Y96$}Fx*Dm$Ro+rVvL8F`_J7uH5AhMCVzHPBNgFawmf4=UQYhsZo zEa4=k8*7=YIa2{X6ZX6Em>+t$=TT^ zlsT3?GGLaQrh$tNN0zkilQ{p4S z)>!6ddt`X8LMDg3T^*|xA%4e%uq@3?zEHRc3PAG!Yg#LyMei+z$ai?l@)%eC1n_!I zkd922N&$Eg!#1ti&4bkJSqd&DEO&J*6hiz3;H^w`gw7qR0Cag_?}3>wVp_^r4lX+3 z?P~vtqOdL+q|ho7Cx!7L?58!W%PX4_B>@*5ijT03b;Ie*Y!1>r+bS^V@p+rf7+lbk zW7B&TGC6@6_Iu@faPmc_I23MA1+dJp>`DbKs!}p=G4YXw>n}XsT=OtYcf;B6G@lnm zvG)(=)3OdMGc3DOx>~ZPLVBj<&W?xSrEM>?duOEIqiZ`Tz%N2gyTYjXw8iGgHsE4L zD!aDdJSxKP0>BN$W{jRUP5}V6*Utk_8u8_VQC`^!T+GxaA*3yx?Hgc%LmOO{v?*hh z$PTun03aQ$EgRa4{YK1a4QvN)GJ|sGmiw59y$t}*PlnOaIt2iXGq~8)*R zG!(3U%1>)0NussN%p_ovZ9a^eqxN=%7G1V&jhm`x#Rsq6IyxGD4Z@yC4X1O%71)mp z&=s3pU7}n+&64@d`i}*Ex8d_?2CH4D{s4QQ%^R=AAv@ z3k`%;L(jt+8Zy>X#M$ETA?PvKfh&RMv#4@5i&oup9JongW_0hU9EyJTG}OK?z=WM! zlHqjJp#W^j1hwo=+$covo(npxS{lW%;3id?bL0*Gm&%o=6sD|Yg3U^X(@{eK&c49S z?{FV6JzFwqSg=iy$oj-UF8xth(CBcR{9!htu=WJFrLg@;%|Ewt;fUP_8_<2HaF3d`Gv=7mD(bP(%aN#t%SqVruGr+n;lG z6>8NJT;jd3viDyji`KhtKMq%dn+oPqalrFl=eb%TDUASdBh<)saK9oojt$O7phi6f zZ&^KDk$N6$nS0vE1>|gyzr0;=J-F$LsRJB?{k1&C?}FZm8h|;-xClZUc{ZHO>G2J{ z<}3;Y@;MVc1dxWHH=rMug!wc$v*xtZ1_%t*MZ*|@t09V3Q0+fFP)Px|-$_J4RCodHoqLQF$DPNks(WUZ1v@;P*eH=VSO*A`eayzmk?8D0XW!~@oQUAW zHn{_q*sx1%qsXVoG5}jFN*0rhsfxfG`49L@~Ftb@b7_gU@ z)cZ?d9_VKZ;~ByDC57{|g7epfG@g7qx$(018HU%QzYP%rUAD{Zi8CkXZ!@KFug1(p zIx}Ow16rvr0CbEAO=aSo;K~b&+uwbBE8m)_)J&ApHzc@UP49g~lX8PDM=1KKvt#5sGOgUalZHIjtx(FoJHWxH4M00)BEo+r15x08u;fwQuPM6LMFI!R^iIF z?H%i03_Nun6fjZ^Sg6Otr=Gjn$eR6z)ISMNLQ3FVfWiX1{cZKc+)%mtDjI9Co2x3B9y%DG-FX&A#J11=6% z#nTsmJT8rYjhZXq7A$lnnz-`wY{!DnL}j=w^x!`B=Ai{w#;+U!-}M#(wlw0CzVPvD zo335;#IiLPOQ#NYY-qv#?-Q@IjPa|l0 z^9)^s;{*W=U>?gdb4l2SvD`M6*Y_j9aV}0L7+Vpx2@c`47=GG&XlUP#_oVqQ^s-9{ zTK7uhUnxH1CM%xk{i(LEUS+6Nk3 z94Sy!7mtl|<6{jwtW|4*U>L1QDsSk?1uKF)0ufkn9~|2Mt*oB?8Z2-Ll{-^w&iu*` z7W$ZRHU6Dv+SYyDuRPq?4IH>Qfv_yS_jHCCAEjQ_P1AaCFZ8|%ru_cRjtxtKHh~c+ za331pzcQ<7gVqWy4|FFJ-Y5X8(zJLi*7d#Cbw|Ci=-x_T{tV+&?U;o;Q2O(VwWPYK$3HGTE@>d?_(+hH44Z^hl6 zbpdzF(7-oFnYM%07`SV^dfts~Hv(;lZCQ_U)ZA6rlG;0vVfuRVXY0}2KICZ)nW_7p zO>XG+!Fo}XH3hdfH87ZE#vKH0(e?;u1i%|-%4>be?yg!@pl0CqrU!=Ltpu97tyRm` zIv<1=ri%MIyW47!bxpwSP3<`k(B4>!3Q->QRRCTUdb=;VvBmFF`2KL#d&25z30l8f zG9dP`gTglVyEwjrYx%UevWt#}QXmU$4u55RT^i{dxHx)14`L0)>-&|34OZX{l{=7u z_XEAX@&(*2>49(1ke9a&6*_AGFEW5E_)&JxAI_{9F&LPpAum6gD}**-v|%=j^?WzE zzTeBzdkSvP$${H-!}ux9hpMNJzLx0nX7=SyiC(PLePdEG_Pxb zOduP`h*!2f1NV*8oVRGfj91MPJv+z-GU8RuJOTGXSOl(fNn^EMwMs%(nFmuhImS2b$WJu?(QmXN6#5oH1@23JV)5RD>~QI(>dD*&Sm7E{je zuu@h8ZqLyF?l7fETYXk2G9@pq05XMal}Pd#@tyi#1!Ij&97DVIi80G7@+ zBa3z#*n&Hj&FrEH2RpeatfmUU%CWI*)^-ORTjv+PO#X?Q7BE7YDO|A6FZ?+B)ck*9 z@K=ld^5XB<;Xj{X@Sq!^TGp;AQktK%%WX!F3pRxj)2GMV)3V^#{ zFnRIdPdSu>cN2JWWx?nl79qot137lZC31u9iQ z@<}$QZkz_LG&zoUwd$=sGY80Jux?3o`{S?p+Fzp6y?n zp9x))0&W$6S0fVn`|D1DJA87^HX2QED=*#en*uPpU@%nQ#La_}H8GC>M>ra(TU7Pz=)0$8W*LOqk14Edx$Y?9T9-4?GZ^6TW^`Xn`( z^-clsbFXmoQ8Z}vxY98H#XIX{i4^cr0V!`q>k~e%WH#sRRBg7GDCk|D}-rQyp6f11tDXkK!pk*vw};rwZi)-IVn(A1>kG!tpeWZxvs9I zpv*~u3Kc+R1-#KqBMKD?N6G7}0K8t75b%*S+gH@*2 z0ZRrCl``O zyr$^;HOhh8nl{3L4`-1-eh3dN*yrM(QM*m)q9DL!csTq2ch6XR@kXIOCF=mp@{Or} z1HPa-@g_vc)D-DNfnuWv_osF{xt-EDPyjwAWeVtVX{&4pVo{O+DFDpk>M#N~Ky5-r zDX#zw<61qgUOp+MAO(V>0KC1U<02aZH#luVC2^*JCV<|Iv$T|o6bOa_u!cMfJ+8bE zjN(u!NC9UGz+Sl*a2RaZS#nB63Isy|=xm3DDa2qfibJI!1)M1$g)%5+wSDLSbiEBQ zf96aSN)>DckX2+>?Bt&vg>OI5K?;OI0b~`KotWwsG_nwiR-;0K0@4}qf_7- zoWIc6vQX`Vu0TGcQ{et{`{?83=LWs$8n=ANCNi2+U<%x=d}{{2l}bw-bIQ;;PzoTM z$Y`!mQ{ZBN$>r%>1f5BNASqDD<}`4jJKh_l!ctjCft&(`Y)%9BxsJ_G!LS%SywO1l z1V;g664}fz(KK)|0^UNK8gj@_NY~C3z>PTy58O$Sj_MVFjX!2ANtgjH!2KAFE>tfv z?j}=sG}0DOg>`rP8(D-6K(-ayvE2=B{fV8L$^>n(U#OOY-_~Bdu&pWX5Q&@ZA+)#! zlp)~{9vu}cU@%kP+qpSbc%viRpKF1rX3z{&d{>uY77sQBDB^S+qH9 zTm{BradQ*73pQ#|P)!v;29ZU(Ol@5SOt?PP|DG!OY`dE%j1;Ja0y>u?`;wdH*yUy0 z<6=S>@I7pI1BH+Fkmp@eDZ<#QO<3* z2rJs-;tiT2e~~jpXHuY+3c%Ry&x=8e{>z7^O6%K&1*GTO%y7!s&gE!95J`vumo^ z@6<4*BLyl^0NFyuoZeIMtk}BL&i7(c&>9A(3RAkW3TWIM*`M5OyC$L7&5nEAoB>$F zu!dHS<}`uR5DSK$g04_>9~wye1}|yBC1kwSp|?CWT@QKZZShu zxe7UBUrOyb+a#4mx!-gq1)M4{&W&@=Cwp#kn!YeyRXuLb$U7aIm+0K2?MZWj(Akj! zIx{t7$5G-UiClq;>m{>ltc#|Di>OP%GZa8pvawiKskOE%(RFqez@{+^Ya6L_xIrMw&aJ=H7SsE^-utsLE_>)<&8y}Kza3-&nLswYtc|DOV!>WaZtfpb^#7rUH7}bfoVJhwWC5A* zx(1#-oD~-AzSOe=vsi3Bm$3629Sx^|1ufI|9ZYWN_M`H?LUmudZ*Z1W?;v>nXu9Cq zw4mksYX>`eyZkDpui#>#*PiGbn#ELFN#<7z2GH&p(}xdq_Ex;&tCFht4lWkvOR2u| zO;WwFl7dm%a4G<65Z;D02)>W!d;V}{C-?Ko-WL2O>>Vau0+)TnlJXv6_I3 z8R4G}fcG_m7uAT?k@IN}bolEYt*VvZWrhYz%*(p?0 zaIpX{!tlrl*S|@V6n4!Kt}txFQEQympCPYOYSiT6%&q`;r=Hm~N5*&1{=0VS1V0R? zadAe>kI4lmwXYkvSh)L6_T3&c#SwVjea2T+oD`nY)JFk$om|sk?Sa?RxRunVuHa%p zSIO;(xvAJ&O+0oZO;l9UbhS^5{_MEa-oBjFmU_8hrka}69o$@@zc}>$9kY%2CP7og zIY|O_hBtEMxMKFd(ALuvgn|VITomKJ;b&LIG-WWx$aM$;9Jw-N;TZP z&}b;Y&D9r29%kvWO)8_02Ie&J;;iFjf~xhu)b^D?j2JknQ>ehj3aw7=@O~$Hy%N{EG zNhW(M!3YgKxH%bd1me=rAAZtgD7V1`Mr7)htDl>*#!Q&?GJY|y?IU*vd8D9{I!3O6 zaRTGIlYIkmDOM+#(%h(%7&v*5Va8~dn};v7_jU(yEVdF*3)4mp-24iD@l@ZfeUGS&b;lWB9Fs~SY{P0ej0In{&t#cAqcb+} z!;apk^6S?K*9{47e#7E=;O1dLV@z3uE7O7ovIQ!v(9)Q3&QRnFqpkYm^N*AFDL_|4|a9Bdy8-fs81OjdijW|T8 z9FQtNTtGrpEfi7(A;EgOo=Nnw;55WDKL(K_WRwQtluUTS&;wBx$n} zN6;mb;u7*Nk`TWje+lXMGZ*N{*m)t2nw=6`w7Vhs=FXd`Y>olMUI4fsN^gzUrdTCG z-vHbh>NjS@OXvTHR-gabZ2=@d9NkF2ua1$q_9UP@2oVf_F+%5>fOVRTzK`gZtux}O z*(;%I(wx{*K=QrOO;oyY5WVFEw6|T;X1kJC(5v32{I(Cov$L05)ksSK$*)Iq^zA>- zV~#k49+PjCaG~lER6>WHqWf-mM?5flEmR$jlOh9>$A<4EQ@)R0Q*hK9e^iJf8R8jn zc;UM!!h{ASr}y{M4~uVM4tNf|CUiYfgl~ARfMk;1r8|dS6yvAL4a<8J2&I^Oqi{R@ zN7HD0w@01HOA<6s8)#g-T>QCN;hF{{C-2$=FrQ*bUEgeDv6dI&U-a{R;>h=Bn~|fb z+pm1Bupjfy7hMO3iSPx5>`I3w2n7ZtCks!b-jn$2Z=(LB6=m5^+PVaiEzl6NsWY6w zKm)ZNUm;$qJRx2!o@yjQLqKZI;bGO?J;#ef8IJ*vG@6rq0ay7&pGN=-eq?yHw3?9p17f-(p6JV3rIZ#cFS{)M!7)AtRp}0YJ%qwvz8C$ z9G-VP^EGvKZ!$k|8^(y&vSeKkQVUPDwn_;czO394ptI85b(z-zQmgW$Ej(R9x8;y^ zRyz{)wbuq0lB*NICA5I;}k6! zaYMb!b3oaf47m~{1;6NIK%)PmJCtw7MR)Otas%U@pW)AbZV^>cts970?a$g zkf617_e^cZFi*^|vdDslz#ss@1SJa^0uq3feU2tS?a5$+9t7j1ENBRbEjin=OH&|X zGA|jn4Fs#?raNloobg(!ckIG4(dECr^P;B0>P_IC*HzTho|l2VwtDPvR5AU}|Lhpi z{Iq|W@VRBai)F!w0EQSFOtxv0Z0Rh~UqAUY@5tg|_2?lh;qxh?KYw&&`b2q%wJU&4 z&bB6P&lW4s4PoX7h7<2<-a-ybTMRLn+GasRKwdN~J7i6M+LK|UjUJ?ow9}44qrX_< zyBJ%sXTh5Q1A=*f7BmFR1%rJbFw9mpB~qLWCSYSI#}GktDJJ2qI{ZPH4bMRw&R9R$ z|0)4?mO-!pUDx*s;$}57i-^h@PfV) zuM{8V>T=aO*`;W0Ej~aDqQ_*en!+Dj;Re!2VWg z4`5KS>|hjCK#B{T(J(8OQp-pgP=SFX)B&e;t9xj~g05Jt+FU+2LX$jEP%SM{j_XMQ4z>N{T zXujtev5u^(CRCrKz49|>7QY?@V#*5!Zj6YAa)|YUo}jccM#w%tPal?5Kg4WJY=5c= z9QM*;mUWqECXRx2HQ3BW0da?dQQU1@l-Jp z6b{SoJ4t&fmo~TXrU5auG<{eg&>ZCMNowXF8oCGR#}oa;ZLJ256J%|4w{q)PIS$o> zDkt-A_Hh#@4NW}zJdOs8J30HnlADO;IQvAG28>s-@+7jHW%wg+Bbc=!TJ@`syvU7tBUl)jil)RL*h#D9Ifxvy8T~#c! zb^l4HuT(|c@pvB<7>qz5ND<_uu)c0E8D(W@DjO+h9dE@>mi(Vk?Xa^=EB@O#mo1O|k zLRCzCF)noHBYia)_;2R_VE_2QVMpfwb(p^^{f*K~RRhCe|6ZFK7|||{0syeTf%bJv zcjk|O7(W!$J5^e=zMO#~c}ivZw1Ewkf|PV38Tp@vcscq8gjViiNsuG2 zKL|Y;N;$^wtKW2XjCVy#NrRHk*c+w=_0@#LLr@D8iIxsKnhC*_z(2j+;4wLLt@2u> zT=Pq#@wL{XJ2VpQWAQC3Y}J$8QMDU7*oK`qrY{oFUOT{_v7ru~N znypV7C@?-d!&3j?#LUPg=4w?E z>HEsMcV8&>oox@$6xIeAe4#}k{MTY(Or5EnB##A4eqHREYi6=M zmh;5p;`9F2=u_rtQ=x^2S8ST`VdpFZ#tO7{;HS(^M?deCsi@vbH{Cnf-(G985BIbZ zd{#fm_Yf0jl`pKKbuOqTwPHNfYr0=82TDa;TR;kwpMWVZ%Wp#Q^HOxX+`@; zw{pgXXGYOF@f`ae3=Zj74NG||#&MP^b@Jz3$1Y55yHj&EDLl$pN-&PgxvFK?uyM_v z>#i21>IRrC1T$+b*ws(r!z8k946>S*AcQ&z4?R#VPoJBEP+UKW2krAS$hw5d7}+|5 z1_6fsIj~@Q&DUXSO|oa_t@dgo)5O$EeSQmX7+yTNtYHU^W$}0fy+kU{R(+9WlJ&}s z>nTV6q~ZF76@V06Rn)XO_ShDI3%Z6oW$e$!dr!!97YK$P&QZm&pn%Yi-=3w&Fs53M z{b;|tn8ML8YuMEJZ8TEPFK?l~y}L?J=(-7VO#Z^t^1-X14~ZBxB2ps(y8)&!ZkTWc>LJLSwP6Ob8eLTb z(@0y#4n}UHe(o@_r~-?bv`=XQkzpxyKW7M%c6{0CRN{iZXHV;Kv&=}=i;No)JQ7}V zoPV^$g>}9#TeKf6F2kP4EfJ5ZE9<%X+Qdf$BM7Co_bX7oquGrG1lpg?Fv%D!BIUUG zd)|C;b6hU>L;5)}13bBxOF?It**V(G9T+ZnazwhS>8Zvvna`JSL$k~2qV;H>h+_SiQCe`Ny5Y_5?b(5RvfuiExnihVC{ZePrm z^>5uo=Ryqv0t%|`K=&mUv}p*J4v;m%Lul&M+dJqsHbjy}myzL&wdIJKK&KhAwOC*M#X z*q^N*BDtG8opD&5i5IyDUXud; zYXwa?x0FM|Sk1BTcAzDgcQqtSMu|V&=D0byGv5ZH!fD7>>jKYKfRZH-Q52FN8W&*$ zonwr#@fhblv!33ls41WY&JYs7w9pKXb!&}kNp5l{-5t9i78=yyo+9TEpegy(QFPsR z`W}~MFqA9!;c<`{T2y!SXE=?6A_wVO_8km_Y!$d`7clYc1v4>4AERxF72(h#^k)Mv z(hIzwuFMz{^`w_&hDL-ry_tq&_Mg(O|0quM&G7+~I9y54e zV=i!E2KANrOfjaTlw$=cG0akJNLG`xNg0#P>$0tY){a1B(A%p$ci1Jeda@W~Pg0_z zh+EF zYl??PlcwIxqrI$lLi>uAK#e(NKEA`mH#&uhN%~CwUr1-?x2MBu`ra>fm>5+~%0smb z%V*N>E$)1pWF8GNUwy=)Bdj%1)7rAtwH5E9JQZ8t+Wz8uL?LuGUOKYob5HO1?v1aF zyeuH7TvH^kbXi97p1d6Y=e0S10V2~_78}gw-o*ehS_h<=G11|5NYH1a3=W)LPuqU}07?_X={n&18EYw50N4EG@@5Z$|4 zbKritVGuPT!CQPuK+s6^%)AkKj!lL(COxKEVR3aX1J+fH(AnPtPHrUdLIVWJOf(a7 zD%@VRs#h_6z z?Ev{YuG8R6VTAQmrRpBiCp(Mvdnq0+n7H=wM`nWVZ@Y>L@3x{AzPjUazIkR3c7>Q_Vz2du6Yo~**xFsf*n=BF% zMozL_DBQ($6x2Pa%>L|<&$eQOmR&GN)l6|ZWS<*N?!}e;az!H+@&~<)gyKH7qPJKH z9J)7pI`g)xl2lW25`{JPmqk7b>QhPy(T=umexJb;Hv`6U%VrBwgTSC)MBp^)kq9m^ zUD_LpVx4ji2)_!jU;p!XLs@E?oJ3`)`I!ad~c>2`xt;H3Rh|LxUsX0R1xZ_^USgm2VuRqwkQ5!CVcoV1b%#bXpn`S5b zNs!yrFRPrj8BlHxCa$$bh*iJrbOuw}7w*9Ft%-(!&2JhL;*NjX4~#=jcc`%$e~c5? wyFU{$8)5tSKJ?~c{oYb8ZDcQPn^oIi9?zV)bMKvd=k6no@9R9*UfyS)H&e!(IdM-rou2HbY12bYJw#?D5&r}*bdoWh z#EdKM8TWD($8?DdU-GU7SKJfck@+4UFTme8<$0XecTModk7jI`jQrtNE~k09cNtAl zKNaXM2>%w8brpWyAWA-xax+gO-U>51j{!&jMt7R_p02R!m5YpWM zyd&YDPl4PYQ;y%FrRHebwNokyWX!G{?K`pwcFE%)%N7u4S;9$EIeW}fwH<-I^#<+O za-4Zrp|Z#1zD*T@%--IcplP1MfAC`<&5Gp08X#xPU!zQKLNmR}gQH&th@mM#Qb8bd zVC^cJncfP+^bxdt+M9w@Y>Dy=4F0#NJ%5n5ogIrU*?Yk7|Adm;#AjA7c_`viJ*UjliqkE`&h zOo#bf*n!W{;OOhjY?@t$rV|L&)oKvuFo<(Uv%yGJ`pl<5q^D7>oo{Bon?@k>$A{YJ zpX0kx_~%={Wfhf((PASyL^t;g@o)b$8&xXR;%y3n%)T`%(4X@Tv`&Au%;`5r1ek}> zfAlc#IQO+fvi+%{mTdAnpP5vAkBew%V~P*&-holvt@*p=z{P`%6B}-+s<5!I-8Lb z$h^4rM!J0E7z!eDan!|!z!)uEvYB5v`&E=lMoJ*FXU(n9I>%5)x7NUCloAOuZW*8@ z-po7CeI91C{OJM>G+|!i16hTz^=GbtpEFZK~VWmXaqTv4=6Xq0n7nyofjO)s5T~(N!0B`soI!sX)#wqeFt76SB>zSzUtby#(8(BTk@=J?T zB=69(D$B`P>9*XX$w!l?=?t{5FhZ?i7?bHg>=zGU%Y z-t@SvfOXSA-g09lPr7O0o_kRgB69~KaHkcT$&a1Zr?#Q4M6b zm7BgI%R#D>EZgvAq4WjHFS&KG?e-QYhwMqH7nOF8t*n7$D_tG3$Q(@;FEEBUEGHKFSU@1ViMQ;-tWFW|BLGfVZusBf zegT2J9pH5>dl^ppC=>DJbbvCqaMNykd_dFpZY;}Y%#XKiA^H{eH21r|y-oDl5&xU) z-Frt%{MBFZc^b$bTq0*rWZf;p@nJt*IsYf`)NLtpWDbdW1R^>0CanjT%oRy*B11s9 zAsq3!`2><9lhi2!)etD-$Q*&}VQt=dTh)T=x2z)oj##b~ahM~JchXxfm zjv`lVUak^Ij)_#K2sj~dl`B^X(rQFUxmLZLKti6Ae@LsS zqsce810&jK6&4M=tsg760~<)HFm;MR00h7tX@x0)0$`^>ECNCxlVU4Q#n@Z~%=a=D zhOSU`ia-zq_=5CAj|T~=VH5%3PLA@d1X3;pLjc^#(fY0lw8W-^#h{@wi-2$j+{y9A zk7fYEL}r1|f(J!lLby{JOx0>ED2&++Hzq~*2xLeORZ*u1xFcZb3-Rm`C`X^Thg6@6 zfMt&5j7Ojj8dgJEY2l237|_BQ%Om{ZXGed)Mb1T4rwF(paHhzax$RvrqG67^gj7F@ zfS)T~6=pHXols~L0XGD$a^)(4x^DOsfv4OeP+u8FV2V7hSP13_#Lv8c8HV)783sm+ z?t%a~V!2ZEJ4Ybnel-aayd z`tQB0V5Q|OLjbb394LG3f2>NNqQ@az)fV!jmW_LnxyZh%t4Sc9F@&#i)h$XaCX;G77=ThC8o&g*jy@u`=VK)^ib$-H)9 zxV9J1hcSj}@0wu@bKKz?M*XD_0p?RQc&?wBoi;vn(m(=(7omAthd5G53g;}#@RfPm zl{^xyGl9f2jH>gv9Flu=Es4OPqKusjR~Lb7tT*=zK^@seWzMOn$K)d*G8Ng@>6~pK zf4pYjniVu_MxgGl^S{^ov?9RYQ5*O1j&pU-1FK&H0VA7GjvhxZwUeQhR#-EUZ;>Hn z8H7B7PapzGKn(AHfQ#Bg0!F&sp`t7Ul_D^KY-;_>2SKHifl}5$2|xg{voZ{xm4*mp zcQ?y-Jc#7&W<$ZVp&^@qz!*Vx#U1JbCm+a&E>F$8xb{Z6GW{t!8CR5l)8_;tAQR-5 zReiAUT&P?Gkku%+@}22~fYENC_m_u}%ETSB~L!RsGr15Dg$OMoX83 z*4kPuAEDboK$S9Q3%aUjBkUq9oz_mrN*KAl6YPK? zuxti-B#%weKz?w{p4F?7jl;Uy!;gx?y{w*)3Gm)Lb%y}acxgI;q*&gPq24Dzq?hn; zeKbXFkyz~lPpr`!9DTi>)e}*bJ`n^e70w)7-9^)U03>=6@0wD*mhzIoYXQSUugQv0 z*F}GElp#?BDizr5yX|%=%h8}A_-Ii!R+trquIiCXruwW z%bG?KjdPT+KToYKR!Vp^jjZ)~=$N>8;R6kHBJDxVLr5V@q7ovXcENv8`OS zoxze))Kn0t1Qt3WZ=!;E3jdjpK`XV^^jR7BlkT9$A~(lu2CDgkHAt{m+< zvWW~oj(1xC{Ib%wR9(GuNsf^00FO<)EA7La^zx*VKz>lo%e~9!G7msAJqjY-jc*

$!|7bN4|{^(k6Uc2U6wzeqz6u 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 diff --git a/Riot/Assets/Images.xcassets/People/create_direct_chat.imageset/create_direct_chat@3x.png b/Riot/Assets/Images.xcassets/People/create_direct_chat.imageset/create_direct_chat@3x.png index 2d29d49844e3039edc21f8ac24f3c532170c3b4a..2a466e5d0a5ef85dd620d6ccca7a6f80186053c7 100644 GIT binary patch literal 6070 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 literal 1595 zcmYLJ4K&kh82?+QF`~w%MHd+vo6j36g-f<%S3CYPEh>_a$b8kPj!`!=#41a2QbtUT zvbsx?(tJhAO49XlEh=F|`XF=vyLIk8?|FW|^ZuUSd7tM!?|UA$KgCB!3#$bHfDW1D zMTJ?(#rC+QgjIb;P=R09sx&RPnI;q?A~Q~`sqsQx{h=DOu^q9msq^? zgJC2&m)d5OFG+fW&iEt$!iuKw@z>1`Ns&C_A_-+zq(j@BbOx^Qx8bJ8T_TO7XysbJ zd;D_IWh$*}HV3=^TYqcg_pSz?n(M5@n~lA>ff_!iy_GqcmA57JgKKJE*WI*v7)6;c z@sckHj?B}orEa(nZHCYNKi_$idaW@_%ojv^?g-;tKd~}fil!A9GT^m^<~^M zF5T=Nta7VM$q>V=-lUvQIaWVV5z;?=W@t;~jzKrCj#<>Mt!b|$i;vK9S?JiqEKV(A zqDV~QNCZ;vAoV~T@rYKx>Eeo$K@2iY=A4@?auyYugZ%RbCNX3xP9^qQG78X4kX`+0 z^P%@HTXhc^`}#iS-mjN>2akZ3M44I5MwOw5%@MU#Q|Nr}kYu?TVMc($L>25RQI+}t zS=UoTIHJ;>|HI(+JXxOD$-i(N^8_rTjO~AM-G*z8=6Kk-;MF#=jBQLu5YGPP>N4Z- zWXrR2e1drU9@PPZcLhz#5a<2vrn+yFqlk>v9CfCBjV~rI3J)VyY8w=4J0+NQkay>E z>(NmjWs(5+^q=_rJ0^r=GJV>S0VOWfn-eR|LHgRs4C{!yJUsDC%0q*?{sq4H(rtJz z-!-!D9IM3-TkPo1#>IMsec*~qS8dn}kC!AhI|+vz+ZWib%=tE_)63B1?*;CDZN%8| zw=b)DmCCs-GjHjbN-fvAql<$tVvx@DHaogZ;=1TUzu#BSUu{Vecs7??qz5RcEZE2Z zc)G0lz6!-!Y$T?m7J2919 zrd5Y>Ut^tF_L~6qOqGNj|4}%q6H&3x(E+O56=6h=p3m|suINp-1+iWVX5TpJc+P>j)q@_Ib@|Zpb&B@q zK9I+^)wZ+yux@8HV`6gZYl6}8U%Ot+XbvSP)=CBj!WksGI~|b1|AilPDqiZA72IL7 zEK+U~P1qIKn|5r}v~quPgL5e!Fjlqw^I~(9p<$9)rg5DK>G5(a#(0U+ zY#i3KFlh#=y%z(N=FvNb2%%=7l#tImsBQd_siz4(L=ArLD^88oe}<^MW8?adO zC?fnruL8Tf>Y__&(d`30>R~YK1l{7v@PiAN6^3Csw7ssCT0j-Zst33+Fg8*Np3419 z$sJYW@m;@?8JB6B_KiKjMXjg^ghvq5p&#NryVADUDPLq2mZ%|c?Y)AfV$914Y~%?` zVil4rE0n^QP`np#tEjYni~@`~$rntw6TqsFt7It(>F7?ok!A_;$zoLq6+_YpN>p1eYm%MD7zd|RvP5W4!d zpq`(#S&z_x4Pt~*MeShL0&B4$PUPUS(X0K_CV2ID153A&GdC%p2EwpxT|GS>b~x4; z5!kPX`%HUj(mY3#`-kg<^q=WIx;ChZ86?H!l0hjU@368@`TgC{QtFZlGxsvi--qyKe9yv-ZKR1fWvnUxCX@%z)swdbKjwPDS_xB54lH_ zXqqDlxZm9k!c~)F8EXacg9tq$36PK@AZ&^X0H!Ptx;j_T4kV;r{rSyD}{0X`VDwKV^nFN zR6h@A_js63zys&EO7^!jBa_h93aqUGj$_hRF|YcW?s!1LM=krB%-j5R)X${}pyz}f z(F(BeG0IZ%#iTUCyv^xz?QpETT&`45%=q~WC`nUz`yMDp+=Cy6lF|s56G%~~$lGH= z2kOsX0Pkyl9JRouCE1Up_Fu+#i{8Cjl=GUF@TGrB!B~{zeB!?%dOiDCgpB-KSdee^ lFNq4$`0^;N_R{>^r#~LMmxMLqvvmLf002ovPDHLkV1lv)L5KhV literal 666 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 literal 1775 zcmV002b@1^@s60z?~{00001b5ch_0Itp) z=>Px*sYygZRCodHTwQDxMHD`BFSk$0TKgG)YJzbFcnZV5>1S7TS(Q2 ze=p+C1GOqzpG-`QL`u| zPwyQOwH`o?KqCVv(FeN@|9!%#?{+hg*(L4X?wX>t` zJ+e5$1pkKhff5cgMAn=^JFe^Z;ytoBZGQx2zNv3&*rGD&cVYheA}sOs?KQGEl^0-1 z@RFHxtcdonoAr^ewO6n(p+AdD>56=&Mq9D9h|qhYB|eV5U51>tEF@|>38xh9eoC&N zAUeB}(E+g*^CBK2tL+7NWD6((&N8CTZC+5S4&o)UaLFtW=u2h3vFIQFh3MQ8L>K6h zd+`-nuVAhc6SHMu*AR6)X}QzX?wm&!7NBdf0R1%80`rQqh}y+iO8jo#mAnTJkyRLy zn_yhqi5{Le?nR*kr;!Ezw-J}$Aq6{3RW1-sEM@fGkER{T+Ru?yn$&^Th^XDI)JH#- zOnZ6~RR1B`geghTZMn=PDh)!VELStDb$A(W--@UbxvFfr*1|fK*n`#FSoU~1HJpG2 zS~Cxmu2@&8$;V@AdU7q{%d2t~vsx!$;R<{VQ6+Lvic(6}yELwH2}ato_4uK>BL!9u zt%DViW%i5}E6?XiTNRz%eXWB9vJ9YXkY&J~5^(Y#!X3%B3RXat+2e9&ywtwTX|r|4 zU==K66~v_8?gb9{ARyV7^~qKAYpsD*CCg=f6I``m1BfoGKb$qNuvEYTG$&c^Z~>To zl5GX7fGo33xm_OlhA7XCFMGhJu~4>N?`}?($|~zBH9~)rA3zWSet8|6&old*|7@U0wb`9G{~~9 zWmfg=knG%GX_IBE&TDrj{4^%nxxoUh*`Y_4wH>tFz?@{~0xKZPga@XxP0UDkF0ibU zHT*-$!-2hL6;AIa7N3v-pDC(CJwU_I$X1j+7vLbq#Wu#CyF zu4T^k`A%JutqhhqS$6Kd<^cL6TL~;|!QKE%+>m8W7wxJGlHIHP6e<&}fGigoF z^_01a!I%^aFRCaColLNZ`nG`9s6AO$9W_bs_;^yOhcb1NEd?te%WTkt#YBIZCi-$) z2@IIhm6NeC#3NZA9fh}ekKjTzWjc2P8^C|ajeusu4G4^Gyo_*I){doB24uPTJy5rn z!%iD(W|Z^KupzEXW{c!9EbMF^paewOBs(#(9Bjju{a`bx?u2Z+c*>kr8h{7($#NDf z{i}&qUx|4Oo7j$iNwnWf-X>}lxNk=<3h<6&Tw;+Gkmcgn2uqI(A3U)-hFs#Ry6N%o z2Y9#jqqx;>OHLuWZcN%Po-k+mCd=@A&maisS zha^CnbS+P-aaf*AvZsNC1^q6E7NmEb^fWqM+e3{Y*%V9R)WE_Wa48;juk&EZY#HJq zq@UZO#@4{X8={Y5QjbmeQDryBzY?9oUWYUp`#G(~aXGsRd%QMB2dRLC%mP4SAj}Pt z`}PwhQNuG|5#5CwbHk)ijt*U2XO))#EODJSMvfgJT63Cc=nkUGVbc70pou7ZKuXno z*t#Yc5XzCuZAldYMAW~-Q8a2`A-ayDqCZ;M#K%aaP2I`p{n~sbu&9A0PLP9s z7t!@F4*wSC%_-tJUC3X8m2R{{ep9OA6Vs Re?tHO002ovPDHLkV1m!yO)vle diff --git a/Riot/Assets/Images.xcassets/Room/Activities/newmessages.imageset/newmessages.png b/Riot/Assets/Images.xcassets/Room/Activities/newmessages.imageset/newmessages.png index 334cbf1cd5c93bc1d75a6b8ea1171ca251f29ba1..9695c3547de47efeaaec0ea62179167355d73332 100644 GIT binary patch delta 739 zcmV<90v!F@1^We%B!2{FK}|sb0I`n?{9y$E00Oc}L_t(Y4aJwsYZO5c#=jn8a1#hB zh$j;y7avH1Acz+Q4`$Z~D(0fMDES+FAVG-;;$I-@%~M3h$L@L%^dcS&BA$W-Pa?Py z9}CfJ`BhJPot@oztwT~U=}vdm_nV%Y>8>?MX>#EBdKA`zYIYY z_20AR<)d$DBu$c&96B)qZ_QbF<_LYaCis6uL!P3sbjLh@I2-3136_J$Hlw%q5{#MP zD*NL^+U5j5A#xXsi`UGH$DiBgInWU-hfnR}+$~P;>=cxKOy1LX(mcEWIvmpmmeM$L zhZ~lH$nfao+-am1ev#6&M)kFc~qVz8VwzshMG2akTaK0Xwz<*Qe6K z6{@}(qp>kYu%4$8HhmMA{{#$eNrpS9`f7~EMw-m&id#1C7T<*h;KG$;co?cN8XIj@ z4-Hg!c7IBwPZB&UR9R#iyMgreyyYh~6baXfFhC!vnoEVY$tz`MWgfr&jC!_4GUkb| z67x5_a_8!Dng*&dWGT~st3|5~)SXsj8-zQjv@7-f>pU8j^8T`RVxH+WgtrvyqTKbTwKmp1GQcCq1t|qmnpU;5}alpv_Q+p zREwIydP{{{z&c>7L8IrhElqXkKa3jG3Rjpa*vxTQeN_tj;7zRfPnaNF`+5Ip`wK{9 V9d2i}55@oh002ovPDHLkV1kP>VsHQe delta 707 zcmV;!0zCcu1=|IXB!2;OQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru;06c~BnFhpi;e&Q0$WK$K~zY`#n(?rrBxip@y|Ke zoRl21MJ`6$IF`(!pxw=cHqB%sI~ zCU9aRvivqKSATLO(=0Jb+m&FVu)CpdPgP*~6AaoP1-!}f$%L0e`XeCzw{GN}eT44T zV6pG}txlXfOES9;_Li|d3*aUeBYb{=kI$8dH`a6WB6H_?=vXE0 zdcc=cj zFNDOa&wo<*Cey^coae(~=D(-Cg_XM;Z{V4Zbfnp!h&>@aGMjH@KD~C}xk!?*xkdjq zzWyoeie6#;L`;KOGL?BF?AX3ts0E5-Dwy4_{aSqf6dRj-_iIhp;*kY`_-_=sF`ovr z1JmRV^uCmthP{zb4cShv pXGvDArr$Jmm4eE;f)C=+_7C04xeJ8ZV{iZf002ovPDHLkV1mX@SU&&& diff --git a/Riot/Assets/Images.xcassets/Room/Activities/newmessages.imageset/newmessages@2x.png b/Riot/Assets/Images.xcassets/Room/Activities/newmessages.imageset/newmessages@2x.png index 8ada7ef00c1380d1ed5ffcbe7a28007c7588c90c..ca6cc104fa68b722a3d8dec4660091f01e5416b5 100644 GIT binary patch delta 1427 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 T8bD`d00000NkvXXu0mjf>U4RQ diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown.png b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown.png index 37fdca05538c6d915fa0964d3919375c6310867a..d609d1458552353f0b089eeeec69ec7cb811a655 100644 GIT binary patch delta 855 zcmV-d1E~Dv2JQxsB!2{FK}|sb0I`n?{9y$E00SjSL_t(Y4ZWAmYZE~j#wXiElS*kl z*q*A`7D~Qoa?#>N3La|FQV*q7Z#C^d5a=ZYgy1ERyA~7#5B)G$iqzgz5J`@ersiM~ zj29JbX|V|nBtFmD3GH@2vT1N&n9V!S`~K#gncbN&e10A4oJV*p>#{~Gn_!otG3nbr_I zIy&0r@pxi@O(DQJvmiQse=vw=#bWW%%F4AFg`xcHGh1GdP&>Y!0%3Ee#htYecIgI{BqR)SjJe-K>$}FIDb^sgy(GxU#I~FavgoMriv+`M+ka6SbRdgN#qD;7u<#cfjAPr4 zEHV{5+{7qqyW4gon+{}=sh}OU>3eE9nNCEJr_70fd|g^wTSY3B5_@}lC;IgaZEbBL z8jXtm{e6*4CiNt=_14~FJq4lt{rw^yj|&F0D%4O*ANraVg13wW%(PG_i06^85Y0FkCSL)2@X}EeB99ls=f; z7wL5RmAb2OT+P8yl);SJqiZfTHlanb=&Rm9aDO}a83+Wrko8p=(5PkR*=$w}4GpQY z5R1i3HuNEhya*(uxb^`#yctZP zV_SAMv1QCDdHZ18W0$>LF8AH*^{yl95!9xf&&c#QGQE!}en+4z$G|l5HW&;BKj3i? zwNR6`Q2IU5jB!2;OQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru;06c~Bs2XQ^fJ&i3!GA;P_8=6Yg%%3cdeBL+ zUZf>NtWXT@^Rf}eHoMWL`d#PE{${>?yYmepn1pGX2_hPGT{lTYF=jRZfQU|*xgmr& zVCFZD<9q<%`aO_34UUbC>9JTW$IRmZ`T{QU3lY6+G#Z;*TU)KJ!G%I0OGHxu`tfJ_ z#LO#eYiqAh8-EO)wiwH@3IOf{F!1Lxh$t(i)Ra>DeqgdJ>mf7W@p}ycMF57Slmkks zy)(gEq2 zCa!g3I}uIg^LgzDSl9Kt-F9!ORLYl1rSUFz-S4p=0DlN(zSnivc;le zxHw%gO*0{gXcQMLA{rI0>n1N6?7D7J5K-(O>^LUcr_4o)nGNArr0cqvot@3-y6)S- z;c!?h7K=9nowG!A(y1Vm$wcPn=1S#q`9UXmBofgV78V}Q&(A-KMx&Q}tUeLU+~`!a zySv+5T7O!4Ix;enJqsR*MD%jG{5T$u58Jl=q}gnK^|87kgb)XQwp6RtowMNWoyOzw zq;1=awOZ}1ugyXngwpAB3&3r^;_dD2kA`71CnqN-bGh7rVHlTP*Znp#GjnTbXeeph z_LCq`PpcuN)aP_MJqF-XH}G&c+#iibulDuzg?}rR%3`fndlwLT>^RO!2mnhd34jbT zs}0X)vl-WQzf~%g#pUJYcU^qLFO*X6H2`R}S{s_C<$|72)oOL;=;-M4@$vCjFI5K4 zVXancv@SLHq zR!3J?pLdM6N~t|5WeC9abFiI>Xx)RdU#^Bys-8-v4v8r77uos~Ge7&;-v9dw)9Xvy YcNwKUV1%8bF#rGn07*qoM6N<$f;$V3wg3PC diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown@2x.png b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown@2x.png index d7b64dd32840176a7cde280f40d1de4a2a443303..0c045230d7e8fd0158f19c018b9dff87f6e4ed3a 100644 GIT binary patch delta 1660 zcmV-?27~$142=ztB!2{FK}|sb0I`n?{9y$E00u-!L_t(&1?8JhOdM4l$A?`4TPXr! zVp|hP6eWQz2-#2$#*6=g^gtklo52I7Y1yP4^yr~Ic+M+fTtgYq+|_bbxxH#axGnV6W^vLnN+tSi86 zZEdeY$@_@Sh<`7`*c>yZR<8km4`m-9h7fNL4i5fiwXRXQlz>}WT57Vhv#&yUGa#Qc zQsPEF;QxZ0P&697H9S0g->FPTz)ej}g*iDn9|E!q@tjlTPU-=C6|sA7Z?A83bo7Z` z8McAZ8NH5aq&p#BZ1-BGl0DXp;r(s zw}@i`mS__~eQs{APm0HU#D~%VrEA zSJDB3i_>VX``&WSPuUI;f!0^>ob#bda_i*_YJA9C}dk3&gWV71KDM z{Y)La{1d#)IeJV;0B&q-EJ9Ph1K3w$N}iw-*q#S3SCy8Qe!Z};u%kCUp-JcE<#nKd zut`OAb+y#n+bc&N3k(5;B}PTeFoQ)vHSW%LD1Y%nOeq&n2wPlSEK6KpUza*NJ6)8X zAZiU0lXtP`m{zaoJ(*IQ?naHLZp#dX< z>sj?pgnB&_QZkWE4l*#8dpP6bJyS!o!uYgpV{O|2(w8!omTU^+Q(%l)Z=tQ{W-2h* z$bU#a4`x*bNUJgxR>xIERzAagMdR09$kanJp7X%nobLECl~Tv$BP%^ztIN#v!&-Xy zwM?f}`N&G(QZ*yfQ?h0Q($VaSE1ixGF03SJU|>LsL?ZIBsGmR}Ahox*%i{a{`=#k= zZ9QN|WswJ~3C^-?2f}h8z}VH*CDqs0+kci}wE|^RhpJD#(N^oL<;W^eE!7OCDF$^Z z7z_%5CM;!BhZ}*Sn5on zzu4e2{JRri)|s4~6asAqOPx*wSqc2JQvs~!Hnb>M+DcY7=_#J165N6o39Il;(SO4n z&|+R?I)P6W`WRq$$Vv~dBF;F0jIZMq`WRqoDj8S3cssxA_xm|(s9|oZVQFbeT3K0< z>gwwFWlt8zl;_MRoIWfsFDHz%9D3Lr^9H&Y?tXWMZWRrvT^$_iQ zqq4G+o61~&17hZB!LXcc+`+dc0?QxB^&aL*pcipXz7;P2sGf!anq(de=zonh`8Xg8 znY2}o=3$nCm)Fo^a|QJ_&)p96G<)gt@^apJX=G$X3WvjPtI_14_1wfr#BGaOi1}Q~ zTz(MG&(Eh70j<=@Jcw*>Z@)7>J|5FA>6^5S#RA;n1`j+snVj+>;Sm|)VaXHIq*Xxf zjleMVH<};6IVH3LwOpE}e1Bd)j&I7UtqC4hFQEPR!OK1B`AJD>Gi^7rH>rnNnERZ# zosT=*;AvOp*+xdVl@Hi2x3;#fkByD}Yb4VUm=(CA4ZU_4z!%aTny~QfHNcuKbxnZ@ z4Nph8osT=*aC!;gY4uD4lmq+cif2t>$#Wzy3n`wy2i7&jOUU9b)^&6Uk72||@a(5% z%~)@!ZEtax-bvmdZpp*?JH#QYtgLJZ%Q_C|7vb@<`s<>P(SrFGfSbF!yVpaZknKNx z*!Hj<=+yklLl4d4Q}Z{Tc<@v6N3D2po^t~Ude5}`E8c&I(qAz}d(Qjp!eR;o0ecR#blVudmGLJ08>04x*HvuHHB5C{a4M*J?+ zvoVjyW6?CN6@L+%h^Ph;`Mb13L>eM4644Cj{P&@up%+;NcDY=2CX?wiB9ai1>3I-| zNFd_8s;U!XV`HH`1$({TI#pHO0APdN$sZ<@X>@RKFtn>+r_)(lTwLq{fEL)BJW3=I zL*wJ)al^rGxBDpP{0smT!QN&?)3n>8qoa=v0lQo-lYiN4_7Kr0kVQen2gzh|Xl!gu z-Ol#g>P1hTI#ozS-vGczkbS8}#3M~jO*8ZJ^IFDWkH=#XLUaSb5y;XYqLqj~lq6|d zQIzC6gIz9H5o4^Ihz>#a=KugS)YjHchC-oD%X`ynW=BT{=bU%u2zK?FeTZ}3+0oI# zcMJ}P!+%~xtcM&6BG!k)VegJg+U<59WsH3extnU6&9)Q@g_gEF!%nBOG2S`^ zIGxVYEy1Y~R1xHUic*%%!5)vN-ss`t@#DuoxOMB+_x=6--<6k_7Z{9gNtreV3nAP_ zA9kafe@GW^=U-t-21;=~CX0DsgP{R2!UlPT?g#&)5!Yg4whV8)me z_G!{>Y<2iZMACi*6OrWccr0(gLWmZ~}2@ z)yT4JW~r%EzTd%!$ji#gYFTRDI4^>ThZz7=K>nm6|G0l>>l8>y+ODY<&}>erVqU;gso!GpS0Olxav`L%1;zP)(y;%T$ltjB}D zmkbeKW!g$-XJ@P3Zf|UEZf?DF=~9;-=(e`DiVGJmoVD3(lEdL>ce~vgj|LI(6(gc} zrVUL@OaxU`O#%Q^RaI4Iigq|073a^N?|-&fETsSd@pwG?@ZrP1b?CI>3;>ohZRq~} z`+r@za^*)o&<=;A!teK=O~>~3_Vz6;ExpvCq?dI80{{#R41_X8%d%YQ_xsP5l$0Du z$4*X8Ms(^HmKhN})2oxo1TD*QWp8h9cRJSR^XZ8NB6`N6(dYsZX?uxIo!NA3#DC}W z^-WDp>50{%(dYsT1OiD!T-5Vgw-a=GdwZqd@9!=yE>6c@*AtuSp%(*zK#~Ih*zNWr z0MK<#Yi@2X5)Oy|Y;SKr${6Doi{-sz$Bxyjs+z2AdbX2uXK0DutU=U^}xT>}mVgHgNPZU=y}-9pFX@o-O1&-K~aS;MdZuzxTzGBURM zVa?H&Bq>5fZAR^RZf-6Ti9{A!T3Q-nu~^vW^WAvzutU|=A*V{odpRY{Vj0iYq<(TMmQ5q}sN8A-ftyDcB0DTT7x)kqUm&F2}2P$5!00000NkvXXu0mjfmrDso diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown@3x.png b/Riot/Assets/Images.xcassets/Room/Activities/scrolldown.imageset/scrolldown@3x.png index abeea3f07f8db7fc42070c42179873d800432fff..be11b41d790fbea327bbd8701675e4bcbf6ddb48 100644 GIT binary patch delta 2390 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 IM6N<$f=+0QYXATM delta 2475 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 diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrollup.imageset/scrollup.png b/Riot/Assets/Images.xcassets/Room/Activities/scrollup.imageset/scrollup.png index 51a5cc889c6db86b914e78d5b5bf108c312cd6be..7c105000b91beeeb5255f297d49d4bcdcd5b54dd 100644 GIT binary patch delta 824 zcmV-81IPT-2G0hNB!2{FK}|sb0I`n?{9y$E00Ra|L_t(Y4aJwiZxTTi#)mCni6PVj z?Wr1p3sqW}&;Vb*1xg{5wElgT{Z``-J_>kQq&!VEs)aCpLIvwzJ=k`%I7EDK2U_EKxz zZg;2C>Fl=K?c(@vEyG07Xmk#mn;2ICJU>W}1$;vMDaM1%&CTK`Q?CJZR<&@Ozy6%b85(JJpqVaX=GBp-!ihrBW$*kZt6l+Qi^md5_U;0D*fLHXhKM z36w}AnA`1UcDtPggF%+h=h^Y`v0jSWKa2g&VZXo09e-mb%YZu63X#pB)6>&Rm~2{z zkOR;^ZtLU}I1S65f%oMyAh-NM-lZw+Hs z6kS_e6S)Wa4h{}jGMOBxL9j-LYj>E+>^L#$a6N<3HM_W8Jz^14IyyRf1LL!v&}=`k zh$+z>35$4QHbAc)v4|<3YP_!2;b`fJ&GHk2SbtPc2IC$14)(?-jR<%EB8wT`LbBW(RNZ)taE0@b({C-)eIpxa;|5O@W19%GVxfAN&jz;!^MYis-gCPArGs(U=1tkr5gg~W?+*|mv7 zJ~7jU{yr}Bx3byn2a#6yJq&Vp~l%soK8R*_mhNn;G^Qg1-pMvigZ=NNXJ>q6jmG0Dy?jnYk>4C@^!@ zb=^Y%y48TxtZ{5?EEtJI#+mssfO|eCStX+P<#Ks@XJ^N28=OcahKXnrKo2@gg_+;1 zudnZ3)fl*HGJm#hCjdMJ5JKk(5z(-e(ojkrv;vcD+s~Q#QLAn683HgUrR-HoWv&I= zww-7|Z#sQa%79WT{|7jcNDMd1OSqj3#A2~hKA$fEfB*o~G>yhV@(rDyo{n3V)!$Cp ziD=R^O#=W700;(y6U^-U^v=)EKb)PNeWtbk-re1uUVmL(-S^qGCm0M)0C*PwAmZ`( z3jkg1K!p%QL}GMwbhuWl6*HO4SD*0vN~sS4%d(;XCfb4S?d|P)o>woGO2t~ORy9rY zNwr!%%4V}=AH#IToMnGwXW2?j@7S#iOI6g5x-IGcz*}d~WuT&{{{^ zg?gUH7k_OhCnsJqnOrOuiv`DVUiyJ+t)qg7BF#P;85s#*2fYkWrBaKFf@i`qj6=n48s_2$FG)_mflt>m0G(V=6T-MFS6H=yV+Y50cPgq z3;FwLAo+a0B&9R}4Bpb+-EduZ`%33hN*zckdja&_F!bZv+S==;daIPmNGSsV25zA2 zOg2Ot4JfzrYAB`hu~@7`ME!r^))i)cb-BF%_Y>x}A8kJXh|PqMMvAW300000NkvXX Hu0mjfQ9654 diff --git a/Riot/Assets/Images.xcassets/Room/Activities/scrollup.imageset/scrollup@2x.png b/Riot/Assets/Images.xcassets/Room/Activities/scrollup.imageset/scrollup@2x.png index 7b5351caeb2fa550a2ea94b7aeaa6132f3f71e61..d52039cfa504a5153bbf1f5f47ff893c1182fdc5 100644 GIT binary patch delta 1644 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 RV-NrU002ovPDHLkV1j`EpU@e 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 LNkvXXu0mjfAyH;A delta 2356 zcmV-43Cs4d62B6VB!2;OQb$4nuFf3k00006VoOIv0RI600RN!9r;`8x010qNS#tmY z4c7nw4c7reD4Tcy000McNliru;06c~DFaar0Zae@2){{0K~#9!?cMKBQ&}1Z@aH)f zS}da!io3JU*z%)AbSFDI>9QmylWhX+gcvfLm@c|8aeU!x|9=6+|3IMdju_Wp$Wqps z2`X9I8qAte%5##jmGTm=BY7>jYvBZwFyq8Jec5OEFw`~cvu zsHm88I-R0iK7SkL`TWdkwZ0Dk)tvKc0MH|%DjP3ML@@yPH)CuX0H$3o*K+{i+X~uh zweAr`@ngo=M*vVN(P=}R^Kn5C9=cqv*@A^`X=zc%+djQy5~cF5_PfQSp6^9LG@W`AsGXehiTq3w3NDi{oY$~kY$ zR^822h$zMw8`EmFe{(vWu`L7L)YNnU5kCWfGT2&~C!)W4Jf2BeLt88stsn@85YYr% zI7IYB6vdmPqoYCDLECJ$dd~Up0iXm5BN4{fS0f`M-^&8pVzCqng3yeJjWXz$=b&-Z zm?(ZA#2cnzu#8qUARqlvOo0u{kE)>4x7zZ z4*;JP;LS+3TJ{GeN6a z5)ozeHp>!ro;6EHYip~9bKWQ?h4$(BW`cR^Rb8G&EG6IdkUtjvYHz-1b*jSJycljy5@ABcduC4mYj}-O|#cPCUSu zJ#q@RNru>sEiEnTjL^|&)GU_^;Chf#vAesw<%C_5uuKn)h@WgVot=HT{FvU}-bb0R zySuxOl$Mqj7ZlsDeRG=HkVR<9&U7e@Tbk(b3T+F}98|#w2Oc2M!$2N`;()J&_6f+_`gY#l^*v zd>6_Xt7JqZ$$*%XCr|!PN`K_Funh)7?cu|R>m;hvS_Tq5ty8H~#Zn`uVqd*_b#OVh zN~MzOHob%afLe+(UAuPeZZsMV0{{er!8xgrleu*1(&XjKmz|4?i!lIz+1c5dfq{V^ zBs#sih=^2(xi3|B@7{fW?AWocy1F{;!-o&&qS2`2vskZOx$^kdt$$lSy-7di zQ6z~0ik$PO3Q5lD^HZnODZUxp!PtyKlA~Migl+O!$FxF{vrI2R zCl=oeDJEG@C}F$QqB-Y$Tye>IeIAFz>X9s^3-VB*$$GbL$#exn1AB*&aHWD`QoxGzBANl zG-HXimt~cOg@w1?lPHRdGDVJQG@2ESbp`a$&`_8$Cc9RB`}Xapp-|{m^50&sSC-vT z##q{wd()28F`Lc*i9{m50vS!Z4~0VUd-v{n8DsPJ@8AEftE=n23@6>smzS3hrkix1 zapX*5NrX0~;(u-^e|EdwkJGmFOh>rg?#D#*M6p|UZGMsoc~$7d1?MIrE+~wv2N4%U zQM|co?OyGdqoboiMEn{6Na4)fm=W>owbq(mbJ(iS=bNjls?s2$vK(8QaLymN-R}Eq z_D0t8Vmh5}1QDMptSd^!Go4O1vYx+P*Ffya$w@LAjekFI&i5mtvTE3yi(h~-c4=s6 zD4I3sLs}#wVQfecP>N6VWTi*d@2yz2U+1o0=@+^Z7ysgW)k_%me_M zZQ|?~MSt<)MqBbbK?4BH%*;fLM&kqk7yw{bq4zErW0yT1&rh3ujdz;<<@5O#^?Lmy zL{uT-2T-8fgT&+U>mHBioyL(X8{TA&yf(Z^jk1N4M9|47o04U@Mz7KZd|@`5zl}zt zKt#VlL_y{)IK~+Jro6m-@WzcB&vSA?&Gm;+HZ6{n2s#;ME7Uwh+1yw9DBD%%BZa&H a`~LwfPq!MEfSe%!0000cK<3RVbc4 z2r7YvprszXc#)#LdGVmF4K;s(zfP$lf>cG(gI3y7h&44k)AyY)Yr0v}XtEhH%#Zix z``I`9V_pQ+S{}Kb=;~jXTlpdx5_i1oVC3w7X`b9%?o@A|w|+rs-AAY0=T=MF4n4Ti&Cu~iL!l2%XoF#SK3HySO|ip% zYiM)}Z7{4ZkGV{w4oVq&!4FfLHAK=f;|xa)MIc~+W%|TlBpDMq z4t-Y?Q3f^nLHneNI*y3rTz3W?A{>Ji=UYoBIoi^_j*w=h!2&Zzni65yp7t(EZrx}6 zGvD9QY<}LZrNf=u>C&EKW_;_zGkUrB)wd%#{8qOhrGmFjL4Wca#r=%b^YtP4dBUQ>r38;dhIF%_(4kiF=&m z`nfq+Ljfx%OF5FBY95$boR^uWT6x|WKHyQq%^|@oa10oy1#kV`sKJI|SQgAg^{bHP z8~-*cIJCjA`lX05IyW-M>B$f~ELdZsT4+KW46FGEj2X^}I4c}Pf@U4+ZA;0X9xTtd zpt%-|8O{ckN2idQVpvas2DE}1CNwL-nB_cJ>B0%E^=;m!Jf{AoU=7wnBP^$e*81mg h)BnN*Lu~M$wpF{qC(npNA20v_002ovPDHLkV1hl|c&q>b literal 834 zcmV-I1HJr-P)Px%{7FPXR7efYS4~J%Q4~JsK1Z!|f{GxshzM%o!WuIR4O|p0jD)gP=?f|oTNSkH zhg<|fv{bQ{r9k+FfTAqF2NMS3@tMKC`u6xjU~xX9 zV@9|EL0o3=t@GLb)l-54x<_W>!tLtzaW5Ywx&EeWi$JZ5Nq2hzsB}ay4QO2-wdkTz z)tby?myujIy7vj7`+&GSlT$Wxyd+P|Wa3coj?+KV{pOJCMp)-GcO!z9Zk+3wv+yBF zX6@ao)~FjpxCgp%t4;uh^GPi68E<2u5dHelrD8WO%Iwh0@&{dkqT2I(P)#GY}ixFDPO5F^kbg4@&TKi3LxYMfhQ)y=BA+= zB?SmrrZQYz6oks)dRzTA_6fcvVz#WBuLzby%eq?Ire}N@#$ppHXjrl|P$oYzCAlOn z)&h2Of{Q`~{d4BG-K6aG zm;_PON5W?Wh-+Ske&~KpB}xU(g5d|aCnmu=S?!4U$H&8b8{^dXWz?3`6TxGj-o}I2vuUsWwD(!CYNa*;WMOFI{mbEui z%`UO#q&=NLUYEGA?BJufGF_K>oQLaDIMA&J6*XeG8clAszQ zQJXxiJWrBFq5A{6quBN)1RbMj^lxhGxG)#4;T*Fl??PxGQpt;iIQXh*pyFCLu(*?xcn4q?D6r^H;Rl zWyR?|YK{C{Xk90}{|EfZ=CC2m=g>`C1&KvYCz*|MN%9=Jf0rc_JL!?Fy)$idX22gu zY7B$clR@nOT{6>?&!ir}2g#!CmPNa$B{J%^4fnwNB6njT+K#Svr`waws=bs)Fu=7_ zbL2ZW?G_H)`M7EL8`qPNui_f5b90ipvc)w%LQ=e9P4w@gw!Mi$&SMs0L_0S6jZppT zh$_QgQ&63&U<6+(Fn&BF%0e~ruH}bl|M$~EPaomV_Mj1{ejANHa}^k7dKf5Um?K+PyR+C~84x~(h0lKjBK?If($2tq&7vElp$)o!teA8Px;9uTTSDEm z_XO^Ha>d9kN|vYrO43FrebJV~XXU$tgZZyvOg#pPE+|6|^@_R}p&hnJw&t6%awGh~ z%e6eumMSbqf_+!_3ShBECI{HKHn48qZz}9w&g2+3MvBE&H@i!BZEiArzAv%Dx!z`1 zl80D%4O#K{1Jt^;FAXpi;Yh?VeC7*Yfn`8uVI~4wF7OJv85WPG6`t8L6SJjciX7`% z^zWRDJZ)I2TV_&g^(EajiU+aZFm1)sHE2jNCV}z%Xf;Cb zFI^tJ=gh{8Y$XU!7tKKMfG6f&9XCHPh(%W$A>o(7_$)IEHf#^Mv&rs~Qo=-K)^ zsHrOXptEmmklr2Wp^?c;+Iq_ZmDF+D8oGCJy|Vk}>;P>#*-d9+q2-m<^jqsT*f*l;nA1}D7$bO>zsr~V;-RF!ey*;C-S^$JaJz$ zDqUGGPS?PMm7xCdf2h(|P8AraCUJb~-?P;D*9q;kbP0dR!I9r+F$SCJvH(T#{`2tY zpS0ztuN_Bd_GLUiNgtj$PD}ljs_sP`e?D}I9_#6JH9~V+n2maPTH1!4O!4{qW;GHr-iLRtv2>wVx6H__22ETZ6q5SA3Yz9pj9@i5TLw#~V`+s~w~7(0 z>c#^ZHwUni$elAhLeFf>$T$i(k&yeb?>vc?KKSVrV-i>;hafem^tl`em@Sn6bLC!| z^PmuVS9e_w%@L*U1h9{a%G=p+hMAZxC76pdWI?@5V{U%SCgmF$ ze?e*QGE2srLx!2^(kV3SVr(~{kCZkkya$6~v4P|O)05lIbA}r(_Fk4$LZUofBX*ufXfhgx=U eJ}%Nv@%{sqGKc((`7+%A0000f literal 1704 zcmV;Z23PrsP)Px*Vo5|nRA>d|n|*8)MHIl_o8FbS&|(SIK#^e36a=H8r4S5CO-%fvf1r)1d=x|5 z07{H8QAtcLG0}faG!QU72prZ>OvRX@CTe1<7>uP56A?;Gq^Oh#jVRaj>+a_H=B|6) zyW73nyLBxgWx+kEkNbt3kaHMzO z@>iWTo?yDZjOt|sd~J7gQ5lLxLfp;{Rj+0=sgpne2SY=_cU$h?b~O{uCj?&K;VBTs zRg z^BHfg5aMK3LMs4-VuAE&{Tc78R(K*+Qdn;3@~#4x=wRsl6sFmsCTcoZ+2BnT4D*<$ zEnRzWM_2wSKBc#rTVZx(C9e|-I! zJ#&kwut&|5W|f>Imm#Y0EpO?aKW_)1PY7KE?!%}gw-2BFq$elqg3cAQf=_j>)>d5`Ov z#?OM7wgD0H^vYZ+Gw5bLPZXS=du`M!a;}W@#Iq;%m1v4QY6XbF(Ktwsi-~z`5xeU(hRV+9mROU4B7#y$D3+hfDn57PddQyr&^QQv1 zVk|5OR;b(s#dG*MIEIJ364*(F!VPzql*8=&$Yp*1s2|SVxC}!wVCcrKeW|+$>gHBM zMe&@lzYG2=(AL)l*8_uw{;dcF2?hRxiyzcSyjrQHvr!OhW-kV}7+?C!3rgYE{1WKw zKc4_^*Iq$;7OjIBu4&O$SIk-nOG@T}r{|Nj;gLj`mnXXLd#tE)s|D55dT6blk||w$ zvTLt;S`V%HQ!=GXI|&&co`PTKncl1?bFK|GXDnWs2Nx zr}f`9bm%Z4-?)%JotV``W|oX}Ml!9wkxoryW+|D@tWH#p5Dr`r$$_ZQMnTQq0U1iD zp=3%IpX}PJ*?S;367MD~Q@XU16k%`|FY4x}Hi>t&WU1NP>T+h+UM*Q__RjQjMkvF) zF7RLZ6=s(68yNd*xq> zH0+9itBCn!`)S8SK7l~_Vy(Ar)z-h2i|}$LNq#c{f6l2&5ak?O$0;gs4u$l#}W9OTG{M38tzqFFjT z=k@xq9w7>TsCvgAJiULUSLRHa|Hi)Ke}1m#iGnMk4ANUXFTap# zkDH1=DY!CVCnx#hzK(m|bl51n|349b%phO0va3zvu>Bv`0~?hy{lQ&`Wa}mWl`oBMG>qD}D$6*yzG3YXOMZO4ly_BC yu*-7Y0000+OR~%r|<7v$L8LhJNL}o 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 literal 2722 zcmV;T3SISyP)PxdFnyY7aov!^dmn?XQ(T^9SL&Clv~ZzUg$+XC)tNB2%*5txTsxFT#QG(D*mnR&4vP==6j_f9g#0 z(szX}z9TYyA<%1%?aIx~&uS#tUlp0TnV^eWI1z^U!@Y+t z{X|qpD{1IYbp5(Gfc_4$-HT=dB-iqQczAqp=<&AIFWgKvjijJ&JkxkzW=7@_%0yAJ z8MzbUBjA~kEI;x_Mg3qh`Arx)^(a@Ol<`|qP>@Up?!35oJ_Mr=|EB!ezC`n$5cEx5 zuRI`O#^G7>z;sLx`@^!lVqZo5e;h}p2#%pYdA51658y=V#!C_@miuuK@x4fRbmhML zpS|idHOWbY&3|evA>fD89XMx3zw*yy_yWJ%cx1;MCk(l)ZRi_L?aY__z9W>{C!8iS zTjgm8`hH(w!2v3tBa2}hx<4!DRnmR$Yz3HTxv0iJN<$vsauVOx9jfhY-o_;MvJ=H= zC5srQp6i3ub3JLN+;O3AKHap0#!^mEEuZ0|gm#MSo(%O|-@h>mOWK!jxfU-KOY>55 zuqK1vRqpYC$HPd37~GxfhaK@H<2*=n7p~q$Hmlr@B2R`0FsQ9P-4u6pHD*m;f2w%_ z1N^ZE(>?*R)eL;n%iKa(#fk|%kOlk&M2cP*TV?Ui3M25J=N7^$*QO8BO`W?JN-U$B z?3Cplvr?SqVFQ;xxK-Nm$aAA+987DvBuU@#fScj6?N_wmvkdH(SU&=*a;|GwV;>EqQ6VWafanx2vQya(Kf$@w)gEGf<}`ifc1DCiFzYw!V+ zX5A|{vx29>F9W1nvvi`Mm*n5IhVIZu%>+Ha1PCy!-f*hTi( z?_3;#Yz#!P)u7W!RDif7JxxR)imd{je>aYdea^$<5&_1l^_msvew4mIO-1_ioEroP zYzhBtT-B{Wr&n=&GL`3CB#<2lYm61>0J7%cV!COqnwpLpWBQDR9DT##7LnrY`B0ow z2zkDV33I`42>NafLf?q9Z*)ZId0>7Sd};o@P!yP_6nP-@KltO-^Kjy7w_6A%^s?L5 zWCA*}QqdMYAZ0>%K`|6&hWa2Rk4J?YFGT5?>&u3^l80bX zUR0AAO6Pn``LCK+3eCO8;d*$)m<1u%60n7;qDk`t!ru^?0ap{{M}9N7Ogtw_j~Q@% z+Wcm48P^=%W;_9%(F|mPj++8w4L4KIWw>lCCrS@DDaIOZmL`|svMxD|u~c)gA&Z(c zLSI;L8*bNG$y$XO^;^ku8*bM*k+rLHQtmeN?BYW0!l9Cw;_5>)rhqQMO4ce&r$RZk zl2sp?#yDozPGrsE$MQo4xoVg+5(&_oCC{ajfCT;h!eA1m-YjLXDx zqV({Nj}>?x#${Y{3^c}*!vJ`Z#sW%3Cdhl5C$IG=?Qq_lQ(G6@_Ht8TRm1i95T%Fr zG=JXHp|r!NV;F#zVY;A}YjPL>-=p!DFRPv+j~uRDz*gys(!fsv3;W2`_QW%6IB+30nW+~Li^_Ufm_DA4&_ zcUtM;A1D>{)QGI}SE|fqNTMarj8KVM(CYk2SMp!6{tp7^^wvmC#n+7lH0V5l)+cN;3V7Ga5I}i+ zjO{mSh=Sfb+}}aXn-7gb-gSZmkR98H3^5+X2g<%5u^Y2n&Tp}$s9e}PuypVHJxDETyuL>2a@v1Uuhgw6v(WAJSn z1J>Slq#?V6icGfrZ#OO+X|#%LTGM%iHIKci;=~d5p)UtGotp(Fm6tut}Vr(yp*p_;C$Z>!vPE(D?F^l*Jw^_#6n`c-#? zKOCw~c0UZxCn@M$0pA-UI6PKGHhxx)N-9I#GX9|Dt^P+v?EJ!+C1qZ?0==7!n@hG}-pt*qN4N3fE%ra7tiza!6;ZPda`L<8q6gw}K&TyMib9Sq~C z(3-AOj;-Ze_XbB4DgdG_mUD#ozxc-b-T3 c%(xWze~xj|8^~V!KL7v#07*qoM6N<$g17`uSpWb4 diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon.png index db35287b831e2129e81edc34c30d923799f031f6..1622e3b9ed2a53dec2c11adc22e7e8019e5a7b29 100644 GIT binary patch delta 498 zcmV2prBiqqDycP z!NFo6zI(h+e4)PfJzlf6ce(eT^PLawITuK?Jh_zy3mFOzv48vKvr%JAOMyeHI)b9S zi)H^MlBJ%EGhqpY4JdN1X3YAyi?V!75_4SAcygZ^i}tra0#F-72bS=F4Yly*>Gim} zAbz5hx1LWc)2s#VV7&gRCn(4!kv`%~W*6%+)Qd+B$E3U^j{$vRwVOvl_9Hy}g1ja| zjW6J>6JLqugMa&fQuajLQ>SdFdlSVMpHC_XVouy}+yZB@2XE$bl4Hq(h0IVH{@MVqG+yDRo07*qoM6N<$f=-i_@% delta 529 zcmV+s0`C2c1gZp(B!2;OQb$4nuFf3k0005xNkln{!gvi$I6FItiGg7z0|Vpwe+>UPm>3v6|NZ^% zy1*>$0^9^F44@wDAo1+%7)A!hsSJPqy8L7K{}gEO-GBf8rGGN9Fz$#wJ6jXGE{G^r zLle)=NoQbW==lHtuj4%PjEgV>7MP@O`1g;oh?S9XPtxgWN-%MB8pF`UGqXy723Gv} z&0q^O)BW31)Mh5GDpT5}7x66BttNvQJ|Hr2us~xky5Ni;+ zy7@+_+5Z{;KM-YPULU%ufsN_XzrX$q92K}mdYUGF TnOl_r015yANkvXXu0mjfI0pe3 diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon@2x.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon@2x.png index 4504684ba4304ff3b6493aba897fba8672ab1a07..cefdc5133dd28b3f03f66b319a0bc5ddfe1c2719 100644 GIT binary patch literal 1120 zcmV-m1fTnfP)Krar}oDgF%BJyNSE4 z)9l~uZSdg^EcebmbH4Marr4-$#HBC`gmQ}vB z^K6e~KHbHM4iKc<$kLe#5o_&lq|_RnRCyYerIqi#Pk)jHxt}TVEeNh4Yo~+RzcyA# zm=Zk)jy=~=vH3jxNaoTHFsW%Q>rEgy8T?6))3!qwss#Gw7gH{8uteu@ zHXqX~SAI;{Cw0}{;!Eo!Cu9S2;tMEv9n{JOzt8m1b}3#Fx9`BurfeU^EcNs6_aM5Jph+4s!%w1sxPU8)&&v;1g?9tF|!I9ShcLEfx6wvM4`k~$|( zG1C|bE&CrE6h!i)cMR#tLP&HNg&uklajqa z!j@~Y^}O=638)_qCB zuo{A;f3a$7@KTo~=QG2K>Gco;;CoHa$iW79_07HVxiWSK6ve#NVc_qo?=WwzNs{yO zDpJgWe`mhaq(+W31K4Ox&?_I1p*{2C>|5CDPdD;eh@`^iegn(<^4uOGyEW(@8EpjA ziXAI*6o+qcZVM^(KINpZp8tPIBH?1MjAC=|2~VT3wl7FYwjO}54TtZLH8z9Q(yZtc z5ZzP@>k>&^T{_wIX_(KT;00rGi=Pd= z>u@#tSo+-{`XLlu#yT-Y^P_~;;D?A_O(?t7-R|#RWAQjTl5dHtDq%-fBq$7xTH&)VHI>#|q(h mIgXM3gAx2~uXXSv>HY&*)n5|QCjwjm0000Px(SV=@dRA>e5n15(nRTRhXxvxzvW}Wi~GOEZ>M3E`xhmOe@)osoV_eW=k8FTru zzSOQTaae@;hY^H{I22~B`C(p2@du3?qGe^ywR3~Hwn-KL@vo`>bpK4SYa`YsxySPg zFPmA?ye5~e!V8pp-@W&o`+47U-no}DCh^yCK6d+_ba=Hymqk~+*sHVSxe&eE-h^jt zz)yS9;XCVecb&NuQ2%(}z0Edu768^VfQOqw`PMi3{%zOoR>wfypx$)&eo&guF$ND7 zIe80=7t`C8f~g9audo4CSGl9DS4a`0yq z?TNO~TYa@2UtcS2 zp!zXKMfnT8-cb(GDTCWJXK-jS<9g@fPBlbg9HF{w1BS=_jsD$0%~$RFwxPU+uv8aA54?$4d9$_7>YI{gy)$m-2`klkV;xOBdaMXPmuw(oe_j zae`fijSZ)K>F`6>?n~bdtfPGVjTPoM=og7=CvRjwwJTM~UYzn!REH^N?;>Ttduc4X z#$ce+M)c2{98`Mf(9(s=;W^dTlf{|Yt#pyuzff-ps$n^Rm19V>y*f?f z{l;9e;2Q(WwY5NHN5)drQdG7Avi(^(YAGsP0onen9JLgct$=KQR*qVV%2q(OKPyKq wMP(}>+n<%AvK5v3pOV=t|E!P=_`mb_FK`oaz(=xtx&QzG07*qoM6N<$f(UI;-~a#s diff --git a/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Input/upload_icon.imageset/upload_icon@3x.png index c4af7fbdfa398bf937a1243be264d3275959f081..5ec25ef868d8bd1d7004ae68dc31cfc6372404c5 100644 GIT binary patch literal 1799 zcmV+i2l)7jP)xkh5gSJgqdq{@N}`GILFLpBbe6jj|KJ5bpw}`6=!OgN=lK?~$V%rj#JK0+S}F33 zUTgz;Ds<{iDK$qHiD^!G*|KGSfvFH(jc!y)j16lF0?HS#F@x*XXW#B=s!XQs*`4Z} zMGqs7Z3pzj3CES%ZN-(M->o>{XJgTO#Y$&8%pQ2f)N8qqs<4RNXF&k;EydV3R+^Zq zz_PY8ktVjth=}pYboOG|0gs42JU?$2R`0vD>sYeEOfSo#viXfsm}yp@38KJWZO4Mc z6r&Y@AKkcI=2Mvm-%@%r=d=e9w`+GnY%)pXWT0%Bqx;XkTVqCR^`f_5=VQuq#c4G~ zM3H0p3>h;E9x1(zGe4l&E!sb*TrZ^>Z3fFeY1ZG+{L^NAbQlKdfG&snKF(PMMP>|b zwq7eTGY7tD`dys)c0=hKv_FbeRGMl8jS%`VcKNGh?kO2nL-1%jqzj{+&YbZuRf-2M zUpe&>nE?+^znA-cRhXvNX&2!9St;dkKyORQrI0uw89jpfM|3^3*98u4#k9XCrFL3S zxb@(h#bC~j9Z={R-5;E;#x`^)1!q>Zp#MvY1jG@k08i?K&cw9u#u@vPHiLw!9FMFopiEco0`BRPGG-2@BC#)hmrye(4oPKV+S4iB4rA1l`{`@iP8*a0(YiqtntiN={iRndFmos1M*+TGHvk{*;EKMYiYeXGYcPfP zaX^c2~Zv%eX;wE9#=;Q@B0_hE&tm*IL^cXy&Rpr zW@~b*`L7yIA#v7b%UKlgD@m&4>nk=qMo(H#IN?dfiKfAY@bLk(Mvt(q!S&|xW5qO1 zL~XX5M`chf#riTe(J^C>^WJ^dPzoov&ftqDcQyvnMnI3T8ppl0$~^bW7@D*^zQ9=a zwhCoH%u`a$vigUwA)M)bh;)46wd_rWmx5P{F2+s0Dp5c2T8PnIiZikC6k2aK)lgg5 zq5O3C_MX)@;Ge@Hyu?a37d8f8Bf1$%9~EKYYPg{EJdEySBpVhKE2n*g@a=W@sFjXi zScG4~x-`#9Hx(wqH%;wnbjPs}qX(?Q*pZb&>Eyj+WwftQ$scGE;MZDiLHQ{-zq3Du ztgJ+M0UTRE?#tT+>p-2O9~YQHui~g^cA{i^jtC(EKNenxEjO{ZFNgB>r;(Kv54qm- zV+*(&ThRX6f{~LidX4EfXCbqu18^{_*2GW zLjYYsB_clcbNe3=jiktNqGZ-@_8zYc#qGomaSz;KP+V>D6nC|}4sf304uj%qlc%_= z<#mAb6n7XDSDQS=T`jKzoTs?Mpt#!PDeh`{9pF609R|hKCQor!%j*E=Def>Rt~Pm! zyINicI8SkhL232~I}D1eO`hVeme&E!Q`})tTy63cceT6@a96D2IsbPr pd9Hc^`SO;=MTkXf9mL3q>3=~w9%tdF>1F@`002ovPDHLkV1g+sXea;x literal 1900 zcmcJQ`6Ckw0LM4S95tIO%dK7(3bUNUN^D4S%AmGvqn>}_{qXsIe)#?YpL8cjELc)e5&!^z?QE@G4vap)Q5Hplv{O<9+3-3WCI`;YD7*^2j!y~? zUlpKm19TlG9>=rz=ZzP!eSNQeW*fyvJp@yMyOKnO3Xm<6mTT*>CxR#Vye@Yr^ht9l zC;z3V@$Rvl7`eXKAgWgW8s2}=+WPL;M-ia4qS$6r1x1Ne!>NuFc~T5$(;t(}2x&Qe z(No3uh@PqL?53lufn9NSMRptb`4Xl}!=-hg zR^G_whU`*n9M~k9pNqoKHC3d5aYad`IX}As69t$gPHP7LbM}@Jsax<}K#I(eE#LjD zOrg9rCeKCuUUIcj$!f~E1S=9>y6tICi$x#W7mA|>FHMnX3oy(NL=ZapHYF^QZc(!_ zb(3`Rd(5w$ZPN?yFt zpdthNE&Z^n4iAxJA`D&uovw*sEMOLSyw*Ijp6TVC3U9ill5&J2wh-=07ekS@EYJ7%gdl8wKw^iGtZN8vhsnyL3*fFeQ|?e9l_gXMBTDgGnYHt|7G zJq;hJ_GN$a9P})N6`q?@fc@3zulWfh5?F;8?SImP+6ec`gdzx+<-5uANQUi{;Yo|t z^|EmyZhV|zUv|1`Q1WI6Wjz4HtVghcPo9JhWz%)naf1(zeyZcmZt8MwTR#FHmN3Vh zC73ORZTHu5paWtMWt|qyDUyq|B@wzPo|!H4pQ>X+!x0;SvcIo&Th9E0RBR+ ztAAUGQB%;kfd{U&__62kB(rB-F{1@lE?&wah3;dbs08UE02&XP&0oBAZL5AeF=QAEf<)j!4@ZP}{XANy zmYMpMup<6@??LUS@0dney5LrS&C-rTY=IrZZuBo}_su6V-~;P+NOp=sqbU+VPj zr9Po^SZy_Rsy7^;I`T`(10r=&+0d{~@;lj|%Q;SON{Al~R7C_N2B8mY;Iy>lbzU)h zWU$n3wNM6$*BLGdrvTOLqY*>rV<)t~L>!M4?x3}sN11D+kp;ff5J#`V@QEQ04K;Ct zwpa#@Au`I&<-j1Z(C6+s&998sV`*+ezrI&y)Z5(vnk!cVx-sx%sIE>FikT5!-5#NKg5 zz}lbrP^8D5{(e3EiB7U{vLCb2ke1yN7dUyCvN2_Y<+6QA6X0k8>(rCFFHJqq*ub()Q&y+t$;f{SuWZ)_d^_b9btaPJ*`nm#tTcWT$jPWWB6VoBx!)$j<8N& zAX%EEn4M{&gV*E65~H?E_S?z5}Vm*q8XDbddjI2OsS3nPx!(HJIJoS!HB>p{TTvGmp~A zf$Tov4P-!be3bVb-zl@f-%{?(2c6j#_ntfk!||jMdG`uC`AwK1qJz|2amv zz59NH6K3AiA1h>Z^0p&>pz7`%$#D~$-7{ZP^F4v31IL8>5Aq4HvvIVpwenB=4`CdL AjQ{`u diff --git a/Riot/Assets/Images.xcassets/Room/Input/voice_call_icon.imageset/voice_call_icon.png b/Riot/Assets/Images.xcassets/Room/Input/voice_call_icon.imageset/voice_call_icon.png index 382d09080bc692cf33eb67052aad8a254ab13e10..1b13559b7fdc94ae4af29aec83eac501c1e62f92 100644 GIT binary patch delta 949 zcmV;m14{h;2g?VLB!2{FK}|sb0I`n?{9y$E00V+aL_t(Y4V_hAh?G?n|DAJZ+g*r! z*woM{daxG}BV0u*BEo`bc6JR{L{KCuAr&M<-F0T~wi}_L5Ry>gYJVPL^3Tl9gD>XG z$_C~ZDUuHg>O(S|RyeE& zs10z(Y=_<+)JY{*980-06Mlq6%EG*A@3=<=e;$G-B@TWm6tXMWsZTAUSCAR_E-0wj zKd6Xz8=w@hB$5@YcgbNJI_{BsBJ+bg;T-0nq@PVf9DLXjwVMfdIsmcM+JbOE0Xt(X z!N&Js9L;#BmVd9kg<}r15+`~eucfaClis?^aCS*e#pcxx|Ak(xLM|DeJkf2w%Nq@ZJWaXm=Y0qAy$dTuU4z#w+?xz_Tn^jANyxoV900GqcLU@O ztCj~ojLFivAp0-muzijES`m$}djZ7P{)0gWw@4NA#z1AiM@~xh7q=`v7_dg9^m5uN zWS6i?eSc%i<@QQeUY*}Hhg)0Elf^!h(L>Wb?)&+l3@VnL1DD|3e$~|UIkcYAckjDx zCy{o9_Zz+ZW@a$;Kcq_fteoNzo7PgIyQ`R6&8$AN(d2WGA*i6I^m116ND*DNx7-oP z^%BgzoGk!Q?3vHpJSGNNlkPhjoK&&@4aew}JAbUlIhrpoUk@A|B*rtof7W0#I`wF< zpFM!LDC%WQbknGfTbi2U4W6QhPE21NIV?WHAzP>d!u;YINQ zQ?+~VCSZ&_;Dg2*^??LR>u$UEjB_?U%~G~?_uiK|=bM>t&VS6EGxs9QKHCb%9%upo zP5==`g5^MD<%02DTJKc~sV5V(sUP+Nsrul#ylH zY;`8`S`o3ceJE%@??*J|MG8dYT`BRcYH~$nef7uZT&fi@JGI^mvGx&w6q=kUUC_Xs zG)<06M*)q!bAOnJg#d!0u}m(l>3ic(ixAelQaJu_O?@4pV1l1p$iJ$Vt+l}{a+!W< zcKwgk($|A=7ttt^*i_3n=44Dhz(b;R-KnLo2NSNOlT6avJ=)(=?GSM?dkNs#^1m~y zbL;m_RO=d9i@{*>ca_E6fhFN;N93Sbc6SV|d*h#KynoSk<)ZOPKjL;e82Q!=Xac@; zS7noUM(@4KN&u@PehC0=T-v%v6S?H>LlFBTW9g8_yvRxb}fDs$Xw+1y=1k= z59<>~@|lf7z$usHQ>qCR-jmOE3PE8$$u)U%{C}hxFWO$og#tkMhs?@AGdMg94-It0 z2eebfNyi06Zw^30|K5>+h+97dG!IEgC=(_7>7F2ogCWcY`KU z_S+s76nuf}_w^sD^2eEW_rsy5Q= zTu0&@|7E;x7&M~Fpz+0|A}7BdIl<(N*3FkOC;J7Vyi!*N z+Igsbhb?bTJjo-a?Qs-NbS%AA>#Akc&S1VrK=)sf)Yni3w~?q$5^$6+-&F~anx2~e zP6S{@vuHM%{IOdl+&H{;`*qI&D#7@sN1tnb83m}>wT8cpCBB?Fo@qyhx0=(+=0Cd@ VXABw69L4|u002ovPDHLkV1k}|=-&VU diff --git a/Riot/Assets/Images.xcassets/Room/Input/voice_call_icon.imageset/voice_call_icon@2x.png b/Riot/Assets/Images.xcassets/Room/Input/voice_call_icon.imageset/voice_call_icon@2x.png index 324c45e3e8b41c4fbcd65f39c7aee20a736703c1..b5a2c69866af3ad2dbe7c98746c8a68f1499f63d 100644 GIT binary patch delta 2288 zcmVwzGO5>t>w zj2chWdR7pt6n1CEZ~pCK+ueWZZnxV%Y5)D-{bt^K^Ja#T+kX?3J%yJQ88Tyt*tsC< zPmG$#m^#hqE-I3LxUuFE&JvUbO9b~0yc0&xV~lzy;A4QTs@_~kQfe1`&cM8lrkeXt z6y8Cb7-Nsej5k{h(R8JvgB6*>l#ZNXjA;PRa50o!--frFK0F8YR?9(LunqX`3!{J1 z+T2V5`Nlzf?0?4>EHu9iq4YdLYYsp!;Sc29_rzx4)p@7!JhlPx)E6Ku3V-*R9@FeNAo4v+9plNouC~!=DqZ-yt6@?`G3bw3ydW{#l`cmJ zj#0dl7#oGy{!Z;~Dn(+#z|;>icZD(3h)}wKYRWH3O@H0BScJWp;;1mRh$cPyPlwbM z$$t@QOD(P7VpfNEx`>ElB+s|9HK(`J(E<9U;N52!yP9g`S?Ta*la?b4`n3q$m6l*< zAu}tHJB$muCoSGA65AwhcH~7VKV7+6MIS@%ASJLSgvyRimp>cyaKQZP2=dS|X$u^? z;A@oA5PxQ&fK$PQwE45Zz?orRSUJM5A(_ZS9&C2_xEY)Ye`k5PVKD=+vR;;%FmtlQ zXJ~I`{GH?CI%+nxh!~AGqM_rDsFk;Z<#x-VHLdG7XZ9$q!Hn0+ZxG8Tp=rC6imPHF zkxGY@oDZcH;F)5{&{{}cR5?EtOIP7+6|&9P%YRk@=VG#bAL@bePg~43d=qg=K6%?#V~%VHC`(}G))AUq& z!ElR%H&jJqtLjtH<^mUU0GbrhBaTAGrqil>4|7wFvRi0zn)G%znq0yUI)FXy`v{^B z?0-&-7xuc_%?Om+T^7eV@AkcbV@GR4m5$DJz8T#|)iT~AwI(4Qp(l_m5df!AsQjWf z$Zq)fe+H~_TS5&X7pNB+w2GwmjF;b_m0rY%c{umHLczIxlhWk~*wz6kRTQ0z_CTRN zO~q#A>|}Q6ZB!2UW-KDd3va<%!bwIlx_?~25*#3Z)lO8@r|k#}?pX#SU}w7ryEdiG z1mwdn*v*aPzJU+6qsZB3q61K^_tLzWadeRgNoTc9uqYrK&^}xXx+t8Tg-y*h2{btX zBz1spkb6-sol1lq*Tb%H9+2;mX7^e01wM) zuKI0K8=7hHn6YOmB!{`uW(kp4<6Q)c(EJiCZb5q%goEEsKA19Py^S*aO?D1UgD&yBXT z@D4j*73tkgGvLIR$cMrFq~6W}Z&CxME{~|l{%a6+Um>Z7318tV(50U3u#}%%j>b?@OS4t?XElmmh?q z7h4?Ya8O2TQ4lH-dS4~bw|@hq?*IfKA0{Ioo=1%D*T#$>zx=43-2Xq<%Mske-h`q& zm{x&>Zvl{C#j}3iDcqA+2iz$D>;_~PJU9~$=i6KZSs5C~#i_2cGIGG`Mm2f@Jy zSc8rn7)IkC{Mo{jJ?N(<;QVPd4C65Hef(Yzx;}8@Hak1`U9a|;QGZk_|0K)^&(B{7 z*^^sjZC2696v8QBGT9kBU|VS1r_~{{FNff*xI-I>UEROQlsGWlLvZ5uDCW4*G}d`E71;s$i+U0V@Aqxg)~f#LrLVK@r~!R}QMjoEn6 zMnl0yghwBg*|oZ!u1}SC8L6zE+naj|mO#fuhu_dUYR}(+?0-05C8CCNCN|ilbmIEE z#z`r|DI+he9yyLPS_VD+py%=IIbaQ{DId;-K*?l>Bh@x3Wr}I6+>@!Tu6!XmSa7xj zv;AXQE3vDtZwRQhmn@i|^$APvsPMUiMtmd%nf#jQmerN^^D6}Bt%I65Jm$3z{L$mNX^&qdv zBflXgL1}ZmGxFL@LhtmdrH?<|<3LfMliGxAPS$U587g#OFV)1RgfUr1KO20000< KMNUMnLSTaHt7EMI delta 2436 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 diff --git a/Riot/Assets/Images.xcassets/Room/add_participant.imageset/add_participant.png b/Riot/Assets/Images.xcassets/Room/add_participant.imageset/add_participant.png index 1ec5cdeb1208b67d6def0f36e2143a714d7780a0..21a6518405a1124d97d96c0230fad3c1c9aabbba 100644 GIT binary patch literal 1099 zcmV-R1ho5!P)AQ%;j zLVif0AX4y=b|qL5R1l?TX{GdGprDOLLMZq^!M7OE*j9}i-ZmJld(!z+cGfI6rLfD71WO3lPz8V~q$buNkSPP8cV zGbeMihM{K)%aj4t1Q=sD65TU5YZ$yVrdC%yR!Yxl+Dxg2!>J#fl!65XMM%?KMi53mYMca&TFg<5DhNWiV?35}j{b*cF5hn+0 zuon9SC?iRaXriSLa{{w1S!!r5Ux5wRj^md*O(EFGv~2wQ=~oziWCyPMp2P~Z*=eJ- z>H$^CD=wwqP#Yq`kdr)+rkZ4mvWvy`KDdI?jQj{BkW1L?B-by-TBY=9@j0zF{H>!X z`UcN>yOEzVC`8(41&Y&$;C}b>NE23#n2aw!=CwFC)?!UfEGpk3gvfJ-g{{3xM^~^H zzmK1f%bkxgWI!7BOjv-s-JRIn5>85aWE+~AiK#h-khG3_g zK9DAVj;Q2q1#T(&42=_)fRhL1+o&JS94m)U!p&)4n_;}tU+=nJ#k`dp`5c$iIX>*P zvnz5(;#AoO-7eedHTl@|HjQIAmN}eiYUTPx#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2jKw? z3J@v~<0W~hoHnYWs8Xx(T3c-&{E#k@;-tYc#;+&bRYj!8D-Z%prX!7XPX=)T1cMl@R5i z3IP}3NQeyq{UAOUO0^j260 z!a#6HD)I8p>W$tRA=+@}kRFW0wgSHdY|Jb|zz(~v?Mc;+MXG8l5C?&3zF3@AsP(C+ zbJ8m3Zt<*KLj0CF0HM^6ch%Itoifp_&HL60!9l>n+(29@*6*p= zbR=n_+fV&*iISF6v&klt3?V*Y#A|ofKG!~}jc#c>mSG5aaITTO>7WcD4{m8YmN6;O z%s~H32vNgag%CBFf&P~!RNbHd`w#a^!}6&aIqNcKAyuwYO6>E|EgHSUe$EYc($sg6 zP&_i-cN;Whe8n4&Jb&rt6K%}(D(zRmlt^Ybp3tg@8rKir1?)To_}chGA@*YEtmz!YbxxI5~3V1jjmC zMoA_d1?~QBeske(^bY%Zy0{jnby{lznc#HG8M)8D>l~>k(}&Y)qt?>j?JJ5$qlFY@yA?vn8uIJ9sVK{Mf0PNlpqu zq0L39J&$awjZBLbn?*+oK{y^I9FG!;N9YO<;2pX_Fg846WvT}Ff%#L}WRW9})p^UP z$SF!X)+wMXG{A}8cAEMwPPb$7Yd|1fqMEeuOz}!q<~~5gh|%uv=F-r0I)-`~jD`ru zBZQ48hEnKK!)DRRv{)&$&7;hb&k|<=-z#3p*B4aa@qTod%9@CP2I4BHw7l-d(nnd5 zQ^F?$9sK!f6M*M6gfmj#= zg)bURH)FUeg;K5QEM1&cz>1s_n)|$XydO?Taw7F@?(_1_XYXSX7M?7u8duI24e`77 ze{jLyl^#u{S|x(Ch<>A>f>1odU$32-a=LM4=mw29+Nj7Wq98M8T$w4^u%K0psp7UNf!H)zo(p0aQ*$jjB|mv}ITuL8YYp#r9mJ5L_|Qd31*di5M|T?DNfL z8MI|s8)ZY~x(G@fPi3h~ADOophzyz6$x;emG(?VW_H=+a-cY$NA`?2iKb5sMiwjpper-P4|DBLak_M_OqmjQwUyQ?;hb~ne|o*`ntNHx^VPN?7rm)k0<+y8ju zk>@Wd*fHm6!j9Yjlg4=V7|wFNiBipTm!)bBXSv?It5&}A!QQ1$4NGOL7vP(FW{FQK zWBuNxPYq8>6kuoVbM1y=GZ3FcJmZF9^LXF4 zP(RpRRev-|`Q-6GF~$n8r@Fq)u4{F`D~t>Y&on~7D|TJ0OLg@8|D)!qsPmWl<$*i# jrGFjd9;9d83qJn^F-Amf$q4jO00000NkvXXu0mjfKbibe diff --git a/Riot/Assets/Images.xcassets/Room/add_participant.imageset/add_participant@2x.png b/Riot/Assets/Images.xcassets/Room/add_participant.imageset/add_participant@2x.png index f9c99cef9eb3633fba8b0685103fbff28870e54c..9383bae0cc38e5b2a34dca6c24dbc3ad64c0e8be 100644 GIT binary patch literal 2258 zcmV;@2rc)CP)>@D@Y*}wJmL9gu=Sfu<KmtVqD5mQe2&4nT6HqH# zAaR`f4pHAWx^C|h*on5bqnP_dYhRc~I&5sOdxtsFa4i`>Lr9TN*E}KMjzxo%Xd|Pl zrI6pz_2aHqypNl`Ct{IdMr#k?a_>aViCZ8<}piQOoHw*`->%0p91Z1pCe~yR$%RJ%6lT4 z7WpdhMomx>_Zsyl?R&CW*=}H9?_-#j9u1ESmX@bEg@ zU%|2`*mjjG5SDPyL;%)?4xay;Cl%pV#`8>xk-`$jduB+NFP*G8ogY$#Gct^>Up`Xh zRj>Q~SE6+Jx7`3vd)VvMG^gX9-wRj<$XFN?2wOK`XZH;XFo7tp?|HW2X71>VaL1Tp z6b{S65Jw6QwYB1dhJAQ^-xp}?_{9bd7DOR?WeGG&nKvCJfJ*Un3jdVkDH3?vT~u*0GsjUtN5b%P@*cM^3yW)z3!LO zxSUk6?Qn>zi7O{6rv-vVRip4KHYSU$ zr=jB%wznRIlXm#-KK~L!=FCAu@R#g-)z9m)Sv!X!fY)$d>Jn{?l_pD3n5dvo{zbb! zQcKSA+{;m#6*(cX;cphtK_*?-*X_ZlCSyHRt{wM`)k#|;W9h~Yc}m9T%?I)Cnkp=w zFdbzV-++o^HEIIm%!)Iv8%O8CGsumj6#jS8Ox{~#x(TU)ZSL-Q!9}4xXVir~(tw3>7xh+Pz}m7EDY% zSJCj~H_|Ecl_c0PVo)k-uULfo_LIo2_)kL8 zXwque_;Y1KQu-4!VWrfPzR@Oe>y&}L^$tDi9=in;vc*X=^g*JWWP#e0WJ-EA?jK)* z>7Fqvz2xE`T080Qz>lYzP*%GOtM-3|PDw>vSZkp)^`E;dR4pCW74suw721053c6Vm zGk1_7MQC_z(hS^}Gd1eWYNn(5L<4Ty@g8=Zs52u=sE?MVC!FMmZHY*E{DK)+NEH%? z+={(hu&(Y0?E3i_{JnT9Tu&C|$CprKEX%zN`IKsIru4DkvuAOvk9I>CtH8Pkb7?bc zM?CrTrBvj9QgW*T`=_ck_=eKTc$$-oH~OyZ({+ELhW5@nDxIq1 zQNW(%EbURMZ{r2adN~^Af4c!EI@{H5NOzVMk4;8A3L|0F__Pd_PCJbV&EA)I{-CSv%SfCmWTR zjFf;}J7ls9#>N==UIFgvlAGy%Kfj2jaX51$fwr`+;6!I-NsCe8{vgHxV0Aczjt0dj zr2mjJw%`F6NU)$hf|;NFxS=y_MOmdeJe=D=9CLndQVXS{;KPNzfs zsihdtQ<&aihoWSWLCMBT`ZnB2pIcNKcN#ETIG{eJF<}16CS_tZ7|ThP##lnW9I{zG zW4PN!{iN?j0=>2Sx!+z1gTfL9AObMvt!UvBZZz2KSzN;uo{dMgU7gY+EaCbh0W$?3 z=hN{p4fx1hzyZ&Vs#-XBP_tt8c;t02n9Z1e&i7fn(qh9&v?Rt511cn gg#+j3B>gGguXq(R+ms(S-T(jq07*qoM6N<$f?E|}CIA2c literal 4418 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 literal 6709 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 diff --git a/Riot/Assets/Images.xcassets/Room/apps-icon.imageset/apps-icon.png b/Riot/Assets/Images.xcassets/Room/apps-icon.imageset/apps-icon.png index a2751b1eb0d391608783365352c05773f2973feb..4e1ba1b0c72cf7b10e6a61da6efa568b3fd87378 100644 GIT binary patch delta 626 zcmV-&0*(E`1d9cbB!2{FK}|sb0I`n?{9y$E00KfuL_t(Y4egfCYZE~f$G>l9v)Pa! zhIj~wq|i%Y(W73(LsdjDRgZeM|A2phP4D7eyz9~0R;-9Uc+-<8p@IbBL9D-s)W)Pq zXPVkx#duBFZ*UcZzkFAo9~+?tkvce;~Y{h-Ni#>aeqV+uB2dS#ya+}qkP;< z<%CzR0?sl~jTmndNrbD&@dm=5 zca*pHwF=UCd$;An&mM)soINj&cY+@%b#r5RDc?pr=%6@ezMtK4RW5UxneNG!YQ_so zAQGL_$BabYtV4JXqPoq&9E1h$g6u;h(F>92eUf8_a(|iI2R;D5)YVBopn6zcI%O{~ z;)5X``9LNd{%tz-H;8J$p!1QYmdM5j@lXmn%uSI8+~f{(W+^iGsjEBvXYex3L2}~W z!Z&!m-(lXrB&JEAXwdGxMbGc(B3~SZ@}$?_a?#!U1(o@bnvk#e#b^xQPv<||e^74h zLkHJysM8A*Z|ihPm_Jx#u$K4F@gY2q8%W?0vuq!n%#Lh24$tCn<0kxC}h4 zz>_jdh9+pRNuq}BCU75EtMCKh zg(T6)_5)zG!e@aCJ2`kXB?oK$c6V+{4(4`q@K-qqntxo%!Nai0ER=E(FTl#=&u$L>NIM=J>J0~r0h4~tbb!y6pAGPN;7$rGPyQ;Z rx@++flOh8bLmYT%v4uGw;mh9v6CKF}2wRH100000NkvXXu0mjfRUQ9J diff --git a/Riot/Assets/Images.xcassets/Room/apps-icon.imageset/apps-icon@2x.png b/Riot/Assets/Images.xcassets/Room/apps-icon.imageset/apps-icon@2x.png index 6061fa96580db63fd9a03b2037830385165770a9..f2e7d0d6b7ffd6e2f4a7257d096b059e24742e17 100644 GIT binary patch delta 1200 zcmV;h1W)_X2gC`GB!2{FK}|sb0I`n?{9y$E00etUL_t(&1?^f*h!jT@epTJg^z14K zxhjZZ*BrzU5^@mt6xX90F`0u(5|KcN7X?WU{-lk1Pz1dwLI`Wb&0#Ra)j+_Q(+Yv0 zED1TNOM;NS1_a%8#+k0lSKU+Xv^!PXwIahp7c*3Kz4yI(?|)Twy?Wivh=@@=8l+Yu zK)ZOE2_I7wwG%-7K$TjRus9f;L9;=%vriLD6!|pNSm}ljTU3kYe7byafQNLLRl~Pk z1jHNZ0Qmn>7_YLbMpe1n1y7=SB_{eV!EB^AydXU5f|ru+ipvL&`xJUUBYF!HvBgCI z1#*?|!3&+AJ= zy^k1s$3Rm`>@m_nkVKmqV|z7E&HyIaR6O=oI<1=Hg_>WF&O^Y!3*E^jgg+45qD#GK zx)1nKIH{)raNzu6cyIEU#9f;iz_sAzT9*d&d*;d+D1T?*B|Wh0mryPaNKWJY#xZLk z!XDl;1}H}&KI{a3%;r?!2TgPpUx0sNqN{$yngPhjO3nZf6wNq5hO#tl3R++p$rTR+ z{&^C&*YBr*WoMgAnyn$4$w5xBh`99)dHiP^`vO`lX0tvq|3}O#o3iU7jkbKGbT7hM z^1Mn9Fn=14Lhm)UOOhON8A!x*k+w$<6U^k%QO@{#PIxJPrLnJnNiaV~Yq>|Cx!`ep zpNapI6Fv<-tq@gf*a5b>2q0hn1pbE#!#N*;z%Nz1Xo11c1W{^$Ppe(=ICkHJ?pJfW z5H_jbu}#g`l)yl{OmtwIka5*SPy5*i*lFOj-hTxvVWKxB?FAMqg}tkJ@&*WYK`fpR zY&Yct@X8N3&s$SVl+o=`kt~>dF6_0%2W8#z>-d2NhFZdK|@`#H9So6n`4;)P}eBe!w z*zT(A9<#|1BIRn}g{i>J!41eU} zfMjySQ_pQ|#qf?;K>!>E{u3Je6_BU~POJ5hM6O3k5vH~|ejx5tkcb`5w zGcW4Vi6wn*(@`L9KC0t$o9kMiLMgTS+(wr_>0Uh4sOif>b%4)pp!@%woJ7BJe;hCX O0000PH-Gucd;1nta;dS6@nrm+om<#A)E*f#?tTAE*Qv=@8&_;MQGu*A^ zfnT$^M9(M2h_wT6eh1v~fR}UTW`Ro{{v%*4Xa0k(xPP3U^La6xGuLQ#+s8coNM7z{ zx4o=ce^7w&EKnr=Q{K|6EKBGc*EkeK^)$b(7mY?`pEPu z%apOrVLqL^Hk5?n1h7YCC}O_(>R{s`K=b$SkAfUgE`7Uo;GLTQpUkyiHz6M=_r4Is z@wAo5RDX%718=L&-@yC?JWTD;I54GKUwXjJG}kT>QS$sEk-0H=3jGEwc)*D~rwQEf z@F#(4&iu58-vb=l>=^yJfFC%Xa~J&3sx?k|cmp(Y{D6;tH!GklB}xIMfKosy;9vCv zAEteqt@?ozY2PLS~~n8dP}Deh-L z&MS+#nP<5YSu`O^o(1D%y{yN#-49I7cETidqgqQD#L@iuvHH?eKQR582)neFvUOnM zFMz4p&dwxsZ)h!L5J&edmEH~$2N$(|fG{3sqZKdaeFLBC>;UJ0FVbB5P3AXI)DKYU z)qm{^X<_vrb`4fuGC!PlPyY58JyXCBtmNDU?N+TZ;o+w}eqcudKX9ciB}xIMfKosy z;HCJ1@w9KVRX;G=?6%+Y@S`3-;NuVH2{=pUA@UYtjQl70MMA|}5z|k-fa>cchDVv< z1K^f&qYs|TC2GDaV*1vtM5~pG`%?dR8#KF=DNQ>;Klo8)h-|X9@!CbphNEp8&tyAhAia4Tk^#002ovPDHLkV1gD9%c1}P diff --git a/Riot/Assets/Images.xcassets/Room/apps-icon.imageset/apps-icon@3x.png b/Riot/Assets/Images.xcassets/Room/apps-icon.imageset/apps-icon@3x.png index cbad4c960a69632ba54a5b4f87d8a613098821e5..d30df16006c65763f96cb4355e4d158542971389 100644 GIT binary patch literal 1259 zcmeAS@N?(olHy`uVBq!ia0vp^ZXnFT1|$ph9<=}|mUKs7M+SzC{oH>NS%KU|o-U3d z6^w7^7-ow&iZt9m^CnYIrjsq(QGiKIN#jOFqOzG`tU%6RX0tdZM{}hkKcsU+ck1m_ zyK&M6la{tOxgQ!dgi~&<`h3G%YEWI`TM;yduIME`)-tf{~XtgJGoAa zOZi@D{eGpavn0M__t&S9CtSL391C4?v-PKY^pa}zxs7dh&N-n|{@&&1l*yhOs#O_% zl>g=I8Mmb#R9;->@<~LfaA}5gwAnM$U;Crpte;iDtWX)YC3ND}jJeZ8W&WJ6mF#)` zMlE%>ok9A8$B#C0@i>55BP_sNbqzKG)I6 z^Vrkq&IcQ~nm6in97*8dTWuh5y2*p5jewBF#z}JyGzcWi-+uBw$YlX)~@?$=Ysza7HqqJT0;F?@c|CSPpdU5lokr>ZR@tYkhDL*^49(Xa!U_w z58^yAan^zL@$(;4Y$`}u@hjZBBKX@v-?Dhg(p5R~?$;;O>U}@#K6ia6+g4fU`JR;m z*Jd&ZCoq``32c}*FEnV+iqp%_oiRGIe70+Sk#cR<=>~4s+dDQHKC3M=-s}8p{c`gU z5^{pktgQVH!8>|HqYF4C*t4)wM7z_&rSALRPDccq27AQ+YP*I6P+s+EE0YNrae$ObaAD3->rV5Dla_$ z(bX~@X0@k@5$Q}m4V+ip9KOsimz%#QZo0efS?L+x_JZ}VzpvL^p}lgw{oy}{!;jRP z+paY#oOwe_KWfZRRz8NF6HRbr8pnVgyZPuH7SIASoo*2g|+_bP0l+XkKtY}0P literal 1043 zcmV+u1nm2XP)Px#24YJ`L;(K){{a7>y{D4^000SaNLh0L01ejw01ejxLMWSf00007bV*G`2jK}1 z2{JkP8~0WK00WarL_t(|+U=arYEwZJ#=mnXxv@~VrnnXaK~T`v76j3S8}SK(ZRySz zaN$h?;zES>#)U87P7)rn0#~R zH#3(x_sj%P{Z<43ci%S03WfgpP^Nn)@>@?Xl-k2(>HBBrqCqqs!r$fGm)fO;jp4Gp zADa_}ul+N@`mmS(^yF%3HwOUmc<-#U(Q+vBxM$}9G=A)rdFmou3(|lyZvb5Xsm)t1 zqI$4CjQ1`A_z>wL`n?p;ACxu{E7+YE}d&U2Aj!Bwi2C=qz2F?@0X1tBnqmclEB=f4S*k2D-%b9i)I1kOERb z3P=H|6p#W^K*tuWvKh4ZV=IXg--=9FOxGHz#GHYmx_93 z%9JhcKc1d@Ib4>uo<9Y6GSFkUYLl~fhD+|PG;Wc>qhLE|Yi}=2FKp%jfb%p4i|JtI z5shXPn9l*B+Th)T+GOTnec(Ke=|1SNp$33O5X(XhCP|)a2PDgjfvE!Er2i`9iqJm+ zQ1t>tHkV~HC23x)>Kl&{Bg>}dGl_qBwLwf+^sL^kO$z;&n+cmiRYMJp#T1YNQa}nw z0VyDr0#ZN<=(vJaHiL57stbcvQC_T^w(2ahXOsoileASY%lu_|u_^>7CJ&*L!suVF zK>oVKe3lsXd6x}VLYX?tqiJ8F4S>hOv_KmpZ8~mKz&=oa^sA*xrBeNE5%B$ctTX+a z!FHcE|1O&;{gC`mTlE_u4=>av=U)$(m6w~Ro#|f**oRlyOsV^Q9~AdalZ~3eu$u!e z)G<9I1iDbi7`adfW3LgyU8qB>7wQflY5;Hmq(|_iC%QWSn16E6#`#xyv57KDz^I|(1YG^E`fE17dQa}nw0jU&_0#ZQ76|9o6#mahJ z1kYLjyqF^tE9-Sp@M$fIf<#mz^@p_y`vP*{E!d;WixH4IOR4ZTkPR5MWxrruV)_m` zs&`QDOT1Yq^k+hu?w!bOjShvq6Y@{qelF|9=4Ih)z&`B8n>sx_^bJaGLBl(S2%i7| N002ovPDHLkV1h5L-CFL_t&-8Fi374gpaVh0ncjLZZ@1 z?1^c`0#p(SDiPimB-Wsk$mA6gL#L&)1Enp@JLZ`%2&X&eyMMWWo3-#mYG_89*#0-u zjO;=%P-my_P#z|kG*qi8JX0Urah|aNfo^Qw7;Fh#{29Fx1XAd1%@8h!w)>w@00000NkvXXu0mjf=`30f delta 226 zcmV<803HAJ0saAyB!2;OQb$4nuFf3k0002ENkl+> zx*XGYh96Ok4FB^J&&{eqmShBRB2UZ~=U`>n&G?^j_dJu75}?q3umnglVSm2>BOlLp zpvct)o1Uh@B|wtCXJ&GVFfwfhGT*R(1W*7Y!#_p_Mn)!>AX~^NQAXxHKzp9d+w>#? ztOH~@6Dz~6{|x{3&Nogg0x4#SI5$~}la=8J!+(Y~FhP(63nv4|vi}T>6X%21my#e7k?HA1^@s6^f-MQ00004XF*Lt006O%3;baP0004;NklOTWk+2=m; z;YhF70V1c-6MqCS#*gWML3`XwEm+e{o%(kX)g{v$Fld*%6*^YgyL6@-z3Ts>IS?-P zP%EBWcUAY&)uBHfu%XdAi|=nk*I`hHe)t(MSv@#;SIA_&&zM4X`R_pdaCm5Mps&3Z zUCU_l1_t={N#fHQkZO&O6U=;quo3&n%s0Y0ZPef+Yf&5nROJOEELlPX@@Y=By04vA zv};~BMktbv0xnx2EqrxTR)>3W;3gng+D+S-T7k?NC1^@s6&N3Wo00001b5ch_0Itp)=>Px$zez+vR5%fxl0Pg% zaS+Gve(zV7PBtSe6OF+lNDN)NNFe3Fn?kuyR<>aoYF)@=lR!CV6S&7?+OSMG}qfbN}upf%|vjWFM_`=AW+y` zYX!q|%AHzx{W~SjzgS&h^d`{;%5!B`2fBGHLXRsTOB)(5EA!L&+e@i`uY2P8TR_gr z7do>qBxijp_~k+}`WL`{ID{ik_VSY3{BVQL8wjA~<8hcs0|`=`>?)0F2N55uH6uC_ z@v)9(xKNFbq_7Qya*0KjLR=jDK=W=&mADSyCRg}B&xvJ1E1K?%@<{HcK~aPku`NSNsD<&8#B~(?D$i0000C~ zoUs=fR4xMxB54y+i?kr9Tr@Q{_jK-^?#$Qtnwh$b?|k>%bANtw?|IyB05g=5R{q07 zVptW+_2MWI!u#V*ugw)n-VG<;AjkADQA%%E|A+;kLnAG^Sjff^KOdwZ! zV#o`rJ(y)-Q3C>rFdds`OG7xcM|n zn@R`d%DhreWwBWoLTnHPD58p@Fz$}c2}>T$Pdw4}Gxmb&Ih)s=nqhmr!c})Lc+!@O z(>po)Xl^Agg&bC$Tw}))YQnSFGzGCwO(%5xvKYwP%72h*=R7w19LHjy8thb`oh~hq zG3K3};+T*+7gx re!ym2R^Lqd!4zf#500000NkvXXu0mjf_X>#m delta 799 zcmV+)1K|9(2B`*+7k?xO1^@s6gzakQ00001b5ch_0Itp)=>Px%<4Ht8R7ef2mS0HI zQ546|xtrF)eDEcUUh=8%%}oijvOuz+dQs>>b2GP3lw8SvSq;Gjphp!{JaCiBY>94wrJmpyg@{0Q({CY6=ZqioDQDL2PR}vo@C+o z6bx-bz;kCba4A=q7_9NkK{9@v2<8njVvztGc18NVxxkESg{nK}6O^nYpt+P71s}DK zcXlgV7^Vj{e}C*R+q;`ybH-}4T>?D_SGjNN^=9K5kP2#^d{k0WTKobLPn#l1eW90& z*TLtLrfuD114#MLPW0|7FSk8Kz>7Mbk3BLgWn0AIO=w&Cm=UA`>L-2HiqeB2Kxj1u z1h4)qFEu}_?TVSU)ybwH?RP~2y@=w57V^$M#N)9G!+%F_E@_(@w*wimu9^P(DBzAM zB#OjHHjX&FzqBnYkP7Bkp-X^xsD(iEWo3D#VW{@nqOxTTQo-%h!7C)t&+nK;tqEWu zLD2BT-tjdjkP^G5gH2$;VHOq}FoGXRpffpx3|J(xS&^*{ngU<$tUzmMVYZn5vjMURKF=MuYdb zN8Q!=V916S(rP+0Ptdp`faVq9<4i3lV&_M)y&^kuY4d3#8;0-~f0dEHv`Z3`jp1r{&Jd*+QpyH(Z-A1g2CJ^B-4*ccz#pvw dei(hN^dI+Y8h4)rsx1Hj002ovPDHLkV1ib^gkJyv diff --git a/Riot/Assets/Images.xcassets/Room/members_list_icon.imageset/members_list_icon.png b/Riot/Assets/Images.xcassets/Room/members_list_icon.imageset/members_list_icon.png index eb23ecd65356ab66a084764be7f1b6ec66ea9dd1..8522a9c34c4d07a70d4c18db5fe37de494398ba4 100644 GIT binary patch literal 448 zcmV;x0YCnUP)5nrzb}MA6rA^VFHVIV?Cg@s&kY3$9W?SxA6nwk5V%fz@AlC@e{9** z#`ac(&=rgLx0hjr;}H@}%oP#fAyQ}5UOM1dur{7TCesbo6J(S7ue!gYMRRi#{q%Vs z_lyE|k`}0I01S!0!x_B3T_d-6XEn$mtxg-&PF5B)g&Bw$rRN9kvusspHQ0I>J4uN( z>;22NYO2x09YlWbut3F?55@8=k%*w8nwvPYcuC#*G!99A784jquK11PS6EHU7_F}I zRCj50K=+bWb_~Om1dZ)XYG{BCL7kfaIRJ^XyqtMh)5xX@WiI)xQMwTm}IPV q0jHlChIl2_p~(1;w@QcA2?FnP&VPkqlmIvY0000JHvVa literal 1083 zcmeAS@N?(olHy`uVBq!ia0vp^{2!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8X6a5n0T@z%2~Ij105p zNH8!kp3V%3D2ed(u}aR*)k{ptPfFFR$SnY>W?-j zfNYSkzLEl1NlCV?QiN}Sf^&XRs)DJWiJpOy9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0 zuU}qXu2*iXmtT~wZ)j<0sc&GUZ)BtkRH0j3nOBlnp_^B%3^4>|j!SBBa#3bMNoIbY z0?6FNr2NtnTO}osMQ{LdXGvxn!lt}psJDO~)CbAv8|oS8W77uoEZlu4x+)S2Aez9w zf>>q)GRn%oC^Hr4T#%#e3~j*1qlh6KX9G0d%DE^tu_V7JBtJjL&Jh&W3ZA)%>8U}f zi7Ayf`sga4nr-w!-bM00By7Q=z`(WR0_ucClpWV5<+_i+Xuaj>;uxYK+8ew#Tf|YM zK0odIB<71T$}^UHI?!)Y<*3sXv1F5|rBcLGzb%_Q1iM2t-@IXYD0FVOy+e0HZ$e=z z2bW+n$HNZJi5iZcK^_zS&UpU*>`p_C<>tFLzd!rF_HWufoj@}ei{R?1a~TwmDMwyd zb7oekRASXU#p5Y68K%n`%KyCF{B82SWWE34ffvHp?OPu|eadsek81)~*{##Nemdue zk)@rA*y5QoYA-a8*S*l6JzdMYQ7U0)ga+R{`yW3leWvHUv6y&AP5JkUd{JYC&g+T? zHPyCrW}FP)_q|NdM`MRrz$T;mr~k}L-=&slJ^!3;(UqsNGJcy@zEryJd`*?iDQzNh zPdgW~PRpIOnpB)w^tGbJw@I6Pp>|x;M4Rrg`sO&YT_XY*n{TStgWCU_N$1 zToM1SQ-MQfCj~zbJKI@aROJ2a~rStNZZ!&EmJGzRXkk*XnmI quY9-nwEgeQzI~n@H+_Nq!}+^DExyBJ6a5vGMLk{pT-G@yGywpbke2ZP diff --git a/Riot/Assets/Images.xcassets/Room/members_list_icon.imageset/members_list_icon@2x.png b/Riot/Assets/Images.xcassets/Room/members_list_icon.imageset/members_list_icon@2x.png index 8eb7a46cab521a45cded7699aa4b1fc4c178cbbe..c697bde87c46214b383b1bd7b5865d020a5cec74 100644 GIT binary patch delta 893 zcmV-@1A_d54TlGi7k?NC1^@s6?P*QF00004XF*Lt006O%3;baP0009%NklcFlo&+BLKN{^#28|tYd)Kux!#$#vo86-uK76d-rhTN=YO1eckX9_`GaK2J}Wxr z5?Gy!7#Grumdh3k*u}&V$;~shNF-|U3S$VvT-neiZt%nrX-~L4AaoFD6NCHBc;*J$ zul{yesW5@+Tz!eSf6a6S!yo{%Q_$~5&~``L#R_>M(o|Tf2xmcb%(^5GQX`5-Q~b6i|zc&>J9fQP_s7KCpdcXi?BFvEDKu^h$nX7LGQT^@pzZq%|^Mo zN1FIFj)ZTVeP7rFjonTrNf438{m>PREAmwlsGkiJ`+QKpJ z3vWqkG>Q)zB>W$mfbaWb>44MX>XS|<7DtrfYC=pyTs@rmna9iLpGUX9-N`*lsTQqg z(<>QV#gwZm`v8do>~6S4idu)bxj_m@j}(yZLVt&nS`JLb|M_&&I+rgXu6X#$Wfcly zNJ?iqVdFedIB0fCbc^#HSta%>74LL1!$!S7w3}M=B^^T6YPbqRCe?W!ZI>rRcTFPt z+Eln+gl!fe-z4fKTf`tTChPHv(!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBD8X6a5n0T@z%2~Ij105p zNH8!kp3V%3D2ed(u}aR*)k{ptPfFFR$SnY>W?-j zfNYSkzLEl1NlCV?QiN}Sf^&XRs)DJWiJpOy9hZWFf=y9MnpKdC8&o@xXRDM^Qc_^0 zuU}qXu2*iXmtT~wZ)j<0sc&GUZ)BtkRH0j3nOBlnp_^B%3^4>|j!SBBa#3bMNoIbY z0?6FNr2NtnTO}osMQ{LdXGvxn!lt}psJDO~)CbAv8|oS8W77uoEZlu4x+)S2Aez9w zf>>q)GRn%oC^Hr4T#%#e3~j*1qlh6KX9G0d%DE^tu_V7JBtJjL&Jh&W3ZA)%>8U}f zi7Ayf`sga4nr-w!-bM00By7Q=z`(WR0_ucClpWV5<+_i+WTNQl;uzw=`!>usBPLYD z?)kad)6e*%IUQ@8A+$KROJr4~#|M5bk(Q+CPP;UxnylpA@nVsJ(?W?iP6ex*W|`<7 z3*Ee7(E~Salcr0{4lZKU6xvuiam(e-$tU;B{C=sqAa! zxfi+o?~&A=`*APFqba%VLOMR%TI+wAW=AE;1PQG<{qgS3$wzj2$w#?aurAe6`jTB_ zzT!ktQMB5_wbuSpQ@xzyjpkN4PHvdib=Yr7{ry7UrZOweb6#;Ob1i1ec14=*et2h| zvUYO#^18q{0~MW#8qc{b0}eW!@UU;Z_I~QsN844FYJOxc+P>}XoSviv&cOoI{^ zW$h2~ymYE&&F;;+0$tXtiBA_0pZLkon?LWu2TsO~`oFuF<0VCp-p`A9b?atz>+{u5 zGN&t=RQam4>TWRial7vXDbyw=TsJd{AT0My85#dJ9B=C?tgSn@ciyG zFO=SGy?xvM!IA}gmOWA0IZY~v^Tn1gPnUjmx8|F8BKMex?n$X-Vheey_ukjZIK_GX zjpZ!)SPSFFVsq>otEw&I|IBjwyHhala@D!=J=ZJOX)rab1fG_JT|cs=jylSMOxc`pVn*SRehXvDCv>96_a>ylrX zYA4*g`hQZ(16`~89lvr~9#aP`6YpEp%-Z2KXw;f3OZqd z&)R>C@4~~&>@Qv#pYWfbm1J7_!d^(a@g(0qZ)y4JtB*}Co&B;qvv-&I%ZHbCMK}0* f$?Mr1;P}J)nCGBQp)z4*}Q$iB}mtwf7 diff --git a/Riot/Assets/Images.xcassets/Room/members_list_icon.imageset/members_list_icon@3x.png b/Riot/Assets/Images.xcassets/Room/members_list_icon.imageset/members_list_icon@3x.png index ec24ed814d286277f7f5ce9f9361527a1c75fadb..b5af8cb0a95d13f0c162ae83b708312d7c549779 100644 GIT binary patch literal 1222 zcmV;%1UdVOP)^93yE`T=@FZ6$cEI){uYEjaAw#g1huFj>P;^YiSbT%)Gt(a4e=Ut%#~~U!B7%Iv zRG$^Rgp~T4vIrcw8Q4v)9wV^BJj6<3{bme3Dp`aLrjYHN^{}fqt+fo$Rh_qM7m@p+ zbyrJ1FeA`|8EfqWoO1_B9;UTyBLm{tqeXWHT}pXKE!6{?yQ!3}QE4`*m3T|9l0bC%wt=fV)+68bqDCwsTk&974?*5`(WK$!~4ZPvrsyJegk|BY|#3bj1M zNsqb&!kDx69G_?S7qyX#1TjO}J55wM|fdvE?XG1`%mj55c9*FW>{Pe|}1MpIP zyvmHDU=Gioz7bE|i#`HZe1YWfU|u2pvM4;w$PTQL^CqaAy@SHGogs?jLpq!Kgkk#_ zW4oj2rA30AH1+y>c>dIMDBE_1D87+JT8}VC9NXtW0uN6N$g3$F@)F8{Ne4}Duy72A+1!`DnlSQuS7W}Xlr^c>|194&96#8x)e2q@^bCY+bZ@M@(y!}J#QM-iM!s`y}cUcrDW<)oMEHGWIY$_+F^Mv zhP5O6)x_br)opOv4n=waVnc#qeK28@NqHvMH^nJ4`xxxye(Q>V0lge;r zZB^2m-T1&&B|k@1NmMeW>itUm59zgs$q-%`<$_04${REXahet{hgKahJvyv<@TyoD zLB^IhjwYdjS=6GfWF8I9V4`rrgJTHMEHY&;J(f-+;vUwV?pxt3w@2VEjSBV$IkEaM zi^3y3$mUkUU?pr>s%iNQ?eJJIk|8pZXHxZIpP+5L-3;(dCrmT6711B zRjecK-R5{4_ji|3cfU3|6Qozf!@_(uXz!g>T1wn<8$;NuFu{^j6}E^WD&or&50fXj zE&2KiY_J?L#Or6Om^|^5ba(tfx{AJA9TJfxx_AOLb1gy^{@w$IaHY@)cIym|GL}XN k>c7AEx1Aw&*#AoY0ew**IFcXtmH+?%07*qoM6N<$g1@jzIsgCw literal 1988 zcmZuy2{;s58y@@CAWK_wrldH3MXJ3k{ zkB`uch$2$3R6SyZ=C>e!#If*?xJbr_QSc-pNDvo`BVD4P!C*n6KgWKZgs?vo5hM0l z@%cfi*f1y@0)zfPCkj5`uk!xGOK|ed?JKKq$x!^(AkE4CSPF^kMk0k8pA+;BWJ|yX z`n&jJ{i0CN|3>^(DM}C$d7g~-=W`V>GKQm||6|+7qo4x1f204cw_mON<{C@$GyQQ< z#?m^FJ~RLzmTPNq&J82Agt5zVvs7YKZZAZ>s*3TwB@_T^PE=8X=W1&;Ws9+}|G18W zStuZOg<|H1I%hQRimNCprX)d9k27K|6grbsVAp9KDBq{ei(~fdOEDx3b`!c`DL_1- zz-n@Ql*?#(f2VTm!)gVuNVlu76dzwER(L4Li=Ly`_Ak*-%SjE$1DYz2OYKf6+*Ti7 z*?Cz+*~4#w2Xwwm``pX1<)(^g;ne|e5||-n&T6si@v}d9<-hcqK@N z83qnrx)G!?NS%>ch@rEi6Vkqv4W>Oqi?p#y3_Z~98WT-Qc>!kXy5SMRvwFbj{62Ae zoX?}m8knZ_(-+!760dH(gRR%)WHUt($`@qbh{g4% zjbQFoKc-E~b_p{qLl9q-U1Fy>_fiVW_Il{54K+THp9xKK3U89($^w(sg8=w?+s@|%>T6Q{`(l5m= zCzY=xV>>%c?r>lGY-?WSNDVkEi#wGwd&T92rgy^L4<7XA@BzC#(lybW_2A$|`Q+cs z7!!4-4%b@jt$l2Z&1T|>Dpm%TOTVt54G9<@1hFnxRQizwNuIW2>W6qQ7RXDcJ;i zyeIb6on!YmN=Puf4Q9Q%m=x}-st;;pXPRX3uBXj*?hoXn2^TFe1qH)1jY1hbXEyJ* z7JJ#Eh7%5)jayGP)K;h2kVQY_B2!jZFs&Y580##bV-KG)v9_oYq{J|6H}Jf zrV#>n+Y1?u!eI*FdM?4Pt#0fZwTjj8jh6Z0-Rg`Z<#DvVis+me?bY8Cbxt=kLeA*3 z+~-m*-$2r*OI7#NUaT1SMYWUj14qZo zJ;CwC_MMNRnPg29U@;ZDF;Y4lXRRwCe=HC2GtQz9hDdbXGBB63k)UB5 zIg@P$x@=>hrQB-0Uv5@#qlzDk`2(7d6h`}ok9r(;W)m3KVm7)`ZZ4Z#rN^iTXM z%!UiuRn5BI3K33Tb)2ofRiy5p{9?oOkP0)k`O*VeQCG>@6&N^vq^??#C8K#~{L%E& zmgkmJF|iV3%b(DPnoSZ&i$*e)a;8jMD5<4*DeiXY(4gY^aY7Kq33aQ9 z^m~21RZYEAzo}oMwdh;pIdzA3s)+~6hfu&J%;OwAtbWFSXn)*a+J}O=iXb?zpl}(? zd(q9exbN8Jf5qqG(0+JoQgF7R;9XFFKMJC+VC;a`ImL&|Tb4^=z)9T@thE5m;rGIr zqUqXO)Eg&-ds{v_xEt(E2+1Z8-hdkw zn!fwNu4h^9FMl7DJYJKt>*eN8;QOOATl=ohNQjz^?$=%kYehDE61x+m#<^J9YS+_j z7PvkW66gWVRA0tOGIC< zuf+qq5c8xHlWqxz)zSuB<0X1viA>_*O-W^Jl%4M|Pk+Pc2zpGN>r&L!Quoi=gxYhi z%_Ptpxo>C}I@C=e*&xIBa;G&iyISm=DaD!U4;L`nZ%d#LaB;8~@NP@5#{dvL$FGGE zUFT82=r}P4(MP>IROO6 zm!e&%1b?a8vPA7lOme%=Uq?BwcEvo%1Fi}3YF7(E9&OR!w#B}9EszoI3PWTPnnPPG zxNEbt%Xko0OAc*ufo(tLiKAU)9%%iB=F}Donq-r-OPSZ-)_DV!Ea6H5b>~dt>y44{ zJL%>tO8>Qxns_V^^eJ&QQ@C8Pv_8$=c@6f5Wg7h%e7g7-uku{7Sd<-<00000NkvXX Hu0mjfojOP$ delta 494 zcmVDGCpbBXRv)IKno{j=()Hkq-32b8_r2Ps)`hagm+=gz@EON&H1~X=*Ork1 z88VF*`RU;;=0e*4*WRjQ)sNs%Ykl~S_2_^+(Di&Q?`QB6Q+VE}&yEG?aMEPEv4>?Qn!?9B}&~=3W-v;l)5YO54y8kO5GKW`X$bHbxWbUwkj-R kGr!VU;jIeK;58l|0L34}`!IbKiU0rr07*qoM6N<$f|AbW6#xJL diff --git a/Riot/Assets/Images.xcassets/Settings/remove_icon_pink.imageset/remove_icon_pink@2x.png b/Riot/Assets/Images.xcassets/Settings/remove_icon_pink.imageset/remove_icon_pink@2x.png index 4824feb84bffab60ee90d59b155f93af3add1d29..0735dff9d3ee47441968ca47af5f26176e5118d4 100644 GIT binary patch delta 1688 zcmV;J250%h38)Q_B!2{FK}|sb0I`n?{9y$E00v)4L_t(&1>1R)C1q|p$N5HJE!5tJZ8U_odgh@d7a5;Piuz_#K~$`ZhYg!sst zz5@>kMg+0tukDWC%!TCZp5{N`LqUCKeZ~>C;E}1OBHQZtz2B=FUTCA)!mDD^PNls_4lP@K^jP|FOat zc;0%9d|ShrR}EPfDaUaaYFzwZBXgA{#JKtyEK{G`s$3m1gH*f@#cb zQ^RlmAP1y8+-UjMve?EPq!K1huU7f!W zTz?Q;Bb|auRSmdqMibZXe8PI33j}s=f*n>e?O0e(uqy?r9Os+n*07~qLBHBwD|kJo zCJnen2y!$qY8B7K@|emQ?63*OodxP^(L3Gw9B{u{CMHbv9|o zjk|kkpNA-WH0=<)iAicnwFJ=Yd~z&sr@$rtI8wIcDOC*4vz|UfpEMhH`cAMAJFWKcuwohdlcE6XH;chXB z*_ktadY(qF!~*DrZ33v?=NVWS(S!|t0dRxTyo@lP&wrm}=bgX}odGx4mF7&Sp6#sf z<1ctU4ez?`e3=5iivo_N0bWm;ihl+yHflo032)RE+V;z?EhyzW-S1YM=s21dcs+M2 z8t_3DTSw8yPw?x}n^p$E@tE9}i8d#zr6z!JmD=0b16u)=Ip8ZW2@Aq5wnE3cno<$K z1gVznhb31T99ltlEZB{v(Qbl_TvjRA)rGv&Ik5mXJ*dFj06eggqfkeg#Vw%U`yp6MKKVqlMJJqd$dU+cs zz)+f)J^ zZ%e{Em1&?9q*CK;;$W-Q8{wTI8ZbMbGH+82aQs;#ypu10P0Z5gZQ>vYtJljr83Bfp zw;2p@rRVkVPW)1@Ki>}>Z&L|it!*~gRp*^N^WOvg`96GU#!P<=ynp$Z|1~iDc)0G3 zCVEL4Lmen%0Kt5U44^ile!lkkXMr8Bk>uN9K4m5(ozf80&tjpDMqW>aA6X!ec=}%- z%jIABtSOw%U5!=BZj@7dT8(V7O>YIB%4A@^;B iC=Wf7lQa45{{Vw}cM$|i8LmA500007Wu2iWq_zTcC{823jD3bboBEhJaeM3qz1rSNse9 z4W*hurH}~r&OI*f896!LDfiCYL+38%oO|x`zR&x0o)G{;=~*ztz%=N2VdNiL>@fgz ztp_~?RDu1%SAU8He+<|H%mXJtE(?_hEe5^=^eFHepuhxB7DM+G@SL;%K5!DW(h5vi z@Ebq}fS0_bNq+@?2V9`5fZY&x8cM5L0Q@@Z`7Pe^AHWR-=>x|8+n+pZfkR+A4LesX zvFFP+Y?e98bHHJUCRC`*gA4-~fd?KFdm-LoD6L!~&zFIhz2zC87vd>lJeG$qmDYm! z5ZD2TmlOS<7avDXIG*nVUiX%7Cy^0d6~<#cpfw{t0)MswuGjAX=RhxnG{S;!2OR=7 zdtoyJ90PMz7>#N_s(XM?xdSo?e3z0FJrKVYHYd8)fgS-~@W9^&$`JkRg8v@_9uqx4 zr^m!y;5_IT!pK4Z&z}J{0#7*0H-S&V{3482{dYC(K+D7saK&R{4X_8|Hw`5ClUK=(p_*>TV(~E(BBm*839{}%p6yFDi@>VCOR1VsN z#RK01(Qm@IdDK~&<%5=qGj@Pl@S5E&h__{Jc7IOT)MDNr4~}OApP2!NiKoEqwM_WU zZV+^IF($n6;1zFq&U$`2EBMR|I84;Wj!P+H#~z5c*BbyG&-Vi_ddoL~BT2$$2cMgP zls-{PVd68;Z(JrE&)4R8e>^ytl*;iqFBWaY0H;rUo5I9?h)cDca4sVQDPc47uu0_y z-+wRzDYMh|6ef;>UV`Xpo3L-Bc>ZuQ9yA8NX#>0|_8o8Rm;^bSd<<;!&a8UCYt^O~qMw@ae4z$7C3YXs1=Q=#vq{**Q^Huai0^7q1~?^lvd)&j zfX^YiUKIF34M?g@bv3ZQ&XzWy16C|6@_z=Q#ewhYu+?T`ooy@a0Qh#1cWfyLe41_p za1U6WQeq3!owNY(^>mwApbz*yr0ygIc)lNaHKkM@fap3bf6`W`cT<=c0R6fdCbUV< zXV7iJ>Q2&x=QHUxp>-!|0DLapCbaI9GlcT%HlcMV$?5srx=m=^DI)`o>o%cvCw~d8 z+l1DgG_-CLT6dDrx=m=^Nki*4p>-z-t=ojwoiwy=6IyqY(7H`%-AP01HlcMVG0ETe z!E~F@x|0~XF9VxG={A9Nr?YAsh%1EPsm0-w?+K1m|R^a-Q){skiGL&^hs$dCX4 N002ovPDHLkV1o4@9Txxq diff --git a/Riot/Assets/Images.xcassets/Settings/remove_icon_pink.imageset/remove_icon_pink@3x.png b/Riot/Assets/Images.xcassets/Settings/remove_icon_pink.imageset/remove_icon_pink@3x.png index 71cd00734caa05f3ecaa315da6611e0b33f06fb6..bf2ba6f6c1fd7ba23a0aafd1ad4aa9becbac1ac2 100644 GIT binary patch delta 940 zcmV;d15^B~2EqrBB!2{FK}|sb0I`n?{9y$E00VhRL_t(|0p;93kJB&|0Py!xB>o5? zvGEC55I4d{0A1NAa03g1`37{%=)`(rI4gm2L-N5{3zQ3zFHR#+*O5ZtYy|2mQYaiNpspc>#IXkI3Q}mC zRzRsEap1HDN)?F<#|bDkBu*S>pj42!alC+HBT3+R1AoOrlEMiBB#k7A6AVZSNg5|8 z5I0f`oZvuQNU?BOfI=h1#9;#pg%lfy704GU1srxDSEN*MM1a~Nfx7%qFL@v8mCc0} z7rM{6G=%xO)wyddhfR$L`asJirC<7?H&VeN05KqXm=zLLT%W|=9Mc3*AbO|=k~j{v zR~*O@DSrx1G@u#@j`e(ViOw6+iJp-6DUhI{4qH(fg2#6ErW^OvjxN5~RHZCKyb1lY zYa8n^RfsdhC}48)r@ZcR#LydYAj?02HI6xogd_^&j1v(_Y!0%+!7r(W1Bw9I;eh^> z!?V<4CfSFWJ^p#fRpn0{Iz0e&rL&n_K` zGBrQ^FV7N(`iQ5)Z_Ufx_y;EAH?uj2_UzJoca@t8)k4|g)LmS+%w6IH@z*@Z0DsoF(rZ2ju>f%1n*!xeok+WX~RE`KSzx;#V1w( O00006z305G14GO{)f?am^ zvbQ@Q{ZZXrvZre@`Av7tq`P4j%Hv8I9w_xY<^FjJ3uRa<^+XvBmfK~H1CxD_`Nc1A z>Xz{QTPZjoPi7uRAbY}#LjYNWLrF--aOUwJNtEHi8k{1KPQY0~s(|Yo?r|A@zsa#C zZNUMkK(AH69e>cDB_TDy0T{!Ny;+eS?gFnt&TdG^V!E}!c_@tk$WmhVNNsUA-Z5vS zE;y{~oFh_K98OBe38@bbo04)s>Wjmc#H5j2;A{m-70DG&BcRlfT;enaN(IR^PAeem zNIq~{16f7#h0_Vh8j??(&Ola>eB<;2ij5Qkr#Db6q<>I2PJluqg~V|N6bdOcj#D7t zNHK7n1NlOVh2sUtHBw9*Z$Pe)V&ixP>WgFn$2(A0Br7;UfZ8I#uNziyf&sNa`U+gM zf)f;|1rk9#mgkt7kEXh@YU9C>f;IACRHwtmDK+k`!=aB1tMZv5+JsoES)w8ct{=Nf9R`lB9|g z3Q1DN34tW39B9B_OhNiI0PkR&G@A4rlLj(=+;$q~mTlH`ix3Q2Otae*YcI*tZP{Y<&JLt&u|ca{2+a_{PL`(Mp5-P7S% S-wi7O0000jRrz|f){?{|L0(@;VD2JC(&+ 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 rb_ZBZi!yws@S<AWE7B3YEx<0ImeI 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 Ef=qi-761SM literal 4035 zcmV;!4?OURP)Px^eMv+?RCodHT>EoX#U0<>bCVDtm#A12!6x_s#aAFad|(BiQ~kl(n$D=TkO#g- zr*`@W=H`7(gi}QajZ4k9LE&fWIWl!drYqqBjoi` z$w>+{mR5*2SvT6(m;q#Ba;lr(zVcSDs#>-;*!iXHE04y6evoCP4c3ije$1wrG-iCJ zqrIXllXsaw*#KHsKT7GC0W?be8@8A+0qF5vZ4=!qJxmWs%Qj(XN1Eoe)}V*C{NcP< zN$MJ@%@i!A$74G6>5J8m?8~Rzlbc_Te_Px$TS_xKne3V-@rnw2f%cqJr;h)ouD$u7 zF>)8=?S{PL`P$d+Y@H!eW~MSau08d2swcMdr3Jq{ny*c^y6{@|wO-o(;yll&JEfEZ zz%{=4V0zcV)s2fAQ$ay>+nX=d!YqQIA1al7z@~cD^Q-1BI~;7cbnD6sVnzDVV42Hn zt%VZa=SJvtEpzKXbLC7M*EGfsluf$_=EHTta$`)&m-_WpRm$EW`s&*8EluV5ZJz13P>w?0^wFCQ8p zj+~hA?sm*zyBrdp*s8U;1bScP%6+Zv6ZMq3)Ri&C6V!Mc?FS&c;wKZ>Li{??7UJoR zzb#FSkIw>Nv#}<@0v`xgR=GxgWR%_~d@&z3)rC%*FD=4PirFvS!0l`ppIGPSOCR^8Cod5}0{zIIPbnd;Juv?u0b zgnC(|zv;-r<0>F`z7#CmZ zz_9}HXD~>ZF9wVF4$t^&3oWRQN7QurwihP((z_X(+c}tf{e205<9HIJ_^HG)Hb z-osQ|Wr65{{kHo=exRm>3}y;E<(P_-Q(e!1G@HXv;?VsOH)Vdf`(4in`|^^qO5gJ z-Iw6o4A~XU3mQ6d$>>%73=i)=URcW#x#)uBp+*qx9M^~ovYk$@U{Knp;HZHU5O4B< zW0#4*%fu9^OrHWghGatlgrU682=hUvH5TN2AZ6&zk_>fqYbaG>Us|sT=VJ;55SdOt zc5pTA9Omuy9RX>`%L9F2UtBi|rJ(_$@kb+YFi1r-#$ z{w&K_-JqjW3wGIj_QBnUNh1LyCW`9=*7O%G*Vca&M#xywP)AIyFQ|jn9es$RPbfQx z3}Lm7PZ?3|n0uc8p34s>1>d5iS6l&8;yf)q>+?~@Kao=lSrqu@R z>7SB>eL)fmpxoL8ggv%y#W_UZGKb@-^sDYq0@b0jbXmkNOFU$h;aZlF4F?$BjC!lk z`fd9|9($|I+mf_w!?xrRT3~>%>z`@%j2s&i&Tji8l0K(IShb|3~7XF@m40F|ST488gaOetw6YK5P>iYG$ z=vj_+hrs=@c3aC$=-92$KoTVKLiy{YiE>eQPsA)h={^+($So^YPM;%cp*_?KoLj*I zJQ>5%I;K)W{T_#W$D%041sNmZaW}1^x;-h2Ai*_8V61l%BX332g&T*Fj%FSdbqazFFrMV`z@xv0CdtZknHeYAZ>-%E;1AGcWaF}46P1Vwq~Cp-tw zClKf7pXaO3R)^73gvDc~tBYx!v20yg*mOW!@N8VOCgc*)FQHH$hyf!`hzVO+0X9BI zN^61>VN8eBB5?HU*pL7A)Crdln_44K=(PQWH&dePYL>Z>-Jq(y�fD0yLJl@gO@OHEqg{;3=Sj+AvY%pEo2&j zyx_&_w3%W2u{=C!-KBW>pBt6cip5XxA!mEghwHaD;jJd`BF{7?qTOoFqg^M+g`l|m z;ihi;Kt4EC%`ASW%QwhF`iLJI!7JEzhe`U;j-ZhLH&zxP9Oxxo$1sFTTz(`{~0N-e~B`ZvDs4VkCKD%p*Nvflv}LMxo7 z{)cuUFAU)dro*|&!x?XB-qE<>tvV^Gi-&Aiu;ZVom0aki6fq%Z3sC%Id{3e{aVuAE z5R_xH@=#2{-W_zMM2vowra{GdZ|Sn&t{i-e@jIW}hdv8AZ@X-jYzwXI0*y3Tajc>v z8(qFK=u#8&^hHByU%GHgIq_8WlF ziveVXks_tk?b#^{mkwwPo{fta4~Qfw#Gz03srl%Lf#>_LL2v6XvH-CGk3l9ROIE-L z-vAF>Cn77qazBK&^pFO`(l7F6FdyZjKZn5!Yy(4VhTU65VE|gY)j(S|BQNrd$U;ze z_QCRCp8|bkpRonn2)@q&oQ$8{jjFt|>fdj=1zV6?ED<6mn&;I1HE)9~mGI}>NtXqy zfK=aRHCz}SVtPtW}ZBFkXNoYxyr51(B0L?lBxba zxxy@Is1d|=%XTz9hGXX`mWS4_HqUL?nT228A{*lae~#T41}Nz;gR$MArLu;k4V%-V z5)o+w0t^UnygShrHMWSNU?pDzi~c_5eN3&Da~hswzR(qF1d)l<>O;p2R%W%!M@iYS z#NPPJoFZ;bV*4}@YQ8cUDfppeeh?hevJKmw4mgw%)H&D}*5$iG12iF3vXjA3WCnM` z#f&}7$2eCVJ%L<5=+D6$<3mJ-_2!~w9cf6*Hc`EZjxTkk&b((I*cVqoaXZ${`MtEY`7ioqh5GZ&{_32tTRPP5wpiWSiRGGDU4=P;V;VCRXWv(^s(vIh^}-4b(pftx?XuV# zEFY;nb)>GAA4eqm5QTT>DMqHPHzCGQiLFjROvUbaa_=)Ex_5KDM%-B#^-S|lrF6vC(qiPZfAjTmVrF!oT#w!PX zC{cxErdpZ~-tVmVCqn&*E zhnkO4>C0*P@WNuZYh`tAa2OMak5?wc@%F~)oT24YHdh@F1eMlzAQIx6T%(#G;pq81 ztVOfQC*3EpKNn9|9u6R3COLp`e4B9vI3_N20h1h-()gESqq)gH$J?-~a#F<*(%a(@P z>cH;#l%gYe9nxolE&XX2IsN8%huG`(oYd#Vq~AGh!EZ>!0;m(Ajj#TE;C2cKet5 zQq0CcnTfdPq9EZAnSt*$&iKbHR3z-@Pylal%%s}TnJW;@aWjVg!zrdb89|ECI>|y`HR;+N;FJa}|R@At_FRzri8jT7dp>O2%q}Z(6uVc6q+q z$B_d)GJdBK{~XHc9OZ*L+orKmHQZZqg|GcZ3|ex02B%TKIAnY5@(+8;Ti5jW&W}Z7 zqqXd5-yA5PMt>7tD%mf9_GU{}{f6wdLrX(Vv0$^DpJXDupAqc2;*je%H%-wobtQsm zuEfGOz!4S}AfRvraYegTO7Cu7*zi?QFPA4spO;^BHx}fKSz_xjYE#PK&3Xnu$#hDb z&PTnjEz`P<&F7j@`7nSg=Y1i70L(GjZC+}*p&n;!;Vym>YEp70wi|Jg5=T=0>3!7O zzxs!hYpMFa)LRpw$pBJzw0=iZ4~&rk<+*OKzVtNT&=49N^5HkENcbDp6;8upiTG|e z{vMzL&u`2Cf)o9u(~aliE}uye(B$$#T30q&>1nM&BcU8@moKp)sU$CalzR`3Wi~ti z4WlgJTfd$G&Ab>~X)|N+XUqU9?J3=Ye^r6cy2UsQV+2g7yQDJ}QRwUsoI;%HLFDNe zU}Hs&*%af+0?xr-f#EhJ%*KHM&%p`ddu_q6Tvs<*se4ePC2xovZan>%H&gcZ|C2Wc pFJYT<=xq2WZ$lLRzF;5%{{vxk=Q|EYPuTzf002ovPDHLkV1fWV!l(cM From e9af0e3975119c2ac55b95e918c3824a29864cfc Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 15 Feb 2019 15:21:33 +0100 Subject: [PATCH 226/244] BF: Reskin: Sometimes the roomVC navigation bar is tranparent #2252 --- CHANGES.rst | 2 ++ Riot/AppDelegate.m | 2 +- Riot/Modules/Room/RoomViewController.m | 21 ++++++++++++++++++++- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 95e90e606..f76806ea6 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -28,6 +28,8 @@ Bug fix: * Share extension: Handle rich item sharing (image + text + URL) (#2224). * Share extension: Sharing pages from Firefox only shares their title (#2163). * Share extension: Fix unloaded theme (PR #2235). + * Reskin: Jump to first unread message doesn't show up in 0.7.12 TF (#2218). + * Reskin: Sometimes the roomVC navigation bar is tranparent (#2252). Changes in 0.7.11 (2019-01-08) =============================================== diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 7f67cc7b0..0254103ac 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -447,7 +447,7 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN UINavigationController *secondNavController = self.secondaryNavigationController; if (secondNavController) { - secondNavController.navigationBar.barTintColor = ThemeService.shared.theme.backgroundColor; + [ThemeService.shared.theme applyStyleOnNavigationBar:secondNavController.navigationBar]; secondNavController.topViewController.view.backgroundColor = ThemeService.shared.theme.backgroundColor; } diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 48a97ecb5..3b7a6d701 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -418,9 +418,26 @@ - (void)userInterfaceThemeDidChange { + // Consider the main navigation controller if the current view controller is embedded inside a split view controller. + UINavigationController *mainNavigationController = self.navigationController; + if (self.splitViewController.isCollapsed && self.splitViewController.viewControllers.count) + { + mainNavigationController = self.splitViewController.viewControllers.firstObject; + } + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; - self.navigationController.navigationBar.translucent = YES; + if (mainNavigationController) + { + [ThemeService.shared.theme applyStyleOnNavigationBar:mainNavigationController.navigationBar]; + } + // Keep navigation bar transparent in some cases + if (!self.expandedHeaderContainer.hidden || !self.previewHeaderContainer.hidden) + { + self.navigationController.navigationBar.translucent = YES; + mainNavigationController.navigationBar.translucent = YES; + } + self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor; // Prepare jump to last unread banner @@ -1524,6 +1541,7 @@ [mainNavigationController.navigationBar setShadowImage:shadowImage]; [mainNavigationController.navigationBar setBackgroundImage:shadowImage forBarMetrics:UIBarMetricsDefault]; mainNavigationController.navigationBar.translucent = isVisible; + self.navigationController.navigationBar.translucent = isVisible; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ @@ -1615,6 +1633,7 @@ mainNavigationController = self.splitViewController.viewControllers.firstObject; } mainNavigationController.navigationBar.translucent = isVisible; + self.navigationController.navigationBar.translucent = isVisible; // Finalize preview header display according to the screen orientation [self refreshPreviewHeader:UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])]; From 532927661d072f4800a0e61d94cb5559152b2b34 Mon Sep 17 00:00:00 2001 From: Fridtjof Mund Date: Thu, 14 Feb 2019 20:22:44 +0000 Subject: [PATCH 227/244] Translated using Weblate (German) Currently translated at 85.5% (520 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index a7ce4c0e7..59f8b8b5e 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -543,7 +543,7 @@ "room_replacement_information" = "Dieser Raum wurde ersetzt und ist nicht länger aktiv."; "room_replacement_link" = "Die Konversation wird hier fortgesetzt."; "room_predecessor_information" = "Dieser Raum ist die Fortsetzung einer anderen Konversation."; -"room_predecessor_link" = "Klicke hier um ältere Nachrichten zu sehen."; +"room_predecessor_link" = "Tippe hier um ältere Nachrichten zu sehen."; "settings_labs_room_members_lazy_loading" = "Raummitglieder verzögert laden"; "settings_labs_room_members_lazy_loading_error_message" = "Dein Heimserver unterstützt das verzögerte Laden von Raummitgliedern noch nicht. Versuche es später erneut."; "room_event_action_view_decrypted_source" = "Zeige entschlüsselten Quellcode"; From 2c729783a7af433f7eba7f1215c3bcb1d90812ed Mon Sep 17 00:00:00 2001 From: sergio Date: Thu, 14 Feb 2019 21:18:18 +0000 Subject: [PATCH 228/244] Translated using Weblate (Russian) Currently translated at 100.0% (608 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index ef2186500..ea431613e 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -559,12 +559,12 @@ "homeserver_connection_lost" = "Невозможно соединиться с этим сервером."; "auth_accept_policies" = "Пожалуйста ознакомьтесь и подтвердите согласие с политикой этого сервера:"; "settings_key_backup_info_checking" = "Проверка ..."; -"settings_key_backup_info_none" = "Ваши ключи не копируются с этого устройства."; +"settings_key_backup_info_none" = "Ваши ключи не сохраняются с этого устройства."; "settings_key_backup" = "РЕЗЕРВНАЯ КОПИЯ КЛЮЧЕЙ"; "settings_key_backup_info_version" = "Версия ключа резервного копирования: %@"; "settings_key_backup_info_algorithm" = "Алгоритм: %@"; -"settings_key_backup_info_valid" = "Это устройство делает резервное копирование ваших ключей."; -"settings_key_backup_info_not_valid" = "Это устройство не делает резервного копирования ваших ключей."; +"settings_key_backup_info_valid" = "Это устройство делает резервное копирование ключей."; +"settings_key_backup_info_not_valid" = "Это устройство не делает резервного копирования ключей."; "settings_key_backup_info_progress" = "Резервное копирование ключей %@..."; "settings_key_backup_info_progress_done" = "Все ключи сохранены"; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Для Безопасного Восстановления Сообщений на этом устройстве, проверьте %@."; From 6caec35e728dac7af620f2ef0314551dc49f00fa Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 15 Feb 2019 17:29:48 +0100 Subject: [PATCH 229/244] Key backup: new recover method detected #2230 --- CHANGES.rst | 1 + Riot/AppDelegate.m | 65 ++++++++++++++++++++++++++++- Riot/Assets/en.lproj/Vector.strings | 6 +++ Riot/Generated/Strings.swift | 16 +++++++ 4 files changed, 86 insertions(+), 2 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index f76806ea6..b27f5b2fb 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -15,6 +15,7 @@ Improvements: * Key backup: Implement recover reminder (#2206). * Key backup: Update key backup setup UI and UX (PR #2243). * Key backup: Logout warning (#2245). + * Key backup: new recover method detected (#2230). Bug fix: * Use white scroll bar on dark themes (#2158). diff --git a/Riot/AppDelegate.m b/Riot/AppDelegate.m index 0254103ac..df6253dc8 100644 --- a/Riot/AppDelegate.m +++ b/Riot/AppDelegate.m @@ -200,7 +200,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN Prompt to ask the user to log in again. */ UIAlertController *cryptoDataCorruptedAlert; - + + /** + Prompt to warn the user about a new backup on the homeserver. + */ + UIAlertController *wrongBackupVersionAlert; + /** The launch animation container view */ @@ -518,6 +523,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN [cryptoDataCorruptedAlert dismissViewControllerAnimated:NO completion:nil]; cryptoDataCorruptedAlert = nil; } + + if (wrongBackupVersionAlert) + { + [wrongBackupVersionAlert dismissViewControllerAnimated:NO completion:nil]; + wrongBackupVersionAlert = nil; + } } - (void)applicationDidEnterBackground:(UIApplication *)application @@ -650,7 +661,10 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN // Observe crypto data storage corruption [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onSessionCryptoDidCorruptData:) name:kMXSessionCryptoDidCorruptDataNotification object:nil]; - + + // Observe wrong backup version + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyBackupStateDidChangeNotification:) name:kMXKeyBackupDidStateChangeNotification object:nil]; + // Resume all existing matrix sessions NSArray *mxAccounts = [MXKAccountManager sharedManager].activeAccounts; for (MXKAccount *account in mxAccounts) @@ -789,6 +803,12 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN NSLog(@"[AppDelegate] restoreInitialDisplay: keep visible log in again"); [self showNotificationAlert:cryptoDataCorruptedAlert]; } + else if (wrongBackupVersionAlert) + { + NSLog(@"[AppDelegate] restoreInitialDisplay: keep visible wrongBackupVersionAlert"); + [self showNotificationAlert:wrongBackupVersionAlert]; + + } // Check whether an error notification is pending else if (_errorNotification) { @@ -982,6 +1002,47 @@ NSString *const kAppDelegateNetworkStatusDidChangeNotification = @"kAppDelegateN } } +- (void)keyBackupStateDidChangeNotification:(NSNotification *)notification +{ + MXKeyBackup *keyBackup = notification.object; + + if (keyBackup.state == MXKeyBackupStateWrongBackUpVersion) + { + if (wrongBackupVersionAlert) + { + [wrongBackupVersionAlert dismissViewControllerAnimated:NO completion:nil]; + } + + wrongBackupVersionAlert = [UIAlertController + alertControllerWithTitle:NSLocalizedStringFromTable(@"e2e_key_backup_wrong_version_title", @"Vector", nil) + + message:NSLocalizedStringFromTable(@"e2e_key_backup_wrong_version", @"Vector", nil) + + preferredStyle:UIAlertControllerStyleAlert]; + + MXWeakify(self); + [wrongBackupVersionAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"e2e_key_backup_wrong_version_button_settings"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + MXStrongifyAndReturnIfNil(self); + self->wrongBackupVersionAlert = nil; + + // TODO: Open settings + }]]; + + [wrongBackupVersionAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"e2e_key_backup_wrong_version_button_wasme"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) + { + MXStrongifyAndReturnIfNil(self); + self->wrongBackupVersionAlert = nil; + }]]; + + [self showNotificationAlert:wrongBackupVersionAlert]; + } +} + #pragma mark - (void)popToHomeViewControllerAnimated:(BOOL)animated completion:(void (^)(void))completion diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 595271704..3143201a0 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -600,6 +600,12 @@ "e2e_enabling_on_app_update" = "Riot now supports end-to-end encryption but you need to log in again to enable it.\n\nYou can do it now or later from the application settings."; "e2e_need_log_in_again" = "You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver.\nThis is a once off; sorry for the inconvenience."; +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "New Key Backup"; +"e2e_key_backup_wrong_version" = "A new secure message key backup has been detected.\n\nIf this wasn’t you, set a new passphrase in Settings."; +"e2e_key_backup_wrong_version_button_settings" = "Settings"; +"e2e_key_backup_wrong_version_button_wasme" = "It was me"; + // Bug report "bug_report_title" = "Bug Report"; "bug_report_description" = "Please describe the bug. What did you do? What did you expect to happen? What actually happened?"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 52a895922..934c135f9 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -478,6 +478,22 @@ internal enum VectorL10n { internal static var e2eEnablingOnAppUpdate: String { return VectorL10n.tr("Vector", "e2e_enabling_on_app_update") } + /// A new secure message key backup has been detected.\n\nIf this wasn’t you, set a new passphrase in Settings. + internal static var e2eKeyBackupWrongVersion: String { + return VectorL10n.tr("Vector", "e2e_key_backup_wrong_version") + } + /// Settings + internal static var e2eKeyBackupWrongVersionButtonSettings: String { + return VectorL10n.tr("Vector", "e2e_key_backup_wrong_version_button_settings") + } + /// It was me + internal static var e2eKeyBackupWrongVersionButtonWasme: String { + return VectorL10n.tr("Vector", "e2e_key_backup_wrong_version_button_wasme") + } + /// New Key Backup + internal static var e2eKeyBackupWrongVersionTitle: String { + return VectorL10n.tr("Vector", "e2e_key_backup_wrong_version_title") + } /// You need to log back in to generate end-to-end encryption keys for this device and submit the public key to your homeserver.\nThis is a once off; sorry for the inconvenience. internal static var e2eNeedLogInAgain: String { return VectorL10n.tr("Vector", "e2e_need_log_in_again") From 016e8258e6c874500b4e7606a288597d55fa915c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 15 Feb 2019 19:03:20 +0100 Subject: [PATCH 230/244] Add keybackup setup intro manual export strings --- Riot/Assets/en.lproj/Vector.strings | 2 ++ Riot/Generated/Strings.swift | 8 ++++++++ 2 files changed, 10 insertions(+) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 595271704..36009d116 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -683,6 +683,8 @@ "key_backup_setup_intro_info" = "Messages in encrypted rooms are secured with end-to-end encryption. Only you and the recipient(s) have the keys to read these messages.\n\nSecurely back up your keys to avoid losing them."; "key_backup_setup_intro_setup_action_without_existing_backup" = "Start using Key Backup"; "key_backup_setup_intro_setup_action_with_existing_backup" = "Use Key Backup"; +"key_backup_setup_intro_manual_export_info" = "(Advanced)"; +"key_backup_setup_intro_manual_export_action" = "Manually export keys"; // Passphrase diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 52a895922..a08c37753 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -758,6 +758,14 @@ internal enum VectorL10n { internal static var keyBackupSetupIntroInfo: String { return VectorL10n.tr("Vector", "key_backup_setup_intro_info") } + /// Manually export keys + internal static var keyBackupSetupIntroManualExportAction: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_manual_export_action") + } + /// (Advanced) + internal static var keyBackupSetupIntroManualExportInfo: String { + return VectorL10n.tr("Vector", "key_backup_setup_intro_manual_export_info") + } /// Use Key Backup internal static var keyBackupSetupIntroSetupActionWithExistingBackup: String { return VectorL10n.tr("Vector", "key_backup_setup_intro_setup_action_with_existing_backup") From b9d7f78d3144860585b1a7b01edbaabca4a3ab87 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 15 Feb 2019 19:04:03 +0100 Subject: [PATCH 231/244] Create encryption keys export presenter --- Riot.xcodeproj/project.pbxproj | 12 ++ .../EncryptionKeysExportPresenter.swift | 147 ++++++++++++++++++ 2 files changed, 159 insertions(+) create mode 100644 Riot/Modules/KeyBackup/ManualExport/EncryptionKeysExportPresenter.swift diff --git a/Riot.xcodeproj/project.pbxproj b/Riot.xcodeproj/project.pbxproj index 7c1a36f6f..6ed5783ba 100644 --- a/Riot.xcodeproj/project.pbxproj +++ b/Riot.xcodeproj/project.pbxproj @@ -373,6 +373,7 @@ B1CA3A2721EF6914000D1D89 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2621EF6913000D1D89 /* UIViewController.swift */; }; B1CA3A2921EF692B000D1D89 /* UIView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CA3A2821EF692B000D1D89 /* UIView.swift */; }; B1CE9EFD22148703000FAE6A /* SignOutAlertPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CE9EFC22148703000FAE6A /* SignOutAlertPresenter.swift */; }; + B1CE9F062216FB09000FAE6A /* EncryptionKeysExportPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1CE9F052216FB09000FAE6A /* EncryptionKeysExportPresenter.swift */; }; B1D250D82118AA0A000F4E93 /* RoomPredecessorBubbleCell.m in Sources */ = {isa = PBXBuildFile; fileRef = B1D250D72118AA0A000F4E93 /* RoomPredecessorBubbleCell.m */; }; B1D4752721EE4E630067973F /* KeyboardAvoider.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752521EE4E620067973F /* KeyboardAvoider.swift */; }; B1D4752821EE4E630067973F /* KeyboardNotification.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1D4752621EE4E620067973F /* KeyboardNotification.swift */; }; @@ -1026,6 +1027,7 @@ B1CA3A2621EF6913000D1D89 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = ""; }; B1CA3A2821EF692B000D1D89 /* UIView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIView.swift; sourceTree = ""; }; B1CE9EFC22148703000FAE6A /* SignOutAlertPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignOutAlertPresenter.swift; sourceTree = ""; }; + B1CE9F052216FB09000FAE6A /* EncryptionKeysExportPresenter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = EncryptionKeysExportPresenter.swift; sourceTree = ""; }; B1D250D62118AA0A000F4E93 /* RoomPredecessorBubbleCell.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RoomPredecessorBubbleCell.h; sourceTree = ""; }; B1D250D72118AA0A000F4E93 /* RoomPredecessorBubbleCell.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RoomPredecessorBubbleCell.m; sourceTree = ""; }; B1D4752521EE4E620067973F /* KeyboardAvoider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardAvoider.swift; sourceTree = ""; }; @@ -1255,6 +1257,7 @@ B1098C0221ECFEAF000DDA48 /* Setup */, B1FDF56421F726AD00BA3834 /* Recover */, B1107ECB2201BE800038014B /* Banners */, + B1CE9F042216FB09000FAE6A /* ManualExport */, ); path = KeyBackup; sourceTree = ""; @@ -2707,6 +2710,14 @@ path = SignOut; sourceTree = ""; }; + B1CE9F042216FB09000FAE6A /* ManualExport */ = { + isa = PBXGroup; + children = ( + B1CE9F052216FB09000FAE6A /* EncryptionKeysExportPresenter.swift */, + ); + path = ManualExport; + sourceTree = ""; + }; B1D4752421EE4E620067973F /* KeyboardAvoiding */ = { isa = PBXGroup; children = ( @@ -3434,6 +3445,7 @@ B1B5574820EE6C4D00210D55 /* PeopleViewController.m in Sources */, B1B5598720EFC3E000210D55 /* Widget.m in Sources */, B1B557E320EF60B900210D55 /* MessagesSearchResultAttachmentBubbleCell.m in Sources */, + B1CE9F062216FB09000FAE6A /* EncryptionKeysExportPresenter.swift in Sources */, B1B5574420EE6C4D00210D55 /* CallViewController.m in Sources */, B1B5572220EE6C4D00210D55 /* RoomSettingsViewController.m in Sources */, B1B5577320EE702800210D55 /* JitsiViewController.m in Sources */, diff --git a/Riot/Modules/KeyBackup/ManualExport/EncryptionKeysExportPresenter.swift b/Riot/Modules/KeyBackup/ManualExport/EncryptionKeysExportPresenter.swift new file mode 100644 index 000000000..1020b0564 --- /dev/null +++ b/Riot/Modules/KeyBackup/ManualExport/EncryptionKeysExportPresenter.swift @@ -0,0 +1,147 @@ +/* + Copyright 2019 New Vector 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 Foundation + +final class EncryptionKeysExportPresenter: NSObject { + + // MARK: - Constants + + private enum Constants { + static let keyExportFileName = "riot-keys.txt" + } + + // MARK: - Properties + + // MARK: Private + + private let session: MXSession + private let activityViewPresenter: ActivityIndicatorPresenterType + private let keyExportFileURL: URL + + private weak var presentingViewController: UIViewController? + private weak var sourceView: UIView? + private var encryptionKeysExportView: MXKEncryptionKeysExportView? + private var documentInteractionController: UIDocumentInteractionController? + + // MARK: Public + + // MARK: - Setup + + init(session: MXSession) { + self.session = session + self.activityViewPresenter = ActivityIndicatorPresenter() + self.keyExportFileURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent(Constants.keyExportFileName) + super.init() + } + + deinit { + self.deleteKeyExportFile() + } + + // MARK: - Public + + func present(from viewController: UIViewController, sourceView: UIView?) { + self.presentingViewController = viewController + self.sourceView = sourceView + + let keysExportView: MXKEncryptionKeysExportView = MXKEncryptionKeysExportView(matrixSession: self.session) + + // Make sure the file is empty + self.deleteKeyExportFile() + + keysExportView.show(in: viewController, + toExportKeysToFile: self.keyExportFileURL, + onLoading: { [weak self] (loading) in + + guard let sself = self else { + return + } + + if loading { + sself.activityViewPresenter.removeCurrentActivityIndicator(animated: false) + sself.activityViewPresenter.presentActivityIndicator(on: viewController.view, animated: true) + } else { + sself.activityViewPresenter.removeCurrentActivityIndicator(animated: true) + } + }, onComplete: { [weak self] (success) in + guard let sself = self else { + return + } + + guard success else { + sself.encryptionKeysExportView = nil + return + } + + sself.presentInteractionDocumentController() + }) + + self.encryptionKeysExportView = keysExportView + } + + // MARK: - Private + + private func presentInteractionDocumentController() { + + let sourceRect: CGRect + + guard let presentingView = self.presentingViewController?.view else { + self.encryptionKeysExportView = nil + return + } + + if let sourceView = self.sourceView { + sourceRect = sourceView.convert(sourceView.bounds, to: presentingView) + } else { + sourceRect = presentingView.bounds + } + + let documentInteractionController = UIDocumentInteractionController(url: self.keyExportFileURL) + documentInteractionController.delegate = self + + if documentInteractionController.presentOptionsMenu(from: sourceRect, in: presentingView, animated: true) { + self.documentInteractionController = documentInteractionController + } else { + self.encryptionKeysExportView = nil + self.deleteKeyExportFile() + } + } + + @objc private func deleteKeyExportFile() { + + let fileManager = FileManager.default + + if fileManager.fileExists(atPath: self.keyExportFileURL.path) { + try? fileManager.removeItem(atPath: self.keyExportFileURL.path) + } + } +} + +// MARK: - UIDocumentInteractionControllerDelegate +extension EncryptionKeysExportPresenter: UIDocumentInteractionControllerDelegate { + + // Note: This method is not called in all cases (see http://stackoverflow.com/a/21867096). + func documentInteractionController(_ controller: UIDocumentInteractionController, didEndSendingToApplication application: String?) { + self.deleteKeyExportFile() + self.documentInteractionController = nil + } + + func documentInteractionControllerDidDismissOptionsMenu(_ controller: UIDocumentInteractionController) { + self.encryptionKeysExportView = nil + self.documentInteractionController = nil + } +} From dc470aac67ca0beed5065b352369a68797974fdd Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 15 Feb 2019 19:04:54 +0100 Subject: [PATCH 232/244] Handle manual export in key backup setup intro screen --- ...yBackupSetupIntroViewController.storyboard | 110 +++++++++++++----- .../KeyBackupSetupIntroViewController.swift | 24 +++- 2 files changed, 102 insertions(+), 32 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard index 8cf1b867c..ddd5f89c3 100644 --- a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.storyboard @@ -22,10 +22,10 @@ - + - + @@ -35,16 +35,16 @@ - + - - + + - + + - + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - + - + - - - + + + + - @@ -133,6 +178,9 @@ Securely back up your keys to avoid losing them. + + + diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift index 7f2d0616b..8963b5af8 100644 --- a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift @@ -34,10 +34,19 @@ final class KeyBackupSetupIntroViewController: UIViewController { @IBOutlet private weak var setUpButtonBackgroundView: UIView! @IBOutlet private weak var setUpButton: UIButton! + @IBOutlet private weak var manualExportContainerView: UIView! + @IBOutlet private weak var manualExportInfoLabel: UILabel! + @IBOutlet private weak var manualExportButton: UIButton! + // MARK: Private private var theme: Theme! private var isABackupAlreadyExists: Bool = false + private var encryptionKeysExportPresenter: EncryptionKeysExportPresenter? + + private var showManualExport: Bool { + return self.encryptionKeysExportPresenter != nil + } // MARK: Public @@ -45,10 +54,11 @@ final class KeyBackupSetupIntroViewController: UIViewController { // MARK: - Setup - class func instantiate(isABackupAlreadyExists: Bool) -> KeyBackupSetupIntroViewController { + class func instantiate(isABackupAlreadyExists: Bool, encryptionKeysExportPresenter: EncryptionKeysExportPresenter?) -> KeyBackupSetupIntroViewController { let viewController = StoryboardScene.KeyBackupSetupIntroViewController.initialScene.instantiate() viewController.theme = ThemeService.shared().theme viewController.isABackupAlreadyExists = isABackupAlreadyExists + viewController.encryptionKeysExportPresenter = encryptionKeysExportPresenter return viewController } @@ -88,6 +98,11 @@ final class KeyBackupSetupIntroViewController: UIViewController { let setupTitle = self.isABackupAlreadyExists ? VectorL10n.keyBackupSetupIntroSetupActionWithExistingBackup : VectorL10n.keyBackupSetupIntroSetupActionWithoutExistingBackup self.setUpButton.setTitle(setupTitle, for: .normal) + + self.manualExportInfoLabel.text = VectorL10n.keyBackupSetupIntroManualExportInfo + + self.manualExportContainerView.isHidden = !self.showManualExport + self.manualExportButton.setTitle(VectorL10n.keyBackupSetupIntroManualExportAction, for: .normal) } private func update(theme: Theme) { @@ -106,6 +121,9 @@ final class KeyBackupSetupIntroViewController: UIViewController { self.setUpButtonBackgroundView.backgroundColor = theme.backgroundColor theme.applyStyle(onButton: self.setUpButton) + + self.manualExportInfoLabel.textColor = theme.textPrimaryColor + theme.applyStyle(onButton: self.manualExportButton) } private func registerThemeServiceDidChangeThemeNotification() { @@ -136,4 +154,8 @@ final class KeyBackupSetupIntroViewController: UIViewController { @IBAction private func validateButtonAction(_ sender: Any) { self.delegate?.keyBackupSetupIntroViewControllerDidTapSetupAction(self) } + + @IBAction private func manualExportButtonAction(_ sender: Any) { + self.encryptionKeysExportPresenter?.present(from: self, sourceView: self.manualExportButton) + } } From b7670532ee7e2d3ff078ead3ab484d69512d7cb8 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 15 Feb 2019 19:06:08 +0100 Subject: [PATCH 233/244] Update KeyBackupSetupCoordinator to handle coming from sign out info --- .../Setup/KeyBackupSetupCoordinator.swift | 33 ++++++++++++++++--- ...ackupSetupCoordinatorBridgePresenter.swift | 7 +++- .../Modules/Settings/SettingsViewController.m | 13 +++++--- 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift index 8c07dd39c..e5dd5561b 100644 --- a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinator.swift @@ -25,6 +25,7 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { private let navigationRouter: NavigationRouterType private let session: MXSession + private let isStartedFromSignOut: Bool // MARK: Public @@ -34,19 +35,18 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { // MARK: - Setup - init(session: MXSession) { + init(session: MXSession, isStartedFromSignOut: Bool) { self.navigationRouter = NavigationRouter(navigationController: RiotNavigationController()) self.session = session + self.isStartedFromSignOut = isStartedFromSignOut } // MARK: - Public methods func start() { - - // Set key backup setup intro as root controller - let isABackupAlreadyExists = !(self.session.crypto.backup?.state == MXKeyBackupStateDisabled) - let keyBackupSetupIntroViewController = KeyBackupSetupIntroViewController.instantiate(isABackupAlreadyExists: isABackupAlreadyExists) + // Set key backup setup intro as root controller + let keyBackupSetupIntroViewController = self.createSetupIntroViewController() keyBackupSetupIntroViewController.delegate = self self.navigationRouter.setRootModule(keyBackupSetupIntroViewController) } @@ -57,6 +57,29 @@ final class KeyBackupSetupCoordinator: KeyBackupSetupCoordinatorType { // MARK: - Private methods + private func createSetupIntroViewController() -> KeyBackupSetupIntroViewController { + + let backupState = self.session.crypto.backup?.state ?? MXKeyBackupStateUnknown + let isABackupAlreadyExists: Bool + + switch backupState { + case MXKeyBackupStateUnknown, MXKeyBackupStateDisabled, MXKeyBackupStateCheckingBackUpOnHomeserver: + isABackupAlreadyExists = false + default: + isABackupAlreadyExists = true + } + + let encryptionKeysExportPresenter: EncryptionKeysExportPresenter? + + if self.isStartedFromSignOut { + encryptionKeysExportPresenter = EncryptionKeysExportPresenter(session: self.session) + } else { + encryptionKeysExportPresenter = nil + } + + return KeyBackupSetupIntroViewController.instantiate(isABackupAlreadyExists: isABackupAlreadyExists, encryptionKeysExportPresenter: encryptionKeysExportPresenter) + } + private func showSetupPassphrase(animated: Bool) { let keyBackupSetupPassphraseCoordinator = KeyBackupSetupPassphraseCoordinator(session: self.session) keyBackupSetupPassphraseCoordinator.delegate = self diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift index 6a0fdb48e..06c0b7856 100644 --- a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorBridgePresenter.swift @@ -46,8 +46,13 @@ final class KeyBackupSetupCoordinatorBridgePresenter: NSObject { // MARK: - Public + // NOTE: Default value feature is not compatible with Objective-C. func present(from viewController: UIViewController, animated: Bool) { - let keyBackupSetupCoordinator = KeyBackupSetupCoordinator(session: self.session) + self.present(from: viewController, isStartedFromSignOut: false, animated: animated) + } + + func present(from viewController: UIViewController, isStartedFromSignOut: Bool, animated: Bool) { + let keyBackupSetupCoordinator = KeyBackupSetupCoordinator(session: self.session, isStartedFromSignOut: isStartedFromSignOut) keyBackupSetupCoordinator.delegate = self viewController.present(keyBackupSetupCoordinator.toPresentable(), animated: animated, completion: nil) keyBackupSetupCoordinator.start() diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 769fbad20..7df4871e3 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -4286,7 +4286,7 @@ SignOutAlertPresenterDelegate> - (void)settingsKeyBackupTableViewSectionShowKeyBackupSetup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection { - [self showKeyBackupSetup]; + [self showKeyBackupSetupFromSignOutFlow:NO]; } - (void)settingsKeyBackup:(SettingsKeyBackupTableViewSection *)settingsKeyBackupTableViewSection showKeyBackupRecover:(MXKeyBackupVersion *)keyBackupVersion @@ -4405,11 +4405,14 @@ SignOutAlertPresenterDelegate> #pragma mark - KeyBackupRecoverCoordinatorBridgePresenter -- (void)showKeyBackupSetup +- (void)showKeyBackupSetupFromSignOutFlow:(BOOL)showFromSignOutFlow { keyBackupSetupCoordinatorBridgePresenter = [[KeyBackupSetupCoordinatorBridgePresenter alloc] initWithSession:self.mainSession]; - - [keyBackupSetupCoordinatorBridgePresenter presentFrom:self animated:true]; + + [keyBackupSetupCoordinatorBridgePresenter presentFrom:self + isStartedFromSignOut:showFromSignOutFlow + animated:true]; + keyBackupSetupCoordinatorBridgePresenter.delegate = self; } @@ -4449,7 +4452,7 @@ SignOutAlertPresenterDelegate> - (void)signOutAlertPresenterDidTapBackupAction:(SignOutAlertPresenter * _Nonnull)presenter { - [self showKeyBackupSetup]; + [self showKeyBackupSetupFromSignOutFlow:YES]; } - (void)signOutAlertPresenterDidTapSignOutAction:(SignOutAlertPresenter * _Nonnull)presenter From 1d1f60e2be7462216b0f30788e2cdd06f77a853b Mon Sep 17 00:00:00 2001 From: Osoitz Date: Fri, 15 Feb 2019 15:54:59 +0000 Subject: [PATCH 234/244] Translated using Weblate (Basque) Currently translated at 98.1% (597 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/eu/ --- Riot/Assets/eu.lproj/Vector.strings | 77 +++++++++++++++++++++++++++-- 1 file changed, 72 insertions(+), 5 deletions(-) diff --git a/Riot/Assets/eu.lproj/Vector.strings b/Riot/Assets/eu.lproj/Vector.strings index abfccc664..f30779b9f 100644 --- a/Riot/Assets/eu.lproj/Vector.strings +++ b/Riot/Assets/eu.lproj/Vector.strings @@ -545,7 +545,7 @@ "room_replacement_information" = "Gela hau ordeztu da eta ez dago aktibo jada."; "room_replacement_link" = "Elkarrizketak hemen darrai."; "room_predecessor_information" = "Gela hau aurreko elkarrizketa baten jarraipena da."; -"room_predecessor_link" = "Egin klik hemen mezu zaharrak ikusteko."; +"room_predecessor_link" = "Sakatu hemen mezu zaharrak ikusteko."; "settings_labs_room_members_lazy_loading" = "Gelako kideen karga alferra"; "settings_labs_room_members_lazy_loading_error_message" = "Zure hasiera zerbitzariak ez du onartzen gelako kideen karga alferra. Saiatu geroago."; "room_event_action_view_decrypted_source" = "Ikusi deszifratutako iturria"; @@ -559,9 +559,9 @@ "room_resource_usage_limit_reached_message_2" = "erabiltzaile batzuk ezin izango dute saioa hasi."; "room_resource_usage_limit_reached_message_contact_3" = " muga hau areagotzeko."; "auth_accept_policies" = "Irakurri eta onartu hasiera-zerbitzariaren baldintzak:"; -"settings_key_backup" = "MEZU SEGURUEN BERRESKURATZEA"; +"settings_key_backup" = "GAKOEN BABES-KOPIA"; "settings_key_backup_info_checking" = "Egiaztatzen..."; -"settings_key_backup_info_none" = "Ez da ezarri mezu seguruen berreskuratzea."; +"settings_key_backup_info_none" = "Ez da zure gakoen babes-kopia egiten gailu honetatik."; "settings_key_backup_info_version" = "Gakoen babes-kopiaren bertsioa: %@"; "settings_key_backup_info_algorithm" = "Algoritmoa: %@"; "settings_key_backup_button_restore" = "Berrezarri babes-kopia"; @@ -570,5 +570,72 @@ "settings_key_backup_delete_confirmation_prompt_title" = "Ezabatu babes-kopia"; "settings_key_backup_info_progress" = "%@ gakoen babes-kopia egiten..."; "settings_key_backup_info_progress_done" = "Gako guztien babes-kopia egin da"; -"settings_key_backup_info_valid" = "Mezu seguruen berreskuratzea ongi ezarri da gailu honetan."; -"settings_key_backup_info_not_valid" = "Mezu seguruen berreskuratzea ez dago aktibo gailu honetan."; +"settings_key_backup_info_valid" = "Gailu honek zure gakoen babes-kopia egiten du."; +"settings_key_backup_info_not_valid" = "Gailu honek ez du zure gakoen babes kopia egiten."; +"settings_key_backup_button_create" = "Hasi 'Gakoen babes-kopia' erabiltzen"; +"settings_key_backup_button_use" = "Erabili gakoen babes-kopia"; +"key_backup_setup_passphrase_title" = "Babestu zure babeskopia pasaesaldi batekin"; +"key_backup_setup_passphrase_info" = "Zure gakoen kopia zifratu bat gordeko dugu gure zerbitzarian. Babestu babes-kopia hori pasaesaldi batekin seguru gorde dadin.\n\nSegurtasun hobe baterako, pasaesaldi hau eta zure ohiko pasahitza desberdinak izatea komeni da."; +"key_backup_setup_passphrase_passphrase_title" = "Sartu"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Idatzi pasaesaldia"; +"key_backup_setup_passphrase_passphrase_valid" = "Ongi!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Gehitu hitzen bat"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Baieztatu"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Baieztatu pasaesaldia"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Ongi!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Pasaesaldiak ez datoz bat"; +"key_backup_setup_passphrase_set_passphrase_action" = "Ezarri pasaesaldia"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Edo babestu zure babes-kopia berreskuratze gako batekin, eta beste nonbait gorde."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Aurreratua) Ezarri berreskuratze gakoa"; +"key_backup_setup_success_title" = "Ongi!"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Zure gakoen babes-kopia egiten ari da.\n\nZure berreskuratze gakoa badaezpadakoa da, pasaesaldia ahaztuz gero berreskuratze gakoarekin berreskuratu ditzakezu zifratutako mezuak.\n\nGorde zure berreskuratze gakoa toki seguruan, pasahitz kudeatzaile batean esaterako (edo gordailu kutxa batean) ."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Gorde berreskuratze gakoa"; +"key_backup_setup_success_from_passphrase_done_action" = "Egina"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Zure gakoen babes-kopia egiten ari da.\n\nEgin berreskuratze gako honen kopia eta gorde toki seguruan."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Berreskuratze gakoa"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Egin kopia bat"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Kopia bat egin dut"; +"key_backup_recover_title" = "Mezu seguruak"; +"key_backup_recover_invalid_passphrase_title" = "Berreskuratze pasaesaldi okerra"; +"key_backup_recover_invalid_passphrase" = "Ezin izan da babes-kopia deszifratu pasaesaldi honekin: egiaztatu berreskuratze pasaesaldia ondo idatzi duzula."; +"key_backup_recover_invalid_recovery_key_title" = "Berreskuratze gakoak ez datoz bat"; +"key_backup_recover_invalid_recovery_key" = "Ezin izan da babes-kopia deszifratu gako honekin: egiaztatu berreskuratze gako egokia sartu duzula."; +"key_backup_recover_from_passphrase_info" = "Erabili zure berreskuratze pasaesaldia zure mezu seguruen historiala desblokeatzeko"; +"key_backup_recover_from_passphrase_passphrase_title" = "Sartu"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Idatzi pasaesaldia"; +"key_backup_recover_from_passphrase_recover_action" = "Desblokeatu historiala"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Ez duzu berreskuratze pasaesaldia gogoratzen? "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "erabili berreskuratze gakoa"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Erabili berreskuratze gakoa zure mezu seguruen historiala desblokeatzeko"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Sartu"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Sartu berreskuratze gakoa"; +"key_backup_recover_from_recovery_key_recover_action" = "Desblokeatu historiala"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Berreskuratze gakoa galdu duzu? Berri bat sortu dezakezu ezarpenetan."; +"key_backup_recover_success_info" = "Babes-kopia berrezarria!"; +"key_backup_recover_done_action" = "Egina"; +"key_backup_setup_banner_title" = "Ez galdu inoiz zure zifratutako mezuak"; +"key_backup_setup_banner_subtitle" = "Hasi 'Gakoen babes-kopia' erabiltzen"; +"key_backup_recover_banner_title" = "Ez galdu inoiz zifratutako mezuak"; +"key_backup_recover_banner_subtitle" = "Erabili Gakoen babes-kopia"; +"sign_out_existing_key_backup_alert_title" = "Ziur saioa amaitu nahi duzula?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Amaitu saioa"; +"sign_out_non_existing_key_backup_alert_title" = "Zure zifratutako mezuak atzitzeko gaitasuna galduko duzu saioa orain amaitzen baduzu"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Hasi Gakoen babes-kopia erabiltzen"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Ez ditut nire zifratutako mezuak behar"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Zifratutako mezuak galduko dituzu"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Zure zifratutako mezuak atzitzeko gaitasuna galduko duzu ez baduzu zure gakoen babes-kopia bat egiten saioa amaitu aurretik."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Amaitu saioa"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Babes-kopia"; +"sign_out_key_backup_in_progress_alert_title" = "Gakoen babes-kopia abian. Saioa orain amaitzen baduzu zure zifratutako mezuak galduko dituzu."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Ez ditut nire zifratutako mezuak behar"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Itxaron egingo dut"; +"settings_key_backup_info" = "Zifratutako mezuak muturretik muturrerako zifratzearen bidez babestuak daude. Zuk eta hartzaileak edo hartzaileek irakurri ditzakezue mezu horiek, beste inork ez."; +"settings_key_backup_info_signout_warning" = "Egin zure gakoen babes-kopia saioa amaitu aurretik galdu nahi ez badituzu."; +"settings_key_backup_info_trust_signature_unknown" = "Babes-kopiak gailu honen sinadura du, ID: %@"; +"settings_key_backup_info_trust_signature_valid" = "Babes-kopiak gailu honen baliozko sinadura bat du"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Gailuak %@ gailuaren baliozko sinadura bat du"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Babes kopiak %@ gailuaren sinadura du"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Babes-kopiak %@ gailuaren baliogabeko sinadura bat du"; From ac60b77ed590c98cb226051a910eace2103f264d Mon Sep 17 00:00:00 2001 From: Sven Thomsen Date: Fri, 15 Feb 2019 18:22:29 +0000 Subject: [PATCH 235/244] Translated using Weblate (German) Currently translated at 92.7% (564 of 608 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 44 +++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 59f8b8b5e..37c986d0a 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -557,3 +557,47 @@ "room_resource_usage_limit_reached_message_2" = "einige Benutzer nicht in der Lage sein werden, sich einzuloggen."; "room_resource_usage_limit_reached_message_contact_3" = " um dieses Limit erhöhen zu lassen."; "auth_accept_policies" = "Bitte Regeln dieses Heimservers ansehen und akzeptieren:"; +"settings_key_backup" = "SCHLÜSSEL SICHERHEITSKOPIE"; +"settings_key_backup_info" = "Verschlüsselte Nachrichten sind mit Ende-zu-Ende-Verschlüsselung gesichert. Nur du und der/die Empfänger haben die Schlüssel um diese Nachrichten zu lesen."; +"settings_key_backup_info_checking" = "Überprüfe..."; +"settings_key_backup_info_none" = "Deine Schlüssel werden von diesem Gerät nicht gesichert."; +"settings_key_backup_info_signout_warning" = "Sichere deine Schlüssel bevor du dich abmeldest, damit du sie nicht verlierst."; +"settings_key_backup_info_version" = "Schlüssel Sicherheitskopie Version: %@"; +"settings_key_backup_info_algorithm" = "Algorithmus"; +"settings_key_backup_info_valid" = "Dieses Gerät sichert deine Schlüssel."; +"settings_key_backup_info_not_valid" = "Dieses Gerät sichert deine Schlüssel nicht."; +"settings_key_backup_info_progress" = "Sichere %@ Schlüssel..."; +"settings_key_backup_info_progress_done" = "Alle Schlüssel wurden gesichert"; +"settings_key_backup_info_trust_signature_unknown" = "Sicherheitskopie hat eine Signatur vom Gerät mit der ID: %@"; +"settings_key_backup_info_trust_signature_valid" = "Sicherheitskopie hat eine gültige Signatur von diesem Gerät"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Sicherheitskopie hat eine gültige Signatur von %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Sicherheitskopie hat eine Signatur von %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Sicherungskopie hat eine ungültige Signatur von %@"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Sicherungskopie hat eine ungültige Signatur von %@"; +"settings_key_backup_button_create" = "Beginne Wiederherstellung mit Hilfe der Sicherheitskopie"; +"settings_key_backup_button_restore" = "Wiederherstellung mit Hilfe der Sicherheitskopie"; +"settings_key_backup_button_delete" = "Sicherheitskopie löschen"; +"settings_key_backup_button_use" = "Benutze Schlüssel Sicherheitskopie"; +"settings_key_backup_delete_confirmation_prompt_title" = "Sicherheitskopie löschen"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Bist du Sicher? Damit gehen alle verschlüsselten Mitteilungen verloren wenn deine Schlüssel nicht anderweitig richtig gespeichert wurden."; +"room_does_not_exist" = "%@ existiert nicht"; +"key_backup_setup_title" = "Schlüssel Sicherheitskopie"; +"key_backup_setup_skip_alert_title" = "Bist du sicher?"; +"key_backup_setup_skip_alert_message" = "Du könntest deine verschlüsselten Mitteilungen verlieren wenn du dich abmeldest oder dein Gerät verlierst."; +"key_backup_setup_skip_alert_skip_action" = "Überspringen"; +"key_backup_setup_intro_title" = "Verliere niemals verschlüsselte Nachrichten"; +"key_backup_setup_intro_info" = "Nachrichten in verschlüsselten Räumen werden durch Ende-zu-Ende-Verschlüsselung gesichert. Nur Du und der / die Empfänger haben die Schlüssel zum Lesen dieser Nachrichten.\n\nSichere deine Schlüssel sicher, um sie nicht zu verlieren."; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Beginne Schlüsselsicherung zu nutzen"; +"key_backup_setup_intro_setup_action_with_existing_backup" = "Benutze Schlüsselsicherung"; +"key_backup_setup_passphrase_title" = "Sichere dein Backup mit einer Passphrase"; +"key_backup_setup_passphrase_info" = "Wir speichern eine verschlüsselte Kopie deiner Schlüssel auf unserem Server. Schütze deine Sicherung mit einer Passphrase, um sie sicher zu halten.\n\nFür maximale Sicherheit sollte sich dies von deinem Kontopasswort unterscheiden."; +"key_backup_setup_passphrase_passphrase_title" = "Gebe"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Passphrase eingeben"; +"key_backup_setup_passphrase_passphrase_valid" = "Gut!"; +"key_backup_setup_passphrase_passphrase_invalid" = "Versuche ein Wort hinzuzufügen"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Bestätigen"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Passphrase bestätigen"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Gut!"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passphrasen müssen übereinstimmen"; +"key_backup_setup_passphrase_set_passphrase_action" = "Setze Passphrase"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Oder sichere deine Sicherung mit einem Wiederherstellungsschlüssel, und sichere sie an einem sicheren Ort."; From fd3520081c52d815d591a7d2211d4b84ee1e40b5 Mon Sep 17 00:00:00 2001 From: Sven Thomsen Date: Fri, 15 Feb 2019 18:24:15 +0000 Subject: [PATCH 236/244] Translated using Weblate (German) Currently translated at 92.0% (565 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 37c986d0a..3dcfcdd0c 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -601,3 +601,4 @@ "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passphrasen müssen übereinstimmen"; "key_backup_setup_passphrase_set_passphrase_action" = "Setze Passphrase"; "key_backup_setup_passphrase_setup_recovery_key_info" = "Oder sichere deine Sicherung mit einem Wiederherstellungsschlüssel, und sichere sie an einem sicheren Ort."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Erweitert) Mit Wiederherstellungsschlüssel einrichten"; From 2c127d097f1a406ca36659bc3f7aea1144ab6488 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 15 Feb 2019 18:34:24 +0000 Subject: [PATCH 237/244] Translated using Weblate (Russian) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index ea431613e..56281a31c 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -663,3 +663,10 @@ "sign_out_non_existing_key_backup_alert_title" = "Вы потеряете доступ к зашифрованным сообщениям если выйдете сейчас"; "key_backup_recover_invalid_passphrase" = "Невозможно расшифровать резервную копию с помощью этой парольной фразы: убедитесь, что вы ввели верную парольную фразу для восстановления."; "key_backup_recover_invalid_recovery_key" = "Невозможно расшифровать резервную копию с помощью этого ключа: убедитесь, что вы ввели верный ключ восстановления."; +"e2e_key_backup_wrong_version_button_settings" = "Настойки"; +"key_backup_setup_intro_manual_export_info" = "(Расширенный)"; +"e2e_key_backup_wrong_version_button_wasme" = "Это был я"; +"key_backup_setup_intro_manual_export_action" = "Ручной экспорт ключей"; +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Новая резервная копия ключей"; +"e2e_key_backup_wrong_version" = "Обнаружена новая резервная копия ключа безопасного сообщения.\n\nЕсли это не так, установите новую фразу-пароль в настройках."; From b548398d1412cf0974aac7abd91914391904eb51 Mon Sep 17 00:00:00 2001 From: Szimszon Date: Fri, 15 Feb 2019 18:50:01 +0000 Subject: [PATCH 238/244] Translated using Weblate (Hungarian) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/hu/ --- Riot/Assets/hu.lproj/Vector.strings | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index 0e2d505b9..7a403aa24 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -667,3 +667,10 @@ "sign_out_key_backup_in_progress_alert_title" = "Kulcsok mentése folyamatban van. Ha most kijelentkezel akkor elveszted a titkosított üzeneteidet."; "sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Nincs szükségem a titkosított üzeneteimre"; "sign_out_key_backup_in_progress_alert_cancel_action" = "Inkább várok"; +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Új Kulcs Mentés"; +"e2e_key_backup_wrong_version" = "Új biztonságos üzenet kulcs mentést észleltünk.\n\nHa ez nem te voltál akkor állíts be egy új jelmondatot a Beállításokban."; +"e2e_key_backup_wrong_version_button_settings" = "Beállítások"; +"e2e_key_backup_wrong_version_button_wasme" = "Én voltam"; +"key_backup_setup_intro_manual_export_info" = "(Haladó)"; +"key_backup_setup_intro_manual_export_action" = "Kulcsok kimentése kézzel"; From 3587bdae7492f788ec544086a4143d00851ab25c Mon Sep 17 00:00:00 2001 From: Sven Thomsen Date: Fri, 15 Feb 2019 19:32:37 +0000 Subject: [PATCH 239/244] Translated using Weblate (German) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 52 +++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 3dcfcdd0c..7956f026d 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -602,3 +602,55 @@ "key_backup_setup_passphrase_set_passphrase_action" = "Setze Passphrase"; "key_backup_setup_passphrase_setup_recovery_key_info" = "Oder sichere deine Sicherung mit einem Wiederherstellungsschlüssel, und sichere sie an einem sicheren Ort."; "key_backup_setup_passphrase_setup_recovery_key_action" = "(Erweitert) Mit Wiederherstellungsschlüssel einrichten"; +"key_backup_setup_success_title" = "Erfolgreich!"; +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Deine Schlüssel werden gesichert.\n\nDein Wiederherstellungsschlüssel ist ein Sicherheitsnetzwerk - Du kannst damit den Zugriff auf deine verschlüsselten Nachrichten wiederherstellen, wenn du deine Passphrase vergisst.\n\nBewahre den Wiederherstellungsschlüssel an einem sehr sicheren Ort auf, beispielsweise einem Kennwortmanager (oder einem Tresor)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Speichere den Wiederherstellungsschlüssel"; +"key_backup_setup_success_from_passphrase_done_action" = "Erledigt"; +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Deine Schlüssel werden gesichert.\n\nErstelle eine Kopie dieses Wiederherstellungsschlüssels und bewahre ihn auf."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Wiederherstellungsschlüssel"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Mache eine Kopie"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Ich fertigte eine Kopie an"; +"key_backup_recover_title" = "Sichere Nachrichten"; +"key_backup_recover_invalid_passphrase_title" = "Falsche Wiederherstellungspassphrase"; +"key_backup_recover_invalid_passphrase" = "Sicherung konnte nicht mit dieser Passphrase entschlüsselt werden: Bitte stelle sicher, dass du die richtige Wiederherstellungspassphrase eingegeben hast."; +"key_backup_recover_invalid_recovery_key_title" = "Wiederherstellungsschlüssel passt nicht"; +"key_backup_recover_invalid_recovery_key" = "Sicherung konnte mit diesem Schlüssel nicht entschlüsselt werden: Bitte stelle sicher, dass du den richtigen Wiederherstellungsschlüssel eingegeben hast."; +"key_backup_recover_from_passphrase_info" = "Nutze deine Wiederherstellungspassphrase um deinen sicheren Chatverlauf zu entschlüsseln"; +"key_backup_recover_from_passphrase_passphrase_title" = "Gebe"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Passphrase eingeben"; +"key_backup_recover_from_passphrase_recover_action" = "Historie entschlüsseln"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Kenne deine Wiederherstellungskennphrase nicht? Du kannst "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "nutze deinen Wiederherstellungsschlüssel"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_recovery_key_info" = "Nutze deinen Wiederherstellungsschlüssel um deinen sicheren Chatverlauf zu entschlüsseln"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Gebe"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Gebe Wiederherstellungsschlüssel ein"; +"key_backup_recover_from_recovery_key_recover_action" = "Historie entschlüsseln"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Hast du deinen Wiederherstellungsschlüssel verloren? Du kannst in den Einstellungen einen neuen einrichten."; +"key_backup_recover_success_info" = "Sicherung wiederhergestellt"; +"key_backup_recover_done_action" = "Erledigt"; +"key_backup_setup_banner_title" = "Verliere niemals verschlüsselte Nachrichten"; +"key_backup_setup_banner_subtitle" = "Beginne Schlüsselsicherung zu nutzen"; +"key_backup_recover_banner_title" = "Verliere niemals verschlüsselte Nachrichten"; +"key_backup_recover_banner_subtitle" = "Benutze Schlüsselsicherung"; +"sign_out_existing_key_backup_alert_title" = "Bist du sicher, dass du dich abmelden willst?"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Abmelden"; +"sign_out_non_existing_key_backup_alert_title" = "Du verlierst den Zugriff auf deine verschlüsselten Nachrichten, wenn du dich jetzt abmeldest"; +"sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Beginne Schlüsselsicherung zu nutzen"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Ich möchte meine verschlüsselten Nachrichten nicht"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Du wirst deine verschlüsselten Nachrichten verlieren"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Du verlierst den Zugriff auf deine verschlüsselten Nachrichten, es sei denn, du sicherst deine Schlüssel, bevor du dich abmeldest."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Abmelden"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Sicherungskopie"; +"sign_out_key_backup_in_progress_alert_title" = "Schlüsselsicherung läuft. Wenn du dich jetzt abmeldest, verlierst du den Zugriff auf deine verschlüsselten Nachrichten."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Ich möchte meine verschlüsselten Nachrichten nicht"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Ich werde warten"; +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Neue Schlüsselsicherung"; +"e2e_key_backup_wrong_version" = "Es wurde eine neue Sicherung für einen sicheren Nachrichtenschlüssel erkannt.\n\nWenn dies nicht der Fall war, lege in den Einstellungen eine neue Passphrase fest."; +"e2e_key_backup_wrong_version_button_settings" = "Einstellungen"; +"e2e_key_backup_wrong_version_button_wasme" = "Das war ich"; +"key_backup_setup_intro_manual_export_info" = "(Erweitert)"; +"key_backup_setup_intro_manual_export_action" = "Manueller Schlüssel Export"; From f594273c6764aade0fdc4061bada8a52d9433a86 Mon Sep 17 00:00:00 2001 From: Sven Thomsen Date: Fri, 15 Feb 2019 19:42:43 +0000 Subject: [PATCH 240/244] Translated using Weblate (German) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 7956f026d..adeac9316 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -544,7 +544,7 @@ "room_replacement_link" = "Die Konversation wird hier fortgesetzt."; "room_predecessor_information" = "Dieser Raum ist die Fortsetzung einer anderen Konversation."; "room_predecessor_link" = "Tippe hier um ältere Nachrichten zu sehen."; -"settings_labs_room_members_lazy_loading" = "Raummitglieder verzögert laden"; +"settings_labs_room_members_lazy_loading" = "Raummitglieder nachladen"; "settings_labs_room_members_lazy_loading_error_message" = "Dein Heimserver unterstützt das verzögerte Laden von Raummitgliedern noch nicht. Versuche es später erneut."; "room_event_action_view_decrypted_source" = "Zeige entschlüsselten Quellcode"; "room_recents_server_notice_section" = "SYSTEMBENACHRICHTIGUNGEN"; From 9e0f411e4cfcd1e0d28b7a1cc381359fb5247e7f Mon Sep 17 00:00:00 2001 From: Fridtjof Mund Date: Fri, 15 Feb 2019 19:46:35 +0000 Subject: [PATCH 241/244] Translated using Weblate (German) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index adeac9316..3b3af0301 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -558,7 +558,7 @@ "room_resource_usage_limit_reached_message_contact_3" = " um dieses Limit erhöhen zu lassen."; "auth_accept_policies" = "Bitte Regeln dieses Heimservers ansehen und akzeptieren:"; "settings_key_backup" = "SCHLÜSSEL SICHERHEITSKOPIE"; -"settings_key_backup_info" = "Verschlüsselte Nachrichten sind mit Ende-zu-Ende-Verschlüsselung gesichert. Nur du und der/die Empfänger haben die Schlüssel um diese Nachrichten zu lesen."; +"settings_key_backup_info" = "Verschlüsselte Nachrichten sind durch Ende-zu-Ende-Verschlüsselung gesichert. Ausschließlich sie und der/die Empfänger besitzen die Schlüssel, um diese Nachrichten zu lesen."; "settings_key_backup_info_checking" = "Überprüfe..."; "settings_key_backup_info_none" = "Deine Schlüssel werden von diesem Gerät nicht gesichert."; "settings_key_backup_info_signout_warning" = "Sichere deine Schlüssel bevor du dich abmeldest, damit du sie nicht verlierst."; From e957de76b0aa534677d1016d12bc916c8d856179 Mon Sep 17 00:00:00 2001 From: Sven Thomsen Date: Fri, 15 Feb 2019 19:47:30 +0000 Subject: [PATCH 242/244] Translated using Weblate (German) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 3b3af0301..b9f864f8f 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -558,7 +558,7 @@ "room_resource_usage_limit_reached_message_contact_3" = " um dieses Limit erhöhen zu lassen."; "auth_accept_policies" = "Bitte Regeln dieses Heimservers ansehen und akzeptieren:"; "settings_key_backup" = "SCHLÜSSEL SICHERHEITSKOPIE"; -"settings_key_backup_info" = "Verschlüsselte Nachrichten sind durch Ende-zu-Ende-Verschlüsselung gesichert. Ausschließlich sie und der/die Empfänger besitzen die Schlüssel, um diese Nachrichten zu lesen."; +"settings_key_backup_info" = "Verschlüsselte Nachrichten sind durch Ende-zu-Ende-Verschlüsselung gesichert. Ausschließlich du und der/die Empfänger besitzen die Schlüssel, um diese Nachrichten zu lesen."; "settings_key_backup_info_checking" = "Überprüfe..."; "settings_key_backup_info_none" = "Deine Schlüssel werden von diesem Gerät nicht gesichert."; "settings_key_backup_info_signout_warning" = "Sichere deine Schlüssel bevor du dich abmeldest, damit du sie nicht verlierst."; From 2d70f374c02b994d139e9b74d7d724fefdd51bc9 Mon Sep 17 00:00:00 2001 From: sergio Date: Fri, 15 Feb 2019 18:38:55 +0000 Subject: [PATCH 243/244] Translated using Weblate (Russian) Currently translated at 100.0% (614 of 614 strings) Translation: Riot iOS/Riot iOS Translate-URL: https://translate.riot.im/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index 56281a31c..f295b9993 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -669,4 +669,4 @@ "key_backup_setup_intro_manual_export_action" = "Ручной экспорт ключей"; // Key backup wrong version "e2e_key_backup_wrong_version_title" = "Новая резервная копия ключей"; -"e2e_key_backup_wrong_version" = "Обнаружена новая резервная копия ключа безопасного сообщения.\n\nЕсли это не так, установите новую фразу-пароль в настройках."; +"e2e_key_backup_wrong_version" = "Обнаружена новая резервная копия ключа безопасного сообщения.\n\nЕсли вы этого не делали, установите новую парольную фразу в настройках."; From 90574256fe3b83781c9bee104a3dff9441be86d8 Mon Sep 17 00:00:00 2001 From: manuroe Date: Fri, 15 Feb 2019 21:53:10 +0100 Subject: [PATCH 244/244] version++ --- CHANGES.rst | 3 +- Podfile | 2 +- Podfile.lock | 34 +++++++++---------- Riot/SupportingFiles/Info.plist | 4 +-- RiotShareExtension/SupportingFiles/Info.plist | 4 +-- SiriIntents/Info.plist | 4 +-- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index b27f5b2fb..96d6b7fc7 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,7 +1,8 @@ -Changes in 0.7.12 (2019-xx-xx) +Changes in 0.8.0 (2019-02-15) =============================================== Improvements: + * Upgrade MatrixKit version (v0.9.5 - https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.5). * Theming: Create ThemeService to make theming easier. Use it to reskin Riot. * Use modern literals and array/dictionary syntax where possible (PR #2160). * Add SwiftGen pod in order to generate Swift constants for assets (#2177). diff --git a/Podfile b/Podfile index 9c33472e9..92626d5a9 100644 --- a/Podfile +++ b/Podfile @@ -9,7 +9,7 @@ source 'https://github.com/CocoaPods/Specs.git' # Different flavours of pods to MatrixKit # The current MatrixKit pod version -$matrixKitVersion = '0.9.3' +$matrixKitVersion = '0.9.5' # The develop branch version #$matrixKitVersion = 'develop' diff --git a/Podfile.lock b/Podfile.lock index d4c795cc8..8a56627bb 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -44,38 +44,38 @@ PODS: - HPGrowingTextView (1.1) - libbase58 (0.1.4) - libPhoneNumber-iOS (0.9.13) - - MatrixKit (0.9.3): + - MatrixKit (0.9.5): - cmark (~> 0.24.1) - DTCoreText (~> 1.6.21) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixKit/Core (= 0.9.3) - - MatrixSDK (= 0.12.1) - - MatrixKit/AppExtension (0.9.3): + - MatrixKit/Core (= 0.9.5) + - MatrixSDK (= 0.12.2) + - MatrixKit/AppExtension (0.9.5): - cmark (~> 0.24.1) - DTCoreText (~> 1.6.21) - DTCoreText/Extension - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.12.1) - - MatrixKit/Core (0.9.3): + - MatrixSDK (= 0.12.2) + - MatrixKit/Core (0.9.5): - cmark (~> 0.24.1) - DTCoreText (~> 1.6.21) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.12.1) - - MatrixSDK (0.12.1): - - MatrixSDK/Core (= 0.12.1) - - MatrixSDK/Core (0.12.1): + - MatrixSDK (= 0.12.2) + - MatrixSDK (0.12.2): + - MatrixSDK/Core (= 0.12.2) + - MatrixSDK/Core (0.12.2): - AFNetworking (~> 3.2.0) - GZIP (~> 1.2.2) - libbase58 (~> 0.1.4) - OLMKit (~> 3.0.0) - Realm (~> 3.11.1) - - MatrixSDK/JingleCallStack (0.12.1): + - MatrixSDK/JingleCallStack (0.12.2): - MatrixSDK/Core - WebRTC (= 63.11.20455) - - MatrixSDK/SwiftSupport (0.12.1): + - MatrixSDK/SwiftSupport (0.12.2): - MatrixSDK/Core - OLMKit (3.0.0): - OLMKit/olmc (= 3.0.0) @@ -101,8 +101,8 @@ DEPENDENCIES: - cmark - DTCoreText - GBDeviceInfo (~> 5.2.0) - - MatrixKit (= 0.9.3) - - MatrixKit/AppExtension (= 0.9.3) + - MatrixKit (= 0.9.5) + - MatrixKit/AppExtension (= 0.9.5) - MatrixSDK/JingleCallStack - MatrixSDK/SwiftSupport - OLMKit @@ -151,8 +151,8 @@ SPEC CHECKSUMS: HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19 libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd libPhoneNumber-iOS: e444379ac18bbfbdefad571da735b2cd7e096caa - MatrixKit: af9f94f36644bc21b63b114413f7bb510506b7d1 - MatrixSDK: f1f510d467d127a5f7afafaafa1554ac5d602132 + MatrixKit: 97bfda595111fe052ea8dbe74f5f65e2eca104a6 + MatrixSDK: 60a9472eacdf51e5110b8bc7beba844debf992ef OLMKit: 88eda69110489f817d59bcb4353b7c247570aa4f PiwikTracker: 42862c7b13028065c3dfd36b4dc38db8a5765acf Realm: 864477d028db77f7c5a0cba64a4892ad53db128a @@ -161,6 +161,6 @@ SPEC CHECKSUMS: WebRTC: f2a6203584745fe53532633397557876b5d71640 zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c -PODFILE CHECKSUM: 4a490fe13099d33a5152d8fb185df82a0b3b72bd +PODFILE CHECKSUM: e4a36bd00d4da77d377d00e5df6044e3ccce3b4c COCOAPODS: 1.6.0.beta.2 diff --git a/Riot/SupportingFiles/Info.plist b/Riot/SupportingFiles/Info.plist index bc5ec921e..5a506aeca 100644 --- a/Riot/SupportingFiles/Info.plist +++ b/Riot/SupportingFiles/Info.plist @@ -17,11 +17,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.7.12 + 0.8.0 CFBundleSignature ???? CFBundleVersion - 0.7.12 + 0.8.0 ITSAppUsesNonExemptEncryption ITSEncryptionExportComplianceCode diff --git a/RiotShareExtension/SupportingFiles/Info.plist b/RiotShareExtension/SupportingFiles/Info.plist index a1557d323..50340428b 100644 --- a/RiotShareExtension/SupportingFiles/Info.plist +++ b/RiotShareExtension/SupportingFiles/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 0.7.12 + 0.8.0 CFBundleVersion - 0.7.12 + 0.8.0 NSExtension NSExtensionAttributes diff --git a/SiriIntents/Info.plist b/SiriIntents/Info.plist index 4dca8f55b..7c7581001 100644 --- a/SiriIntents/Info.plist +++ b/SiriIntents/Info.plist @@ -17,9 +17,9 @@ CFBundlePackageType XPC! CFBundleShortVersionString - 0.7.12 + 0.8.0 CFBundleVersion - 0.7.12 + 0.8.0 NSExtension NSExtensionAttributes

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 IwVYo35ASfy(f|Me diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20.png old mode 100644 new mode 100755 index 79f827209b7bef625fd2cf9ed461173000329f0e..fd768188621962c8cf72d51b40d0764ade62c33d GIT binary patch delta 682 zcmV;b0#*IZ3DE_RBnkm@Qb$4nuFf3kks%X*32;bRa{vGi!vFvd!vV){sAK>D0%l1> zK~y+Ty^~8%6JZpF{T&)(Tp~n_L|wUZhtUM%%B8Q%RgOtl->G1WkP* z+? zU_K4gCkeKYjJK}XO;Oba^Oq=Hw z8pZv&6wJ#K?BNWi_?(_q6$A7T@Oe~0=ldiE$ueqtXK9{ok0WR?hH>f18ph)^OJ52i zd2_!G22wjJa3~8(8TST*i66M%VkCXLe={-INr;l$r!@19u99p4H#P{&kZk# z=wD20?Mj8(O^)~^TzAFrbXG*=*Khr_Dh8;D?umHKkM(t^K Q_5c6?07*qoM6N<$f*K1zTmS$7 literal 1229 zcmeAS@N?(olHy`uVBq!ia0vp^A|TAc1|)ksWqE-VOS+@4BLl<6e(pbstU$g(vPY0F z14ES>14Ba#1H&(%P{RubhEf9thF1v;3|2E37{m+a>4nJa0`PlBg3pY z5)2HCk(nV8B@w}FfdWk9dNvV1jxdlMg3=B3ERzPNMYDuC(MQ%=Bu~mhw5?F;5 zkPQ;nS5g2gDap1~itr6kaLzAERWQ{v(KAr8<5EyiuqjGOvkG!?gK7uzY?U%fN(!v> z^~=l4^~#O)@{7{-4J|D#^$m>ljf`}GDs+o0^GXscbn}XpA%?)raY-#sF3Kz@$;{7F z0GXSZlwVq6tE2?72o50bEXhnm*pycc^%l^B`XCv7Lp=k1xY4lG>|7tQSo??GH%AzT^)~K6I%yQIT6%sJHOpIf(-r zEHNC17BLnsd0VpV^NzL)w8{N=+o7JN7TV{o8#qI{Ue`y%WrJ;nR(#hr`ZjLau#cOf-ab{9dlWzD3PjXA~?r8cqC8NB|M zL+xFcgvtaK9f5v{4K6QE1UzgyU^3V1&i0RQUusFc7Tcx9{bIJP>#ixR-<`gsd^%gO zv?NWUnrW7n_lp%5r!=QZ&%7vHaBY==`1Zt|e7`oc&UtC4y7>0b8;lxW4?~I?D~@H( zax0gL>f?A`qVw+LRHq~BOyDF2hMom`Ynqy?&j1z z$+c`}e#(A`HSY?m={{eUqVZ-@@e$|lj+%#04Bp+}-F&A&F7K?XQtE=FsEUsjjO!ks z^u9Iu4TFe0`$gfvU4K{|_RTo_mfbw?eo>0t(S zT<FTXqe{Gqyck1X-p-y|`rO+2`xBm>G~Jcr^h;u^d#Bs_vkSMm>D|s($X$|R-|AZ1+w$(l zlhaFDZYkEYhD>~9cC~NC{!`A?yN%7{xo?#HnSbT}(iKv_b9$5cL4}5=tDnm{r-UW| Do`dof diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20@2x-1.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-20@2x-1.png old mode 100644 new mode 100755 index 032ddd8ed5f538037c3f1a8ae93b0f0e67339516..839031adb7d171ac8701d01afa3ac9a60a874004 GIT binary patch delta 1628 zcmV-i2BZ0b3gQfq8Gi-<004~sxNQIc00DDSM?wIu&K&6g000DMK}|sb0I`n?{9y$E z000SaNLh0L01m?d01m?e$8V@)000H|Nklr+%^9PTfv>FVfcm}NH82R}5H zQ)5mSYt)%S(NZF4QV6H=ZYWr(WnM-_K$ojrR0KuEdtNgU7Jpn=*t@$3$S$Hq_DsL$ z-LtT4$T{0OP9Jz?o;hdFp0n?Be)o4D!~Yy30%OI9z*rHrz`K2aqxlv9?(F#sf5?3g1BM0GxqFdRWXBtuZ{W2}O?X|7^Gj@4P-;g)u?_Py@_fNQ8$Oj| zdW92vFLt0q1b_cm7!r7{wFhw-^>}tgojQ&ej$2cY_i|d0W4(>Nw%f>U4KhzV?yz(s z^NJ4(D;=1bXGQkeTiUNh2VH@^f8NJiTPzs8>N+N6nelQ~LqA80;7`izDD(J{Z|m-- zNd)g{6XC*Qmmj-Yx)5J#LrSq7J@@WwzibS;0x#R|V1LZ&>zEiOEW`#9o;DmJ)MUev> zx4ItFcYigjg$qRlEfykUan(7m`u>{}9uetBuC)sV^4*L*R@6CrwH1bkuD}zP06sKX z@#>F_N)W9^J}*fU_gy_Q#hqn018QNC;_~exP~1w(?QZT;BG-!h3*#yG65J1Ey}XsF=&Pbblee)~)VIJ?_S$qb@8x<53peBcvd@ zd4^;%lZIB@Eu2%(27j-9`7tE$^C}0*#Y)V`W@y5?7}D&%~*1S#C-r9$W-CV>okCICf} zul!)fsFihiW?3DkY`KAzXKtcILSehP6YsMvN-bn|=gD*Nk|Z29^bnIkE@+a)$|YIY z@?MZ0%@V{+=lNKvpA3h&GE{tB>rw7zl4M9}N-KA2D+~_j9_Rp}=^NGmgDJ;I>C0Si*#2U2vG$dT4uBE^~U#jX+* z6>i0#C28Gwse|83yw1$A8j8IT41c(Ia11IJOD&{pX;H@C`pZ7VN$VTz;sL7GC@=8t zj%Ije;*JI}CkZo|Vi#7}Rev5zAjv_OlejMm>k%;tWJYF*^_T=4v1ldEh>?RW$!nul zimUTl5zTJJpo<5RWT;M(S?$49M=xrmGrT13q{#3@3Fp(x>+p;8ZKH_Ef`23hGLb^a zl@>=4kroW`MVTwdN+@trHv(OOoM!q3iq)7TUxq9y*Agr3sJPmt-5tbdg*H4V^=~Lw z(~9gi^G$7rTy02TiYADiAWfTQLQ_eiOeLki4Hnqm(}&3$8dXdNT{~Fh_>2Zj`Kbx_ z4D3yG1)i3QKd;=TIzX=U(SMycIu&_dBBOpnnGMHeP>4jWJjbM9OhyVEC&H&m@$NIQ z!P6DUe-LI%=51{Z?$S7&kermaHFaW^eAoSe$#|`7j-FV0t-n8qtoiu2*Rbh?SG#L? z=n5n_w@uG(#yZ)Ea}puBDW4{LjiF}25NM%f*$Y3l?3&v2lTXSyuT>dwFJVX^ajESN zQuf)AP-Ig~DY4^xtNuJkRLM)Mu6AQpl^chKd7+_TSYQbJV~BiIh+5#I#)!aJF(NQF a0RI4jNX$^Rx!!I70000_CX>@2H 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 a0RI4jNX$^Rx!!I70000_CX>@2H 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 M>UxOM+g9QK0ZXFg%>V!Z diff --git a/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29.png b/Riot/Assets/SharedImages.xcassets/AppIcon.appiconset/Icon-29.png old mode 100644 new mode 100755 index 6b0dcba99ae27bfe6678459a5bedaa0baa3530d1..97985440209f82dfce97fc8fb38a40d148d38dab GIT binary patch delta 1095 zcmV-N1i1T+2hj+S8Gi-<0035#XAb}X00DDSM?wIu&K&6g000DMK}|sb0I`n?{9y$E z000SaNLh0L01m?d01m?e$8V@)000B#NklNU00may+4G?h3VjUK@AcG8|;5G-Rwqwn+GSm11SGXK^a@8 zg5zBZsvfAgV~Zg%@sIYa4@(MF6L0XfVHgW@`?2(}8B6la_^!c@suy9LvW7GZLjP37 z&z)XmwYbn`iGOOpPAw_4yj>B%&3YR)>8;rCn-%MhSW(g!z`4-~j0CSCyX=hNnm>-( zu?RA5xKZ7$Y98d0LbDp3NYj}GFllRw2C$=U3>km8u=jT-exT^sboc!N-r$KNO9Za7N3owiB%FAwd73RL zl$$2K*(rc)iwCf!#D?q+FAM}JejE^1@=O(=MsFNh1U*adoh_3TT1sP4 zIT#X6!+)u};);n*H9ib#FQ!!5?iY{?l-7Ne8E&x3p^*4!ndFgbP+R#P``JZid5*^qwSDN14T#KikyWm5ArTT*BVrH5<7(d{zX@zWg-ayotZ{;D0T3kTkt-xa@F z@XfhVTvx`SqbQH3NG(ea<(d-oEJ1fSI>Z7vLJm3AGoft!x7|$+6t(*>{((LGQ8mq^ zbbno@?&TC;rLD8wID%C(z#AylY58XKIsVo>$n{B$R6}$6%Uv(hDRQnUH`8?Rib4y% zHI8EP%{$G@-1=xJk4)Kf6-Bpv2+;+)@Hix{4>wa1x|wV-MO%2&t9hAQQfP8HFmzwD zOALQ0t-XqASL7fa1qL%L3FiI0j2i2SOMjkbDO67#XrR?6QrhknP>%FOS3r9KMCizW zd2$FVDXmE;+akKXwKF!?bV;EV_W~&DQ(&S7;(BreWz!-zJqc?sru5)t0$|2>P7=VPxi0pP}<8;9q_q`EMFX+~EKK N002ovPDHLkV1kGt{eb`g delta 897 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 delta 2204 zcmV;N2xIrF5}gr{8Gix*003^;-G2Z800DDSM?wIu&K&6g000SaNLh0L01FcU01FcV z0GgZ_00007bV*G`2jC103_CX>@2H zM@dakSAh-}000OINkl& zAOPkRm?cm}0DtZ9$nISG`X3)&Z7etAkO2f>hM-BE%;s=b z+1h_2{2+)7q84ao+$tT-kC$`@!53dr*k@GZ3IEftF5bBGMI5qCxAX&<@%IjyW0~!U zWg^lrWt}99I8z8Ylo_5KK2p}R_=TYR!j)3~=kxo&{(t4~62`X~0z>CyDfiwuAkX;( z1ONi4VnVS(Adb?c5xeWmA2M=tm7~Xt6L2RVdP!&S+Wys#u5Zf<0FbF{-&{*h>B^|F zb#{dm5=adzS=FlOxdP2B`OQB*xYB0+>GHHr)K`MrSZa3l6`5-(rJ3?p_e}(kIBPL~ zIcRp2uz##OV`gDFY+hOUk|6YE