From a02e1d6ca49c761cf9a13b15c3fd72e7f284e7a1 Mon Sep 17 00:00:00 2001 From: Simon Wiedmer Date: Tue, 4 Jan 2022 08:58:52 +0100 Subject: [PATCH 001/188] Disable proximity sensor and enable sleep after call ended --- .../Controllers/MXKCallViewController.m | 43 +++++++++---------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m index 55781b106..55acfb1b5 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m @@ -1422,29 +1422,26 @@ static const CGFloat kLocalPreviewMargin = 20; } } -- (void)updateProximityAndSleep -{ - BOOL inCall = (mxCall.state == MXCallStateConnected || mxCall.state == MXCallStateRinging || mxCall.state == MXCallStateInviteSent || mxCall.state == MXCallStateConnecting || mxCall.state == MXCallStateCreateOffer || mxCall.state == MXCallStateCreateAnswer); - - if (inCall) - { - BOOL isBuiltInReceiverUsed = self.isBuiltInReceiverAudioOuput; - - // Enable the proximity monitoring when the built in receiver is used as the audio output. - BOOL enableProxMonitoring = isBuiltInReceiverUsed; - [[UIDevice currentDevice] setProximityMonitoringEnabled:enableProxMonitoring]; - - // Disable the idle timer during a video call, or during a voice call which is performed with the built-in receiver. - // Note: if the device is locked, VoIP calling get dropped if an incoming GSM call is received. - BOOL disableIdleTimer = mxCall.isVideoCall || isBuiltInReceiverUsed; - - UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; - if (sharedApplication) - { - sharedApplication.idleTimerDisabled = disableIdleTimer; - } - } -} + - (void)updateProximityAndSleep + { + BOOL inCall = (mxCall.state == MXCallStateConnected || mxCall.state == MXCallStateRinging || mxCall.state == MXCallStateInviteSent || mxCall.state == MXCallStateConnecting || mxCall.state == MXCallStateCreateOffer || mxCall.state == MXCallStateCreateAnswer); + + BOOL isBuiltInReceiverUsed = self.isBuiltInReceiverAudioOuput; + + // Enable the proximity monitoring when the built in receiver is used as the audio output. + BOOL enableProxMonitoring = inCall && isBuiltInReceiverUsed; + [[UIDevice currentDevice] setProximityMonitoringEnabled:enableProxMonitoring]; + + // Disable the idle timer during a video call, or during a voice call which is performed with the built-in receiver. + // Note: if the device is locked, VoIP calling get dropped if an incoming GSM call is received. + BOOL disableIdleTimer = inCall && (mxCall.isVideoCall || isBuiltInReceiverUsed); + + UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; + if (sharedApplication) + { + sharedApplication.idleTimerDisabled = disableIdleTimer; + } + } - (UIView *)createIncomingCallView { From d0e5289967601e408278cf4b13dba6e127e41365 Mon Sep 17 00:00:00 2001 From: Simon Wiedmer Date: Tue, 25 Jan 2022 09:02:56 +0100 Subject: [PATCH 002/188] Add changelog --- changelog.d/4103.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4103.bugfix diff --git a/changelog.d/4103.bugfix b/changelog.d/4103.bugfix new file mode 100644 index 000000000..2093e302e --- /dev/null +++ b/changelog.d/4103.bugfix @@ -0,0 +1 @@ +Fix proximity sensor staying on and sleep timer staying disabled after call ends From 3a1cd3d9301f421aff865f2c2d932457e82ca67e Mon Sep 17 00:00:00 2001 From: Simon Wiedmer Date: Mon, 31 Jan 2022 11:13:07 +0100 Subject: [PATCH 003/188] Call native api only if there is a change --- .../MatrixKit/Controllers/MXKCallViewController.m | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m index 55acfb1b5..7f23a8ec6 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKCallViewController.m @@ -1430,14 +1430,19 @@ static const CGFloat kLocalPreviewMargin = 20; // Enable the proximity monitoring when the built in receiver is used as the audio output. BOOL enableProxMonitoring = inCall && isBuiltInReceiverUsed; - [[UIDevice currentDevice] setProximityMonitoringEnabled:enableProxMonitoring]; + + UIDevice *device = [UIDevice currentDevice]; + if (device && device.isProximityMonitoringEnabled != enableProxMonitoring) + { + [device setProximityMonitoringEnabled:enableProxMonitoring]; + } // Disable the idle timer during a video call, or during a voice call which is performed with the built-in receiver. // Note: if the device is locked, VoIP calling get dropped if an incoming GSM call is received. BOOL disableIdleTimer = inCall && (mxCall.isVideoCall || isBuiltInReceiverUsed); UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; - if (sharedApplication) + if (sharedApplication && sharedApplication.isIdleTimerDisabled != disableIdleTimer) { sharedApplication.idleTimerDisabled = disableIdleTimer; } From 2cef1a73987e819af498f111d7620302341a25bd Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 2 Feb 2022 12:24:22 +0000 Subject: [PATCH 004/188] Add the Use Case selection screen to the onboarding flow. --- .../Contents.json | 15 ++ .../onboarding_use_case_community.svg | 5 + .../Contents.json | 15 ++ .../onboarding_use_case_community_dark.svg | 5 + .../Contents.json | 15 ++ .../onboarding_use_case_icon.svg | 4 + .../Contents.json | 15 ++ .../onboarding_use_case_personal.svg | 5 + .../Contents.json | 15 ++ .../onboarding_use_case_personal_dark.svg | 5 + .../Contents.json | 15 ++ .../onboarding_use_case_work.svg | 5 + .../Contents.json | 15 ++ .../onboarding_use_case_work_dark.svg | 5 + Riot/Assets/en.lproj/Vector.strings | 11 ++ Riot/Generated/Images.swift | 7 + Riot/Generated/Strings.swift | 36 +++++ Riot/Managers/UserSessions/UserSession.swift | 2 + .../UserSessions/UserSessionProperties.swift | 80 +++++++++++ .../UserSessions/UserSessionsService.swift | 3 + .../Analytics/PostHogAnalyticsClient.swift | 2 +- .../AuthenticationCoordinator.swift | 4 +- .../AuthenticationCoordinatorProtocol.swift | 2 +- .../Onboarding/OnboardingCoordinator.swift | 66 ++++++++- RiotNSE/target.yml | 1 + RiotShareExtension/target.yml | 1 + .../AnalyticsPromptModels.swift | 39 +++--- .../AnalyticsPromptCoordinator.swift | 4 +- .../Coordinator/AnalyticsPromptStrings.swift | 9 -- .../MockAnalyticsPromptStrings.swift | 15 -- .../View/AnalyticsPrompt.swift | 13 +- .../View/AnalyticsPromptTermsText.swift | 74 ---------- .../Modules/Common/Mock/MockAppScreens.swift | 1 + .../Common/Util/InlineTextButton.swift | 89 ++++++++++++ .../Modules/Common/Util/StyledText.swift | 126 +++++++++++++++++ .../Common/OnboardingButtonStyle.swift | 32 +++++ .../OnboardingUseCaseCoordinator.swift | 60 ++++++++ .../MockOnboardingUseCaseScreenState.swift | 52 +++++++ .../UseCase/OnboardingUseCaseModels.swift | 41 ++++++ .../UseCase/OnboardingUseCaseViewModel.swift | 52 +++++++ .../OnboardingUseCaseViewModelProtocol.swift | 24 ++++ .../Test/UI/OnboardingUseCaseUITests.swift | 23 +++ .../OnboardingUseCaseViewModelTests.swift | 24 ++++ .../UseCase/View/OnboardingUseCase.swift | 132 ++++++++++++++++++ .../View/OnboardingUseCaseButton.swift | 59 ++++++++ RiotTests/OnboardingTests.swift | 87 ++++++++++++ SiriIntents/target.yml | 1 + changelog.d/5160.feature | 1 + 48 files changed, 1178 insertions(+), 134 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/onboarding_use_case_community.svg create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/onboarding_use_case_community_dark.svg create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/onboarding_use_case_icon.svg create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/onboarding_use_case_personal.svg create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/onboarding_use_case_personal_dark.svg create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/onboarding_use_case_work.svg create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/onboarding_use_case_work_dark.svg create mode 100644 Riot/Managers/UserSessions/UserSessionProperties.swift delete mode 100644 RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptTermsText.swift create mode 100644 RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift create mode 100644 RiotSwiftUI/Modules/Common/Util/StyledText.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift create mode 100644 RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift create mode 100644 RiotTests/OnboardingTests.swift create mode 100644 changelog.d/5160.feature diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/Contents.json new file mode 100644 index 000000000..9f6e8de0a --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_community.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/onboarding_use_case_community.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/onboarding_use_case_community.svg new file mode 100644 index 000000000..6b58a7b56 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community.imageset/onboarding_use_case_community.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/Contents.json new file mode 100644 index 000000000..e34cfce4e --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_community_dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/onboarding_use_case_community_dark.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/onboarding_use_case_community_dark.svg new file mode 100644 index 000000000..1fb2f8af1 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_community_dark.imageset/onboarding_use_case_community_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/Contents.json new file mode 100644 index 000000000..f4e9e56ac --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_icon.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/onboarding_use_case_icon.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/onboarding_use_case_icon.svg new file mode 100644 index 000000000..2366becdb --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_icon.imageset/onboarding_use_case_icon.svg @@ -0,0 +1,4 @@ + + + + diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/Contents.json new file mode 100644 index 000000000..1073b4087 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_personal.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/onboarding_use_case_personal.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/onboarding_use_case_personal.svg new file mode 100644 index 000000000..efd561c9a --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal.imageset/onboarding_use_case_personal.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/Contents.json new file mode 100644 index 000000000..081fb3fde --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_personal_dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/onboarding_use_case_personal_dark.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/onboarding_use_case_personal_dark.svg new file mode 100644 index 000000000..b5c728adc --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_personal_dark.imageset/onboarding_use_case_personal_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/Contents.json new file mode 100644 index 000000000..40d6dcbdf --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_work.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/onboarding_use_case_work.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/onboarding_use_case_work.svg new file mode 100644 index 000000000..61cf7bd86 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work.imageset/onboarding_use_case_work.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/Contents.json b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/Contents.json new file mode 100644 index 000000000..da38b9aad --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/Contents.json @@ -0,0 +1,15 @@ +{ + "images" : [ + { + "filename" : "onboarding_use_case_work_dark.svg", + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "preserves-vector-representation" : true + } +} diff --git a/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/onboarding_use_case_work_dark.svg b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/onboarding_use_case_work_dark.svg new file mode 100644 index 000000000..0f6ee387a --- /dev/null +++ b/Riot/Assets/Images.xcassets/Onboarding/onboarding_use_case_work_dark.imageset/onboarding_use_case_work_dark.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index e81838b29..f7ee5c0ca 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -93,6 +93,17 @@ "onboarding_splash_page_4_title_no_pun" = "Messaging for your team."; "onboarding_splash_page_4_message" = "Element is also great for the workplace. It’s trusted by the world’s most secure organisations."; +"onboarding_use_case_title" = "Who will you chat to the most?"; +"onboarding_use_case_message" = "We’ll help you get connected."; +"onboarding_use_case_personal_messaging" = "Friends and family"; +"onboarding_use_case_work_messaging" = "Coworkers and teams"; +"onboarding_use_case_community_messaging" = "Online community members"; +/* The placeholder string contains onboarding_use_case_skip_button as a tappable action */ +"onboarding_use_case_not_sure_yet" = "Not sure yet? You can %@"; +"onboarding_use_case_skip_button" = "skip this question"; +"onboarding_use_case_existing_server_message" = "Looking to join an existing server?"; +"onboarding_use_case_existing_server_button" = "Connect to server"; + // Authentication "auth_login" = "Log in"; "auth_register" = "Register"; diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index eca6c861e..cec8486d5 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -118,6 +118,13 @@ internal enum Asset { internal static let onboardingSplashScreenPage3Dark = ImageAsset(name: "OnboardingSplashScreenPage3Dark") internal static let onboardingSplashScreenPage4 = ImageAsset(name: "OnboardingSplashScreenPage4") internal static let onboardingSplashScreenPage4Dark = ImageAsset(name: "OnboardingSplashScreenPage4Dark") + internal static let onboardingUseCaseCommunity = ImageAsset(name: "onboarding_use_case_community") + internal static let onboardingUseCaseCommunityDark = ImageAsset(name: "onboarding_use_case_community_dark") + internal static let onboardingUseCaseIcon = ImageAsset(name: "onboarding_use_case_icon") + internal static let onboardingUseCasePersonal = ImageAsset(name: "onboarding_use_case_personal") + internal static let onboardingUseCasePersonalDark = ImageAsset(name: "onboarding_use_case_personal_dark") + internal static let onboardingUseCaseWork = ImageAsset(name: "onboarding_use_case_work") + internal static let onboardingUseCaseWorkDark = ImageAsset(name: "onboarding_use_case_work_dark") internal static let peopleEmptyScreenArtwork = ImageAsset(name: "people_empty_screen_artwork") internal static let peopleEmptyScreenArtworkDark = ImageAsset(name: "people_empty_screen_artwork_dark") internal static let peopleFloatingAction = ImageAsset(name: "people_floating_action") diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 2a92eec26..ea3ecab07 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2443,6 +2443,42 @@ public class VectorL10n: NSObject { public static var onboardingSplashRegisterButtonTitle: String { return VectorL10n.tr("Vector", "onboarding_splash_register_button_title") } + /// Online community members + public static var onboardingUseCaseCommunityMessaging: String { + return VectorL10n.tr("Vector", "onboarding_use_case_community_messaging") + } + /// Connect to server + public static var onboardingUseCaseExistingServerButton: String { + return VectorL10n.tr("Vector", "onboarding_use_case_existing_server_button") + } + /// Looking to join an existing server? + public static var onboardingUseCaseExistingServerMessage: String { + return VectorL10n.tr("Vector", "onboarding_use_case_existing_server_message") + } + /// We’ll help you get connected. + public static var onboardingUseCaseMessage: String { + return VectorL10n.tr("Vector", "onboarding_use_case_message") + } + /// Not sure yet? You can %@ + public static func onboardingUseCaseNotSureYet(_ p1: String) -> String { + return VectorL10n.tr("Vector", "onboarding_use_case_not_sure_yet", p1) + } + /// Friends and family + public static var onboardingUseCasePersonalMessaging: String { + return VectorL10n.tr("Vector", "onboarding_use_case_personal_messaging") + } + /// skip this question + public static var onboardingUseCaseSkipButton: String { + return VectorL10n.tr("Vector", "onboarding_use_case_skip_button") + } + /// Who will you chat to the most? + public static var onboardingUseCaseTitle: String { + return VectorL10n.tr("Vector", "onboarding_use_case_title") + } + /// Coworkers and teams + public static var onboardingUseCaseWorkMessaging: String { + return VectorL10n.tr("Vector", "onboarding_use_case_work_messaging") + } /// Open public static var `open`: String { return VectorL10n.tr("Vector", "open") diff --git a/Riot/Managers/UserSessions/UserSession.swift b/Riot/Managers/UserSessions/UserSession.swift index 786fed88d..fa5b883ac 100644 --- a/Riot/Managers/UserSessions/UserSession.swift +++ b/Riot/Managers/UserSessions/UserSession.swift @@ -33,6 +33,8 @@ class UserSession: NSObject, UserSessionProtocol { let account: MXKAccount // Keep strong reference to the MXSession because account.mxSession can become nil on logout or failure let matrixSession: MXSession + /// An object that contains user specific properties. + private(set) lazy var properties = UserSessionProperties(userId: userId) var userId: String { guard let userId = self.account.mxCredentials.userId else { diff --git a/Riot/Managers/UserSessions/UserSessionProperties.swift b/Riot/Managers/UserSessions/UserSessionProperties.swift new file mode 100644 index 000000000..d7f4b31df --- /dev/null +++ b/Riot/Managers/UserSessions/UserSessionProperties.swift @@ -0,0 +1,80 @@ +// +// Copyright 2021 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 + +/// User properties that are tied to a particular user ID. +class UserSessionProperties: NSObject { + + // MARK: - Constants + private enum Constants { + static let suiteName = BuildSettings.baseBundleIdentifier + ".UserSession" + static let useCaseKey = "useCase" + } + + // MARK: - Properties + + // MARK: Private + + /// The user ID for these properties + private let userId: String + /// The underlying dictionary that stores the properties in user defaults. + private var dictionary: [String: Any] { + didSet { + UserDefaults(suiteName: Constants.suiteName)?.dictionary(forKey: userId) + } + } + + // MARK: Public + + /// The user's use case selection if this session was the one used to register the account. + var useCase: UseCase? { + get { + guard let useCaseRawValue = dictionary[Constants.useCaseKey] as? String else { return nil } + return UseCase(rawValue: useCaseRawValue) + } set { + dictionary[Constants.useCaseKey] = newValue?.rawValue + } + } + + /// Represents a selected use case for the app. + /// Note: The raw string value is used for storage. + enum UseCase: String { + case personalMessaging + case workMessaging + case communityMessaging + case skipped + } + + // MARK: - Setup + + /// Create new properties for the specified user ID. + /// - Parameter userId: The user ID to load properties for. + init(userId: String) { + self.userId = userId + self.dictionary = UserDefaults(suiteName: Constants.suiteName)?.dictionary(forKey: userId) ?? [:] + + super.init() + } + + // MARK: - Public + + /// Clear all of the stored properties. + func delete() { + dictionary = [:] + UserDefaults(suiteName: Constants.suiteName)?.removeObject(forKey: userId) + } +} diff --git a/Riot/Managers/UserSessions/UserSessionsService.swift b/Riot/Managers/UserSessions/UserSessionsService.swift index 7a68d9752..c5842dfed 100644 --- a/Riot/Managers/UserSessions/UserSessionsService.swift +++ b/Riot/Managers/UserSessions/UserSessionsService.swift @@ -131,6 +131,9 @@ class UserSessionsService: NSObject { NotificationCenter.default.post(name: UserSessionsService.willRemoveUserSession, object: self, userInfo: [NotificationUserInfoKey.userSession: userSession]) } + // Clear any stored user properties from this session. + userSession.properties.delete() + self.userSessions.removeAll { (userSession) -> Bool in return userId == userSession.userId } diff --git a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift index 1c7172112..f6db52f36 100644 --- a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift +++ b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift @@ -36,7 +36,7 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { } func identify(id: String) { - postHog?.identify(id) + postHog?.identify(id, properties: nil) } func reset() { diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift index a310cdb1a..521ad52c2 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift @@ -32,7 +32,7 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc // Must be used only internally var childCoordinators: [Coordinator] = [] - var completion: (() -> Void)? + var completion: ((MXKAuthenticationType) -> Void)? // MARK: - Setup @@ -82,6 +82,6 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc // MARK: - AuthenticationViewControllerDelegate extension AuthenticationCoordinator: AuthenticationViewControllerDelegate { func authenticationViewControllerDidDismiss(_ authenticationViewController: AuthenticationViewController!) { - completion?() + completion?(authenticationViewController.authType) } } diff --git a/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift b/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift index 7037f9d1f..c90c212a5 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift @@ -20,7 +20,7 @@ import Foundation /// `AuthenticationCoordinatorProtocol` is a protocol describing a Coordinator that handle's the authentication navigation flow. protocol AuthenticationCoordinatorProtocol: Coordinator, Presentable { - var completion: (() -> Void)? { get set } + var completion: ((MXKAuthenticationType) -> Void)? { get set } /// Update the screen to display registration or login. func update(authenticationType: MXKAuthenticationType) diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 8a6dcc7c4..b14707c13 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -60,6 +60,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { // MARK: Screen results private var splashScreenResult: OnboardingSplashScreenViewModelResult? + private var useCaseResult: OnboardingUseCaseViewModelResult? // MARK: Public @@ -126,9 +127,43 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { self.navigationRouter.setRootModule(coordinator, popCompletion: nil) } + @available(iOS 14.0, *) /// Displays the next view in the flow after the splash screen. private func splashScreenCoordinator(_ coordinator: OnboardingSplashScreenCoordinator, didCompleteWith result: OnboardingSplashScreenViewModelResult) { splashScreenResult = result + + switch result { + case .register: + showUseCase() + case .login: + showAuthenticationScreen() + } + } + + @available(iOS 14.0, *) + /// Show the use case screen for new users. + private func showUseCase() { + let coordinator = OnboardingUseCaseCoordinator() + coordinator.completion = { [weak self, weak coordinator] result in + guard let self = self, let coordinator = coordinator else { return } + self.useCaseCoordinator(coordinator, didCompleteWith: result) + } + + coordinator.start() + add(childCoordinator: coordinator) + + if self.navigationRouter.modules.isEmpty { + self.navigationRouter.setRootModule(coordinator, popCompletion: nil) + } else { + self.navigationRouter.push(coordinator, animated: true) { [weak self] in + self?.remove(childCoordinator: coordinator) + } + } + } + + /// Displays the next view in the flow after the use case screen. + private func useCaseCoordinator(_ coordinator: OnboardingUseCaseCoordinator, didCompleteWith result: OnboardingUseCaseViewModelResult) { + useCaseResult = result showAuthenticationScreen() } @@ -139,9 +174,9 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { MXLog.debug("[OnboardingCoordinator] showAuthenticationScreen") let coordinator = authenticationCoordinator - coordinator.completion = { [weak self, weak coordinator] in + coordinator.completion = { [weak self, weak coordinator] authenticationType in guard let self = self, let coordinator = coordinator else { return } - self.authenticationCoordinatorDidComplete(coordinator) + self.authenticationCoordinator(coordinator, didCompleteWith: authenticationType) } // Due to needing to preload the authVC, this breaks the Coordinator init/start pattern. @@ -178,8 +213,33 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { } /// Displays the next view in the flow after the authentication screen. - private func authenticationCoordinatorDidComplete(_ coordinator: AuthenticationCoordinatorProtocol) { + private func authenticationCoordinator(_ coordinator: AuthenticationCoordinatorProtocol, didCompleteWith authenticationType: MXKAuthenticationType) { completion?() isShowingAuthentication = false + + // Store the chosen use case when appropriate for any default configuration and, if opted in, for analytics. + if authenticationType == MXKAuthenticationTypeRegister, + let useCaseResult = useCaseResult, + let userSession = UserSessionsService.shared.mainUserSession { + userSession.properties.useCase = useCaseResult.userSessionPropertyValue + } + } +} + +extension OnboardingUseCaseViewModelResult { + /// The result converted into the type stored in the user session. + var userSessionPropertyValue: UserSessionProperties.UseCase? { + switch self { + case .personalMessaging: + return .personalMessaging + case .workMessaging: + return .workMessaging + case .communityMessaging: + return .communityMessaging + case .skipped: + return .skipped + case .customServer: + return nil + } } } diff --git a/RiotNSE/target.yml b/RiotNSE/target.yml index 68a86ca51..1f15351ef 100644 --- a/RiotNSE/target.yml +++ b/RiotNSE/target.yml @@ -63,6 +63,7 @@ targets: - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift - path: ../Riot/Modules/MatrixKit - path: ../Riot/Modules/Analytics + - path: ../Riot/Managers/UserSessions - path: ../Riot/Managers/AppInfo/ excludes: - "**/*.md" # excludes all files with the .md extension diff --git a/RiotShareExtension/target.yml b/RiotShareExtension/target.yml index 494407323..945d77d7a 100644 --- a/RiotShareExtension/target.yml +++ b/RiotShareExtension/target.yml @@ -70,6 +70,7 @@ targets: buildPhase: resources - path: ../Riot/Modules/MatrixKit - path: ../Riot/Modules/Analytics + - path: ../Riot/Managers/UserSessions excludes: - "**/*.md" # excludes all files with the .md extension - path: ../Riot/Generated/MatrixKitStrings.swift diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift index 2cfdb6e0f..6e4e34f30 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/AnalyticsPromptModels.swift @@ -42,18 +42,13 @@ struct AnalyticsPromptViewState: BindableState { /// A collection of strings for the UI that need to be created in /// the coordinator or mocked in the RiotSwiftUI target. protocol AnalyticsPromptStringsProtocol { - var appDisplayName: String { get } - var point1: NSAttributedString { get } var point2: NSAttributedString { get } - - var termsNewUser: NSAttributedString { get } - var termsUpgrade: NSAttributedString { get } } enum AnalyticsPromptType { - case newUser(termsString: NSAttributedString) - case upgrade(termsString: NSAttributedString) + case newUser + case upgrade } extension AnalyticsPromptType { @@ -67,11 +62,23 @@ extension AnalyticsPromptType { } } - /// The terms string that should be displayed. - var termsStrings: NSAttributedString { + /// The main part of the terms string that should be displayed. + var mainTermsString: String { switch self { - case .newUser(let termsString), .upgrade(let termsString): - return termsString + case .newUser: + return VectorL10n.analyticsPromptTermsNewUser("%@") + case .upgrade: + return VectorL10n.analyticsPromptTermsUpgrade("%@") + } + } + + /// The tappable part of the terms string that should be displayed. + var termsLinkString: String { + switch self { + case .newUser: + return VectorL10n.analyticsPromptTermsLinkNewUser + case .upgrade: + return VectorL10n.analyticsPromptTermsLinkUpgrade } } @@ -96,15 +103,7 @@ extension AnalyticsPromptType { } } -extension AnalyticsPromptType: CaseIterable { - static var allCases: [AnalyticsPromptType] { - let strings = MockAnalyticsPromptStrings() - return [ - .newUser(termsString: strings.termsNewUser), - .upgrade(termsString: strings.termsUpgrade) - ] - } -} +extension AnalyticsPromptType: CaseIterable { } extension AnalyticsPromptType: Identifiable { var id: String { diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift index 6e107b62b..32884fea0 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptCoordinator.swift @@ -52,9 +52,9 @@ final class AnalyticsPromptCoordinator: Coordinator, Presentable { let promptType: AnalyticsPromptType if Analytics.shared.promptShouldDisplayUpgradeMessage { - promptType = .upgrade(termsString: strings.termsUpgrade) + promptType = .upgrade } else { - promptType = .newUser(termsString: strings.termsNewUser) + promptType = .newUser } let viewModel = AnalyticsPromptViewModel(promptType: promptType, strings: strings, termsURL: BuildSettings.analyticsTermsURL) diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift index 4ce8ab20d..cc653f6d5 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/Coordinator/AnalyticsPromptStrings.swift @@ -18,16 +18,7 @@ import Foundation @available(iOS 14.0, *) struct AnalyticsPromptStrings: AnalyticsPromptStringsProtocol { - let appDisplayName = AppInfo.current.displayName - let point1 = HTMLFormatter().formatHTML(VectorL10n.analyticsPromptPoint1, withAllowedTags: ["b", "p"], fontSize: UIFont.systemFontSize) let point2 = HTMLFormatter().formatHTML(VectorL10n.analyticsPromptPoint2, withAllowedTags: ["b", "p"], fontSize: UIFont.systemFontSize) - - let termsNewUser = HTMLFormatter().format(VectorL10n.analyticsPromptTermsNewUser("%@"), - with: VectorL10n.analyticsPromptTermsLinkNewUser, - using: BuildSettings.analyticsTermsURL) - let termsUpgrade = HTMLFormatter().format(VectorL10n.analyticsPromptTermsUpgrade("%@"), - with: VectorL10n.analyticsPromptTermsLinkUpgrade, - using: BuildSettings.analyticsTermsURL) } diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift index ee0e59ed0..37a38e32d 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/MockAnalyticsPromptStrings.swift @@ -17,14 +17,9 @@ import UIKit struct MockAnalyticsPromptStrings: AnalyticsPromptStringsProtocol { - var appDisplayName = "Element" - let point1: NSAttributedString let point2: NSAttributedString - let termsNewUser: NSAttributedString - let termsUpgrade: NSAttributedString - let shortString = NSAttributedString(string: "This is a short string.") let longString = NSAttributedString(string: "This is a very long string that will be used to test the layout over multiple lines of text to ensure everything is correct.") @@ -38,15 +33,5 @@ struct MockAnalyticsPromptStrings: AnalyticsPromptStringsProtocol { point2.append(NSAttributedString(string: "don't", attributes: [.font: UIFont.boldSystemFont(ofSize: UIFont.systemFontSize)])) point2.append(NSAttributedString(string: " share information with third parties")) self.point2 = point2 - - let termsNewUser = NSMutableAttributedString(string: "You can read all our terms ") - termsNewUser.append(NSAttributedString(string: "here", attributes: [.link: URL(string: "https://element.io/cookie-policy")!])) - termsNewUser.append(NSAttributedString(string: ".")) - self.termsNewUser = termsNewUser - - let termsUpgrade = NSMutableAttributedString(string: "Read all our terms ") - termsUpgrade.append(NSAttributedString(string: "here", attributes: [.link: URL(string: "https://element.io/cookie-policy")!])) - termsUpgrade.append(NSAttributedString(string: ". Is that OK?")) - self.termsUpgrade = termsUpgrade } } diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift index 5e622ab5d..178d1d215 100644 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift +++ b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPrompt.swift @@ -42,12 +42,10 @@ struct AnalyticsPrompt: View { VStack { Text("\(viewModel.viewState.promptType.message)\n") - AnalyticsPromptTermsText(attributedString: viewModel.viewState.promptType.termsStrings) - .accessibilityLabel(Text(viewModel.viewState.promptType.termsStrings.string)) - .accessibilityValue(Text(VectorL10n.accessibilityButtonLabel)) - .onTapGesture { - viewModel.send(viewAction: .openTermsURL) - } + InlineTextButton(viewModel.viewState.promptType.mainTermsString, + tappableText: viewModel.viewState.promptType.termsLinkString) { + viewModel.send(viewAction: .openTermsURL) + } } } @@ -71,7 +69,7 @@ struct AnalyticsPrompt: View { Image(uiImage: Asset.Images.analyticsLogo.image) .padding(.bottom, 25) - Text(VectorL10n.analyticsPromptTitle(viewModel.viewState.strings.appDisplayName)) + Text(VectorL10n.analyticsPromptTitle(AppInfo.current.displayName)) .font(theme.fonts.title2B) .foregroundColor(theme.colors.primaryContent) .padding(.bottom, 2) @@ -125,6 +123,7 @@ struct AnalyticsPrompt: View { .padding(.bottom, geometry.safeAreaInsets.bottom > 0 ? 0 : 16) } .background(theme.colors.background.ignoresSafeArea()) + .accentColor(theme.colors.accent) } } } diff --git a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptTermsText.swift b/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptTermsText.swift deleted file mode 100644 index 7616e1084..000000000 --- a/RiotSwiftUI/Modules/AnalyticsPrompt/View/AnalyticsPromptTermsText.swift +++ /dev/null @@ -1,74 +0,0 @@ -// -// Copyright 2021 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 SwiftUI - -@available(iOS 14.0, *) -/// The last line of text in the description with highlighting on the link string. -struct AnalyticsPromptTermsText: View { - - // MARK: - Properties - - // MARK: Private - - @Environment(\.theme) private var theme - - /// A string with a link attribute. - private struct StringComponent { - let string: String - let isLink: Bool - } - - /// Internal representation of the string as composable parts. - private let components: [StringComponent] - - // MARK: - Setup - - init(attributedString: NSAttributedString) { - var components = [StringComponent]() - let range = NSRange(location: 0, length: attributedString.length) - let string = attributedString.string as NSString - - attributedString.enumerateAttributes(in: range, options: []) { attributes, range, stop in - let isLink = attributes.keys.contains(.link) - components.append(StringComponent(string: string.substring(with: range), isLink: isLink)) - } - - self.components = components - } - - // MARK: - Views - - var body: some View { - components.reduce(Text("")) { - $0 + Text($1.string).foregroundColor($1.isLink ? theme.colors.accent : nil) - } - } -} - -// MARK: - Previews -@available(iOS 14.0, *) -struct AnalyticsPromptTermsText_Previews: PreviewProvider { - - static let strings = MockAnalyticsPromptStrings() - - static var previews: some View { - VStack(spacing: 8) { - AnalyticsPromptTermsText(attributedString: strings.termsNewUser) - AnalyticsPromptTermsText(attributedString: strings.termsUpgrade) - } - } -} diff --git a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift index bf139307f..e2d3d4816 100644 --- a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift +++ b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift @@ -20,6 +20,7 @@ import Foundation @available(iOS 14.0, *) enum MockAppScreens { static let appScreens: [MockScreenState.Type] = [ + MockOnboardingUseCaseScreenState.self, MockOnboardingSplashScreenScreenState.self, MockLocationSharingScreenState.self, MockAnalyticsPromptScreenState.self, diff --git a/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift b/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift new file mode 100644 index 000000000..a2208bdc0 --- /dev/null +++ b/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift @@ -0,0 +1,89 @@ +// +// Copyright 2021 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 SwiftUI + +@available(iOS, introduced: 14.0, deprecated: 15.0, message: "Use Text with an AttributedString instead that includes a link and handle the tap by adding an OpenURLAction to the environment.") +/// A `Button`, that fakes having a tappable string inside of a regular string. +struct InlineTextButton: View { + + struct StringComponent { + let string: Substring + let isTinted: Bool + } + + // MARK: - Properties + + // MARK: Private + + /// The individual components of the string. + private let components: [StringComponent] + private let action: () -> Void + + + // MARK: - Setup + + /// Creates a new `InlineTextButton`. + /// - Parameters: + /// - mainText: The main text that shouldn't appear tappable. This must contain a single `%@` placeholder somewhere within. + /// - tappableText: The tappable text that will be substituted into the `%@` placeholder. + /// - action: The action to perform when tapping the button. + internal init(_ mainText: String, tappableText: String, action: @escaping () -> Void) { + guard let range = mainText.range(of: "%@") else { + self.components = [StringComponent(string: Substring(mainText), isTinted: false)] + self.action = action + return + } + + let firstComponent = StringComponent(string: mainText[.. some View { + components.reduce(Text("")) { lastValue, component in + lastValue + Text(component.string) + .foregroundColor(component.isTinted ? .accentColor.opacity(configuration.isPressed ? 0.2 : 1) : nil) + } + } + } +} + +@available(iOS 14.0, *) +struct Previews_InlineButtonText_Previews: PreviewProvider { + static var previews: some View { + InlineTextButton("Hello there this is a sentence. %@.", + tappableText: "And this is a button", + action: { }) + .padding() + } +} diff --git a/RiotSwiftUI/Modules/Common/Util/StyledText.swift b/RiotSwiftUI/Modules/Common/Util/StyledText.swift new file mode 100644 index 000000000..fbb7919f2 --- /dev/null +++ b/RiotSwiftUI/Modules/Common/Util/StyledText.swift @@ -0,0 +1,126 @@ +// +// Copyright 2021 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 SwiftUI +import DesignKit + +@available(iOS, introduced: 14.0, deprecated: 15.0, message: "Use Text with an AttributedString instead.") +/// A `Text` view that renders attributed strings with their `.font` and `.foregroundColor` attributes. +/// This view is a workaround for iOS 13/14 not supporting `AttributedString`. +struct StyledText: View { + + // MARK: - Properties + + // MARK: Private + + @Environment(\.theme) private var theme + + /// A string with a bold property. + private struct StringComponent { + let string: String + var font: Font? = nil + var color: Color? = nil + } + + /// Internal representation of the string as composable parts. + private let components: [StringComponent] + + // MARK: - Setup + + /// Creates a `StyledText` using the supplied attributed string. + /// - Parameter attributedString: The attributed string to display. + init(_ attributedString: NSAttributedString) { + var components = [StringComponent]() + let range = NSRange(location: 0, length: attributedString.length) + let string = attributedString.string as NSString + + attributedString.enumerateAttributes(in: range, options: []) { attributes, range, stop in + let font = attributes[.font] as? UIFont + let color = attributes[.foregroundColor] as? UIColor + + let component = StringComponent( + string: string.substring(with: range), + font: font.map { Font($0) }, + color: color.map { Color($0) } + ) + + components.append(component) + } + + self.components = components + } + + /// Creates a `StyledText` using a plain string. + /// - Parameter string: The plain string to display + init(_ string: String) { + self.components = [StringComponent(string: string, font: nil)] + } + + // MARK: - Views + + var body: some View { + components.reduce(Text("")) { lastValue, component in + lastValue + Text(component.string) + .font(component.font) + .foregroundColor(component.color) + } + } +} + + +@available(iOS 14.0, *) +struct StyledText_Previews: PreviewProvider { + static func prettyText() -> NSAttributedString { + let string = NSMutableAttributedString(string: "T", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 12), + .foregroundColor: UIColor.red + ]) + string.append(NSAttributedString(string: "e", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 14), + .foregroundColor: UIColor.orange + ])) + string.append(NSAttributedString(string: "s", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 13), + .foregroundColor: UIColor.yellow + ])) + string.append(NSAttributedString(string: "t", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 15), + .foregroundColor: UIColor.green + ])) + string.append(NSAttributedString(string: "i", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 11), + .foregroundColor: UIColor.cyan + ])) + string.append(NSAttributedString(string: "n", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 16), + .foregroundColor: UIColor.blue + ])) + string.append(NSAttributedString(string: "g", attributes: [ + .font: UIFont.boldSystemFont(ofSize: 14), + .foregroundColor: UIColor.purple + ])) + return string + } + + static var previews: some View { + VStack(spacing: 8) { + StyledText("Hello, World!") + StyledText(NSAttributedString(string: "Testing", + attributes: [.font: UIFont.boldSystemFont(ofSize: 64)])) + StyledText(prettyText()) + } + } +} diff --git a/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift new file mode 100644 index 000000000..73a591d86 --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/Common/OnboardingButtonStyle.swift @@ -0,0 +1,32 @@ +// +// Copyright 2021 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 SwiftUI + +@available(iOS 14.0, *) +struct OnboardingButtonStyle: ButtonStyle { + @Environment(\.theme) private var theme + + func makeBody(configuration: Configuration) -> some View { + configuration.label + .frame(maxWidth: .infinity, alignment: .leading) + .background( + RoundedRectangle(cornerRadius: 8) + .stroke(configuration.isPressed ? theme.colors.accent : theme.colors.quinaryContent, lineWidth: configuration.isPressed ? 2 : 1.5) + ) + .contentShape(RoundedRectangle(cornerRadius: 8)) + } +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift new file mode 100644 index 000000000..5265c828e --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift @@ -0,0 +1,60 @@ +// +// Copyright 2021 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 SwiftUI + +final class OnboardingUseCaseCoordinator: Coordinator, Presentable { + + // MARK: - Properties + + // MARK: Private + + private let onboardingUseCaseHostingController: UIViewController + private var onboardingUseCaseViewModel: OnboardingUseCaseViewModelProtocol + + // MARK: Public + + // Must be used only internally + var childCoordinators: [Coordinator] = [] + var completion: ((OnboardingUseCaseViewModelResult) -> Void)? + + // MARK: - Setup + + @available(iOS 14.0, *) + init() { + let viewModel = OnboardingUseCaseViewModel() + let view = OnboardingUseCase(viewModel: viewModel.context) + onboardingUseCaseViewModel = viewModel + + let hostingController = VectorHostingController(rootView: view) + hostingController.vc_removeBackTitle() + onboardingUseCaseHostingController = hostingController + } + + // MARK: - Public + func start() { + MXLog.debug("[OnboardingUseCaseCoordinator] did start.") + onboardingUseCaseViewModel.completion = { [weak self] result in + MXLog.debug("[OnboardingUseCaseCoordinator] OnboardingUseCaseViewModel did complete with result: \(result).") + guard let self = self else { return } + self.completion?(result) + } + } + + func toPresentable() -> UIViewController { + return self.onboardingUseCaseHostingController + } +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift new file mode 100644 index 000000000..7cf850d9b --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift @@ -0,0 +1,52 @@ +// +// Copyright 2021 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 SwiftUI + +/// Using an enum for the screen allows you define the different state cases with +/// the relevant associated data for each case. +@available(iOS 14.0, *) +enum MockOnboardingUseCaseScreenState: MockScreenState, CaseIterable { + // A case for each state you want to represent + // with specific, minimal associated data that will allow you + // mock that screen. + case `default` + + /// The associated screen + var screenType: Any.Type { + OnboardingUseCase.self + } + + /// A list of screen state definitions + static var allCases: [MockOnboardingUseCaseScreenState] { + // Each of the presence statuses + [.default] + } + + /// Generate the view struct for the screen state. + var screenView: ([Any], AnyView) { + let viewModel = OnboardingUseCaseViewModel() + + // can simulate service and viewModel actions here if needs be. + + return ( + [self, viewModel], + AnyView(OnboardingUseCase(viewModel: viewModel.context) + .addDependency(MockAvatarService.example)) + ) + } +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift new file mode 100644 index 000000000..c67798b6d --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseModels.swift @@ -0,0 +1,41 @@ +// +// Copyright 2021 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 + +// MARK: - Coordinator + +// MARK: View model + +enum OnboardingUseCaseStateAction { + case viewAction(OnboardingUseCaseViewAction) +} + +enum OnboardingUseCaseViewModelResult { + case personalMessaging + case workMessaging + case communityMessaging + case skipped + case customServer +} + +// MARK: View + +struct OnboardingUseCaseViewState: BindableState { } + +enum OnboardingUseCaseViewAction { + case answer(OnboardingUseCaseViewModelResult) +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift new file mode 100644 index 000000000..89a4ae9f1 --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModel.swift @@ -0,0 +1,52 @@ +// +// Copyright 2021 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 SwiftUI + +@available(iOS 14, *) +typealias OnboardingUseCaseViewModelType = StateStoreViewModel +@available(iOS 14, *) +class OnboardingUseCaseViewModel: OnboardingUseCaseViewModelType, OnboardingUseCaseViewModelProtocol { + + // MARK: - Properties + + // MARK: Private + + // MARK: Public + + var completion: ((OnboardingUseCaseViewModelResult) -> Void)? + + // MARK: - Setup + + init() { + super.init(initialViewState: OnboardingUseCaseViewState()) + } + + // MARK: - Public + + override func process(viewAction: OnboardingUseCaseViewAction) { + switch viewAction { + case .answer(let result): + completion?(result) + } + } + + override class func reducer(state: inout OnboardingUseCaseViewState, action: OnboardingUseCaseStateAction) { + // There is no mutable state to reduce :) + } +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift new file mode 100644 index 000000000..0c535b36c --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/OnboardingUseCaseViewModelProtocol.swift @@ -0,0 +1,24 @@ +// +// Copyright 2021 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 OnboardingUseCaseViewModelProtocol { + + var completion: ((OnboardingUseCaseViewModelResult) -> Void)? { get set } + @available(iOS 14, *) + var context: OnboardingUseCaseViewModelType.Context { get } +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift new file mode 100644 index 000000000..0f254dfb3 --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/UI/OnboardingUseCaseUITests.swift @@ -0,0 +1,23 @@ +// +// Copyright 2021 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 XCTest +import RiotSwiftUI + +@available(iOS 14.0, *) +class OnboardingUseCaseUITests: MockScreenTest { + // The view has no parameters or changing state to test. +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift new file mode 100644 index 000000000..9d3883faf --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Test/Unit/OnboardingUseCaseViewModelTests.swift @@ -0,0 +1,24 @@ +// +// Copyright 2021 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 XCTest + +@testable import RiotSwiftUI + +@available(iOS 14.0, *) +class OnboardingUseCaseViewModelTests: XCTestCase { + // The view model has nothing to test. +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift new file mode 100644 index 000000000..dfa0fb21e --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift @@ -0,0 +1,132 @@ +// +// Copyright 2021 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 SwiftUI + +@available(iOS 14.0, *) +/// The screen shown to a new user to select their use case for the app. +struct OnboardingUseCase: View { + + // MARK: - Properties + + // MARK: Private + + @Environment(\.theme) private var theme + @Environment(\.horizontalSizeClass) private var horizontalSizeClass + + // MARK: Public + + @ObservedObject var viewModel: OnboardingUseCaseViewModel.Context + + /// The screen's title and instructions. + var titleContent: some View { + VStack(spacing: 8) { + Image(Asset.Images.onboardingUseCaseIcon.name) + .padding(.bottom, 8) + + Text(VectorL10n.onboardingUseCaseTitle) + .font(theme.fonts.title2B) + .foregroundColor(theme.colors.primaryContent) + + Text(VectorL10n.onboardingUseCaseMessage) + .font(theme.fonts.body) + .foregroundColor(theme.colors.secondaryContent) + } + } + + /// The buttons used to select a use case for the app. + var useCaseButtons: some View { + VStack(spacing: 8) { + OnboardingUseCaseButton(title: VectorL10n.onboardingUseCasePersonalMessaging, + image: theme.isDark ? Asset.Images.onboardingUseCasePersonalDark : Asset.Images.onboardingUseCasePersonal) { + viewModel.send(viewAction: .answer(.personalMessaging)) + } + + OnboardingUseCaseButton(title: VectorL10n.onboardingUseCaseWorkMessaging, + image: theme.isDark ? Asset.Images.onboardingUseCaseWorkDark : Asset.Images.onboardingUseCaseWork) { + viewModel.send(viewAction: .answer(.workMessaging)) + } + + OnboardingUseCaseButton(title: VectorL10n.onboardingUseCaseCommunityMessaging, + image: theme.isDark ? Asset.Images.onboardingUseCaseCommunityDark : Asset.Images.onboardingUseCaseCommunity) { + viewModel.send(viewAction: .answer(.communityMessaging)) + } + + InlineTextButton(VectorL10n.onboardingUseCaseNotSureYet("%@"), + tappableText: VectorL10n.onboardingUseCaseSkipButton) { + viewModel.send(viewAction: .answer(.skipped)) + } + .font(theme.fonts.subheadline) + .foregroundColor(theme.colors.tertiaryContent) + .padding(.top, 8) + } + } + + /// A footer showing a button to connect to a server. + var serverFooter: some View { + VStack(spacing: 14) { + Text(VectorL10n.onboardingUseCaseExistingServerMessage) + .font(theme.fonts.subheadline) + .foregroundColor(theme.colors.tertiaryContent) + + Button { viewModel.send(viewAction: .answer(.customServer)) } label: { + Text(VectorL10n.onboardingUseCaseExistingServerButton) + .font(theme.fonts.body) + } + } + } + + var body: some View { + GeometryReader { geometry in + VStack { + ScrollView { + VStack(spacing: 0) { + titleContent + .padding(.bottom, 36) + + useCaseButtons + } + .frame(maxWidth: OnboardingConstants.maxContentWidth, + maxHeight: OnboardingConstants.maxContentHeight) + .padding(.horizontal, 16) + .padding(.top, 48) + .padding(.bottom, 16) + } + .frame(maxWidth: .infinity) + + serverFooter + .padding(.horizontal, 16) + .padding(.bottom, geometry.safeAreaInsets.bottom > 0 ? 20 : 36) + } + } + .background(theme.colors.background.ignoresSafeArea()) + .accentColor(theme.colors.accent) + } +} + +// MARK: - Previews + +@available(iOS 14.0, *) +struct OnboardingUseCase_Previews: PreviewProvider { + static let stateRenderer = MockOnboardingUseCaseScreenState.stateRenderer + static var previews: some View { + NavigationView { + stateRenderer.screenGroup() + .navigationBarTitleDisplayMode(.inline) + } + .navigationViewStyle(StackNavigationViewStyle()) + } +} diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift new file mode 100644 index 000000000..0fedfedb0 --- /dev/null +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseButton.swift @@ -0,0 +1,59 @@ +// +// Copyright 2021 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 SwiftUI + +@available(iOS 14.0, *) +/// A button used for the Use Case selection. +struct OnboardingUseCaseButton: View { + + // MARK: Private + + @Environment(\.theme) private var theme + + // MARK: Public + + /// The button's title. + let title: String + /// The button's image. + let image: ImageAsset + + /// The button's action when tapped. + let action: () -> Void + + var body: some View { + Button(action: action) { + HStack(spacing: 16) { + Image(image.name) + Text(title) + .font(theme.fonts.bodySB) + .foregroundColor(theme.colors.primaryContent) + } + .padding(16) + } + .buttonStyle(OnboardingButtonStyle()) + } +} + +@available(iOS 14.0, *) +struct Previews_OnboardingUseCaseButton_Previews: PreviewProvider { + static var previews: some View { + OnboardingUseCaseButton(title: VectorL10n.onboardingUseCaseWorkMessaging, + image: Asset.Images.onboardingUseCaseWork, + action: { }) + .padding(16) + } +} diff --git a/RiotTests/OnboardingTests.swift b/RiotTests/OnboardingTests.swift new file mode 100644 index 000000000..090bae3d0 --- /dev/null +++ b/RiotTests/OnboardingTests.swift @@ -0,0 +1,87 @@ +// +// Copyright 2021 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 XCTest +@testable import Riot + +class OnboardingTests: XCTestCase { + + let userId = "@test:matrix.org" + + override func setUp() { + // Clear any properties for the test + UserSessionProperties(userId: userId).delete() + } + + func testEmptyUseCase() { + // Given an empty set of user properties + let properties = UserSessionProperties(userId: userId) + + // Then the use case property should return nil + XCTAssertNil(properties.useCase, "A use case has not been set") + } + + func testPersonalMessagingUseCase() { + // Given an empty set of user properties + let properties = UserSessionProperties(userId: userId) + + // When storing a use case result of personal messaging + let result = OnboardingUseCaseViewModelResult.personalMessaging + properties.store(useCaseResult: result) + + // Then the use case property should return personal messaging + XCTAssertEqual(properties.useCase, .personalMessaging, "The use case should be Personal Messaging") + } + + func testSkippedUseCase() { + // Given an empty set of user properties + let properties = UserSessionProperties(userId: userId) + + // When storing a skipped use case result + let result = OnboardingUseCaseViewModelResult.skipped + properties.store(useCaseResult: result) + + // Then the use case property should return skipped + XCTAssertEqual(properties.useCase, .skipped) + } + + func testCustomServerUseCase() { + // Given an empty set of user properties + let properties = UserSessionProperties(userId: userId) + + // When storing a custom server case result + let result = OnboardingUseCaseViewModelResult.customServer + properties.store(useCaseResult: result) + + // Then the use case property should return nil + XCTAssertNil(properties.useCase) + } + + func testUseCaseAfterDeletingProperties() { + // Given a set of user properties with the Work Messaging use case + let properties = UserSessionProperties(userId: userId) + let result = OnboardingUseCaseViewModelResult.workMessaging + properties.store(useCaseResult: result) + XCTAssertEqual(properties.useCase, .workMessaging, "The use case should be Work Messaging") + + // When deleting the user properties + properties.delete() + + // Then the use case property should return nil + XCTAssertNil(properties.useCase) + } + +} diff --git a/SiriIntents/target.yml b/SiriIntents/target.yml index ca60c3bc1..ddb51c5eb 100644 --- a/SiriIntents/target.yml +++ b/SiriIntents/target.yml @@ -52,6 +52,7 @@ targets: - path: ../Riot/Managers/Locale/LocaleProvider.swift - path: ../Riot/Modules/MatrixKit - path: ../Riot/Modules/Analytics + - path: ../Riot/Managers/UserSessions - path: ../Riot/Managers/AppInfo/ - path: ../Riot/Managers/Locale/LocaleProviderType.swift - path: ../Riot/Generated/Strings.swift diff --git a/changelog.d/5160.feature b/changelog.d/5160.feature new file mode 100644 index 000000000..2d567e205 --- /dev/null +++ b/changelog.d/5160.feature @@ -0,0 +1 @@ +Add Onboarding Use Case selection screen after the splash screen. From 9dd22024a1c0fcb9b43f92941fa17e9a2698f0da Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 4 Feb 2022 16:10:03 +0000 Subject: [PATCH 005/188] Tweaks to the Use Case screen ready for review. Update strings. Show the custom server field as needed. Enable scroll edges appearance for white navigation bar. --- Riot/Assets/en.lproj/Vector.strings | 4 ++-- Riot/Generated/Strings.swift | 4 ++-- Riot/Managers/Theme/Theme.swift | 9 ++++++- Riot/Managers/Theme/Themes/DarkTheme.swift | 24 ++++++++++++------- Riot/Managers/Theme/Themes/DefaultTheme.swift | 16 +++++++++---- .../AuthenticationCoordinator.swift | 4 ++++ .../AuthenticationCoordinatorProtocol.swift | 3 +++ .../AuthenticationViewController.h | 4 ++++ .../AuthenticationViewController.m | 3 ++- .../SwiftUI/VectorHostingController.swift | 6 ++++- .../Onboarding/OnboardingCoordinator.swift | 16 +++++++++---- .../View/OnboardingSplashScreenPage.swift | 1 + .../OnboardingUseCaseCoordinator.swift | 1 + .../UseCase/View/OnboardingUseCase.swift | 5 ++-- 14 files changed, 73 insertions(+), 27 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index f7ee5c0ca..4b6cb9383 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -96,8 +96,8 @@ "onboarding_use_case_title" = "Who will you chat to the most?"; "onboarding_use_case_message" = "We’ll help you get connected."; "onboarding_use_case_personal_messaging" = "Friends and family"; -"onboarding_use_case_work_messaging" = "Coworkers and teams"; -"onboarding_use_case_community_messaging" = "Online community members"; +"onboarding_use_case_work_messaging" = "Teams"; +"onboarding_use_case_community_messaging" = "Communities"; /* The placeholder string contains onboarding_use_case_skip_button as a tappable action */ "onboarding_use_case_not_sure_yet" = "Not sure yet? You can %@"; "onboarding_use_case_skip_button" = "skip this question"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index ea3ecab07..840b7c7e9 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2443,7 +2443,7 @@ public class VectorL10n: NSObject { public static var onboardingSplashRegisterButtonTitle: String { return VectorL10n.tr("Vector", "onboarding_splash_register_button_title") } - /// Online community members + /// Communities public static var onboardingUseCaseCommunityMessaging: String { return VectorL10n.tr("Vector", "onboarding_use_case_community_messaging") } @@ -2475,7 +2475,7 @@ public class VectorL10n: NSObject { public static var onboardingUseCaseTitle: String { return VectorL10n.tr("Vector", "onboarding_use_case_title") } - /// Coworkers and teams + /// Teams public static var onboardingUseCaseWorkMessaging: String { return VectorL10n.tr("Vector", "onboarding_use_case_work_messaging") } diff --git a/Riot/Managers/Theme/Theme.swift b/Riot/Managers/Theme/Theme.swift index 2418cc967..f8e0a382d 100644 --- a/Riot/Managers/Theme/Theme.swift +++ b/Riot/Managers/Theme/Theme.swift @@ -112,11 +112,18 @@ import DesignKit /// - Parameter tabBar: The tab bar to customise. func applyStyle(onTabBar tabBar: UITabBar) - /// Apply the theme on a navigation bar. + /// Apply the theme on a navigation bar, without enabling the iOS 15's scroll edges appearance. /// /// - Parameter navigationBar: the navigation bar to customise. func applyStyle(onNavigationBar navigationBar: UINavigationBar) + /// Apply the theme on a navigation bar. + /// + /// - Parameter navigationBar: the navigation bar to customise. + /// - Parameter modernScrollEdgesAppearance: whether or not to use the iOS 15 style scroll edges appearance + func applyStyle(onNavigationBar navigationBar: UINavigationBar, + withModernScrollEdgesAppearance modernScrollEdgesAppearance: Bool) + /// Apply the theme on a search bar. /// /// - Parameter searchBar: the search bar to customise. diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index ebac661c8..c24201cca 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -112,28 +112,36 @@ class DarkTheme: NSObject, Theme { } } - // Note: We are not using UINavigationBarAppearance on iOS 13/14 because of UINavigationBar directly including UISearchBar on their titleView that cause crop issues with UINavigationController pop. + // Protocols don't support default parameter values and a protocol extension won't work for @objc func applyStyle(onNavigationBar navigationBar: UINavigationBar) { - navigationBar.tintColor = self.tintColor + applyStyle(onNavigationBar: navigationBar, withModernScrollEdgesAppearance: false) + } + + // Note: We are not using UINavigationBarAppearance on iOS 13/14 because of UINavigationBar directly including UISearchBar on their titleView that cause crop issues with UINavigationController pop. + func applyStyle(onNavigationBar navigationBar: UINavigationBar, + withModernScrollEdgesAppearance modernScrollEdgesAppearance: Bool) { + navigationBar.tintColor = tintColor // On iOS 15 use UINavigationBarAppearance to fix visual issues with the scrollEdgeAppearance style. if #available(iOS 15.0, *) { let appearance = UINavigationBarAppearance() appearance.configureWithOpaqueBackground() - appearance.backgroundColor = self.baseColor - appearance.shadowColor = nil + appearance.backgroundColor = baseColor + if !modernScrollEdgesAppearance { + appearance.shadowColor = nil + } appearance.titleTextAttributes = [ - NSAttributedString.Key.foregroundColor: self.textPrimaryColor + NSAttributedString.Key.foregroundColor: textPrimaryColor ] navigationBar.standardAppearance = appearance - navigationBar.scrollEdgeAppearance = appearance + navigationBar.scrollEdgeAppearance = modernScrollEdgesAppearance ? nil : appearance } else { navigationBar.titleTextAttributes = [ - NSAttributedString.Key.foregroundColor: self.textPrimaryColor + NSAttributedString.Key.foregroundColor: textPrimaryColor ] - navigationBar.barTintColor = self.baseColor + navigationBar.barTintColor = baseColor navigationBar.shadowImage = UIImage() // Remove bottom shadow // The navigation bar needs to be opaque so that its background color is the expected one diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index 2be798d23..a2fe37492 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -118,9 +118,15 @@ class DefaultTheme: NSObject, Theme { } } - // Note: We are not using UINavigationBarAppearance on iOS 13/14 because of UINavigationBar directly including UISearchBar on their titleView that cause crop issues with UINavigationController pop. + // Protocols don't support default parameter values and a protocol extension doesn't work for @objc func applyStyle(onNavigationBar navigationBar: UINavigationBar) { - navigationBar.tintColor = self.tintColor + applyStyle(onNavigationBar: navigationBar, withModernScrollEdgesAppearance: false) + } + + // Note: We are not using UINavigationBarAppearance on iOS 13/14 because of UINavigationBar directly including UISearchBar on their titleView that cause crop issues with UINavigationController pop. + func applyStyle(onNavigationBar navigationBar: UINavigationBar, + withModernScrollEdgesAppearance modernScrollEdgesAppearance: Bool) { + navigationBar.tintColor = tintColor // On iOS 15 use UINavigationBarAppearance to fix visual issues with the scrollEdgeAppearance style. if #available(iOS 15.0, *) { @@ -128,13 +134,15 @@ class DefaultTheme: NSObject, Theme { appearance.configureWithOpaqueBackground() appearance.backgroundColor = baseColor - appearance.shadowColor = nil + if !modernScrollEdgesAppearance { + appearance.shadowColor = nil + } appearance.titleTextAttributes = [ NSAttributedString.Key.foregroundColor: textPrimaryColor ] navigationBar.standardAppearance = appearance - navigationBar.scrollEdgeAppearance = appearance + navigationBar.scrollEdgeAppearance = modernScrollEdgesAppearance ? nil : appearance } else { navigationBar.titleTextAttributes = [ NSAttributedString.Key.foregroundColor: textPrimaryColor diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift index 521ad52c2..9cdb59ddb 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift @@ -62,6 +62,10 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc authenticationViewController.authType = authenticationType } + func showCustomServer() { + authenticationViewController.hideCustomServers(false) + } + func update(externalRegistrationParameters: [AnyHashable: Any]) { authenticationViewController.externalRegistrationParameters = externalRegistrationParameters } diff --git a/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift b/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift index c90c212a5..14a3d1186 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift @@ -25,6 +25,9 @@ protocol AuthenticationCoordinatorProtocol: Coordinator, Presentable { /// Update the screen to display registration or login. func update(authenticationType: MXKAuthenticationType) + /// Enable the custom server checkbox to allow the user to enter a homeserver URL. + func showCustomServer() + /// Force a registration process based on a predefined set of parameters from a server provisioning link. /// For more information see `AuthenticationViewController.externalRegistrationParameters`. func update(externalRegistrationParameters: [AnyHashable: Any]) diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index 894ea8b45..6d412400f 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -54,6 +54,10 @@ /// returns YES if the SSO login can be continued. - (BOOL)continueSSOLoginWithToken:(NSString*)loginToken txnId:(NSString*)txnId; +/// Hides/shows the custom homeserver field. +/// @param hidden YES to hide, NO to show. +- (void)hideCustomServers:(BOOL)hidden; + @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 4f76a029b..5579bc416 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -214,7 +214,8 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; - (void)userInterfaceThemeDidChange { - [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar]; + [ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar + withModernScrollEdgesAppearance:YES]; self.view.backgroundColor = ThemeService.shared.theme.backgroundColor; diff --git a/Riot/Modules/Common/SwiftUI/VectorHostingController.swift b/Riot/Modules/Common/SwiftUI/VectorHostingController.swift index 677780e4f..8afaaa060 100644 --- a/Riot/Modules/Common/SwiftUI/VectorHostingController.swift +++ b/Riot/Modules/Common/SwiftUI/VectorHostingController.swift @@ -28,6 +28,10 @@ class VectorHostingController: UIHostingController { private var theme: Theme + // MARK: Public + + var enableNavigationBarScrollEdgesAppearance = false + init(rootView: Content) where Content: View { self.theme = ThemeService.shared().theme super.init(rootView: AnyView(rootView.vectorContent())) @@ -67,7 +71,7 @@ class VectorHostingController: UIHostingController { private func update(theme: Theme) { if let navigationBar = self.navigationController?.navigationBar { - theme.applyStyle(onNavigationBar: navigationBar) + theme.applyStyle(onNavigationBar: navigationBar, withModernScrollEdgesAppearance: enableNavigationBarScrollEdgesAppearance) } } } diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index b14707c13..3dd2e3e5c 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -132,6 +132,10 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { private func splashScreenCoordinator(_ coordinator: OnboardingSplashScreenCoordinator, didCompleteWith result: OnboardingSplashScreenViewModelResult) { splashScreenResult = result + // Set the auth type early to allow network requests to finish during display of the use case screen. + let mxkAuthenticationType = splashScreenResult == .register ? MXKAuthenticationTypeRegister : MXKAuthenticationTypeLogin + authenticationCoordinator.update(authenticationType: mxkAuthenticationType) + switch result { case .register: showUseCase() @@ -182,13 +186,14 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { // Due to needing to preload the authVC, this breaks the Coordinator init/start pattern. // This can be re-assessed once we re-write a native flow for authentication. - // Set authType first as registration parameters or soft logout credentials will modify this. - let mxkAuthenticationType = splashScreenResult == .register ? MXKAuthenticationTypeRegister : MXKAuthenticationTypeLogin - coordinator.update(authenticationType: mxkAuthenticationType) - if let externalRegistrationParameters = externalRegistrationParameters { coordinator.update(externalRegistrationParameters: externalRegistrationParameters) } + + if useCaseResult == .customServer { + coordinator.showCustomServer() + } + if let softLogoutCredentials = parameters.softLogoutCredentials { coordinator.update(softLogoutCredentials: softLogoutCredentials) } @@ -217,10 +222,11 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { completion?() isShowingAuthentication = false - // Store the chosen use case when appropriate for any default configuration and, if opted in, for analytics. + // Handle the chosen use case if appropriate if authenticationType == MXKAuthenticationTypeRegister, let useCaseResult = useCaseResult, let userSession = UserSessionsService.shared.mainUserSession { + // Store the value in the user's session userSession.properties.useCase = useCaseResult.userSessionPropertyValue } } diff --git a/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift b/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift index 53a71d301..9ec08b950 100644 --- a/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift +++ b/RiotSwiftUI/Modules/Onboarding/SplashScreen/View/OnboardingSplashScreenPage.swift @@ -48,6 +48,7 @@ struct OnboardingSplashScreenPage: View { .scaledToFit() .frame(maxWidth: 300) .padding(20) + .accessibilityHidden(true) VStack(spacing: 8) { OnboardingSplashScreenTitleText(content.title) diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift index 5265c828e..f91c79861 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift @@ -41,6 +41,7 @@ final class OnboardingUseCaseCoordinator: Coordinator, Presentable { let hostingController = VectorHostingController(rootView: view) hostingController.vc_removeBackTitle() + hostingController.enableNavigationBarScrollEdgesAppearance = true onboardingUseCaseHostingController = hostingController } diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift index dfa0fb21e..5431ebd16 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift @@ -36,6 +36,7 @@ struct OnboardingUseCase: View { VStack(spacing: 8) { Image(Asset.Images.onboardingUseCaseIcon.name) .padding(.bottom, 8) + .accessibilityHidden(true) Text(VectorL10n.onboardingUseCaseTitle) .font(theme.fonts.title2B) @@ -101,9 +102,7 @@ struct OnboardingUseCase: View { } .frame(maxWidth: OnboardingConstants.maxContentWidth, maxHeight: OnboardingConstants.maxContentHeight) - .padding(.horizontal, 16) - .padding(.top, 48) - .padding(.bottom, 16) + .padding(16) } .frame(maxWidth: .infinity) From 4d00cceb488434d064c787ad787faf2fd2017a04 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 4 Feb 2022 17:46:27 +0000 Subject: [PATCH 006/188] Fix tests. --- .../UserSessions/UserSessionProperties.swift | 2 +- .../Analytics/PostHogAnalyticsClient.swift | 2 +- .../Common/Util/InlineTextButton.swift | 4 ++-- .../UseCase/View/OnboardingUseCase.swift | 1 - RiotTests/OnboardingTests.swift | 23 +++++++++++++++---- 5 files changed, 23 insertions(+), 9 deletions(-) diff --git a/Riot/Managers/UserSessions/UserSessionProperties.swift b/Riot/Managers/UserSessions/UserSessionProperties.swift index d7f4b31df..e637aa3fc 100644 --- a/Riot/Managers/UserSessions/UserSessionProperties.swift +++ b/Riot/Managers/UserSessions/UserSessionProperties.swift @@ -34,7 +34,7 @@ class UserSessionProperties: NSObject { /// The underlying dictionary that stores the properties in user defaults. private var dictionary: [String: Any] { didSet { - UserDefaults(suiteName: Constants.suiteName)?.dictionary(forKey: userId) + UserDefaults(suiteName: Constants.suiteName)?.set(dictionary, forKey: userId) } } diff --git a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift index f6db52f36..1c7172112 100644 --- a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift +++ b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift @@ -36,7 +36,7 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { } func identify(id: String) { - postHog?.identify(id, properties: nil) + postHog?.identify(id) } func reset() { diff --git a/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift b/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift index a2208bdc0..1b1924b0b 100644 --- a/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift +++ b/RiotSwiftUI/Modules/Common/Util/InlineTextButton.swift @@ -20,7 +20,7 @@ import SwiftUI /// A `Button`, that fakes having a tappable string inside of a regular string. struct InlineTextButton: View { - struct StringComponent { + private struct StringComponent { let string: Substring let isTinted: Bool } @@ -66,7 +66,7 @@ struct InlineTextButton: View { .accessibilityLabel(components.map { $0.string }.joined()) } - struct Style: ButtonStyle { + private struct Style: ButtonStyle { let components: [StringComponent] func makeBody(configuration: Configuration) -> some View { diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift index 5431ebd16..f0f0ad403 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift @@ -25,7 +25,6 @@ struct OnboardingUseCase: View { // MARK: Private @Environment(\.theme) private var theme - @Environment(\.horizontalSizeClass) private var horizontalSizeClass // MARK: Public diff --git a/RiotTests/OnboardingTests.swift b/RiotTests/OnboardingTests.swift index 090bae3d0..4c43fd0bd 100644 --- a/RiotTests/OnboardingTests.swift +++ b/RiotTests/OnboardingTests.swift @@ -40,7 +40,7 @@ class OnboardingTests: XCTestCase { // When storing a use case result of personal messaging let result = OnboardingUseCaseViewModelResult.personalMessaging - properties.store(useCaseResult: result) + properties.useCase = result.userSessionPropertyValue // Then the use case property should return personal messaging XCTAssertEqual(properties.useCase, .personalMessaging, "The use case should be Personal Messaging") @@ -52,7 +52,7 @@ class OnboardingTests: XCTestCase { // When storing a skipped use case result let result = OnboardingUseCaseViewModelResult.skipped - properties.store(useCaseResult: result) + properties.useCase = result.userSessionPropertyValue // Then the use case property should return skipped XCTAssertEqual(properties.useCase, .skipped) @@ -64,7 +64,7 @@ class OnboardingTests: XCTestCase { // When storing a custom server case result let result = OnboardingUseCaseViewModelResult.customServer - properties.store(useCaseResult: result) + properties.useCase = result.userSessionPropertyValue // Then the use case property should return nil XCTAssertNil(properties.useCase) @@ -74,7 +74,7 @@ class OnboardingTests: XCTestCase { // Given a set of user properties with the Work Messaging use case let properties = UserSessionProperties(userId: userId) let result = OnboardingUseCaseViewModelResult.workMessaging - properties.store(useCaseResult: result) + properties.useCase = result.userSessionPropertyValue XCTAssertEqual(properties.useCase, .workMessaging, "The use case should be Work Messaging") // When deleting the user properties @@ -84,4 +84,19 @@ class OnboardingTests: XCTestCase { XCTAssertNil(properties.useCase) } + func testUseCasePersistence() { + // Given a set of user properties with the Personal Messaging use case + var properties: UserSessionProperties? = UserSessionProperties(userId: userId) + let result = OnboardingUseCaseViewModelResult.personalMessaging + properties?.useCase = result.userSessionPropertyValue + XCTAssertEqual(properties?.useCase, .personalMessaging, "The use case should be Personal Messaging") + + // When the app is relaunched and a new user properties instance is creates + properties = nil + let newProperties = UserSessionProperties(userId: userId) + + // Then the use case property should still return Personal Messaging + XCTAssertEqual(newProperties.useCase, .personalMessaging, "The use case should be Personal Messaging") + } + } From 3b3d4189b20f80a8e4bef7ce1a3ea61ee0c8b0cb Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Sun, 6 Feb 2022 21:06:58 +0000 Subject: [PATCH 007/188] Make registration spec compliant (fixes registration on Conduit) Web PR: https://github.com/matrix-org/matrix-react-sdk/pull/4347 Signed-off-by: Aaron Raimist --- .../MatrixKit/Controllers/MXKAuthenticationViewController.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m index 3465c136b..7ffe37570 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m @@ -981,8 +981,7 @@ { // Trigger here a register request in order to associate the filled userId and password to the current session id // This will check the availability of the userId at the same time - NSDictionary *parameters = @{@"auth": @{}, - @"username": self.authInputsView.userId, + NSDictionary *parameters = @{@"username": self.authInputsView.userId, @"password": self.authInputsView.password, @"bind_email": @(NO), @"initial_device_display_name":self.deviceDisplayName From 8849db64c39ba8c294f965aaa68bd3ccc4e24baf Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Sun, 6 Feb 2022 21:16:15 +0000 Subject: [PATCH 008/188] Add changelog Signed-off-by: Aaron Raimist --- changelog.d/5510.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5510.bugfix diff --git a/changelog.d/5510.bugfix b/changelog.d/5510.bugfix new file mode 100644 index 000000000..a573977ac --- /dev/null +++ b/changelog.d/5510.bugfix @@ -0,0 +1 @@ +Fix registration to be compliant with the Matrix specification. This allows registering for accounts on Conduit servers. Contributed by @aaronraimist. \ No newline at end of file From 32a0a65c24d5af2e2147aac6504368ec234e2ad8 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 9 Feb 2022 18:41:45 +0000 Subject: [PATCH 009/188] Prepare for new sprint --- Config/AppVersion.xcconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Config/AppVersion.xcconfig b/Config/AppVersion.xcconfig index 64366834e..3fe634b3f 100644 --- a/Config/AppVersion.xcconfig +++ b/Config/AppVersion.xcconfig @@ -15,5 +15,5 @@ // // Version -MARKETING_VERSION = 1.8.0 -CURRENT_PROJECT_VERSION = 1.8.0 +MARKETING_VERSION = 1.8.1 +CURRENT_PROJECT_VERSION = 1.8.1 From 7737cee9fa3d8f5252fe2ba9391c9249cb214454 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 03:14:00 +0300 Subject: [PATCH 010/188] Make SectionHeaderView subclass from UITableViewHeaderFooterView --- .../Common/SectionHeaders/SectionHeaderView.h | 4 +- .../Common/SectionHeaders/SectionHeaderView.m | 69 ++++++++++++++++--- 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/Riot/Modules/Common/SectionHeaders/SectionHeaderView.h b/Riot/Modules/Common/SectionHeaders/SectionHeaderView.h index e4e37c25c..515ee86a4 100644 --- a/Riot/Modules/Common/SectionHeaders/SectionHeaderView.h +++ b/Riot/Modules/Common/SectionHeaders/SectionHeaderView.h @@ -20,7 +20,7 @@ /** Section header view class. Respects left and right safe area insets and layouts its subviews. */ -@interface SectionHeaderView : UIView +@interface SectionHeaderView : UITableViewHeaderFooterView /** Default value: 20.0 @@ -57,4 +57,6 @@ */ @property (nonatomic, strong) UIView *bottomView; ++ (NSString*)defaultReuseIdentifier; + @end diff --git a/Riot/Modules/Common/SectionHeaders/SectionHeaderView.m b/Riot/Modules/Common/SectionHeaders/SectionHeaderView.m index 855c4e2c0..54150ac8e 100644 --- a/Riot/Modules/Common/SectionHeaders/SectionHeaderView.m +++ b/Riot/Modules/Common/SectionHeaders/SectionHeaderView.m @@ -17,10 +17,17 @@ #import "SectionHeaderView.h" +#import "GeneratedInterface-Swift.h" + static const CGFloat kInterItemsSpaceHorizontal = 8.0; @implementation SectionHeaderView ++ (NSString*)defaultReuseIdentifier +{ + return NSStringFromClass([self class]); +} + - (void)setMinimumLeftInset:(CGFloat)minimumLeftInset { _minimumLeftInset = minimumLeftInset; @@ -41,25 +48,53 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0; - (void)setTopSpanningView:(UIView *)topSpanningView { + // remove old one + [_topSpanningView removeFromSuperview]; _topSpanningView = topSpanningView; + if (_topSpanningView) + { + // add new one + [self.contentView addSubview:_topSpanningView]; + } [self setNeedsLayout]; } - (void)setHeaderLabel:(UILabel *)headerLabel { + // remove old one + [_headerLabel removeFromSuperview]; _headerLabel = headerLabel; + if (_headerLabel) + { + // add new one + [self.contentView addSubview:_headerLabel]; + } [self setNeedsLayout]; } - (void)setAccessoryView:(UIView *)accessoryView { + // remove old one + [_accessoryView removeFromSuperview]; _accessoryView = accessoryView; + if (_accessoryView) + { + // add new one + [self.contentView addSubview:_accessoryView]; + } [self setNeedsLayout]; } - (void)setBottomView:(UIView *)bottomView { + // remove old one + [_bottomView removeFromSuperview]; _bottomView = bottomView; + if (_bottomView) + { + // add new one + [self.contentView addSubview:_bottomView]; + } [self setNeedsLayout]; } @@ -88,6 +123,15 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0; return self; } +- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier +{ + if (self = [super initWithReuseIdentifier:reuseIdentifier]) + { + [self setup]; + } + return self; +} + - (void)setup { _minimumLeftInset = 20; @@ -95,21 +139,24 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0; _topViewHeight = 30; } +- (void)prepareForReuse +{ + [self.contentView vc_removeAllSubviews]; + [super prepareForReuse]; +} + - (void)layoutSubviews { [super layoutSubviews]; CGFloat _leftInset = 0.0, _rightInset = 0.0; - - _leftInset += self.safeAreaInsets.left; - _rightInset += self.safeAreaInsets.right; - CGFloat leftMargin = MAX(_leftInset, _minimumLeftInset); - CGFloat rightMargin = MAX(_rightInset, _minimumRightInset); + CGFloat leftMargin = _minimumLeftInset; + CGFloat rightMargin = _minimumRightInset; if (_topSpanningView) { - CGRect frame = self.bounds; + CGRect frame = self.contentView.bounds; frame.size.height = _topViewHeight; _topSpanningView.frame = frame; } @@ -130,9 +177,9 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0; else { // center header label vertically - frame.origin.y = MAX(0, (self.bounds.size.height - frame.size.height)/2); + frame.origin.y = MAX(0, (self.contentView.bounds.size.height - frame.size.height)/2); } - frame.size.width = self.bounds.size.width - leftMargin - rightMargin; + frame.size.width = self.contentView.bounds.size.width - leftMargin - rightMargin; _headerLabel.frame = frame; } @@ -143,7 +190,7 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0; rightMargin = MAX(_rightInset, 20); CGRect frame = _accessoryView.frame; - frame.origin.x = self.bounds.size.width - frame.size.width - rightMargin; + frame.origin.x = self.contentView.bounds.size.width - frame.size.width - rightMargin; frame.origin.y = MAX(0, (_topViewHeight - frame.size.height)/2); _accessoryView.frame = frame; } @@ -157,8 +204,8 @@ static const CGFloat kInterItemsSpaceHorizontal = 8.0; CGRect frame = _bottomView.frame; frame.origin.x = leftMargin; frame.origin.y = CGRectGetMaxY(_headerLabel.frame); - frame.size.width = self.bounds.size.width - leftMargin - rightMargin; - frame.size.height = self.bounds.size.height - frame.origin.y; + frame.size.width = self.contentView.bounds.size.width - leftMargin - rightMargin; + frame.size.height = self.contentView.bounds.size.height - frame.origin.y; _bottomView.frame = frame; } } From 357c8fa62169bdf2b2eed2422673733e6b28cb2d Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 03:14:50 +0300 Subject: [PATCH 011/188] Register section header classes for table views --- Riot/Modules/Common/Recents/RecentsViewController.m | 4 ++++ Riot/Modules/Contacts/ContactsTableViewController.m | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 0aa137a5a..e1818b321 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -30,6 +30,7 @@ #import "DirectoryRecentTableViewCell.h" #import "RoomIdOrAliasTableViewCell.h" #import "TableViewCellWithCollectionView.h" +#import "SectionHeaderView.h" #import "GeneratedInterface-Swift.h" @@ -145,6 +146,9 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro // Register key verification banner cells [self.recentsTableView registerNib:CrossSigningSetupBannerCell.nib forCellReuseIdentifier:CrossSigningSetupBannerCell.defaultReuseIdentifier]; + + [self.recentsTableView registerClass:SectionHeaderView.class + forHeaderFooterViewReuseIdentifier:SectionHeaderView.defaultReuseIdentifier]; // Hide line separators of empty cells self.recentsTableView.tableFooterView = [[UIView alloc] init]; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index bf83b6372..24efac2d6 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -17,6 +17,7 @@ #import #import "ContactsTableViewController.h" +#import "SectionHeaderView.h" #import "UIViewController+RiotSearch.h" @@ -95,6 +96,9 @@ self.contactsTableView.dataSource = contactsDataSource; // Note: dataSource may be nil here [self.contactsTableView registerClass:ContactTableViewCell.class forCellReuseIdentifier:ContactTableViewCell.defaultReuseIdentifier]; + + [self.contactsTableView registerClass:SectionHeaderView.class + forHeaderFooterViewReuseIdentifier:SectionHeaderView.defaultReuseIdentifier]; // Hide line separators of empty cells self.contactsTableView.tableFooterView = [[UIView alloc] init]; From 16135e6e8ac93913f7360e469a4fb97987f9054c Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 03:19:00 +0300 Subject: [PATCH 012/188] Reuse section headers --- .../Recents/DataSources/RecentsDataSource.h | 3 ++- .../Recents/DataSources/RecentsDataSource.m | 20 ++++++++++--------- .../Contacts/ContactsTableViewController.m | 4 +++- .../Contacts/DataSources/ContactsDataSource.h | 6 ++++-- .../Contacts/DataSources/ContactsDataSource.m | 20 ++++++++++--------- .../UnifiedSearchRecentsDataSource.m | 4 ++-- .../Controllers/MXKRecentListViewController.m | 4 +++- .../MXKInterleavedRecentsDataSource.m | 2 +- .../Models/RoomList/MXKRecentsDataSource.h | 3 ++- .../Models/RoomList/MXKRecentsDataSource.m | 2 +- 10 files changed, 40 insertions(+), 28 deletions(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h index 745ab180c..8cc599eba 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h @@ -142,9 +142,10 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange; @param section the section index @param frame the drawing area for the header of the specified section. + @param tableView the table view @return the sticky header view. */ -- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame; +- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView; /** Get the height of the section header view. diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 0a7328bef..9e4bf8da2 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -198,7 +198,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou [self.recentsListService updateSpace:currentSpace]; } -- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView { UIView *stickyHeader; @@ -209,7 +209,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou shrinkedSectionsBitMask = RECENTSDATASOURCE_SECTION_DIRECTORY; } - stickyHeader = [self viewForHeaderInSection:section withFrame:frame]; + stickyHeader = [self viewForHeaderInSection:section withFrame:frame inTableView:tableView]; shrinkedSectionsBitMask = savedShrinkedSectionsBitMask; @@ -752,7 +752,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return missedNotifAndUnreadBadgeBgView; } -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView { // No header view in key backup banner section if (section == self.secureBackupBannerSection || section == self.crossSigningBannerSection) @@ -760,8 +760,14 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou return nil; } - SectionHeaderView *sectionHeader = [[SectionHeaderView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + SectionHeaderView *sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderView.defaultReuseIdentifier]; + if (sectionHeader == nil) + { + sectionHeader = [[SectionHeaderView alloc] initWithReuseIdentifier:SectionHeaderView.defaultReuseIdentifier]; + } + sectionHeader.backgroundView = [UIView new]; + sectionHeader.frame = frame; + sectionHeader.backgroundView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; sectionHeader.topViewHeight = RECENTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT; NSInteger sectionBitwise = 0; @@ -808,7 +814,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou shrinkButton.backgroundColor = [UIColor clearColor]; [shrinkButton addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; shrinkButton.tag = sectionBitwise; - [sectionHeader addSubview:shrinkButton]; sectionHeader.topSpanningView = shrinkButton; sectionHeader.userInteractionEnabled = YES; @@ -825,7 +830,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou UIImageView *chevronView = [[UIImageView alloc] initWithImage:chevron]; chevronView.tintColor = ThemeService.shared.theme.textSecondaryColor; chevronView.contentMode = UIViewContentModeCenter; - [sectionHeader addSubview:chevronView]; sectionHeader.accessoryView = chevronView; } else if (_recentsDataSourceMode == RecentsDataSourceModeHome) @@ -835,7 +839,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou if (badgeView) { - [sectionHeader addSubview:badgeView]; sectionHeader.accessoryView = badgeView; } } @@ -845,7 +848,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame]; headerLabel.backgroundColor = [UIColor clearColor]; headerLabel.attributedText = [self attributedStringForHeaderTitleInSection:section]; - [sectionHeader addSubview:headerLabel]; sectionHeader.headerLabel = headerLabel; return sectionHeader; diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index 24efac2d6..badf8a085 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -459,7 +459,9 @@ - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { - return [contactsDataSource viewForHeaderInSection:section withFrame:[tableView rectForHeaderInSection:section]]; + return [contactsDataSource viewForHeaderInSection:section + withFrame:[tableView rectForHeaderInSection:section] + inTableView:tableView]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.h b/Riot/Modules/Contacts/DataSources/ContactsDataSource.h index 5b665377e..6d6205e9b 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.h +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.h @@ -95,18 +95,20 @@ typedef enum : NSUInteger @param section the section index @param frame the drawing area for the header of the specified section. + @param tableView the table view @return the section header. */ -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame; +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView *)tableView; /** Get the sticky header view for the specified section. @param section the section index @param frame the drawing area for the header of the specified section. + @param tableView the table view @return the sticky header view. */ -- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame; +- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView *)tableView; /** Refresh the contacts data source and notify its delegate. diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index c7d1692bd..fd84c8c03 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -791,19 +791,24 @@ return sectionTitle; } -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView *)tableView { NSInteger sectionBitwise = 0; - SectionHeaderView *sectionHeader = [[SectionHeaderView alloc] initWithFrame:frame]; - sectionHeader.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; + SectionHeaderView *sectionHeader = [tableView dequeueReusableHeaderFooterViewWithIdentifier:SectionHeaderView.defaultReuseIdentifier]; + if (sectionHeader == nil) + { + sectionHeader = [[SectionHeaderView alloc] initWithReuseIdentifier:SectionHeaderView.defaultReuseIdentifier]; + } + sectionHeader.frame = frame; + sectionHeader.backgroundView = [UIView new]; + sectionHeader.backgroundView.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; sectionHeader.topViewHeight = CONTACTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT; frame.size.height = CONTACTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT - 10; UILabel *headerLabel = [[UILabel alloc] initWithFrame:frame]; headerLabel.attributedText = [self attributedStringForHeaderTitleInSection:section]; headerLabel.backgroundColor = [UIColor clearColor]; - [sectionHeader addSubview:headerLabel]; sectionHeader.headerLabel = headerLabel; if (_areSectionsShrinkable) @@ -832,7 +837,6 @@ shrinkButton.backgroundColor = [UIColor clearColor]; [shrinkButton addTarget:self action:@selector(onButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; shrinkButton.tag = sectionBitwise; - [sectionHeader addSubview:shrinkButton]; sectionHeader.topSpanningView = shrinkButton; sectionHeader.userInteractionEnabled = YES; @@ -849,7 +853,6 @@ UIImageView *chevronView = [[UIImageView alloc] initWithImage:chevron]; chevronView.tintColor = ThemeService.shared.theme.textSecondaryColor; chevronView.contentMode = UIViewContentModeCenter; - [sectionHeader addSubview:chevronView]; sectionHeader.accessoryView = chevronView; } @@ -893,20 +896,19 @@ localContactsCheckbox.tintColor = ThemeService.shared.theme.tintColor; // Add the check box container - [sectionHeader addSubview:localContactsCheckboxContainer]; sectionHeader.bottomView = localContactsCheckboxContainer; } return sectionHeader; } -- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForStickyHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView *)tableView { // Return the section header used when the section is shrinked NSInteger savedShrinkedSectionsBitMask = shrinkedSectionsBitMask; shrinkedSectionsBitMask = CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE | CONTACTSDATASOURCE_USERDIRECTORY_BITWISE; - UIView *stickyHeader = [self viewForHeaderInSection:section withFrame:frame]; + UIView *stickyHeader = [self viewForHeaderInSection:section withFrame:frame inTableView:tableView]; shrinkedSectionsBitMask = savedShrinkedSectionsBitMask; diff --git a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m index 59d169d7f..1493226ae 100644 --- a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m +++ b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m @@ -148,13 +148,13 @@ return count; } -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView { UIView *sectionHeader = nil; if (section != searchedRoomIdOrAliasSection) { - sectionHeader = [super viewForHeaderInSection:section withFrame:frame]; + sectionHeader = [super viewForHeaderInSection:section withFrame:frame inTableView:tableView]; } return sectionHeader; diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m index 828f84825..6a1a94100 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m @@ -421,7 +421,9 @@ - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { // Let dataSource provide the section header. - return [dataSource viewForHeaderInSection:section withFrame:[tableView rectForHeaderInSection:section]]; + return [dataSource viewForHeaderInSection:section + withFrame:[tableView rectForHeaderInSection:section] + inTableView:tableView]; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath diff --git a/Riot/Modules/MatrixKit/Models/RoomList/MXKInterleavedRecentsDataSource.m b/Riot/Modules/MatrixKit/Models/RoomList/MXKInterleavedRecentsDataSource.m index 28bb4c6ae..b9b34b566 100644 --- a/Riot/Modules/MatrixKit/Models/RoomList/MXKInterleavedRecentsDataSource.m +++ b/Riot/Modules/MatrixKit/Models/RoomList/MXKInterleavedRecentsDataSource.m @@ -56,7 +56,7 @@ #pragma mark - Override MXKRecentsDataSource -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView { UIView *sectionHeader = nil; diff --git a/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.h b/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.h index b9de69b4a..f37147425 100644 --- a/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.h +++ b/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.h @@ -88,9 +88,10 @@ @param section the section index @param frame the drawing area for the header of the specified section. + @param tableView the table view @return the section header. */ -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame; +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView; /** Get the data for the cell at the given index path. diff --git a/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.m b/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.m index 0da982a1d..fa6480b85 100644 --- a/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.m +++ b/Riot/Modules/MatrixKit/Models/RoomList/MXKRecentsDataSource.m @@ -257,7 +257,7 @@ } } -- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame +- (UIView *)viewForHeaderInSection:(NSInteger)section withFrame:(CGRect)frame inTableView:(UITableView*)tableView { UIView *sectionHeader = nil; From 82bee33aeb82eb325d2be35de95923f2fbea9872 Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Thu, 10 Feb 2022 00:18:52 +0000 Subject: [PATCH 013/188] Switch to using `m.login.dummy` Signed-off-by: Aaron Raimist --- .../MatrixKit/Controllers/MXKAuthenticationViewController.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m index 7ffe37570..d71e19b6d 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m @@ -981,7 +981,11 @@ { // Trigger here a register request in order to associate the filled userId and password to the current session id // This will check the availability of the userId at the same time - NSDictionary *parameters = @{@"username": self.authInputsView.userId, + NSDictionary *parameters = @{@"auth": @{ + @"session": self.authInputsView.authSession.session, + @"type": kMXLoginFlowTypeDummy + }, + @"username": self.authInputsView.userId, @"password": self.authInputsView.password, @"bind_email": @(NO), @"initial_device_display_name":self.deviceDisplayName From 22a2bb0f901c3700cff53a3b745dc7f2fb65c94c Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 03:19:51 +0300 Subject: [PATCH 014/188] Refresh tab bar badges when off-screen fetcher updated --- Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 9e4bf8da2..2e16761eb 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -1471,7 +1471,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou - (void)recentsListServiceDidChangeData:(id)service totalCountsChanged:(BOOL)totalCountsChanged { - // no-op + [[AppDelegate theDelegate].masterTabBarController refreshTabBarBadges]; } - (void)recentsListServiceDidChangeData:(id)service From 06551036c8db41d84cecc1c4f97c4ac91a7b972c Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 03:20:34 +0300 Subject: [PATCH 015/188] Update section header label and accessory view when needed --- Riot/Modules/Common/Recents/RecentsViewController.m | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index e1818b321..b81c6322a 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -1022,6 +1022,18 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro TableViewCellWithCollectionView *collectionViewCell = (TableViewCellWithCollectionView *)cell; [collectionViewCell.collectionView reloadData]; cellReloaded = YES; + + CGRect headerFrame = [self.recentsTableView rectForHeaderInSection:update.sectionIndex]; + UIView *headerView = [self.recentsTableView headerViewForSection:update.sectionIndex]; + UIView *updatedHeaderView = [self.dataSource viewForHeaderInSection:update.sectionIndex withFrame:headerFrame inTableView:self.recentsTableView]; + if ([headerView isKindOfClass:SectionHeaderView.class] + && [updatedHeaderView isKindOfClass:SectionHeaderView.class]) + { + SectionHeaderView *sectionHeaderView = (SectionHeaderView *)headerView; + SectionHeaderView *updatedSectionHeaderView = (SectionHeaderView *)updatedHeaderView; + sectionHeaderView.headerLabel = updatedSectionHeaderView.headerLabel; + sectionHeaderView.accessoryView = updatedSectionHeaderView.accessoryView; + } } } } From 990d9bb3054f8736e5e6b35270028952c2df6344 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 03:21:38 +0300 Subject: [PATCH 016/188] Add changelog --- changelog.d/5537.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5537.bugfix diff --git a/changelog.d/5537.bugfix b/changelog.d/5537.bugfix new file mode 100644 index 000000000..5da0cca4c --- /dev/null +++ b/changelog.d/5537.bugfix @@ -0,0 +1 @@ +HomeViewController: Refresh section badges and tab bar badges on updates. From 4b1eb75fd35a47bedac153dece07740a96900090 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 7 Feb 2022 14:26:47 +0200 Subject: [PATCH 017/188] Fixed various project warnings. Completely disabled nullability checks, went down from ~20k to 195. --- .swiftlint.yml | 2 +- Config/BuildSettings.swift | 2 - Config/Project-Warnings.xcconfig | 4 + Podfile | 7 +- Riot/Assets/Base.lproj/Main.storyboard | 48 +-- Riot/Managers/BugReport/RageShakeManager.m | 2 +- .../PushNotificationService.h | 1 - Riot/Managers/Widgets/WidgetManager.m | 4 +- Riot/Modules/Application/LegacyAppDelegate.m | 78 ++--- .../AuthenticationViewController.h | 1 - .../Authentication/Views/AuthInputsView.m | 30 +- .../Views/ForgotPasswordInputsView.m | 2 +- Riot/Modules/Call/CallViewController.m | 4 +- Riot/Modules/Call/Views/IncomingCallView.h | 3 - .../CustomSizedPresentationController.swift | 2 +- .../Common/Recents/RecentsViewController.m | 12 +- .../SegmentedViewController.m | 3 + .../Home/GroupHomeViewController.h | 3 - .../Home/GroupHomeViewController.m | 33 ++- .../Members/GroupParticipantsViewController.h | 3 - .../Members/GroupParticipantsViewController.m | 19 +- .../Rooms/GroupRoomsViewController.h | 3 - .../Rooms/GroupRoomsViewController.m | 7 +- .../TabDetail/GroupDetailsViewController.h | 3 - .../Details/ContactDetailsViewController.m | 4 +- .../UnifiedSearchRecentsDataSource.m | 12 - .../UnifiedSearchViewController.m | 8 +- .../Fallback/AuthFallBackViewController.m | 2 +- .../WidgetPermissionViewController.swift | 2 - ...SuccessFromRecoveryKeyViewController.swift | 2 +- .../MajorUpdateViewController.swift | 2 - .../MXKAttachmentsViewController.m | 4 + .../MXKAuthenticationViewController.m | 3 + .../MXKCountryPickerViewController.m | 2 +- .../Controllers/MXKGroupListViewController.m | 6 + .../MXKLanguagePickerViewController.m | 2 +- .../Controllers/MXKRecentListViewController.m | 6 + .../MXKRoomMemberListViewController.m | 6 + .../Controllers/MXKSearchViewController.m | 6 + .../Controllers/MXKWebViewViewController.m | 4 + .../Modules/MatrixKit/Libs/SwiftUTI/UTI.swift | 276 +++++++++--------- Riot/Modules/MatrixKit/MatrixKit.h | 1 - .../Models/Account/MXKAccountManager.m | 9 + .../MatrixKit/Models/Contact/MXKContact.h | 3 + .../MatrixKit/Models/Contact/MXKContact.m | 3 + .../Models/Contact/MXKContactManager.m | 8 + .../Modules/MatrixKit/Models/MXKAppSettings.m | 3 + .../RoomList/MXKSessionRecentsDataSource.h | 2 +- Riot/Modules/MatrixKit/Utils/MXKConstants.h | 3 - .../Utils/MXKDocumentPickerPresenter.swift | 3 +- Riot/Modules/MatrixKit/Utils/MXKTools.m | 2 +- Riot/Modules/MatrixKit/Utils/MXKUTI.swift | 10 +- .../MXKAuthenticationFallbackWebView.m | 2 +- .../MXKAuthenticationRecaptchaWebView.m | 2 +- .../MXKEncryptionInfoView.m | 4 +- ...MXKRoomInputToolbarViewWithHPGrowingText.h | 33 --- ...MXKRoomInputToolbarViewWithHPGrowingText.m | 187 ------------ ...KRoomInputToolbarViewWithHPGrowingText.xib | 85 ------ ...OnboardingCoordinatorBridgePresenter.swift | 3 +- ...ditHistoryCoordinatorBridgePresenter.swift | 1 - .../EmojiPickerViewController.swift | 2 +- Riot/Modules/Room/MXKRoomViewController.m | 15 +- .../Members/RoomParticipantsViewController.m | 5 +- .../Room/RoomCoordinatorBridgePresenter.swift | 3 +- Riot/Modules/Room/RoomViewController.m | 19 +- .../Room/Search/RoomSearchViewController.m | 8 +- .../Views/Activities/RoomActivitiesView.m | 3 + .../Common/MXKRoomBubbleTableViewCell.m | 3 + .../RoomKeyRequestViewController.m | 6 +- ...SecretsRecoveryWithKeyViewController.swift | 2 +- ...RecoveryWithPassphraseViewController.swift | 2 +- .../Modules/Settings/SettingsViewController.m | 2 + .../SpaceDetailViewController.swift | 6 +- .../SpaceDetail/SpaceDetailViewModel.swift | 30 +- .../Spaces/SpaceList/SpaceListViewModel.swift | 12 +- ...aceMembersCoordinatorBridgePresenter.swift | 3 +- ...xploreRoomCoordinatorBridgePresenter.swift | 3 +- .../SpaceChildRoomDetailViewModel.swift | 6 +- .../SplitView/SplitViewCoordinator.swift | 9 +- Riot/Modules/TabBar/MasterTabBarController.m | 6 +- .../ThreadsCoordinatorBridgePresenter.swift | 3 +- .../UserDevices/UsersDevicesViewController.m | 4 +- Riot/Utils/EventFormatter.m | 2 +- RiotNSE/NotificationService.swift | 2 +- changelog.d/pr-5513.misc | 1 + 85 files changed, 465 insertions(+), 679 deletions(-) delete mode 100644 Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.h delete mode 100644 Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.m delete mode 100644 Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.xib create mode 100644 changelog.d/pr-5513.misc diff --git a/.swiftlint.yml b/.swiftlint.yml index 4d215eb98..f210c1ac3 100755 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -36,7 +36,7 @@ line_length: error: 1000 file_length: - warning: 700 + warning: 800 error: 1000 type_body_length: diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 305f4dddc..0996ce2ef 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -146,8 +146,6 @@ final class BuildSettings: NSObject { static let stunServerFallbackUrlString: String? = "stun:turn.matrix.org" // MARK: - Public rooms Directory - #warning("Unused build setting: should this be implemented in ShowDirectory?") - static let publicRoomsAllowServerChange: Bool = true // List of homeservers for the public rooms directory static let publicRoomsDirectoryServers = [ "matrix.org", diff --git a/Config/Project-Warnings.xcconfig b/Config/Project-Warnings.xcconfig index 8c9512128..350f6dd29 100644 --- a/Config/Project-Warnings.xcconfig +++ b/Config/Project-Warnings.xcconfig @@ -46,3 +46,7 @@ GCC_WARN_UNDECLARED_SELECTOR = YES GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE GCC_WARN_UNUSED_FUNCTION = YES GCC_WARN_UNUSED_VARIABLE = YES + +WARNING_CFLAGS = $(inherited) -Wno-nullability-completeness; +OTHER_SWIFT_FLAGS = $(inherited) -Xcc -Wno-nullability-completeness + diff --git a/Podfile b/Podfile index c98ddb10c..09f7811c9 100644 --- a/Podfile +++ b/Podfile @@ -49,7 +49,6 @@ end ######################################## def import_MatrixKit_pods - pod 'HPGrowingTextView', '~> 1.1' pod 'libPhoneNumber-iOS', '~> 0.9.13' pod 'DTCoreText', '~> 1.6.25' #pod 'DTCoreText/Extension', '~> 1.6.25' @@ -98,7 +97,7 @@ abstract_target 'RiotPods' do pod 'DSWaveformImage', '~> 6.1.1' pod 'ffmpeg-kit-ios-audio', '4.5.1' - pod 'FLEX', '~> 4.5.0', :configurations => ['Debug'] + pod 'FLEX', '~> 4.5.0', :configurations => ['Debug'], :inhibit_warnings => true target 'RiotTests' do inherit! :search_paths @@ -149,6 +148,10 @@ post_install do |installer| # Stop Xcode 12 complaining about old IPHONEOS_DEPLOYMENT_TARGET from pods config.build_settings.delete 'IPHONEOS_DEPLOYMENT_TARGET' + + # Disable nullability checks + config.build_settings['WARNING_CFLAGS'] ||= ['$(inherited)','-Wno-nullability-completeness'] + config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['$(inherited)', '-Xcc', '-Wno-nullability-completeness'] end end end \ No newline at end of file diff --git a/Riot/Assets/Base.lproj/Main.storyboard b/Riot/Assets/Base.lproj/Main.storyboard index 4708d7dbc..885be7db7 100644 --- a/Riot/Assets/Base.lproj/Main.storyboard +++ b/Riot/Assets/Base.lproj/Main.storyboard @@ -1,9 +1,9 @@ - + - + @@ -46,24 +46,6 @@ - - - - - - - - - - - - - - - - - - @@ -116,14 +98,6 @@ - - - - - - - - @@ -501,24 +475,6 @@ - - - - - - - - - - - - - - - - - - diff --git a/Riot/Managers/BugReport/RageShakeManager.m b/Riot/Managers/BugReport/RageShakeManager.m index 4ce848240..5f04baa9e 100644 --- a/Riot/Managers/BugReport/RageShakeManager.m +++ b/Riot/Managers/BugReport/RageShakeManager.m @@ -200,7 +200,7 @@ static RageShakeManager* sharedInstance = nil; UIImage *image; - AppDelegate* theDelegate = [AppDelegate theDelegate]; + LegacyAppDelegate* theDelegate = [AppDelegate theDelegate]; UIGraphicsBeginImageContextWithOptions(theDelegate.window.bounds.size, NO, [UIScreen mainScreen].scale); // Iterate over every window from back to front diff --git a/Riot/Managers/PushNotification/PushNotificationService.h b/Riot/Managers/PushNotification/PushNotificationService.h index aaec583d7..c16b65792 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.h +++ b/Riot/Managers/PushNotification/PushNotificationService.h @@ -108,7 +108,6 @@ NS_ASSUME_NONNULL_BEGIN @param pushNotificationService PushNotificationService object. @param roomId Room identifier to be navigated. - @param eventId Event identifier to be navigated around. */ - (void)pushNotificationService:(PushNotificationService *)pushNotificationService shouldNavigateToRoomWithId:(NSString *)roomId; diff --git a/Riot/Managers/Widgets/WidgetManager.m b/Riot/Managers/Widgets/WidgetManager.m index 2b25d2e13..240d573c1 100644 --- a/Riot/Managers/Widgets/WidgetManager.m +++ b/Riot/Managers/Widgets/WidgetManager.m @@ -338,7 +338,6 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain"; Check user's power for widgets management in a room. @param room the room to check. - @return an NSError if the user cannot act on widgets in this room. Else, nil. */ - (void)checkWidgetPermissionInRoom:(MXRoom *)room success:(dispatch_block_t)success failure:(void (^)(NSError *))failure { @@ -742,6 +741,8 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain"; return configs[mxSession.myUser.userId].scalarToken; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)loadConfigs { NSUserDefaults *userDefaults = [MXKAppSettings standardAppSettings].sharedUserDefaults; @@ -787,6 +788,7 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain"; [userDefaults setObject:[NSKeyedArchiver archivedDataWithRootObject:configs] forKey:@"integrationManagerConfigs"]; } +#pragma clang diagnostic pop #pragma mark - Errors diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index a462a4bc0..6fe61c3b1 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -838,28 +838,28 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } // Enable error notifications - isErrorNotificationSuspended = NO; + self->isErrorNotificationSuspended = NO; - if (noCallSupportAlert) + if (self->noCallSupportAlert) { MXLogDebug(@"[AppDelegate] restoreInitialDisplay: keep visible noCall support alert"); - [self showNotificationAlert:noCallSupportAlert]; + [self showNotificationAlert:self->noCallSupportAlert]; } - else if (cryptoDataCorruptedAlert) + else if (self->cryptoDataCorruptedAlert) { MXLogDebug(@"[AppDelegate] restoreInitialDisplay: keep visible log in again"); - [self showNotificationAlert:cryptoDataCorruptedAlert]; + [self showNotificationAlert:self->cryptoDataCorruptedAlert]; } - else if (wrongBackupVersionAlert) + else if (self->wrongBackupVersionAlert) { MXLogDebug(@"[AppDelegate] restoreInitialDisplay: keep visible wrongBackupVersionAlert"); - [self showNotificationAlert:wrongBackupVersionAlert]; + [self showNotificationAlert:self->wrongBackupVersionAlert]; } // Check whether an error notification is pending - else if (_errorNotification) + else if (self->_errorNotification) { - [self showNotificationAlert:_errorNotification]; + [self showNotificationAlert:self->_errorNotification]; } }]; @@ -876,10 +876,10 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } // Enable error notification (Check whether a notification is pending) - isErrorNotificationSuspended = NO; - if (_errorNotification) + self->isErrorNotificationSuspended = NO; + if (self->_errorNotification) { - [self showNotificationAlert:_errorNotification]; + [self showNotificationAlert:self->_errorNotification]; } }]; } @@ -1429,9 +1429,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni else { void(^findRoom)(void) = ^{ - if ([_masterTabBarController.selectedViewController conformsToProtocol:@protocol(MXKViewControllerActivityHandling)]) + if ([self->_masterTabBarController.selectedViewController conformsToProtocol:@protocol(MXKViewControllerActivityHandling)]) { - UIViewController *homeViewController = (UIViewController*)_masterTabBarController.selectedViewController; + UIViewController *homeViewController = (UIViewController*)self->_masterTabBarController.selectedViewController; [homeViewController startActivityIndicator]; @@ -1439,7 +1439,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni { // The alias may be not part of user's rooms states // Ask the HS to resolve the room alias into a room id and then retry - universalLinkFragmentPending = fragment; + self->universalLinkFragmentPending = fragment; MXKAccount* account = accountManager.activeAccounts.firstObject; [account.mxSession.matrixRestClient roomIDForRoomAlias:roomIdOrAlias success:^(NSString *roomId) { @@ -1447,7 +1447,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [homeViewController stopActivityIndicator]; // Check that 'fragment' has not been cancelled - if ([universalLinkFragmentPending isEqualToString:fragment]) + if ([self->universalLinkFragmentPending isEqualToString:fragment]) { // Retry opening the link but with the returned room id NSString *newUniversalLinkFragment = @@ -1467,7 +1467,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni if (![newUniversalLinkFragment isEqualToString:fragment]) { - universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias}; + self->universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias}; UniversalLinkParameters *newParameters = [[UniversalLinkParameters alloc] initWithFragment:newUniversalLinkFragment universalLinkURL:universalLinkURL presentationParameters:presentationParameters]; @@ -1498,12 +1498,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni MXKAccount* account = accountManager.activeAccounts.firstObject; MXLogDebug(@"[AppDelegate] Universal link: Need to wait for the session to be sync'ed and running"); - universalLinkFragmentPending = fragment; + self->universalLinkFragmentPending = fragment; - universalLinkWaitingObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull notif) { + self->universalLinkWaitingObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXSessionStateDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull notif) { // Check that 'fragment' has not been cancelled - if ([universalLinkFragmentPending isEqualToString:fragment]) + if ([self->universalLinkFragmentPending isEqualToString:fragment]) { // Check whether the concerned session is the associated one if (notif.object == account.mxSession && account.mxSession.state == MXSessionStateRunning) @@ -1582,7 +1582,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni universalLinkWaitingObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidAddAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { // Check that 'fragment' has not been cancelled - if ([universalLinkFragmentPending isEqualToString:fragment]) + if ([self->universalLinkFragmentPending isEqualToString:fragment]) { MXLogDebug(@"[AppDelegate] Universal link: The user is now logged in. Retry the link"); [self handleUniversalLinkWithParameters:universalLinkParameters]; @@ -1647,7 +1647,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni universalLinkWaitingObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidAddAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { // Check that 'fragment' has not been cancelled - if ([universalLinkFragmentPending isEqualToString:fragment]) + if ([self->universalLinkFragmentPending isEqualToString:fragment]) { MXLogDebug(@"[AppDelegate] Universal link: The user is now logged in. Retry the link"); [self handleUniversalLinkWithParameters:universalLinkParameters]; @@ -2319,7 +2319,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } // Return to authentication screen - [_masterTabBarController showOnboardingFlow]; + [self->_masterTabBarController showOnboardingFlow]; // Note: Keep App settings // But enforce usage of member lazy loading @@ -2730,7 +2730,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni if ([[ruleAction.parameters valueForKey:@"set_tweak"] isEqualToString:@"sound"]) { // Play message sound - AudioServicesPlaySystemSound(_messageSound); + AudioServicesPlaySystemSound(self->_messageSound); } } } @@ -3425,9 +3425,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni { case MXEventTypeCallInvite: { - if (noCallSupportAlert) + if (self->noCallSupportAlert) { - [noCallSupportAlert dismissViewControllerAnimated:NO completion:nil]; + [self->noCallSupportAlert dismissViewControllerAnimated:NO completion:nil]; } MXCallInviteEventContent *callInviteEventContent = [MXCallInviteEventContent modelFromJSON:event.content]; @@ -3449,15 +3449,15 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni NSString *message = [VectorL10n noVoip:callerDisplayname :appDisplayName]; - noCallSupportAlert = [UIAlertController alertControllerWithTitle:[VectorL10n noVoipTitle] - message:message - preferredStyle:UIAlertControllerStyleAlert]; + self->noCallSupportAlert = [UIAlertController alertControllerWithTitle:[VectorL10n noVoipTitle] + message:message + preferredStyle:UIAlertControllerStyleAlert]; __weak typeof(self) weakSelf = self; - [noCallSupportAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ignore] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { + [self->noCallSupportAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ignore] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { if (weakSelf) { @@ -3467,9 +3467,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni }]]; - [noCallSupportAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n rejectCall] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { + [self->noCallSupportAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n rejectCall] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { // Reject the call by sending the hangup event NSDictionary *content = @{ @@ -3490,7 +3490,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni }]]; - [self showNotificationAlert:noCallSupportAlert]; + [self showNotificationAlert:self->noCallSupportAlert]; break; } @@ -3498,10 +3498,10 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni case MXEventTypeCallHangup: case MXEventTypeCallReject: // The call has ended. The alert is no more needed. - if (noCallSupportAlert) + if (self->noCallSupportAlert) { - [noCallSupportAlert dismissViewControllerAnimated:YES completion:nil]; - noCallSupportAlert = nil; + [self->noCallSupportAlert dismissViewControllerAnimated:YES completion:nil]; + self->noCallSupportAlert = nil; } break; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index 894ea8b45..1f6b278d0 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -37,7 +37,6 @@ @property (weak, nonatomic) IBOutlet UIButton *customServersTickButton; @property (weak, nonatomic) IBOutlet UIView *customServersContainer; @property (weak, nonatomic) IBOutlet UIView *homeServerContainer; -@property (weak, nonatomic) IBOutlet UIView *identityServerContainer; @property (weak, nonatomic) IBOutlet UIView *homeServerSeparator; @property (weak, nonatomic) IBOutlet UIView *identityServerSeparator; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 43efbce8b..b4eaad74a 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -431,7 +431,7 @@ style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - inputsAlert = nil; + self->inputsAlert = nil; }]]; @@ -551,10 +551,10 @@ } // Check whether a second 3pid is available - _isThirdPartyIdentifierPending = (!self.emailContainer.isHidden && self.emailTextField.text.length && ![self isFlowCompleted:kMXLoginFlowTypeEmailIdentity]); + self->_isThirdPartyIdentifierPending = (!self.emailContainer.isHidden && self.emailTextField.text.length && ![self isFlowCompleted:kMXLoginFlowTypeEmailIdentity]); // Launch msisdn validation - NSString *e164 = [[NBPhoneNumberUtil sharedInstance] format:nbPhoneNumber numberFormat:NBEPhoneNumberFormatE164 error:nil]; + NSString *e164 = [[NBPhoneNumberUtil sharedInstance] format:self->nbPhoneNumber numberFormat:NBEPhoneNumberFormatE164 error:nil]; NSString *msisdn; if ([e164 hasPrefix:@"+"]) { @@ -564,12 +564,12 @@ { msisdn = [e164 substringFromIndex:2]; } - submittedMSISDN = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumMSISDN andAddress:msisdn]; - - [submittedMSISDN requestValidationTokenWithMatrixRestClient:restClient - isDuringRegistration:YES - nextLink:nil - success:^ + self->submittedMSISDN = [[MXK3PID alloc] initWithMedium:kMX3PIDMediumMSISDN andAddress:msisdn]; + + [self->submittedMSISDN requestValidationTokenWithMatrixRestClient:restClient + isDuringRegistration:YES + nextLink:nil + success:^ { [self showValidationMSISDNDialogToPrepareParameters:callback]; @@ -763,7 +763,7 @@ { NSDictionary *parameters = @{ @"auth": @{ - @"session":currentSession.session, + @"session": self->currentSession.session, @"response": response, @"type": kMXLoginFlowTypeRecaptcha }, @@ -870,7 +870,7 @@ { // We finalize here a registration triggered from external inputs. All the required data are handled by the session id NSDictionary *parameters = @{ - @"auth": @{@"session": currentSession.session, @"response": response, @"type": kMXLoginFlowTypeRecaptcha}, + @"auth": @{@"session": self->currentSession.session, @"response": response, @"type": kMXLoginFlowTypeRecaptcha}, }; callback (parameters, nil); } @@ -1705,7 +1705,7 @@ if (weakSelf) { typeof(self) self = weakSelf; - UITextField *textField = [inputsAlert textFields].firstObject; + UITextField *textField = [self->inputsAlert textFields].firstObject; NSString *smsCode = textField.text; self->inputsAlert = nil; @@ -1776,9 +1776,9 @@ self->inputsAlert = [UIAlertController alertControllerWithTitle:title message:msg preferredStyle:UIAlertControllerStyleAlert]; - [inputsAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { + [self->inputsAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { if (weakSelf) { diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 9173043f7..386df8331 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -219,7 +219,7 @@ style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - inputsAlert = nil; + self->inputsAlert = nil; }]]; diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 8ec636401..8f9eab5a1 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -721,7 +721,9 @@ CallAudioRouteMenuViewDelegate> { MXWeakify(self); [self.mainSession.callManager getThirdPartyUserFrom:phoneNumber success:^(MXThirdPartyUserInstance * _Nonnull user) { - MXStrongifyAndReturnIfNil(self); + if (weakself == nil) { + return; + } continueBlock(user.userId); } failure:^(NSError * _Nullable error) { diff --git a/Riot/Modules/Call/Views/IncomingCallView.h b/Riot/Modules/Call/Views/IncomingCallView.h index 3035aebb2..45f897115 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.h +++ b/Riot/Modules/Call/Views/IncomingCallView.h @@ -43,9 +43,6 @@ typedef void (^IncomingCallViewAction)(void); @param mxcAvatarURI the Matrix Content URI of the caller avatar. @param mediaManager the media manager used to download this avatar if it is not cached yet. - @param placeholderImage - @param callerName - @param callInfo */ - (instancetype)initWithCallerAvatar:(NSString *)mxcAvatarURI mediaManager:(MXMediaManager *)mediaManager diff --git a/Riot/Modules/Common/Presentation/CustomSizedPresentationController.swift b/Riot/Modules/Common/Presentation/CustomSizedPresentationController.swift index 554705d73..7c7dfb47d 100644 --- a/Riot/Modules/Common/Presentation/CustomSizedPresentationController.swift +++ b/Riot/Modules/Common/Presentation/CustomSizedPresentationController.swift @@ -86,7 +86,7 @@ class CustomSizedPresentationController: UIPresentationController { // effect calls for only the top two corners to be rounded we size // the view such that the bottom CORNER_RADIUS points lie below // the bottom edge of the screen. - let cornerViewRect = presentationWrapperView.bounds//.inset(by: UIEdgeInsets(top: 0, left: 0, bottom: -cornerRadius, right: 0)) + let cornerViewRect = presentationWrapperView.bounds// .inset(by: UIEdgeInsets(top: 0, left: 0, bottom: -cornerRadius, right: 0)) let presentationRoundedCornerView = UIView(frame: cornerViewRect) presentationRoundedCornerView.autoresizingMask = [.flexibleWidth, .flexibleHeight] diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 0aa137a5a..bbf442a53 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -35,7 +35,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewControllerDataReadyNotification"; -@interface RecentsViewController () +@interface RecentsViewController () { // Tell whether a recents refresh is pending (suspended during editing mode). BOOL isRefreshPending; @@ -1292,7 +1292,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro [self stopActivityIndicator]; // Leave editing mode - [self cancelEditionMode:isRefreshPending]; + [self cancelEditionMode:self->isRefreshPending]; } }]; @@ -1300,7 +1300,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro else { // Leave editing mode - [self cancelEditionMode:isRefreshPending]; + [self cancelEditionMode:self->isRefreshPending]; } } @@ -1358,7 +1358,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro [self stopActivityIndicator]; // Leave editing mode - [self cancelEditionMode:isRefreshPending]; + [self cancelEditionMode:self->isRefreshPending]; } failure:^(NSError *error) { @@ -1366,7 +1366,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro [self stopActivityIndicator]; - MXLogDebug(@"[RecentsViewController] Failed to update direct tag of the room (%@)", editedRoomId); + MXLogDebug(@"[RecentsViewController] Failed to update direct tag of the room (%@)", self->editedRoomId); // Notify the end user NSString *userId = self.mainSession.myUser.userId; // TODO: handle multi-account @@ -1375,7 +1375,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro userInfo:userId ? @{kMXKErrorUserIdKey: userId} : nil]; // Leave editing mode - [self cancelEditionMode:isRefreshPending]; + [self cancelEditionMode:self->isRefreshPending]; }]; } diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 60547f8c5..883a9c416 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -165,6 +165,8 @@ // Adjust Top [NSLayoutConstraint deactivateConstraints:@[self.selectionContainerTopConstraint]]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" // it is not possible to define a constraint to the topLayoutGuide in the xib editor // so do it in the code .. self.selectionContainerTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide @@ -174,6 +176,7 @@ attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[self.selectionContainerTopConstraint]]; diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.h b/Riot/Modules/Communities/Home/GroupHomeViewController.h index 69b2300da..510e1dfcc 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.h +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.h @@ -63,9 +63,6 @@ /** Set the group for which the details are displayed. Provide the related matrix session. - - @param group - @param mxSession */ - (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession; diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 6e5d5d3b5..a5a48ebba 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -40,7 +40,7 @@ // The options used to load long description html content. NSDictionary *options; - NSString *groupLongDescription; + NSString *groupLongDescriptionString; // The current pushed view controller UIViewController *pushedViewController; @@ -229,25 +229,25 @@ // Indeed the group update notifications are triggered by the matrix session only for the user's groups. void (^success)(void) = ^void(void) { - [self refreshDisplayWithGroup:_group]; + [self refreshDisplayWithGroup:self->_group]; }; // Trigger a refresh on the group summary. - [self.mxSession updateGroupSummary:_group success:(isPreview ? success : nil) failure:^(NSError *error) { + [self.mxSession updateGroupSummary:self->_group success:(isPreview ? success : nil) failure:^(NSError *error) { - MXLogDebug(@"[GroupHomeViewController] viewWillAppear: group summary update failed %@", _group.groupId); + MXLogDebug(@"[GroupHomeViewController] viewWillAppear: group summary update failed %@", self->_group.groupId); }]; // Trigger a refresh on the group members (ignore here the invited users). - [self.mxSession updateGroupUsers:_group success:(isPreview ? success : nil) failure:^(NSError *error) { + [self.mxSession updateGroupUsers:self->_group success:(isPreview ? success : nil) failure:^(NSError *error) { - MXLogDebug(@"[GroupHomeViewController] viewWillAppear: group members update failed %@", _group.groupId); + MXLogDebug(@"[GroupHomeViewController] viewWillAppear: group members update failed %@", self->_group.groupId); }]; // Trigger a refresh on the group rooms. - [self.mxSession updateGroupRooms:_group success:(isPreview ? success : nil) failure:^(NSError *error) { + [self.mxSession updateGroupRooms:self->_group success:(isPreview ? success : nil) failure:^(NSError *error) { - MXLogDebug(@"[GroupHomeViewController] viewWillAppear: group rooms update failed %@", _group.groupId); + MXLogDebug(@"[GroupHomeViewController] viewWillAppear: group rooms update failed %@", self->_group.groupId); }]; } @@ -523,11 +523,11 @@ { if (_group.summary.profile.longDescription.length) { - groupLongDescription = _group.summary.profile.longDescription; + groupLongDescriptionString = _group.summary.profile.longDescription; } else { - groupLongDescription = nil; + groupLongDescriptionString = nil; } [self renderGroupLongDescription]; @@ -535,13 +535,13 @@ - (void)renderGroupLongDescription { - if (groupLongDescription) + if (groupLongDescriptionString) { // Using DTCoreText, which renders static string, helps to avoid code injection attacks // that could happen with the default HTML renderer of NSAttributedString which is a // webview. // The supplied options include a callback to sanitize html tags and load image data. - NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[groupLongDescription dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL]; + NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[groupLongDescriptionString dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL]; // Apply additional treatments NSInteger mxIdsBitMask = (MXKTOOLS_USER_IDENTIFIER_BITWISE | MXKTOOLS_ROOM_IDENTIFIER_BITWISE | MXKTOOLS_ROOM_ALIAS_BITWISE | MXKTOOLS_EVENT_IDENTIFIER_BITWISE | MXKTOOLS_GROUP_IDENTIFIER_BITWISE); @@ -694,12 +694,12 @@ self->currentRequest = nil; [self stopActivityIndicator]; - [self refreshDisplayWithGroup:[_mxSession groupWithGroupId:_group.groupId]]; + [self refreshDisplayWithGroup:[self->_mxSession groupWithGroupId:self->_group.groupId]]; } } failure:^(NSError *error) { - MXLogDebug(@"[GroupDetailsViewController] join group (%@) failed", _group.groupId); + MXLogDebug(@"[GroupDetailsViewController] join group (%@) failed", self->_group.groupId); if (weakSelf) { @@ -732,7 +732,7 @@ } failure:^(NSError *error) { - MXLogDebug(@"[GroupDetailsViewController] leave group (%@) failed", _group.groupId); + MXLogDebug(@"[GroupDetailsViewController] leave group (%@) failed", self->_group.groupId); if (weakSelf) { @@ -802,6 +802,8 @@ #pragma mark - UITextView delegate +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { BOOL shouldInteractWithURL = YES; @@ -903,5 +905,6 @@ return shouldInteractWithURL; } +#pragma clang diagnostic pop @end diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.h b/Riot/Modules/Communities/Members/GroupParticipantsViewController.h index 83b862664..e5b4a9ba8 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.h +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.h @@ -76,9 +76,6 @@ /** Set the group for which the details are displayed. Provide the related matrix session. - - @param group - @param mxSession */ - (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index 9a87f6562..c78907883 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -93,6 +93,8 @@ // Adjust Top and Bottom constraints to take into account potential navBar and tabBar. [NSLayoutConstraint deactivateConstraints:@[_searchBarTopConstraint, _tableViewBottomConstraint]]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" _searchBarTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual @@ -108,6 +110,7 @@ attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[_searchBarTopConstraint, _tableViewBottomConstraint]]; @@ -239,18 +242,18 @@ // Indeed the group update notifications are triggered by the matrix session only for the user's groups. void (^success)(void) = ^void(void) { - [self refreshDisplayWithGroup:_group]; + [self refreshDisplayWithGroup:self->_group]; }; // Trigger a refresh on the group members and the invited users. [self.mxSession updateGroupUsers:_group success:(isPreview ? success : nil) failure:^(NSError *error) { - MXLogDebug(@"[GroupParticipantsViewController] viewWillAppear: group members update failed %@", _group.groupId); + MXLogDebug(@"[GroupParticipantsViewController] viewWillAppear: group members update failed %@", self->_group.groupId); }]; [self.mxSession updateGroupInvitedUsers:_group success:(isPreview ? success : nil) failure:^(NSError *error) { - MXLogDebug(@"[GroupParticipantsViewController] viewWillAppear: invited users update failed %@", _group.groupId); + MXLogDebug(@"[GroupParticipantsViewController] viewWillAppear: invited users update failed %@", self->_group.groupId); }]; } @@ -305,7 +308,7 @@ [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ - tableViewMaskLayer.bounds = newBounds; + self->tableViewMaskLayer.bounds = newBounds; } completion:^(BOOL finished){ @@ -421,7 +424,7 @@ [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ - addParticipantButtonImageViewBottomConstraint.constant = keyboardHeight + 9; + self->addParticipantButtonImageViewBottomConstraint.constant = keyboardHeight + 9; // Force to render the view [self.view layoutIfNeeded]; @@ -653,7 +656,7 @@ pendingMaskSpinnerView.alpha = 0; [UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ - pendingMaskSpinnerView.alpha = 1; + self->pendingMaskSpinnerView.alpha = 1; } completion:^(BOOL finished) { }]; @@ -1075,14 +1078,14 @@ self->currentAlert = nil; [self addPendingActionMask]; - [self.mxSession leaveGroup:_group.groupId success:^{ + [self.mxSession leaveGroup:self->_group.groupId success:^{ [self withdrawViewControllerAnimated:YES completion:nil]; } failure:^(NSError *error) { [self removePendingActionMask]; - MXLogDebug(@"[GroupParticipantsVC] Leave group %@ failed", _group.groupId); + MXLogDebug(@"[GroupParticipantsVC] Leave group %@ failed", self->_group.groupId); // Alert user [[AppDelegate theDelegate] showErrorAsAlert:error]; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h index 792865b96..fe0a504a7 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h @@ -63,9 +63,6 @@ /** Set the group for which the rooms are listed. Provide the related matrix session. - - @param group - @param mxSession */ - (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 855c46580..4f60c4970 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -79,6 +79,8 @@ // Adjust Top and Bottom constraints to take into account potential navBar and tabBar. [NSLayoutConstraint deactivateConstraints:@[_searchBarTopConstraint, _tableViewBottomConstraint]]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" _searchBarTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual @@ -94,6 +96,7 @@ attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[_searchBarTopConstraint, _tableViewBottomConstraint]]; @@ -203,13 +206,13 @@ // Indeed the group update notifications are triggered by the matrix session only for the user's groups. void (^success)(void) = ^void(void) { - [self refreshDisplayWithGroup:_group]; + [self refreshDisplayWithGroup:self->_group]; }; // Trigger a refresh on the group rooms. [self.mxSession updateGroupRooms:_group success:(isPreview ? success : nil) failure:^(NSError *error) { - MXLogDebug(@"[GroupRoomsViewController] viewWillAppear: group rooms update failed %@", _group.groupId); + MXLogDebug(@"[GroupRoomsViewController] viewWillAppear: group rooms update failed %@", self->_group.groupId); }]; } diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.h b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.h index e228101d4..faaab6b94 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.h +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.h @@ -40,9 +40,6 @@ /** Set the group for which the details are displayed. Provide the related matrix session. - - @param group - @param mxSession */ - (void)setGroup:(MXGroup*)group withMatrixSession:(MXSession*)mxSession; diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index be2fe5596..8527ba72c 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -1084,7 +1084,7 @@ MXRoomCreationParameters *roomCreationParameters = [MXRoomCreationParameters parametersForDirectRoomWithUser:matrixId]; roomCreationRequest = [self.mainSession createRoomWithParameters:roomCreationParameters success:^(MXRoom *room) { - roomCreationRequest = nil; + self->roomCreationRequest = nil; // Delay the call in order to be sure that the room is ready dispatch_async(dispatch_get_main_queue(), ^{ @@ -1096,7 +1096,7 @@ MXLogDebug(@"[ContactDetailsViewController] Create room failed"); - roomCreationRequest = nil; + self->roomCreationRequest = nil; [self removePendingActionMask]; diff --git a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m index 59d169d7f..d22de6e55 100644 --- a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m +++ b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m @@ -35,18 +35,6 @@ @implementation UnifiedSearchRecentsDataSource -- (instancetype)init -{ - self = [super init]; - if (self) - { - searchedRoomIdOrAliasSection = -1; - - _hideRecents = NO; - } - return self; -} - #pragma mark - - (void)setPublicRoomsDirectoryDataSource:(PublicRoomsDirectoryDataSource *)publicRoomsDirectoryDataSource diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index 8c1956330..7c8d816db 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -482,8 +482,8 @@ // Do it asynchronously to give time to messagesSearchViewController to be set up // so that it can display its loading wheel dispatch_async(dispatch_get_main_queue(), ^{ - [messagesSearchDataSource searchMessages:self.searchBar.text force:NO]; - messagesSearchViewController.shouldScrollToBottomOnRefresh = YES; + [self->messagesSearchDataSource searchMessages:self.searchBar.text force:NO]; + self->messagesSearchViewController.shouldScrollToBottomOnRefresh = YES; }); } } @@ -499,8 +499,8 @@ // Do it asynchronously to give time to filesSearchViewController to be set up // so that it can display its loading wheel dispatch_async(dispatch_get_main_queue(), ^{ - [filesSearchDataSource searchMessages:self.searchBar.text force:NO]; - filesSearchViewController.shouldScrollToBottomOnRefresh = YES; + [self->filesSearchDataSource searchMessages:self.searchBar.text force:NO]; + self->filesSearchViewController.shouldScrollToBottomOnRefresh = YES; }); } } diff --git a/Riot/Modules/Home/Fallback/AuthFallBackViewController.m b/Riot/Modules/Home/Fallback/AuthFallBackViewController.m index 93a770610..50f7b5f5c 100644 --- a/Riot/Modules/Home/Fallback/AuthFallBackViewController.m +++ b/Riot/Modules/Home/Fallback/AuthFallBackViewController.m @@ -157,7 +157,7 @@ NSString *FallBackViewControllerJavascriptOnLogin = @"window.matrixLogin.onLogin if ([urlString hasPrefix:@"js:"]) { // Listen only to scheme of the JS-WKWebView bridge - NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; + NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; diff --git a/Riot/Modules/Integrations/WidgetPermission/WidgetPermissionViewController.swift b/Riot/Modules/Integrations/WidgetPermission/WidgetPermissionViewController.swift index 2bb3a48bd..fbee5bb4b 100644 --- a/Riot/Modules/Integrations/WidgetPermission/WidgetPermissionViewController.swift +++ b/Riot/Modules/Integrations/WidgetPermission/WidgetPermissionViewController.swift @@ -218,8 +218,6 @@ extension WidgetPermissionViewController: SlidingModalPresentable { let widthConstraint = sizingViewContollerView.widthAnchor.constraint(equalToConstant: width) widthConstraint.isActive = true WidgetPermissionViewController.Sizing.widthConstraint = widthConstraint - - sizingViewContollerView.heightAnchor.constraint(equalToConstant: 0) } sizingViewContollerView.layoutIfNeeded() diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift index 0c33c5915..fd2ab986a 100644 --- a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift @@ -143,7 +143,7 @@ final class KeyBackupSetupSuccessFromRecoveryKeyViewController: UIViewController private func shareRecoveryKey() { // Set up activity view controller - let activityItems: [Any] = [ self.recoveryKey ] + let activityItems: [Any] = [ self.recoveryKey as Any ] let activityViewController = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) activityViewController.completionWithItemsHandler = { (activityType, completed, returnedItems, error) in diff --git a/Riot/Modules/MajorUpdate/MajorUpdateViewController.swift b/Riot/Modules/MajorUpdate/MajorUpdateViewController.swift index 0b57526ef..e10c7e715 100644 --- a/Riot/Modules/MajorUpdate/MajorUpdateViewController.swift +++ b/Riot/Modules/MajorUpdate/MajorUpdateViewController.swift @@ -165,8 +165,6 @@ extension MajorUpdateViewController: SlidingModalPresentable { let widthConstraint = sizingViewContollerView.widthAnchor.constraint(equalToConstant: width) widthConstraint.isActive = true MajorUpdateViewController.Sizing.widthConstraint = widthConstraint - - sizingViewContollerView.heightAnchor.constraint(equalToConstant: 0) } sizingViewContollerView.layoutIfNeeded() diff --git a/Riot/Modules/MatrixKit/Controllers/MXKAttachmentsViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKAttachmentsViewController.m index a21fbc396..06df81822 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKAttachmentsViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKAttachmentsViewController.m @@ -175,7 +175,11 @@ _attachmentsCollection.hidden = YES; // Display collection cell in full screen + + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" self.automaticallyAdjustsScrollViewInsets = NO; + #pragma clang diagnostic pop } - (BOOL)prefersStatusBarHidden diff --git a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m index 3465c136b..34789e133 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKAuthenticationViewController.m @@ -215,6 +215,8 @@ // and report the inputAccessoryView.superview of the firstResponder in self.keyboardView. } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)setKeyboardHeight:(CGFloat)keyboardHeight { // Deduce the bottom inset for the scroll view (Don't forget the potential tabBar) @@ -229,6 +231,7 @@ insets.bottom = scrollViewInsetBottom; self.authenticationScrollView.contentInset = insets; } +#pragma clang diagnostic pop - (void)destroy { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKCountryPickerViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKCountryPickerViewController.m index 273046244..80ea288f7 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKCountryPickerViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKCountryPickerViewController.m @@ -152,7 +152,7 @@ NSString* const kMXKCountryPickerViewControllerCountryCellId = @"kMXKCountryPick { UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; - searchController.dimsBackgroundDuringPresentation = NO; + searchController.obscuresBackgroundDuringPresentation = NO; searchController.hidesNavigationBarDuringPresentation = NO; searchController.searchResultsUpdater = self; diff --git a/Riot/Modules/MatrixKit/Controllers/MXKGroupListViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKGroupListViewController.m index e9950fa3f..b23a55720 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKGroupListViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKGroupListViewController.m @@ -92,6 +92,8 @@ [[[self class] nib] instantiateWithOwner:self options:nil]; } + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" // Adjust search bar Top constraint to take into account potential navBar. if (_groupsSearchBarTopConstraint) { @@ -123,6 +125,7 @@ [NSLayoutConstraint activateConstraints:@[_groupsTableViewBottomConstraint]]; } + #pragma clang diagnostic pop // Hide search bar by default [self hideSearchBar:YES]; @@ -209,6 +212,8 @@ self.keyboardView = _groupsSearchBar.inputAccessoryView.superview; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)setKeyboardHeight:(CGFloat)keyboardHeight { // Deduce the bottom constraint for the table view (Don't forget the potential tabBar) @@ -225,6 +230,7 @@ // Force layout immediately to take into account new constraint [self.view layoutIfNeeded]; } +#pragma clang diagnostic pop - (void)destroy { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKLanguagePickerViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKLanguagePickerViewController.m index 92d1a065c..b1c796356 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKLanguagePickerViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKLanguagePickerViewController.m @@ -160,7 +160,7 @@ NSString* const kMXKLanguagePickerCellDataKeyLanguage = @"language"; { UISearchController *searchController = [[UISearchController alloc] initWithSearchResultsController:nil]; - searchController.dimsBackgroundDuringPresentation = NO; + searchController.obscuresBackgroundDuringPresentation = NO; searchController.hidesNavigationBarDuringPresentation = NO; searchController.searchResultsUpdater = self; diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m index 828f84825..86cb1dbfe 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m @@ -97,6 +97,8 @@ [[[self class] nib] instantiateWithOwner:self options:nil]; } + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" // Adjust search bar Top constraint to take into account potential navBar. if (_recentsSearchBarTopConstraint) { @@ -126,6 +128,7 @@ _recentsTableViewBottomConstraint.active = YES; } + #pragma clang diagnostic pop // Hide search bar by default [self hideSearchBar:YES]; @@ -229,6 +232,8 @@ self.keyboardView = _recentsSearchBar.inputAccessoryView.superview; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)setKeyboardHeight:(CGFloat)keyboardHeight { // Deduce the bottom constraint for the table view (Don't forget the potential tabBar) @@ -245,6 +250,7 @@ // Force layout immediately to take into account new constraint [self.view layoutIfNeeded]; } +#pragma clang diagnostic pop - (void)destroy { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberListViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberListViewController.m index 217fb4758..f53ccc57a 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberListViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKRoomMemberListViewController.m @@ -105,6 +105,8 @@ // Adjust Top and Bottom constraints to take into account potential navBar and tabBar. [NSLayoutConstraint deactivateConstraints:@[_membersSearchBarTopConstraint, _membersTableViewBottomConstraint]]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" _membersSearchBarTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual @@ -120,6 +122,7 @@ attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[_membersSearchBarTopConstraint, _membersTableViewBottomConstraint]]; @@ -225,6 +228,8 @@ self.keyboardView = _membersSearchBar.inputAccessoryView.superview; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)setKeyboardHeight:(CGFloat)keyboardHeight { // Deduce the bottom constraint for the table view (Don't forget the potential tabBar) @@ -241,6 +246,7 @@ // Force layout immediately to take into account new constraint [self.view layoutIfNeeded]; } +#pragma clang diagnostic pop - (void)destroy { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKSearchViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKSearchViewController.m index 7ac637b33..8d6a03b18 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKSearchViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKSearchViewController.m @@ -76,6 +76,8 @@ // Adjust Top and Bottom constraints to take into account potential navBar and tabBar. [NSLayoutConstraint deactivateConstraints:@[_searchSearchBarTopConstraint, _searchTableViewBottomConstraint]]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" _searchSearchBarTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual @@ -91,6 +93,7 @@ attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[_searchSearchBarTopConstraint, _searchTableViewBottomConstraint]]; @@ -140,6 +143,8 @@ self.keyboardView = _searchSearchBar.inputAccessoryView.superview; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)setKeyboardHeight:(CGFloat)keyboardHeight { // Deduce the bottom constraint for the table view (Don't forget the potential tabBar) @@ -156,6 +161,7 @@ // Force layout immediately to take into account new constraint [self.view layoutIfNeeded]; } +#pragma clang diagnostic pop - (void)destroy { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKWebViewViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKWebViewViewController.m index 07c23b452..b96fe3bd5 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKWebViewViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKWebViewViewController.m @@ -133,6 +133,9 @@ NSString *const kMXKWebViewViewControllerJavaScriptEnableLog = multiplier:1.0 constant:0]; // Force webview in full height + + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:webView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual @@ -147,6 +150,7 @@ NSString *const kMXKWebViewViewControllerJavaScriptEnableLog = attribute:NSLayoutAttributeTop multiplier:1.0 constant:0]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[leftConstraint, rightConstraint, topConstraint, bottomConstraint]]; diff --git a/Riot/Modules/MatrixKit/Libs/SwiftUTI/UTI.swift b/Riot/Modules/MatrixKit/Libs/SwiftUTI/UTI.swift index c3d66c481..4ea8ea88d 100644 --- a/Riot/Modules/MatrixKit/Libs/SwiftUTI/UTI.swift +++ b/Riot/Modules/MatrixKit/Libs/SwiftUTI/UTI.swift @@ -104,7 +104,9 @@ public class UTI: RawRepresentable, Equatable { // UTTypeCreatePreferredIdentifierForTag only returns nil if the tag class is unknwown, which can't happen to us since we use an // enum of known values. Hence we can force-cast the result. + // swiftlint:disable force_unwrapping let identifier = (unmanagedIdentifier?.takeRetainedValue() as String?)! + // swiftlint:enable force_unwrapping self.init(rawValue: identifier) } @@ -122,7 +124,7 @@ public class UTI: RawRepresentable, Equatable { public convenience init(withExtension fileExtension: String, conformingTo conforming: UTI? = nil) { - self.init(withTagClass:.fileExtension, value: fileExtension, conformingTo: conforming) + self.init(withTagClass: .fileExtension, value: fileExtension, conformingTo: conforming) } /** @@ -138,7 +140,7 @@ public class UTI: RawRepresentable, Equatable { public convenience init(withMimeType mimeType: String, conformingTo conforming: UTI? = nil) { - self.init(withTagClass:.mimeType, value: mimeType, conformingTo: conforming) + self.init(withTagClass: .mimeType, value: mimeType, conformingTo: conforming) } #if os(macOS) @@ -146,7 +148,9 @@ public class UTI: RawRepresentable, Equatable { /** Initialize an UTI with a pasteboard type. - - Important: **This function is de-facto deprecated!** The old cocoa pasteboard types ( `NSStringPboardType`, `NSPDFPboardType`, etc) have been deprecated in favour of actual UTIs, and the constants are not available anymore in Swift. This function only works correctly with the values of these old constants, but _not_ with the replacement values (like `NSPasteboardTypeString` etc), since these already are UTIs. + - Important: **This function is de-facto deprecated!** The old cocoa pasteboard types ( `NSStringPboardType`, `NSPDFPboardType`, etc) have been deprecated in favour of actual UTIs, and the + constants are not available anymore in Swift. This function only works correctly with the values of these old constants, but _not_ with the replacement values (like `NSPasteboardTypeString` etc), since these + already are UTIs. - Parameters: - pbType: The pasteboard type (e.g. NSPDFPboardType). - conformingTo: If specified, the returned UTI must conform to this UTI. If nil is specified, this parameter is ignored. The default is nil. @@ -155,7 +159,7 @@ public class UTI: RawRepresentable, Equatable { */ public convenience init(withPBType pbType: String, conformingTo conforming: UTI? = nil) { - self.init(withTagClass:.pbType, value: pbType, conformingTo: conforming) + self.init(withTagClass: .pbType, value: pbType, conformingTo: conforming) } /** @@ -172,7 +176,7 @@ public class UTI: RawRepresentable, Equatable { public convenience init(withOSType osType: String, conformingTo conforming: UTI? = nil) { - self.init(withTagClass:.osType, value: osType, conformingTo: conforming) + self.init(withTagClass: .osType, value: osType, conformingTo: conforming) } #endif @@ -297,7 +301,7 @@ public class UTI: RawRepresentable, Equatable { return UTTypeConformsTo(self.rawCFValue, otherUTI.rawCFValue) as Bool } - public static func ==(lhs: UTI, rhs: UTI) -> Bool { + public static func == (lhs: UTI, rhs: UTI) -> Bool { return UTTypeEqual(lhs.rawCFValue, rhs.rawCFValue) as Bool } @@ -319,11 +323,11 @@ public class UTI: RawRepresentable, Equatable { /// Returns a uniform type’s declaration as a Dictionary, or nil if if no declaration for that type can be found. - public var declaration: [AnyHashable:Any]? { + public var declaration: [AnyHashable: Any]? { let unmanagedDeclaration = UTTypeCopyDeclaration(self.rawCFValue) - guard let declaration = unmanagedDeclaration?.takeRetainedValue() as? [AnyHashable:Any] else { + guard let declaration = unmanagedDeclaration?.takeRetainedValue() as? [AnyHashable: Any] else { return nil } @@ -356,137 +360,137 @@ public class UTI: RawRepresentable, Equatable { public extension UTI { - static let item = UTI(rawValue: kUTTypeItem as String) - static let content = UTI(rawValue: kUTTypeContent as String) - static let compositeContent = UTI(rawValue: kUTTypeCompositeContent as String) - static let message = UTI(rawValue: kUTTypeMessage as String) - static let contact = UTI(rawValue: kUTTypeContact as String) - static let archive = UTI(rawValue: kUTTypeArchive as String) - static let diskImage = UTI(rawValue: kUTTypeDiskImage as String) - static let data = UTI(rawValue: kUTTypeData as String) - static let directory = UTI(rawValue: kUTTypeDirectory as String) - static let resolvable = UTI(rawValue: kUTTypeResolvable as String) - static let symLink = UTI(rawValue: kUTTypeSymLink as String) - static let executable = UTI(rawValue: kUTTypeExecutable as String) - static let mountPoint = UTI(rawValue: kUTTypeMountPoint as String) - static let aliasFile = UTI(rawValue: kUTTypeAliasFile as String) - static let aliasRecord = UTI(rawValue: kUTTypeAliasRecord as String) - static let urlBookmarkData = UTI(rawValue: kUTTypeURLBookmarkData as String) - static let url = UTI(rawValue: kUTTypeURL as String) - static let fileURL = UTI(rawValue: kUTTypeFileURL as String) - static let text = UTI(rawValue: kUTTypeText as String) - static let plainText = UTI(rawValue: kUTTypePlainText as String) - static let utf8PlainText = UTI(rawValue: kUTTypeUTF8PlainText as String) - static let utf16ExternalPlainText = UTI(rawValue: kUTTypeUTF16ExternalPlainText as String) - static let utf16PlainText = UTI(rawValue: kUTTypeUTF16PlainText as String) - static let delimitedText = UTI(rawValue: kUTTypeDelimitedText as String) - static let commaSeparatedText = UTI(rawValue: kUTTypeCommaSeparatedText as String) - static let tabSeparatedText = UTI(rawValue: kUTTypeTabSeparatedText as String) - static let utf8TabSeparatedText = UTI(rawValue: kUTTypeUTF8TabSeparatedText as String) - static let rtf = UTI(rawValue: kUTTypeRTF as String) - static let html = UTI(rawValue: kUTTypeHTML as String) - static let xml = UTI(rawValue: kUTTypeXML as String) - static let sourceCode = UTI(rawValue: kUTTypeSourceCode as String) - static let assemblyLanguageSource = UTI(rawValue: kUTTypeAssemblyLanguageSource as String) - static let cSource = UTI(rawValue: kUTTypeCSource as String) - static let objectiveCSource = UTI(rawValue: kUTTypeObjectiveCSource as String) + static let item = UTI(rawValue: kUTTypeItem as String) + static let content = UTI(rawValue: kUTTypeContent as String) + static let compositeContent = UTI(rawValue: kUTTypeCompositeContent as String) + static let message = UTI(rawValue: kUTTypeMessage as String) + static let contact = UTI(rawValue: kUTTypeContact as String) + static let archive = UTI(rawValue: kUTTypeArchive as String) + static let diskImage = UTI(rawValue: kUTTypeDiskImage as String) + static let data = UTI(rawValue: kUTTypeData as String) + static let directory = UTI(rawValue: kUTTypeDirectory as String) + static let resolvable = UTI(rawValue: kUTTypeResolvable as String) + static let symLink = UTI(rawValue: kUTTypeSymLink as String) + static let executable = UTI(rawValue: kUTTypeExecutable as String) + static let mountPoint = UTI(rawValue: kUTTypeMountPoint as String) + static let aliasFile = UTI(rawValue: kUTTypeAliasFile as String) + static let aliasRecord = UTI(rawValue: kUTTypeAliasRecord as String) + static let urlBookmarkData = UTI(rawValue: kUTTypeURLBookmarkData as String) + static let url = UTI(rawValue: kUTTypeURL as String) + static let fileURL = UTI(rawValue: kUTTypeFileURL as String) + static let text = UTI(rawValue: kUTTypeText as String) + static let plainText = UTI(rawValue: kUTTypePlainText as String) + static let utf8PlainText = UTI(rawValue: kUTTypeUTF8PlainText as String) + static let utf16ExternalPlainText = UTI(rawValue: kUTTypeUTF16ExternalPlainText as String) + static let utf16PlainText = UTI(rawValue: kUTTypeUTF16PlainText as String) + static let delimitedText = UTI(rawValue: kUTTypeDelimitedText as String) + static let commaSeparatedText = UTI(rawValue: kUTTypeCommaSeparatedText as String) + static let tabSeparatedText = UTI(rawValue: kUTTypeTabSeparatedText as String) + static let utf8TabSeparatedText = UTI(rawValue: kUTTypeUTF8TabSeparatedText as String) + static let rtf = UTI(rawValue: kUTTypeRTF as String) + static let html = UTI(rawValue: kUTTypeHTML as String) + static let xml = UTI(rawValue: kUTTypeXML as String) + static let sourceCode = UTI(rawValue: kUTTypeSourceCode as String) + static let assemblyLanguageSource = UTI(rawValue: kUTTypeAssemblyLanguageSource as String) + static let cSource = UTI(rawValue: kUTTypeCSource as String) + static let objectiveCSource = UTI(rawValue: kUTTypeObjectiveCSource as String) @available( OSX 10.11, iOS 9.0, * ) - static let swiftSource = UTI(rawValue: kUTTypeSwiftSource as String) - static let cPlusPlusSource = UTI(rawValue: kUTTypeCPlusPlusSource as String) - static let objectiveCPlusPlusSource = UTI(rawValue: kUTTypeObjectiveCPlusPlusSource as String) - static let cHeader = UTI(rawValue: kUTTypeCHeader as String) - static let cPlusPlusHeader = UTI(rawValue: kUTTypeCPlusPlusHeader as String) - static let javaSource = UTI(rawValue: kUTTypeJavaSource as String) - static let script = UTI(rawValue: kUTTypeScript as String) - static let appleScript = UTI(rawValue: kUTTypeAppleScript as String) - static let osaScript = UTI(rawValue: kUTTypeOSAScript as String) - static let osaScriptBundle = UTI(rawValue: kUTTypeOSAScriptBundle as String) - static let javaScript = UTI(rawValue: kUTTypeJavaScript as String) - static let shellScript = UTI(rawValue: kUTTypeShellScript as String) - static let perlScript = UTI(rawValue: kUTTypePerlScript as String) - static let pythonScript = UTI(rawValue: kUTTypePythonScript as String) - static let rubyScript = UTI(rawValue: kUTTypeRubyScript as String) - static let phpScript = UTI(rawValue: kUTTypePHPScript as String) - static let json = UTI(rawValue: kUTTypeJSON as String) - static let propertyList = UTI(rawValue: kUTTypePropertyList as String) - static let xmlPropertyList = UTI(rawValue: kUTTypeXMLPropertyList as String) - static let binaryPropertyList = UTI(rawValue: kUTTypeBinaryPropertyList as String) - static let pdf = UTI(rawValue: kUTTypePDF as String) - static let rtfd = UTI(rawValue: kUTTypeRTFD as String) - static let flatRTFD = UTI(rawValue: kUTTypeFlatRTFD as String) - static let txnTextAndMultimediaData = UTI(rawValue: kUTTypeTXNTextAndMultimediaData as String) - static let webArchive = UTI(rawValue: kUTTypeWebArchive as String) - static let image = UTI(rawValue: kUTTypeImage as String) - static let jpeg = UTI(rawValue: kUTTypeJPEG as String) - static let jpeg2000 = UTI(rawValue: kUTTypeJPEG2000 as String) - static let tiff = UTI(rawValue: kUTTypeTIFF as String) - static let pict = UTI(rawValue: kUTTypePICT as String) - static let gif = UTI(rawValue: kUTTypeGIF as String) - static let png = UTI(rawValue: kUTTypePNG as String) - static let quickTimeImage = UTI(rawValue: kUTTypeQuickTimeImage as String) - static let appleICNS = UTI(rawValue: kUTTypeAppleICNS as String) - static let bmp = UTI(rawValue: kUTTypeBMP as String) - static let ico = UTI(rawValue: kUTTypeICO as String) - static let rawImage = UTI(rawValue: kUTTypeRawImage as String) - static let scalableVectorGraphics = UTI(rawValue: kUTTypeScalableVectorGraphics as String) + static let swiftSource = UTI(rawValue: kUTTypeSwiftSource as String) + static let cPlusPlusSource = UTI(rawValue: kUTTypeCPlusPlusSource as String) + static let objectiveCPlusPlusSource = UTI(rawValue: kUTTypeObjectiveCPlusPlusSource as String) + static let cHeader = UTI(rawValue: kUTTypeCHeader as String) + static let cPlusPlusHeader = UTI(rawValue: kUTTypeCPlusPlusHeader as String) + static let javaSource = UTI(rawValue: kUTTypeJavaSource as String) + static let script = UTI(rawValue: kUTTypeScript as String) + static let appleScript = UTI(rawValue: kUTTypeAppleScript as String) + static let osaScript = UTI(rawValue: kUTTypeOSAScript as String) + static let osaScriptBundle = UTI(rawValue: kUTTypeOSAScriptBundle as String) + static let javaScript = UTI(rawValue: kUTTypeJavaScript as String) + static let shellScript = UTI(rawValue: kUTTypeShellScript as String) + static let perlScript = UTI(rawValue: kUTTypePerlScript as String) + static let pythonScript = UTI(rawValue: kUTTypePythonScript as String) + static let rubyScript = UTI(rawValue: kUTTypeRubyScript as String) + static let phpScript = UTI(rawValue: kUTTypePHPScript as String) + static let json = UTI(rawValue: kUTTypeJSON as String) + static let propertyList = UTI(rawValue: kUTTypePropertyList as String) + static let xmlPropertyList = UTI(rawValue: kUTTypeXMLPropertyList as String) + static let binaryPropertyList = UTI(rawValue: kUTTypeBinaryPropertyList as String) + static let pdf = UTI(rawValue: kUTTypePDF as String) + static let rtfd = UTI(rawValue: kUTTypeRTFD as String) + static let flatRTFD = UTI(rawValue: kUTTypeFlatRTFD as String) + static let txnTextAndMultimediaData = UTI(rawValue: kUTTypeTXNTextAndMultimediaData as String) + static let webArchive = UTI(rawValue: kUTTypeWebArchive as String) + static let image = UTI(rawValue: kUTTypeImage as String) + static let jpeg = UTI(rawValue: kUTTypeJPEG as String) + static let jpeg2000 = UTI(rawValue: kUTTypeJPEG2000 as String) + static let tiff = UTI(rawValue: kUTTypeTIFF as String) + static let pict = UTI(rawValue: kUTTypePICT as String) + static let gif = UTI(rawValue: kUTTypeGIF as String) + static let png = UTI(rawValue: kUTTypePNG as String) + static let quickTimeImage = UTI(rawValue: kUTTypeQuickTimeImage as String) + static let appleICNS = UTI(rawValue: kUTTypeAppleICNS as String) + static let bmp = UTI(rawValue: kUTTypeBMP as String) + static let ico = UTI(rawValue: kUTTypeICO as String) + static let rawImage = UTI(rawValue: kUTTypeRawImage as String) + static let scalableVectorGraphics = UTI(rawValue: kUTTypeScalableVectorGraphics as String) @available(OSX 10.12, iOS 9.1, watchOS 2.1, *) - static let livePhoto = UTI(rawValue: kUTTypeLivePhoto as String) + static let livePhoto = UTI(rawValue: kUTTypeLivePhoto as String) @available(OSX 10.12, iOS 9.1, *) - static let audiovisualContent = UTI(rawValue: kUTTypeAudiovisualContent as String) - static let movie = UTI(rawValue: kUTTypeMovie as String) - static let video = UTI(rawValue: kUTTypeVideo as String) - static let audio = UTI(rawValue: kUTTypeAudio as String) - static let quickTimeMovie = UTI(rawValue: kUTTypeQuickTimeMovie as String) - static let mpeg = UTI(rawValue: kUTTypeMPEG as String) - static let mpeg2Video = UTI(rawValue: kUTTypeMPEG2Video as String) - static let mpeg2TransportStream = UTI(rawValue: kUTTypeMPEG2TransportStream as String) - static let mp3 = UTI(rawValue: kUTTypeMP3 as String) - static let mpeg4 = UTI(rawValue: kUTTypeMPEG4 as String) - static let mpeg4Audio = UTI(rawValue: kUTTypeMPEG4Audio as String) - static let appleProtectedMPEG4Audio = UTI(rawValue: kUTTypeAppleProtectedMPEG4Audio as String) - static let appleProtectedMPEG4Video = UTI(rawValue: kUTTypeAppleProtectedMPEG4Video as String) - static let aviMovie = UTI(rawValue: kUTTypeAVIMovie as String) - static let audioInterchangeFileFormat = UTI(rawValue: kUTTypeAudioInterchangeFileFormat as String) - static let waveformAudio = UTI(rawValue: kUTTypeWaveformAudio as String) - static let midiAudio = UTI(rawValue: kUTTypeMIDIAudio as String) - static let playlist = UTI(rawValue: kUTTypePlaylist as String) - static let m3UPlaylist = UTI(rawValue: kUTTypeM3UPlaylist as String) - static let folder = UTI(rawValue: kUTTypeFolder as String) - static let volume = UTI(rawValue: kUTTypeVolume as String) - static let package = UTI(rawValue: kUTTypePackage as String) - static let bundle = UTI(rawValue: kUTTypeBundle as String) - static let pluginBundle = UTI(rawValue: kUTTypePluginBundle as String) - static let spotlightImporter = UTI(rawValue: kUTTypeSpotlightImporter as String) - static let quickLookGenerator = UTI(rawValue: kUTTypeQuickLookGenerator as String) - static let xpcService = UTI(rawValue: kUTTypeXPCService as String) - static let framework = UTI(rawValue: kUTTypeFramework as String) - static let application = UTI(rawValue: kUTTypeApplication as String) - static let applicationBundle = UTI(rawValue: kUTTypeApplicationBundle as String) - static let applicationFile = UTI(rawValue: kUTTypeApplicationFile as String) - static let unixExecutable = UTI(rawValue: kUTTypeUnixExecutable as String) - static let windowsExecutable = UTI(rawValue: kUTTypeWindowsExecutable as String) - static let javaClass = UTI(rawValue: kUTTypeJavaClass as String) - static let javaArchive = UTI(rawValue: kUTTypeJavaArchive as String) - static let systemPreferencesPane = UTI(rawValue: kUTTypeSystemPreferencesPane as String) - static let gnuZipArchive = UTI(rawValue: kUTTypeGNUZipArchive as String) - static let bzip2Archive = UTI(rawValue: kUTTypeBzip2Archive as String) - static let zipArchive = UTI(rawValue: kUTTypeZipArchive as String) - static let spreadsheet = UTI(rawValue: kUTTypeSpreadsheet as String) - static let presentation = UTI(rawValue: kUTTypePresentation as String) - static let database = UTI(rawValue: kUTTypeDatabase as String) - static let vCard = UTI(rawValue: kUTTypeVCard as String) - static let toDoItem = UTI(rawValue: kUTTypeToDoItem as String) - static let calendarEvent = UTI(rawValue: kUTTypeCalendarEvent as String) - static let emailMessage = UTI(rawValue: kUTTypeEmailMessage as String) - static let internetLocation = UTI(rawValue: kUTTypeInternetLocation as String) - static let inkText = UTI(rawValue: kUTTypeInkText as String) - static let font = UTI(rawValue: kUTTypeFont as String) - static let bookmark = UTI(rawValue: kUTTypeBookmark as String) - static let _3DContent = UTI(rawValue: kUTType3DContent as String) - static let pkcs12 = UTI(rawValue: kUTTypePKCS12 as String) - static let x509Certificate = UTI(rawValue: kUTTypeX509Certificate as String) - static let electronicPublication = UTI(rawValue: kUTTypeElectronicPublication as String) - static let log = UTI(rawValue: kUTTypeLog as String) + static let audiovisualContent = UTI(rawValue: kUTTypeAudiovisualContent as String) + static let movie = UTI(rawValue: kUTTypeMovie as String) + static let video = UTI(rawValue: kUTTypeVideo as String) + static let audio = UTI(rawValue: kUTTypeAudio as String) + static let quickTimeMovie = UTI(rawValue: kUTTypeQuickTimeMovie as String) + static let mpeg = UTI(rawValue: kUTTypeMPEG as String) + static let mpeg2Video = UTI(rawValue: kUTTypeMPEG2Video as String) + static let mpeg2TransportStream = UTI(rawValue: kUTTypeMPEG2TransportStream as String) + static let mp3 = UTI(rawValue: kUTTypeMP3 as String) + static let mpeg4 = UTI(rawValue: kUTTypeMPEG4 as String) + static let mpeg4Audio = UTI(rawValue: kUTTypeMPEG4Audio as String) + static let appleProtectedMPEG4Audio = UTI(rawValue: kUTTypeAppleProtectedMPEG4Audio as String) + static let appleProtectedMPEG4Video = UTI(rawValue: kUTTypeAppleProtectedMPEG4Video as String) + static let aviMovie = UTI(rawValue: kUTTypeAVIMovie as String) + static let audioInterchangeFileFormat = UTI(rawValue: kUTTypeAudioInterchangeFileFormat as String) + static let waveformAudio = UTI(rawValue: kUTTypeWaveformAudio as String) + static let midiAudio = UTI(rawValue: kUTTypeMIDIAudio as String) + static let playlist = UTI(rawValue: kUTTypePlaylist as String) + static let m3UPlaylist = UTI(rawValue: kUTTypeM3UPlaylist as String) + static let folder = UTI(rawValue: kUTTypeFolder as String) + static let volume = UTI(rawValue: kUTTypeVolume as String) + static let package = UTI(rawValue: kUTTypePackage as String) + static let bundle = UTI(rawValue: kUTTypeBundle as String) + static let pluginBundle = UTI(rawValue: kUTTypePluginBundle as String) + static let spotlightImporter = UTI(rawValue: kUTTypeSpotlightImporter as String) + static let quickLookGenerator = UTI(rawValue: kUTTypeQuickLookGenerator as String) + static let xpcService = UTI(rawValue: kUTTypeXPCService as String) + static let framework = UTI(rawValue: kUTTypeFramework as String) + static let application = UTI(rawValue: kUTTypeApplication as String) + static let applicationBundle = UTI(rawValue: kUTTypeApplicationBundle as String) + static let applicationFile = UTI(rawValue: kUTTypeApplicationFile as String) + static let unixExecutable = UTI(rawValue: kUTTypeUnixExecutable as String) + static let windowsExecutable = UTI(rawValue: kUTTypeWindowsExecutable as String) + static let javaClass = UTI(rawValue: kUTTypeJavaClass as String) + static let javaArchive = UTI(rawValue: kUTTypeJavaArchive as String) + static let systemPreferencesPane = UTI(rawValue: kUTTypeSystemPreferencesPane as String) + static let gnuZipArchive = UTI(rawValue: kUTTypeGNUZipArchive as String) + static let bzip2Archive = UTI(rawValue: kUTTypeBzip2Archive as String) + static let zipArchive = UTI(rawValue: kUTTypeZipArchive as String) + static let spreadsheet = UTI(rawValue: kUTTypeSpreadsheet as String) + static let presentation = UTI(rawValue: kUTTypePresentation as String) + static let database = UTI(rawValue: kUTTypeDatabase as String) + static let vCard = UTI(rawValue: kUTTypeVCard as String) + static let toDoItem = UTI(rawValue: kUTTypeToDoItem as String) + static let calendarEvent = UTI(rawValue: kUTTypeCalendarEvent as String) + static let emailMessage = UTI(rawValue: kUTTypeEmailMessage as String) + static let internetLocation = UTI(rawValue: kUTTypeInternetLocation as String) + static let inkText = UTI(rawValue: kUTTypeInkText as String) + static let font = UTI(rawValue: kUTTypeFont as String) + static let bookmark = UTI(rawValue: kUTTypeBookmark as String) + static let _3DContent = UTI(rawValue: kUTType3DContent as String) + static let pkcs12 = UTI(rawValue: kUTTypePKCS12 as String) + static let x509Certificate = UTI(rawValue: kUTTypeX509Certificate as String) + static let electronicPublication = UTI(rawValue: kUTTypeElectronicPublication as String) + static let log = UTI(rawValue: kUTTypeLog as String) } #if os(OSX) diff --git a/Riot/Modules/MatrixKit/MatrixKit.h b/Riot/Modules/MatrixKit/MatrixKit.h index b6e5806f4..d9cf57cf0 100644 --- a/Riot/Modules/MatrixKit/MatrixKit.h +++ b/Riot/Modules/MatrixKit/MatrixKit.h @@ -69,7 +69,6 @@ #import "MXKRoomCreationView.h" #import "MXKRoomInputToolbarView.h" -#import "MXKRoomInputToolbarViewWithHPGrowingText.h" #import "MXKRoomDataSourceManager.h" diff --git a/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m b/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m index 9c37c1696..352e0ad6e 100644 --- a/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m +++ b/Riot/Modules/MatrixKit/Models/Account/MXKAccountManager.m @@ -104,6 +104,8 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa } } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)saveAccounts { NSDate *startDate = [NSDate date]; @@ -123,6 +125,7 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa MXLogDebug(@"[MXKAccountManager] saveAccounts. Done (result: %@) in %.0fms", @(result), [[NSDate date] timeIntervalSinceDate:startDate] * 1000); } +#pragma clang diagnostic pop - (void)addAccount:(MXKAccount *)account andOpenSession:(BOOL)openSession { @@ -608,6 +611,8 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa return [matrixKitCacheFolder stringByAppendingPathComponent:kMXKAccountsKey]; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)loadAccounts { MXLogDebug(@"[MXKAccountManager] loadAccounts"); @@ -675,6 +680,7 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa mxAccounts = [NSMutableArray array]; } } +#pragma clang diagnostic pop - (NSData*)encryptData:(NSData*)data { @@ -708,6 +714,8 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa return data; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)migrateAccounts { NSString *pathOld = [[MXKAppSettings cacheFolder] stringByAppendingPathComponent:kMXKAccountsKeyOld]; @@ -727,6 +735,7 @@ NSString *const MXKAccountManagerDataType = @"org.matrix.kit.MXKAccountManagerDa [fileManager removeItemAtPath:pathOld error:nil]; } } +#pragma clang diagnostic pop - (void)readAndWriteCredentials:(void (^)(NSArray * _Nullable readData, void (^completion)(BOOL didUpdateCredentials)))readAnWriteHandler { diff --git a/Riot/Modules/MatrixKit/Models/Contact/MXKContact.h b/Riot/Modules/MatrixKit/Models/Contact/MXKContact.h index 3d8e8af24..a927577e9 100644 --- a/Riot/Modules/MatrixKit/Models/Contact/MXKContact.h +++ b/Riot/Modules/MatrixKit/Models/Contact/MXKContact.h @@ -93,6 +93,8 @@ extern NSString *const kMXKContactDefaultContactPrefixId; */ - (void)resetMatrixThumbnail; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" /** The contact ID from native phonebook record */ @@ -105,6 +107,7 @@ extern NSString *const kMXKContactDefaultContactPrefixId; @return MXKContact instance */ - (id)initLocalContactWithABRecord:(ABRecordRef)record; +#pragma clang diagnostic pop /** Create a matrix contact with the dedicated info diff --git a/Riot/Modules/MatrixKit/Models/Contact/MXKContact.m b/Riot/Modules/MatrixKit/Models/Contact/MXKContact.m index 2b1e57727..f949b3a9b 100644 --- a/Riot/Modules/MatrixKit/Models/Contact/MXKContact.m +++ b/Riot/Modules/MatrixKit/Models/Contact/MXKContact.m @@ -40,6 +40,8 @@ NSString *const kMXKContactDefaultContactPrefixId = @"Default_"; @implementation MXKContact @synthesize isMatrixContact, isThirdPartyInvite; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + (NSString*)contactID:(ABRecordRef)record { return [NSString stringWithFormat:@"%@%d", kMXKContactLocalContactPrefixId, ABRecordGetRecordID(record)]; @@ -217,6 +219,7 @@ NSString *const kMXKContactDefaultContactPrefixId = @"Default_"; } return self; } +#pragma clang diagnostic pop - (id)initMatrixContactWithDisplayName:(NSString*)displayName andMatrixID:(NSString*)matrixID { diff --git a/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m b/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m index 52ac60a68..0ccf8096b 100644 --- a/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m +++ b/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m @@ -537,6 +537,8 @@ NSString *const MXKContactManagerDataType = @"org.matrix.kit.MXKContactManagerDa } } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" - (void)refreshLocalContacts { MXLogDebug(@"[MXKContactManager] refreshLocalContacts : Started"); @@ -721,6 +723,7 @@ NSString *const MXKContactManagerDataType = @"org.matrix.kit.MXKContactManagerDa }); } } +#pragma clang diagnostic pop - (void)updateMatrixIDsForLocalContact:(MXKContact *)contact { @@ -1582,6 +1585,9 @@ static NSString *matrixIDsDictFile = @"matrixIDsDictV2"; static NSString *localContactsFile = @"localContactsV2"; static NSString *contactsBookInfoFile = @"contactsV2"; +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + - (NSString*)dataFilePathForComponent:(NSString*)component { NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); @@ -1857,6 +1863,8 @@ static NSString *contactsBookInfoFile = @"contactsV2"; } } +#pragma clang diagnostic pop + - (BOOL)encryptAndSaveData:(NSData*)data toFile:(NSString*)fileName { NSError *error = nil; diff --git a/Riot/Modules/MatrixKit/Models/MXKAppSettings.m b/Riot/Modules/MatrixKit/Models/MXKAppSettings.m index 88aa527f7..c0984a6da 100644 --- a/Riot/Modules/MatrixKit/Models/MXKAppSettings.m +++ b/Riot/Modules/MatrixKit/Models/MXKAppSettings.m @@ -670,6 +670,8 @@ static NSString *const kMXAppGroupID = @"group.org.matrix"; } } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (NSString*)phonebookCountryCode { NSString* res = phonebookCountryCode; @@ -699,6 +701,7 @@ static NSString *const kMXAppGroupID = @"group.org.matrix"; return res; } +#pragma clang diagnostic pop - (void)setPhonebookCountryCode:(NSString *)stringValue { diff --git a/Riot/Modules/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h b/Riot/Modules/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h index 0748f1e62..c03c4c4de 100644 --- a/Riot/Modules/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h +++ b/Riot/Modules/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h @@ -30,8 +30,8 @@ extern NSString *const kMXKRecentCellIdentifier; /** The recents data source based on a unique matrix session. + Deprecated: Please see MXSession.roomListDataManager */ -MXK_DEPRECATED_ATTRIBUTE_WITH_MSG("See MXSession.roomListDataManager") @interface MXKSessionRecentsDataSource : MXKDataSource { @protected diff --git a/Riot/Modules/MatrixKit/Utils/MXKConstants.h b/Riot/Modules/MatrixKit/Utils/MXKConstants.h index b580d234e..7a5659b8c 100644 --- a/Riot/Modules/MatrixKit/Utils/MXKConstants.h +++ b/Riot/Modules/MatrixKit/Utils/MXKConstants.h @@ -17,9 +17,6 @@ #import -#define MXK_DEPRECATED_ATTRIBUTE __attribute__((deprecated)) -#define MXK_DEPRECATED_ATTRIBUTE_WITH_MSG(msg) __attribute((deprecated((msg)))) - /** The Matrix iOS Kit version. */ diff --git a/Riot/Modules/MatrixKit/Utils/MXKDocumentPickerPresenter.swift b/Riot/Modules/MatrixKit/Utils/MXKDocumentPickerPresenter.swift index 1f9b9c89c..0ff493e30 100644 --- a/Riot/Modules/MatrixKit/Utils/MXKDocumentPickerPresenter.swift +++ b/Riot/Modules/MatrixKit/Utils/MXKDocumentPickerPresenter.swift @@ -24,7 +24,8 @@ import MobileCoreServices /// MXKDocumentPickerPresenter presents a controller that provides access to documents or destinations outside the app’s sandbox. /// Internally presents a UIDocumentPickerViewController in UIDocumentPickerMode.import. -/// Note: You must turn on the iCloud Documents capabilities in Xcode (see https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/DocumentPickerProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40014451) +/// Note: You must turn on the iCloud Documents capabilities in Xcode +/// (see https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/DocumentPickerProgrammingGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40014451) @objcMembers public class MXKDocumentPickerPresenter: NSObject { diff --git a/Riot/Modules/MatrixKit/Utils/MXKTools.m b/Riot/Modules/MatrixKit/Utils/MXKTools.m index c941fbc98..7e3231324 100644 --- a/Riot/Modules/MatrixKit/Utils/MXKTools.m +++ b/Riot/Modules/MatrixKit/Utils/MXKTools.m @@ -1112,7 +1112,7 @@ manualChangeMessageForVideo:(NSString*)manualChangeMessageForVideo // Caution: We need here to escape the non-ASCII characters (like '#' in room alias) // to convert the link into a legal URL string. NSString *link = [attributedString.string substringWithRange:match.range]; - link = [link stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; + link = [link stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; [*mutableAttributedString addAttribute:NSLinkAttributeName value:link range:match.range]; } }]; diff --git a/Riot/Modules/MatrixKit/Utils/MXKUTI.swift b/Riot/Modules/MatrixKit/Utils/MXKUTI.swift index 911beec65..87822cd7d 100644 --- a/Riot/Modules/MatrixKit/Utils/MXKUTI.swift +++ b/Riot/Modules/MatrixKit/Utils/MXKUTI.swift @@ -20,7 +20,7 @@ import MobileCoreServices // We do not use the SwiftUTI pod anymore // The library is embedded in MatrixKit. See Libs/SwiftUTI/README.md for more details -//import SwiftUTI +// import SwiftUTI /// MXKUTI represents a Universal Type Identifier (e.g. kUTTypePNG). /// See https://developer.apple.com/library/archive/documentation/FileManagement/Conceptual/understanding_utis/understand_utis_conc/understand_utis_conc.html#//apple_ref/doc/uid/TP40001319-CH202-SW5 for more information. @@ -134,6 +134,8 @@ extension MXKUTI { self.init(rawValue: uti as String) } + // swiftlint:disable unused_optional_binding + /// Initialize with local file URL. /// This method is currently applicable only to URLs for file system resources. /// @@ -153,6 +155,8 @@ extension MXKUTI { } } + // swiftlint:enable unused_optional_binding + public convenience init?(localFileURL: URL) { self.init(localFileURL: localFileURL, loadResourceValues: true) } @@ -173,6 +177,8 @@ extension MXKUTI { } } +// swiftlint:disable force_unwrapping + // MARK: - Some system defined UTIs extension MXKUTI { public static let data = MXKUTI(cfRawValue: kUTTypeData)! @@ -190,6 +196,8 @@ extension MXKUTI { public static let xml = MXKUTI(cfRawValue: kUTTypeXML)! } +// swiftlint:enable force_unwrapping + // MARK: - Convenience static methods extension MXKUTI { diff --git a/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationFallbackWebView.m b/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationFallbackWebView.m index 09c50ffc6..ad44e34d8 100644 --- a/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationFallbackWebView.m +++ b/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationFallbackWebView.m @@ -120,7 +120,7 @@ sendObjectMessage({ \ MXLogDebug(@"[MXKAuthenticationFallbackWebView] URL has js: prefix"); // Listen only to scheme of the JS-WKWebView bridge - NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; + NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByRemovingPercentEncoding]; NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; diff --git a/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m b/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m index 8e3bfa6fa..cfcafc744 100644 --- a/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m +++ b/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m @@ -102,7 +102,7 @@ var onloadCallback = function() { \ if ([urlString hasPrefix:@"js:"]) { // Listen only to scheme of the JS-WKWebView bridge - NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByReplacingPercentEscapesUsingEncoding:NSASCIIStringEncoding]; + NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; diff --git a/Riot/Modules/MatrixKit/Views/EncryptionInfoView/MXKEncryptionInfoView.m b/Riot/Modules/MatrixKit/Views/EncryptionInfoView/MXKEncryptionInfoView.m index a6537cbd5..cc6c3175e 100644 --- a/Riot/Modules/MatrixKit/Views/EncryptionInfoView/MXKEncryptionInfoView.m +++ b/Riot/Modules/MatrixKit/Views/EncryptionInfoView/MXKEncryptionInfoView.m @@ -417,7 +417,7 @@ static NSAttributedString *verticalWhitespace = nil; [_mxSession.crypto setDeviceVerification:MXDeviceVerified forDevice:_mxDeviceInfo.deviceId ofUser:_mxDeviceInfo.userId success:^{ // Refresh data - _mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent]; + self->_mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent]; if (self->_delegate) { [self->_delegate encryptionInfoView:self didDeviceInfoVerifiedChange:self.mxDeviceInfo]; @@ -473,7 +473,7 @@ static NSAttributedString *verticalWhitespace = nil; [_mxSession.crypto setDeviceVerification:verificationStatus forDevice:_mxDeviceInfo.deviceId ofUser:_mxDeviceInfo.userId success:^{ // Refresh data - _mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent]; + self->_mxDeviceInfo = [self.mxSession.crypto eventDeviceInfo:self.mxEvent]; if (self->_delegate) { diff --git a/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.h b/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.h deleted file mode 100644 index b10b54fa6..000000000 --- a/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright 2015 OpenMarket 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 "MXKRoomInputToolbarView.h" - -#import - -/** - `MXKRoomInputToolbarViewWithHPGrowingText` is a MXKRoomInputToolbarView-inherited class in which message - composer is based on `HPGrowingTextView`. - - Toolbar buttons are not overridden by this class. We keep the default implementation. - */ -@interface MXKRoomInputToolbarViewWithHPGrowingText : MXKRoomInputToolbarView -{ -@protected - HPGrowingTextView *growingTextView; -} - -@end diff --git a/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.m b/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.m deleted file mode 100644 index fe5f87ff7..000000000 --- a/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.m +++ /dev/null @@ -1,187 +0,0 @@ -/* - Copyright 2015 OpenMarket Ltd - Copyright 2017 Vector Creations Ltd - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import "MXKRoomInputToolbarViewWithHPGrowingText.h" - -@interface MXKRoomInputToolbarViewWithHPGrowingText() -{ - // HPGrowingTextView triggers growingTextViewDidChange event when it recomposes itself - // Save the last edited text to prevent unexpected typing events - NSString* lastEditedText; -} - -/** - Message composer defined in `messageComposerContainer`. - */ -@property (nonatomic) IBOutlet HPGrowingTextView *growingTextView; - -@end - -@implementation MXKRoomInputToolbarViewWithHPGrowingText -@synthesize growingTextView; - -+ (UINib *)nib -{ - return [UINib nibWithNibName:NSStringFromClass([MXKRoomInputToolbarViewWithHPGrowingText class]) - bundle:[NSBundle bundleForClass:[MXKRoomInputToolbarViewWithHPGrowingText class]]]; -} - -- (void)awakeFromNib -{ - [super awakeFromNib]; - - // Handle message composer based on HPGrowingTextView use - growingTextView.delegate = self; - - [growingTextView setTranslatesAutoresizingMaskIntoConstraints: NO]; - - // Add an accessory view to the text view in order to retrieve keyboard view. - inputAccessoryView = [[UIView alloc] initWithFrame:CGRectZero]; - growingTextView.internalTextView.inputAccessoryView = self.inputAccessoryView; - - // on IOS 8, the growing textview animation could trigger weird UI animations - // indeed, the messages tableView can be refreshed while its height is updated (e.g. when setting a message) - growingTextView.animateHeightChange = NO; - - lastEditedText = nil; -} - -- (void)dealloc -{ - [self destroy]; -} - --(void)customizeViewRendering -{ - [super customizeViewRendering]; - - // set text input font - growingTextView.font = [UIFont systemFontOfSize:14]; - - // draw a rounded border around the textView - growingTextView.layer.cornerRadius = 5; - growingTextView.layer.borderWidth = 1; - growingTextView.layer.borderColor = [UIColor lightGrayColor].CGColor; - growingTextView.clipsToBounds = YES; - growingTextView.backgroundColor = [UIColor whiteColor]; -} - -- (void)destroy -{ - if (growingTextView) - { - growingTextView.delegate = nil; - growingTextView = nil; - } - - [super destroy]; -} - -- (void)setMaxHeight:(CGFloat)maxHeight -{ - growingTextView.maxHeight = maxHeight - (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant); - [growingTextView refreshHeight]; - - super.maxHeight = maxHeight; -} - -- (NSString*)textMessage -{ - return growingTextView.text; -} - -- (void)setTextMessage:(NSString *)textMessage -{ - growingTextView.text = textMessage; - self.rightInputToolbarButton.enabled = textMessage.length; -} - -- (void)pasteText:(NSString *)text -{ - self.textMessage = [growingTextView.text stringByReplacingCharactersInRange:growingTextView.selectedRange withString:text]; -} - -- (void)setPlaceholder:(NSString *)inPlaceholder -{ - [super setPlaceholder:inPlaceholder]; - growingTextView.placeholder = inPlaceholder; -} - -- (BOOL)becomeFirstResponder -{ - return [growingTextView becomeFirstResponder]; -} - -- (void)dismissKeyboard -{ - [growingTextView resignFirstResponder]; -} - -#pragma mark - HPGrowingTextView delegate - -- (void)growingTextViewDidEndEditing:(HPGrowingTextView *)sender -{ - if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:isTyping:)]) - { - [self.delegate roomInputToolbarView:self isTyping:NO]; - } -} - -- (void)growingTextViewDidChange:(HPGrowingTextView *)sender -{ - NSString *msg = growingTextView.text; - - // HPGrowingTextView triggers growingTextViewDidChange event when it recomposes itself. - // Save the last edited text to prevent unexpected typing events - if (![lastEditedText isEqualToString:msg]) - { - lastEditedText = msg; - if (msg.length) - { - if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:isTyping:)]) - { - [self.delegate roomInputToolbarView:self isTyping:YES]; - } - self.rightInputToolbarButton.enabled = YES; - } - else - { - if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:isTyping:)]) - { - [self.delegate roomInputToolbarView:self isTyping:NO]; - } - self.rightInputToolbarButton.enabled = NO; - } - } -} - -- (void)growingTextView:(HPGrowingTextView *)growingTextView willChangeHeight:(float)height -{ - // Update growing text's superview (toolbar view) - CGFloat updatedHeight = height + (self.messageComposerContainerTopConstraint.constant + self.messageComposerContainerBottomConstraint.constant); - if ([self.delegate respondsToSelector:@selector(roomInputToolbarView:heightDidChanged:completion:)]) - { - [self.delegate roomInputToolbarView:self heightDidChanged:updatedHeight completion:nil]; - } -} - -- (BOOL)growingTextView:(HPGrowingTextView *)growingTextView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text -{ - return self.isEditable; -} - -@end diff --git a/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.xib b/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.xib deleted file mode 100644 index 3f4117499..000000000 --- a/Riot/Modules/MatrixKit/Views/RoomInputToolbar/MXKRoomInputToolbarViewWithHPGrowingText.xib +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Riot/Modules/Onboarding/OnboardingCoordinatorBridgePresenter.swift b/Riot/Modules/Onboarding/OnboardingCoordinatorBridgePresenter.swift index 9cc43c1b1..32f433936 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinatorBridgePresenter.swift @@ -28,7 +28,8 @@ class OnboardingCoordinatorBridgePresenterParameters: NSObject { /// OnboardingCoordinatorBridgePresenter enables to start OnboardingCoordinator from a view controller. /// This bridge is used while waiting for global usage of coordinator pattern. -/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. +/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers). Each bridge should be removed +/// once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class OnboardingCoordinatorBridgePresenter: NSObject { diff --git a/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorBridgePresenter.swift b/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorBridgePresenter.swift index 1e0dab2f8..b908e5cb0 100644 --- a/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorBridgePresenter.swift @@ -58,7 +58,6 @@ final class EditHistoryCoordinatorBridgePresenter: NSObject { func present(from viewController: UIViewController, animated: Bool) { guard let formatter = self.createEventFormatter(session: self.session) else { - //s das return } diff --git a/Riot/Modules/Room/EmojiPicker/EmojiPickerViewController.swift b/Riot/Modules/Room/EmojiPicker/EmojiPickerViewController.swift index 47349e326..b9d2beb85 100644 --- a/Riot/Modules/Room/EmojiPicker/EmojiPickerViewController.swift +++ b/Riot/Modules/Room/EmojiPicker/EmojiPickerViewController.swift @@ -164,7 +164,7 @@ final class EmojiPickerViewController: UIViewController { private func setupSearchController() { let searchController = UISearchController(searchResultsController: nil) - searchController.dimsBackgroundDuringPresentation = false + searchController.obscuresBackgroundDuringPresentation = false searchController.searchResultsUpdater = self searchController.searchBar.placeholder = VectorL10n.searchDefaultPlaceholder searchController.hidesNavigationBarDuringPresentation = false diff --git a/Riot/Modules/Room/MXKRoomViewController.m b/Riot/Modules/Room/MXKRoomViewController.m index 0028f45f3..702802342 100644 --- a/Riot/Modules/Room/MXKRoomViewController.m +++ b/Riot/Modules/Room/MXKRoomViewController.m @@ -228,6 +228,8 @@ [[[self class] nib] instantiateWithOwner:self options:nil]; } + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" // Adjust bottom constraint of the input toolbar container in order to take into account potential tabBar _roomInputToolbarContainerBottomConstraint.active = NO; _roomInputToolbarContainerBottomConstraint = [NSLayoutConstraint constraintWithItem:self.bottomLayoutGuide @@ -237,6 +239,8 @@ attribute:NSLayoutAttributeBottom multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop + _roomInputToolbarContainerBottomConstraint.active = YES; [self.view setNeedsUpdateConstraints]; @@ -419,6 +423,8 @@ }); } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" // The 2 following methods are deprecated since iOS 8 - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { @@ -446,6 +452,7 @@ self->isSizeTransitionInProgress = NO; }); } +#pragma clang diagnostic pop - (void)viewDidLayoutSubviews { @@ -488,6 +495,8 @@ self.keyboardView = keyboardView; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated" - (void)setKeyboardHeight:(CGFloat)keyboardHeight { // Deduce the bottom constraint for the input toolbar view (Don't forget the potential tabBar) @@ -531,6 +540,7 @@ super.keyboardHeight = keyboardHeight; } +#pragma clang diagnostic pop - (void)destroy { @@ -1046,7 +1056,7 @@ [titleView destroy]; } - titleView = self.navigationItem.titleView = [roomTitleViewClass roomTitleView]; + self.navigationItem.titleView = titleView = [roomTitleViewClass roomTitleView]; titleView.delegate = self; // Define directly the navigation titleView with the custom title view instance. Do not use anymore a container. @@ -2116,6 +2126,8 @@ self->eventDetailsView = eventDetailsView; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" [self.view addConstraint:[NSLayoutConstraint constraintWithItem:eventDetailsView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual @@ -2131,6 +2143,7 @@ attribute:NSLayoutAttributeTop multiplier:1.0f constant:-10.0f]]; + #pragma clang diagnostic pop [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeLeading diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 0c8cee07f..bdf4465b6 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -102,6 +102,8 @@ // Adjust Top and Bottom constraints to take into account potential navBar and tabBar. [NSLayoutConstraint deactivateConstraints:@[_searchBarTopConstraint]]; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" _searchBarTopConstraint = [NSLayoutConstraint constraintWithItem:self.topLayoutGuide attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual @@ -109,6 +111,7 @@ attribute:NSLayoutAttributeTop multiplier:1.0f constant:0.0f]; + #pragma clang diagnostic pop [NSLayoutConstraint activateConstraints:@[_searchBarTopConstraint]]; @@ -850,7 +853,7 @@ pendingMaskSpinnerView.alpha = 0; [UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ - pendingMaskSpinnerView.alpha = 1; + self->pendingMaskSpinnerView.alpha = 1; } completion:^(BOOL finished) { }]; diff --git a/Riot/Modules/Room/RoomCoordinatorBridgePresenter.swift b/Riot/Modules/Room/RoomCoordinatorBridgePresenter.swift index bd6b70d77..017b8b6e8 100644 --- a/Riot/Modules/Room/RoomCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Room/RoomCoordinatorBridgePresenter.swift @@ -62,7 +62,8 @@ class RoomCoordinatorBridgePresenterParameters: NSObject { /// RoomCoordinatorBridgePresenter enables to start RoomCoordinator from a view controller. /// This bridge is used while waiting for global usage of coordinator pattern. -/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. +/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers). Each bridge should be removed +/// once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class RoomCoordinatorBridgePresenter: NSObject { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index ce081145f..d5f40da02 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -90,7 +90,7 @@ NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNo NSNotificationName const RoomGroupCallTileTappedNotification = @"RoomGroupCallTileTappedNotification"; const NSTimeInterval kResizeComposerAnimationDuration = .05; -@interface RoomViewController () @@ -2585,7 +2585,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; self.bubblesTableViewTopConstraint.constant = self.previewHeaderContainerHeightConstraint.constant - self.bubblesTableView.adjustedContentInset.top; - previewHeader.roomAvatar.alpha = 1; + self->previewHeader.roomAvatar.alpha = 1; // Force to render the view [self forceLayoutRefresh]; @@ -5735,6 +5735,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; self->encryptionInfoView = encryptionInfoView; + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wdeprecated" [self.view addConstraint:[NSLayoutConstraint constraintWithItem:encryptionInfoView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual @@ -5750,6 +5752,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; attribute:NSLayoutAttributeTop multiplier:1.0f constant:-10.0f]]; + #pragma clang diagnostic pop [self.view addConstraint:[NSLayoutConstraint constraintWithItem:self.view attribute:NSLayoutAttributeLeading @@ -5829,19 +5832,19 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn animations:^{ - readMarkerTableViewCell.readMarkerViewLeadingConstraint.constant = readMarkerTableViewCell.readMarkerViewTrailingConstraint.constant = readMarkerTableViewCell.bubbleOverlayContainer.frame.size.width / 2; - readMarkerTableViewCell.readMarkerView.alpha = 0; + self->readMarkerTableViewCell.readMarkerViewLeadingConstraint.constant = self->readMarkerTableViewCell.readMarkerViewTrailingConstraint.constant = self->readMarkerTableViewCell.bubbleOverlayContainer.frame.size.width / 2; + self->readMarkerTableViewCell.readMarkerView.alpha = 0; // Force to render the view - [readMarkerTableViewCell.bubbleOverlayContainer layoutIfNeeded]; + [self->readMarkerTableViewCell.bubbleOverlayContainer layoutIfNeeded]; } completion:^(BOOL finished){ - readMarkerTableViewCell.readMarkerView.hidden = YES; - readMarkerTableViewCell.readMarkerView.alpha = 1; + self->readMarkerTableViewCell.readMarkerView.hidden = YES; + self->readMarkerTableViewCell.readMarkerView.alpha = 1; - readMarkerTableViewCell = nil; + self->readMarkerTableViewCell = nil; }]; }); diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index 7d830ecb3..8097ca2b0 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -352,8 +352,8 @@ // Do it asynchronously to give time to messagesSearchViewController to be set up // so that it can display its loading wheel dispatch_async(dispatch_get_main_queue(), ^{ - [messagesSearchDataSource searchMessages:self.searchBar.text force:NO]; - messagesSearchViewController.shouldScrollToBottomOnRefresh = YES; + [self->messagesSearchDataSource searchMessages:self.searchBar.text force:NO]; + self->messagesSearchViewController.shouldScrollToBottomOnRefresh = YES; }); } } @@ -365,8 +365,8 @@ // Do it asynchronously to give time to filesSearchViewController to be set up // so that it can display its loading wheel dispatch_async(dispatch_get_main_queue(), ^{ - [filesSearchDataSource searchMessages:self.searchBar.text force:NO]; - filesSearchViewController.shouldScrollToBottomOnRefresh = YES; + [self->filesSearchDataSource searchMessages:self.searchBar.text force:NO]; + self->filesSearchViewController.shouldScrollToBottomOnRefresh = YES; }); } } diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index cb15df862..f32e4cc68 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -484,6 +484,8 @@ #pragma mark - UITextViewDelegate +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { if ([[URL absoluteString] isEqualToString:@"onResendLink"]) @@ -559,6 +561,7 @@ return YES; } +#pragma clang diagnostic pop #pragma mark - UIGestureRecognizerDelegate diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.m b/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.m index b0a2fba49..555733c7f 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.m @@ -1549,6 +1549,8 @@ static NSMutableDictionary *childClasses; return shouldInteractWithURL; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-implementations" // Delegate method only called on iOS 9. iOS 10+ use method above. - (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange { @@ -1571,6 +1573,7 @@ static NSMutableDictionary *childClasses; return shouldInteractWithURL; } +#pragma clang diagnostic pop #pragma mark - WKNavigationDelegate diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m index a5bf789d6..91f62a8d6 100644 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m @@ -92,7 +92,7 @@ // Accept the received requests from this device [self.mxSession.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ - onComplete(); + self->onComplete(); }]; } }]]; @@ -110,7 +110,7 @@ // Ignore all pending requests from this device [self.mxSession.crypto ignoreAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ - onComplete(); + self->onComplete(); }]; } }]]; @@ -169,7 +169,7 @@ // As the device is now verified, all other key requests will be automatically accepted. [self.mxSession.crypto acceptAllPendingKeyRequestsFromUser:self.device.userId andDevice:self.device.deviceId onComplete:^{ - onComplete(); + self->onComplete(); }]; } else diff --git a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift index 911f08302..23b48397e 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift @@ -103,7 +103,7 @@ final class SecretsRecoveryWithKeyViewController: UIViewController { switch self.viewModel.recoveryGoal { case .default, .keyBackup, .restoreSecureBackup: informationText = VectorL10n.secretsRecoveryWithKeyInformationDefault - case .unlockSecureBackup(_): + case .unlockSecureBackup: informationText = VectorL10n.secretsRecoveryWithKeyInformationUnlockSecureBackupWithKey case .verifyDevice: informationText = VectorL10n.secretsRecoveryWithKeyInformationVerifyDevice diff --git a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift index 5c64fd51b..0578f2b37 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift @@ -106,7 +106,7 @@ final class SecretsRecoveryWithPassphraseViewController: UIViewController { switch self.viewModel.recoveryGoal { case .default, .keyBackup, .restoreSecureBackup: informationText = VectorL10n.secretsRecoveryWithPassphraseInformationDefault - case .unlockSecureBackup(_): + case .unlockSecureBackup: informationText = VectorL10n.secretsRecoveryWithKeyInformationUnlockSecureBackupWithPhrase case .verifyDevice: informationText = VectorL10n.secretsRecoveryWithPassphraseInformationVerifyDevice diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index d009b7b6e..a1964925e 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -258,7 +258,9 @@ TableViewSectionsDelegate> @property (nonatomic) UNNotificationSettings *systemNotificationSettings; @property (nonatomic, weak) DeactivateAccountViewController *deactivateAccountViewController; + @property (nonatomic, strong) NotificationSettingsCoordinatorBridgePresenter *notificationSettingsBridgePresenter; + @property (nonatomic, strong) SignOutAlertPresenter *signOutAlertPresenter; @property (nonatomic, weak) UIButton *signOutButton; @property (nonatomic, strong) SingleImagePickerPresenter *imagePickerPresenter; diff --git a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift index 60c942176..bbd8b5a90 100644 --- a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift +++ b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewController.swift @@ -219,7 +219,11 @@ class SpaceDetailViewController: UIViewController { self.inviterPanelHeight.constant = 0 } - let avatarViewData = AvatarViewData(matrixItemId: parameters.spaceId, displayName: parameters.displayName, avatarUrl: parameters.avatarUrl, mediaManager: self.mediaManager, fallbackImage: .matrixItem(parameters.spaceId, parameters.displayName)) + let avatarViewData = AvatarViewData(matrixItemId: parameters.spaceId, + displayName: parameters.displayName, + avatarUrl: parameters.avatarUrl, + mediaManager: self.mediaManager, + fallbackImage: .matrixItem(parameters.spaceId, parameters.displayName)) self.titleLabel.text = parameters.displayName self.avatarView.fill(with: avatarViewData) diff --git a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift index 46bb2b1f1..df57aeba0 100644 --- a/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift +++ b/Riot/Modules/Spaces/SpaceDetail/SpaceDetailViewModel.swift @@ -76,14 +76,30 @@ class SpaceDetailViewModel: SpaceDetailViewModelType { private func loadData() { if let publicRoom = self.publicRoom { - self.update(viewState: .loaded(SpaceDetailLoadedParameters(spaceId: publicRoom.roomId, displayName: publicRoom.displayname(), topic: publicRoom.topic, avatarUrl: publicRoom.avatarUrl, joinRule: publicRoom.worldReadable ? .public : .private, membership: .unknown, inviterId: nil, inviter: nil, membersCount: UInt(publicRoom.numJoinedMembers)))) + self.update(viewState: .loaded(SpaceDetailLoadedParameters(spaceId: publicRoom.roomId, + displayName: publicRoom.displayname(), + topic: publicRoom.topic, + avatarUrl: publicRoom.avatarUrl, + joinRule: publicRoom.worldReadable ? .public : .private, + membership: .unknown, + inviterId: nil, + inviter: nil, + membersCount: UInt(publicRoom.numJoinedMembers)))) } else { guard let space = self.session.spaceService.getSpace(withId: self.spaceId), let summary = space.summary else { MXLog.error("[SpaceDetailViewModel] setupViews: no space found") return } - let parameters = SpaceDetailLoadedParameters(spaceId: space.spaceId, displayName: summary.displayname, topic: summary.topic, avatarUrl: summary.avatar, joinRule: nil, membership: summary.membership, inviterId: nil, inviter: nil, membersCount: 0) + let parameters = SpaceDetailLoadedParameters(spaceId: space.spaceId, + displayName: summary.displayname, + topic: summary.topic, + avatarUrl: summary.avatar, + joinRule: nil, + membership: summary.membership, + inviterId: nil, + inviter: nil, + membersCount: 0) self.update(viewState: .loaded(parameters)) self.update(viewState: .loading) @@ -103,7 +119,15 @@ class SpaceDetailViewModel: SpaceDetailViewModelType { } }) - let parameters = SpaceDetailLoadedParameters(spaceId: space.spaceId, displayName: summary.displayname, topic: summary.topic, avatarUrl: summary.avatar, joinRule: joinRule, membership: summary.membership, inviterId: inviterId, inviter: inviter, membersCount: membersCount) + let parameters = SpaceDetailLoadedParameters(spaceId: space.spaceId, + displayName: summary.displayname, + topic: summary.topic, + avatarUrl: summary.avatar, + joinRule: joinRule, + membership: summary.membership, + inviterId: inviterId, + inviter: inviter, + membersCount: membersCount) self.update(viewState: .loaded(parameters)) } } diff --git a/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift b/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift index 62770e05e..4d82d8368 100644 --- a/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift +++ b/Riot/Modules/Spaces/SpaceList/SpaceListViewModel.swift @@ -204,7 +204,11 @@ final class SpaceListViewModel: SpaceListViewModelType { let homeNotificationState = session.spaceService.notificationCounter.homeNotificationState let homeViewData = SpaceListItemViewData(spaceId: Constants.homeSpaceId, - title: VectorL10n.spacesHomeSpaceTitle, avatarViewData: avatarViewData, isInvite: false, notificationCount: homeNotificationState.allCount, highlightedNotificationCount: homeNotificationState.allHighlightCount) + title: VectorL10n.spacesHomeSpaceTitle, + avatarViewData: avatarViewData, + isInvite: false, + notificationCount: homeNotificationState.allCount, + highlightedNotificationCount: homeNotificationState.allHighlightCount) return homeViewData } @@ -214,7 +218,11 @@ final class SpaceListViewModel: SpaceListViewModelType { session.spaceService.rootSpaceSummaries.forEach { summary in let avatarViewData = AvatarViewData(matrixItemId: summary.roomId, displayName: summary.displayname, avatarUrl: summary.avatar, mediaManager: session.mediaManager, fallbackImage: .matrixItem(summary.roomId, summary.displayname)) let notificationState = session.spaceService.notificationCounter.notificationState(forSpaceWithId: summary.roomId) - let viewData = SpaceListItemViewData(spaceId: summary.roomId, title: summary.displayname, avatarViewData: avatarViewData, isInvite: summary.membership == .invite, notificationCount: notificationState?.groupMissedDiscussionsCount ?? 0, highlightedNotificationCount: notificationState?.groupMissedDiscussionsHighlightedCount ?? 0) + let viewData = SpaceListItemViewData(spaceId: summary.roomId, title: summary.displayname, + avatarViewData: avatarViewData, + isInvite: summary.membership == .invite, + notificationCount: notificationState?.groupMissedDiscussionsCount ?? 0, + highlightedNotificationCount: notificationState?.groupMissedDiscussionsHighlightedCount ?? 0) if viewData.isInvite { invites.append(viewData) } else { diff --git a/Riot/Modules/Spaces/SpaceMembers/SpaceMembersCoordinatorBridgePresenter.swift b/Riot/Modules/Spaces/SpaceMembers/SpaceMembersCoordinatorBridgePresenter.swift index 7b4ea93c6..056a591b1 100644 --- a/Riot/Modules/Spaces/SpaceMembers/SpaceMembersCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Spaces/SpaceMembers/SpaceMembersCoordinatorBridgePresenter.swift @@ -24,7 +24,8 @@ import Foundation /// SpaceMembersCoordinatorBridgePresenter enables to start SpaceMemberListCoordinator from a view controller. /// This bridge is used while waiting for global usage of coordinator pattern. -/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. +/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers). +/// Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class SpaceMembersCoordinatorBridgePresenter: NSObject { diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoomCoordinatorBridgePresenter.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoomCoordinatorBridgePresenter.swift index 824801fb4..bbbcedfac 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoomCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoomCoordinatorBridgePresenter.swift @@ -24,7 +24,8 @@ import Foundation /// ExploreRoomCoordinatorBridgePresenter enables to start ExploreRoomCoordinator from a view controller. /// This bridge is used while waiting for global usage of coordinator pattern. -/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. +/// It breaks the Coordinator abstraction and it has been introduced for Objective-C compatibility (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has +/// been integrated by another Coordinator. @objcMembers final class ExploreRoomCoordinatorBridgePresenter: NSObject { diff --git a/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailViewModel.swift b/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailViewModel.swift index 299c42d4a..c5989e23b 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailViewModel.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/SpaceChildRoomDetail/SpaceChildRoomDetailViewModel.swift @@ -71,7 +71,11 @@ final class SpaceChildRoomDetailViewModel: SpaceChildRoomDetailViewModelType { // MARK: - Private private func loadData() { - let avatarViewData = AvatarViewData(matrixItemId: self.childInfo.childRoomId, displayName: self.childInfo.displayName, avatarUrl: self.childInfo.avatarUrl, mediaManager: self.session.mediaManager, fallbackImage: .matrixItem(self.childInfo.childRoomId, self.childInfo.name)) + let avatarViewData = AvatarViewData(matrixItemId: self.childInfo.childRoomId, + displayName: self.childInfo.displayName, + avatarUrl: self.childInfo.avatarUrl, + mediaManager: self.session.mediaManager, + fallbackImage: .matrixItem(self.childInfo.childRoomId, self.childInfo.name)) self.update(viewState: .loaded(self.childInfo, avatarViewData, self.isRoomJoined)) } diff --git a/Riot/Modules/SplitView/SplitViewCoordinator.swift b/Riot/Modules/SplitView/SplitViewCoordinator.swift index 442da486e..2157cbd31 100644 --- a/Riot/Modules/SplitView/SplitViewCoordinator.swift +++ b/Riot/Modules/SplitView/SplitViewCoordinator.swift @@ -266,7 +266,8 @@ extension SplitViewCoordinator: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, separateSecondaryFrom primaryViewController: UIViewController) -> UIViewController? { // If the primary root controller of the UISplitViewController is a UINavigationController, - // it's possible to have nested navigation controllers due to private property `_allowNestedNavigationControllers` set to true (https://blog.malcolmhall.com/2017/01/27/default-behaviour-of-uisplitviewcontroller-collapsesecondaryviewcontroller/). + // it's possible to have nested navigation controllers due to private property `_allowNestedNavigationControllers` set to true + // (https://blog.malcolmhall.com/2017/01/27/default-behaviour-of-uisplitviewcontroller-collapsesecondaryviewcontroller/). // So if the top view controller of the primary navigation controller is a navigation controller and it corresponds to the existing `detailNavigationController` instance. // Return `detailNavigationController` as is, it will be used as the secondary view of the split view controller. if let topMostNavigationController = self.selectedNavigationRouter?.modules.last as? UINavigationController, topMostNavigationController == self.detailNavigationController { @@ -302,7 +303,8 @@ extension SplitViewCoordinator: UISplitViewControllerDelegate { // Return false to let the split view controller try to incorporate the secondary view controller's content into the collapsed interface. // If the primary root controller of a UISplitViewController is a UINavigationController, - // it's possible to have nested navigation controllers due to private property `_allowNestedNavigationControllers` set to true (https://blog.malcolmhall.com/2017/01/27/default-behaviour-of-uisplitviewcontroller-collapsesecondaryviewcontroller/). + // it's possible to have nested navigation controllers due to private property `_allowNestedNavigationControllers` set to true + // (https://blog.malcolmhall.com/2017/01/27/default-behaviour-of-uisplitviewcontroller-collapsesecondaryviewcontroller/). // So in this case returning false here will push the `detailNavigationController` on top of the `primaryNavigationController`. // Sample primary view stack: // primaryNavigationController[ @@ -344,7 +346,8 @@ extension SplitViewCoordinator: SplitViewMasterPresentableDelegate { // - If the split view controller is collpased (one column visible): // The `detailNavigationController` will be pushed on top of the primary navigation controller. // In fact if the primary root controller of a UISplitViewController is a UINavigationController, - // it's possible to have nested navigation controllers due to private property `_allowNestedNavigationControllers` set to true (https://blog.malcolmhall.com/2017/01/27/default-behaviour-of-uisplitviewcontroller-collapsesecondaryviewcontroller/). + // it's possible to have nested navigation controllers due to private property `_allowNestedNavigationControllers` set to true + // (https://blog.malcolmhall.com/2017/01/27/default-behaviour-of-uisplitviewcontroller-collapsesecondaryviewcontroller/). // - Else if the split view controller is not collpased (two column visible) // It will set the `detailNavigationController` as the secondary view of the split view controller self.splitViewController.showDetailViewController(detailNavigationController, sender: nil) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 9b01d88d3..5484b0c2f 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -531,7 +531,8 @@ self.addAccountObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidAddAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { MXStrongifyAndReturnIfNil(self); -#warning What was this doing? This should probably happen elsewhere + + // What was this doing? This should probably happen elsewhere // self.onboardingCoordinatorBridgePresenter = nil; [[NSNotificationCenter defaultCenter] removeObserver:self.addAccountObserver]; @@ -541,7 +542,8 @@ self.removeAccountObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kMXKAccountManagerDidRemoveAccountNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { MXStrongifyAndReturnIfNil(self); // The user has cleared data for their soft logged out account -#warning What was this doing? This should probably happen elsewhere + + // What was this doing? This should probably happen elsewhere // self.onboardingCoordinatorBridgePresenter = nil; [[NSNotificationCenter defaultCenter] removeObserver:self.removeAccountObserver]; diff --git a/Riot/Modules/Threads/ThreadsCoordinatorBridgePresenter.swift b/Riot/Modules/Threads/ThreadsCoordinatorBridgePresenter.swift index 43879b292..2fb6fc14b 100644 --- a/Riot/Modules/Threads/ThreadsCoordinatorBridgePresenter.swift +++ b/Riot/Modules/Threads/ThreadsCoordinatorBridgePresenter.swift @@ -28,7 +28,8 @@ import Foundation /// ThreadsCoordinatorBridgePresenter enables to start ThreadsCoordinator from a view controller. /// This bridge is used while waiting for global usage of coordinator pattern. -/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers). Each bridge should be removed once the underlying Coordinator has been integrated by another Coordinator. +/// **WARNING**: This class breaks the Coordinator abstraction and it has been introduced for **Objective-C compatibility only** (mainly for integration in legacy view controllers). Each bridge should be removed +/// once the underlying Coordinator has been integrated by another Coordinator. @objcMembers final class ThreadsCoordinatorBridgePresenter: NSObject { diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 308f0afcd..6e2145c4c 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -279,9 +279,9 @@ [self stopActivityIndicator]; [self dismissViewControllerAnimated:YES completion:nil]; - if (onCompleteBlock) + if (self->onCompleteBlock) { - onCompleteBlock(YES); + self->onCompleteBlock(YES); } }]; } diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index efb79d40e..32c0eaf1f 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -247,7 +247,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm"; { // Track e2e failures dispatch_async(dispatch_get_main_queue(), ^{ - [[DecryptionFailureTracker sharedInstance] reportUnableToDecryptErrorForEvent:event withRoomState:roomState myUser:mxSession.myUser.userId]; + [[DecryptionFailureTracker sharedInstance] reportUnableToDecryptErrorForEvent:event withRoomState:roomState myUser:self->mxSession.myUser.userId]; }); if (event.decryptionError.code == MXDecryptingErrorUnknownInboundSessionIdCode) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 0cba64e18..533d35549 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -396,7 +396,7 @@ class NotificationService: UNNotificationServiceExtension { } if !isHighlighted { - #warning("In practice, this only hides the notification's content. An empty notification may be less useful in this instance?") + // In practice, this only hides the notification's content. An empty notification may be less useful in this instance? // Ignore this notif. MXLog.debug("[NotificationService] notificationContentForEvent: Ignore non highlighted notif in mentions only room") onComplete(nil, false) diff --git a/changelog.d/pr-5513.misc b/changelog.d/pr-5513.misc new file mode 100644 index 000000000..f39615d48 --- /dev/null +++ b/changelog.d/pr-5513.misc @@ -0,0 +1 @@ +Fixed or ignored various project warnings for better DevX \ No newline at end of file From 75c4b26851bf23c388bdbcd529134983368211e7 Mon Sep 17 00:00:00 2001 From: aringenbach <80891108+aringenbach@users.noreply.github.com> Date: Thu, 10 Feb 2022 09:25:20 +0100 Subject: [PATCH 018/188] Fix phone number validation through custom URL (#5527) * Fix phone number validation through custom URL * Rename msisdnSubmissionHttpClient Co-authored-by: Arnaud Ringenbach --- Riot/Modules/MatrixKit/Models/MXK3PID.m | 29 ++++++++++++++++++------- changelog.d/3562.bugfix | 1 + 2 files changed, 22 insertions(+), 8 deletions(-) create mode 100644 changelog.d/3562.bugfix diff --git a/Riot/Modules/MatrixKit/Models/MXK3PID.m b/Riot/Modules/MatrixKit/Models/MXK3PID.m index 5c4657cfa..0ccf5c702 100644 --- a/Riot/Modules/MatrixKit/Models/MXK3PID.m +++ b/Riot/Modules/MatrixKit/Models/MXK3PID.m @@ -29,6 +29,10 @@ @property (nonatomic) NSString *sid; @property (nonatomic) MXIdentityService *identityService; @property (nonatomic) NSString *submitUrl; +/** + HTTP client dedicated to sending MSISDN token to custom URLs. + */ +@property (nonatomic, strong) MXHTTPClient *msisdnSubmissionHttpClient; @end @@ -255,14 +259,23 @@ @"token": token }; - MXHTTPClient *httpClient = [[MXHTTPClient alloc] initWithBaseURL:nil andOnUnrecognizedCertificateBlock:nil]; - return [httpClient requestWithMethod:@"POST" - path:url - parameters:parameters - success:^(NSDictionary *JSONResponse) { - success(); - } - failure:failure]; + self.msisdnSubmissionHttpClient = [[MXHTTPClient alloc] initWithBaseURL:nil andOnUnrecognizedCertificateBlock:nil]; + + MXWeakify(self); + return [self.msisdnSubmissionHttpClient requestWithMethod:@"POST" + path:url + parameters:parameters + success:^(NSDictionary *JSONResponse) { + success(); + MXStrongifyAndReturnIfNil(self); + self.msisdnSubmissionHttpClient = nil; + } + failure:^(NSError *error) { + failure(error); + MXStrongifyAndReturnIfNil(self); + self.msisdnSubmissionHttpClient = nil; + }]; + } - (void)add3PIDToUser:(BOOL)bind diff --git a/changelog.d/3562.bugfix b/changelog.d/3562.bugfix new file mode 100644 index 000000000..8259627ad --- /dev/null +++ b/changelog.d/3562.bugfix @@ -0,0 +1 @@ +Authent: fix phone number validation through custom URL \ No newline at end of file From 23f150594442e04eee7628c2fbdff63eac63bfff Mon Sep 17 00:00:00 2001 From: Aaron Raimist Date: Thu, 10 Feb 2022 10:08:01 +0000 Subject: [PATCH 019/188] Fix changelog name --- changelog.d/{5510.bugfix => 3736.bugfix} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename changelog.d/{5510.bugfix => 3736.bugfix} (100%) diff --git a/changelog.d/5510.bugfix b/changelog.d/3736.bugfix similarity index 100% rename from changelog.d/5510.bugfix rename to changelog.d/3736.bugfix From 56b70d254bfdd330f626525f736ca28481f26bef Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 10 Feb 2022 12:59:13 +0000 Subject: [PATCH 020/188] Updates following PR feedback. --- Riot/Managers/Settings/RiotSettings.swift | 8 +++++++- Riot/Managers/UserSessions/UserSession.swift | 16 +++++++-------- .../UserSessions/UserSessionProperties.swift | 20 ++++++++++++------- .../UserSessions/UserSessionsService.swift | 2 +- .../AuthenticationCoordinator.swift | 2 +- .../AuthenticationViewController.h | 6 +++--- .../AuthenticationViewController.m | 16 +++++++-------- .../Onboarding/OnboardingCoordinator.swift | 6 +++--- 8 files changed, 44 insertions(+), 32 deletions(-) diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 1b1af2591..fdff093ce 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -99,7 +99,7 @@ final class RiotSettings: NSObject { @UserDefault(key: "userInterfaceTheme", defaultValue: nil, storage: defaults) var userInterfaceTheme - // MARK: Other + // MARK: Analytics & Rageshakes /// Whether the user was previously shown the Matomo analytics prompt. var hasSeenAnalyticsPrompt: Bool { @@ -130,6 +130,12 @@ final class RiotSettings: NSObject { @UserDefault(key: "enableRageShake", defaultValue: false, storage: defaults) var enableRageShake + // MARK: User + + /// A dictionary of dictionaries keyed by user ID for storage of the `UserSessionProperties` from any active `UserSession`s. + @UserDefault(key: "userSessionProperties", defaultValue: [:], storage: defaults) + var userSessionProperties: [String: [String: Any]] + // MARK: Labs /// Indicates if CallKit ringing is enabled for group calls. This setting does not disable the CallKit integration for group calls, only relates to ringing. diff --git a/Riot/Managers/UserSessions/UserSession.swift b/Riot/Managers/UserSessions/UserSession.swift index fa5b883ac..8795812e6 100644 --- a/Riot/Managers/UserSessions/UserSession.swift +++ b/Riot/Managers/UserSessions/UserSession.swift @@ -33,21 +33,21 @@ class UserSession: NSObject, UserSessionProtocol { let account: MXKAccount // Keep strong reference to the MXSession because account.mxSession can become nil on logout or failure let matrixSession: MXSession + let userId: String /// An object that contains user specific properties. - private(set) lazy var properties = UserSessionProperties(userId: userId) - - var userId: String { - guard let userId = self.account.mxCredentials.userId else { - fatalError("[UserSession] identifier: account.mxCredentials.userId should be defined") - } - return userId - } + let userProperties: UserSessionProperties // MARK: - Setup init(account: MXKAccount, matrixSession: MXSession) { + guard let userId = account.mxCredentials.userId else { + fatalError("[UserSession] identifier: account.mxCredentials.userId should be defined") + } + self.account = account self.matrixSession = matrixSession + self.userId = userId + self.userProperties = UserSessionProperties(userId: userId) super.init() } } diff --git a/Riot/Managers/UserSessions/UserSessionProperties.swift b/Riot/Managers/UserSessions/UserSessionProperties.swift index e637aa3fc..4bac87579 100644 --- a/Riot/Managers/UserSessions/UserSessionProperties.swift +++ b/Riot/Managers/UserSessions/UserSessionProperties.swift @@ -21,7 +21,6 @@ class UserSessionProperties: NSObject { // MARK: - Constants private enum Constants { - static let suiteName = BuildSettings.baseBundleIdentifier + ".UserSession" static let useCaseKey = "useCase" } @@ -31,10 +30,16 @@ class UserSessionProperties: NSObject { /// The user ID for these properties private let userId: String - /// The underlying dictionary that stores the properties in user defaults. + + /// The underlying dictionary for this userId from user defaults. private var dictionary: [String: Any] { - didSet { - UserDefaults(suiteName: Constants.suiteName)?.set(dictionary, forKey: userId) + get { + RiotSettings.shared.userSessionProperties[userId] ?? [:] + } + set { + var sharedProperties = RiotSettings.shared.userSessionProperties + sharedProperties[userId] = newValue + RiotSettings.shared.userSessionProperties = sharedProperties } } @@ -65,8 +70,6 @@ class UserSessionProperties: NSObject { /// - Parameter userId: The user ID to load properties for. init(userId: String) { self.userId = userId - self.dictionary = UserDefaults(suiteName: Constants.suiteName)?.dictionary(forKey: userId) ?? [:] - super.init() } @@ -75,6 +78,9 @@ class UserSessionProperties: NSObject { /// Clear all of the stored properties. func delete() { dictionary = [:] - UserDefaults(suiteName: Constants.suiteName)?.removeObject(forKey: userId) + + var sharedProperties = RiotSettings.shared.userSessionProperties + sharedProperties[userId] = nil + RiotSettings.shared.userSessionProperties = sharedProperties } } diff --git a/Riot/Managers/UserSessions/UserSessionsService.swift b/Riot/Managers/UserSessions/UserSessionsService.swift index c5842dfed..c94497161 100644 --- a/Riot/Managers/UserSessions/UserSessionsService.swift +++ b/Riot/Managers/UserSessions/UserSessionsService.swift @@ -132,7 +132,7 @@ class UserSessionsService: NSObject { } // Clear any stored user properties from this session. - userSession.properties.delete() + userSession.userProperties.delete() self.userSessions.removeAll { (userSession) -> Bool in return userId == userSession.userId diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift index 9cdb59ddb..e2ba6ee2e 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift @@ -63,7 +63,7 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc } func showCustomServer() { - authenticationViewController.hideCustomServers(false) + authenticationViewController.setCustomServerFieldsVisible(true) } func update(externalRegistrationParameters: [AnyHashable: Any]) { diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index 6d412400f..f3699125d 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -54,9 +54,9 @@ /// returns YES if the SSO login can be continued. - (BOOL)continueSSOLoginWithToken:(NSString*)loginToken txnId:(NSString*)txnId; -/// Hides/shows the custom homeserver field. -/// @param hidden YES to hide, NO to show. -- (void)hideCustomServers:(BOOL)hidden; +/// Show or hide the custom server textfields. +/// @param isVisible YES to show, NO to hide. +- (void)setCustomServerFieldsVisible:(BOOL)isVisible; @end diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 5579bc416..0ff35511e 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -160,7 +160,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; } self.serverOptionsContainer.hidden = !BuildSettings.authScreenShowCustomServerOptions; - [self hideCustomServers:YES]; + [self setCustomServerFieldsVisible:NO]; // Soft logout section self.softLogoutClearDataButton.layer.cornerRadius = 5; @@ -888,7 +888,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; { if (sender == self.customServersTickButton) { - [self hideCustomServers:!self.customServersContainer.hidden]; + [self setCustomServerFieldsVisible:self.customServersContainer.hidden]; } else if (sender == self.forgotPasswordButton) { @@ -1236,14 +1236,14 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self.view layoutIfNeeded]; } -- (void)hideCustomServers:(BOOL)hidden +- (void)setCustomServerFieldsVisible:(BOOL)isVisible { - if (self.customServersContainer.isHidden == hidden) + if (self.customServersContainer.isHidden != isVisible) { return; } - if (hidden) + if (!isVisible) { [self.homeServerTextField resignFirstResponder]; [self.identityServerTextField resignFirstResponder]; @@ -1361,7 +1361,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self.authenticationActivityIndicator startAnimating]; // Hide the custom server details in order to save customized inputs - [self hideCustomServers:YES]; + [self setCustomServerFieldsVisible:NO]; MXKAccount *account = [[MXKAccountManager sharedManager] accountForUserId:userId]; MXSession *session = account.mxSession; @@ -1586,7 +1586,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; { // wellKnown matches with application default servers // Hide custom servers - [self hideCustomServers:YES]; + [self setCustomServerFieldsVisible:NO]; } else { @@ -1618,7 +1618,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; } // And show custom servers - [self hideCustomServers:NO]; + [self setCustomServerFieldsVisible:YES]; } #pragma mark - KeyVerificationCoordinatorBridgePresenterDelegate diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 3dd2e3e5c..571140f43 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -138,7 +138,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { switch result { case .register: - showUseCase() + showUseCaseSelectionScreen() case .login: showAuthenticationScreen() } @@ -146,7 +146,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { @available(iOS 14.0, *) /// Show the use case screen for new users. - private func showUseCase() { + private func showUseCaseSelectionScreen() { let coordinator = OnboardingUseCaseCoordinator() coordinator.completion = { [weak self, weak coordinator] result in guard let self = self, let coordinator = coordinator else { return } @@ -227,7 +227,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { let useCaseResult = useCaseResult, let userSession = UserSessionsService.shared.mainUserSession { // Store the value in the user's session - userSession.properties.useCase = useCaseResult.userSessionPropertyValue + userSession.userProperties.useCase = useCaseResult.userSessionPropertyValue } } } From ff28bd7657ce8a9dcb11ce8cf24a454e4d784a50 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 16:48:27 +0300 Subject: [PATCH 021/188] Use thread protocol when possible --- .../Threads/ThreadList/ThreadListCoordinator.swift | 4 ++-- .../ThreadList/ThreadListCoordinatorProtocol.swift | 2 +- .../Threads/ThreadList/ThreadListViewModel.swift | 12 ++++++------ .../ThreadList/ThreadListViewModelProtocol.swift | 4 ++-- .../Threads/ThreadList/Views/Cell/ThreadModel.swift | 2 +- Riot/Modules/Threads/ThreadsCoordinator.swift | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift b/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift index a870d8808..618d967c5 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift @@ -65,11 +65,11 @@ extension ThreadListCoordinator: ThreadListViewModelCoordinatorDelegate { self.delegate?.threadListCoordinatorDidLoadThreads(self) } - func threadListViewModelDidSelectThread(_ viewModel: ThreadListViewModelProtocol, thread: MXThread) { + func threadListViewModelDidSelectThread(_ viewModel: ThreadListViewModelProtocol, thread: MXThreadProtocol) { self.delegate?.threadListCoordinatorDidSelectThread(self, thread: thread) } - func threadListViewModelDidSelectThreadViewInRoom(_ viewModel: ThreadListViewModelProtocol, thread: MXThread) { + func threadListViewModelDidSelectThreadViewInRoom(_ viewModel: ThreadListViewModelProtocol, thread: MXThreadProtocol) { self.delegate?.threadListCoordinatorDidSelectRoom(self, roomId: thread.roomId, eventId: thread.id) } diff --git a/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift b/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift index e23505480..fb9b02bee 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift @@ -20,7 +20,7 @@ import Foundation protocol ThreadListCoordinatorDelegate: AnyObject { func threadListCoordinatorDidLoadThreads(_ coordinator: ThreadListCoordinatorProtocol) - func threadListCoordinatorDidSelectThread(_ coordinator: ThreadListCoordinatorProtocol, thread: MXThread) + func threadListCoordinatorDidSelectThread(_ coordinator: ThreadListCoordinatorProtocol, thread: MXThreadProtocol) func threadListCoordinatorDidSelectRoom(_ coordinator: ThreadListCoordinatorProtocol, roomId: String, eventId: String) func threadListCoordinatorDidCancel(_ coordinator: ThreadListCoordinatorProtocol) } diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index 381c19f52..01d42bf47 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -26,12 +26,12 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { private let session: MXSession private let roomId: String - private var threads: [MXThread] = [] + private var threads: [MXThreadProtocol] = [] private var eventFormatter: MXKEventFormatter? private var roomState: MXRoomState? private var currentOperation: MXHTTPOperation? - private var longPressedThread: MXThread? + private var longPressedThread: MXThreadProtocol? // MARK: Public @@ -144,7 +144,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { // MARK: - Private - private func model(forThread thread: MXThread) -> ThreadModel { + private func model(forThread thread: MXThreadProtocol) -> ThreadModel { let rootAvatarViewData: AvatarViewData? let rootMessageSender: MXUser? let lastAvatarViewData: AvatarViewData? @@ -199,7 +199,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { notificationStatus: notificationStatus) } - private func rootMessageText(forThread thread: MXThread) -> NSAttributedString? { + private func rootMessageText(forThread thread: MXThreadProtocol) -> NSAttributedString? { guard let eventFormatter = eventFormatter else { return nil } @@ -229,7 +229,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { error: formatterError) } - private func lastMessageTextAndTime(forThread thread: MXThread) -> (NSAttributedString?, String?) { + private func lastMessageTextAndTime(forThread thread: MXThreadProtocol) -> (NSAttributedString?, String?) { guard let eventFormatter = eventFormatter else { return (nil, nil) } @@ -323,7 +323,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { private func actionShare() { guard let thread = longPressedThread, - let index = threads.firstIndex(of: thread) else { + let index = threads.firstIndex(where: { thread.id == $0.id }) else { return } if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId), diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift index 3720f0c35..09db9be20 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift @@ -24,8 +24,8 @@ protocol ThreadListViewModelViewDelegate: AnyObject { protocol ThreadListViewModelCoordinatorDelegate: AnyObject { func threadListViewModelDidLoadThreads(_ viewModel: ThreadListViewModelProtocol) - func threadListViewModelDidSelectThread(_ viewModel: ThreadListViewModelProtocol, thread: MXThread) - func threadListViewModelDidSelectThreadViewInRoom(_ viewModel: ThreadListViewModelProtocol, thread: MXThread) + func threadListViewModelDidSelectThread(_ viewModel: ThreadListViewModelProtocol, thread: MXThreadProtocol) + func threadListViewModelDidSelectThreadViewInRoom(_ viewModel: ThreadListViewModelProtocol, thread: MXThreadProtocol) func threadListViewModelDidCancel(_ viewModel: ThreadListViewModelProtocol) } diff --git a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadModel.swift b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadModel.swift index 1692b9f6c..6667d5bfc 100644 --- a/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadModel.swift +++ b/Riot/Modules/Threads/ThreadList/Views/Cell/ThreadModel.swift @@ -32,7 +32,7 @@ enum ThreadNotificationStatus { case notified case highlighted - init(withThread thread: MXThread) { + init(withThread thread: MXThreadProtocol) { if thread.highlightCount > 0 { self = .highlighted } else if thread.isParticipated && thread.notificationCount > 0 { diff --git a/Riot/Modules/Threads/ThreadsCoordinator.swift b/Riot/Modules/Threads/ThreadsCoordinator.swift index f5857dcc9..d645decd3 100644 --- a/Riot/Modules/Threads/ThreadsCoordinator.swift +++ b/Riot/Modules/Threads/ThreadsCoordinator.swift @@ -153,7 +153,7 @@ extension ThreadsCoordinator: ThreadListCoordinatorDelegate { } - func threadListCoordinatorDidSelectThread(_ coordinator: ThreadListCoordinatorProtocol, thread: MXThread) { + func threadListCoordinatorDidSelectThread(_ coordinator: ThreadListCoordinatorProtocol, thread: MXThreadProtocol) { let roomCoordinator = createThreadCoordinator(forThreadId: thread.id) selectedThreadCoordinator = roomCoordinator roomCoordinator.start() From 1e26681e347926aa90c50bee9249c2727ee7bb48 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 10 Feb 2022 14:59:45 +0100 Subject: [PATCH 022/188] Message bubbles: Move bubbles settings to labs section atm. --- .../Modules/Settings/SettingsViewController.m | 39 +++++++++++++------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index a1964925e..bab34cb22 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -158,7 +158,8 @@ typedef NS_ENUM(NSUInteger, ABOUT) typedef NS_ENUM(NSUInteger, LABS_ENABLE) { LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX = 0, - LABS_ENABLE_THREADS_INDEX + LABS_ENABLE_THREADS_INDEX, + LABS_ENABLE_MESSAGE_BUBBLES_INDEX }; typedef NS_ENUM(NSUInteger, SECURITY) @@ -510,7 +511,9 @@ TableViewSectionsDelegate> if (BuildSettings.roomScreenAllowTimelineStyleConfiguration) { - [sectionUserInterface addRowWithTag:USER_INTERFACE_TIMELINE_STYLE_INDEX]; + // NOTE: Message bubbles are under labs section atm + +// [sectionUserInterface addRowWithTag:USER_INTERFACE_TIMELINE_STYLE_INDEX]; } [tmpSections addObject: sectionUserInterface]; @@ -568,6 +571,7 @@ TableViewSectionsDelegate> Section *sectionLabs = [Section sectionWithTag:SECTION_TAG_LABS]; [sectionLabs addRowWithTag:LABS_ENABLE_RINGING_FOR_GROUP_CALLS_INDEX]; [sectionLabs addRowWithTag:LABS_ENABLE_THREADS_INDEX]; + [sectionLabs addRowWithTag:LABS_ENABLE_MESSAGE_BUBBLES_INDEX]; sectionLabs.headerTitle = [VectorL10n settingsLabs]; if (sectionLabs.hasAnyRows) { @@ -1471,6 +1475,22 @@ TableViewSectionsDelegate> return [footerText copy]; } +- (UITableViewCell *)buildMessageBubblesCellForTableView: +(UITableView*)tableView + atIndexPath:(NSIndexPath*)indexPath +{ + MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; + + labelAndSwitchCell.mxkLabel.text = [VectorL10n settingsEnableRoomMessageBubbles]; + + labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.roomScreenEnableMessageBubbles; + labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; + labelAndSwitchCell.mxkSwitch.enabled = YES; + [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleEnableRoomMessageBubbles:) forControlEvents:UIControlEventTouchUpInside]; + + return labelAndSwitchCell; +} + #pragma mark - 3Pid Add - (void)showAuthenticationIfNeededForAdding:(MX3PIDMedium)medium withSession:(MXSession*)session completion:(void (^)(NSDictionary* authParams))completion @@ -2208,16 +2228,7 @@ TableViewSectionsDelegate> } else if (row == USER_INTERFACE_TIMELINE_STYLE_INDEX) { - MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; - - labelAndSwitchCell.mxkLabel.text = [VectorL10n settingsEnableRoomMessageBubbles]; - - labelAndSwitchCell.mxkSwitch.on = RiotSettings.shared.roomScreenEnableMessageBubbles; - labelAndSwitchCell.mxkSwitch.onTintColor = ThemeService.shared.theme.tintColor; - labelAndSwitchCell.mxkSwitch.enabled = YES; - [labelAndSwitchCell.mxkSwitch addTarget:self action:@selector(toggleEnableRoomMessageBubbles:) forControlEvents:UIControlEventTouchUpInside]; - - cell = labelAndSwitchCell; + cell = [self buildMessageBubblesCellForTableView:tableView atIndexPath:indexPath]; } } else if (section == SECTION_TAG_IGNORED_USERS) @@ -2448,6 +2459,10 @@ TableViewSectionsDelegate> cell = labelAndSwitchCell; } + else if (row == LABS_ENABLE_MESSAGE_BUBBLES_INDEX) + { + cell = [self buildMessageBubblesCellForTableView:tableView atIndexPath:indexPath]; + } } else if (section == SECTION_TAG_FLAIR) { From c5e926d4e6f9d5c26097541378826fa6be9dedea Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 10 Feb 2022 15:08:24 +0100 Subject: [PATCH 023/188] SettingsViewController: Fix indent issue. --- Riot/Modules/Settings/SettingsViewController.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index bab34cb22..c9c738f66 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1475,9 +1475,8 @@ TableViewSectionsDelegate> return [footerText copy]; } -- (UITableViewCell *)buildMessageBubblesCellForTableView: -(UITableView*)tableView - atIndexPath:(NSIndexPath*)indexPath +- (UITableViewCell *)buildMessageBubblesCellForTableView:(UITableView*)tableView + atIndexPath:(NSIndexPath*)indexPath { MXKTableViewCellWithLabelAndSwitch* labelAndSwitchCell = [self getLabelAndSwitchCell:tableView forIndexPath:indexPath]; From 952d69477bd4c69ba97be0f8d085acd70c3c0b76 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 17:35:18 +0300 Subject: [PATCH 024/188] Use new api to fetch thread list --- .../ThreadList/ThreadListViewModel.swift | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index 01d42bf47..2242250ba 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -250,23 +250,35 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { if showLoading { viewState = .loading } + + let onlyParticipated: Bool switch selectedFilterType { case .all: - threads = session.threadingService.threads(inRoom: roomId) + onlyParticipated = false case .myThreads: - threads = session.threadingService.participatedThreads(inRoom: roomId) + onlyParticipated = true } + session.threadingService.allThreads(inRoom: roomId, + onlyParticipated: onlyParticipated) { [weak self] response in + guard let self = self else { return } + switch response { + case .success(let threads): + self.threads = threads + self.threadsLoaded() + case .failure(let error): + MXLog.error("[ThreadListViewModel] loadData: error: \(error)") + } + } + } + + private func threadsLoaded() { if threads.isEmpty { viewState = .empty(emptyViewModel) return } - - threadsLoaded() - } - - private func threadsLoaded() { + guard let eventFormatter = session.roomSummaryUpdateDelegate as? MXKEventFormatter, let room = session.room(withRoomId: roomId) else { // go into loaded state From df5fb6f4bdc58234aaf12c2032537fb7cddc3f26 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Thu, 10 Feb 2022 17:35:54 +0300 Subject: [PATCH 025/188] Add changelog --- changelog.d/5540.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5540.change diff --git a/changelog.d/5540.change b/changelog.d/5540.change new file mode 100644 index 000000000..f885fdd8c --- /dev/null +++ b/changelog.d/5540.change @@ -0,0 +1 @@ +ThreadListViewModel: Use new apis to fetch threads. From 1426aafc622a06e7b6e286f6a9ddc46e1e956253 Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 10 Feb 2022 15:39:03 +0000 Subject: [PATCH 026/188] Update the tintColor in ThemeV1 to sRGB to match Compound and ThemeV2. --- Riot/Managers/Theme/Themes/DarkTheme.swift | 2 +- Riot/Managers/Theme/Themes/DefaultTheme.swift | 2 +- .../LaunchLoading/LoadingAnimation/ElementView.swift | 8 ++++---- changelog.d/5545.bugfix | 1 + 4 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 changelog.d/5545.bugfix diff --git a/Riot/Managers/Theme/Themes/DarkTheme.swift b/Riot/Managers/Theme/Themes/DarkTheme.swift index c24201cca..8ec84240d 100644 --- a/Riot/Managers/Theme/Themes/DarkTheme.swift +++ b/Riot/Managers/Theme/Themes/DarkTheme.swift @@ -45,7 +45,7 @@ class DarkTheme: NSObject, Theme { var textTertiaryColor: UIColor = UIColor(rgb: 0x8E99A4) var textQuinaryColor: UIColor = UIColor(rgb: 0x394049) - var tintColor: UIColor = UIColor(displayP3Red: 0.05098039216, green: 0.7450980392, blue: 0.5450980392, alpha: 1.0) + var tintColor: UIColor = UIColor(rgb: 0x0DBD8B) var tintBackgroundColor: UIColor = UIColor(rgb: 0x1F6954) var tabBarUnselectedItemTintColor: UIColor = UIColor(rgb: 0x8E99A4) var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) diff --git a/Riot/Managers/Theme/Themes/DefaultTheme.swift b/Riot/Managers/Theme/Themes/DefaultTheme.swift index a2fe37492..f8f69f7a6 100644 --- a/Riot/Managers/Theme/Themes/DefaultTheme.swift +++ b/Riot/Managers/Theme/Themes/DefaultTheme.swift @@ -45,7 +45,7 @@ class DefaultTheme: NSObject, Theme { var textTertiaryColor: UIColor = UIColor(rgb: 0x8D99A5) var textQuinaryColor: UIColor = UIColor(rgb: 0xE3E8F0) - var tintColor: UIColor = UIColor(displayP3Red: 0.05098039216, green: 0.7450980392, blue: 0.5450980392, alpha: 1.0) + var tintColor: UIColor = UIColor(rgb: 0x0DBD8B) var tintBackgroundColor: UIColor = UIColor(rgb: 0xe9fff9) var tabBarUnselectedItemTintColor: UIColor = UIColor(rgb: 0xC1C6CD) var unreadRoomIndentColor: UIColor = UIColor(rgb: 0x2E3648) diff --git a/Riot/Modules/LaunchLoading/LoadingAnimation/ElementView.swift b/Riot/Modules/LaunchLoading/LoadingAnimation/ElementView.swift index f65e8a124..2e80a9c6f 100644 --- a/Riot/Modules/LaunchLoading/LoadingAnimation/ElementView.swift +++ b/Riot/Modules/LaunchLoading/LoadingAnimation/ElementView.swift @@ -102,7 +102,7 @@ public class ElementView: UIView { path.layer.bounds = CGRect(x: 0, y: 0, width: 55.2, height: 55.2) path.layer.masksToBounds = false path.shapeLayer.fillRule = CAShapeLayerFillRule.evenOdd - path.shapeLayer.fillColor = UIColor(displayP3Red: 0.052, green: 0.743, blue: 0.543, alpha: 1).cgColor + path.shapeLayer.fillColor = UIColor(rgb: 0x0DBD8B).cgColor path.shapeLayer.lineDashPattern = [] path.shapeLayer.lineDashPhase = 0 path.shapeLayer.lineWidth = 0 @@ -120,7 +120,7 @@ public class ElementView: UIView { path_1.layer.bounds = CGRect(x: 0, y: 0, width: 55.2, height: 55.2) path_1.layer.masksToBounds = false path_1.shapeLayer.fillRule = CAShapeLayerFillRule.evenOdd - path_1.shapeLayer.fillColor = UIColor(displayP3Red: 0.052, green: 0.743, blue: 0.543, alpha: 1).cgColor + path_1.shapeLayer.fillColor = UIColor(rgb: 0x0DBD8B).cgColor path_1.shapeLayer.lineDashPattern = [] path_1.shapeLayer.lineDashPhase = 0 path_1.shapeLayer.lineWidth = 0 @@ -138,7 +138,7 @@ public class ElementView: UIView { path_2.layer.bounds = CGRect(x: 0, y: 0, width: 55.2, height: 55.2) path_2.layer.masksToBounds = false path_2.shapeLayer.fillRule = CAShapeLayerFillRule.evenOdd - path_2.shapeLayer.fillColor = UIColor(displayP3Red: 0.052, green: 0.743, blue: 0.543, alpha: 1).cgColor + path_2.shapeLayer.fillColor = UIColor(rgb: 0x0DBD8B).cgColor path_2.shapeLayer.lineDashPattern = [] path_2.shapeLayer.lineDashPhase = 0 path_2.shapeLayer.lineWidth = 0 @@ -156,7 +156,7 @@ public class ElementView: UIView { path_3.layer.bounds = CGRect(x: 0, y: 0, width: 55.2, height: 55.2) path_3.layer.masksToBounds = false path_3.shapeLayer.fillRule = CAShapeLayerFillRule.evenOdd - path_3.shapeLayer.fillColor = UIColor(displayP3Red: 0.052, green: 0.743, blue: 0.543, alpha: 1).cgColor + path_3.shapeLayer.fillColor = UIColor(rgb: 0x0DBD8B).cgColor path_3.shapeLayer.lineDashPattern = [] path_3.shapeLayer.lineDashPhase = 0 path_3.shapeLayer.lineWidth = 0 diff --git a/changelog.d/5545.bugfix b/changelog.d/5545.bugfix new file mode 100644 index 000000000..a9b8dbd3c --- /dev/null +++ b/changelog.d/5545.bugfix @@ -0,0 +1 @@ +Update the tintColor in ThemeV1 to sRGB to match the Compound and ThemeV2. \ No newline at end of file From 2f6546799e546ecdec03aaeda9f9f62964bc2411 Mon Sep 17 00:00:00 2001 From: aringenbach <80891108+aringenbach@users.noreply.github.com> Date: Thu, 10 Feb 2022 17:13:23 +0100 Subject: [PATCH 027/188] Add objective C support to SwiftGen assets helpers (#5533) * Add objective C support to SwiftGen assets helpers * Use dot notation in ObjC & fix minor issues Co-authored-by: Arnaud Ringenbach --- .../MXKRoomBubbleTableViewCell+Riot.m | 8 +- Riot/Categories/UIViewController+RiotSearch.m | 2 +- Riot/Generated/Images.swift | 17 +- .../AuthenticationViewController.m | 10 +- .../Authentication/Views/AuthInputsView.m | 2 +- .../BugReport/BugReportViewController.m | 8 +- Riot/Modules/Call/CallViewController.m | 24 +- Riot/Modules/Call/Views/IncomingCallView.m | 4 +- .../Recents/DataSources/RecentsDataSource.m | 4 +- .../Common/Recents/RecentsViewController.m | 14 +- .../Members/GroupParticipantsViewController.m | 4 +- .../Contacts/DataSources/ContactsDataSource.m | 6 +- .../Details/ContactDetailsViewController.m | 2 +- .../Favorites/FavouritesViewController.m | 4 +- .../Files/CellData/FilesSearchCellData.m | 8 +- .../Files/Views/FilesSearchTableViewCell.m | 10 +- .../UnifiedSearchViewController.m | 2 +- .../Views/RoomIdOrAliasTableViewCell.m | 2 +- Riot/Modules/Home/HomeViewController.m | 20 +- .../Widgets/WidgetViewController.m | 2 +- .../Library/MediaAlbumContentViewController.m | 4 +- .../MediaPicker/MediaPickerViewController.m | 16 +- Riot/Modules/People/PeopleViewController.m | 6 +- .../Detail/RoomMemberDetailsViewController.m | 4 +- .../Members/RoomParticipantsViewController.m | 4 +- Riot/Modules/Room/RoomViewController.m | 34 +- .../Settings/RoomSettingsViewController.m | 12 +- .../Views/TableViewCellWithCheckBoxAndLabel.m | 4 +- .../Views/TableViewCellWithCheckBoxes.m | 8 +- .../Views/Activities/RoomActivitiesView.m | 8 +- .../Encryption/RoomEncryptedDataBubbleCell.m | 3 +- .../Views/InputToolbar/RoomInputToolbarView.m | 18 +- .../Title/Preview/PreviewRoomTitleView.m | 2 +- .../Views/DirectoryServerTableViewCell.m | 2 +- Riot/Modules/Rooms/RoomsViewController.m | 6 +- .../ManageSessionViewController.m | 4 +- .../Security/SecurityViewController.m | 8 +- .../Modules/Settings/SettingsViewController.m | 8 +- .../StartChat/StartChatViewController.m | 2 +- .../UserDevices/Views/DeviceTableViewCell.m | 6 +- Riot/Utils/EventFormatter.m | 2 +- .../Shared/View/RecentRoomTableViewCell.m | 4 +- RiotShareExtension/target.yml | 1 + .../Templates/Assets/swift4-element.stencil | 337 ++++++++++++++++++ Tools/SwiftGen/swiftgen-config.yml | 2 +- changelog.d/pr-5533.misc | 1 + 46 files changed, 504 insertions(+), 155 deletions(-) create mode 100644 Tools/SwiftGen/Templates/Assets/swift4-element.stencil create mode 100644 changelog.d/pr-5533.misc diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 98fde6a11..0d8f4ac0a 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -697,7 +697,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = if ([bubbleData isKindOfClass:RoomBubbleCellData.class] && ((RoomBubbleCellData*)bubbleData).componentIndexOfSentMessageTick >= 0) { - UIImage *image = [UIImage imageNamed:@"sent_message_tick"]; + UIImage *image = AssetImages.sentMessageTick.image; image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; tickView = [[UIImageView alloc] initWithImage:image]; tickView.tintColor = ThemeService.shared.theme.textTertiaryColor; @@ -733,7 +733,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = } else { - UIImage *image = [UIImage imageNamed:@"sending_message_tick"]; + UIImage *image = AssetImages.sendingMessageTick.image; image = [image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; tickView = [[UIImageView alloc] initWithImage:image]; tickView.tintColor = ThemeService.shared.theme.textTertiaryColor; @@ -746,7 +746,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = if (component.event.sentState == MXEventSentStateFailed) { - tickView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"error_message_tick"]]; + tickView = [[UIImageView alloc] initWithImage:AssetImages.errorMessageTick.image]; [statusViews addObject:tickView]; [self addTickView:tickView atIndex:index]; } @@ -815,7 +815,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = } // Define 'Edit' button frame - UIImage *editIcon = [UIImage imageNamed:@"edit_icon"]; + UIImage *editIcon = AssetImages.editIcon.image; CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth - 22 - editIcon.size.width / 2; CGFloat editBtnPosY = isFirstDisplayedComponent ? -13 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13; UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(editBtnPosX, editBtnPosY, 44, 44)]; diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index 09b7896b3..eef17866e 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -136,7 +136,7 @@ - (void)addBackgroundImageViewToView:(UIView*)view { - UIImage *searchBgImage = [MXKTools paintImage:[UIImage imageNamed:@"search_bg"] withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; + UIImage *searchBgImage = [MXKTools paintImage:AssetImages.searchBg.image withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:searchBgImage]; backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO; diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index cec8486d5..26cb7157e 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -18,8 +18,10 @@ internal typealias AssetImageTypeAlias = ImageAsset.Image // MARK: - Asset Catalogs // swiftlint:disable identifier_name line_length nesting type_body_length type_name -internal enum Asset { - internal enum Images { +@objcMembers +internal class Asset: NSObject { + @objcMembers + @objc(AssetImages) internal class Images: NSObject { internal static let analyticsCheckmark = ImageAsset(name: "AnalyticsCheckmark") internal static let analyticsLogo = ImageAsset(name: "AnalyticsLogo") internal static let socialLoginButtonApple = ImageAsset(name: "social_login_button_apple") @@ -244,7 +246,8 @@ internal enum Asset { internal static let tabRooms = ImageAsset(name: "tab_rooms") internal static let launchScreenLogo = ImageAsset(name: "launch_screen_logo") } - internal enum SharedImages { + @objcMembers + @objc(AssetSharedImages) internal class SharedImages: NSObject { internal static let cancel = ImageAsset(name: "cancel") internal static let e2eVerified = ImageAsset(name: "e2e_verified") internal static let horizontalLogo = ImageAsset(name: "horizontal_logo") @@ -256,7 +259,8 @@ internal enum Asset { // MARK: - Implementation Details -internal struct ImageAsset { +@objcMembers +internal class ImageAsset: NSObject { internal fileprivate(set) var name: String #if os(macOS) @@ -282,6 +286,10 @@ internal struct ImageAsset { return result } + internal init(name: String) { + self.name = name + } + #if os(iOS) || os(tvOS) @available(iOS 8.0, tvOS 9.0, *) internal func image(compatibleWith traitCollection: UITraitCollection) -> Image { @@ -321,3 +329,4 @@ private final class BundleToken { }() } // swiftlint:enable convenience_type + diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 0ff35511e..776e23373 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -136,7 +136,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; self.defaultIdentityServerUrl = RiotSettings.shared.identityServerUrlString; - self.welcomeImageView.image = [UIImage imageNamed:@"horizontal_logo"]; + self.welcomeImageView.image = AssetSharedImages.horizontalLogo.image; [self.submitButton.layer setCornerRadius:5]; self.submitButton.clipsToBounds = YES; @@ -150,8 +150,8 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self.skipButton setTitle:[VectorL10n authSkip] forState:UIControlStateHighlighted]; self.skipButton.enabled = YES; - [self.customServersTickButton setImage:[UIImage imageNamed:@"selection_untick"] forState:UIControlStateNormal]; - [self.customServersTickButton setImage:[UIImage imageNamed:@"selection_untick"] forState:UIControlStateHighlighted]; + [self.customServersTickButton setImage:AssetImages.selectionUntick.image forState:UIControlStateNormal]; + [self.customServersTickButton setImage:AssetImages.selectionUntick.image forState:UIControlStateHighlighted]; if (!BuildSettings.authScreenShowRegister) { @@ -1273,7 +1273,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self setHomeServerTextFieldText:self.defaultHomeServerUrl]; [self setIdentityServerTextFieldText:self.defaultIdentityServerUrl]; - [self.customServersTickButton setImage:[UIImage imageNamed:@"selection_untick"] forState:UIControlStateNormal]; + [self.customServersTickButton setImage:AssetImages.selectionUntick.image forState:UIControlStateNormal]; self.customServersContainer.hidden = YES; // Refresh content view height @@ -1297,7 +1297,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self setIdentityServerTextFieldText:customIdentityServerURL]; } - [self.customServersTickButton setImage:[UIImage imageNamed:@"selection_tick"] forState:UIControlStateNormal]; + [self.customServersTickButton setImage:AssetImages.selectionTick.image forState:UIControlStateNormal]; self.customServersContainer.hidden = NO; // Refresh content view height diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index b4eaad74a..ea0bc4741 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -1322,7 +1322,7 @@ [phoneNumberPickerNavigationController pushViewController:phoneNumberCountryPicker animated:NO]; - UIBarButtonItem *leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"back_icon"] style:UIBarButtonItemStylePlain target:self action:@selector(dismissCountryPicker)]; + UIBarButtonItem *leftBarButtonItem = [[UIBarButtonItem alloc] initWithImage:AssetImages.backIcon.image style:UIBarButtonItemStylePlain target:self action:@selector(dismissCountryPicker)]; phoneNumberCountryPicker.navigationItem.leftBarButtonItem = leftBarButtonItem; [self.delegate authInputsView:self presentViewController:phoneNumberPickerNavigationController animated:YES]; diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index e43ec06d7..3dd714654 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -222,11 +222,11 @@ _sendLogs = sendLogs; if (_sendLogs) { - _sendLogsButtonImage.image = [UIImage imageNamed:@"selection_tick"]; + _sendLogsButtonImage.image = AssetImages.selectionTick.image; } else { - _sendLogsButtonImage.image = [UIImage imageNamed:@"selection_untick"]; + _sendLogsButtonImage.image = AssetImages.selectionUntick.image; } } @@ -235,11 +235,11 @@ _sendScreenshot = sendScreenshot; if (_sendScreenshot) { - _sendScreenshotButtonImage.image = [UIImage imageNamed:@"selection_tick"]; + _sendScreenshotButtonImage.image = AssetImages.selectionTick.image; } else { - _sendScreenshotButtonImage.image = [UIImage imageNamed:@"selection_untick"]; + _sendScreenshotButtonImage.image = AssetImages.selectionUntick.image; } } diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 8f9eab5a1..d4ff8d4d5 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -73,20 +73,20 @@ CallAudioRouteMenuViewDelegate> // Back button - UIImage *backButtonImage = [UIImage imageNamed:@"back_icon"]; + UIImage *backButtonImage = AssetImages.backIcon.image; [self.backToAppButton setImage:backButtonImage forState:UIControlStateNormal]; [self.backToAppButton setImage:backButtonImage forState:UIControlStateHighlighted]; // Camera switch - UIImage *cameraSwitchButtonImage = [UIImage imageNamed:@"camera_switch"]; + UIImage *cameraSwitchButtonImage = AssetImages.cameraSwitch.image; [self.cameraSwitchButton setImage:cameraSwitchButtonImage forState:UIControlStateNormal]; [self.cameraSwitchButton setImage:cameraSwitchButtonImage forState:UIControlStateHighlighted]; // Audio mute - UIImage *audioMuteOffButtonImage = [UIImage imageNamed:@"call_audio_mute_off_icon"]; - UIImage *audioMuteOnButtonImage = [UIImage imageNamed:@"call_audio_mute_on_icon"]; + UIImage *audioMuteOffButtonImage = AssetImages.callAudioMuteOffIcon.image; + UIImage *audioMuteOnButtonImage = AssetImages.callAudioMuteOnIcon.image; [self.audioMuteButton setImage:audioMuteOffButtonImage forState:UIControlStateNormal]; [self.audioMuteButton setImage:audioMuteOffButtonImage forState:UIControlStateHighlighted]; @@ -94,8 +94,8 @@ CallAudioRouteMenuViewDelegate> // Video mute - UIImage *videoOffButtonImage = [UIImage imageNamed:@"call_video_mute_off_icon"]; - UIImage *videoOnButtonImage = [UIImage imageNamed:@"call_video_mute_on_icon"]; + UIImage *videoOffButtonImage = AssetImages.callVideoMuteOffIcon.image; + UIImage *videoOnButtonImage = AssetImages.callVideoMuteOnIcon.image; [self.videoMuteButton setImage:videoOffButtonImage forState:UIControlStateNormal]; [self.videoMuteButton setImage:videoOffButtonImage forState:UIControlStateHighlighted]; @@ -103,14 +103,14 @@ CallAudioRouteMenuViewDelegate> // More - UIImage *moreButtonImage = [UIImage imageNamed:@"call_more_icon"]; + UIImage *moreButtonImage = AssetImages.callMoreIcon.image; [self.moreButtonForVoice setImage:moreButtonImage forState:UIControlStateNormal]; [self.moreButtonForVideo setImage:moreButtonImage forState:UIControlStateNormal]; // Hang up - UIImage *hangUpButtonImage = [UIImage imageNamed:@"call_hangup_large"]; + UIImage *hangUpButtonImage = AssetImages.callHangupLarge.image; [self.endCallButton setTitle:nil forState:UIControlStateNormal]; [self.endCallButton setTitle:nil forState:UIControlStateHighlighted]; @@ -269,17 +269,17 @@ CallAudioRouteMenuViewDelegate> switch (self.mxCall.audioOutputRouter.currentRoute.routeType) { case MXiOSAudioOutputRouteTypeBuiltIn: - [self.speakerButton setImage:[UIImage imageNamed:@"call_speaker_off_icon"] + [self.speakerButton setImage:AssetImages.callSpeakerOffIcon.image forState:UIControlStateNormal]; break; case MXiOSAudioOutputRouteTypeLoudSpeakers: - [self.speakerButton setImage:[UIImage imageNamed:@"call_speaker_on_icon"] + [self.speakerButton setImage:AssetImages.callSpeakerOnIcon.image forState:UIControlStateNormal]; break; case MXiOSAudioOutputRouteTypeExternalWired: case MXiOSAudioOutputRouteTypeExternalBluetooth: case MXiOSAudioOutputRouteTypeExternalCar: - [self.speakerButton setImage:[UIImage imageNamed:@"call_speaker_external_icon"] + [self.speakerButton setImage:AssetImages.callSpeakerExternalIcon.image forState:UIControlStateNormal]; break; } @@ -484,7 +484,7 @@ CallAudioRouteMenuViewDelegate> andFontSize:fontSize]; } - return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + return [MXKTools paintImage:AssetImages.placeholder.image withColor:self.overriddenTheme.tintColor]; } diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 35500cf4e..b58145546 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -89,7 +89,7 @@ static const CGFloat kButtonSize = 80.0; UIColor *answerButtonBorderColor = ThemeService.shared.theme.tintColor; - self.answerButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_hangon_icon"] + self.answerButton = [[CircleButton alloc] initWithImage:AssetImages.voiceCallHangonIcon.image borderColor:answerButtonBorderColor]; self.answerButton.defaultBackgroundColor = ThemeService.shared.theme.backgroundColor; self.answerButton.tintColor = answerButtonBorderColor; @@ -103,7 +103,7 @@ static const CGFloat kButtonSize = 80.0; UIColor *rejectButtonBorderColor = ThemeService.shared.theme.warningColor; - self.rejectButton = [[CircleButton alloc] initWithImage:[UIImage imageNamed:@"voice_call_hangup_icon"] + self.rejectButton = [[CircleButton alloc] initWithImage:AssetImages.voiceCallHangupIcon.image borderColor:rejectButtonBorderColor]; self.rejectButton.defaultBackgroundColor = ThemeService.shared.theme.backgroundColor; self.rejectButton.tintColor = rejectButtonBorderColor; diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 2e16761eb..faaa6554b 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -821,11 +821,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou UIImage *chevron; if (shrinkedSectionsBitMask & sectionBitwise) { - chevron = [UIImage imageNamed:@"disclosure_icon"]; + chevron = AssetImages.disclosureIcon.image; } else { - chevron = [UIImage imageNamed:@"shrink_icon"]; + chevron = AssetImages.shrinkIcon.image; } UIImageView *chevronView = [[UIImageView alloc] initWithImage:chevron]; chevronView.tintColor = ThemeService.shared.theme.textSecondaryColor; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 852a336a2..41b8c20ae 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -1109,7 +1109,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro }]; directChatAction.backgroundColor = actionBackgroundColor; - UIImage *directChatImage = [UIImage imageNamed:@"room_action_direct_chat"]; + UIImage *directChatImage = AssetImages.roomActionDirectChat.image; directChatImage = [directChatImage vc_tintedImageUsingColor:isDirect ? selectedColor : unselectedColor]; directChatAction.image = [directChatImage vc_notRenderedImage]; @@ -1136,13 +1136,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro muteAction.backgroundColor = actionBackgroundColor; UIImage *notificationImage; - if([BuildSettings showNotificationsV2]) + if([BuildSettings showNotificationsV2] && isMuted) { - notificationImage = isMuted ? [UIImage imageNamed:@"room_action_notification_muted"] : [UIImage imageNamed:@"room_action_notification"]; + notificationImage = AssetImages.roomActionNotificationMuted.image; } else { - notificationImage = [UIImage imageNamed:@"room_action_notification"]; + notificationImage = AssetImages.roomActionNotification.image; } notificationImage = [notificationImage vc_tintedImageUsingColor:isMuted ? unselectedColor : selectedColor]; @@ -1173,7 +1173,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro }]; favouriteAction.backgroundColor = actionBackgroundColor; - UIImage *favouriteImage = [UIImage imageNamed:@"room_action_favourite"]; + UIImage *favouriteImage = AssetImages.roomActionFavourite.image; favouriteImage = [favouriteImage vc_tintedImageUsingColor:isFavourite ? selectedColor : unselectedColor]; favouriteAction.image = [favouriteImage vc_notRenderedImage]; @@ -1190,7 +1190,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro }]; priorityAction.backgroundColor = actionBackgroundColor; - UIImage *priorityImage = isInLowPriority ? [UIImage imageNamed:@"room_action_priority_high"] : [UIImage imageNamed:@"room_action_priority_low"]; + UIImage *priorityImage = isInLowPriority ? AssetImages.roomActionPriorityHigh.image : AssetImages.roomActionPriorityLow.image; priorityImage = [priorityImage vc_tintedImageUsingColor:unselectedColor]; priorityAction.image = [priorityImage vc_notRenderedImage]; @@ -1204,7 +1204,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro }]; leaveAction.backgroundColor = actionBackgroundColor; - UIImage *leaveImage = [UIImage imageNamed:@"room_action_leave"]; + UIImage *leaveImage = AssetImages.roomActionLeave.image; leaveImage = [leaveImage vc_tintedImageUsingColor:unselectedColor]; leaveAction.image = [leaveImage vc_notRenderedImage]; diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index c78907883..26cf2b02d 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -475,7 +475,7 @@ addParticipantButtonImageView.backgroundColor = [UIColor clearColor]; addParticipantButtonImageView.contentMode = UIViewContentModeCenter; - addParticipantButtonImageView.image = [UIImage imageNamed:@"add_group_participant"]; + addParticipantButtonImageView.image = AssetImages.addGroupParticipant.image; CGFloat side = 78.0f; NSLayoutConstraint* widthConstraint = [NSLayoutConstraint constraintWithItem:addParticipantButtonImageView @@ -537,7 +537,7 @@ contactsDataSource.displaySearchInputInContactsList = YES; contactsDataSource.forceMatrixIdInDisplayName = YES; // Add a plus icon to the contact cell in the contacts picker, in order to make it more understandable for the end user. - contactsDataSource.contactCellAccessoryImage = [[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]; + contactsDataSource.contactCellAccessoryImage = [AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]; // List all the participants matrix user id to ignore them during the contacts search. for (Contact *contact in actualParticipants) diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index fd84c8c03..9a2935903 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -844,11 +844,11 @@ UIImage *chevron; if (shrinkedSectionsBitMask & sectionBitwise) { - chevron = [UIImage imageNamed:@"disclosure_icon"]; + chevron = AssetImages.disclosureIcon.image; } else { - chevron = [UIImage imageNamed:@"shrink_icon"]; + chevron = AssetImages.shrinkIcon.image; } UIImageView *chevronView = [[UIImageView alloc] initWithImage:chevron]; chevronView.tintColor = ThemeService.shared.theme.textSecondaryColor; @@ -892,7 +892,7 @@ 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"]; + localContactsCheckbox.image = hideNonMatrixEnabledContacts ? AssetImages.selectionTick.image : AssetImages.selectionUntick.image; localContactsCheckbox.tintColor = ThemeService.shared.theme.tintColor; // Add the check box container diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index 8527ba72c..fe2b2d6e1 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -733,7 +733,7 @@ } else { - roomCell.avatarImageView.image = [UIImage imageNamed:@"start_chat"]; + roomCell.avatarImageView.image = AssetImages.startChat.image; roomCell.avatarImageView.defaultBackgroundColor = [UIColor clearColor]; roomCell.titleLabel.text = [VectorL10n roomParticipantsActionStartNewChat]; } diff --git a/Riot/Modules/Favorites/FavouritesViewController.m b/Riot/Modules/Favorites/FavouritesViewController.m index 23b43b856..62ef8cd8f 100644 --- a/Riot/Modules/Favorites/FavouritesViewController.m +++ b/Riot/Modules/Favorites/FavouritesViewController.m @@ -155,11 +155,11 @@ { if (ThemeService.shared.isCurrentThemeDark) { - return [UIImage imageNamed:@"favourites_empty_screen_artwork_dark"]; + return AssetImages.favouritesEmptyScreenArtworkDark.image; } else { - return [UIImage imageNamed:@"favourites_empty_screen_artwork"]; + return AssetImages.favouritesEmptyScreenArtwork.image; } } diff --git a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m index 6e509e089..5a183820f 100644 --- a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m +++ b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m @@ -132,19 +132,19 @@ if ([msgtype isEqualToString:kMXMessageTypeImage]) { - return [UIImage imageNamed:@"file_photo_icon"]; + return AssetImages.filePhotoIcon.image; } else if ([msgtype isEqualToString:kMXMessageTypeAudio]) { - return [UIImage imageNamed:@"file_music_icon"]; + return AssetImages.fileMusicIcon.image; } else if ([msgtype isEqualToString:kMXMessageTypeVideo]) { - return [UIImage imageNamed:@"file_video_icon"]; + return AssetImages.fileVideoIcon.image; } else if ([msgtype isEqualToString:kMXMessageTypeFile]) { - return [UIImage imageNamed:@"file_doc_icon"]; + return AssetImages.fileDocIcon.image; } return nil; diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index e2633d41c..287a71a6f 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -107,19 +107,19 @@ switch (type) { case MXKAttachmentTypeImage: - image = [UIImage imageNamed:@"file_photo_icon"]; + image = AssetImages.filePhotoIcon.image; break; case MXKAttachmentTypeAudio: - image = [UIImage imageNamed:@"file_music_icon"]; + image = AssetImages.fileMusicIcon.image; break; case MXKAttachmentTypeVoiceMessage: - image = [UIImage imageNamed:@"file_music_icon"]; + image = AssetImages.fileMusicIcon.image; break; case MXKAttachmentTypeVideo: - image = [UIImage imageNamed:@"file_video_icon"]; + image = AssetImages.fileVideoIcon.image; break; case MXKAttachmentTypeFile: - image = [UIImage imageNamed:@"file_doc_icon"]; + image = AssetImages.fileDocIcon.image; break; default: break; diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index 7c8d816db..78eeaa4b7 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -251,7 +251,7 @@ peopleSearchDataSource.showLocalContacts = NO; peopleSearchDataSource.areSectionsShrinkable = YES; peopleSearchDataSource.displaySearchInputInContactsList = YES; - peopleSearchDataSource.contactCellAccessoryImage = [[UIImage imageNamed: @"disclosure_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textSecondaryColor];; + peopleSearchDataSource.contactCellAccessoryImage = [AssetImages.disclosureIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textSecondaryColor];; [peopleSearchViewController displayList:peopleSearchDataSource]; // Check whether there are others sessions diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index 0a798aefc..820f2ac03 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -49,7 +49,7 @@ } else { - self.avatarImageView.image = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + self.avatarImageView.image = [MXKTools paintImage:AssetImages.placeholder.image withColor:ThemeService.shared.theme.tintColor]; } diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 3a02c310e..e94b4c472 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -89,7 +89,7 @@ self.recentsTableView.contentInsetAdjustmentBehavior = UIScrollViewContentInsetAdjustmentNever; // Add the (+) button programmatically - plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"plus_floating_action"] + plusButtonImageView = [self vc_addFABWithImage:AssetImages.plusFloatingAction.image target:self action:@selector(onPlusButtonPressed)]; @@ -416,19 +416,19 @@ // Update the edition menu content (Use the button tag to store the current value). tableViewCell.directChatButton.tag = room.isDirect; [tableViewCell.directChatButton addTarget:self action:@selector(onDirectChatButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - tableViewCell.directChatImageView.image = [UIImage imageNamed:@"room_action_direct_chat"]; + tableViewCell.directChatImageView.image = AssetImages.roomActionDirectChat.image; tableViewCell.directChatImageView.tintColor = room.isDirect ? selectedColor : unselectedColor; tableViewCell.notificationsButton.tag = room.isMute || room.isMentionsOnly; [tableViewCell.notificationsButton addTarget:self action:@selector(onNotificationsButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - if ([BuildSettings showNotificationsV2]) + if ([BuildSettings showNotificationsV2] && tableViewCell.notificationsButton.tag) { - tableViewCell.notificationsImageView.image = tableViewCell.notificationsButton.tag ? [UIImage imageNamed:@"room_action_notification_muted"] : [UIImage imageNamed:@"room_action_notification"]; + tableViewCell.notificationsImageView.image = AssetImages.roomActionNotificationMuted.image; } else { - tableViewCell.notificationsImageView.image = [UIImage imageNamed:@"room_action_notification"]; + tableViewCell.notificationsImageView.image = AssetImages.roomActionNotification.image; } tableViewCell.notificationsImageView.tintColor = tableViewCell.notificationsButton.tag ? unselectedColor : selectedColor; @@ -446,16 +446,16 @@ tableViewCell.favouriteButton.tag = (currentTag && [kMXRoomTagFavourite isEqualToString:currentTag.name]); [tableViewCell.favouriteButton addTarget:self action:@selector(onFavouriteButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - tableViewCell.favouriteImageView.image = [UIImage imageNamed:@"room_action_favourite"]; + tableViewCell.favouriteImageView.image = AssetImages.roomActionFavourite.image; tableViewCell.favouriteImageView.tintColor = tableViewCell.favouriteButton.tag ? selectedColor : unselectedColor; tableViewCell.priorityButton.tag = (currentTag && [kMXRoomTagLowPriority isEqualToString:currentTag.name]); [tableViewCell.priorityButton addTarget:self action:@selector(onPriorityButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - tableViewCell.priorityImageView.image = tableViewCell.priorityButton.tag ? [UIImage imageNamed:@"room_action_priority_high"] : [UIImage imageNamed:@"room_action_priority_low"]; + tableViewCell.priorityImageView.image = tableViewCell.priorityButton.tag ? AssetImages.roomActionPriorityHigh.image : AssetImages.roomActionPriorityLow.image; tableViewCell.priorityImageView.tintColor = unselectedColor; [tableViewCell.leaveButton addTarget:self action:@selector(onLeaveButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - tableViewCell.leaveImageView.image = [UIImage imageNamed:@"room_action_leave"]; + tableViewCell.leaveImageView.image = AssetImages.roomActionLeave.image; tableViewCell.leaveImageView.tintColor = unselectedColor; } } @@ -1048,11 +1048,11 @@ { if (ThemeService.shared.isCurrentThemeDark) { - return [UIImage imageNamed:@"home_empty_screen_artwork_dark"]; + return AssetImages.homeEmptyScreenArtworkDark.image; } else { - return [UIImage imageNamed:@"home_empty_screen_artwork"]; + return AssetImages.homeEmptyScreenArtwork.image; } } diff --git a/Riot/Modules/Integrations/Widgets/WidgetViewController.m b/Riot/Modules/Integrations/Widgets/WidgetViewController.m index a5e93b152..77056bcb0 100644 --- a/Riot/Modules/Integrations/Widgets/WidgetViewController.m +++ b/Riot/Modules/Integrations/Widgets/WidgetViewController.m @@ -60,7 +60,7 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse { self.navigationItem.title = widget.name ? widget.name : widget.type; - UIBarButtonItem *menuButton = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"room_context_menu_more"] style:UIBarButtonItemStylePlain target:self action:@selector(onMenuButtonPressed:)]; + UIBarButtonItem *menuButton = [[UIBarButtonItem alloc] initWithImage:AssetImages.roomContextMenuMore.image style:UIBarButtonItemStylePlain target:self action:@selector(onMenuButtonPressed:)]; self.navigationItem.rightBarButtonItem = menuButton; } diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index c01c845e6..440aeb027 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -268,10 +268,10 @@ }]; - cell.bottomLeftIcon.image = [UIImage imageNamed:@"video_icon"]; + cell.bottomLeftIcon.image = AssetImages.videoIcon.image; cell.bottomLeftIcon.hidden = (asset.mediaType == PHAssetMediaTypeImage); - cell.bottomRightIcon.image = [UIImage imageNamed:@"selection_tick"]; + cell.bottomRightIcon.image = AssetImages.selectionTick.image; cell.bottomRightIcon.tintColor = ThemeService.shared.theme.tintColor; cell.bottomRightIcon.hidden = !selectedAssets || (NSNotFound == [selectedAssets indexOfObject:asset]); diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index 48ff40d19..8905b926b 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -729,8 +729,8 @@ videoPlayerControl = [UIButton buttonWithType:UIButtonTypeCustom]; [videoPlayerControl addTarget:self action:@selector(controlVideoPlayer) forControlEvents:UIControlEventTouchUpInside]; videoPlayerControl.frame = CGRectMake(0, 0, 44, 44); - [videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateNormal]; - [videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateHighlighted]; + [videoPlayerControl setImage:AssetImages.cameraPlay.image forState:UIControlStateNormal]; + [videoPlayerControl setImage:AssetImages.cameraPlay.image forState:UIControlStateHighlighted]; [validationView addSubview:videoPlayerControl]; videoPlayerControl.center = validationView.imageView.center; @@ -796,8 +796,8 @@ [videoPlayer.player seekToTime:kCMTimeZero]; [videoPlayer.view removeFromSuperview]; - [videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateNormal]; - [videoPlayerControl setImage:[UIImage imageNamed:@"camera_play"] forState:UIControlStateHighlighted]; + [videoPlayerControl setImage:AssetImages.cameraPlay.image forState:UIControlStateNormal]; + [videoPlayerControl setImage:AssetImages.cameraPlay.image forState:UIControlStateHighlighted]; } else { @@ -815,8 +815,8 @@ [videoPlayer.player play]; - [videoPlayerControl setImage:[UIImage imageNamed:@"camera_stop"] forState:UIControlStateNormal]; - [videoPlayerControl setImage:[UIImage imageNamed:@"camera_stop"] forState:UIControlStateHighlighted]; + [videoPlayerControl setImage:AssetImages.cameraStop.image forState:UIControlStateNormal]; + [videoPlayerControl setImage:AssetImages.cameraStop.image forState:UIControlStateHighlighted]; [validationView bringSubviewToFront:videoPlayerControl]; } } @@ -860,7 +860,7 @@ }]; - cell.bottomLeftIcon.image = [UIImage imageNamed:@"video_icon"]; + cell.bottomLeftIcon.image = AssetImages.videoIcon.image; cell.bottomLeftIcon.hidden = (asset.mediaType == PHAssetMediaTypeImage); // Disable user interaction in mxkImageView, in order to let collection handle user selection @@ -968,7 +968,7 @@ if (collection.assetCollectionSubtype == PHAssetCollectionSubtypeSmartAlbumVideos) { - cell.bottomLeftIcon.image = [UIImage imageNamed:@"video_icon"]; + cell.bottomLeftIcon.image = AssetImages.videoIcon.image; cell.bottomLeftIcon.hidden = NO; } else diff --git a/Riot/Modules/People/PeopleViewController.m b/Riot/Modules/People/PeopleViewController.m index 43bb1754c..028ec8eef 100644 --- a/Riot/Modules/People/PeopleViewController.m +++ b/Riot/Modules/People/PeopleViewController.m @@ -69,7 +69,7 @@ self.recentsTableView.tag = RecentsDataSourceModePeople; // Add the (+) button programmatically - plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"people_floating_action"] + plusButtonImageView = [self vc_addFABWithImage:AssetImages.peopleFloatingAction.image target:self action:@selector(onPlusButtonPressed)]; } @@ -177,11 +177,11 @@ { if (ThemeService.shared.isCurrentThemeDark) { - return [UIImage imageNamed:@"people_empty_screen_artwork_dark"]; + return AssetImages.peopleEmptyScreenArtworkDark.image; } else { - return [UIImage imageNamed:@"people_empty_screen_artwork"]; + return AssetImages.peopleEmptyScreenArtwork.image; } } diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index 687587dfe..b5928f009 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -350,7 +350,7 @@ return [AvatarGenerator generateAvatarForMatrixItem:self.mxRoomMember.userId withDisplayName:self.mxRoomMember.displayname]; } - return [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + return [MXKTools paintImage:AssetImages.placeholder.image withColor:ThemeService.shared.theme.tintColor]; } @@ -984,7 +984,7 @@ } else { - roomCell.avatarImageView.image = [UIImage imageNamed:@"start_chat"]; + roomCell.avatarImageView.image = AssetImages.startChat.image; roomCell.avatarImageView.defaultBackgroundColor = [UIColor clearColor]; roomCell.avatarImageView.userInteractionEnabled = NO; roomCell.titleLabel.text = [VectorL10n roomParticipantsActionStartNewChat]; diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index bdf4465b6..5eadaa9b7 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -145,7 +145,7 @@ // Add invite members button programmatically - [self vc_addFABWithImage:[UIImage imageNamed:@"add_member_floating_action"] + [self vc_addFABWithImage:AssetImages.addMemberFloatingAction.image target:self action:@selector(onAddParticipantButtonPressed)]; @@ -562,7 +562,7 @@ contactsDataSource.displaySearchInputInContactsList = YES; contactsDataSource.forceMatrixIdInDisplayName = YES; // Add a plus icon to the contact cell in the contacts picker, in order to make it more understandable for the end user. - contactsDataSource.contactCellAccessoryImage = [[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]; + contactsDataSource.contactCellAccessoryImage = [AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]; // List all the participants matrix user id to ignore them during the contacts search. for (Contact *contact in actualParticipants) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index d5f40da02..1c0e72410 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -442,7 +442,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; if (ThemeService.shared.isCurrentThemeDark) { - [self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown_dark"] forState:UIControlStateNormal]; + [self.scrollToBottomButton setImage:AssetImages.scrolldownDark.image forState:UIControlStateNormal]; self.jumpToLastUnreadBanner.backgroundColor = ThemeService.shared.theme.colors.navigation; [self.jumpToLastUnreadBanner vc_removeShadow]; @@ -450,7 +450,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } else { - [self.scrollToBottomButton setImage:[UIImage imageNamed:@"scrolldown"] forState:UIControlStateNormal]; + [self.scrollToBottomButton setImage:AssetImages.scrolldown.image forState:UIControlStateNormal]; self.jumpToLastUnreadBanner.backgroundColor = ThemeService.shared.theme.colors.background; [self.jumpToLastUnreadBanner vc_addShadowWithColor:ThemeService.shared.theme.shadowColor @@ -1429,7 +1429,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; - (UIBarButtonItem *)videoCallBarButtonItem { - UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"video_call"] + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:AssetImages.videoCall.image style:UIBarButtonItemStylePlain target:self action:@selector(onVideoCallPressed:)]; @@ -1440,7 +1440,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; - (UIBarButtonItem *)threadMoreBarButtonItem { - UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"room_context_menu_more"] + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:AssetImages.roomContextMenuMore.image style:UIBarButtonItemStylePlain target:self action:@selector(onButtonPressed:)]; @@ -1452,7 +1452,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; - (BadgedBarButtonItem *)threadListBarButtonItem { UIButton *button = [UIButton new]; - UIImage *icon = [[UIImage imageNamed:@"threads_icon"] vc_resizedWith:CGSizeMake(21, 21)]; + UIImage *icon = [AssetImages.threadsIcon.image vc_resizedWith:CGSizeMake(21, 21)]; button.contentEdgeInsets = UIEdgeInsetsMake(4, 8, 4, 8); [button setImage:icon forState:UIControlStateNormal]; @@ -1609,7 +1609,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; if (self.roomDataSource.room.summary.membersCount.joined == 2 && self.roomDataSource.room.isDirect) { // voice call button for Matrix call - UIBarButtonItem *itemVoice = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"voice_call_hangon_icon"] + UIBarButtonItem *itemVoice = [[UIBarButtonItem alloc] initWithImage:AssetImages.voiceCallHangonIcon.image style:UIBarButtonItemStylePlain target:self action:@selector(onVoiceCallPressed:)]; @@ -1638,7 +1638,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; { // show Join button CallTileActionButton *button = [CallTileActionButton new]; - [button setImage:[UIImage imageNamed:@"call_video_icon"] + [button setImage:AssetImages.callVideoIcon.image forState:UIControlStateNormal]; [button setTitle:[VectorL10n roomJoinGroupCall] forState:UIControlStateNormal]; @@ -1660,7 +1660,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; UIBarButtonItem *item = [self videoCallBarButtonItem]; if (!self.canEditJitsiWidget) { - item.image = [[UIImage imageNamed:@"video_call"] vc_withAlpha:0.3]; + item.image = [AssetImages.videoCall.image vc_withAlpha:0.3]; } [rightBarButtonItems addObject:item]; } @@ -1669,7 +1669,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; if ([self widgetsCount:NO]) { - UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"integrations_icon"] + UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithImage:AssetImages.integrationsIcon.image style:UIBarButtonItemStylePlain target:self action:@selector(onIntegrationsPressed:)]; @@ -1986,7 +1986,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; NSMutableArray *actionItems = [NSMutableArray new]; if (RiotSettings.shared.roomScreenAllowMediaLibraryAction) { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_media_library"] andAction:^{ + [actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionMediaLibrary.image andAction:^{ MXStrongifyAndReturnIfNil(self); if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; @@ -1996,7 +1996,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } if (RiotSettings.shared.roomScreenAllowStickerAction) { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_sticker"] andAction:^{ + [actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionSticker.image andAction:^{ MXStrongifyAndReturnIfNil(self); if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; @@ -2006,7 +2006,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } if (RiotSettings.shared.roomScreenAllowFilesAction) { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_file"] andAction:^{ + [actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionFile.image andAction:^{ MXStrongifyAndReturnIfNil(self); if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; @@ -2016,7 +2016,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } if (BuildSettings.pollsEnabled && self.displayConfiguration.sendingPollsEnabled) { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_poll"] andAction:^{ + [actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionPoll.image andAction:^{ MXStrongifyAndReturnIfNil(self); if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; @@ -2026,7 +2026,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } if (BuildSettings.locationSharingEnabled) { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_location"] andAction:^{ + [actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionLocation.image andAction:^{ MXStrongifyAndReturnIfNil(self); if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; @@ -2036,7 +2036,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } if (RiotSettings.shared.roomScreenAllowCameraAction) { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_camera"] andAction:^{ + [actionItems addObject:[[RoomActionItem alloc] initWithImage:AssetImages.actionCamera.image andAction:^{ MXStrongifyAndReturnIfNil(self); if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; @@ -2553,7 +2553,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } else { - previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + previewHeader.roomAvatarPlaceholder = [MXKTools paintImage:AssetImages.placeholder.image withColor:ThemeService.shared.theme.tintColor]; } } @@ -3717,7 +3717,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; { MXKPasteboardManager.shared.pasteboard.URL = url; [self.view vc_toastWithMessage:VectorL10n.roomEventCopyLinkInfo - image:[UIImage imageNamed:@"link_icon"] + image:AssetImages.linkIcon.image duration:2.0 position:ToastPositionBottom additionalMargin:self.roomInputToolbarContainerHeightConstraint.constant]; diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index d844deaee..4d07543fe 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -1047,7 +1047,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { MXKPasteboardManager.shared.pasteboard.URL = url; [self.view vc_toastWithMessage:VectorL10n.roomEventCopyLinkInfo - image:[UIImage imageNamed:@"link_icon"] + image:AssetImages.linkIcon.image duration:2.0 position:ToastPositionBottom additionalMargin:0.0]; @@ -2640,7 +2640,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addAddressCell.mxkLabel.text = nil; addAddressCell.accessoryType = UITableViewCellAccessoryNone; - addAddressCell.accessoryView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; + addAddressCell.accessoryView = [[UIImageView alloc] initWithImage:[AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; addAddressTextField = addAddressCell.mxkTextField; addAddressTextField.placeholder = [VectorL10n roomDetailsNewAddressPlaceholder:self.mainSession.matrixRestClient.homeserverSuffix]; @@ -2717,7 +2717,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { if ([alias isEqualToString:canonicalAlias]) { - addressCell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"main_alias_icon"]]; + addressCell.accessoryView = [[UIImageView alloc] initWithImage:AssetImages.mainAliasIcon.image]; } } } @@ -2741,7 +2741,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti addCommunityCell.mxkLabel.text = nil; addCommunityCell.accessoryType = UITableViewCellAccessoryNone; - addCommunityCell.accessoryView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; + addCommunityCell.accessoryView = [[UIImageView alloc] initWithImage:[AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; addGroupTextField = addCommunityCell.mxkTextField; addGroupTextField.placeholder = [VectorL10n roomDetailsNewFlairPlaceholder:self.mainSession.matrixRestClient.homeserverSuffix]; @@ -3270,7 +3270,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti completionHandler(YES); }]; removeAddressAction.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - removeAddressAction.image = [[UIImage imageNamed:@"remove_icon"] vc_notRenderedImage]; + removeAddressAction.image = [AssetImages.removeIcon.image vc_notRenderedImage]; // Create swipe action configuration @@ -3291,7 +3291,7 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti completionHandler(YES); }]; removeAddressAction.backgroundColor = ThemeService.shared.theme.headerBackgroundColor; - removeAddressAction.image = [[UIImage imageNamed:@"remove_icon"] vc_notRenderedImage]; + removeAddressAction.image = [AssetImages.removeIcon.image vc_notRenderedImage]; // Create swipe action configuration diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m index b623ffc7d..718cce122 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m @@ -34,11 +34,11 @@ { if (enabled) { - _checkBox.image = [UIImage imageNamed:@"selection_tick"]; + _checkBox.image = AssetImages.selectionTick.image; } else { - _checkBox.image = [UIImage imageNamed:@"selection_untick"]; + _checkBox.image = AssetImages.selectionUntick.image; } _enabled = enabled; diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m index 9504214a1..c3a683e7c 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m @@ -131,7 +131,7 @@ [checkboxContainer addSubview:checkbox]; // Store the new check box unselected by default - checkbox.image = [UIImage imageNamed:@"selection_untick"]; + checkbox.image = AssetImages.selectionUntick.image; checkbox.tintColor = ThemeService.shared.theme.tintColor; checkbox.tag = 0; [checkBoxesArray addObject:checkbox]; @@ -263,7 +263,7 @@ if (isSelected && !checkBox.tag) { - checkBox.image = [UIImage imageNamed:@"selection_tick"]; + checkBox.image = AssetImages.selectionTick.image; checkBox.tag = 1; if (!self.allowsMultipleSelection) @@ -276,7 +276,7 @@ checkBox = checkBoxesArray[k]; if (checkBox.tag) { - checkBox.image = [UIImage imageNamed:@"selection_untick"]; + checkBox.image = AssetImages.selectionUntick.image; checkBox.tag = 0; } } @@ -285,7 +285,7 @@ } else if (!isSelected && checkBox.tag) { - checkBox.image = [UIImage imageNamed:@"selection_untick"]; + checkBox.image = AssetImages.selectionUntick.image; checkBox.tag = 0; } } diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index f32e4cc68..6acd41443 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -124,7 +124,7 @@ [self.resendButton setTitle:[VectorL10n retry] forState:UIControlStateNormal]; self.resendButton.backgroundColor = ThemeService.shared.theme.tintColor; - UIImage *image = [[UIImage imageNamed:@"room_context_menu_delete"] imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; + UIImage *image = [AssetImages.roomContextMenuDelete.image imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; [self.deleteButton setImage:image forState:UIControlStateNormal]; self.deleteButton.tintColor = ThemeService.shared.theme.warningColor; @@ -174,7 +174,7 @@ if (labelText.length) { - self.iconImageView.image = [UIImage imageNamed:@"error"]; + self.iconImageView.image = AssetImages.error.image; self.iconImageView.tintColor = ThemeService.shared.theme.noticeColor; self.messageLabel.text = labelText; self.messageLabel.textColor = ThemeService.shared.theme.warningColor; @@ -192,7 +192,7 @@ if (labelText.length) { - self.iconImageView.image = [UIImage imageNamed:@"typing"]; + self.iconImageView.image = AssetImages.typing.image; self.iconImageView.tintColor = ThemeService.shared.theme.tintColor; self.messageLabel.text = labelText; @@ -309,7 +309,7 @@ self.messageTextView.hidden = NO; self.messageTextView.backgroundColor = [UIColor clearColor]; - self.iconImageView.image = [UIImage imageNamed:@"error"]; + self.iconImageView.image = AssetImages.error.image; self.iconImageView.tintColor = ThemeService.shared.theme.noticeColor; self.iconImageView.hidden = NO; diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.m index 6958e3ed5..7a5e50ff9 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.m @@ -16,6 +16,7 @@ */ #import "RoomEncryptedDataBubbleCell.h" +#import "GeneratedInterface-Swift.h" NSString *const kRoomEncryptedDataBubbleCellTapOnEncryptionIcon = @"kRoomEncryptedDataBubbleCellTapOnEncryptionIcon"; @@ -28,7 +29,7 @@ NSString *const kRoomEncryptedDataBubbleCellTapOnEncryptionIcon = @"kRoomEncrypt return nil; } - return [UIImage imageNamed:@"encryption_warning"]; + return AssetImages.encryptionWarning.image; } + (void)addEncryptionStatusFromBubbleData:(MXKRoomBubbleCellData *)bubbleData inContainerView:(UIView *)containerView diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index cffe8fe1b..63737645b 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -127,21 +127,21 @@ static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3; self.attachMediaButton.accessibilityLabel = [VectorL10n roomAccessibilityUpload]; - UIImage *image = [UIImage imageNamed:@"input_text_background"]; + UIImage *image = AssetImages.inputTextBackground.image; image = [image resizableImageWithCapInsets:UIEdgeInsetsMake(9, 15, 10, 16)]; self.inputTextBackgroundView.image = image; self.inputTextBackgroundView.tintColor = ThemeService.shared.theme.roomInputTextBorder; if ([ThemeService.shared.themeId isEqualToString:@"light"]) { - [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon"] forState:UIControlStateNormal]; + [self.attachMediaButton setImage:AssetImages.uploadIcon.image forState:UIControlStateNormal]; } else if ([ThemeService.shared.themeId isEqualToString:@"dark"] || [ThemeService.shared.themeId isEqualToString:@"black"]) { - [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal]; + [self.attachMediaButton setImage:AssetImages.uploadIconDark.image forState:UIControlStateNormal]; } else if (ThemeService.shared.theme.userInterfaceStyle == UIUserInterfaceStyleDark) { - [self.attachMediaButton setImage:[UIImage imageNamed:@"upload_icon_dark"] forState:UIControlStateNormal]; + [self.attachMediaButton setImage:AssetImages.uploadIconDark.image forState:UIControlStateNormal]; } self.inputContextImageView.tintColor = ThemeService.shared.theme.textSecondaryColor; @@ -192,8 +192,8 @@ static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3; switch (_sendMode) { case RoomInputToolbarViewSendModeReply: - buttonImage = [UIImage imageNamed:@"send_icon"]; - self.inputContextImageView.image = [UIImage imageNamed:@"input_reply_icon"]; + buttonImage = AssetImages.sendIcon.image; + self.inputContextImageView.image = AssetImages.inputReplyIcon.image; self.inputContextLabel.text = [VectorL10n roomMessageReplyingTo:self.eventSenderDisplayName]; self.inputContextViewHeightConstraint.constant = kContextBarHeight; @@ -201,8 +201,8 @@ static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3; self.textView.maxHeight -= kContextBarHeight; break; case RoomInputToolbarViewSendModeEdit: - buttonImage = [UIImage imageNamed:@"save_icon"]; - self.inputContextImageView.image = [UIImage imageNamed:@"input_edit_icon"]; + buttonImage = AssetImages.saveIcon.image; + self.inputContextImageView.image = AssetImages.inputEditIcon.image; self.inputContextLabel.text = [VectorL10n roomMessageEditing]; self.inputContextViewHeightConstraint.constant = kContextBarHeight; @@ -210,7 +210,7 @@ static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3; self.textView.maxHeight -= kContextBarHeight; break; default: - buttonImage = [UIImage imageNamed:@"send_icon"]; + buttonImage = AssetImages.sendIcon.image; if (previousMode != _sendMode) { diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index 81a128564..7e8456a5b 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -102,7 +102,7 @@ andImageOrientation:UIImageOrientationUp toFitViewSize:self.roomAvatar.frame.size withMethod:MXThumbnailingMethodCrop - previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + previewImage:[MXKTools paintImage:AssetImages.placeholder.image withColor:ThemeService.shared.theme.tintColor] mediaManager:self.mxRoom.mxSession.mediaManager]; } diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index fed334510..6ec9484e6 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -63,7 +63,7 @@ [self.iconImageView setImageURI:iconURL withType:nil andImageOrientation:UIImageOrientationUp - previewImage:[MXKTools paintImage:[UIImage imageNamed:@"placeholder"] + previewImage:[MXKTools paintImage:AssetImages.placeholder.image withColor:ThemeService.shared.theme.tintColor] mediaManager:cellData.mediaManager]; } diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 71975e939..6e2adfc62 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -58,7 +58,7 @@ self.recentsTableView.tag = RecentsDataSourceModeRooms; // Add the (+) button programmatically - plusButtonImageView = [self vc_addFABWithImage:[UIImage imageNamed:@"rooms_floating_action"] + plusButtonImageView = [self vc_addFABWithImage:AssetImages.roomsFloatingAction.image target:self action:@selector(onPlusButtonPressed)]; } @@ -157,11 +157,11 @@ { if (ThemeService.shared.isCurrentThemeDark) { - return [UIImage imageNamed:@"rooms_empty_screen_artwork_dark"]; + return AssetImages.roomsEmptyScreenArtworkDark.image; } else { - return [UIImage imageNamed:@"rooms_empty_screen_artwork"]; + return AssetImages.roomsEmptyScreenArtwork.image; } } diff --git a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m index 42920094f..ab7edff15 100644 --- a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m +++ b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m @@ -383,12 +383,12 @@ enum { if (deviceInfo.trustLevel.isVerified) { cell.textLabel.text = [VectorL10n manageSessionTrusted]; - cell.imageView.image = [UIImage imageNamed:@"encryption_trusted"]; + cell.imageView.image = AssetImages.encryptionTrusted.image; } else { cell.textLabel.text = [VectorL10n manageSessionNotTrusted]; - cell.imageView.image = [UIImage imageNamed:@"encryption_warning"]; + cell.imageView.image = AssetImages.encryptionWarning.image; } return cell; diff --git a/Riot/Modules/Settings/Security/SecurityViewController.m b/Riot/Modules/Settings/Security/SecurityViewController.m index 99b7f7c93..7082ba3bf 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.m +++ b/Riot/Modules/Settings/Security/SecurityViewController.m @@ -1097,19 +1097,19 @@ TableViewSectionsDelegate> { if ([deviceId isEqualToString:self.mainSession.myDeviceId]) { - return [UIImage imageNamed:@"encryption_warning"]; + return AssetImages.encryptionWarning.image; } else { - return [UIImage imageNamed:@"encryption_normal"]; + return AssetImages.encryptionNormal.image; } } - UIImage* shieldImageForDevice = [UIImage imageNamed:@"encryption_warning"]; + UIImage* shieldImageForDevice = AssetImages.encryptionWarning.image; MXDeviceInfo *device = [self.mainSession.crypto deviceWithDeviceId:deviceId ofUser:self.mainSession.myUser.userId]; if (device.trustLevel.isVerified) { - shieldImageForDevice = [UIImage imageNamed:@"encryption_trusted"]; + shieldImageForDevice = AssetImages.encryptionTrusted.image; } return shieldImageForDevice; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index c9c738f66..04eaa5519 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -1838,7 +1838,7 @@ TableViewSectionsDelegate> newEmailCell.mxkLabel.text = [VectorL10n settingsAddEmailAddress]; newEmailCell.mxkTextField.text = nil; newEmailCell.mxkTextField.userInteractionEnabled = NO; - newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; + newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:[AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; } else { @@ -1873,7 +1873,7 @@ TableViewSectionsDelegate> newEmailTextField = newEmailCell.mxkTextField; } - UIImage *accessoryViewImage = [[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.tintColor]; + UIImage *accessoryViewImage = [AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.tintColor]; newEmailCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; } @@ -1891,7 +1891,7 @@ TableViewSectionsDelegate> newPhoneCell.mxkLabel.text = [VectorL10n settingsAddPhoneNumber]; newPhoneCell.mxkTextField.text = nil; newPhoneCell.mxkTextField.userInteractionEnabled = NO; - newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:[[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; + newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:[AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]]; cell = newPhoneCell; } @@ -1953,7 +1953,7 @@ TableViewSectionsDelegate> newPhoneNumberCell = newPhoneCell; } - UIImage *accessoryViewImage = [[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.tintColor]; + UIImage *accessoryViewImage = [AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.tintColor]; newPhoneCell.accessoryView = [[UIImageView alloc] initWithImage:accessoryViewImage]; cell = newPhoneCell; diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 4f2d71dc1..9d8da5e52 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -105,7 +105,7 @@ dataSource.forceMatrixIdInDisplayName = YES; // Add a plus icon to the contact cell when a search session is in progress, // in order to make it more understandable for the end user. - dataSource.contactCellAccessoryImage = [[UIImage imageNamed:@"plus_icon"] vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]; + dataSource.contactCellAccessoryImage = [AssetImages.plusIcon.image vc_tintedImageUsingColor:ThemeService.shared.theme.textPrimaryColor]; [self displayList:dataSource]; diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 7fde39ca4..d2f3a045c 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -55,7 +55,7 @@ case MXDeviceUnknown: case MXDeviceUnverified: { - self.deviceStatus.image = [UIImage imageNamed:@"e2e_warning"]; + self.deviceStatus.image = AssetImages.e2eWarning.image; [_verifyButton setTitle:[MatrixKitL10n roomEventEncryptionInfoVerify] forState:UIControlStateNormal]; [_verifyButton setTitle:[MatrixKitL10n roomEventEncryptionInfoVerify] forState:UIControlStateHighlighted]; @@ -65,7 +65,7 @@ } case MXDeviceVerified: { - self.deviceStatus.image = [UIImage imageNamed:@"e2e_verified"]; + self.deviceStatus.image = AssetSharedImages.e2eVerified.image; [_verifyButton setTitle:[MatrixKitL10n roomEventEncryptionInfoUnverify] forState:UIControlStateNormal]; [_verifyButton setTitle:[MatrixKitL10n roomEventEncryptionInfoUnverify] forState:UIControlStateHighlighted]; @@ -76,7 +76,7 @@ } case MXDeviceBlocked: { - self.deviceStatus.image = [UIImage imageNamed:@"e2e_blocked"]; + self.deviceStatus.image = AssetImages.e2eBlocked.image; [_verifyButton setTitle:[MatrixKitL10n roomEventEncryptionInfoVerify] forState:UIControlStateNormal]; [_verifyButton setTitle:[MatrixKitL10n roomEventEncryptionInfoVerify] forState:UIControlStateHighlighted]; diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 32c0eaf1f..88c504bf0 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -82,7 +82,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm"; CGSize imageSize = CGSizeMake(20, 20); NSTextAttachment *attachment = [[NSTextAttachment alloc] init]; - attachment.image = [[[UIImage imageNamed:@"room_context_menu_delete"] vc_resizedWith:imageSize] vc_tintedImageUsingColor:color]; + attachment.image = [[AssetImages.roomContextMenuDelete.image vc_resizedWith:imageSize] vc_tintedImageUsingColor:color]; attachment.bounds = CGRectMake(0, font.descender, imageSize.width, imageSize.height); NSAttributedString *imageString = [NSAttributedString attributedStringWithAttachment:attachment]; diff --git a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m index d5f277193..b33952e20 100644 --- a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m +++ b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m @@ -56,8 +56,8 @@ self.contentView.backgroundColor = ThemeService.shared.theme.backgroundColor; self.selectionButton.tintColor = ThemeService.shared.theme.tintColor; - [self.selectionButton setImage:[UIImage imageNamed:@"radio-button-default"] forState:UIControlStateNormal]; - [self.selectionButton setImage:[UIImage imageNamed:@"radio-button-selected"] forState:UIControlStateSelected]; + [self.selectionButton setImage:AssetSharedImages.radioButtonDefault.image forState:UIControlStateNormal]; + [self.selectionButton setImage:AssetSharedImages.radioButtonSelected.image forState:UIControlStateSelected]; [self.selectionButton setTitle:@"" forState:UIControlStateNormal]; [self.selectionButton setTitle:@"" forState:UIControlStateSelected]; diff --git a/RiotShareExtension/target.yml b/RiotShareExtension/target.yml index 945d77d7a..b9c5b32fd 100644 --- a/RiotShareExtension/target.yml +++ b/RiotShareExtension/target.yml @@ -60,6 +60,7 @@ targets: - path: ../Riot/Modules/Common/Recents/Model/RecentCellData.m - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift - path: ../Riot/Generated/Strings.swift + - path: ../Riot/Generated/Images.swift - path: ../Riot/Managers/Locale/LocaleProviderType.swift - path: ../Riot/Managers/Locale/LocaleProvider.swift - path: ../Riot/Modules/Common/SegmentedViewController/SegmentedViewController.xib diff --git a/Tools/SwiftGen/Templates/Assets/swift4-element.stencil b/Tools/SwiftGen/Templates/Assets/swift4-element.stencil new file mode 100644 index 000000000..a614d8715 --- /dev/null +++ b/Tools/SwiftGen/Templates/Assets/swift4-element.stencil @@ -0,0 +1,337 @@ +// swiftlint:disable all +// Generated using SwiftGen — https://github.com/SwiftGen/SwiftGen + +{% if catalogs %} +{% set className %}{{param.className|default:"Asset"}}{% endset %} +{% set arResourceGroupType %}{{param.arResourceGroupTypeName|default:"ARResourceGroupAsset"}}{% endset %} +{% set colorType %}{{param.colorTypeName|default:"ColorAsset"}}{% endset %} +{% set dataType %}{{param.dataTypeName|default:"DataAsset"}}{% endset %} +{% set imageType %}{{param.imageTypeName|default:"ImageAsset"}}{% endset %} +{% set symbolType %}{{param.symbolTypeName|default:"SymbolAsset"}}{% endset %} +{% set forceNamespaces %}{{param.forceProvidesNamespaces|default:"false"}}{% endset %} +{% set accessModifier %}{% if param.publicAccess %}public{% else %}internal{% endif %}{% endset %} +#if os(macOS) + import AppKit +#elseif os(iOS) +{% if resourceCount.arresourcegroup > 0 %} + import ARKit +{% endif %} + import UIKit +#elseif os(tvOS) || os(watchOS) + import UIKit +#endif + +// Deprecated typealiases +{% if resourceCount.color > 0 %} +@available(*, deprecated, renamed: "{{colorType}}.Color", message: "This typealias will be removed in SwiftGen 7.0") +{{accessModifier}} typealias {{param.colorAliasName|default:"AssetColorTypeAlias"}} = {{colorType}}.Color +{% endif %} +{% if resourceCount.image > 0 %} +@available(*, deprecated, renamed: "{{imageType}}.Image", message: "This typealias will be removed in SwiftGen 7.0") +{{accessModifier}} typealias {{param.imageAliasName|default:"AssetImageTypeAlias"}} = {{imageType}}.Image +{% endif %} + +// swiftlint:disable superfluous_disable_command file_length implicit_return + +// MARK: - Asset Catalogs + +{% macro enumBlock assets %} + {% call casesBlock assets %} + {% if param.allValues %} + + // swiftlint:disable trailing_comma + {% if resourceCount.arresourcegroup > 0 %} + {{accessModifier}} static let allResourceGroups: [{{arResourceGroupType}}] = [ + {% filter indent:2 %}{% call allValuesBlock assets "arresourcegroup" "" %}{% endfilter %} + ] + {% endif %} + {% if resourceCount.color > 0 %} + {{accessModifier}} static let allColors: [{{colorType}}] = [ + {% filter indent:2 %}{% call allValuesBlock assets "color" "" %}{% endfilter %} + ] + {% endif %} + {% if resourceCount.data > 0 %} + {{accessModifier}} static let allDataAssets: [{{dataType}}] = [ + {% filter indent:2 %}{% call allValuesBlock assets "data" "" %}{% endfilter %} + ] + {% endif %} + {% if resourceCount.image > 0 %} + {{accessModifier}} static let allImages: [{{imageType}}] = [ + {% filter indent:2 %}{% call allValuesBlock assets "image" "" %}{% endfilter %} + ] + {% endif %} + {% if resourceCount.symbol > 0 %} + {{accessModifier}} static let allSymbols: [{{symbolType}}] = [ + {% filter indent:2 %}{% call allValuesBlock assets "symbol" "" %}{% endfilter %} + ] + {% endif %} + // swiftlint:enable trailing_comma + {% endif %} +{% endmacro %} +{% macro casesBlock assets %} + {% for asset in assets %} + {% if asset.type == "arresourcegroup" %} + {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{arResourceGroupType}}(name: "{{asset.value}}") + {% elif asset.type == "color" %} + {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{colorType}}(name: "{{asset.value}}") + {% elif asset.type == "data" %} + {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{dataType}}(name: "{{asset.value}}") + {% elif asset.type == "image" %} + {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{imageType}}(name: "{{asset.value}}") + {% elif asset.type == "symbol" %} + {{accessModifier}} static let {{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}} = {{symbolType}}(name: "{{asset.value}}") + {% elif asset.items and ( forceNamespaces == "true" or asset.isNamespaced == "true" ) %} + {{accessModifier}} enum {{asset.name|swiftIdentifier:"pretty"|escapeReservedKeywords}} { + {% filter indent:2 %}{% call casesBlock asset.items %}{% endfilter %} + } + {% elif asset.items %} + {% call casesBlock asset.items %} + {% endif %} + {% endfor %} +{% endmacro %} +{% macro allValuesBlock assets filter prefix %} + {% for asset in assets %} + {% if asset.type == filter %} + {{prefix}}{{asset.name|swiftIdentifier:"pretty"|lowerFirstWord|escapeReservedKeywords}}, + {% elif asset.items and ( forceNamespaces == "true" or asset.isNamespaced == "true" ) %} + {% set prefix2 %}{{prefix}}{{asset.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}.{% endset %} + {% call allValuesBlock asset.items filter prefix2 %} + {% elif asset.items %} + {% call allValuesBlock asset.items filter prefix %} + {% endif %} + {% endfor %} +{% endmacro %} +// swiftlint:disable identifier_name line_length nesting type_body_length type_name +@objcMembers +{{accessModifier}} class {{className}}: NSObject { + {% if catalogs.count > 1 or param.forceFileNameEnum %} + {% for catalog in catalogs %} + @objcMembers + @objc({{className}}{{catalog.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}) {{accessModifier}} class {{catalog.name|swiftIdentifier:"pretty"|escapeReservedKeywords}}: NSObject { + {% filter indent:2 %}{% call enumBlock catalog.assets %}{% endfilter %} + } + {% endfor %} + {% else %} + {% call enumBlock catalogs.first.assets %} + {% endif %} +} +// swiftlint:enable identifier_name line_length nesting type_body_length type_name + +// MARK: - Implementation Details +{% if resourceCount.arresourcegroup > 0 %} + +{{accessModifier}} struct {{arResourceGroupType}} { + {{accessModifier}} fileprivate(set) var name: String + + #if os(iOS) + @available(iOS 11.3, *) + {{accessModifier}} var referenceImages: Set { + return ARReferenceImage.referenceImages(in: self) + } + + @available(iOS 12.0, *) + {{accessModifier}} var referenceObjects: Set { + return ARReferenceObject.referenceObjects(in: self) + } + #endif +} + +#if os(iOS) +@available(iOS 11.3, *) +{{accessModifier}} extension ARReferenceImage { + static func referenceImages(in asset: {{arResourceGroupType}}) -> Set { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + return referenceImages(inGroupNamed: asset.name, bundle: bundle) ?? Set() + } +} + +@available(iOS 12.0, *) +{{accessModifier}} extension ARReferenceObject { + static func referenceObjects(in asset: {{arResourceGroupType}}) -> Set { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + return referenceObjects(inGroupNamed: asset.name, bundle: bundle) ?? Set() + } +} +#endif +{% endif %} +{% if resourceCount.color > 0 %} + +{{accessModifier}} final class {{colorType}} { + {{accessModifier}} fileprivate(set) var name: String + + #if os(macOS) + {{accessModifier}} typealias Color = NSColor + #elseif os(iOS) || os(tvOS) || os(watchOS) + {{accessModifier}} typealias Color = UIColor + #endif + + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) + {{accessModifier}} private(set) lazy var color: Color = Color(asset: self) + + #if os(iOS) || os(tvOS) + @available(iOS 11.0, tvOS 11.0, *) + {{accessModifier}} func color(compatibleWith traitCollection: UITraitCollection) -> Color { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + guard let color = Color(named: name, in: bundle, compatibleWith: traitCollection) else { + fatalError("Unable to load color asset named \(name).") + } + return color + } + #endif + + fileprivate init(name: String) { + self.name = name + } +} + +{{accessModifier}} extension {{colorType}}.Color { + @available(iOS 11.0, tvOS 11.0, watchOS 4.0, macOS 10.13, *) + convenience init!(asset: {{colorType}}) { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + #if os(iOS) || os(tvOS) + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSColor.Name(asset.name), bundle: bundle) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} +{% endif %} +{% if resourceCount.data > 0 %} + +{{accessModifier}} struct {{dataType}} { + {{accessModifier}} fileprivate(set) var name: String + + @available(iOS 9.0, tvOS 9.0, watchOS 6.0, macOS 10.11, *) + {{accessModifier}} var data: NSDataAsset { + return NSDataAsset(asset: self) + } +} + +@available(iOS 9.0, tvOS 9.0, watchOS 6.0, macOS 10.11, *) +{{accessModifier}} extension NSDataAsset { + convenience init!(asset: {{dataType}}) { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + #if os(iOS) || os(tvOS) || os(watchOS) + self.init(name: asset.name, bundle: bundle) + #elseif os(macOS) + self.init(name: NSDataAsset.Name(asset.name), bundle: bundle) + #endif + } +} +{% endif %} +{% if resourceCount.image > 0 %} + +@objcMembers +{{accessModifier}} class {{imageType}}: NSObject { + {{accessModifier}} fileprivate(set) var name: String + + #if os(macOS) + {{accessModifier}} typealias Image = NSImage + #elseif os(iOS) || os(tvOS) || os(watchOS) + {{accessModifier}} typealias Image = UIImage + #endif + + @available(iOS 8.0, tvOS 9.0, watchOS 2.0, macOS 10.7, *) + {{accessModifier}} var image: Image { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + #if os(iOS) || os(tvOS) + let image = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + let name = NSImage.Name(self.name) + let image = (bundle == .main) ? NSImage(named: name) : bundle.image(forResource: name) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + + {{accessModifier}} init(name: String) { + self.name = name + } + + #if os(iOS) || os(tvOS) + @available(iOS 8.0, tvOS 9.0, *) + {{accessModifier}} func image(compatibleWith traitCollection: UITraitCollection) -> Image { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + guard let result = Image(named: name, in: bundle, compatibleWith: traitCollection) else { + fatalError("Unable to load image asset named \(name).") + } + return result + } + #endif +} + +{{accessModifier}} extension {{imageType}}.Image { + @available(iOS 8.0, tvOS 9.0, watchOS 2.0, *) + @available(macOS, deprecated, + message: "This initializer is unsafe on macOS, please use the {{imageType}}.image property") + convenience init!(asset: {{imageType}}) { + #if os(iOS) || os(tvOS) + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + self.init(named: asset.name, in: bundle, compatibleWith: nil) + #elseif os(macOS) + self.init(named: NSImage.Name(asset.name)) + #elseif os(watchOS) + self.init(named: asset.name) + #endif + } +} +{% endif %} +{% if resourceCount.symbol > 0 %} + +{{accessModifier}} struct {{symbolType}} { + {{accessModifier}} fileprivate(set) var name: String + + #if os(iOS) || os(tvOS) || os(watchOS) + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, *) + {{accessModifier}} typealias Configuration = UIImage.SymbolConfiguration + {{accessModifier}} typealias Image = UIImage + + @available(iOS 12.0, tvOS 12.0, watchOS 5.0, *) + {{accessModifier}} var image: Image { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + #if os(iOS) || os(tvOS) + let image = Image(named: name, in: bundle, compatibleWith: nil) + #elseif os(watchOS) + let image = Image(named: name) + #endif + guard let result = image else { + fatalError("Unable to load symbol asset named \(name).") + } + return result + } + + @available(iOS 13.0, tvOS 13.0, watchOS 6.0, *) + {{accessModifier}} func image(with configuration: Configuration) -> Image { + let bundle = {{param.bundle|default:"BundleToken.bundle"}} + guard let result = Image(named: name, in: bundle, with: configuration) else { + fatalError("Unable to load symbol asset named \(name).") + } + return result + } + #endif +} +{% endif %} +{% if not param.bundle %} + +// swiftlint:disable convenience_type +private final class BundleToken { + static let bundle: Bundle = { + #if SWIFT_PACKAGE + return Bundle.module + #else + return Bundle(for: BundleToken.self) + #endif + }() +} +// swiftlint:enable convenience_type +{% endif %} +{% else %} +// No assets found +{% endif %} + diff --git a/Tools/SwiftGen/swiftgen-config.yml b/Tools/SwiftGen/swiftgen-config.yml index 3d1cd6693..a561f43ae 100755 --- a/Tools/SwiftGen/swiftgen-config.yml +++ b/Tools/SwiftGen/swiftgen-config.yml @@ -28,7 +28,7 @@ xcassets: - Assets/Images.xcassets - Assets/SharedImages.xcassets outputs: - templateName: swift4 + templatePath: Templates/Assets/swift4-element.stencil output: Images.swift plist: inputs: Assets/Riot-Defaults.plist diff --git a/changelog.d/pr-5533.misc b/changelog.d/pr-5533.misc new file mode 100644 index 000000000..6ba114e65 --- /dev/null +++ b/changelog.d/pr-5533.misc @@ -0,0 +1 @@ +SwiftGen: Objective-C support for assets helpers From 6846189a7c4ed616a58a161b067b9fab8d284c24 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 11 Feb 2022 13:10:33 +0200 Subject: [PATCH 028/188] vector-im/element-ios/issues/5114 - Added support for unstable poll prefixes. --- .../Coordinator/PollEditFormCoordinator.swift | 10 ++++++---- changelog.d/5114.change | 1 + 2 files changed, 7 insertions(+), 4 deletions(-) create mode 100644 changelog.d/5114.change diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift index 2878648c8..a3fa803e2 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift @@ -146,15 +146,17 @@ final class PollEditFormCoordinator: Coordinator, Presentable { } private static func pollDetailsTypeToKindKey(_ type: EditFormPollType) -> String { - let mapping = [EditFormPollType.disclosed : kMXMessageContentKeyExtensiblePollKindDisclosed, - EditFormPollType.undisclosed : kMXMessageContentKeyExtensiblePollKindUndisclosed] + let mapping = [EditFormPollType.disclosed : kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381, + EditFormPollType.undisclosed : kMXMessageContentKeyExtensiblePollKindUndisclosedMSC3381] - return mapping[type] ?? kMXMessageContentKeyExtensiblePollKindDisclosed + return mapping[type] ?? kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381 } private static func pollKindKeyToDetailsType(_ key: String) -> EditFormPollType { let mapping = [kMXMessageContentKeyExtensiblePollKindDisclosed : EditFormPollType.disclosed, - kMXMessageContentKeyExtensiblePollKindUndisclosed : EditFormPollType.undisclosed] + kMXMessageContentKeyExtensiblePollKindDisclosedMSC3381 : EditFormPollType.disclosed, + kMXMessageContentKeyExtensiblePollKindUndisclosed : EditFormPollType.undisclosed, + kMXMessageContentKeyExtensiblePollKindUndisclosedMSC3381 : EditFormPollType.undisclosed] return mapping[key] ?? EditFormPollType.disclosed } diff --git a/changelog.d/5114.change b/changelog.d/5114.change new file mode 100644 index 000000000..694524c66 --- /dev/null +++ b/changelog.d/5114.change @@ -0,0 +1 @@ +Added support for unstable poll prefixes. \ No newline at end of file From a90d8e287dd6d779d9c3e43f9efaa969f20ad7d7 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Tue, 8 Feb 2022 14:04:00 +0000 Subject: [PATCH 029/188] Exclude all items from iCloud backup Signed-off-by: Andy Uhnak --- .../URLPreviews/Core Data/URLPreviewStore.swift | 8 ++++++++ Riot/Modules/Application/AppCoordinator.swift | 13 +++++++++++++ .../MatrixKit/Models/Contact/MXKContactManager.m | 4 ++++ Riot/Modules/MatrixKit/Models/MXKAppSettings.m | 10 +++++----- changelog.d/5498.change | 1 + 5 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 changelog.d/5498.change diff --git a/Riot/Managers/URLPreviews/Core Data/URLPreviewStore.swift b/Riot/Managers/URLPreviews/Core Data/URLPreviewStore.swift index da955da40..ecd152fa2 100644 --- a/Riot/Managers/URLPreviews/Core Data/URLPreviewStore.swift +++ b/Riot/Managers/URLPreviews/Core Data/URLPreviewStore.swift @@ -61,6 +61,14 @@ class URLPreviewStore { if let error = error { MXLog.error("[URLPreviewStore] Core Data container error: \(error.localizedDescription)") } + + if let url = storeDescription.url { + do { + try FileManager.default.excludeItemFromBackup(at: url) + } catch { + MXLog.error("[URLPreviewStore] Cannot exclude Core Data from backup: \(error.localizedDescription)") + } + } } } diff --git a/Riot/Modules/Application/AppCoordinator.swift b/Riot/Modules/Application/AppCoordinator.swift index d60faf924..03cdc9d6e 100755 --- a/Riot/Modules/Application/AppCoordinator.swift +++ b/Riot/Modules/Application/AppCoordinator.swift @@ -16,6 +16,7 @@ import Foundation import Intents +import MatrixSDK #if DEBUG import FLEX @@ -79,6 +80,7 @@ final class AppCoordinator: NSObject, AppCoordinatorType { func start() { self.setupLogger() self.setupTheme() + self.excludeAllItemsFromBackup() // Setup navigation router store _ = NavigationRouterStore.shared @@ -129,6 +131,17 @@ final class AppCoordinator: NSObject, AppCoordinatorType { } } + private func excludeAllItemsFromBackup() { + let manager = FileManager.default + + // Individual files and directories created by the application or SDK are excluded case-by-case, + // but sometimes the lifecycle of a file is not directly controlled by the app (e.g. plists for + // UserDefaults). For that reason the app will always exclude all top-level directories as well + // as individual files. + manager.excludeAllUserDirectoriesFromBackup() + manager.excludeAllAppGroupDirectoriesFromBackup() + } + private func showAuthentication() { // TODO: Implement } diff --git a/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m b/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m index 0ccf8096b..3226deef8 100644 --- a/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m +++ b/Riot/Modules/MatrixKit/Models/Contact/MXKContactManager.m @@ -1873,6 +1873,10 @@ static NSString *contactsBookInfoFile = @"contactsV2"; if (error == nil) { [cipher writeToFile:[self dataFilePathForComponent:fileName] atomically:YES]; + [[NSFileManager defaultManager] excludeItemFromBackupAt:[NSURL fileURLWithPath:fileName] error:&error]; + if (error) { + MXLogDebug(@"[MXKContactManager] Cannot exclude item from backup %@", error.localizedDescription); + } } else { diff --git a/Riot/Modules/MatrixKit/Models/MXKAppSettings.m b/Riot/Modules/MatrixKit/Models/MXKAppSettings.m index c0984a6da..b31fc0658 100644 --- a/Riot/Modules/MatrixKit/Models/MXKAppSettings.m +++ b/Riot/Modules/MatrixKit/Models/MXKAppSettings.m @@ -19,6 +19,7 @@ #import "MXKAppSettings.h" #import "MXKTools.h" +@import MatrixSDK; // get ISO country name @@ -66,11 +67,10 @@ static NSString *const kMXAppGroupID = @"group.org.matrix"; { NSString *cacheFolder; - // Check for a potential application group id - NSString *applicationGroupIdentifier = [MXSDKOptions sharedInstance].applicationGroupIdentifier; - if (applicationGroupIdentifier) + // Check for a potential application group container + NSURL *sharedContainerURL = [[NSFileManager defaultManager] applicationGroupContainerURL]; + if (sharedContainerURL) { - NSURL *sharedContainerURL = [[NSFileManager defaultManager] containerURLForSecurityApplicationGroupIdentifier:applicationGroupIdentifier]; cacheFolder = [sharedContainerURL path]; } else @@ -86,7 +86,7 @@ static NSString *const kMXAppGroupID = @"group.org.matrix"; if (cacheFolder && ![[NSFileManager defaultManager] fileExistsAtPath:cacheFolder]) { NSError *error; - [[NSFileManager defaultManager] createDirectoryAtPath:cacheFolder withIntermediateDirectories:YES attributes:nil error:&error]; + [[NSFileManager defaultManager] createDirectoryExcludedFromBackupAtPath:cacheFolder error:&error]; if (error) { MXLogDebug(@"[MXKAppSettings] cacheFolder: Error: Cannot create MatrixKit folder at %@. Error: %@", cacheFolder, error); diff --git a/changelog.d/5498.change b/changelog.d/5498.change new file mode 100644 index 000000000..091816db7 --- /dev/null +++ b/changelog.d/5498.change @@ -0,0 +1 @@ +Exclude all files and directories from iCloud and iTunes backup From f05fb9f3e51b8dd4ecd72834155869dda1eb8834 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 11 Feb 2022 12:29:06 +0000 Subject: [PATCH 030/188] Fix for the green spinner not being dismissed with a local synapse. --- Riot/Modules/Application/LegacyAppDelegate.m | 59 ++++++++++++-------- changelog.d/5559.bugfix | 1 + 2 files changed, 36 insertions(+), 24 deletions(-) create mode 100644 changelog.d/5559.bugfix diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 6fe61c3b1..4201330fd 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -232,6 +232,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni */ @property (nonatomic, assign, getter=isRoomListDataReady) BOOL roomListDataReady; +/** + An optional completion block that will be called when a `RecentsViewControllerDataReadyNotification` + is observed during app launch. + */ +@property (nonatomic, copy, nullable) void (^roomListDataReadyCompletion)(void); + /** Flag to indicate whether a cache clear is being performed. */ @@ -417,6 +423,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } [NSBundle mxk_setLanguage:language]; [NSBundle mxk_setFallbackLanguage:@"en"]; + + [self listenForRoomListDataReady]; mxSessionArray = [NSMutableArray array]; callEventsListeners = [NSMutableDictionary dictionary]; @@ -2411,7 +2419,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni return; } - [self ensureRoomListDataReadyWithCompletion:^{ + void (^finishAppLaunch)(void) = ^{ [self hideLaunchAnimation]; if (self.setPinCoordinatorBridgePresenter) @@ -2443,7 +2451,17 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni // Enable listening of incoming key verification requests [self enableIncomingKeyVerificationObserver:mainSession]; } - }]; + }; + + if (self.isRoomListDataReady) + { + finishAppLaunch(); + } + else + { + // An observer has been set in didFinishLaunching that will call the stored block when ready + self.roomListDataReadyCompletion = finishAppLaunch; + } } } @@ -2599,29 +2617,22 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni [self handleAppState]; } -/** - Ensures room list data is ready. - - @param completion Completion block to be called when it's ready. Not dispatched in case the data is already ready. - */ -- (void)ensureRoomListDataReadyWithCompletion:(void(^)(void))completion +- (void)listenForRoomListDataReady { - if (self.isRoomListDataReady) - { - completion(); - } - else - { - NSNotificationCenter * __weak notificationCenter = [NSNotificationCenter defaultCenter]; - __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:RecentsViewControllerDataReadyNotification - object:nil - queue:[NSOperationQueue mainQueue] - usingBlock:^(NSNotification * _Nonnull notification) { - [notificationCenter removeObserver:observer]; - self.roomListDataReady = YES; - completion(); - }]; - } + NSNotificationCenter * __weak notificationCenter = [NSNotificationCenter defaultCenter]; + __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:RecentsViewControllerDataReadyNotification + object:nil + queue:[NSOperationQueue mainQueue] + usingBlock:^(NSNotification * _Nonnull notification) { + [notificationCenter removeObserver:observer]; + self.roomListDataReady = YES; + + if (self.roomListDataReadyCompletion) + { + self.roomListDataReadyCompletion(); + self.roomListDataReadyCompletion = nil; + } + }]; } #pragma mark - diff --git a/changelog.d/5559.bugfix b/changelog.d/5559.bugfix new file mode 100644 index 000000000..7f27180a0 --- /dev/null +++ b/changelog.d/5559.bugfix @@ -0,0 +1 @@ +App Launch: Fix a potential issue where the green spinner is kept on screen when the room lists are ready. \ No newline at end of file From ac0b219bb5cffde3e2c40f89bf2129eedb200182 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Fri, 11 Feb 2022 13:27:51 +0200 Subject: [PATCH 031/188] Fix introspect not being able to theme the SwiftUI navigation bars. --- .../Room/LocationSharing/View/LocationSharingView.swift | 6 +++--- .../Modules/Room/PollEditForm/View/PollEditForm.swift | 6 +++--- changelog.d/pr-5556.misc | 1 + 3 files changed, 7 insertions(+), 6 deletions(-) create mode 100644 changelog.d/pr-5556.misc diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift index ca13a80f9..0d40d14d9 100644 --- a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift +++ b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift @@ -66,6 +66,9 @@ struct LocationSharingView: View { } } .navigationBarTitleDisplayMode(.inline) + .introspectNavigationController { navigationController in + ThemeService.shared().theme.applyStyle(onNavigationBar: navigationController.navigationBar) + } .ignoresSafeArea() .alert(item: $context.alertInfo) { info in if let secondaryButton = info.secondaryButton { @@ -89,9 +92,6 @@ struct LocationSharingView: View { .accentColor(theme.colors.accent) .activityIndicator(show: context.viewState.showLoadingIndicator) .navigationViewStyle(StackNavigationViewStyle()) - .introspectNavigationController { navigationController in - ThemeService.shared().theme.applyStyle(onNavigationBar: navigationController.navigationBar) - } } @ViewBuilder diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift index 21bf5b189..7ea906593 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift @@ -116,14 +116,14 @@ struct PollEditForm: View { } } .navigationBarTitleDisplayMode(.inline) + .introspectNavigationController { navigationController in + ThemeService.shared().theme.applyStyle(onNavigationBar: navigationController.navigationBar) + } } } } .accentColor(theme.colors.accent) .navigationViewStyle(StackNavigationViewStyle()) - .introspectNavigationController { navigationController in - ThemeService.shared().theme.applyStyle(onNavigationBar: navigationController.navigationBar) - } } } diff --git a/changelog.d/pr-5556.misc b/changelog.d/pr-5556.misc new file mode 100644 index 000000000..83d944af7 --- /dev/null +++ b/changelog.d/pr-5556.misc @@ -0,0 +1 @@ +Fix introspect not being able to theme the SwiftUI navigation bars. \ No newline at end of file From 590e5cf4f1dc7db7367af995cec83028f0328504 Mon Sep 17 00:00:00 2001 From: MaximeE Date: Fri, 11 Feb 2022 14:25:20 +0100 Subject: [PATCH 032/188] Replace kick by remove in all strings --- Riot/Assets/en.lproj/Vector.strings | 2 +- Riot/Generated/MatrixKitStrings.swift | 6 +++--- Riot/Generated/Strings.swift | 2 +- .../MatrixKitAssets.bundle/en.lproj/MatrixKit.strings | 6 +++--- .../MatrixKit/Utils/EventFormatter/MXKEventFormatter.m | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 0614860bb..76c063e06 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -396,7 +396,7 @@ Tap the + to start adding people."; "room_event_action_view_decrypted_source" = "View Decrypted Source"; "room_event_action_report" = "Report content"; "room_event_action_report_prompt_reason" = "Reason for reporting this content"; -"room_event_action_kick_prompt_reason" = "Reason for kicking this user"; +"room_event_action_kick_prompt_reason" = "Reason for removing this user"; "room_event_action_ban_prompt_reason" = "Reason for banning this user"; "room_event_action_report_prompt_ignore_user" = "Do you want to hide all messages from this user?"; "room_event_action_save" = "Save"; diff --git a/Riot/Generated/MatrixKitStrings.swift b/Riot/Generated/MatrixKitStrings.swift index b178f6d8d..f59c7d116 100644 --- a/Riot/Generated/MatrixKitStrings.swift +++ b/Riot/Generated/MatrixKitStrings.swift @@ -467,7 +467,7 @@ public class MatrixKitL10n: NSObject { public static var inviteUser: String { return MatrixKitL10n.tr("invite_user") } - /// Kick + /// Remove from chat public static var kick: String { return MatrixKitL10n.tr("kick") } @@ -1059,11 +1059,11 @@ public class MatrixKitL10n: NSObject { public static func noticeRoomJoinRulePublicForDm(_ p1: String) -> String { return MatrixKitL10n.tr("notice_room_join_rule_public_for_dm", p1) } - /// %@ kicked %@ + /// %@ removed %@ public static func noticeRoomKick(_ p1: String, _ p2: String) -> String { return MatrixKitL10n.tr("notice_room_kick", p1, p2) } - /// You kicked %@ + /// You removed %@ public static func noticeRoomKickByYou(_ p1: String) -> String { return MatrixKitL10n.tr("notice_room_kick_by_you", p1) } diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 7d781899c..2a13bd080 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -3259,7 +3259,7 @@ public class VectorL10n: NSObject { public static var roomEventActionForward: String { return VectorL10n.tr("Vector", "room_event_action_forward") } - /// Reason for kicking this user + /// Reason for removing this user public static var roomEventActionKickPromptReason: String { return VectorL10n.tr("Vector", "room_event_action_kick_prompt_reason") } diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings index b7937f194..1b6c229ac 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings @@ -367,7 +367,7 @@ "notice_room_join" = "%@ joined"; "notice_room_leave" = "%@ left"; "notice_room_reject" = "%@ rejected the invitation"; -"notice_room_kick" = "%@ kicked %@"; +"notice_room_kick" = "%@ removed %@"; "notice_room_unban" = "%@ unbanned %@"; "notice_room_ban" = "%@ banned %@"; "notice_room_withdraw" = "%@ withdrew %@'s invitation"; @@ -399,7 +399,7 @@ "notice_room_join_by_you" = "You joined"; "notice_room_leave_by_you" = "You left"; "notice_room_reject_by_you" = "You rejected the invitation"; -"notice_room_kick_by_you" = "You kicked %@"; +"notice_room_kick_by_you" = "You removed %@"; "notice_room_unban_by_you" = "You unbanned %@"; "notice_room_ban_by_you" = "You banned %@"; "notice_room_withdraw_by_you" = "You withdrew %@'s invitation"; @@ -479,7 +479,7 @@ "num_members_one" = "%@ user"; "num_members_other" = "%@ users"; "invite" = "Invite"; -"kick" = "Kick"; +"kick" = "Remove from chat"; "ban" = "Ban"; "unban" = "Un-ban"; "message_unsaved_changes" = "There are unsaved changes. Leaving will discard them."; diff --git a/Riot/Modules/MatrixKit/Utils/EventFormatter/MXKEventFormatter.m b/Riot/Modules/MatrixKit/Utils/EventFormatter/MXKEventFormatter.m index 94ee3fa09..adb2b45af 100644 --- a/Riot/Modules/MatrixKit/Utils/EventFormatter/MXKEventFormatter.m +++ b/Riot/Modules/MatrixKit/Utils/EventFormatter/MXKEventFormatter.m @@ -955,7 +955,7 @@ static NSString *const kHTMLATagRegexPattern = @"([^<]*)"; } if (event.content[@"kick"]) { - displayText = [NSString stringWithFormat:@"%@\n\u2022 kick: %@", displayText, event.content[@"kick"]]; + displayText = [NSString stringWithFormat:@"%@\n\u2022 remove: %@", displayText, event.content[@"kick"]]; } if (event.content[@"redact"]) { From 03bda186bcdc71800a0b0cff2c8aea3043f0dbcd Mon Sep 17 00:00:00 2001 From: MaximeE Date: Fri, 11 Feb 2022 14:32:28 +0100 Subject: [PATCH 033/188] Changelog --- changelog.d/5346.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5346.bugfix diff --git a/changelog.d/5346.bugfix b/changelog.d/5346.bugfix new file mode 100644 index 000000000..bd7103e6b --- /dev/null +++ b/changelog.d/5346.bugfix @@ -0,0 +1 @@ +Wordings: Replace "kick" and all affiliate word by "remove" \ No newline at end of file From c740a8110e0c2a717a4984b4eeb98624443eec88 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 11 Feb 2022 18:11:44 +0300 Subject: [PATCH 034/188] Use thread protocols where possible --- .../DataSources/HomeMessagesSearchDataSource.m | 5 +++-- .../Models/Room/MXKRoomBubbleComponent.h | 4 ++-- .../Models/Room/MXKRoomBubbleComponent.m | 15 ++++++++++++--- Riot/Modules/Room/DataSources/RoomDataSource.h | 2 +- Riot/Modules/Room/DataSources/RoomDataSource.m | 3 ++- Riot/Modules/Room/RoomViewController.m | 2 +- .../Search/DataSources/RoomSearchDataSource.m | 5 +++-- .../Views/Threads/Summary/ThreadSummaryView.swift | 10 ++++++---- 8 files changed, 30 insertions(+), 16 deletions(-) diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 14a736b36..b5d03cd4f 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -164,8 +164,9 @@ { if (cellData.hasThreadRoot) { - MXThread *thread = cellData.bubbleComponents.firstObject.thread; - ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; + id thread = cellData.bubbleComponents.firstObject.thread; + ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread + session:self.mxSession]; [bubbleCell.tmpSubviews addObject:threadSummaryView]; threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.h b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.h index b778785e6..6ec53437e 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.h +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.h @@ -19,7 +19,7 @@ #import "MXKEventFormatter.h" #import "MXKURLPreviewDataProtocol.h" -@class MXThread; +@protocol MXThreadProtocol; /** Flags to indicate if a fix is required at the display time. @@ -108,7 +108,7 @@ typedef enum : NSUInteger { /** Thread for the bubble component. Should only exist for thread root events. */ -@property (nonatomic, readonly) MXThread *thread; +@property (nonatomic, readonly) id thread; /** Create a new `MXKRoomBubbleComponent` object based on a `MXEvent` instance. diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m index 9a244040e..25560044b 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomBubbleComponent.m @@ -22,7 +22,7 @@ @interface MXKRoomBubbleComponent () -@property (nonatomic, readwrite) MXThread *thread; +@property (nonatomic, readwrite) id thread; @end @@ -69,8 +69,17 @@ _showEncryptionBadge = [self shouldShowWarningBadgeForEvent:event roomState:(MXRoomState*)roomState session:session]; [self updateLinkWithRoomState:roomState]; - - self.thread = [session.threadingService threadWithId:event.eventId]; + + if (event.unsignedData.relations.thread) + { + self.thread = [[MXThreadModel alloc] initWithRootEvent:event + notificationCount:0 + highlightCount:0]; + } + else + { + self.thread = [session.threadingService threadWithId:event.eventId]; + } } return self; } diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.h b/Riot/Modules/Room/DataSources/RoomDataSource.h index 76d55375e..1ce04fc08 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.h +++ b/Riot/Modules/Room/DataSources/RoomDataSource.h @@ -130,6 +130,6 @@ @param roomDataSource room data source instance */ - (void)roomDataSource:(RoomDataSource * _Nonnull)roomDataSource - didTapThread:(MXThread * _Nonnull)thread; + didTapThread:(id _Nonnull)thread; @end diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index f4561638f..82901062d 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -466,7 +466,8 @@ const CGFloat kTypingCellHeight = 24; // display thread summary view if the component has a thread in the room timeline if (RiotSettings.shared.enableThreads && component.thread && !self.threadId) { - threadSummaryView = [[ThreadSummaryView alloc] initWithThread:component.thread]; + threadSummaryView = [[ThreadSummaryView alloc] initWithThread:component.thread + session:self.mxSession]; threadSummaryView.delegate = self; threadSummaryView.tag = index; diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 1c0e72410..e8ea422ed 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4283,7 +4283,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [self updateTitleViewEncryptionDecoration]; } -- (void)roomDataSource:(RoomDataSource *)roomDataSource didTapThread:(MXThread *)thread +- (void)roomDataSource:(RoomDataSource *)roomDataSource didTapThread:(id)thread { [self openThreadWithId:thread.id]; } diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 5b99eea2d..51e283d37 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -143,8 +143,9 @@ { if (cellData.hasThreadRoot) { - MXThread *thread = cellData.bubbleComponents.firstObject.thread; - ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread]; + id thread = cellData.bubbleComponents.firstObject.thread; + ThreadSummaryView *threadSummaryView = [[ThreadSummaryView alloc] initWithThread:thread + session:self.mxSession]; [bubbleCell.tmpSubviews addObject:threadSummaryView]; threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; diff --git a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift index c1da2d9dd..1a9799b27 100644 --- a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift +++ b/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift @@ -38,7 +38,8 @@ class ThreadSummaryView: UIView { @IBOutlet private weak var lastMessageContentLabel: UILabel! private var theme: Theme = ThemeService.shared().theme - private(set) var thread: MXThread? + private(set) var thread: MXThreadProtocol? + private weak var session: MXSession? private lazy var tapGestureRecognizer: UITapGestureRecognizer = { return UITapGestureRecognizer(target: self, action: #selector(tapped(_:))) @@ -48,8 +49,9 @@ class ThreadSummaryView: UIView { // MARK: - Setup - init(withThread thread: MXThread) { + init(withThread thread: MXThreadProtocol, session: MXSession) { self.thread = thread + self.session = session super.init(frame: CGRect(origin: .zero, size: CGSize(width: Constants.viewDefaultWidth, height: RoomBubbleCellLayout.threadSummaryViewHeight))) @@ -59,7 +61,7 @@ class ThreadSummaryView: UIView { translatesAutoresizingMaskIntoConstraints = false } - static func contentViewHeight(forThread thread: MXThread?, fitting maxWidth: CGFloat) -> CGFloat { + static func contentViewHeight(forThread thread: MXThreadProtocol?, fitting maxWidth: CGFloat) -> CGFloat { return RoomBubbleCellLayout.threadSummaryViewHeight } @@ -93,7 +95,7 @@ class ThreadSummaryView: UIView { guard let thread = thread, let lastMessage = thread.lastMessage, - let session = thread.session, + let session = session, let eventFormatter = session.roomSummaryUpdateDelegate as? MXKEventFormatter, let room = session.room(withRoomId: lastMessage.roomId) else { lastMessageAvatarView.avatarImageView.image = nil From 3a9a6d357fef7346460559dbd57f5588819ed6d5 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 11 Feb 2022 18:14:41 +0300 Subject: [PATCH 035/188] Use thread relation if exists when opening search results --- Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m | 2 +- .../GlobalSearch/Messages/HomeMessagesSearchViewController.m | 2 +- Riot/Modules/Room/Search/RoomSearchViewController.m | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 5ec57f136..d51cfaa64 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -160,7 +160,7 @@ threadParameters = [[ThreadParameters alloc] initWithThreadId:event.threadId stackRoomScreen:NO]; } - else if ([self.mainSession.threadingService isEventThreadRoot:event]) + else if (event.unsignedData.relations.thread || [self.mainSession.threadingService isEventThreadRoot:event]) { threadParameters = [[ThreadParameters alloc] initWithThreadId:event.eventId stackRoomScreen:NO]; diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index b8ba693be..8ba3d8241 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -167,7 +167,7 @@ threadParameters = [[ThreadParameters alloc] initWithThreadId:event.threadId stackRoomScreen:NO]; } - else if ([self.mainSession.threadingService isEventThreadRoot:event]) + else if (event.unsignedData.relations.thread || [self.mainSession.threadingService isEventThreadRoot:event]) { threadParameters = [[ThreadParameters alloc] initWithThreadId:event.eventId stackRoomScreen:NO]; diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index 8097ca2b0..214f3f497 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -165,7 +165,7 @@ threadParameters = [[ThreadParameters alloc] initWithThreadId:event.threadId stackRoomScreen:NO]; } - else if ([self.mainSession.threadingService isEventThreadRoot:event]) + else if (event.unsignedData.relations.thread || [self.mainSession.threadingService isEventThreadRoot:event]) { threadParameters = [[ThreadParameters alloc] initWithThreadId:event.eventId stackRoomScreen:NO]; From 7e46ee7e3f750f4739f85beae61940eedaf785b3 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 11 Feb 2022 18:15:23 +0300 Subject: [PATCH 036/188] Avoid redundant live timeline loading if thread relation exists --- .../Messages/DataSources/HomeMessagesSearchDataSource.m | 4 ++++ Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index b5d03cd4f..b136c9af4 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -89,6 +89,10 @@ { continueBlock(); } + else if (result.result.unsignedData.relations.thread) + { + continueBlock(); + } else if (room) { [room liveTimeline:^(id liveTimeline) { diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 51e283d37..dd33c86cb 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -96,6 +96,10 @@ { continueBlock(); } + else if (result.result.unsignedData.relations.thread) + { + continueBlock(); + } else { [roomDataSource.room liveTimeline:^(id liveTimeline) { From 00b2734f48d36af08823e7ede7069792e23d747e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 11 Feb 2022 18:16:37 +0300 Subject: [PATCH 037/188] Add changelog --- changelog.d/5562.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5562.change diff --git a/changelog.d/5562.change b/changelog.d/5562.change new file mode 100644 index 000000000..729c93acc --- /dev/null +++ b/changelog.d/5562.change @@ -0,0 +1 @@ +Search: Use bundled aggregations if provided. From af615ea6657d65e61b2a06117bea5daaae7974e8 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 11 Feb 2022 15:42:12 +0000 Subject: [PATCH 038/188] Fix spinner when clearing cache. --- Riot/Modules/Application/LegacyAppDelegate.m | 21 ++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 4201330fd..a85047c69 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -232,6 +232,11 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni */ @property (nonatomic, assign, getter=isRoomListDataReady) BOOL roomListDataReady; +/** + An observer token for `RecentsViewControllerDataReadyNotification`s notifications. + */ +@property (nonatomic, nullable) id roomListDataReadyObserver; + /** An optional completion block that will be called when a `RecentsViewControllerDataReadyNotification` is observed during app launch. @@ -423,8 +428,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni } [NSBundle mxk_setLanguage:language]; [NSBundle mxk_setFallbackLanguage:@"en"]; - - [self listenForRoomListDataReady]; mxSessionArray = [NSMutableArray array]; callEventsListeners = [NSMutableDictionary dictionary]; @@ -2382,6 +2385,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni case MXSessionStateInitialised: case MXSessionStateBackgroundSyncInProgress: self.roomListDataReady = NO; + [self listenForRoomListDataReady]; isLaunching = YES; break; case MXSessionStateStoreDataReady: @@ -2619,13 +2623,22 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni - (void)listenForRoomListDataReady { + if (self.roomListDataReadyObserver) + { + return; + } + + MXWeakify(self); NSNotificationCenter * __weak notificationCenter = [NSNotificationCenter defaultCenter]; - __block id observer = [[NSNotificationCenter defaultCenter] addObserverForName:RecentsViewControllerDataReadyNotification + self.roomListDataReadyObserver = [[NSNotificationCenter defaultCenter] addObserverForName:RecentsViewControllerDataReadyNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * _Nonnull notification) { - [notificationCenter removeObserver:observer]; + MXStrongifyAndReturnIfNil(self); + + [notificationCenter removeObserver:self.roomListDataReadyObserver]; self.roomListDataReady = YES; + self.roomListDataReadyObserver = nil; if (self.roomListDataReadyCompletion) { From 21e21cccc3208f15e3f20fc25c258f324d039eb7 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 11 Feb 2022 18:16:13 +0000 Subject: [PATCH 039/188] Fix for images sometimes being sent unencrypted inside an encrypted room. --- Riot/Modules/Room/MXKRoomViewController.h | 6 ++++++ Riot/Modules/Room/RoomViewController.m | 9 +++++++++ .../Room/Views/InputToolbar/RoomInputToolbarView.h | 7 +++++++ .../Room/Views/InputToolbar/RoomInputToolbarView.m | 1 + changelog.d/5564.bugfix | 1 + 5 files changed, 24 insertions(+) create mode 100644 changelog.d/5564.bugfix diff --git a/Riot/Modules/Room/MXKRoomViewController.h b/Riot/Modules/Room/MXKRoomViewController.h index 45ad325b5..6cdaab93a 100644 --- a/Riot/Modules/Room/MXKRoomViewController.h +++ b/Riot/Modules/Room/MXKRoomViewController.h @@ -444,4 +444,10 @@ typedef NS_ENUM(NSUInteger, MXKRoomViewControllerJoinRoomResult) { */ - (void)handleTypingNotification:(BOOL)typing; + +/** + Share encryption keys in this room. + */ +- (void)shareEncryptionKeys; + @end diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 1c0e72410..889271d50 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4564,6 +4564,15 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [self.userSuggestionCoordinator processTextMessage:toolbarView.textMessage]; } +- (void)roomInputToolbarViewDidOpenActionMenu:(MXKRoomInputToolbarView*)toolbarView +{ + // Consider opening the action menu as beginning to type and share encryption keys if requested. + if ([MXKAppSettings standardAppSettings].outboundGroupSessionKeyPreSharingStrategy == MXKKeyPreSharingWhenTyping) + { + [self shareEncryptionKeys]; + } +} + #pragma mark - MXKRoomMemberDetailsViewControllerDelegate - (void)roomMemberDetailsViewController:(MXKRoomMemberDetailsViewController *)roomMemberDetailsViewController startChatWithMemberId:(NSString *)matrixId completion:(void (^)(void))completion diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h index 282687128..e3feed12e 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h @@ -47,6 +47,13 @@ typedef enum : NSUInteger */ - (void)roomInputToolbarViewDidChangeTextMessage:(MXKRoomInputToolbarView*)toolbarView; +/** + Inform the delegate that the action menu was opened. + + @param toolbarView the room input toolbar view + */ +- (void)roomInputToolbarViewDidOpenActionMenu:(MXKRoomInputToolbarView*)toolbarView; + @end /** diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 63737645b..cc00383e4 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -429,6 +429,7 @@ static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3; if (_actionMenuOpened) { self.actionsBar.hidden = NO; [self.actionsBar animateWithShowIn:_actionMenuOpened completion:nil]; + [self.delegate roomInputToolbarViewDidOpenActionMenu:self]; } else { diff --git a/changelog.d/5564.bugfix b/changelog.d/5564.bugfix new file mode 100644 index 000000000..b9c450d48 --- /dev/null +++ b/changelog.d/5564.bugfix @@ -0,0 +1 @@ +Fix for images sometimes being sent unencrypted inside an encrypted room. \ No newline at end of file From e1db1620ee34c58d759cfd62d48275e947139e73 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 11 Feb 2022 18:17:39 +0000 Subject: [PATCH 040/188] Revert "Fix for images sometimes being sent unencrypted inside an encrypted room." This reverts commit 3491e0d7aa2782c3e8379c1b40644af5492e8f83. --- Riot/Modules/Room/MXKRoomViewController.h | 6 ------ Riot/Modules/Room/RoomViewController.m | 9 --------- .../Room/Views/InputToolbar/RoomInputToolbarView.h | 7 ------- .../Room/Views/InputToolbar/RoomInputToolbarView.m | 1 - changelog.d/5564.bugfix | 1 - 5 files changed, 24 deletions(-) delete mode 100644 changelog.d/5564.bugfix diff --git a/Riot/Modules/Room/MXKRoomViewController.h b/Riot/Modules/Room/MXKRoomViewController.h index 6cdaab93a..45ad325b5 100644 --- a/Riot/Modules/Room/MXKRoomViewController.h +++ b/Riot/Modules/Room/MXKRoomViewController.h @@ -444,10 +444,4 @@ typedef NS_ENUM(NSUInteger, MXKRoomViewControllerJoinRoomResult) { */ - (void)handleTypingNotification:(BOOL)typing; - -/** - Share encryption keys in this room. - */ -- (void)shareEncryptionKeys; - @end diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 889271d50..1c0e72410 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -4564,15 +4564,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [self.userSuggestionCoordinator processTextMessage:toolbarView.textMessage]; } -- (void)roomInputToolbarViewDidOpenActionMenu:(MXKRoomInputToolbarView*)toolbarView -{ - // Consider opening the action menu as beginning to type and share encryption keys if requested. - if ([MXKAppSettings standardAppSettings].outboundGroupSessionKeyPreSharingStrategy == MXKKeyPreSharingWhenTyping) - { - [self shareEncryptionKeys]; - } -} - #pragma mark - MXKRoomMemberDetailsViewControllerDelegate - (void)roomMemberDetailsViewController:(MXKRoomMemberDetailsViewController *)roomMemberDetailsViewController startChatWithMemberId:(NSString *)matrixId completion:(void (^)(void))completion diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h index e3feed12e..282687128 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h @@ -47,13 +47,6 @@ typedef enum : NSUInteger */ - (void)roomInputToolbarViewDidChangeTextMessage:(MXKRoomInputToolbarView*)toolbarView; -/** - Inform the delegate that the action menu was opened. - - @param toolbarView the room input toolbar view - */ -- (void)roomInputToolbarViewDidOpenActionMenu:(MXKRoomInputToolbarView*)toolbarView; - @end /** diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index cc00383e4..63737645b 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -429,7 +429,6 @@ static const NSTimeInterval kActionMenuComposerHeightAnimationDuration = .3; if (_actionMenuOpened) { self.actionsBar.hidden = NO; [self.actionsBar animateWithShowIn:_actionMenuOpened completion:nil]; - [self.delegate roomInputToolbarViewDidOpenActionMenu:self]; } else { diff --git a/changelog.d/5564.bugfix b/changelog.d/5564.bugfix deleted file mode 100644 index b9c450d48..000000000 --- a/changelog.d/5564.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix for images sometimes being sent unencrypted inside an encrypted room. \ No newline at end of file From d9a25e19ee1d973ae696811eeb64a11fb9de125e Mon Sep 17 00:00:00 2001 From: Thibault Martin Date: Fri, 11 Feb 2022 08:37:03 +0000 Subject: [PATCH 041/188] Translated using Weblate (French) Currently translated at 100.0% (49 of 49 strings) Translation: Element iOS/Element iOS (Push) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-push/fr/ --- Riot/Assets/fr.lproj/Localizable.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Riot/Assets/fr.lproj/Localizable.strings b/Riot/Assets/fr.lproj/Localizable.strings index 97b1481bb..84ef90f6f 100644 --- a/Riot/Assets/fr.lproj/Localizable.strings +++ b/Riot/Assets/fr.lproj/Localizable.strings @@ -116,3 +116,6 @@ /** General **/ "NOTIFICATION" = "Notification"; + +/* New file message from a specific person, not referencing a room. */ +"LOCATION_FROM_USER" = "%@ a partagé sa localisation"; From 1fd38b22572219230d37defe42d968ed33a8d465 Mon Sep 17 00:00:00 2001 From: Thibault Martin Date: Fri, 11 Feb 2022 08:36:48 +0000 Subject: [PATCH 042/188] Translated using Weblate (French) Currently translated at 100.0% (442 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/fr/ --- .../Assets/MatrixKitAssets.bundle/fr.lproj/MatrixKit.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/fr.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/fr.lproj/MatrixKit.strings index 03688dc76..380b96677 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/fr.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/fr.lproj/MatrixKit.strings @@ -478,3 +478,4 @@ "attachment_unsupported_preview_message" = "Ce type de fichier n’est pas pris en charge."; "attachment_unsupported_preview_title" = "Prévisualisation impossible"; "room_displayname_all_other_members_left" = "%@ (Quitté)"; +"message_reply_to_sender_sent_their_location" = "a partagé sa localisation."; From 76e749cdf603f96290ee2b153b9d8fb964a98247 Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 11 Feb 2022 19:44:37 +0000 Subject: [PATCH 043/188] Translated using Weblate (Swedish) Currently translated at 100.0% (442 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/sv/ --- .../Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings index ecadb738e..79192a6e2 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings @@ -74,7 +74,7 @@ "ignore" = "Ignorera"; "unignore" = "Avignorera"; // Events formatter -"notice_avatar_changed_too" = "(avataren ändrades också)"; +"notice_avatar_changed_too" = "(avataren byttes också)"; "notice_room_name_removed" = "%@ tog bort rumsnamnet"; "notice_room_topic_removed" = "%@ tog bort ämnet"; "notice_event_redacted" = ""; @@ -307,7 +307,7 @@ "notice_room_unban_by_you" = "Du avbannade %@"; "notice_room_ban_by_you" = "Du bannade %@"; "notice_room_withdraw_by_you" = "Du drog tillbaka inbjudan för %@"; -"notice_avatar_url_changed_by_you" = "Du ändrade din avatar"; +"notice_avatar_url_changed_by_you" = "Du bytte din avatar"; "notice_display_name_set_by_you" = "Du bytte ditt visningsnamn till %@"; "notice_display_name_changed_from_by_you" = "Du bytte ditt visningsnamn från %@ till %@"; "notice_display_name_removed_by_you" = "Du tog bort ditt visningsnamn"; From 395e98dd954b003c194aa25fcdfc53b736c1f63c Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sat, 12 Feb 2022 15:22:49 +0000 Subject: [PATCH 044/188] Translated using Weblate (Slovak) Currently translated at 98.4% (435 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/sk/ --- .../Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings index 7bd5de0d0..b34fe6b79 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings @@ -548,3 +548,6 @@ "account_linked_emails" = "Prepojené e-maily"; "room_event_encryption_info_event_fingerprint_key" = "Deklarovaný kľúč odtlačkov prstov Ed25519\n"; "notification_settings_notify_all_other" = "Oznámiť pre všetky ostatné správy/miestnosti"; +"call_transfer_to_user" = "Presmerovať na používateľa %@"; +"call_more_actions_transfer" = "Presmerovať"; +"login_use_fallback" = "Použiť náhradnú stránku"; From cdfa801bc7059f1c2143304ba7e35e1c399a795e Mon Sep 17 00:00:00 2001 From: aringenbach <80891108+aringenbach@users.noreply.github.com> Date: Mon, 14 Feb 2022 10:25:21 +0100 Subject: [PATCH 045/188] Update filter placeholder and icon (#5520) * Update filter placeholder and icon * Use SwiftGen asset helper & add filter_on icon Co-authored-by: Arnaud Ringenbach --- .../Common/filter_off.imageset/Contents.json | 23 ++++++++++++++++++ .../Common/filter_off.imageset/filter_off.png | Bin 0 -> 201 bytes .../filter_off.imageset/filter_off@2x.png | Bin 0 -> 297 bytes .../filter_off.imageset/filter_off@3x.png | Bin 0 -> 397 bytes .../Common/filter_on.imageset/Contents.json | 23 ++++++++++++++++++ .../Common/filter_on.imageset/filter_on.png | Bin 0 -> 204 bytes .../filter_on.imageset/filter_on@2x.png | Bin 0 -> 295 bytes .../filter_on.imageset/filter_on@3x.png | Bin 0 -> 377 bytes Riot/Assets/en.lproj/Vector.strings | 1 + Riot/Generated/Images.swift | 2 ++ Riot/Generated/Strings.swift | 4 +++ .../Common/Recents/RecentsViewController.m | 23 +++++++++++++++--- changelog.d/5250.change | 1 + 13 files changed, 74 insertions(+), 3 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Common/filter_off.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off.png create mode 100644 Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off@2x.png create mode 100644 Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off@3x.png create mode 100644 Riot/Assets/Images.xcassets/Common/filter_on.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on.png create mode 100644 Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on@2x.png create mode 100644 Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on@3x.png create mode 100644 changelog.d/5250.change diff --git a/Riot/Assets/Images.xcassets/Common/filter_off.imageset/Contents.json b/Riot/Assets/Images.xcassets/Common/filter_off.imageset/Contents.json new file mode 100644 index 000000000..0ada96c02 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Common/filter_off.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "filter_off.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "filter_off@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "filter_off@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off.png b/Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off.png new file mode 100644 index 0000000000000000000000000000000000000000..7f42aaf6d4c28a6b228f1d46052494fe88212da4 GIT binary patch literal 201 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-1!HlL zyA#8@b22Z19F}xPUq=Rpjs4tz5?O)#I8PVHkP61P7kBeE81S%M*sR_tDX1!{n&fsv z<$}Udk7+$VtM06R^y9LO!xYt0L*3hj^}HUM&-a~s9K149@qNGaT*37pbql0(eD8`L rF}xwt$#?6*-+=ofjz=qnx0W*+?UG>O7Io7A+Qi`L>gTe~DWM4f@#H^O literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off@2x.png b/Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..50b077fd2a18047157f6a592e7c9881e4f3c30fe GIT binary patch literal 297 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=+`2n>JlPzsH85kbaN0w}`kK0ys_t){QX;1lQmR|q- z(5`G(*Z$9bo8#*eX20*35#@WZi8bcm;iuEE6V8$7~()E#zO z-Yp%uGGwz;^rjsXA2CLWS%u#5_{kR<&E(61XFZU8By8jd1vpoyw69!LLKbLh*2~7aFBXx=Z literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off@3x.png b/Riot/Assets/Images.xcassets/Common/filter_off.imageset/filter_off@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..f03bf3c7b59ce77d1b33a6352c097e0b7706e12e GIT binary patch literal 397 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!oCO|{#S9FJ79h;%I?XTvD9BhG z{Oo0OJA0=~izKY2;Mr15~ z{((*FSc?}|aw3!AJ%{s-&RZHD7c|xCh&TM7!1;Sx&Hh)SlYPI5PTq5#2WTz`gskK1 zySGeO|JxNg{WbTm<^40Rt*;DgJ3nRN#guPXUny3B$eDv$tzo~`0Kh1l;a8v9h-=A}8_w?}s zt+ALg$67>GWn#do01tm&S5;4yDMlid>wk7l>X>D;B|mZb7VcGAogJFa6Sp;Ic_=Lb zIZwtn>s^P?Cy%Oq9bVO0E}fMsw(%~d-)HeZnRuo~(DmJo#hbago=!YcBY5>DU(hFx hpG+VRF)%pn&tcfQDcN>wM(xi{N>!uvNVKMcS1~i=qs^xh$@g4iRPP`jE^Bw2Z;i)z4*}Q$iB}y{<@T literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on@2x.png b/Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b9cff9c1be71b3df4428ae3507f9e3fc2bf9200e GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=l_SQb3}@T zyQ7>x^PpFbsw#`kY||$9^l7o1R3?3Q^qbr|^YUb%)@`ddvh6o06M z|M=;@Y>6}J$vNR0{v1!dwRCga!O9(NPxn7c@SVf_sPb2pZvF-DaK-~#rZfLv*Vz&s z;~lWBs!PC{xWt~$(696s#aCra# literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on@3x.png b/Riot/Assets/Images.xcassets/Common/filter_on.imageset/filter_on@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..5fec0029d0bcedf04bcd3c775960386c6dfe28dd GIT binary patch literal 377 zcmeAS@N?(olHy`uVBq!ia0vp^9w5xY1|&n@ZgvM!oCO|{#S9FJ79h;%I?XTvD9BhG z<_9J&ZiAUSd0U#p4$Y z90H0Hn1n7cera^^<`ArI;QFI4wQ*Zz{F8(y345a|=Su=j1A!HjtSok{5swQOHvYfW z&-;2x-JZW^mtERoWU?ctEbjJ^sw1zfO6AW@_br~vIj`Gz(>%{m)39etSbwFx; 0 ? AssetImages.filterOn.image : AssetImages.filterOff.image; + [self.recentsSearchBar setImage:filterIcon + forSearchBarIcon:UISearchBarIconSearch + state:UIControlStateNormal]; +} + #pragma mark - CreateRoomCoordinatorBridgePresenterDelegate - (void)createRoomCoordinatorBridgePresenterDelegate:(CreateRoomCoordinatorBridgePresenter *)coordinatorBridgePresenter didCreateNewRoom:(MXRoom *)room diff --git a/changelog.d/5250.change b/changelog.d/5250.change new file mode 100644 index 000000000..7c4d2e83f --- /dev/null +++ b/changelog.d/5250.change @@ -0,0 +1 @@ +Filter: update placeholder text and icon From 441a18310cbcb8099bc708ceda8652ff2ff66b82 Mon Sep 17 00:00:00 2001 From: noantiq Date: Sat, 12 Feb 2022 12:56:25 +0000 Subject: [PATCH 046/188] Translated using Weblate (German) Currently translated at 99.8% (1431 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 78 ++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 1c6bc5911..e058ec190 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -45,7 +45,7 @@ "auth_optional_phone_placeholder" = "Telefon-Nummer (optional)"; "auth_phone_placeholder" = "Telefon-Nummer"; "auth_repeat_password_placeholder" = "Wiederhole Passwort"; -"auth_repeat_new_password_placeholder" = "Bestätige dein neues Passwort"; +"auth_repeat_new_password_placeholder" = "Bestätige das neue Passwort für dein Matrix-Konto"; "auth_invalid_user_name" = "Nutzernamen dürfen nur Buchstaben, Nummern, Punkte, Binde- und Unterstriche enthalten"; "auth_invalid_password" = "Passwort zu kurz (min. 6 Zeichen)"; "auth_invalid_email" = "Dies sieht nicht nach eine validen E-Mail-Adresse aus"; @@ -56,7 +56,7 @@ "auth_missing_email_or_phone" = "Fehlende E-Mail-Adresse oder Telefon-Nummer"; "auth_password_dont_match" = "Passwörter stimmen nicht überein"; "auth_username_in_use" = "Benutzername bereits verwendet"; -"auth_forgot_password" = "Passwort vergessen?"; +"auth_forgot_password" = "Passwort des Matrix-Kontos vergessen?"; "auth_msisdn_validation_title" = "Verifizierung ausstehend"; "auth_msisdn_validation_message" = "Bitte gib unten den Aktivierungs-Code ein, den wir per SMS verschickt haben."; "auth_msisdn_validation_error" = "Telefonnummer kann nicht verifiziert werden."; @@ -137,7 +137,7 @@ "room_participants_action_invite" = "Einladen"; "room_participants_action_leave" = "Diesen Raum verlassen"; "room_participants_action_remove" = "Aus diesem Raum entfernen"; -"room_participants_action_ban" = "Aus diesem Raum bannen"; +"room_participants_action_ban" = "Aus diesem Raum verbannen"; "room_participants_action_ignore" = "Alle Nachrichten dieser Person verbergen"; "room_participants_action_unignore" = "Alle Nachrichten dieser Person zeigen"; "room_participants_action_set_moderator" = "Moderationsrechte vergeben"; @@ -166,7 +166,7 @@ "room_event_action_quote" = "Zitieren"; "room_event_action_more" = "Mehr"; "room_event_action_share" = "Teilen"; -"room_event_action_permalink" = "Permalink"; +"room_event_action_permalink" = "Link zur Nachricht kopieren"; "room_event_action_view_source" = "Zeige Quelltext"; "room_event_action_report" = "Inhalt melden"; "room_event_action_report_prompt_reason" = "Grund fürs Melden dieses Inhalts"; @@ -234,11 +234,11 @@ "settings_term_conditions" = "Geschäftsbedingungen"; "settings_privacy_policy" = "Datenschutzerklärung"; "settings_send_crash_report" = "Sende anonyme Absturz- und Nutzungsdaten"; -"settings_change_password" = "Passwort ändern"; +"settings_change_password" = "Passwort deines Matrix-Kontos ändern"; "settings_old_password" = "altes Passwort"; "settings_new_password" = "neues Passwort"; "settings_confirm_password" = "bestätige Passwort"; -"settings_password_updated" = "Dein Passwort wurde aktualisiert"; +"settings_password_updated" = "Das Passwort deines Matrix-Kontos wurde aktualisiert"; "settings_crypto_device_name" = "Öffentlicher Sitzungs-Name: "; "settings_crypto_device_key" = "\nSitzungs-Schlüssel:\n"; "settings_crypto_export" = "Schlüssel exportieren"; @@ -262,7 +262,7 @@ "room_details_no_local_addresses" = "Dieser Raum hat keine lokalen Adressen"; "room_details_new_address" = "Füge neue Adresse hinzu"; "room_details_new_address_placeholder" = "Füge neue Adresse hinzu (z.B. #foo%@)"; -"room_details_banned_users_section" = "Gebannte Nutzer"; +"room_details_banned_users_section" = "Verbannte Personen"; "room_details_advanced_section" = "Erweitert"; "room_details_advanced_room_id" = "Raum-ID:"; "room_details_advanced_enable_e2e_encryption" = "Aktivere Verschlüsselung (Warnung: Nicht deaktivierbar!)"; @@ -279,11 +279,11 @@ "auth_use_server_options" = "Individuelle Server-Optionen"; "auth_email_validation_message" = "Prüfe dein E-Mail-Konto um mit der Registrierung fortzufahren"; "auth_recaptcha_message" = "Dieser Heimserver will sicherstellen dass du kein Roboter bist"; -"auth_reset_password_message" = "E-Mail-Adresse angeben, um das Passwort zurückzusetzen:"; +"auth_reset_password_message" = "Um das Passwort deines Matrix-Kontos zurückzusetzen, gib die mit deinem Konto verbundene E-Mail-Adresse an:"; "auth_reset_password_missing_email" = "Die E-Mail-Adresse die mit dem Konto verbunden ist muss eingegeben werden."; "auth_reset_password_error_unauthorized" = "Konnte E-Mail-Adresse nicht verifizieren. Klicke den Link in der Registrierungs-E-Mail"; "auth_reset_password_error_not_found" = "Diese E-Mail-Adresse ist nicht mit einer Matrix-ID auf diesem Heimserver verknüpft."; -"auth_reset_password_success_message" = "Dein Passwort wurde zurückgesetzt.\n\nDu wurdest aus allen Sitzungen abgemeldet, diese bekommen jetzt keine Push-Benachrichtigungen mehr. Um diese wieder einzuschalten, melde dich auf den Geräten erneut an."; +"auth_reset_password_success_message" = "Das Passwort deines Matrix-Kontos wurde zurückgesetzt.\n\nDu wurdest aus allen Sitzungen abgemeldet und bekommst keine Push-Benachrichtigungen mehr. Um diese zu reaktivieren, melde dich jeweils auf allen Geräten erneut an."; "auth_add_email_and_phone_warning" = "Registrierung mit E-Mail und Telefonnummer zugleich ist noch nicht unterstützt. Nur die Telefonnummer wird berücksichtigt. Du kannst deine E-Mail-Adresse in deinem Profil ergänzen."; "room_creation_make_public_prompt_msg" = "Sicher, dass du diesen Raum öffentlich machen willst? Jeder kann deine Nachrichten lesen und dem Raum beitreten."; "room_creation_invite_another_user" = "Benutzer-ID, Name oder E-Mail"; @@ -320,7 +320,7 @@ "settings_labs_e2e_encryption_prompt_message" = "Zum Fertigstellen der Verschlüsselung bitte neu anmelden."; "settings_third_party_notices" = "Anmerkungen von Dritten"; "settings_clear_cache" = "Cache löschen"; -"settings_fail_to_update_password" = "Passwortänderung fehlgeschlagen"; +"settings_fail_to_update_password" = "Passwortänderung des Matrix-Kontos fehlgeschlagen"; "settings_crypto_device_id" = "\nSitzungs-ID: "; "settings_crypto_blacklist_unverified_devices" = "Verschlüssele nur zu verifizierten Sitzungen"; "room_details_people" = "Mitglieder"; @@ -505,7 +505,7 @@ "e2e_room_key_request_message_new_device" = "Du hast die neue Sitzung '%@' hinzugefügt, welche Verschlüsselungs-Schlüssel anfordert."; "room_do_not_have_permission_to_post" = "Du hast keine Berechtigung Nachrichten in diesem Raum zu senden"; "room_event_action_kick_prompt_reason" = "Grund für das Entfernen des Benutzers"; -"room_event_action_ban_prompt_reason" = "Grund für die Verbannung des Benutzers"; +"room_event_action_ban_prompt_reason" = "Grund für die Verbannung der Person"; "room_action_send_photo_or_video" = "Foto oder Video senden"; "room_action_send_sticker" = "Aufkleber senden"; "settings_deactivate_account" = "DEAKTIVIERTES KONTO"; @@ -526,7 +526,7 @@ "deactivate_account_forget_messages_information_part3" = ": Dies wird dafür sorgen, dass zukünftige Nutzer eine unvollständige Konversation sehen)"; "deactivate_account_validate_action" = "Konto deaktiveren"; "deactivate_account_password_alert_title" = "Konto deaktivieren"; -"deactivate_account_password_alert_message" = "Zum Fortfahren, Passwort eingeben"; +"deactivate_account_password_alert_message" = "Zum Fortfahren, gib bitte das Passwort deines Matrix-Kontos ein"; "event_formatter_rerequest_keys_part1_link" = "Verschlüsselungsschlüssel neu anfordern"; "event_formatter_rerequest_keys_part2" = " von deinen anderen Sitzungen anfragen."; // Re-request confirmation dialog @@ -585,7 +585,7 @@ "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 Sicherungsphrase"; -"key_backup_setup_passphrase_info" = "Wir speichern eine verschlüsselte Kopie deiner Schlüssel auf unserem Server. Schütze sie mit einer Passphrase, um sie sicher zu halten.\n\nFür maximale Sicherheit sollte sich dies von deinem Kontopasswort unterscheiden."; +"key_backup_setup_passphrase_info" = "Wir speichern eine verschlüsselte Kopie deiner Schlüssel auf unserem Server. Schütze sie mit einer Passphrase, um sie sicher zu halten.\n\nFür maximale Sicherheit sollte sich dies von dem Passwort deines Matrix-Kontos unterscheiden."; "key_backup_setup_passphrase_passphrase_title" = "Eingeben"; "key_backup_setup_passphrase_passphrase_placeholder" = "Sicherungsphrase eingeben"; "key_backup_setup_passphrase_passphrase_valid" = "Gut!"; @@ -801,7 +801,7 @@ "image_picker_action_library" = "Aus der Mediathek auswählen"; "camera_unavailable" = "Die Kamera ist auf deinem Gerät nicht verfügbar"; "photo_library_access_not_granted" = "%@ hat keine Berechtigung zum Zugriff auf die Fotobibliothek. Bitte ändere die Datenschutzeinstellungen"; -"auth_forgot_password_error_no_configured_identity_server" = "Es ist kein Identitätsserver konfiguriert: Füge einen hinzu, um dein Kennwort zurückzusetzen."; +"auth_forgot_password_error_no_configured_identity_server" = "Es ist kein Identitätsserver konfiguriert: Füge einen hinzu, um das Kennwort deines Matrix-Kontos zurückzusetzen."; "room_creation_error_invite_user_by_email_without_identity_server" = "Es ist kein Identitätsserver konfiguriert, sodass du keine Teilnehmenden mit einer E-Mail hinzufügen kannst."; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Es ist kein Identitätsserver konfiguriert, sodass du keinen Chat mit einem Kontakt über eine E-Mail starten kannst."; // Service terms @@ -810,9 +810,9 @@ "service_terms_modal_accept_button" = "Akzeptieren"; "service_terms_modal_description_for_identity_server" = "Für andere auffindbar sein"; "service_terms_modal_description_for_integration_manager" = "Bots, Brücken, Widgets und Aufkleberpakete verwenden"; -"auth_email_is_required" = "Es ist kein Identitätsserver konfiguriert, sodass du keine E-Mail-Adresse hinzufügen kannst, um dein Kennwort in Zukunft zurückzusetzen."; -"auth_phone_is_required" = "Es ist kein Identitätsserver konfiguriert, sodass du keine Telefonnummer hinzufügen kannst, um dein Kennwort in Zukunft zurückzusetzen."; -"auth_reset_password_error_is_required" = "Es ist kein Identitätsserver konfiguriert: Füge einen in die Serveroptionen ein, um dein Kennwort zurückzusetzen."; +"auth_email_is_required" = "Es ist kein Identitätsserver konfiguriert, sodass du keine E-Mail-Adresse hinzufügen kannst, um das Kennwort deines Matrix-Kontos in Zukunft zurückzusetzen."; +"auth_phone_is_required" = "Es ist kein Identitätsserver konfiguriert, sodass du keine Telefonnummer hinzufügen kannst, um das Kennwort deines Matrix-Kontos in Zukunft zurückzusetzen."; +"auth_reset_password_error_is_required" = "Es ist kein Identitätsserver konfiguriert: Füge einen in die Serveroptionen ein, um das Kennwort deines Matrix-Kontos zurückzusetzen."; // Errors "error_user_already_logged_in" = "Du versuchst anscheinend, eine Verbindung zu einem anderen Heimserver herzustellen. Möchtest du dich abmelden?"; "contacts_address_book_no_identity_server" = "Kein Identitätsserver konfiguriert"; @@ -888,7 +888,7 @@ "identity_server_settings_alert_disconnect_still_sharing_3pid" = "Du teilst noch deine persönlichen Daten mit dem Identitätsserver %@.\n\nWir empfehlen dir deine E-Mail-Adresse und Telefonnummer zu entfernen, bevor du die Verbindung zum Identitätsserver trennst."; "settings_add_3pid_password_title_email" = "E-Mail-Adresse hinzufügen"; "settings_add_3pid_password_title_msidsn" = "Telefonnummer hinzufügen"; -"settings_add_3pid_password_message" = "Um fortzufahren, bitte Passwort eingeben"; +"settings_add_3pid_password_message" = "Um fortzufahren, gib bitte das Passwort deines Matrix-Kontos ein"; "settings_add_3pid_invalid_password_message" = "Ungültige Anmeldedaten"; "identity_server_settings_disconnect_info" = "Eine Trennung vom Identitätsserver bedeutet, dass du weder von anderen Nutzer gefunden werden, noch diese dich per E-Mail oder Telefonnummer einladen können."; "error_not_supported_on_mobile" = "Dies ist in der Mobilvariante von %@ nicht möglich."; @@ -1012,7 +1012,7 @@ "security_settings_crosssigning_info_ok" = "Quersignierung ist bereit zur Anwendung."; "security_settings_crosssigning_reset" = "Zurücksetzen"; "security_settings_coming_soon" = "Entschuldigung, diese Funktion ist noch nicht für %@ iOS verfügbar. Bitte nutze einen anderen Matrix-Client, um es einzurichten. %@ iOS wird es benutzen."; -"security_settings_user_password_description" = "Bestätige deine Identität durch Eingabe des Kontopassworts"; +"security_settings_user_password_description" = "Bestätige deine Identität durch Eingabe des Passworts deines Matrix-Kontos"; // AuthenticatedSessionViewControllerFactory "authenticated_session_flow_not_supported" = "Diese App unterstützt nicht diese Authentifizierungsmethode für deinen Heimserver."; "secure_key_backup_setup_intro_title" = "Sichere Datensicherung"; @@ -1020,7 +1020,7 @@ "room_participants_action_security_status_complete_security" = "Vollständige Sicherheit"; "external_link_confirmation_title" = "Überprüfe diesen Link genau"; "external_link_confirmation_message" = "Der Link %@ bringt dich auf eine andere Seite: %@\n\nSicher, dass du fortfahren möchtest?"; -"security_settings_crypto_sessions_description_2" = "Wenn du dich nicht angemeldet hast, ändere dein Passwort und setze die Sichere Sicherheitskopie zurück."; +"security_settings_crypto_sessions_description_2" = "Wenn du dich nicht angemeldet hast, ändere das Passwort deines Matrix-Kontos und setze die Sichere Sicherheitskopie zurück."; "security_settings_secure_backup_description" = "Sichere die Schlüssel, um Datenverlust zu verhindern. Sie werden mit einem Sicherungsschlüssel gesichert."; "security_settings_crosssigning_info_exists" = "Dein Konto hat eine Quersignatur-Identität, aber dieser Sitzung wird noch nicht vertraut. Vervollständige die Sicherheit auf diese Sitzung."; "security_settings_crosssigning_info_trusted" = "Quersignierung ist aktiviert. Du kannst anderen Nutzern und deinen anderen Sitzungen basierend auf der Quersignatur vertrauen, aber du kannst in dieser Sitzung keine Quersignierung durchführen, da sie keine privaten Quersignatur-Schlüssel enthält. Vervollständige die Sicherheit dieser Sitzung."; @@ -1134,7 +1134,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Drucke ihn aus und bewahre ihn an einem sicheren Ort auf\n✓ Speichere ihn auf einem USB-Stick oder einem Sicherungslaufwerk\n✓ Kopiere ihn zu deinem persönlichen Speicher im Netz"; "secrets_setup_recovery_passphrase_title" = "Setze Sicherheitsphrase"; "secrets_setup_recovery_passphrase_information" = "Gib eine Sicherheitsphrase ein, welche nur du kennst und deine Daten auf dem Server geheim halten soll."; -"secrets_setup_recovery_passphrase_additional_information" = "Benutze dein Kontopasswort nicht mehrfach."; +"secrets_setup_recovery_passphrase_additional_information" = "Benutze nicht das Passwort deines Matrix-Kontos."; "secrets_setup_recovery_passphrase_validate_action" = "Fertig"; "secrets_setup_recovery_passphrase_confirm_information" = "Gib deine Sicherheitsphrase zur Bestätigung erneut ein."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Bestätigen"; @@ -1231,7 +1231,7 @@ "secrets_recovery_reset_action_part_1" = "Wiederherstellungsoptionen vergessen oder verloren? "; "less" = "Weniger"; -"secrets_reset_authentication_message" = "Gib dein Kontopasswort ein, um zu bestätigen"; +"secrets_reset_authentication_message" = "Gib zum Bestätigen das Passwort deines Matrix-Kontos ein"; "secrets_reset_reset_action" = "Zurücksetzen"; "secrets_reset_warning_message" = "Du wirst ohne Nachrichtenverlauf, Nachrichten, vertraute Geräte oder vertraute Benutzer neustarten."; "secrets_reset_warning_title" = "Falls du alles zurücksetzt"; @@ -1248,7 +1248,7 @@ // MARK: - Favourites -"favourites_empty_view_title" = "Lieblingsräume und -nutzer"; +"favourites_empty_view_title" = "Favorisierte Räume und Personen"; "favourites_empty_view_information" = "Um einen Lieblingschat hinzuzufügen, halte diesen gedrückt und wähle den Stern aus. Du findest deine Lieblingschats gesammelt hier."; "home_empty_view_information" = "Die sichere Chat-App für Teams, Freunde und Organisationen. Tippe unten auf das +, um Leute und Räume hinzuzufügen."; "rooms_empty_view_information" = "Noch keine Chat-Räume vorhanden. Tippe auf das +, um einem Raum beizutreten oder einen neuen zu erstellen."; @@ -1603,3 +1603,35 @@ "poll_edit_form_poll_type_open_description" = "Ergebnisse werden direkt nach Stimmabgabe angezeigt"; "poll_edit_form_poll_type_open" = "Offene Umfrage"; "poll_edit_form_update_failure_title" = "Aktualisierung der Umfrage fehlgeschlagen"; +"threads_empty_tip" = "Hinweis: Tippe auf eine Nachricht und wähle „Thread“ um einen neuen zu starten."; +"threads_empty_info_my" = "Antworte auf einen laufenden Thread oder tippe auf eine Nachricht und wähle „Thread“ um einen neuen zu starten."; +"home_context_menu_normal_priority" = "Normale Priorität"; +"home_context_menu_low_priority" = "Niedrige Priorität"; +"home_context_menu_unfavourite" = "Aus Favoriten entfernen"; +"home_context_menu_favourite" = "Favorisieren"; +"location_sharing_post_failure_subtitle" = "%@ konnte deinen Standort nicht versenden. Bitte versuche es später erneut."; +"location_sharing_post_failure_title" = "Wir konnten deinen Standort nicht versenden"; +"home_context_menu_leave" = "Verlassen"; +"home_context_menu_unmute" = "Stummschaltung aufheben"; +"home_context_menu_mute" = "Stummschalten"; +"home_context_menu_notifications" = "Benachrichtigungen"; +"home_context_menu_make_room" = "Zu Räume verschieben"; +"home_context_menu_make_dm" = "Zu Personen verschieben"; +"event_formatter_message_deleted" = "Nachricht gelöscht"; +"settings_labs_enable_threads" = "Threads"; +"message_from_a_thread" = "Aus einem Thread"; +"threads_empty_show_all_threads" = "Alle Threads anzeigen"; +"threads_empty_info_all" = "Threads helfen dabei, dass deine Konversationen beim Thema und leicht nachverfolgbar bleiben."; +"threads_empty_title" = "Organisiere Diskussionen mit Threads"; +"threads_action_my_threads" = "Meine Threads"; +"threads_action_all_threads" = "Alle Threads"; +"threads_title" = "Threads"; +"thread_copy_link_to_thread" = "Link in Thread kopieren"; + +// MARK: Threads +"room_thread_title" = "Thread"; +"room_accessibility_thread_more" = "Mehr"; +"room_accessibility_threads" = "Threads"; +"room_event_copy_link_info" = "Link in die Zwischenablage kopiert."; +"room_event_action_reply_in_thread" = "Thread"; +"room_event_action_view_in_room" = "Im Raum anzeigen"; From 79e997ddcfdcfd081c8967e299b56c17f13f8990 Mon Sep 17 00:00:00 2001 From: Thibault Martin Date: Fri, 11 Feb 2022 08:36:29 +0000 Subject: [PATCH 047/188] Translated using Weblate (French) Currently translated at 99.8% (1431 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/ --- Riot/Assets/fr.lproj/Vector.strings | 66 +++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index d30a43e9e..a26d64064 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -47,7 +47,7 @@ "auth_optional_phone_placeholder" = "Numéro de téléphone (facultatif)"; "auth_phone_placeholder" = "Numéro de téléphone"; "auth_repeat_password_placeholder" = "Répéter le mot de passe"; -"auth_repeat_new_password_placeholder" = "Confirmer le nouveau mot de passe"; +"auth_repeat_new_password_placeholder" = "Confirmer le nouveau mot de passe de votre compte Matrix"; "auth_invalid_login_param" = "Nom d’utilisateur et/ou mot de passe incorrect"; "auth_invalid_user_name" = "Les noms d’utilisateur ne peuvent contenir que des lettres, des chiffres, des points, des traits d’union ou des tirets bas"; "auth_invalid_password" = "Mot de passe trop court (min 6)"; @@ -70,14 +70,14 @@ "auth_msisdn_validation_message" = "Nous vous avons envoyé un SMS avec un code d’activation. Merci de le recopier ci-dessous."; "auth_msisdn_validation_error" = "Impossible de vérifier votre numéro de téléphone."; "auth_recaptcha_message" = "Ce serveur d’accueil voudrait s’assurer que vous n’êtes pas un robot"; -"auth_reset_password_message" = "Pour réinitialiser votre mot de passe, saisissez l’adresse e-mail liée à votre compte :"; +"auth_reset_password_message" = "Pour réinitialiser le mot de passe de votre compte Matrix, saisissez l’adresse e-mail liée à votre compte :"; "auth_reset_password_missing_email" = "Vous devez saisir l’adresse e-mail liée à votre compte."; "auth_reset_password_missing_password" = "Vous devez spécifier un nouveau mot de passe."; "auth_reset_password_email_validation_message" = "Un e-mail a été envoyé à %@. Cliquez d’abord sur le lien dans l’e-mail, puis ci-dessous."; "auth_reset_password_next_step_button" = "J’ai vérifié mon adresse e-mail"; "auth_reset_password_error_unauthorized" = "Impossible de vérifier l’adresse e-mail : assurez-vous de cliquer sur le lien dans l’e-mail"; "auth_reset_password_error_not_found" = "Votre adresse e-mail ne semble pas associée à un identifiant Matrix sur ce serveur d’accueil."; -"auth_reset_password_success_message" = "Votre mot de passe a été réinitialisé.\n\nVous avez été déconnecté de toutes vos sessions et ne recevrez plus de notifications. Pour réactiver les notifications, reconnectez-vous sur chaque appareil."; +"auth_reset_password_success_message" = "Le mot de passe de votre compte Matrix a été réinitialisé.\n\nVous avez été déconnecté de toutes vos sessions et ne recevrez plus de notifications. Pour réactiver les notifications, reconnectez-vous sur chaque appareil."; "auth_add_email_and_phone_warning" = "L’inscription avec un e-mail et un numéro de téléphone à la fois n’est pas prise en charge tant que l’API n'existe pas. Seul votre numéro de téléphone sera pris en compte. Vous pourrez ajouter l’adresse e-mail dans vos options de profil."; // Chat creation "room_creation_title" = "Nouvelle discussion"; @@ -206,7 +206,7 @@ "room_event_action_redact" = "Effacer"; "room_event_action_more" = "Plus"; "room_event_action_share" = "Partager"; -"room_event_action_permalink" = "Permalien"; +"room_event_action_permalink" = "Copier le lien vers le message"; "room_event_action_view_source" = "Voir la source"; "room_event_action_report" = "Signaler le contenu"; "room_event_action_report_prompt_reason" = "Raison pour le signalement du contenu"; @@ -292,12 +292,12 @@ "settings_send_crash_report" = "Envoyer des rapports d’anomalies anonymes et des statistiques d’utilisation"; "settings_enable_rageshake" = "Secouer l’appareil pour signaler un bug"; "settings_clear_cache" = "Vider le cache"; -"settings_change_password" = "Changer de mot de passe"; +"settings_change_password" = "Changer le mot de passe de votre compte Matrix"; "settings_old_password" = "ancien mot de passe"; "settings_new_password" = "nouveau mot de passe"; "settings_confirm_password" = "confirmer le mot de passe"; -"settings_fail_to_update_password" = "Échec de la modification du mot de passe"; -"settings_password_updated" = "Votre mot de passe a été modifié"; +"settings_fail_to_update_password" = "Échec de la modification du mot de passe du compte Matrix"; +"settings_password_updated" = "Le mot de passe de votre compte Matrix a été modifié"; "settings_crypto_device_name" = "Nom de la session : "; "settings_crypto_device_id" = "\nIdentifiant de la session : "; "settings_crypto_device_key" = "\nClé de la session :\n"; @@ -526,7 +526,7 @@ "deactivate_account_forget_messages_information_part3" = ": les futurs utilisateurs auront alors une vue incomplète des conversations)"; "deactivate_account_validate_action" = "Désactiver le compte"; "deactivate_account_password_alert_title" = "Désactiver le compte"; -"deactivate_account_password_alert_message" = "Pour continuer, veuillez renseigner votre mot de passe"; +"deactivate_account_password_alert_message" = "Pour continuer, veuillez renseigner le mot de passe de votre compte Matrix"; "event_formatter_rerequest_keys_part1_link" = "Redemander les clés de chiffrement"; "event_formatter_rerequest_keys_part2" = " depuis vos autres sessions."; // Re-request confirmation dialog @@ -584,7 +584,7 @@ "key_backup_setup_intro_title" = "Ne perdez jamais vos messages chiffrés"; "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" = "Nous conserverons une copie chiffrée de vos clés sur notre serveur. Protégez votre sauvegarde avec une phrase secrète pour qu’elle soit en sécurité.\n\nPour une sécurité maximale, elle devrait être différente du mot de passe de votre compte."; +"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 secrète pour qu’elle soit en sécurité.\n\nPour une sécurité maximale, elle devrait être différente du mot de passe de votre compte Matrix."; "key_backup_setup_passphrase_passphrase_title" = "Saisir"; "key_backup_setup_passphrase_passphrase_placeholder" = "Saisir la phrase secrète"; "key_backup_setup_passphrase_passphrase_valid" = "Super !"; @@ -816,7 +816,7 @@ "image_picker_action_library" = "Choisir dans la médiathèque"; "camera_unavailable" = "L’appareil photo n’est pas disponible sur votre appareil"; "photo_library_access_not_granted" = "%@ n’a pas la permission pour accéder à la médiathèque, veuillez modifier les options de confidentialité"; -"auth_forgot_password_error_no_configured_identity_server" = "Aucun serveur d’identité n’est configuré : ajoutez-en un pour réinitialiser votre mot de passe."; +"auth_forgot_password_error_no_configured_identity_server" = "Aucun serveur d’identité n’est configuré : ajoutez-en un pour réinitialiser le mot de passe de votre compte Matrix."; "room_creation_error_invite_user_by_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de participant avec un e-mail."; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas commencer de discussion avec un contact en utilisant un e-mail."; // Service terms @@ -845,9 +845,9 @@ "auth_add_email_message_2" = "Définissez une adresse e-mail pour la récupération de compte, et pour être éventuellement découvrable par les personnes qui vous connaissent."; "auth_add_phone_message_2" = "Définissez un numéro de téléphone pour être éventuellement découvrable par les personnes qui vous connaissent."; "auth_add_email_phone_message_2" = "Définissez une adresse e-mail pour la récupération de compte. Vous pouvez ensuite utiliser votre e-mail ou votre numéro de téléphone pour être découvrable par les personnes qui vous connaissent."; -"auth_email_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter d’adresse e-mail pour pouvoir réinitialiser votre mot de passe ultérieurement."; -"auth_phone_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de numéro de téléphone pour pouvoir réinitialiser votre mot de passe ultérieurement."; -"auth_reset_password_error_is_required" = "Aucun serveur d’identité n’est configuré : ajoutez-en un dans les options du serveur pour réinitialiser votre mot de passe."; +"auth_email_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter d’adresse e-mail pour pouvoir réinitialiser le mot de passe de votre compte Matrix ultérieurement."; +"auth_phone_is_required" = "Aucun serveur d’identité n’est configuré donc vous ne pouvez pas ajouter de numéro de téléphone pour pouvoir réinitialiser le mot de passe de votre compte Matrix ultérieurement."; +"auth_reset_password_error_is_required" = "Aucun serveur d’identité n’est configuré : ajoutez-en un dans les options du serveur pour réinitialiser le mot de passe de votre compte Matrix."; "contacts_address_book_no_identity_server" = "Aucun serveur d’identité n’est configuré"; "settings_discovery_settings" = "DÉCOUVERTE"; "settings_identity_server_settings" = "SERVEUR D’IDENTITÉ"; @@ -908,7 +908,7 @@ "service_terms_modal_message_identity_server" = "Acceptez les conditions du serveur d’identité (%@) pour découvrir des contacts."; "settings_add_3pid_password_title_email" = "Ajouter une adresse e-mail"; "settings_add_3pid_password_title_msidsn" = "Ajouter un numéro de téléphone"; -"settings_add_3pid_password_message" = "Pour continuer, saisissez votre mot de passe"; +"settings_add_3pid_password_message" = "Pour continuer, saisissez le mot de passe de votre compte Matrix"; "settings_add_3pid_invalid_password_message" = "Informations d’authentification invalides"; "error_not_supported_on_mobile" = "Vous ne pouvez pas faire cela depuis %@ mobile."; "widget_menu_refresh" = "Actualiser"; @@ -1130,7 +1130,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Imprimez-la et stockez-la dans un endroit sûr\n✓ Sauvegardez-la sur une clé USB ou un disque de sauvegarde\n✓ Copiez-la sur votre stockage personnel dans le cloud"; "secrets_setup_recovery_passphrase_title" = "Définir une phrase de sécurité"; "secrets_setup_recovery_passphrase_information" = "Saisissez une phrase de sécurité que vous seul connaissez, utilisée pour sécuriser les secrets sur votre serveur."; -"secrets_setup_recovery_passphrase_additional_information" = "N’utilisez pas le mot de passe de votre compte."; +"secrets_setup_recovery_passphrase_additional_information" = "N’utilisez pas le mot de passe de votre compte Matrix."; "secrets_setup_recovery_passphrase_validate_action" = "Terminé"; "secrets_setup_recovery_passphrase_confirm_information" = "Saisissez à nouveau votre phrase de sécurité pour la confirmer."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Confirmer"; @@ -1139,13 +1139,13 @@ "authenticated_session_flow_not_supported" = "Cette application ne prend par en charge le mécanisme d’authentification de votre serveur d’accueil."; "secure_backup_setup_banner_title" = "Sauvegarde sécurisée"; "secure_backup_setup_banner_subtitle" = "Protection afin d’éviter de perdre l’accès aux messages et données chiffrés"; -"security_settings_crypto_sessions_description_2" = "Si vous ne reconnaissez pas une connexion, changez votre mot de passe et réinitialisez la sauvegarde sécurisée."; +"security_settings_crypto_sessions_description_2" = "Si vous ne reconnaissez pas une connexion, changez le mot de passe de votre compte Matrix et réinitialisez la sauvegarde sécurisée."; "security_settings_secure_backup" = "SAUVEGARDE SÉCURISÉE"; "security_settings_secure_backup_description" = "Sauvegardez vos clés de chiffrement et les données de votre compte au où vous perdriez l’accès à vos sessions. Vos clés seront protégées par une clé de sécurité unique."; "security_settings_secure_backup_setup" = "Configurer"; "security_settings_secure_backup_synchronise" = "Synchroniser"; "security_settings_secure_backup_delete" = "Supprimer la sauvegarde"; -"security_settings_user_password_description" = "Confirmez votre identité en saisissant le mot de passe de votre compte"; +"security_settings_user_password_description" = "Confirmez votre identité en saisissant le mot de passe de votre compte Matrix"; "secure_key_backup_setup_existing_backup_error_title" = "Une sauvegarde pour les messages existe déjà"; "secure_key_backup_setup_existing_backup_error_info" = "Déverrouillez-la pour la réutiliser dans la sauvegarde sécurisée ou supprimez-la pour créer une nouvelle sauvegarde de messages dans la sauvegarde sécurisée."; "secure_key_backup_setup_existing_backup_error_unlock_it" = "La déverrouiller"; @@ -1285,7 +1285,7 @@ // MARK: - Major update "major_update_title" = "Riot est désormais %@"; -"secrets_reset_authentication_message" = "Saisir votre mot de passe de compte pour confirmer"; +"secrets_reset_authentication_message" = "Saisissez le mot de passe de votre compte Matrix pour confirmer"; "secrets_reset_reset_action" = "Réinitialiser"; "secrets_reset_warning_message" = "Vous allez reprendre sans historique, sans message, appareil ou utilisateur de confiance."; "secrets_reset_warning_title" = "Si vous réinitialisez tout"; @@ -1640,3 +1640,33 @@ "poll_edit_form_update_failure_subtitle" = "Veuillez réessayer"; "poll_edit_form_update_failure_title" = "Échec lors de la mise à jour du sondage"; "poll_edit_form_poll_type" = "Type de sondage"; +"location_sharing_post_failure_subtitle" = "%# n’a pas pu envoyer votre localisation. Merci de réessayer plus tard."; +"location_sharing_post_failure_title" = "Nous n’avons pas pu envoyer votre localisation"; +"home_context_menu_leave" = "Partir"; +"home_context_menu_unfavourite" = "Retirer des favoris"; +"home_context_menu_favourite" = "Mettre en favoris"; +"home_context_menu_unmute" = "Retirer la sourdine"; +"home_context_menu_mute" = "Mettre en sourdine"; +"home_context_menu_notifications" = "Notifications"; +"home_context_menu_make_room" = "Déplacer vers Salons"; +"home_context_menu_make_dm" = "Déplacer vers Personnes"; +"event_formatter_message_deleted" = "Message supprimé"; +"settings_labs_enable_threads" = "Fils de discussion"; +"message_from_a_thread" = "Depuis un fil de discussion"; +"threads_empty_show_all_threads" = "Afficher tous les fils de discussion"; +"threads_empty_tip" = "Astuce : appuyez sur un message puis sur « Fil » pour en commencer un nouveau."; +"threads_empty_info_my" = "Répondez à un fil de discussion actif, ou appuyez sur un message et utilisez « Fil » pour en commencer un nouveau."; +"threads_empty_info_all" = "Les fils de discussion vous permettent de centrer vos conversations sur un sujet, et de les suivre facilement."; +"threads_empty_title" = "Gardez vos conversations organisées avec les fils de discussion"; +"threads_action_my_threads" = "Mes fils"; +"threads_action_all_threads" = "Tous les fils"; +"threads_title" = "Fils"; +"thread_copy_link_to_thread" = "Copier le lien vers le fil"; + +// MARK: Threads +"room_thread_title" = "Fil"; +"room_accessibility_thread_more" = "Plus"; +"room_accessibility_threads" = "Fils"; +"room_event_copy_link_info" = "Lien copié dans le presse-papier."; +"room_event_action_reply_in_thread" = "Fil"; +"room_event_action_view_in_room" = "Afficher dans le salon"; From c0b8e11affd4beb8581f39a18265bac5231766fb Mon Sep 17 00:00:00 2001 From: Szimszon Date: Sun, 13 Feb 2022 09:18:10 +0000 Subject: [PATCH 048/188] Translated using Weblate (Hungarian) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ --- Riot/Assets/hu.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index e7d700ffa..2b2bf8853 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -52,7 +52,7 @@ "auth_optional_phone_placeholder" = "Telefonszám (nem kötelező)"; "auth_phone_placeholder" = "Telefonszám"; "auth_repeat_password_placeholder" = "Jelszó megerősítés"; -"auth_repeat_new_password_placeholder" = "Új jelszó megerősítés"; +"auth_repeat_new_password_placeholder" = "Új Matrix fiók jelszó megerősítés"; "auth_home_server_placeholder" = "URL (pl. https://matrix.org)"; "auth_identity_server_placeholder" = "URL (pl. https://vector.im)"; "auth_invalid_login_param" = "Hibás felhasználói név és/vagy jelszó"; @@ -73,7 +73,7 @@ "auth_untrusted_id_server" = "Az azonosító szerver megbízhatatlan"; "auth_password_dont_match" = "A jelszavak nem egyeznek meg"; "auth_username_in_use" = "A felhasználónév foglalt"; -"auth_forgot_password" = "Elfelejtetted a jelszót?"; +"auth_forgot_password" = "Elfelejtetted a Matrix fiók jelszót?"; "auth_email_not_found" = "E-mail küldési hiba: Az e-mail cím nem található"; "auth_use_server_options" = "Egyedi szerver beállítások használata (haladó)"; "auth_email_validation_message" = "Ellenőrizd az e-mailedet a regisztráció folytatásához"; @@ -81,14 +81,14 @@ "auth_msisdn_validation_message" = "Elküldtük az SMS aktivációs kódot. Írd be a kódot ide."; "auth_msisdn_validation_error" = "Nem sikerült ellenőrizni a telefonszámot."; "auth_recaptcha_message" = "Ez a Matrix szerver szeretne megbizonyosodni arról, hogy nem vagy robot"; -"auth_reset_password_message" = "A jelszó visszaállításához add meg az e-mail címet amit a felhasználói fiókhoz kötöttél:"; +"auth_reset_password_message" = "A Matrix fiók jelszó visszaállításához add meg az e-mail címet amit a felhasználói fiókhoz kötöttél:"; "auth_reset_password_missing_email" = "A felhasználói fiókodhoz kötött jelszót kell megadni."; "auth_reset_password_missing_password" = "Add meg az új jelszót."; "auth_reset_password_email_validation_message" = "Az e-mailt elküldtük a %@ címre. Ha rákattintottál a linkre ami benne van utána kattints ide."; "auth_reset_password_next_step_button" = "Ellenőriztem az e-mail címet"; "auth_reset_password_error_unauthorized" = "E-mail cím ellenőrzése nem sikerült: bizonyosodj meg róla, hogy az e-mailben lévő linkre rákattintottál"; "auth_reset_password_error_not_found" = "Úgy tűnik az e-mail címed nincs összekötve a Matrix azonosítóddal a Matrix szerveren."; -"auth_reset_password_success_message" = "Visszaállítottuk a jelszavad.\n\nKijelentkeztettünk minden munkamenetedből és nem kapsz értesítéseket sem. Az értesítések újra engedélyezéséhez jelentkezz be újra az eszközökön."; +"auth_reset_password_success_message" = "Visszaállítottuk a Matrix fiók jelszavad.\n\nKijelentkeztettünk minden munkamenetedből és nem kapsz értesítéseket sem. Az értesítések újra engedélyezéséhez jelentkezz be újra az eszközökön."; // Chat creation "room_creation_title" = "Új csevegés"; "room_creation_account" = "Fiók"; @@ -224,7 +224,7 @@ "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"; +"room_event_action_permalink" = "Üzenet hivatkozás másolása"; "room_event_action_view_source" = "Forrás megjelenítése"; "room_event_action_view_decrypted_source" = "Visszafejtett forrás megjelenítése"; "room_event_action_report" = "Tartalom bejelentése"; @@ -338,12 +338,12 @@ "settings_send_crash_report" = "Személytelen összeomlás és felhasználási adatok küldése"; "settings_enable_rageshake" = "Eszköz megrázása a hiba bejelentéséhez"; "settings_clear_cache" = "Gyorsítótár kiürítése"; -"settings_change_password" = "Jelszó megváltoztatása"; +"settings_change_password" = "Matrix fiók jelszó megváltoztatása"; "settings_old_password" = "régi jelszó"; "settings_new_password" = "új jelszó"; "settings_confirm_password" = "jelszó megerősítése"; -"settings_fail_to_update_password" = "A jelszó frissítése nem sikerült"; -"settings_password_updated" = "A jelszavad frissítve"; +"settings_fail_to_update_password" = "A Matrix fiók jelszó frissítése nem sikerült"; +"settings_password_updated" = "A Matrix fiók jelszavad frissítve"; "settings_crypto_device_name" = "Munkamenet neve: "; "settings_crypto_device_id" = "\nMunkamenet azonosítója: "; "settings_crypto_device_key" = "\nMunkamenet kulcsa:\n"; @@ -543,7 +543,7 @@ "deactivate_account_forget_messages_information_part3" = ": ezzel a jövőben a felhasználók hiányos csevegést fognak csak látni)"; "deactivate_account_validate_action" = "Felhasználói fiók felfüggesztése"; "deactivate_account_password_alert_title" = "Felhasználói fiók felfüggesztése"; -"deactivate_account_password_alert_message" = "A folytatáshoz add meg a jelszavadat"; +"deactivate_account_password_alert_message" = "A folytatáshoz add meg a Matrix fiók jelszavadat"; // Re-request confirmation dialog "rerequest_keys_alert_title" = "Kérés elküldve"; "rerequest_keys_alert_message" = "Kérlek indítsd el a %@et egy másik eszközödön amelyik vissza tudja fejteni az üzenetet, hogy el tudja küldeni a kulcsokat ennek a munkamenetnek."; @@ -589,7 +589,7 @@ "key_backup_setup_intro_title" = "Soha ne veszítsd el a titkosított üzeneteidet"; "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" = "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_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 Matrix 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!"; @@ -813,7 +813,7 @@ "room_event_action_reaction_history" = "Reakciók története"; // MARK: Reaction history "reaction_history_title" = "Reakciók"; -"auth_forgot_password_error_no_configured_identity_server" = "Azonosítási szerver nincs beállítva: a jelszó visszaállításhoz adj hozzá egyet."; +"auth_forgot_password_error_no_configured_identity_server" = "Azonosítási szerver nincs beállítva: a Matrix fiók jelszó visszaállításhoz adj hozzá egyet."; "room_creation_error_invite_user_by_email_without_identity_server" = "Azonosítási szerver nincs beállítva, így e-mail cím alapján nem tudsz hozzáadni résztvevőt."; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Azonosítási szerver nincs beállítva, így e-mail cím alapján nem tudsz beszélgetést kezdeményezni."; "room_action_camera" = "Fotó vagy videó készítése"; @@ -850,9 +850,9 @@ "auth_add_email_message_2" = "E-mail cím beállítása fiók visszaállításhoz és, hogy később az ismerősök megtalálhassanak."; "auth_add_phone_message_2" = "Telefonszám beállítása, hogy később az ismerősök megtalálhassanak."; "auth_add_email_phone_message_2" = "E-mail cím beállítása fiók visszaállításhoz. Használj később e-mail címet vagy telefonszámot, hogy az ismerősök megtalálhassanak."; -"auth_email_is_required" = "Azonosítási szerver nincs beállítva, így nem tudsz hozzáadni e-mail címet amivel vissza lehetne állítani a jelszót a későbbiekben."; -"auth_phone_is_required" = "Azonosítási szerver nincs beállítva, így nem tudsz hozzáadni telefonszámot, hogy vissza lehetne állítani a jelszót a későbbiekben."; -"auth_reset_password_error_is_required" = "Azonosítási szerver nincs beállítva: adj hozzá egyet a szerver beállításoknál, hogy a jelszót vissza lehessen állítani."; +"auth_email_is_required" = "Azonosítási szerver nincs beállítva, így nem tudsz hozzáadni e-mail címet amivel vissza lehetne állítani a Matrix fiók jelszót a későbbiekben."; +"auth_phone_is_required" = "Azonosítási szerver nincs beállítva, így nem tudsz hozzáadni telefonszámot, hogy vissza lehetne állítani a Matrix fiók jelszót a későbbiekben."; +"auth_reset_password_error_is_required" = "Azonosítási szerver nincs beállítva: adj hozzá egyet a szerver beállításoknál, hogy a Matrix fiók jelszót vissza lehessen állítani."; "contacts_address_book_no_identity_server" = "Azonosítási szerver nincs beállítva"; "settings_discovery_settings" = "FELDERÍTÉS"; "settings_identity_server_settings" = "AZONOSÍTÁSI SZERVER"; @@ -913,7 +913,7 @@ "service_terms_modal_message_identity_server" = "Az azonosítási szerver (%@) felhasználási feltételeit el kell fogadnod, hogy ismerősöket kereshess."; "settings_add_3pid_password_title_email" = "E-mail cím hozzáadása"; "settings_add_3pid_password_title_msidsn" = "Telefonszám hozzáadása"; -"settings_add_3pid_password_message" = "A folytatáshoz add meg a jelszavadat"; +"settings_add_3pid_password_message" = "A folytatáshoz add meg a Matrix fiók jelszavadat"; "settings_add_3pid_invalid_password_message" = "Érvénytelen jelszó"; "error_not_supported_on_mobile" = "%@ mobilról ezt nem teheted meg."; "widget_menu_refresh" = "Frissítés"; @@ -1119,7 +1119,7 @@ "security_settings_secure_backup_setup" = "Beállítás"; "security_settings_secure_backup_synchronise" = "Szinkronizál"; "security_settings_secure_backup_delete" = "Mentés törlése"; -"security_settings_user_password_description" = "A fiók jelszó megadásával erősítsd meg a személyazonosságodat"; +"security_settings_user_password_description" = "A Matrix fiók jelszó megadásával erősítsd meg a személyazonosságodat"; "secure_key_backup_setup_intro_title" = "Biztonsági Mentés"; "secure_key_backup_setup_intro_info" = "A titkosított üzenetekhez és adatokhoz való hozzáférés elvesztése esetén használható biztonsági tartalék a titkosított kulcsok a szerveredre való elmentésével."; "secure_key_backup_setup_intro_use_security_key_title" = "Használd a Biztonsági Kulcsot"; @@ -1139,14 +1139,14 @@ "secrets_setup_recovery_key_done_action" = "Kész"; "secrets_setup_recovery_key_storage_alert_title" = "Tartsd biztonságban"; "secrets_setup_recovery_passphrase_title" = "Biztonsági Jelmondat beállítása"; -"secrets_setup_recovery_passphrase_additional_information" = "Ne a fiók jelszavadat használd."; +"secrets_setup_recovery_passphrase_additional_information" = "Ne a Matrix fiók jelszavadat használd."; "secrets_setup_recovery_passphrase_validate_action" = "Kész"; "secrets_setup_recovery_passphrase_confirm_information" = "A megerősítéshez add meg újra a Biztonsági Jelmondatot."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Megerősítés"; "secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Jelmondat megerősítése"; "cross_signing_setup_banner_title" = "Titkosítás beállítása"; "cross_signing_setup_banner_subtitle" = "A többi eszközödet ellenőrizd egyszerűen"; -"security_settings_crypto_sessions_description_2" = "Ha ez a bejelentkezés nem ismerős, akkor változtasd meg a jelszavad és újra állítsd be a Biztonsági Mentést."; +"security_settings_crypto_sessions_description_2" = "Ha ez a bejelentkezés nem ismerős, akkor változtasd meg a Matrix fiók jelszavad és újra állítsd be a Biztonsági Mentést."; "security_settings_secure_backup_description" = "Mentsd el a titkosítási kulcsokat a fiókadatokkal arra az esetre ha elvesztenéd a hozzáférést a munkameneteidhez. A kulcsok egy egyedi Biztonsági Kulccsal lesznek védve."; // AuthenticatedSessionViewControllerFactory "authenticated_session_flow_not_supported" = "Ez az alkalmazás nem támogatja a matrix szervered azonosítási mechanizmusát."; @@ -1244,7 +1244,7 @@ "room_info_list_one_member" = "1 tag"; "room_info_list_several_members" = "%@ tag"; "room_info_list_section_other" = "Más"; -"secrets_reset_authentication_message" = "A fiók jelszavaddal erősítsd meg"; +"secrets_reset_authentication_message" = "A Matrix fiók jelszavaddal erősítsd meg"; "secrets_reset_reset_action" = "Visszaállít"; "secrets_reset_warning_message" = "Tiszta lappal indulsz, üzenetek, megbízható eszközök és felhasználók nélkül."; "secrets_reset_warning_title" = "Ha mindent visszaállítasz"; @@ -1626,3 +1626,35 @@ "poll_edit_form_update_failure_subtitle" = "Kérlek próbáld újra"; "poll_edit_form_update_failure_title" = "A szavazást nem sikerült frissíteni"; "poll_edit_form_poll_type" = "Szavazás típusa"; +"location_sharing_post_failure_subtitle" = "%@ a helyadatodat nem lehet elküldeni. Próbáld újra később."; +"location_sharing_post_failure_title" = "A földrajzi helyzetét nem lehet elküldeni"; +"home_context_menu_leave" = "Elhagyás"; +"home_context_menu_normal_priority" = "Normál prioritás"; +"home_context_menu_low_priority" = "Alacsony prioritás"; +"home_context_menu_unfavourite" = "Törlés a kedvencekből"; +"home_context_menu_favourite" = "Kedvencek"; +"home_context_menu_unmute" = "Némítás kikapcsolása"; +"home_context_menu_mute" = "Némítás"; +"home_context_menu_notifications" = "Értesítések"; +"home_context_menu_make_room" = "Szobák közé mozgatás"; +"home_context_menu_make_dm" = "Közvetlen beszélgetések közé helyezés"; +"event_formatter_message_deleted" = "Üzenet törölve"; +"settings_labs_enable_threads" = "Üzenetszálas beszélgetés"; +"message_from_a_thread" = "Az üzenetszálból"; +"threads_empty_show_all_threads" = "Minden üzenetszál megjelenítése"; +"threads_empty_tip" = "Tipp: Koppints az üzenetre és használd az „Üzenetszál”-at új indításhoz."; +"threads_empty_info_my" = "Válaszolj egy már meglévő üzenetszálba vagy koppints az üzenetre és használd az „Üzenetszál”-at új indításhoz."; +"threads_empty_info_all" = "Az üzenetszálak segítenek a különböző témájú beszélgetések figyelemmel kísérésében."; +"threads_empty_title" = "Beszélgetések üzenetszálakba rendezése"; +"threads_action_my_threads" = "Üzenetszálaim"; +"threads_action_all_threads" = "Minden üzenetszál"; +"threads_title" = "Üzenetszálak"; +"thread_copy_link_to_thread" = "Üzenetszálra mutató hivatkozás másolása"; + +// MARK: Threads +"room_thread_title" = "Üzenetszál"; +"room_accessibility_thread_more" = "Több"; +"room_accessibility_threads" = "Üzenetszálak"; +"room_event_copy_link_info" = "Hivatkozás a vágólapra másolva."; +"room_event_action_reply_in_thread" = "Üzenetszál"; +"room_event_action_view_in_room" = "Megjelenítés szobában"; From 1935de7952cb4a10db0eeb8332a6d0541684dc6f Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Thu, 10 Feb 2022 18:53:11 +0000 Subject: [PATCH 049/188] Translated using Weblate (Albanian) Currently translated at 99.7% (1429 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ --- Riot/Assets/sq.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index 0b0f12415..848a9fedb 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -46,7 +46,7 @@ "auth_optional_phone_placeholder" = "Numër telefoni (opsionale)"; "auth_phone_placeholder" = "Numër telefoni"; "auth_repeat_password_placeholder" = "Rijepeni fjalëkalimin"; -"auth_repeat_new_password_placeholder" = "Ripohoni fjalëkalimin tuaj të ri"; +"auth_repeat_new_password_placeholder" = "Që ta ripohoni, jepni fjalëkalimin e llogarisë tuaj Matrix"; "auth_home_server_placeholder" = "URL (p.sh., https://matrix.org)"; "auth_identity_server_placeholder" = "URL (p.sh., https://vector.im)"; "auth_invalid_login_param" = "Emër përdoruesi dhe/ose fjalëkalim i pasaktë"; @@ -62,12 +62,12 @@ "auth_untrusted_id_server" = "Shërbyesi i identiteteve s’është i besuar"; "auth_password_dont_match" = "Fjalëkalimet s’përputhen"; "auth_username_in_use" = "Emër përdoruesi i përdorur"; -"auth_forgot_password" = "Harruat fjalëkalimin?"; +"auth_forgot_password" = "Harruat fjalëkalimin e llogarisë tuaj Matrix?"; "auth_email_not_found" = "S’u arrit të dërgohej email: Kjo adresë email s’u gjet"; "auth_email_validation_message" = "Ju lutemi, që të vazhdojë regjistrimi, kontrolloni email-in tuaj"; "auth_msisdn_validation_title" = "Verifikim Në Pritje të Miratimit"; "auth_msisdn_validation_error" = "S’arrihet të verifikohet numër telefoni."; -"auth_reset_password_message" = "Që të ricaktoni fjalëkalimin, jepni adresën email të lidhur me llogarinë tuaj:"; +"auth_reset_password_message" = "Që të ricaktoni fjalëkalimin e llogarisë tuaj Matrix, jepni adresën email të lidhur me llogarinë tuaj:"; "auth_reset_password_missing_email" = "Duhet dhënë adresa email e lidhur me llogarinë tuaj."; "auth_reset_password_missing_password" = "Duhet dhënë një fjalëkalim i ri."; // Chat creation @@ -180,7 +180,7 @@ "room_event_action_copy" = "Kopjoje"; "room_event_action_quote" = "Citim"; "room_event_action_more" = "Më tepër"; -"room_event_action_permalink" = "Permalidhje"; +"room_event_action_permalink" = "Kopjoje lidhjen te mesazh"; "room_event_action_view_source" = "Shihini Burimin"; "room_event_action_report" = "Raportoni lëndë"; "room_event_action_report_prompt_reason" = "Arsye për raportimin e kësaj lënde"; @@ -257,11 +257,11 @@ "settings_privacy_policy" = "Rregulla Privatësie"; "settings_third_party_notices" = "Njoftime Palësh të Treta"; "settings_clear_cache" = "Pastroje fshehtinën"; -"settings_change_password" = "Ndryshoni fjalëkalimin"; +"settings_change_password" = "Ndryshoni fjalëkalim llogarie Matrix"; "settings_old_password" = "fjalëkalim i vjetër"; "settings_new_password" = "fjalëkalim i ri"; "settings_confirm_password" = "ripohoni fjalëkalimin"; -"settings_password_updated" = "Fjalëkalimi juaj u përditësua"; +"settings_password_updated" = "Fjalëkalimi i llogarisë tuaj Matrix u përditësua"; "settings_crypto_device_name" = "Emër sesioni: "; "settings_crypto_device_id" = "\nID sesioni: "; "settings_crypto_device_key" = "\nKyç sesioni:\n"; @@ -426,7 +426,7 @@ "settings_pin_rooms_with_missed_notif" = "Fikso dhomat me njoftime të humbura"; "settings_pin_rooms_with_unread" = "Fikso dhomat me mesazhe të palexuar"; "settings_labs_create_conference_with_jitsi" = "Krijoni thirrje konferencë me Jitsi-n"; -"settings_fail_to_update_password" = "S’arrihet të përditësohet fjalëkalimi"; +"settings_fail_to_update_password" = "S’u arrit të përditësohet fjalëkalimi i llogarisë Matrix"; "settings_deactivate_my_account" = "Çaktivizoje llogarinë time"; "room_details_mute_notifs" = "Heshtoji njoftimet"; "room_details_access_section_no_address_warning" = "Që të lidhni një dhomë, ajo duhet të ketë një adresë"; @@ -464,10 +464,10 @@ "deactivate_account_forget_messages_information_part2_emphasize" = "Kujdes"; "deactivate_account_validate_action" = "Çaktivizoje llogarinë"; "deactivate_account_password_alert_title" = "Çaktivizoni Llogarinë"; -"deactivate_account_password_alert_message" = "Që të vazhdohet, ju lutemi, jepni fjalëkalimin tuaj"; +"deactivate_account_password_alert_message" = "Që të vazhdohet, ju lutemi, jepni fjalëkalimin e llogarisë tuaj Matrix."; // Re-request confirmation dialog "rerequest_keys_alert_title" = "Kërkesa u Dërgua"; -"auth_reset_password_success_message" = "Fjalëkalimi juaj u ri caktua.\n\nËshtë bërë dalja juaj nga llogaria në krejt sesionet dhe s’do të merrni më njoftime push. Për riaktivizim të njoftimeve, ribëni hyrjen në çdo pajisje."; +"auth_reset_password_success_message" = "Fjalëkalimi i llogarisë tuaj Matrix u ricaktua.\n\nËshtë bërë dalja juaj nga llogaria në krejt sesionet dhe s’do të merrni më njoftime push. Për riaktivizim të njoftimeve, ribëni hyrjen në çdo pajisje."; "room_creation_make_public_prompt_msg" = "Jeni i sigurt se doni ta bëni publike këtë fjalosje? Në një të tillë, mesazhet tuaj mund t’i lexojë cilido dhe mund të hyjë në bisedë."; "room_creation_wait_for_creation" = "Po krijohet tashmë një dhomë. Ju lutemi, prisni."; "contacts_address_book_permission_required" = "Lypset leje për hyrje në kontaktet vendore"; @@ -580,7 +580,7 @@ "key_backup_setup_intro_title" = "Mos humbni kurrë mesazhe të fshehtëzuar"; "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" = "Do të depozitojmë një kopje të fshehtëzuar të kyçeve tuaj në shërbyesin tonë. Mbrojeni kopjeruajtjen tuaj me një frazë, 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_info" = "Do të depozitojmë një kopje të fshehtëzuar të kyçeve tuaj në shërbyesin tonë. Mbrojeni kopjeruajtjen tuaj me një frazë, 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ë Matrix."; "key_backup_setup_passphrase_passphrase_title" = "Jepeni"; "key_backup_setup_passphrase_passphrase_placeholder" = "Jepni frazë"; "key_backup_setup_passphrase_passphrase_valid" = "Bukur!"; @@ -812,7 +812,7 @@ "emoji_picker_flags_category" = "Flamuj"; // MARK: Reaction history "reaction_history_title" = "Reagime"; -"auth_forgot_password_error_no_configured_identity_server" = "S’ka shërbyes identitetesh të formësuar: shtoni një të tillë që të ricaktoni fjalëkalimin tuaj."; +"auth_forgot_password_error_no_configured_identity_server" = "S’ka shërbyes identitetesh të formësuar: shtoni një të tillë që të ricaktoni fjalëkalimin e llogarisë tuaj Matrix."; "room_creation_error_invite_user_by_email_without_identity_server" = "S’ka shërbyes identitetesh të formësua, ndaj s’mund të shtoni një pjesëmarrës me një email."; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "S’ka shërbyes identitetesh të formësuar, ndaj s’mund të nisni një fjalosje me një kontakt duke përdorur një email."; // Service terms @@ -839,9 +839,9 @@ "auth_add_email_message_2" = "Caktoni një email për rimarrje llogarie, dhe që më vonë të jeni (opsionale) i zbulueshëm nga persona që ju njohin."; "auth_add_phone_message_2" = "Caktoni një telefon, dhe jini më vonë i zbulueshëm nga persona që ju njohin."; "auth_add_email_phone_message_2" = "Caktoni një email për rimarrje llogarie. Përdorni më vonë email ose telefon që të jeni (opsionale) i zbulueshëm nga persona që ju njohin."; -"auth_email_is_required" = "S’ka të formësuar shërbyes identitetesh, ndaj s’mund të shtoni adresë email që të mund të ricaktoni fjalëkalimin tuaj në të ardhmen."; -"auth_phone_is_required" = "S’ka të formësuar shërbyes identitetesh, ndaj s’mund të shtoni numër telefoni që të mund të ricaktoni fjalëkalimin tuaj në të ardhmen."; -"auth_reset_password_error_is_required" = "S’ka të formësuar shërbyes identitetesh: shtoni një të tillë që nga mundësitë rreth shërbyesit, që të ricaktoni fjalëkalimin tuaj."; +"auth_email_is_required" = "S’ka të formësuar shërbyes identitetesh, ndaj s’mund të shtoni adresë email që të mund të ricaktoni fjalëkalimin e llogarisë tuaj Matrix në të ardhmen."; +"auth_phone_is_required" = "S’ka të formësuar shërbyes identitetesh, ndaj s’mund të shtoni numër telefoni që të mund të ricaktoni fjalëkalimin e llogarisë tuaj Matrix në të ardhmen."; +"auth_reset_password_error_is_required" = "S’ka të formësuar shërbyes identitetesh: shtoni një të tillë që nga mundësitë rreth shërbyesit, që të ricaktoni fjalëkalimin e llogarisë tuaj Matrix."; "contacts_address_book_no_identity_server" = "S’ka të formësuar shërbyes identitetesh"; "settings_discovery_settings" = "ZBULIM"; "settings_identity_server_settings" = "SHËRBYES IDENTITETESH"; @@ -850,7 +850,7 @@ "settings_three_pids_management_information_part3" = "."; "settings_add_3pid_password_title_email" = "Shtoni adresë email"; "settings_add_3pid_password_title_msidsn" = "Shtoni numër telefoni"; -"settings_add_3pid_password_message" = "Që të vazhdohet, ju lutemi, jepni fjalëkalimin tuaj"; +"settings_add_3pid_password_message" = "Që të vazhdohet, ju lutemi, jepni fjalëkalimin e llogarisë tuaj Matrix."; "settings_add_3pid_invalid_password_message" = "Kredenciale të pavlefshme"; "settings_devices_description" = "Emri publik i një sesioni është i dukshëm për persona me të cilët komunikoni"; "settings_discovery_no_identity_server" = "S’po përdorni ndonjë shërbyes identitetesh. Që të jeni i zbulueshëm nga kontakte ekzistuese që njihni, shtoni një të tillë."; @@ -1122,7 +1122,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Shtypeni dhe vendoseni diku të parrezik\n✓ Ruajeni në një diskth USB ose në një pajisje kopjeruajtjesh\n✓ Kopjojeni te depoja juaj personale në re"; "secrets_setup_recovery_passphrase_title" = "Caktoni një Frazë Sigurie"; "secrets_setup_recovery_passphrase_information" = "Jepni një frazë sigurie që e dini vetëm ju, për ta përdorur për sigurim të fshehtash në shërbyesin tuaj."; -"secrets_setup_recovery_passphrase_additional_information" = "Mos përdorni fjalëkalimin e llogarisë tuaj."; +"secrets_setup_recovery_passphrase_additional_information" = "Mos përdorni fjalëkalimin e llogarisë tuaj Matrix."; "secrets_setup_recovery_passphrase_validate_action" = "U bë"; "secrets_setup_recovery_passphrase_confirm_information" = "Që ta ripohoni, rijepeni Frazën e Sigurisë."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Ripohojeni"; @@ -1132,13 +1132,13 @@ "security_settings_secure_backup_setup" = "Ujdiseni"; "security_settings_secure_backup_synchronise" = "Njëkohësoje"; "security_settings_secure_backup_delete" = "Fshije Kopjeruajtjen"; -"security_settings_user_password_description" = "Ripohoni identitetin tuaj duke dhënë fjalëkalimin e llogarisë tuaj"; +"security_settings_user_password_description" = "Ripohoni identitetin tuaj duke dhënë fjalëkalimin e llogarisë tuaj Matrix"; "secure_key_backup_setup_existing_backup_error_title" = "Një kopjeruajtje për mesazhe që ekzistojnë tashmë"; "secure_key_backup_setup_existing_backup_error_info" = "Shkyçeni, që ta ripërdorni te kopjeruajtja e sigurt ose për ta fshirë që të krijoni një kopjeruajtje të re mesazhesh te kopjeruajtja e sigurt."; "secure_key_backup_setup_existing_backup_error_unlock_it" = "Shkyçe"; "secure_key_backup_setup_existing_backup_error_delete_it" = "Fshije"; "sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Fillo të përdorësh Kojperuajtje të Sigurt"; -"security_settings_crypto_sessions_description_2" = "Nëse nuk njihni një palë kredenciale, ndryshoni fjalëkalimin tuaj dhe riujdisni Kopjeruajtjen e Sigurt."; +"security_settings_crypto_sessions_description_2" = "Nëse nuk njihni një palë kredenciale, ndryshoni fjalëkalimin tuaj Matrix dhe riujdisni Kopjeruajtjen e Sigurt."; "cross_signing_setup_banner_title" = "Ujdisni fshehtëzim"; "cross_signing_setup_banner_subtitle" = "Verifikoni më me lehtësi pajisje të tjera"; // Events formatter with you @@ -1229,7 +1229,7 @@ "pin_protection_kick_user_alert_message" = "Shumë gabime, u bë nxjerrja juaj jashtë"; "switch" = "Këmbe"; "joined" = "Erdhi"; -"secrets_reset_authentication_message" = "Që ta ripohoni, jepni fjalëkalimin e llogarisë tuaj"; +"secrets_reset_authentication_message" = "Që ta ripohoni, jepni fjalëkalimin e llogarisë tuaj Matrix"; "secrets_reset_reset_action" = "Riktheji"; "secrets_reset_warning_message" = "Do të filloni pa historik, pa mesazhe, pajisje të besuara ose përdorues të besuar."; "secrets_reset_warning_title" = "Nëse ktheni gjithçka te parazgjedhjet"; @@ -1615,3 +1615,35 @@ "poll_edit_form_update_failure_subtitle" = "Ju lutemi, riprovoni"; "poll_edit_form_update_failure_title" = "S’u arrit të përditësohet anketimi"; "poll_edit_form_poll_type" = "Lloj anketimi"; +"location_sharing_post_failure_subtitle" = "%@ s’dërgoi dot vendndodhjen tuaj. Ju lutemi, riprovoni më vonë."; +"location_sharing_post_failure_title" = "S’dërguam dot vendndodhjen tuaj"; +"home_context_menu_leave" = "Ikni"; +"home_context_menu_normal_priority" = "Përparësi normale"; +"home_context_menu_low_priority" = "Me përparësi të ulët"; +"home_context_menu_unfavourite" = "Hiqe prej të Parapëlqyerish"; +"home_context_menu_favourite" = "Bëje të parapëlqyer"; +"home_context_menu_unmute" = "Ktheji zërin"; +"home_context_menu_mute" = "Heshtoje"; +"home_context_menu_notifications" = "Njoftime"; +"home_context_menu_make_room" = "Shpjere te Dhoma"; +"home_context_menu_make_dm" = "Shpjere te Persona"; +"event_formatter_message_deleted" = "Mesazhi u fshi"; +"settings_labs_enable_threads" = "Mesazhe me rrjedha"; +"message_from_a_thread" = "Nga një rrjedhë"; +"threads_empty_show_all_threads" = "Shfaqi krejt rrjedhat"; +"threads_empty_tip" = "Ndihmëz: Prekni një mesazh dhe përdorni “Rrjedhë”, që të nisni një të re."; +"threads_empty_info_my" = "Përgjigjuni te një rrjedhë në zhvillim, ose prekni një mesazh dhe përdorni “Rrjedhë”, që të nisni një të re."; +"threads_empty_info_all" = "Rrjedhat ndihmojnë që të mbahet biseda juaj brenda temës dhe të ndiqet kollaj."; +"threads_empty_title" = "Mbajini diskutimet të sistemuara në rrjedha"; +"threads_action_my_threads" = "Rrjedhat e mia"; +"threads_action_all_threads" = "Krejt rrjedhat"; +"threads_title" = "Rrjedha"; +"thread_copy_link_to_thread" = "Kopjoje lidhjen te rrjedha"; + +// MARK: Threads +"room_thread_title" = "Rrjedhë"; +"room_accessibility_thread_more" = "Më tepër"; +"room_accessibility_threads" = "Rrjedha"; +"room_event_copy_link_info" = "Lidhja u kopjua në të papastër."; +"room_event_action_reply_in_thread" = "Rrjedhë"; +"room_event_action_view_in_room" = "Shiheni në dhomë"; From 406fa521523a34d84eb79aa01581fb1d475a2a9c Mon Sep 17 00:00:00 2001 From: random Date: Sat, 12 Feb 2022 11:45:03 +0000 Subject: [PATCH 050/188] Translated using Weblate (Italian) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ --- Riot/Assets/it.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/it.lproj/Vector.strings b/Riot/Assets/it.lproj/Vector.strings index 9a80d83b0..abb600606 100644 --- a/Riot/Assets/it.lproj/Vector.strings +++ b/Riot/Assets/it.lproj/Vector.strings @@ -34,7 +34,7 @@ "auth_optional_phone_placeholder" = "Numero di telefono (opzionale)"; "auth_phone_placeholder" = "Numero di telefono"; "auth_repeat_password_placeholder" = "Ripeti la password"; -"auth_repeat_new_password_placeholder" = "Conferma la nuova password"; +"auth_repeat_new_password_placeholder" = "Conferma la nuova password dell'account Matrix"; "auth_home_server_placeholder" = "URL (es. https://matrix.org)"; "auth_identity_server_placeholder" = "URL (es. https://vector.im)"; "auth_invalid_login_param" = "Nome utente e/o password non corretti"; @@ -52,12 +52,12 @@ "auth_missing_email_or_phone" = "Indirizzo email o numero di telefono mancante"; "auth_email_in_use" = "Questo indirizzo email è già in uso"; "auth_phone_in_use" = "Questo numero di telefono è già in uso"; -"auth_forgot_password" = "Password dimenticata?"; +"auth_forgot_password" = "Password dell'account Matrix dimenticata?"; "auth_email_validation_message" = "Per favore controlla la tua email per proseguire la registrazione"; "auth_msisdn_validation_title" = "In attesa di verifica"; "auth_msisdn_validation_message" = "Ti è stato spedito un SMS con il codice di attivazione. Per favore inserisci il codice qui sotto."; "auth_msisdn_validation_error" = "Impossibile verificare il numero di telefono."; -"auth_reset_password_message" = "Per ripristinare la password inserisci l'indirizzo email associato al tuo account:"; +"auth_reset_password_message" = "Per ripristinare la password dell'account Matrix inserisci l'indirizzo email associato al tuo account:"; // String for App Store "store_short_description" = "Conversazioni sicure e decentralizzate"; // Actions @@ -90,7 +90,7 @@ "auth_reset_password_next_step_button" = "Ho verificato il mio indirizzo email"; "auth_reset_password_error_unauthorized" = "Verifica indirizzo email fallita: assicurati di aver cliccato sul link contenuto nell'email"; "auth_reset_password_error_not_found" = "Il tuo indirizzo email non sembra associato a nessun ID utente registrato su questo Home Server."; -"auth_reset_password_success_message" = "La tua password è stata ripristinata.\n\nSei stato disconnesso da tutte le sessioni e non riceverai più alcuna notifica. Per riabilitare le notifiche, riconnettiti su ciascun dispositivo."; +"auth_reset_password_success_message" = "La password del tuo account Matrix è stata ripristinata.\n\nSei stato disconnesso da tutte le sessioni e non riceverai più alcuna notifica. Per riabilitare le notifiche, riconnettiti su ciascun dispositivo."; "auth_add_email_and_phone_warning" = "Al momento non è ancora possibile registrarsi contemporaneamente con indirizzo email e numero di telefono e quindi verrà utilizzato solo il numero di telefono. Puoi aggiungere la tua email al tuo profilo dall menù Impostazioni."; "auth_accept_policies" = "Per favore, rileggi e accetta i termini di servizio di questo Home Server:"; "auth_autodiscover_invalid_response" = "Risposta Home Server non valida"; @@ -230,7 +230,7 @@ "room_event_action_redact" = "Rimuovi"; "room_event_action_more" = "Altro"; "room_event_action_share" = "Condividi"; -"room_event_action_permalink" = "Permalink"; +"room_event_action_permalink" = "Copia link nel messaggio"; "room_event_action_view_source" = "Vedi il codice sorgente"; "room_event_action_view_decrypted_source" = "Vedi il codice sorgente decifrato"; "room_event_action_report" = "Segnala il contenuto"; @@ -319,7 +319,7 @@ "settings_add_email_address" = "Aggiungi indirizzo email"; "settings_phone_number" = "Telefono"; "settings_add_phone_number" = "Aggiungi numero di telefono"; -"settings_change_password" = "Cambia password"; +"settings_change_password" = "Cambia password dell'account Matrix"; "settings_night_mode" = "Modalità notte"; "settings_fail_to_update_profile" = "Errore nell'aggiornamento del profilo"; "settings_enable_push_notif" = "Notifiche per questo dispositivo"; @@ -356,8 +356,8 @@ "settings_old_password" = "vecchia password"; "settings_new_password" = "nuova password"; "settings_confirm_password" = "conferma password"; -"settings_fail_to_update_password" = "Aggiornamento password fallito"; -"settings_password_updated" = "La tua password è stata aggiornata"; +"settings_fail_to_update_password" = "Aggiornamento password dell'account Matrix fallito"; +"settings_password_updated" = "La password del tuo account Matrix è stata aggiornata"; "settings_crypto_device_name" = "Nome sessione: "; "settings_crypto_device_id" = "\nID sessione: "; "settings_crypto_device_key" = "\nChiave sessione:\n"; @@ -580,7 +580,7 @@ "deactivate_account_forget_messages_information_part3" = ": gli utenti futuri vedranno un elenco incompleto di conversazioni)"; "deactivate_account_validate_action" = "Disattiva account"; "deactivate_account_password_alert_title" = "Disattiva account"; -"deactivate_account_password_alert_message" = "Per proseguire, inserisci la tua password"; +"deactivate_account_password_alert_message" = "Per continuare, inserisci la password del tuo account Matrix"; // Re-request confirmation dialog "rerequest_keys_alert_title" = "Richiesta inviata"; "rerequest_keys_alert_message" = "Avvia %@ su un altro dispositivo che possa decifrare il messaggio, in modo da poter inviare le chiavi a questa sessione."; @@ -594,7 +594,7 @@ "key_backup_setup_intro_manual_export_info" = "(Avanzato)"; "key_backup_setup_intro_manual_export_action" = "Esporta manualmente le chiavi"; "key_backup_setup_passphrase_title" = "Proteggi il tuo backup con una frase di sicurezza"; -"key_backup_setup_passphrase_info" = "Sul tuo Home Server verrà effettuato un Backup cifrato delle tue chiavi crittograficher. Proteggi il Backup con una frase di sicurezza perchè sia al sicuro.\n \nPer una massima sicurezza, la password del Backup dovrebbe essere diversa dalla password del tuo account."; +"key_backup_setup_passphrase_info" = "Conserveremo una copia cifrata delle tue chiavi sul nostro server. Proteggi il tuo backup con una frase di sicurezza per tenerlo sicuro.\n \nPer la massima sicurezza, dovrebbe essere diversa dalla password del tuo account Matrix."; "key_backup_setup_passphrase_passphrase_title" = "Inserisci"; "key_backup_setup_passphrase_passphrase_placeholder" = "Inserisci frase"; "key_backup_setup_passphrase_passphrase_valid" = "Bene!"; @@ -651,7 +651,7 @@ "sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Non voglio i miei messaggi cifrati"; "sign_out_key_backup_in_progress_alert_cancel_action" = "Attendo"; "close" = "Chiudi"; -"auth_forgot_password_error_no_configured_identity_server" = "Non è stato configurato alcun server d'identità: aggiungine uno per ripristinare la password."; +"auth_forgot_password_error_no_configured_identity_server" = "Non è stato configurato alcun server d'identità: aggiungine uno per ripristinare la password dell'account Matrix."; "auth_softlogout_signed_out" = "Sei uscito"; "auth_softlogout_sign_in" = "Accedi"; "auth_softlogout_reason" = "L'amministratore dell'Home Server (%1$@) ti ha disconnesso dal tuo account %2$@ (%3$@)."; @@ -820,9 +820,9 @@ "auth_add_email_message_2" = "Imposta un'email per il ripristino dell'account in caso di problemi e, se vuoi, anche per farti trovare da chi conosce quell'indirizzo email."; "auth_add_phone_message_2" = "Aggiungi un numero di telefono se vuoi farti trovare da chi lo conosce."; "auth_add_email_phone_message_2" = "Imposta un'email per il ripristino dell'account in caso di problemi. Email e telefono potranno essere usati anche per farti trovare dagli altri utenti."; -"auth_email_is_required" = "Non è stato configurato alcun server d'identità, perciò non puoi aggiungere un indirizzo email per ripristinare la tua password in futuro."; -"auth_phone_is_required" = "Non è stato configurato alcun server d'identità, perciò non puoi aggiungere un numero di telefono per ripristinare la tua password in futuro."; -"auth_reset_password_error_is_required" = "Non è stato configurato alcun server d'identità: aggiungine uno nelle opzioni server per ripristinare la password."; +"auth_email_is_required" = "Non è stato configurato alcun server d'identità, perciò non puoi aggiungere un indirizzo email per ripristinare la tua password dell'account Matrix in futuro."; +"auth_phone_is_required" = "Non è stato configurato alcun server d'identità, perciò non puoi aggiungere un numero di telefono per ripristinare la tua password dell'account Matrix in futuro."; +"auth_reset_password_error_is_required" = "Non è stato configurato alcun server d'identità: aggiungine uno nelle opzioni server per ripristinare la password dell'account Matrix."; "contacts_address_book_no_identity_server" = "Nessun server d'identità configurato"; "settings_discovery_settings" = "SCOPRI"; "settings_identity_server_settings" = "SERVER D'IDENTITÀ"; @@ -883,7 +883,7 @@ "error_invite_3pid_with_no_identity_server" = "Aggiungi un server d'identità nelle impostazioni per poter invitare utenti tramite email."; "settings_add_3pid_password_title_email" = "Aggiungi indirizzo email"; "settings_add_3pid_password_title_msidsn" = "Aggiungi numero di telefono"; -"settings_add_3pid_password_message" = "Per continuare, inserisci la tua password"; +"settings_add_3pid_password_message" = "Per continuare, inserisci la password del tuo account Matrix"; "settings_add_3pid_invalid_password_message" = "Credenziali non valide"; "error_not_supported_on_mobile" = "Non puoi farlo da %@ mobile."; "widget_menu_refresh" = "Ricarica"; @@ -1104,7 +1104,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Stampala e conservala in un posto sicuro\n✓ Salvala in una chiave USB o disco di backup\n✓ Copiala nel tuo archivio cloud pesonale"; "secrets_setup_recovery_passphrase_title" = "Imposta una frase di sicurezza"; "secrets_setup_recovery_passphrase_information" = "Inserisci una frase di sicurezza che conosci solo tu, usata per proteggere i segreti nel tuo server."; -"secrets_setup_recovery_passphrase_additional_information" = "Non usare la password del tuo account."; +"secrets_setup_recovery_passphrase_additional_information" = "Non usare la password del tuo account Matrix."; "secrets_setup_recovery_passphrase_validate_action" = "Fatto"; "secrets_setup_recovery_passphrase_confirm_information" = "Inserisci la frase di sicurezza di nuovo per confermarla."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Conferma"; @@ -1113,13 +1113,13 @@ "authenticated_session_flow_not_supported" = "Questa app non supporta il metodo di autenticazione del tuo homeserver."; "secure_backup_setup_banner_title" = "Backup Sicuro"; "secure_backup_setup_banner_subtitle" = "Proteggiti dalla perdita dei messaggi e dati crittografati"; -"security_settings_crypto_sessions_description_2" = "Se non riconosci un accesso, modifica la password e reimposta il Backup Sicuro."; +"security_settings_crypto_sessions_description_2" = "Se non riconosci un accesso, modifica la password dell'account Matrix e reimposta il Backup Sicuro."; "security_settings_secure_backup" = "BACKUP SICURO"; "security_settings_secure_backup_description" = "Fai un backup delle chiavi crittografiche con i dati del tuo account in caso tu perda l'accesso alle tue sessioni. Le chiavi saranno protette con una chiave di sicurezza univoca."; "security_settings_secure_backup_setup" = "Configura"; "security_settings_secure_backup_synchronise" = "Sincronizza"; "security_settings_secure_backup_delete" = "Elimina backup"; -"security_settings_user_password_description" = "Conferma la tua identità inserendo la password del tuo account"; +"security_settings_user_password_description" = "Conferma la tua identità inserendo la password dell'account Matrix"; // Events formatter with you "event_formatter_widget_added_by_you" = "Hai aggiunto il widget: %@"; "event_formatter_widget_removed_by_you" = "Hai rimosso il widget: %@"; @@ -1215,7 +1215,7 @@ "room_details_advanced_e2e_encryption_enabled_for_dm" = "La crittografia è attiva"; "room_details_advanced_e2e_encryption_disabled_for_dm" = "La crittografia non è attiva."; "pin_protection_kick_user_alert_message" = "Troppi errori, sei stato disconnesso"; -"secrets_reset_authentication_message" = "Inserisci la password del tuo account per confermare"; +"secrets_reset_authentication_message" = "Inserisci la password del tuo account Matrix per confermare"; "secrets_reset_reset_action" = "Reimposta"; "secrets_reset_warning_message" = "Ricomincerai senza cronologia, messaggi, dispositivi o utenti fidati."; "secrets_reset_warning_title" = "Se reimposti tutto"; @@ -1597,3 +1597,35 @@ "poll_edit_form_update_failure_subtitle" = "Riprova"; "poll_edit_form_update_failure_title" = "Aggiornamento del sondaggio fallito"; "poll_edit_form_poll_type" = "Tipo sondaggio"; +"location_sharing_post_failure_subtitle" = "%@ non ha potuto rilevare la tua posizione. Riprova più tardi."; +"location_sharing_post_failure_title" = "Non siamo riusciti ad inviare la tua posizione"; +"home_context_menu_leave" = "Esci"; +"home_context_menu_normal_priority" = "Priorità normale"; +"home_context_menu_low_priority" = "Bassa priorità"; +"home_context_menu_unfavourite" = "Rimuovi dai preferiti"; +"home_context_menu_favourite" = "Preferito"; +"home_context_menu_unmute" = "Riattiva audio"; +"home_context_menu_mute" = "Silenzioso"; +"home_context_menu_notifications" = "Notifiche"; +"home_context_menu_make_room" = "Sposta in Stanze"; +"home_context_menu_make_dm" = "Sposta in Persone"; +"event_formatter_message_deleted" = "Messaggio eliminato"; +"settings_labs_enable_threads" = "Messaggi in conversazioni"; +"message_from_a_thread" = "Da una conversazione"; +"threads_empty_show_all_threads" = "Mostra tutte le conversazioni"; +"threads_empty_tip" = "Consiglio: tocca un messaggio e usa “Conversazione” per iniziarne una."; +"threads_empty_info_my" = "Rispondi ad una conversazione in corso o tocca un messaggio e usa “Conversazione” per iniziarne una nuova."; +"threads_empty_info_all" = "Le conversazioni ti aiutano a tenere le tue discussioni in tema e rintracciabili."; +"threads_empty_title" = "Tieni le discussioni organizzate in conversazioni"; +"threads_action_my_threads" = "Le mie conversazioni"; +"threads_action_all_threads" = "Tutte le conversazioni"; +"threads_title" = "Conversazioni"; +"thread_copy_link_to_thread" = "Copia link nella conversazione"; + +// MARK: Threads +"room_thread_title" = "Conversazione"; +"room_accessibility_thread_more" = "Altro"; +"room_accessibility_threads" = "Conversazioni"; +"room_event_copy_link_info" = "Link copiato negli appunti."; +"room_event_action_reply_in_thread" = "Conversazione"; +"room_event_action_view_in_room" = "Vedi nella stanza"; From 828f5019014218b2b0f0b39a2cfc4af3d88164d3 Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Fri, 11 Feb 2022 15:54:02 +0000 Subject: [PATCH 051/188] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ --- Riot/Assets/pt_BR.lproj/Vector.strings | 74 ++++++++++++++++++-------- 1 file changed, 53 insertions(+), 21 deletions(-) diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index bc625d918..ac178a35a 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -50,7 +50,7 @@ "auth_optional_phone_placeholder" = "Número de telefone (opcional)"; "auth_phone_placeholder" = "Número de telefone"; "auth_repeat_password_placeholder" = "Repetir senha"; -"auth_repeat_new_password_placeholder" = "Confirmar sua nova senha"; +"auth_repeat_new_password_placeholder" = "Confirme a nova senha de sua conta Matrix"; "auth_home_server_placeholder" = "URL (e.g. https://matrix.org)"; "auth_identity_server_placeholder" = "URL (e.g. https://vector.im)"; "auth_invalid_login_param" = "Nome de usuária(o) e/ou senha incorretos"; @@ -71,7 +71,7 @@ "auth_untrusted_id_server" = "O servidor de identidade não é confiado"; "auth_password_dont_match" = "Senhas não correspondem"; "auth_username_in_use" = "Nome de usuária(o) em uso"; -"auth_forgot_password" = "Esqueceu senha?"; +"auth_forgot_password" = "Esqueceu senha de conta Matrix?"; "auth_email_not_found" = "Falha para enviar email: Este endereço de email não foi encontrado"; "auth_use_server_options" = "Usar opções de servidor personalizadas (avançado)"; "auth_email_validation_message" = "Por favor cheque seu email para continuar registro"; @@ -79,14 +79,14 @@ "auth_msisdn_validation_message" = "Nós temos enviado um SMS com um código de ativação. Por favor entre este código abaixo."; "auth_msisdn_validation_error" = "Incapaz de verificar número de telefone."; "auth_recaptcha_message" = "Este servidorcasa gostaria de assegurar que você não é um robô"; -"auth_reset_password_message" = "Para resettar sua senha, entre o endereço de email linkado a sua conta:"; +"auth_reset_password_message" = "Para resettar a senha de sua conta Matrix, entre o endereço de email linkado a sua conta:"; "auth_reset_password_missing_email" = "O email linkado à sua conta deve ser entrado."; "auth_reset_password_missing_password" = "Uma nova senha deve ser entrada."; "auth_reset_password_email_validation_message" = "Um email tem sido enviado para %@. Uma vez que você tenha seguido o link que ele contém, clique abaixo."; "auth_reset_password_next_step_button" = "Eu tenho verificado meu endereço de email"; "auth_reset_password_error_unauthorized" = "Falha para verificar endereço de email: assegure que você clicou no link no email"; "auth_reset_password_error_not_found" = "Seu endereço de email não parece estar associado com uma ID Matrix neste servidorcasa."; -"auth_reset_password_success_message" = "Sua senha tem sido resettada.\n\nVocê tem sido feito logout de todas as sessões e não vai mais receber notificações push. Para re-habilitar notificações, refaça login em cada dispositivo."; +"auth_reset_password_success_message" = "A senha de sua conta Matrix tem sido resettada.\n\nVocê tem sido feito logout de todas as sessões e não vai mais receber notificações push. Para re-habilitar notificações, refaça login em cada dispositivo."; "auth_add_email_and_phone_warning" = "Registro com email e número de telefone ao mesmo tempo não é suportado ainda até que a api exista. Somente o número de telefone vai ser levado em conta. Você pode adicionar seu email a seu perfil em ajustes."; "room_creation_appearance" = "Aparência"; "room_creation_appearance_name" = "Nome"; @@ -105,7 +105,7 @@ "room_recents_people_section" = "PESSOAS"; "room_recents_conversations_section" = "SALAS"; "room_recents_no_conversation" = "Nenhuma sala"; -"room_recents_low_priority_section" = "BAIXA PRIORIDADE"; +"room_recents_low_priority_section" = "PRIORIDADE BAIXA"; "room_recents_invites_section" = "CONVITES"; "room_recents_start_chat_with" = "Começar chat"; "room_recents_create_empty_room" = "Criar sala"; @@ -224,7 +224,7 @@ "room_event_action_redact" = "Remover"; "room_event_action_more" = "Mais"; "room_event_action_share" = "Compartilhar"; -"room_event_action_permalink" = "Permalink"; +"room_event_action_permalink" = "Copiar link para mensagem"; "room_event_action_view_source" = "Visualizar Fonte"; "room_event_action_view_decrypted_source" = "Visualizar Fonte Decriptada"; "room_event_action_report" = "Reportar conteúdo"; @@ -347,12 +347,12 @@ "settings_send_crash_report" = "Enviar dados de cash & uso anon"; "settings_enable_rageshake" = "Agitar com raiva para reportar bug"; "settings_clear_cache" = "Limpar cache"; -"settings_change_password" = "Mudar senha"; +"settings_change_password" = "Mudar senha de conta Matrix"; "settings_old_password" = "senha antiga"; "settings_new_password" = "senha nova"; "settings_confirm_password" = "confirmar senha"; -"settings_fail_to_update_password" = "Falha para atualizar senha"; -"settings_password_updated" = "Sua senha tem sido atualizada"; +"settings_fail_to_update_password" = "Falha para atualizar senha de conta Matrix"; +"settings_password_updated" = "A senha de sua conta Matrix tem sido atualizada"; "settings_crypto_device_name" = "Nome de sessão: "; "settings_crypto_device_id" = "\nID de sessão: "; "settings_crypto_device_key" = "\nChave de sessão:\n"; @@ -366,7 +366,7 @@ "room_details_room_name" = "Nome de Sala"; "room_details_topic" = "Tópico"; "room_details_favourite_tag" = "Favoritar"; -"room_details_low_priority_tag" = "Baixa prioridade"; +"room_details_low_priority_tag" = "Prioridade baixa"; "room_details_mute_notifs" = "Mutar notificações"; "room_details_direct_chat" = "Chat Direto"; "room_details_access_section" = "Quem pode acessar esta sala?"; @@ -550,7 +550,7 @@ "deactivate_account_forget_messages_information_part3" = ": isto vai causar usuárias/os futuras/os terem uma visualização incompleta de conversas)"; "deactivate_account_validate_action" = "Desativar conta"; "deactivate_account_password_alert_title" = "Desativar Conta"; -"deactivate_account_password_alert_message" = "Para continuar, por favor entre sua senha"; +"deactivate_account_password_alert_message" = "Para continuar, por favor entre a senha de sua conta Matrix"; // Re-request confirmation dialog "rerequest_keys_alert_title" = "Requisição Enviada"; "rerequest_keys_alert_message" = "Por favor lance %@ num outro dispositivo que possa decriptar a mensagem para que ele possa enviar as chaves para esta sessão."; @@ -600,7 +600,7 @@ "key_backup_setup_intro_manual_export_info" = "(Avançada)"; "key_backup_setup_intro_manual_export_action" = "Exportar chaves manualmente"; "key_backup_setup_passphrase_title" = "Assegure seu backup com uma Frase de Segurança"; -"key_backup_setup_passphrase_info" = "Nós vamos armazenar uma cópia encriptada de suas chaves em nosso servidor. Proteja seu backup com uma frase para mantê-lo seguro.\n\nPara segurança máxima, esta deveria ser diferente da senha de sua conta."; +"key_backup_setup_passphrase_info" = "Nós vamos armazenar uma cópia encriptada de suas chaves em nosso servidor. Proteja seu backup com uma frase para mantê-lo seguro.\n\nPara segurança máxima, esta deveria ser diferente da senha de sua conta Matrix."; "key_backup_setup_passphrase_passphrase_title" = "Entrar"; "key_backup_setup_passphrase_passphrase_placeholder" = "Entrar frase"; "key_backup_setup_passphrase_passphrase_valid" = "Ótimo!"; @@ -667,7 +667,7 @@ "settings_calls_stun_server_fallback_description" = "Permitir servidor fallback de assistência de chamadas %@ quando seu servidorcasa não oferece um (seu endereço de IP seria compartilhado durante uma chamada)."; "security_settings_blacklist_unverified_devices" = "Nunca enviar mensagens para sessões não-confiadas"; "security_settings_blacklist_unverified_devices_description" = "Verificar todas as sessões de um/uma usuário(a) para marcá-las como confiadas e enviar mensagens para ele/ela."; -"security_settings_user_password_description" = "Confirme sua identidade ao entrar a senha de sua conta"; +"security_settings_user_password_description" = "Confirme sua identidade ao entrar a senha de sua conta Matrix"; // Manage session "manage_session_title" = "Gerenciar sessão"; "manage_session_name" = "Nome de sessão"; @@ -740,7 +740,7 @@ "key_verification_scan_confirmation_scanning_device_waiting_other" = "Esperando por outro dispositivo…"; "user_verification_start_waiting_partner" = "Esperando por %@…"; "settings_devices_description" = "O nome público de uma sessão é visível para pessoas com quem você se comunica"; -"security_settings_crypto_sessions_description_2" = "Se você não reconhece um login, mude sua senha e resette Backup Seguro."; +"security_settings_crypto_sessions_description_2" = "Se você não reconhece um login, mude a senha de sua conta Matrix e resette Backup Seguro."; "security_settings_export_keys_manually" = "Exportar chaves manualmente"; "identity_server_settings_change" = "Mudar"; "identity_server_settings_alert_change_title" = "Mudar servidor de identidade"; @@ -771,7 +771,7 @@ "user_verification_session_details_verify_action_current_user_manually" = "Verificar Manualmente por Texto"; "user_verification_session_details_verify_action_other_user" = "Verificar manualmente"; "auth_add_email_phone_message_2" = "Defina um email para recuperação de conta. Use depois email ou telefone para ser opcionalmente descobertável por pessoas que conhecem você."; -"auth_email_is_required" = "Nenhum servidor de identidade está configurado então você não pode adicionar um endereço de email a fim de resettar sua senha no futuro."; +"auth_email_is_required" = "Nenhum servidor de identidade está configurado então você não pode adicionar um endereço de email a fim de resettar a senha de sua conta Matrix no futuro."; "auth_softlogout_clear_data_message_1" = "Aviso: Seus dados pessoais (incluindo chaves de encriptação) ainda estão armazenados neste dispositivo."; "auth_softlogout_clear_data_sign_out" = "Fazer signout"; "room_creation_error_invite_user_by_email_without_identity_server" = "Nenhum servidor de identidade está configurado então você não pode adicionar um/uma participante com um email."; @@ -818,9 +818,9 @@ // Accessibility "accessibility_checkbox_label" = "checkbox"; "auth_add_phone_message_2" = "Defina um número de telefone, e depois para ser opcionalmente descobertável por pessoas que conhecem você."; -"auth_phone_is_required" = "Nenhum servidor de identidade está configurado então você não pode adicionar um número de telefone a fim de resettar sua senha no futuro."; -"auth_forgot_password_error_no_configured_identity_server" = "Nenhum servidor de identidade está configurado: adicione um para resettar sua senha."; -"auth_reset_password_error_is_required" = "Nenhum servidor de identidade está configurado: adicione um em opções de servidor para resettar sua senha."; +"auth_phone_is_required" = "Nenhum servidor de identidade está configurado então você não pode adicionar um número de telefone a fim de resettar a senha de sua conta Matrix no futuro."; +"auth_forgot_password_error_no_configured_identity_server" = "Nenhum servidor de identidade está configurado: adicione um para resettar a senha de sua conta Matrix."; +"auth_reset_password_error_is_required" = "Nenhum servidor de identidade está configurado: adicione um em opções de servidor para resettar a senha de sua conta Matrix."; "auth_softlogout_signed_out" = "Você está com signout feito"; "auth_softlogout_sign_in" = "Fazer Signin"; "auth_softlogout_recover_encryption_keys" = "Faça signin para recuperar chaves de encriptação armazenadas exclusivamente neste dispositivo. Você precisa delas para ler todas suas mensagens seguras em qualquer dispositivo."; @@ -853,7 +853,7 @@ "settings_three_pids_management_information_part2" = "Descoberta"; "settings_labs_message_reaction" = "Reagir a mensagens com emoji"; "settings_add_3pid_password_title_msidsn" = "Adicionar número de telefone"; -"settings_add_3pid_password_message" = "Para continuar, por favor entre sua senha"; +"settings_add_3pid_password_message" = "Para continuar, por favor entre a senha de sua conta Matrix"; "settings_add_3pid_invalid_password_message" = "Credenciais inválidas"; "settings_key_backup_button_connect" = "Conectar esta sessão a Backup de Chave"; "settings_discovery_no_identity_server" = "Você não está atualmente usando um servidor de identidade. Para ser descobertável por contatos existentes, adicione um."; @@ -1121,7 +1121,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Imprima-a e armazene-a em algum lugar seguro\n✓ Salve-a em uma chave USB ou drive de backup \n✓ Copie-a para seu armazenamento nuvem pessoal"; "secrets_setup_recovery_passphrase_title" = "Definir uma Frase de Segurança"; "secrets_setup_recovery_passphrase_information" = "Entre uma frase de segurança que só você conheça, usada para assegurar segredos em seu servidor."; -"secrets_setup_recovery_passphrase_additional_information" = "Não use a senha de sua conta."; +"secrets_setup_recovery_passphrase_additional_information" = "Não use a senha de sua conta Matrix."; "secrets_setup_recovery_passphrase_confirm_information" = "Entre sua Frase de Segurança de novo para confirmá-la."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Confirmar"; "secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Confirmar frase"; @@ -1212,7 +1212,7 @@ "more" = "Mais"; "switch" = "Trocar"; "joined" = "Juntou-Se"; -"secrets_reset_authentication_message" = "Entre a senha de sua conta para confirmar"; +"secrets_reset_authentication_message" = "Entre a senha de sua conta Matrix para confirmar"; "secrets_reset_reset_action" = "Resettar"; "secrets_reset_warning_message" = "Você vai recomeçar com nada de histórico, mensagens, dispositivos confiados ou usuárias(os) confiadas(os)."; "secrets_reset_warning_title" = "Se você resettar tudo"; @@ -1594,3 +1594,35 @@ "poll_edit_form_update_failure_subtitle" = "Por favor tente de novo"; "poll_edit_form_update_failure_title" = "Falha para atualizar sondagem"; "poll_edit_form_poll_type" = "Tipo de sondagem"; +"location_sharing_post_failure_subtitle" = "%@ não conseguiu enviar sua localização. Por favor tente de novo mais tarde."; +"location_sharing_post_failure_title" = "Nós não conseguimos enviar sua localização"; +"home_context_menu_leave" = "Sair"; +"home_context_menu_normal_priority" = "Prioridade normal"; +"home_context_menu_low_priority" = "Prioridade baixa"; +"home_context_menu_unfavourite" = "Remover de Favoritos"; +"home_context_menu_favourite" = "Favoritar"; +"home_context_menu_unmute" = "Desmutar"; +"home_context_menu_mute" = "Mutar"; +"home_context_menu_notifications" = "Notificações"; +"home_context_menu_make_room" = "Mover para Salas"; +"home_context_menu_make_dm" = "Mover para Pessoas"; +"event_formatter_message_deleted" = "Mensagem deletada"; +"settings_labs_enable_threads" = "Mensageria com threads"; +"message_from_a_thread" = "De uma thread"; +"threads_empty_show_all_threads" = "Mostrar todas as threads"; +"threads_empty_tip" = "Dica: Toque numa mensagem e use “Thread” para começar uma."; +"threads_empty_info_my" = "Responda a uma thread acontecendo ou toque numa mensagem e use “Thread” para começar uma nova."; +"threads_empty_info_all" = "Threads ajudam manter suas conversas em-tópico e fáceis de rastrear."; +"threads_empty_title" = "Mantenha discussões organizadas com threads"; +"threads_action_my_threads" = "Minhas threads"; +"threads_action_all_threads" = "Todas as threads"; +"threads_title" = "Threads"; +"thread_copy_link_to_thread" = "Copiar link para thread"; + +// MARK: Threads +"room_thread_title" = "Thread"; +"room_accessibility_thread_more" = "Mais"; +"room_accessibility_threads" = "Threads"; +"room_event_copy_link_info" = "Link copiado para clipboard."; +"room_event_action_reply_in_thread" = "Thread"; +"room_event_action_view_in_room" = "Visualizar em sala"; From be5fc58da77e232b6add33ae819ee488fca0817b Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Wed, 9 Feb 2022 13:19:10 +0000 Subject: [PATCH 052/188] Translated using Weblate (Ukrainian) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ --- Riot/Assets/uk.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/uk.lproj/Vector.strings b/Riot/Assets/uk.lproj/Vector.strings index dd0e93cac..d3fa52880 100644 --- a/Riot/Assets/uk.lproj/Vector.strings +++ b/Riot/Assets/uk.lproj/Vector.strings @@ -50,7 +50,7 @@ "auth_optional_phone_placeholder" = "Номер телефону (необов'язково)"; "auth_phone_placeholder" = "Номер телефону"; "auth_repeat_password_placeholder" = "Повторіть пароль"; -"auth_repeat_new_password_placeholder" = "Підтвердьте новий пароль"; +"auth_repeat_new_password_placeholder" = "Підтвердьте новий пароль облікового запису Matrix"; "auth_home_server_placeholder" = "URL (наприклад, https://matrix.org)"; "auth_identity_server_placeholder" = "URL (наприклад, https://vector.im)"; "auth_invalid_login_param" = "Неправильне ім'я користувача або пароль"; @@ -71,7 +71,7 @@ "auth_untrusted_id_server" = "Сервер облікових даних не довірений"; "auth_password_dont_match" = "Паролі не збігаються"; "auth_username_in_use" = "Ім'я користувача зайняте"; -"auth_forgot_password" = "Забули пароль?"; +"auth_forgot_password" = "Забули пароль облікового запису Matrix?"; "auth_email_not_found" = "Не вдалося надіслати лист: Таку адресу е-пошти не знайдено"; "auth_use_server_options" = "Власні налаштування сервера"; "auth_email_validation_message" = "Перевірте свою пошту для продовження реєстрації"; @@ -79,7 +79,7 @@ "auth_msisdn_validation_message" = "Ми надіслали СМС із кодом активації. Введіть цей код унизу."; "auth_msisdn_validation_error" = "Не вдалося перевірити номер телефону."; "auth_recaptcha_message" = "Цей домашній сервер бажає переконатися, що ви не робот"; -"auth_reset_password_message" = "Щоб відновити пароль, введіть адресу е-пошти, пов'язану з вашим обліковим записом:"; +"auth_reset_password_message" = "Щоб відновити пароль облікового запису Matrix, введіть адресу е-пошти, пов'язану з вашим обліковим записом:"; "auth_reset_password_missing_email" = "Необхідно ввести адресу е-пошти, пов'язану з вашим обліковим записом."; // String for App Store "store_short_description" = "Захищений, децентралізований чат/VoIP"; @@ -89,16 +89,16 @@ "auth_add_email_message_2" = "Вкажіть е-пошту для відновлення облікового запису, а також для можливості знаходження вас іншими користувачами."; "auth_add_phone_message_2" = "Вкажіть номер телефону для можливості знаходження вас іншими користувачами."; "auth_add_email_phone_message_2" = "Вкажіть е-пошту для відновлення облікового запису. Використовуйте електронну пошту чи номер телефону для можливості знаходження вас іншими користувачами."; -"auth_email_is_required" = "Ідентифікаційний сервер не налаштовано, тому ви не можете додати адресу електронної пошти, щоб мати можливість відновити пароль в майбутньому."; -"auth_phone_is_required" = "Ідентифікаційний сервер не налаштовано, тому ви не можете додати номер телефону, щоб мати можливість відновити пароль в майбутньому."; -"auth_forgot_password_error_no_configured_identity_server" = "Ідентифікаційний сервер не налаштовано: додайте його, щоб мати можливість відновити пароль в майбутньому."; +"auth_email_is_required" = "Сервер ідентифікації не налаштовано, тому ви не можете додати адресу електронної пошти, щоб мати можливість відновити пароль облікового запису Matrix у майбутньому."; +"auth_phone_is_required" = "Сервер ідентифікації не налаштовано, тому ви не можете додати номер телефону, щоб мати можливість відновити пароль облікового запису Matrix у майбутньому."; +"auth_forgot_password_error_no_configured_identity_server" = "Сервер ідентифікації не налаштовано: додайте його, щоб мати можливість відновити пароль облікового запису Matrix у майбутньому."; "auth_reset_password_missing_password" = "Необхідно ввести новий пароль."; "auth_reset_password_email_validation_message" = "На адресу %@ надіслано лист. Після переходу за посиланням в листі, натисніть внизу."; "auth_reset_password_next_step_button" = "Я підтверджую свою адресу е-пошти"; "auth_reset_password_error_unauthorized" = "Не вдалося перевірити е-пошту: переконайтеся, що ви перейшли за посиланням у листі"; "auth_reset_password_error_not_found" = "Схоже, ваша адреса електронної пошти не пов'язана з жодним Matrix ID на цьому домашньому сервері."; -"auth_reset_password_error_is_required" = "Ідентифікаційний сервер не налаштовано: додайте його в параметрах сервера, щоб мати можливість відновити пароль в майбутньому."; -"auth_reset_password_success_message" = "Ваш пароль було скинуто.\n\nСеанс входу завершено на всіх сесіях і припинено отримання push-сповіщень. Щоб активувати сповіщення, виконайте вхід з новим паролем на кожному пристрої."; +"auth_reset_password_error_is_required" = "Сервер ідентифікації не налаштовано: додайте його у параметрах сервера, щоб мати можливість відновити пароль облікового запису Matrix у майбутньому."; +"auth_reset_password_success_message" = "Ваш пароль облікового запису Matrix було скинуто.\n\nСеанс входу завершено у всіх сеансах і припинено отримання push-сповіщень. Щоб активувати сповіщення, увійдіть з новим паролем на кожному пристрої."; "auth_add_email_and_phone_warning" = "Реєстрація за допомогою електронної пошти і номера телефону водночас не підтримується, доки немає API. Лише номер телефону буде додано до облікового запису. Ви можете додати електронну пошту до свого профілю в налаштуваннях."; "auth_accept_policies" = "Ознайомтесь та прийміть правила цього домашнього сервера:"; "auth_softlogout_signed_out" = "Ви вийшли"; @@ -231,7 +231,7 @@ "settings_enable_push_notif" = "Сповіщення на цьому пристрої"; "settings_fail_to_update_profile" = "Не вдалося оновити профіль"; "settings_night_mode" = "Нічний режим"; -"settings_change_password" = "Змінити пароль"; +"settings_change_password" = "Змінити пароль облікового запису Matrix"; "settings_add_phone_number" = "Додати номер телефону"; "settings_phone_number" = "Телефон"; "settings_add_email_address" = "Додати адресу е-пошти"; @@ -832,8 +832,8 @@ "settings_add_3pid_password_title_msidsn" = "Додати номер телефону"; "settings_device_notifications" = "Сповіщення пристрою"; "settings_add_3pid_password_title_email" = "Додати адресу е-пошти"; -"settings_password_updated" = "Пароль оновлено"; -"settings_fail_to_update_password" = "Не вдалося оновити пароль"; +"settings_password_updated" = "Пароль облікового запису Matrix оновлено"; +"settings_fail_to_update_password" = "Не вдалося оновити пароль облікового запису Matrix"; "settings_confirm_password" = "підтвердити пароль"; "settings_new_password" = "новий пароль"; "settings_old_password" = "старий пароль"; @@ -862,8 +862,8 @@ "settings_crypto_device_id" = "\nID сеансу: "; "settings_crypto_device_name" = "Назва сеансу: "; "settings_add_3pid_invalid_password_message" = "Хибні облікові дані"; -"settings_add_3pid_password_message" = "Щоб продовжити, введіть пароль"; -"deactivate_account_password_alert_message" = "Щоб продовжити, введіть пароль"; +"settings_add_3pid_password_message" = "Щоб продовжити, введіть пароль облікового запису Matrix"; +"deactivate_account_password_alert_message" = "Щоб продовжити, введіть пароль облікового запису Matrix"; // Deactivate account @@ -970,7 +970,7 @@ "room_event_action_report" = "Поскаржитися на вміст"; "room_event_action_view_decrypted_source" = "Переглянути розшифроване джерело"; "room_event_action_view_source" = "Переглянути джерело"; -"room_event_action_permalink" = "Постійне посилання"; +"room_event_action_permalink" = "Скопіювати посилання на повідомлення"; "room_event_action_forward" = "Переслати"; "room_resend_unsent_messages" = "Повторно надіслати не надіслані повідомлення"; "room_prompt_cancel" = "скасувати всі"; @@ -1034,7 +1034,7 @@ // AuthenticatedSessionViewControllerFactory "authenticated_session_flow_not_supported" = "Цей застосунок не підтримує способу входу, доступного на вашому домашньому сервері."; -"security_settings_user_password_description" = "Підтвердьте свою особу, ввівши пароль свого облікового запису"; +"security_settings_user_password_description" = "Підтвердьте свою особу, ввівши пароль свого облікового запису Matrix"; "security_settings_coming_soon" = "Вибачте, ця дія ще не доступна в %@ iOS. Якщо налаштуєте це іншим клієнтом Matrix, %@ iOS зможе також це використати."; "security_settings_complete_security_alert_message" = "Спершу слід доповнити захист вашого поточного сеансу."; "security_settings_blacklist_unverified_devices_description" = "Звірте всі сеанси користувача, щоб позначити його довіреним і надіслати йому повідомлення."; @@ -1043,7 +1043,7 @@ "security_settings_crosssigning_info_trusted" = "Перехресне підписування увімкнено. Ви можете робити інших користувачів і свої інші сеанси довіреними на підставі перехресного підпису, але ви не можете перехресно підписувати цим сеансом, бо в нього ще нема закритих ключів перехресного підписування. Доповніть захист цього сеансу."; "security_settings_crosssigning_info_exists" = "Ваш обліковий запис має ідентичність перехресного підписування, але вона ще не довірена цим сеансом. Доповніть захист цього сеансу."; "security_settings_secure_backup_description" = "Зробіть резервну копію своїх ключів шифрування й даних облікового запису на випадок втрати доступу до своїх сеансів. Ваші ключі будуть захищені унікальним ключем безпеки."; -"security_settings_crypto_sessions_description_2" = "Якщо не впізнаєте вхід, скиньте пароль і налаштування безпечного резервного копіювання."; +"security_settings_crypto_sessions_description_2" = "Якщо не впізнаєте сеанс, скиньте пароль облікового запису Matrix і налаштування безпечного резервного копіювання."; "settings_identity_server_no_is_description" = "Зараз ви не використовуєте сервер ідентифікації. Щоб знаходити наявні контакти й вони знаходили вас, додайте сервер угорі."; "settings_identity_server_description" = "Налаштований угорі сервер ідентифікації дає вам змогу знаходити людей за наявними контактами, а їм знаходити вас."; "settings_discovery_three_pid_details_information_phone_number" = "Керуйте параметрами для цього номера телефону, за яким інші користувачі можуть вас знаходити й запрошувати до кімнат. Додавайте й видаляйте номери в Облікових записах."; @@ -1109,7 +1109,7 @@ // Banner "cross_signing_setup_banner_title" = "Налаштування шифрування"; -"secrets_reset_authentication_message" = "Введіть пароль свого облікового запису, щоб продовжити"; +"secrets_reset_authentication_message" = "Введіть пароль свого облікового запису Matrix, щоб продовжити"; "security_settings_blacklist_unverified_devices" = "Ніколи не надсилати повідомлення не довіреним сеансам"; "security_settings_advanced" = "ДОДАТКОВО"; "security_settings_export_keys_manually" = "Експорт ключів вручну"; @@ -1357,7 +1357,7 @@ "secrets_setup_recovery_passphrase_title" = "Встановіть фразу безпеки"; "secrets_setup_recovery_passphrase_information" = "Введіть відому лише вам фразу безпеки для захисту таємниць на вашому сервері."; -"secrets_setup_recovery_passphrase_additional_information" = "Не застосовуйте пароль облікового запису повторно."; +"secrets_setup_recovery_passphrase_additional_information" = "Не застосовуйте пароль облікового запису Matrix повторно."; "secrets_setup_recovery_passphrase_confirm_information" = "Для підтвердження введіть таємну фразу ще раз."; "secure_key_backup_setup_existing_backup_error_title" = "Резервна копія повідомлень уже існує"; "secure_key_backup_setup_existing_backup_error_info" = "Розблокуйте її, щоб продовжити попереднє захищене резервне копіювання, або видаліть її, щоб почати захищене резервне копіювання повідомлень заново."; @@ -1590,7 +1590,7 @@ "key_backup_setup_intro_title" = "Ніколи не втрачайте зашифровані повідомлення"; "key_backup_setup_intro_info" = "Повідомлення в зашифрованих кімнатах захищені наскрізним шифруванням. Тільки ви та одержувачі маєте ключі для читання цих повідомлень.\n\nСтворіть захищену резервну копію ключів, щоб їх не втратити."; -"key_backup_setup_passphrase_info" = "Ми збережемо зашифровану копію ваших ключів на нашому сервері. Захистіть свою резервну копію парольною фразою.\n\nДля максимальної безпеки фраза повинна відрізнятися від пароля вашого облікового запису."; +"key_backup_setup_passphrase_info" = "Ми збережемо зашифровану копію ваших ключів на нашому сервері. Захистіть свою резервну копію парольною фразою.\n\nДля максимальної безпеки фраза повинна відрізнятися від пароля вашого облікового запису Matrix."; "key_backup_setup_passphrase_set_passphrase_action" = "Встановити фразу"; // MARK: Key backup recover @@ -1738,3 +1738,35 @@ "poll_edit_form_update_failure_subtitle" = "Повторіть спробу"; "poll_edit_form_update_failure_title" = "Не вдалося оновити опитування"; "poll_edit_form_poll_type" = "Тип опитування"; +"location_sharing_post_failure_subtitle" = "%@ не може отримати доступ до вашого місцеперебування. Повторіть спробу пізніше."; +"location_sharing_post_failure_title" = "Ми не можемо надіслати дані про ваше місцеперебування"; +"home_context_menu_leave" = "Вийти"; +"home_context_menu_normal_priority" = "Звичайна пріоритетність"; +"home_context_menu_low_priority" = "Неважливі"; +"home_context_menu_unfavourite" = "Вилучити з улюблених"; +"home_context_menu_favourite" = "Улюблені"; +"home_context_menu_unmute" = "Увімкнути звук"; +"home_context_menu_mute" = "Без звуку"; +"home_context_menu_notifications" = "Сповіщення"; +"home_context_menu_make_room" = "Перемістити на вкладку «Кімнати»"; +"home_context_menu_make_dm" = "Перемістити на вкладку «Люди»"; +"event_formatter_message_deleted" = "Повідомлення видалено"; +"settings_labs_enable_threads" = "Треди спілкування"; +"message_from_a_thread" = "З треду"; +"threads_empty_show_all_threads" = "Показати всі треди"; +"threads_empty_tip" = "Порада: Торкніться повідомлення та натисніть «Тред», щоб розпочати його."; +"threads_empty_info_my" = "Відповідайте у поточний тред або торкніться повідомлення та натисніть «Тред», щоб почати новий."; +"threads_empty_info_all" = "Треди допомагають підтримувати розмови за темою та за ними легко стежити."; +"threads_empty_title" = "Спілкуйтеся за темою в тредах"; +"threads_action_my_threads" = "Мої треди"; +"threads_action_all_threads" = "Усі треди"; +"threads_title" = "Треди"; +"thread_copy_link_to_thread" = "Копіювати посилання на тред"; + +// MARK: Threads +"room_thread_title" = "Тред"; +"room_accessibility_thread_more" = "Більше"; +"room_accessibility_threads" = "Треди"; +"room_event_copy_link_info" = "Посилання скопійовано до буфера обміну."; +"room_event_action_reply_in_thread" = "Тред"; +"room_event_action_view_in_room" = "Переглянути у кімнаті"; From 9543c8f2bf505821ca8b4f3d9986185c1f70e7ac Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 11 Feb 2022 20:15:45 +0000 Subject: [PATCH 053/188] Translated using Weblate (Swedish) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sv/ --- Riot/Assets/sv.lproj/Vector.strings | 163 ++++++++++++++++++++++++---- 1 file changed, 143 insertions(+), 20 deletions(-) diff --git a/Riot/Assets/sv.lproj/Vector.strings b/Riot/Assets/sv.lproj/Vector.strings index 88d35e629..5b2a7675f 100644 --- a/Riot/Assets/sv.lproj/Vector.strings +++ b/Riot/Assets/sv.lproj/Vector.strings @@ -47,7 +47,7 @@ "auth_optional_phone_placeholder" = "Telefonnummer (valfritt)"; "auth_phone_placeholder" = "Telefonnummer"; "auth_repeat_password_placeholder" = "Upprepa lösenord"; -"auth_repeat_new_password_placeholder" = "Bekräfta ditt lösenord"; +"auth_repeat_new_password_placeholder" = "Bekräfta ditt nya Matrixkontolösenord"; "auth_identity_server_placeholder" = "URL (t.ex. https://vector.im)"; "auth_invalid_login_param" = "Felaktigt användarnamn och/eller lösenord"; "auth_invalid_password" = "Lösenordet är för kort (minst 6 tecken)"; @@ -59,17 +59,17 @@ "auth_missing_email_or_phone" = "E-postadress eller telefonnummer saknas"; "auth_email_in_use" = "Den här e-postadressen är upptagen"; "auth_phone_in_use" = "Det här telefonnumret är upptaget"; -"auth_email_is_required" = "Ingen identitetsserver är konfigurerad, så du kan inte lägga till en e-postadress för att återställa ditt lösenord i framtiden."; -"auth_phone_is_required" = "Ingen identitetsserver är konfigurerad, så du kan inte lägga till ett telefonnummer för att återställa ditt lösenord i framtiden."; +"auth_email_is_required" = "Ingen identitetsserver är konfigurerad, så du kan inte lägga till en e-postadress för att återställa ditt Matrixkontolösenord i framtiden."; +"auth_phone_is_required" = "Ingen identitetsserver är konfigurerad, så du kan inte lägga till ett telefonnummer för att återställa ditt Matrixkontolösenord i framtiden."; "auth_password_dont_match" = "Lösenorden matchar inte"; "auth_username_in_use" = "Användarnamn upptaget"; -"auth_forgot_password" = "Glömt lösenordet?"; +"auth_forgot_password" = "Glömt Matrixkontolösenordet?"; "auth_email_not_found" = "Misslyckades att skicka e-post: Den här e-postadressen hittades inte"; "auth_use_server_options" = "Använd anpassade serveralternativ (avancerat)"; "auth_email_validation_message" = "Kolla din e-post för att fortsätta registreringen"; "auth_msisdn_validation_message" = "Vi har skickat ett SMS med en aktiveringskod. Ange den koden nedan."; "auth_msisdn_validation_error" = "Kunde inte verifiera telefonnummer."; -"auth_reset_password_message" = "För att återställa ditt lösenord, ange e-postadressen som är länkad till ditt konto:"; +"auth_reset_password_message" = "För att återställa ditt Matrixkontolösenord, ange e-postadressen som är länkad till ditt konto:"; "auth_reset_password_missing_email" = "Du måste ange e-postadressen som är länkad till ditt konto."; "auth_reset_password_missing_password" = "Ett nytt lösenord måste anges."; "auth_reset_password_email_validation_message" = "Ett e-brev har skickats till %@. När du har följt länken i det, tryck nedan."; @@ -204,7 +204,7 @@ "room_event_action_redact" = "Ta bort"; "room_event_action_more" = "Mer"; "room_event_action_share" = "Dela"; -"room_event_action_permalink" = "Permalänk"; +"room_event_action_permalink" = "Kopiera länk till meddelande"; "room_event_action_view_source" = "Visa källa"; "room_event_action_view_decrypted_source" = "Visa avkrypterad källa"; "room_event_action_report" = "Rapportera innehåll"; @@ -297,7 +297,7 @@ "settings_add_email_address" = "Lägg till e-postadress"; "settings_phone_number" = "Telefon"; "settings_add_phone_number" = "Lägg till telefonnummer"; -"settings_change_password" = "Ändra lösenord"; +"settings_change_password" = "Byt Matrixkontolösenord"; "settings_night_mode" = "Nattläge"; "settings_fail_to_update_profile" = "Misslyckades att uppdatera profil"; "settings_three_pids_management_information_part1" = "Hantera vilka e-postadresser eller telefonnummer som du kan använda för att logga in eller återfå ditt konto här. Kontrollera vilka som kan hitta dig i "; @@ -331,11 +331,11 @@ "settings_old_password" = "gammalt lösenord"; "settings_new_password" = "nytt lösenord"; "settings_confirm_password" = "bekräfta lösenord"; -"settings_fail_to_update_password" = "Misslyckades att uppdatera lösenord"; -"settings_password_updated" = "Ditt lösenord har uppdaterats"; +"settings_fail_to_update_password" = "Misslyckades att uppdatera Matrixkontolösenord"; +"settings_password_updated" = "Ditt Matrixkontolösenord har uppdaterats"; "settings_add_3pid_password_title_email" = "Lägg till e-postadress"; "settings_add_3pid_password_title_msidsn" = "Lägg till telefonnummer"; -"settings_add_3pid_password_message" = "För att fortsätta, ange ditt lösenord"; +"settings_add_3pid_password_message" = "För att fortsätta, ange ditt Matrixkontolösenord"; "settings_add_3pid_invalid_password_message" = "Ogiltiga uppgifter"; "settings_crypto_export" = "Exportera nycklar"; "settings_crypto_blacklist_unverified_devices" = "Kryptera endast till verifierade sessioner"; @@ -379,7 +379,7 @@ "security_settings_advanced" = "AVANCERAT"; "security_settings_blacklist_unverified_devices" = "Skicka aldrig meddelanden till obetrodda sessioner"; "security_settings_blacklist_unverified_devices_description" = "Verifiera en användares alla sessioner för att markera den som betrodd och skicka meddelanden till den."; -"security_settings_user_password_description" = "Bekräfta din identitet genom att ange ditt kontolösenord"; +"security_settings_user_password_description" = "Bekräfta din identitet genom att ange ditt Matrixkontolösenord"; // Manage session "manage_session_title" = "Hantera session"; "manage_session_info" = "SESSIONSINFO"; @@ -406,11 +406,11 @@ "auth_home_server_placeholder" = "URL (t.ex. https://matrix.org)"; "auth_invalid_user_name" = "Användarnamn får endast innehålla bokstäver, siffror, punkter, bindestreck och understreck"; "auth_add_email_message_2" = "Ställ in en e-postadress för kontoåterställning, och senare för att valfritt bli upptäckbar av personer som känner dig."; -"auth_forgot_password_error_no_configured_identity_server" = "Ingen identitetsserver är konfigurerad: lägg till en för att återställa ditt lösenord."; +"auth_forgot_password_error_no_configured_identity_server" = "Ingen identitetsserver är konfigurerad: lägg till en för att återställa ditt Matrixkontolösenord."; "auth_msisdn_validation_title" = "Avvaktar verifiering"; "auth_recaptcha_message" = "Den här hemservern vill kontrollera att du inte är en robot"; -"auth_reset_password_error_is_required" = "Ingen identitetsserver är konfigurerad: lägg till en i serveralternativen för att återställa ditt lösenord."; -"auth_reset_password_success_message" = "Ditt lösenord har återställts.\n\nDu har loggats ut från alla sessioner och kommer inte längre att ta emot pushnotiser. För att återaktivera pushnotiser, logga in igen på varje enhet."; +"auth_reset_password_error_is_required" = "Ingen identitetsserver är konfigurerad: lägg till en i serveralternativen för att återställa ditt Matrixkontolösenord."; +"auth_reset_password_success_message" = "Ditt Matrixkontolösenord har återställts.\n\nDu har loggats ut från alla sessioner och kommer inte längre att ta emot pushnotiser. För att återaktivera pushnotiser, logga in igen på varje enhet."; "auth_accept_policies" = "Granska och acceptera villkoren för denna hemserver:"; "auth_softlogout_reason" = "Admin hos din hemserver (%1$@) har loggat ut dig från ditt konto %2$@ (%3$@)."; "auth_softlogout_clear_data" = "Rensa personlig data"; @@ -653,7 +653,7 @@ "settings_discovery_three_pids_management_information_part3" = "."; "settings_identity_server_description" = "Med hjälp av identitetsservern som anges ovan kan du upptäcka och upptäckas av befintliga kontakter du känner."; "settings_identity_server_no_is_description" = "Du använder för närvarande inte en identitetsserver. För att upptäcka och bli upptäckt av befintliga kontakter du känner, lägg till en ovan."; -"security_settings_crypto_sessions_description_2" = "Om du inte känner igen en inloggning, ändra ditt lösenord och återställ säker säkerhetskopiering."; +"security_settings_crypto_sessions_description_2" = "Om du inte känner igen en inloggning, byt ditt Matrixkontolösenord och återställ säker säkerhetskopiering."; "security_settings_secure_backup" = "SÄKER SÄKERHETSKOPIERING"; "security_settings_secure_backup_description" = "Säkerhetskopiera dina nycklar med din kontodata ifall du förlorar åtkomst till dina sessioner. Dina nycklar kommer att säkras med en unik säkerhetsnyckel."; "security_settings_backup" = "MEDDELANDESÄKERHETSKOPIERING"; @@ -751,7 +751,7 @@ "deactivate_account_forget_messages_information_part3" = ": detta leder till att framtida användare kommer att se en ofullständig bild av konversationer)"; "deactivate_account_validate_action" = "Inaktivera konto"; "deactivate_account_password_alert_title" = "Inaktivera konto"; -"deactivate_account_password_alert_message" = "För att fortsätta, ange ditt lösenord"; +"deactivate_account_password_alert_message" = "För att fortsätta, ange ditt Matrixkontolösenord"; "rerequest_keys_alert_message" = "Starta %@ på en annan enhet som dekryptera meddelandet så att den kan skicka nycklarna till den här sessionen."; "secure_key_backup_setup_intro_use_security_key_title" = "Använd en säkerhetsnyckel"; "secure_key_backup_setup_intro_use_security_key_info" = "Generera en säkerhetsnyckel att lagra på en säker plats, exempelvis i en lösenordshanterare eller ett kassaskåp."; @@ -860,7 +860,7 @@ "key_backup_setup_intro_title" = "Bli aldrig av med krypterade meddelanden"; "key_backup_setup_intro_setup_action_without_existing_backup" = "Börja använda nyckelsäkerhetskopiering"; "key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Anslut den här enheten till nyckelsäkerhetskopiering"; -"key_backup_setup_passphrase_info" = "Vi kommer lagra en krypterad kopia av dina nycklar på vår server. Skydda din säkerhetskopia med en fras för att hålla den säker.\n\nFör maximal säkerhet bör denna skilja sig från ditt kontolösenord."; +"key_backup_setup_passphrase_info" = "Vi kommer lagra en krypterad kopia av dina nycklar på vår server. Skydda din säkerhetskopia med en fras för att hålla den säker.\n\nFör maximal säkerhet bör denna skilja sig från ditt Matrixkontokontolösenord."; "key_backup_setup_passphrase_setup_recovery_key_info" = "Eller säkra din säkerhetskopia med en säkerhetsnyckel och spara den någonstans säkert."; "key_backup_recover_invalid_passphrase" = "Säkerhetskopian kunde inte avkrypteras med den här frasen: vänligen kontrollera att du angav rätt säkerhetsfras."; "key_backup_recover_invalid_recovery_key_title" = "Säkerhetsnyckeln matchade inte"; @@ -1093,7 +1093,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Skriv ut den och förvara den säkert\n✓ Spara den på ett USB-minne eller säkerhetskopieringsenhet\n✓ Kopiera den till din personliga molnlagring"; "secrets_setup_recovery_passphrase_title" = "Sätt en säkerhetsfras"; "secrets_setup_recovery_passphrase_information" = "Ange en säkerhetsfras endast du känner till vilken används för att säkra hemligheter på din server."; -"secrets_setup_recovery_passphrase_additional_information" = "Använd inte ditt kontolösenord."; +"secrets_setup_recovery_passphrase_additional_information" = "Använd inte ditt Matrixkontolösenord."; "secrets_setup_recovery_passphrase_validate_action" = "Klart"; "secrets_setup_recovery_passphrase_confirm_information" = "Ange din säkerhetsfras igen för att bekräfta den."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Bekräfta"; @@ -1180,7 +1180,7 @@ "room_info_list_one_member" = "1 medlem"; "room_info_list_several_members" = "%@ medlemmar"; "room_info_list_section_other" = "Andra"; -"secrets_reset_authentication_message" = "Ange ditt kontolösenord för att bekräfta"; +"secrets_reset_authentication_message" = "Ange ditt Matrixkontolösenord för att bekräfta"; "secrets_reset_reset_action" = "Återställ"; "secrets_reset_warning_message" = "så kommer du att börja om utan historik, meddelanden, betrodda enheter eller betrodda användare."; "secrets_reset_information" = "Gör bara detta om du inte har någon annan enhet att verifiera den här enheten med."; @@ -1217,7 +1217,7 @@ "invite_friends_action" = "Bjud in vänner till %@"; "pin_protection_settings_change_pin" = "Byt PIN-kod"; -"pin_protection_confirm_pin_to_change" = "Bekräfta PIN-kod för att fortsätta"; +"pin_protection_confirm_pin_to_change" = "Bekräfta PIN-kod för att byta PIN-kod"; "bug_report_background_mode" = "Fortsätt i bakgrunden"; "social_login_button_title_sign_up" = "Skapa konto med %@"; "social_login_button_title_sign_in" = "Logga in med %@"; @@ -1468,3 +1468,126 @@ "leave_space_only_action" = "Lämna inga rum"; "leave_space_message_admin_warning" = "Du är admin för det här utrymmet, försäkra att du har överfört adminrättigheter till en annan medlem innan du lämnar."; "leave_space_message" = "Är du säker på att du vill lämna %@? Vill du även lämna alla rum och utrymmen i det här utrymmet?"; +"location_sharing_settings_toggle_title" = "Aktivera platsdelning"; +"location_sharing_settings_header" = "Platsdelning"; +"location_sharing_open_google_maps" = "Öppna i Google Maps"; +"location_sharing_open_apple_maps" = "Öppna i Apple Maps"; +"location_sharing_invalid_authorization_settings" = "Inställningar"; +"location_sharing_invalid_authorization_not_now" = "Inte nu"; +"location_sharing_invalid_authorization_error_title" = "%@ är inte behörig att komma åt din plats. Du kan aktivera åtkomst i Inställningar > Plats"; +"location_sharing_locating_user_error_title" = "%@ kunde inte komma åt din plats. Vänligen pröva igen senare."; +"location_sharing_loading_map_error_title" = "%@ kunde inte ladda kartan. Vänligen pröva igen senare."; +"location_sharing_post_failure_subtitle" = "%@ kunde inte skicka din plats. Vänligen pröva igen senare."; +"location_sharing_post_failure_title" = "Vi kunde inte skicka din plats"; +"location_sharing_share_action" = "Dela"; +"location_sharing_close_action" = "Stäng"; + +// MARK: - Location sharing + +"location_sharing_title" = "Plats"; +"poll_timeline_not_closed_subtitle" = "Vänligen pröva igen"; +"poll_timeline_not_closed_title" = "Misslyckades att avsluta omröstning"; +"poll_timeline_vote_not_registered_subtitle" = "Tyvärr registrerades inte din röst, vänligen pröva igen"; +"poll_timeline_vote_not_registered_title" = "Röst registrerades inte"; +"poll_timeline_total_final_results" = "Slutgiltigt resultat baserat på %lu röst"; +"poll_timeline_total_final_results_one_vote" = "Slutgiltigt resultat baserat på 1 röst"; +"poll_timeline_total_votes_not_voted" = "%lu röster avgivna. Rösta för att se resultatet"; +"poll_timeline_total_one_vote_not_voted" = "1 röst avgiven. Rösta för att se resultatet"; +"poll_timeline_total_votes" = "%lu röster avgivna"; +"poll_timeline_total_one_vote" = "1 röst avgiven"; +"poll_timeline_total_no_votes" = "Inga röster avgivna"; +"poll_timeline_votes_count" = "%lu röster"; +"poll_timeline_one_vote" = "1 röst"; +"poll_edit_form_poll_type_closed_description" = "Resultat avslöjas när du avslutar omröstningen"; +"poll_edit_form_poll_type_closed" = "Sluten omröstning"; +"poll_edit_form_poll_type_open_description" = "Röstare ser resultat så fort de har röstat"; +"poll_edit_form_poll_type_open" = "Öppna omröstning"; +"poll_edit_form_update_failure_subtitle" = "Vänligen pröva igen"; +"poll_edit_form_update_failure_title" = "Misslyckades att uppdatera omröstning"; +"poll_edit_form_post_failure_subtitle" = "Vänligen pröva igen"; +"poll_edit_form_post_failure_title" = "Misslyckades att lägga upp omröstning"; +"poll_edit_form_add_option" = "Lägg till alternativ"; +"poll_edit_form_option_number" = "Alternativ %lu"; +"poll_edit_form_create_options" = "Skapa alternativ"; +"poll_edit_form_input_placeholder" = "Skriv något"; +"poll_edit_form_question_or_topic" = "Fråga eller ämne"; +"poll_edit_form_poll_question_or_topic" = "Omröstningens fråga eller ämne"; +"poll_edit_form_poll_type" = "Omröstningstyp"; + +// Mark: - Polls + +"poll_edit_form_create_poll" = "Skapa omröstning"; +"home_context_menu_leave" = "Lämna"; +"home_context_menu_normal_priority" = "Normal prioritet"; +"home_context_menu_low_priority" = "Låg prioritet"; +"home_context_menu_unfavourite" = "Ta bort från favoriter"; +"home_context_menu_favourite" = "Favoritmarkera"; +"home_context_menu_unmute" = "Avtysta"; +"home_context_menu_mute" = "Tysta"; +"home_context_menu_notifications" = "Aviseringar"; +"home_context_menu_make_room" = "Flytta till rum"; +"home_context_menu_make_dm" = "Flytta till personer"; +"share_extension_send_now" = "Skicka nu"; +"share_extension_low_quality_video_message" = "Skicka i %@ för bättre kvalité, eller skicka i låg kvalité nedan."; +"share_extension_low_quality_video_title" = "Video kommer skickas i låg kvalité"; +"analytics_prompt_stop" = "Sluta dela"; +"analytics_prompt_yes" = "Ja, det är okej"; +"analytics_prompt_not_now" = "Inte ny"; +"analytics_prompt_point_3" = "Du kan stänga av det här när som helst i inställningarna"; +/* Note: The word "don't" is formatted in bold */ +"analytics_prompt_point_2" = "Vi delar inte någon information med tredje parter"; +/* Note: The word "don't" is formatted in bold */ +"analytics_prompt_point_1" = "Vi spelar inte in eller profilerar någon kontodata"; +"analytics_prompt_terms_link_upgrade" = "här"; +/* Note: The placeholder is for the contents of analytics_prompt_terms_link_upgrade */ +"analytics_prompt_terms_upgrade" = "Läs alla våra villkor %@. Är det OK?"; +"analytics_prompt_terms_link_new_user" = "här"; +/* Note: The placeholder is for the contents of analytics_prompt_terms_link_new_user */ +"analytics_prompt_terms_new_user" = "Du kan läsa alla våra villkor %@."; +"analytics_prompt_message_upgrade" = "Du har tidigare gått med på att dela anonym användningsdata med oss. Nu, för att hjälpa oss att förstå hur folk använder multipla enheter, så kommer vi att generera en slumpmässig identifierare som delas mellan dina enheter."; +"analytics_prompt_message_new_user" = "Hjälp oss att identifiera problem och förbättra %@ genom att dela anonym användningsdata. För att förstå hur personer använder multipla enheter så kommer vi att generera en slumpmässig identifierare som delas mellan dina enheter."; + +// Analytics +"analytics_prompt_title" = "Hjälp till att förbättra %@"; +"event_formatter_message_deleted" = "Meddelande raderat"; +"settings_enable_room_message_bubbles" = "Meddelandebubblor"; +"settings_discovery_accept_terms" = "Acceptera identitetsserverns villkor"; +"settings_analytics_and_crash_data" = "Skicka krasch- och analysdata"; +"settings_labs_enable_threads" = "Trådade meddelanden"; +"settings_labs_enabled_polls" = "Omröstningar"; +"settings_about" = "OM"; +"message_from_a_thread" = "Från en tråd"; +"threads_empty_show_all_threads" = "Visa alla trådar"; +"threads_empty_tip" = "Tips: Tryck på ett meddelande och använd “Tråd” för att starta en."; +"threads_empty_info_my" = "Svara på en pågående tråd eller tryck på ett meddelande och använd “Tråd” för att starta en ny."; +"threads_empty_info_all" = "Trådar hjälper till att hålla dina konversationer till ämnet och lätta att följa."; +"threads_empty_title" = "Håll diskussioner organiserade med trådar"; +"threads_action_my_threads" = "Mina trådar"; +"threads_action_all_threads" = "Alla trådar"; +"threads_title" = "Trådar"; +"thread_copy_link_to_thread" = "Kopiera länk till tråd"; + +// MARK: Threads +"room_thread_title" = "Tråd"; +"room_accessibility_thread_more" = "Mer"; +"room_accessibility_threads" = "Trådar"; +"room_event_copy_link_info" = "Länk kopierad till klippbordet."; +"room_event_action_reply_in_thread" = "Tråd"; +"room_event_action_view_in_room" = "Visa i rum"; +"room_event_action_end_poll" = "Avsluta omröstning"; +"room_event_action_remove_poll" = "Ta bort omröstning"; +"onboarding_splash_page_4_message" = "Element är också bra för arbetsplatser. Den är betrodd av världens säkraste organisationer."; +"onboarding_splash_page_4_title_no_pun" = "Meddelanden för ditt team."; +"onboarding_splash_page_3_message" = "Totalsträckskrypterad och inget telefonnummer krävs. Ingen reklam eller datainsamling."; +"onboarding_splash_page_3_title" = "Säkra meddelanden."; +"onboarding_splash_page_2_message" = "Välj vart dina konversationer lagras, vilket ger dig kontroll och självständighet. Ansluter via Matrix."; +"onboarding_splash_page_2_title" = "Du har kontrollen."; +"onboarding_splash_page_1_message" = "Säker och oberoende kommunikation som ger dig samma sekretessnivå som en personlig konversation i dit eget hem."; +"onboarding_splash_page_1_title" = "Äg dina konversationer."; +"onboarding_splash_login_button_title" = "Jag har redan ett konto"; + +// Onboarding +"onboarding_splash_register_button_title" = "Skapa konto"; +"accessibility_button_label" = "knapp"; +"ok" = "OK"; +"enable" = "Aktivera"; From 513c209f8730a7ae7c98d03d79f0c68436ec19f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 9 Feb 2022 14:05:12 +0000 Subject: [PATCH 054/188] Translated using Weblate (Estonian) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ --- Riot/Assets/et.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index 77da3b78c..172becd1e 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -53,7 +53,7 @@ "auth_optional_phone_placeholder" = "Telefoninumber (kui soovid)"; "auth_phone_placeholder" = "Telefoninumber"; "auth_repeat_password_placeholder" = "Korda salasõna"; -"auth_repeat_new_password_placeholder" = "Korda uut salasõna"; +"auth_repeat_new_password_placeholder" = "Korda uut Matrix'i konto salasõna"; "auth_home_server_placeholder" = "URL (näiteks https://matrix.org)"; "auth_identity_server_placeholder" = "URL (näiteks https://vector.im)"; "auth_invalid_login_param" = "Vigane kasutajanimi ja/või salasõna"; @@ -70,13 +70,13 @@ "auth_missing_email_or_phone" = "E-posti aadress või telefoninumber on puudu"; "auth_email_in_use" = "See e-posti aadress on juba kasutusel"; "auth_phone_in_use" = "See telefoninumber on juba kasutusel"; -"auth_email_is_required" = "Ühtegi isikutuvastusserverit pole seadistatud ning sul ei ole võimalik lisada oma e-posti aadressi hilisemaks võimalikuks salasõna muutmiseks."; -"auth_phone_is_required" = "Ühtegi isikutuvastusserverit pole seadistatud ning sul ei ole võimalik lisada oma telefoninumbrit hilisemaks võimalikuks salasõna muutmiseks."; +"auth_email_is_required" = "Ühtegi isikutuvastusserverit pole seadistatud ning sul ei ole võimalik lisada oma e-posti aadressi hilisemaks võimalikuks Matrix'i konto salasõna muutmiseks."; +"auth_phone_is_required" = "Ühtegi isikutuvastusserverit pole seadistatud ning sul ei ole võimalik lisada oma telefoninumbrit hilisemaks võimalikuks Matrix'i konto salasõna muutmiseks."; "auth_untrusted_id_server" = "See isikutuvastusserver pole usaldusväärne"; "auth_password_dont_match" = "Salasõnad ei klapi omavahel"; "auth_username_in_use" = "Selline kasutajanimi on juba olemas"; -"auth_forgot_password" = "Kas unustasid oma salasõna?"; -"auth_forgot_password_error_no_configured_identity_server" = "Ühtegi isikutuvastusserverit pole seadistatud: salasõna taastamiseks määra see."; +"auth_forgot_password" = "Kas unustasid oma Matrix'i konto salasõna?"; +"auth_forgot_password_error_no_configured_identity_server" = "Ühtegi isikutuvastusserverit pole seadistatud: Matrix'i konto salasõna taastamiseks määra see."; "auth_email_not_found" = "E-kirja saatmine ei õnnestunud: sellist e-posti aadressi ei leidu"; "auth_use_server_options" = "Kohandatud serveriseadistused"; "auth_email_validation_message" = "Registreerimise jätkamiseks palun vaata oma e-posti"; @@ -84,15 +84,15 @@ "auth_msisdn_validation_message" = "Me oleme SMS'iga saatnud aktiveerimiskoodi. Palun sisesta see kood siia."; "auth_msisdn_validation_error" = "Telefoninumbri verifitseerimine ei õnnestunud."; "auth_recaptcha_message" = "See server soovib kindlaks teha, et sa ei ole robot"; -"auth_reset_password_message" = "Salasõna taastamiseks sisesta sinu kontoga seotud e-posti aadress:"; +"auth_reset_password_message" = "Matrix'i konto salasõna taastamiseks sisesta sinu kontoga seotud e-posti aadress:"; "auth_reset_password_missing_email" = "Sa pead sisestama oma kontoga seotud e-posti aadressi."; "auth_reset_password_missing_password" = "Palun sisesta uus salasõna."; "auth_reset_password_email_validation_message" = "Saatsime e-kirja %@ aadressile. Kui oled avanud selles kirjas leidunud lingi, siis palun vajuta järgnevat nuppu."; "auth_reset_password_next_step_button" = "Ma olen teinud läbi oma e-posti aadressi kontrolli"; "auth_reset_password_error_unauthorized" = "E-posti aadressi kontrollimine ei õnnestunud: palun vaata, et sa kindlasti klõpsisid saabunud kirjas olnud viidet"; "auth_reset_password_error_not_found" = "Sinu e-posti aadress ei tundu olema selles koduserveris seotud Matrixi kasutajatunnusega."; -"auth_reset_password_error_is_required" = "Ühtegi isikutuvastusserverit pole seadistatud: salasõna taastamiseks määra see serveri sätetes."; -"auth_reset_password_success_message" = "Sinu salasõna on vahetatud. \n \nSa oled välja logitud kõikidest oma seni kasutusel olnud sessioonidest ega saa enam teateid ega sõnumeid. Nende uuesti lugemiseks palun logi igas seadmes tagasi Matrix'i võrku."; +"auth_reset_password_error_is_required" = "Ühtegi isikutuvastusserverit pole seadistatud: Matrix'i konto salasõna taastamiseks määra see serveri sätetes."; +"auth_reset_password_success_message" = "Sinu Matrix'i konto salasõna on vahetatud. \n \nSa oled välja logitud kõikidest oma seni kasutusel olnud sessioonidest ega saa enam teateid ega sõnumeid. Nende uuesti lugemiseks palun logi igas seadmes tagasi Matrix'i võrku."; "auth_add_email_and_phone_warning" = "Registreerimine kasutades korraga nii e-posti aadressi kui ka telefoninumbrit ei ole senise API versiooni puhul veel võimalik. Hetkel läheb arvesse vaid telefoninumber. Sa võid hiljem lisada e-posti aadressi oma kasutajaprofiili seadetest."; "auth_accept_policies" = "Palun vaata üle kõik selle koduserveri kasutustingimused ja nõustu nendega:"; "auth_autodiscover_invalid_response" = "Vigane koduserveri tuvastamise päringu vastus"; @@ -209,7 +209,7 @@ "deactivate_account_forget_messages_information_part2_emphasize" = "Hoiatus"; "deactivate_account_validate_action" = "Kas eemaldame selle konto kasutusest"; "deactivate_account_password_alert_title" = "Eemalda konto"; -"deactivate_account_password_alert_message" = "Jätkamiseks palun sisesta oma salasõna"; +"deactivate_account_password_alert_message" = "Jätkamiseks palun sisesta oma Matrix'i konto salasõna"; "auth_login_single_sign_on" = "Logi sisse"; // Room recents "room_recents_directory_section" = "JUTUTUBADE LOEND"; @@ -251,7 +251,7 @@ "room_event_action_redact" = "Eemalda"; "room_event_action_more" = "Veel"; "room_event_action_share" = "Jaga"; -"room_event_action_permalink" = "Püsiviide"; +"room_event_action_permalink" = "Kopeeri link sõnumisse"; "room_event_action_view_source" = "Vaata lähtekoodi"; "room_event_action_view_decrypted_source" = "Näita dekrüptitud lähtekoodi"; "room_event_action_report" = "Teata kahtlasest sisust"; @@ -487,7 +487,7 @@ "settings_add_email_address" = "Lisa e-posti aadress"; "settings_phone_number" = "Telefon"; "settings_add_phone_number" = "Lisa telefoninumber"; -"settings_change_password" = "Muuda salasõna"; +"settings_change_password" = "Muuda Matrix'i konto salasõna"; "settings_fail_to_update_profile" = "Profiili uuendamine ei õnnestunud"; "settings_global_settings_info" = "Üldised teavituste seadistused leiduvad sinu %@ veebikliendis"; "settings_pin_rooms_with_missed_notif" = "Klammerda jututoad, kus leidub lugemata teavitusi"; @@ -524,11 +524,11 @@ "settings_old_password" = "vana salasõna"; "settings_new_password" = "uus salasõna"; "settings_confirm_password" = "korda uut salasõna"; -"settings_fail_to_update_password" = "Salasõna uuendamine ei õnnestunud"; -"settings_password_updated" = "Sinu salasõna on muudetud"; +"settings_fail_to_update_password" = "Matrix'i konto salasõna uuendamine ei õnnestunud"; +"settings_password_updated" = "Sinu Matrix'i konto salasõna on muudetud"; "settings_add_3pid_password_title_email" = "Lisa e-posti aadress"; "settings_add_3pid_password_title_msidsn" = "Lisa telefoninumber"; -"settings_add_3pid_password_message" = "Jätkamiseks palun sisesta oma salasõna"; +"settings_add_3pid_password_message" = "Jätkamiseks palun sisesta oma Matrix'i konto salasõna"; "settings_add_3pid_invalid_password_message" = "Vigane kasutajanimi või salasõna"; "settings_crypto_device_name" = "Sessiooni nimi: "; "settings_crypto_device_id" = "\nSessiooni tunnus: "; @@ -537,7 +537,7 @@ "settings_crypto_blacklist_unverified_devices" = "Kasuta krüptimist vaid verifitseeritud sessioonides"; "settings_deactivate_my_account" = "Eemalda minu konto kasutusest"; "security_settings_crypto_sessions_loading" = "Laadin sessioone…"; -"security_settings_user_password_description" = "Tuvasta oma isik sisestades salasõna"; +"security_settings_user_password_description" = "Tuvasta oma isik sisestades Matrix'i konto salasõna"; // Manage session "manage_session_title" = "Halda sessiooni"; "manage_session_info" = "SESSIOONI TEAVE"; @@ -766,7 +766,7 @@ // Security settings "security_settings_title" = "Turvalisus"; "security_settings_crypto_sessions" = "MINU SESSIOONID"; -"security_settings_crypto_sessions_description_2" = "Kui sa ei tunne ära mõnda oma sisselogimissessiooni, siis muuda ära oma salasõna ja tee võtmetest uus turvaline varukoopia."; +"security_settings_crypto_sessions_description_2" = "Kui sa ei tunne ära mõnda oma sisselogimissessiooni, siis muuda ära oma Matrix'i konto salasõna ja tee võtmetest uus turvaline varukoopia."; "security_settings_secure_backup" = "TURVALINE VARUNDUS"; "security_settings_secure_backup_description" = "Selleks puhuks, kui sa kaotad ligipääsu kõikidele oma sessioonidele, tee varukoopia oma krüptovõtmetest ja kasutajakonto seadistustest. Unikaalse turvavõtmega tagad selle, et sinu varukoopia on kaitstud."; "security_settings_secure_backup_setup" = "Võta kasutusele"; @@ -794,7 +794,7 @@ "key_backup_setup_intro_manual_export_info" = "(Lisaseadistused)"; "key_backup_setup_intro_manual_export_action" = "Ekspordi võtmed käsitsi"; "key_backup_setup_passphrase_title" = "Krüpti oma varukoopia turvafraasiga"; -"key_backup_setup_passphrase_info" = "Me salvestame krüptitud varukoopia sinu krüptovõtmetest meie serveris. Tagamaks, et keegi ei saa seda kasutada, krüpti varukoopia paroolifraasiga.\n\n Parima turvalisuse jaoks peaks paroolifraas olema erinev sinu konto salasõnast."; +"key_backup_setup_passphrase_info" = "Me salvestame krüptitud varukoopia sinu krüptovõtmetest meie serveris. Tagamaks, et keegi ei saa seda kasutada, krüpti varukoopia paroolifraasiga.\n\n Parima turvalisuse jaoks peaks paroolifraas olema erinev sinu Matrix'i konto salasõnast."; "key_backup_setup_passphrase_passphrase_title" = "Sisesta"; "key_backup_setup_passphrase_passphrase_placeholder" = "Sisesta paroolifraas"; "key_backup_setup_passphrase_passphrase_valid" = "Tore!"; @@ -1057,7 +1057,7 @@ "secrets_setup_recovery_key_storage_alert_message" = "✓ Trüki välja ja hoia turvalises kohas\n✓ Salvesta ta mälupulgale või välisele kõvakattale\n✓ Kopeeri ta sinu isiklikku salvestusruumi mõnes andmepilves"; "secrets_setup_recovery_passphrase_title" = "Määra turvafraas"; "secrets_setup_recovery_passphrase_information" = "Andmete kaitsmiseks sinu koduserveris sisesta turvafraas, mida vaid sina tead."; -"secrets_setup_recovery_passphrase_additional_information" = "Palun ära kasuta selleks oma tavalist konto salasõna."; +"secrets_setup_recovery_passphrase_additional_information" = "Palun ära kasuta selleks oma Matrix'i konto salasõna."; "secrets_setup_recovery_passphrase_validate_action" = "Valmis"; "secrets_setup_recovery_passphrase_confirm_information" = "Kinnituseks sisesta turvafraas uuesti."; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Kinnita"; @@ -1181,7 +1181,7 @@ "room_details_advanced_e2e_encryption_enabled_for_dm" = "Krüptimine on selles jututoas kasutusel"; "room_details_advanced_e2e_encryption_disabled_for_dm" = "Krüptimine ei ole selles jututoas kasutusel."; "pin_protection_kick_user_alert_message" = "Liiga palju vigu PIN-koodi sisestamisel ning sa oled nüüd välja logitud"; -"secrets_reset_authentication_message" = "Kinnitamaks seda muudatust, sisesta oma konto salasõna"; +"secrets_reset_authentication_message" = "Kinnitamaks seda muudatust, sisesta oma Matrix'i konto salasõna"; "secrets_reset_reset_action" = "Taasta algolek"; "secrets_reset_warning_message" = "Siis alustad nii, et kadunud on ajalugu, sõnumid ning usaldatud seadmed ja kasutajad."; "secrets_reset_warning_title" = "Kui sa alustad kõigega algusest"; @@ -1563,3 +1563,35 @@ "poll_edit_form_update_failure_subtitle" = "Palun proovi uuesti"; "poll_edit_form_update_failure_title" = "Küsitluse muutmine ei õnnestunud"; "poll_edit_form_poll_type" = "Küsitluse tüüp"; +"location_sharing_post_failure_subtitle" = "%@ ei saanud sinu asukohta edastada. Palun proovi hiljem uuesti."; +"location_sharing_post_failure_title" = "Sinu asukoha saatmine ei õnnestunud"; +"home_context_menu_leave" = "Lahku"; +"home_context_menu_normal_priority" = "Tavalise tähtsusega"; +"home_context_menu_low_priority" = "Vähetähtis"; +"home_context_menu_unfavourite" = "Eemalda lemmikute hulgast"; +"home_context_menu_favourite" = "Lemmik"; +"home_context_menu_unmute" = "Eemalda summutamine"; +"home_context_menu_mute" = "Summuta"; +"home_context_menu_notifications" = "Teavitused"; +"home_context_menu_make_dm" = "Tõsta otsevestluste alla"; +"home_context_menu_make_room" = "Tõsta jututubade alla"; +"event_formatter_message_deleted" = "Sõnum on kustutatud"; +"settings_labs_enable_threads" = "Sõnumid jutulõngana"; +"message_from_a_thread" = "Jutulõngast"; +"threads_empty_show_all_threads" = "Näita kõiki jutulõngasid"; +"threads_empty_tip" = "Soovitus: uue jutulõnga alustamiseks klõpsi sõnumit ja vali „Jutulõng“."; +"threads_empty_info_my" = "Vasta olemasolevasse jutulõnga või uue jutulõnga alustamiseks klõpsi sõnumit ja vali „Jutulõng“."; +"threads_empty_info_all" = "Jutulõngad aitavad hoida vestlused teemakohastena ning mugavalt loetavatena."; +"threads_empty_title" = "Halda vestlusi jutulõngadena"; +"threads_action_my_threads" = "Minu jutulõngad"; +"threads_action_all_threads" = "Kõik jutulõngad"; +"threads_title" = "Jutulõngad"; +"thread_copy_link_to_thread" = "Kopeeri jutulõnga link"; + +// MARK: Threads +"room_thread_title" = "Jutulõng"; +"room_accessibility_thread_more" = "Veel"; +"room_accessibility_threads" = "Jutulõngad"; +"room_event_copy_link_info" = "Link on kopeeritud lõikelauale."; +"room_event_action_reply_in_thread" = "Jutulõng"; +"room_event_action_view_in_room" = "Vaata jututoas"; From 378687833fccc5f2f7ab6bc67073d0d62ab6ef70 Mon Sep 17 00:00:00 2001 From: Linerly Date: Thu, 10 Feb 2022 05:52:56 +0000 Subject: [PATCH 055/188] Translated using Weblate (Indonesian) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ --- Riot/Assets/id.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/id.lproj/Vector.strings b/Riot/Assets/id.lproj/Vector.strings index 28dd88f35..f1d9ec304 100644 --- a/Riot/Assets/id.lproj/Vector.strings +++ b/Riot/Assets/id.lproj/Vector.strings @@ -3,7 +3,7 @@ "auth_invalid_login_param" = "Nama pengguna dan/atau kata sandi tidak benar"; "auth_identity_server_placeholder" = "URL (contoh https://vector.im)"; "auth_home_server_placeholder" = "URL (contoh https://matrix.org)"; -"auth_repeat_new_password_placeholder" = "Konfirmasi kata sandi baru Anda"; +"auth_repeat_new_password_placeholder" = "Konfirmasi kata sandi akun Matrix baru Anda"; "auth_repeat_password_placeholder" = "Ulangi kata sandi"; "auth_phone_placeholder" = "Nomor telepon"; "auth_optional_phone_placeholder" = "Nomor telepon (opsional)"; @@ -73,13 +73,13 @@ "auth_email_validation_message" = "Silakan periksa surel Anda untuk melanjutkan pendaftaran"; "auth_use_server_options" = "Gunakan opsi server khusus (lanjutan)"; "auth_email_not_found" = "Gagal mengirim surel: Alamat email ini tidak ditemukan"; -"auth_forgot_password_error_no_configured_identity_server" = "Tidak ada server identitas yang dikonfigurasikan: tambahkan satu untuk mengatur ulang kata sandi Anda."; -"auth_forgot_password" = "Lupa kata sandi?"; +"auth_forgot_password_error_no_configured_identity_server" = "Tidak ada server identitas yang dikonfigurasikan: tambahkan satu untuk mengatur ulang kata sandi akun Matrix Anda."; +"auth_forgot_password" = "Lupa kata sandi akun Matrix?"; "auth_username_in_use" = "Nama pengguna telah dipakai"; "auth_password_dont_match" = "Kata sandi tidak cocok"; "auth_untrusted_id_server" = "Server identitas tidak dipercaya"; -"auth_phone_is_required" = "Tidak ada server identitas yang dikonfigurasi sehingga Anda tidak dapat menambahkan nomor telepon untuk mengatur ulang kata sandi Anda di masa depan."; -"auth_email_is_required" = "Tidak ada server identitas yang dikonfigurasi sehingga Anda tidak dapat menambahkan alamat email untuk mengatur ulang kata sandi Anda di masa depan."; +"auth_phone_is_required" = "Tidak ada server identitas yang dikonfigurasi sehingga Anda tidak dapat menambahkan nomor telepon untuk mengatur ulang kata sandi akun Matrix Anda di masa depan."; +"auth_email_is_required" = "Tidak ada server identitas yang dikonfigurasi sehingga Anda tidak dapat menambahkan alamat email untuk mengatur ulang kata sandi akun Matrix Anda di masa depan."; "auth_phone_in_use" = "Nomor telepon ini sudah dipakai"; "auth_email_in_use" = "Surel ini sudah dipakai"; "auth_missing_email_or_phone" = "Tidak ada surel atau nomor telepon"; @@ -133,7 +133,7 @@ "settings_integrations_allow_button" = "Kelola integrasi"; "settings_enable_callkit" = "Panggilan yang diintegrasi"; "settings_night_mode" = "Mode Malam"; -"settings_change_password" = "Ubah kata sandi"; +"settings_change_password" = "Ubah kata sandi akun Matrix"; "settings_first_name" = "Nama Depan"; "settings_display_name" = "Nama Tampilan"; "settings_profile_picture" = "Gambar Profil"; @@ -498,7 +498,7 @@ "room_event_action_delete" = "Hapus"; "room_event_action_resend" = "Kirim Ulang"; "room_event_action_save" = "Simpan"; -"room_event_action_permalink" = "Tautan"; +"room_event_action_permalink" = "Salin tautan ke pesan"; "room_event_action_share" = "Bagikan"; "room_event_action_more" = "Lainnya"; "room_event_action_redact" = "Hapus"; @@ -595,14 +595,14 @@ "room_creation_account" = "Akun"; "social_login_list_title_sign_up" = "Atau"; "social_login_list_title_sign_in" = "Atau"; -"auth_reset_password_error_is_required" = "Tidak ada server identitas yang diatur: tambahkan di pengaturan server untuk mengatur ulang kata sandi Anda."; +"auth_reset_password_error_is_required" = "Tidak ada server identitas yang diatur: tambahkan di pengaturan server untuk mengatur ulang kata sandi akun Matrix Anda."; "auth_reset_password_error_not_found" = "Alamat email Anda terlihat tidak diasosiasikan dengan sebuah ID Matrix di homeserver ini."; "auth_reset_password_error_unauthorized" = "Gagal untuk memverifikasi alamat email: pastikan Anda membuka tautan yang ada di email"; "auth_reset_password_next_step_button" = "Saya telah memverifikasi alamat email saya"; "auth_reset_password_email_validation_message" = "Sebuah email telah dikirim ke %@. Setelah Anda membuka tautan yang ada, klik di bawah."; "auth_reset_password_missing_password" = "Sebuah kata sandi baru harus dimasukkan."; "auth_reset_password_missing_email" = "Alamat email yang tertaut dengan akun Anda harus dimasukkan."; -"auth_reset_password_message" = "Untuk mengatur ulang kata sandi Anda, masukkan alamat email yang tertaut ke akun Anda:"; +"auth_reset_password_message" = "Untuk mengatur ulang kata sandi akun Matrix Anda, masukkan alamat email yang tertaut ke akun Anda:"; "auth_recaptcha_message" = "Homeserver ini ingin memastikan bahwa Anda bukan sebuah robot"; "auth_msisdn_validation_error" = "Tidak dapat memverifikasi nomor telepon."; "auth_msisdn_validation_message" = "Kami telah mengirim sebuah SMS dengan kode aktivasi. Silakan masukkan kodenya di bawah."; @@ -696,7 +696,7 @@ "security_settings_blacklist_unverified_devices_description" = "Verifikasi semua sesi pengguna untuk menandainya sebagai terpercaya dan kirim pesan ke mereka."; "security_settings_crosssigning_info_exists" = "Akun Anda memiliki identitas penandatanganan silang, tetapi belum dipercayai oleh sesi ini. Selesaikan keamanan sesi ini."; "security_settings_secure_backup_description" = "Cadangkan kunci enkripsi Anda dengan data akun Anda untuk berjaga-jaga jika Anda kehilangan akses ke sesi Anda. Kunci Anda akan diamankan dengan Kunci Keamanan yang unik."; -"security_settings_crypto_sessions_description_2" = "Jika Anda tidak tahu sebuah login, ubah kata sandi Anda dan atur ulang Cadangan Aman."; +"security_settings_crypto_sessions_description_2" = "Jika Anda tidak tahu sebuah login, ubah kata sandi akun Matrix Anda dan atur ulang Cadangan Aman."; "settings_identity_server_no_is_description" = "Anda saat ini tidak menggunakan sebuah server identitas. Untuk menemukan dan dapat ditemukan oleh kontak yang Anda tahu, tambahkan satu di atas."; "settings_identity_server_description" = "Dengan menggunakan set server identitas di atas, Anda dapat menemukan dan dapat ditemukan oleh kontak yang ada yang Anda kenal."; "settings_discovery_three_pid_details_information_phone_number" = "Kelola preferensi untuk nomor telepon ini, yang dapat digunakan pengguna lain untuk menemukan Anda dan digunakan untuk mengundang Anda ke ruangan. Tambahkan atau hapus nomor telepon di Akun."; @@ -823,7 +823,7 @@ "room_details_access_section_anyone_apart_from_guest_for_dm" = "Siapa saja yang tahu linknya, selain dari tamu"; "identity_server_settings_alert_error_invalid_identity_server" = "%@ bukan server identitas yang valid."; "identity_server_settings_alert_no_terms_title" = "Server identitas tidak mempunyai kebijakan layanan"; -"security_settings_user_password_description" = "Konfirmasi identitas Anda dengan memasukkan kata sandi akun Anda"; +"security_settings_user_password_description" = "Konfirmasi identitas Anda dengan memasukkan kata sandi akun Matrix Anda"; "security_settings_secure_backup_info_valid" = "Sesi ini mencadangkan kunci Anda."; "version_check_modal_title_deprecated" = "Kami tidak mendukung iOS %@ lagi"; "version_check_modal_title_supported" = "Kami mengakhiri dukungan untuk iOS %@"; @@ -838,7 +838,7 @@ "voice_message_release_to_send" = "Tahan untuk merekam, lepaskan untuk mengirim"; "spaces_empty_space_title" = "Space ini belum ada ruangan"; "create_room_show_in_directory" = "Tampilkan ruangan di direktori"; -"secrets_reset_authentication_message" = "Masukkan kata sandi akun Anda untuk mengkonfirmasi"; +"secrets_reset_authentication_message" = "Masukkan kata sandi akun Matrix Anda untuk mengkonfirmasi"; "secrets_recovery_with_key_information_unlock_secure_backup_with_key" = "Masukkan Kunci Keamanan Anda untuk melanjutkan."; "secrets_recovery_with_key_information_unlock_secure_backup_with_phrase" = "Masukkan Frasa Keamanan Anda untuk melanjutkan."; @@ -988,7 +988,7 @@ "settings_key_backup_info_progress_done" = "Semua kunci telah dicadangkan"; "settings_key_backup_info_progress" = "Mencadangkan %@ kunci…"; "settings_key_backup_info_version" = "Versi Cadangan Kunci: %@"; -"settings_fail_to_update_password" = "Gagal untuk memperbarui kata sandi"; +"settings_fail_to_update_password" = "Gagal untuk memperbarui kata sandi akun Matrix"; "settings_labs_enable_ringing_for_group_calls" = "Dering untuk panggilan grup"; "settings_enable_push_notif" = "Notifikasi di perangkat ini"; "settings_fail_to_update_profile" = "Gagal untuk memperbarui profil"; @@ -1418,7 +1418,7 @@ // Bug report "bug_report_title" = "Laporan Bug"; -"deactivate_account_password_alert_message" = "Untuk melanjutkan, mohon masukkan kata sandi Anda"; +"deactivate_account_password_alert_message" = "Untuk melanjutkan, mohon masukkan kata sandi akun Matrix Anda"; "widget_integration_must_be_in_room" = "Anda tidak berada di ruangan ini."; "settings_devices_description" = "Nama publik sesi dapat dilihat oleh orang yang berkomunikasi dengan Anda"; "settings_key_backup_delete_confirmation_prompt_msg" = "Apakah Anda yakin? Anda akan kehilangan pesan terenkripsi jika kunci Anda tidak dicadangkan secara benar."; @@ -1523,7 +1523,7 @@ "security_settings_crosssigning_info_not_bootstrapped" = "Penandatanganan silang belum disiapkan."; "settings_key_backup_button_connect" = "Hubungkan sesi ini ke Cadangan Kunci"; "settings_key_backup_info_trust_signature_valid_device_unverified" = "Cadangan memiliki tanda tangan dari %@"; -"settings_add_3pid_password_message" = "Untuk melanjutkan, mohon masukkan kata sandi Anda"; +"settings_add_3pid_password_message" = "Untuk melanjutkan, mohon masukkan kata sandi akun Matrix Anda"; "settings_send_crash_report" = "Kirim crash & data penggunaan anonim"; "secure_key_backup_setup_cancel_alert_message" = "Jika Anda membatalkan sekarang, Anda mungkin kehilangan pesan & data terenkripsi jika Anda kehilangan akses ke login Anda.\n\nAnda juga dapat mengatur Cadangan Aman & kelola kunci Anda di Pengaturan."; "room_participants_security_information_room_encrypted" = "Pesan di ruangan ini dienkripsi secara ujung-ke-ujung.\n\nPesan Anda diamankan dengan kunci dan hanya Anda dan penerima punya kunci uniknya untuk membukanya."; @@ -1539,7 +1539,7 @@ // Success from passphrase "key_backup_setup_success_from_passphrase_info" = "Kunci Anda sedang dicadangkan.\n\nKunci Keamanan Anda adalah jaring pengaman — Anda dapat menggunakannya untuk memulihkan akses ke pesan terenkripsi jika Anda lupa frasa sandi.\n\nSimpan Kunci Keamanan Anda di suatu tempat yang sangat aman, seperti pengelola kata sandi (atau brankas)."; -"key_backup_setup_passphrase_info" = "Kami akan menyimpan salinan terenkripsi dari kunci Anda di server kami. Lindungi cadangan Anda dengan frasa agar tetap aman.\n\nUntuk keamanan maksimum, ini harus berbeda dari kata sandi akun Anda."; +"key_backup_setup_passphrase_info" = "Kami akan menyimpan salinan terenkripsi dari kunci Anda di server kami. Lindungi cadangan Anda dengan frasa agar tetap aman.\n\nUntuk keamanan maksimum, ini harus berbeda dari kata sandi akun Matrix Anda."; "key_backup_setup_intro_info" = "Pesan di ruang terenkripsi diamankan dengan enkripsi ujung-ke-ujung. Hanya Anda dan penerima yang memiliki kunci untuk membaca pesan ini.\n\nCadangkan kunci Anda dengan aman untuk menghindari kehilangannya."; "deactivate_account_informations_part5" = "Jika Anda ingin kami melupakan pesan Anda, silakan centang kotak di bawah ini\n\nVisibilitas pesan di Matrix mirip dengan email. Kami melupakan pesan Anda berarti bahwa pesan yang telah Anda kirim tidak akan dibagikan dengan pengguna baru atau tidak terdaftar, tetapi pengguna terdaftar yang sudah memiliki akses ke pesan ini akan tetap memiliki akses ke salinannya."; "deactivate_account_informations_part1" = "Ini akan membuat akun Anda tidak dapat digunakan secara permanen. Anda tidak akan dapat masuk, dan tidak seorang pun dapat mendaftarkan ulang ID pengguna yang sama. Ini akan menyebabkan akun Anda meninggalkan semua ruangan yang diikutinya, dan akan menghapus detail akun Anda dari server identitas Anda. "; @@ -1552,7 +1552,7 @@ "unknown_devices_alert" = "Ruangan ini berisi sesi tidak dikenal yang belum diverifikasi.\nIni berarti tidak ada jaminan bahwa sesi tersebut adalah milik pengguna yang mereka klaim.\nKami menyarankan Anda memverifikasinya untuk setiap sesi sebelum melanjutkan, tetapi Anda dapat mengirim ulang pesan tanpa memverifikasi jika Anda mau."; "room_warning_about_encryption" = "Enkripsi ujung-ke-ujung masih dalam beta dan mungkin tidak dapat dihandalkan.\n\nAnda seharusnya tidak mempercayainya dulu untuk mengamankan data.\n\nPerangkat masih belum dapat mendekripsi riwayat sebelum mereka bergabung ke ruangannya.\n\nPesan terenkripsi masih belum terlihat di client yang belum mengimplementasikan enkripsi."; "auth_add_email_and_phone_warning" = "Pendaftaran dengan email dan nomor telepon sekaligus belum didukung sampai API-nya sudah ada. Hanya nomor telepon yang akan diperhitungkan. Anda dapat menambahkan email Anda di profil Anda di pengaturan."; -"auth_reset_password_success_message" = "Kata sandi Anda telah diatur ulang.\n\nAnda telah dikeluarkan dari semua sesi dan tidak akan menerima lagi notifikasi push. Untuk mengaktifkan ulang notifikasi, masuk ulang di setiap perangkat."; +"auth_reset_password_success_message" = "Kata sandi akun Matrix Anda telah diatur ulang.\n\nAnda telah dikeluarkan dari semua sesi dan tidak akan menerima lagi notifikasi push. Untuk mengaktifkan ulang notifikasi, masuk ulang di setiap perangkat."; "spaces_add_rooms_coming_soon_title" = "Penambahan ruangan akan segera datang"; "leave_space_and_all_rooms_action" = "Tinggalkan semua ruangan dan space"; "space_beta_announce_subtitle" = "Versi baru dari komunitas"; @@ -1562,7 +1562,7 @@ "pin_protection_confirm_pin_to_disable" = "Konfirmasi PIN untuk menonaktifkan PIN"; "pin_protection_choose_pin" = "Buat sebuah PIN untuk keamanan"; "cross_signing_setup_banner_subtitle" = "Verifikasi perangkat Anda yang lain dengan mudah"; -"secrets_setup_recovery_passphrase_additional_information" = "Jangan menggunakan kata sandi akun Anda."; +"secrets_setup_recovery_passphrase_additional_information" = "Jangan menggunakan kata sandi akun Matrix Anda."; "secrets_recovery_with_key_invalid_recovery_key_title" = "Tidak dapat mengakses penyimpanan rahasia"; "secrets_recovery_with_passphrase_invalid_passphrase_title" = "Tidak dapat mengakses penyimpanan rahasia"; @@ -1616,7 +1616,7 @@ "security_settings_crosssigning_info_ok" = "Penandatanganan silang siap dipakai."; "settings_discovery_error_message" = "Sebuah kesalahan terjadi. Mohon coba lagi."; "settings_crypto_blacklist_unverified_devices" = "Enkripsi ke sesi terverifikasi saja"; -"settings_password_updated" = "Kata sandi Anda telah diperbarui"; +"settings_password_updated" = "Kata sandi akun Matrix Anda telah diperbarui"; "settings_enable_rageshake" = "Rage shake untuk melaporkan bug"; // No VoIP support @@ -1742,3 +1742,35 @@ "poll_edit_form_update_failure_subtitle" = "Silakan coba lagi"; "poll_edit_form_update_failure_title" = "Gagal untuk memperbarui poll"; "poll_edit_form_poll_type" = "Tipe poll"; +"location_sharing_post_failure_subtitle" = "%@ tidak dapat mengirimkan lokasi Anda. Silakan coba lagi nanti."; +"location_sharing_post_failure_title" = "Kami tidak dapat mengirimkan lokasi Anda"; +"home_context_menu_leave" = "Tinggalkan"; +"home_context_menu_normal_priority" = "Prioritas normal"; +"home_context_menu_low_priority" = "Prioritas rendah"; +"home_context_menu_unfavourite" = "Hilangkan dari Favorit"; +"home_context_menu_favourite" = "Favorit"; +"home_context_menu_unmute" = "Hilangkan bisuan"; +"home_context_menu_mute" = "Bisukan"; +"home_context_menu_notifications" = "Notifikasi"; +"home_context_menu_make_room" = "Pindah ke Ruangan"; +"home_context_menu_make_dm" = "Pindah ke Orang"; +"event_formatter_message_deleted" = "Pesan dihapus"; +"settings_labs_enable_threads" = "Perpesanan utasan"; +"message_from_a_thread" = "Dari sebuah utasan"; +"threads_empty_show_all_threads" = "Tampilkan semua utasan"; +"threads_empty_tip" = "Tip: Ketuk pada sebuah pesan dan gunakan “Utasan” untuk memulai yang baru."; +"threads_empty_info_my" = "Balas ke utasan yang sedang terjadi atau ketuk pada sebuah pesan dan gunakan “Utasan” untuk memulai yang baru."; +"threads_empty_info_all" = "Utasan membantu membuat obrolan sesuai topik dan mudah untuk dilacak."; +"threads_empty_title" = "Buat diskusi tetap teratur dengan utasan"; +"threads_action_my_threads" = "Utasan saya"; +"threads_action_all_threads" = "Semua utasan"; +"threads_title" = "Utasan"; +"thread_copy_link_to_thread" = "Salin tautan ke utasan"; + +// MARK: Threads +"room_thread_title" = "Utasan"; +"room_accessibility_thread_more" = "Lainnya"; +"room_accessibility_threads" = "Utasan"; +"room_event_copy_link_info" = "Tautan disalin ke papan klip."; +"room_event_action_reply_in_thread" = "Utasan"; +"room_event_action_view_in_room" = "Tampilkan di ruangan"; From 097deb41bcaa2a61ef66b2482c1cf451207355c4 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Sat, 12 Feb 2022 15:24:59 +0000 Subject: [PATCH 056/188] Translated using Weblate (Slovak) Currently translated at 98.9% (1418 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ --- Riot/Assets/sk.lproj/Vector.strings | 106 +++++++++++++++++++--------- 1 file changed, 74 insertions(+), 32 deletions(-) diff --git a/Riot/Assets/sk.lproj/Vector.strings b/Riot/Assets/sk.lproj/Vector.strings index 99bee79d5..5f7977207 100644 --- a/Riot/Assets/sk.lproj/Vector.strings +++ b/Riot/Assets/sk.lproj/Vector.strings @@ -112,15 +112,15 @@ "auth_reset_password_email_validation_message" = "Na adresu %s bola odoslaná správa. Po kliknutí na odkaz, ktorý obsahuje, kliknite nižšie."; "auth_reset_password_missing_password" = "Musíte zadať nové heslo."; "auth_reset_password_missing_email" = "Musíte zadať emailovú adresu prepojenú s vašim účtom."; -"auth_reset_password_message" = "Ak chcete obnoviť vaše heslo, zadajte emailovú adresu prepojenú s vašim účtom:"; +"auth_reset_password_message" = "Ak chcete obnoviť vaše heslo k účtu Matrix, zadajte emailovú adresu prepojenú s vašim účtom:"; "auth_recaptcha_message" = "Tento domovský server by sa rád uistil, že nie ste robot"; "auth_msisdn_validation_error" = "Nie je možné overiť telefónne číslo."; "auth_msisdn_validation_message" = "Odoslali sme vám SMS správu, ktorá obsahuje overovací kód. Prosím, zadajte ho nižšie."; "auth_msisdn_validation_title" = "Čaká sa na overenie"; "auth_use_server_options" = "Použiť vlastné možnosti servera (pre pokročilých)"; "auth_email_not_found" = "Nepodarilo sa odoslať e-mail: Táto e-mailová adresa nebola nájdená"; -"auth_forgot_password_error_no_configured_identity_server" = "Nie je nastavený žiadny server identity: pridajte ho na obnovenie hesla."; -"auth_forgot_password" = "Zabudli ste heslo?"; +"auth_forgot_password_error_no_configured_identity_server" = "Nie je nastavený žiadny server identity: pridajte ho na obnovenie hesla k účtu Matrix."; +"auth_forgot_password" = "Zabudli ste heslo k účtu Matrix?"; "auth_username_in_use" = "Používateľské meno sa už používa"; "auth_password_dont_match" = "Heslá sa nezhodujú"; "auth_phone_in_use" = "Toto telefónne číslo sa už používa"; @@ -138,7 +138,7 @@ "auth_invalid_login_param" = "Nesprávne používateľské meno a/alebo heslo"; "auth_identity_server_placeholder" = "URL (napr. https://vector.im)"; "auth_home_server_placeholder" = "URL (napr. https://matrix.org)"; -"auth_repeat_new_password_placeholder" = "Potvrďte svoje nové heslo"; +"auth_repeat_new_password_placeholder" = "Potvrďte svoje nové heslo k účtu Matrix"; "auth_repeat_password_placeholder" = "Zopakovať heslo"; "auth_phone_placeholder" = "Telefónne číslo"; "auth_optional_phone_placeholder" = "Telefónne číslo (nepovinné)"; @@ -189,7 +189,7 @@ "settings_notifications_disabled_alert_title" = "Oznámenia vypnuté"; "settings_device_notifications" = "Oznámenia zariadenia"; "settings_night_mode" = "Nočný režim"; -"settings_change_password" = "Zmeniť heslo"; +"settings_change_password" = "Zmeniť heslo k účtu Matrix"; "settings_first_name" = "Krstné meno"; "settings_display_name" = "Zobrazované meno"; "settings_profile_picture" = "Profilový obrázok"; @@ -506,7 +506,7 @@ "room_event_action_delete" = "Vymazať"; "room_event_action_resend" = "Znovu odoslať"; "room_event_action_save" = "Uložiť"; -"room_event_action_permalink" = "Trvalý odkaz"; +"room_event_action_permalink" = "Kopírovať odkaz do správy"; "room_event_action_forward" = "Preposlať"; "room_event_action_share" = "Zdieľať"; "room_event_action_more" = "Viac"; @@ -533,10 +533,10 @@ "room_member_power_level_custom_in" = "Vlastné (%@) v %@"; "room_member_power_level_moderator_in" = "Moderátor v %@"; "room_member_power_level_admin_in" = "Správca v %@"; -"room_participants_security_information_room_encrypted_for_dm" = "Správy sú tu šifrované end-to-end.\n\nVaše správy sú zabezpečené zámkami a jedinečné kľúče na ich odomknutie máte len vy a príjemca."; -"room_participants_security_information_room_encrypted" = "Správy v tejto miestnosti sú šifrované end-to-end.\n\nVaše správy sú zabezpečené zámkami a jedinečné kľúče na ich odomknutie máte len vy a príjemca."; -"room_participants_security_information_room_not_encrypted" = "Správy v tejto miestnosti nie sú šifrované end-to-end (od vás až k príjemcovi)."; -"room_participants_security_information_room_not_encrypted_for_dm" = "Správy tu nie sú šifrované end-to-end (od vás až k príjemcovi)."; +"room_participants_security_information_room_encrypted_for_dm" = "Správy sú tu end-to-end šifrované.\n\nVaše správy sú zabezpečené zámkami a jedinečné kľúče na ich odomknutie máte len vy a príjemca."; +"room_participants_security_information_room_encrypted" = "Správy v tejto miestnosti sú end-to-end šifrované.\n\nVaše správy sú zabezpečené zámkami a jedinečné kľúče na ich odomknutie máte len vy a príjemca."; +"room_participants_security_information_room_not_encrypted" = "Správy v tejto miestnosti nie sú end-to-end šifrované (od vás až k príjemcovi)."; +"room_participants_security_information_room_not_encrypted_for_dm" = "Správy tu nie sú end-to-end šifrované (od vás až k príjemcovi)."; "room_participants_security_loading" = "Načítavanie…"; "room_participants_action_security_status_loading" = "Načítavanie…"; "room_participants_action_security_status_warning" = "Upozornenie"; @@ -584,7 +584,7 @@ "directory_cell_title" = "Prezrieť priečinok"; "receipt_status_read" = "Prečítané: "; "room_details_files" = "Nahrané súbory"; -"settings_ui_theme_auto" = "Automaticky"; +"settings_ui_theme_auto" = "Automatický"; // Success from passphrase "key_backup_setup_success_from_passphrase_info" = "Vaše kľúče sa zálohujú.\n\nVáš bezpečnostný kľúč je bezpečnostná sieť - môžete ho použiť na obnovenie prístupu k zašifrovaným správam, ak zabudnete svoju prístupovú frázu.\n\nBezpečnostný kľúč uchovávajte na veľmi bezpečnom mieste, napríklad v správcovi hesiel (alebo v trezore)."; @@ -619,7 +619,7 @@ "event_formatter_call_has_ended" = "Hovor ukončený"; // Image picker -"image_picker_action_camera" = "Urobiť fotografiu"; +"image_picker_action_camera" = "Spraviť fotku"; "group_participants_invite_malformed_id_title" = "Chyba pozvania"; "group_participants_leave_prompt_title" = "Opustiť skupinu"; @@ -729,7 +729,7 @@ // Re-request confirmation dialog "rerequest_keys_alert_title" = "Žiadosť odoslaná"; -"deactivate_account_password_alert_message" = "Aby ste mohli pokračovať, prosím zadajte svoje heslo"; +"deactivate_account_password_alert_message" = "Aby ste mohli pokračovať, prosím zadajte svoje heslo k účtu Matrix"; "deactivate_account_password_alert_title" = "Deaktivovať účet"; "deactivate_account_validate_action" = "Deaktivovať účet"; "deactivate_account_informations_part2_emphasize" = "Táto akcia je nezvratná."; @@ -901,13 +901,13 @@ "room_creation_wait_for_creation" = "Miestnosť sa už vytvára. Počkajte, prosím."; "room_creation_make_public_prompt_msg" = "Ste si istí, že chcete túto konverzáciu zverejniť? Ktokoľvek si môže prečítať vaše správy a pripojiť sa ku konverzácii."; "social_login_button_title_sign_in" = "Prihlásiť sa s %@"; -"auth_reset_password_error_is_required" = "Nie je nastavený žiadny server identity: pridajte ho v možnostiach servera a obnovte heslo."; +"auth_reset_password_error_is_required" = "Nie je nastavený žiadny server identity: pridajte ho v možnostiach servera a obnovte heslo k účtu Matrix."; "security_settings_crosssigning_info_trusted" = "Krížové podpisovanie je povolené. Na základe krížového podpisovania môžete dôverovať iným používateľom a ostatným reláciám, ale nemôžete krížovo podpisovať z tejto relácie, pretože nemá súkromné kľúče na krížové podpisovanie. Dokončite zabezpečenie tejto relácie."; "manage_session_sign_out" = "Odhlásiť sa z tejto relácie"; "security_settings_crosssigning_info_ok" = "Krížové podpisovanie je pripravené na použitie."; "settings_discovery_error_message" = "Vyskytla sa chyba. Prosím, skúste to znova."; "settings_crypto_blacklist_unverified_devices" = "Šifrovať len overeným reláciám"; -"settings_password_updated" = "Vaše heslo bolo aktualizované"; +"settings_password_updated" = "Vaše heslo k účtu Matrix bolo aktualizované"; "settings_notifications_disabled_alert_message" = "Ak chcete povoliť upozornenia, prejdite do nastavení zariadenia."; "settings_enable_push_notif" = "Oznámenia na tomto zariadení"; "auth_autodiscover_invalid_response" = "Neplatná odpoveď pri zisťovaní domovského servera"; @@ -1156,7 +1156,7 @@ "identity_server_settings_alert_disconnect_still_sharing_3pid" = "Svoje osobné údaje stále zdieľate na serveri totožností %@.\n\nOdporúčame vám, aby ste pred odpojením odstránili svoje e-mailové adresy a telefónne čísla zo servera totožností."; "identity_server_settings_disconnect_info" = "Odpojenie od servera totožností bude znamenať, že vás nebudú môcť objaviť iní používatelia a že nebudete môcť pozývať ostatných prostredníctvom e-mailu alebo telefónu."; "identity_server_settings_description" = "V súčasnosti používate %@ na objavovanie existujúcich kontaktov, ktoré poznáte, a na to, aby vás mohli objaviť."; -"security_settings_crypto_sessions_description_2" = "Ak nespoznávate prihlásenie, zmeňte si heslo a vykonajte obnovenie funkcie Zabezpečené zálohovanie."; +"security_settings_crypto_sessions_description_2" = "Ak nespoznávate prihlásenie, zmeňte si heslo k účtu Matrix a obnovte Zabezpečenú zálohu."; "settings_identity_server_no_is_description" = "Momentálne nepoužívate žiadny server totožností. Ak chcete objaviť existujúce kontakty, ktoré poznáte, a byť nimi objaviteľní, pridajte jeden vyššie."; "settings_analytics_and_crash_data" = "Odoslať údaje o páde a analytické údaje"; "settings_labs_create_conference_with_jitsi" = "Vytvárajte konferenčné hovory pomocou aplikácie jitsi"; @@ -1251,7 +1251,7 @@ "settings_discovery_three_pids_management_information_part1" = "Spravujte, ktoré e-mailové adresy alebo telefónne čísla môžu ostatní používatelia použiť na vaše objavenie a pozvanie do miestností. E-mailové adresy alebo telefónne čísla môžete pridávať alebo odstraňovať z tohto zoznamu v "; "settings_discovery_terms_not_signed" = "Musíte súhlasiť s podmienkami služby servera totožnosti (%@), aby vás mohli nájsť podľa e-mailovej adresy alebo telefónneho čísla."; "settings_key_backup_button_connect" = "Pripojiť túto reláciu k zálohovaniu kľúčov"; -"settings_fail_to_update_password" = "Nepodarilo sa aktualizovať heslo"; +"settings_fail_to_update_password" = "Nepodarilo sa aktualizovať heslo k účtu Matrix"; "settings_labs_enable_ringing_for_group_calls" = "Zvonenie pre skupinové hovory"; "widget_integration_positive_power_level" = "Úroveň oprávnenia musí byť kladné celé číslo."; "settings_integrations_allow_description" = "Použite správcu integrácií (%@) na spravovanie botov, premostení, widgetov a balíčkov s nálepkami. \n\nSprávcovia integrácie dostávajú konfiguračné údaje a môžu vo vašom mene upravovať widgety, posielať pozvánky do miestnosti a nastavovať úrovne oprávnení."; @@ -1262,7 +1262,7 @@ "settings_room_invitations" = "Pozvánky do miestnosti"; "settings_global_settings_info" = "Všeobecné nastavenia oznámení sú k dispozícii vo webovom klientovi %@"; "settings_confirm_media_size_description" = "Keď je táto funkcia zapnutá, budete vyzvaní, aby ste potvrdili, v akej veľkosti sa budú obrázky a videá odosielať."; -"settings_three_pids_management_information_part1" = "Tu môžete spravovať e-mailové adresy alebo telefónne čísla, ktoré môžete použiť na prihlásenie alebo obnovenie účtu. Ovládajte, kto vás môže nájsť v "; +"settings_three_pids_management_information_part1" = "Tu môžete spravovať e-mailové adresy alebo telefónne čísla, ktoré môžete použiť na prihlásenie alebo obnovenie účtu. Ovládajte, kto vás môže nájsť v sekcii "; "settings_fail_to_update_profile" = "Nepodarilo sa aktualizovať profil"; "settings_email_address_placeholder" = "Zadajte svoju e-mailovú adresu"; "settings_remove_phone_prompt_msg" = "Určite chcete odstrániť telefónne číslo %@?"; @@ -1283,10 +1283,10 @@ "auth_softlogout_recover_encryption_keys" = "Prihláste sa, aby ste obnovili šifrovacie kľúče uložené výlučne v tomto zariadení. Potrebujete ich na čítanie všetkých svojich zabezpečených správ na akomkoľvek zariadení."; "auth_softlogout_reason" = "Váš správca domovského servera (%1$@) vás odhlásil z vášho účtu %2$@ (%3$@)."; "auth_add_email_and_phone_warning" = "Registrácia pomocou e-mailu a telefónneho čísla naraz zatiaľ nie je podporovaná, kým nebude existovať api. Do úvahy sa bude brať iba telefónne číslo. Svoj e-mail môžete pridať do svojho profilu v nastaveniach."; -"auth_reset_password_success_message" = "Vaše heslo bolo obnovené.\n\nBoli ste odhlásení zo všetkých relácií a už nebudete dostávať push oznámenia. Ak chcete opätovne povoliť oznámenia, znovu sa prihláste na každom zariadení."; +"auth_reset_password_success_message" = "Vaše heslo k účtu Matrix bolo obnovené.\n\nBoli ste odhlásení zo všetkých relácií a už nebudete dostávať push oznámenia. Ak chcete opätovne povoliť oznámenia, znovu sa prihláste na každom zariadení."; "auth_untrusted_id_server" = "Server totožností nie je dôveryhodný"; -"auth_phone_is_required" = "Nie je nastavený žiadny server totožností, takže nemôžete pridať e-telefónne číslo, aby ste mohli v budúcnosti obnoviť svoje heslo."; -"auth_email_is_required" = "Nie je nastavený žiadny server totožností, takže nemôžete pridať e-mailovú adresu, aby ste mohli v budúcnosti obnoviť svoje heslo."; +"auth_phone_is_required" = "Nie je nastavený žiadny server totožností, takže nemôžete pridať e-telefónne číslo, aby ste mohli v budúcnosti obnoviť svoje heslo k účtu Matrix."; +"auth_email_is_required" = "Nie je nastavený žiadny server totožností, takže nemôžete pridať e-mailovú adresu, aby ste mohli v budúcnosti obnoviť svoje heslo k účtu Matrix."; "auth_add_email_phone_message_2" = "Nastavte si e-mail na obnovenie účtu. Neskôr môžete voliteľne použiť e-mail alebo telefón, aby vás mohli nájsť ľudia, ktorí vás poznajú."; "cross_signing_setup_banner_subtitle" = "Jednoduchšie overenie ostatných zariadení"; "room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Šifrovať len overeným reláciám"; @@ -1298,7 +1298,7 @@ "room_intro_cell_information_room_without_topic_sentence2_part2" = " aby ľudia vedeli, o čom je táto miestnosť."; "room_intro_cell_information_room_without_topic_sentence2_part1" = "Pridať tému"; "room_avatar_view_accessibility_hint" = "Zmeniť obrázok miestnosti"; -"invite_friends_share_text" = "Hej, ozvi sa mi na %@: %@"; +"invite_friends_share_text" = "Ahoj, ozvi sa mi na %@: %@"; // MARK: - Invite friends @@ -1338,11 +1338,11 @@ // Banner "cross_signing_setup_banner_title" = "Nastaviť šifrovanie"; -"secrets_reset_authentication_message" = "Zadajte heslo svojho účtu pre potvrdenie"; +"secrets_reset_authentication_message" = "Zadajte heslo svojho účtu Matrix pre potvrdenie"; "secrets_setup_recovery_passphrase_summary_information" = "Zapamätajte si bezpečnostnú frázu. Môžete ju použiť na odomknutie zašifrovaných správ a údajov."; "secrets_setup_recovery_passphrase_summary_title" = "Uložte si bezpečnostnú frázu"; "secrets_setup_recovery_passphrase_confirm_information" = "Opätovne zadajte bezpečnostnú frázu a potvrďte ju."; -"secrets_setup_recovery_passphrase_additional_information" = "Nepoužívajte heslo k svojmu účtu."; +"secrets_setup_recovery_passphrase_additional_information" = "Nepoužívajte heslo k svojmu účtu Matrix."; "secrets_setup_recovery_passphrase_information" = "Zadajte bezpečnostnú frázu, ktorú poznáte len vy a ktorá sa používa na zabezpečenie tajomstiev na vašom serveri."; "secrets_recovery_with_key_recovery_key_title" = "Zadajte"; "secrets_recovery_with_key_information_unlock_secure_backup_with_key" = "Ak chcete pokračovať, zadajte bezpečnostný kľúč."; @@ -1449,7 +1449,7 @@ // Success from recovery key "key_backup_setup_success_from_recovery_key_info" = "Vaše kľúče sa zálohujú.\n\nVytvorte si kópiu tohto bezpečnostného kľúča a uschovajte ho na bezpečnom mieste."; "key_backup_setup_passphrase_passphrase_invalid" = "Skúste pridať slovo"; -"key_backup_setup_passphrase_info" = "Šifrovanú kópiu vašich kľúčov uložíme na našom serveri. Chráňte svoju zálohu frázou, aby bola bezpečná.\n\nV záujme maximálneho zabezpečenia by sa mala líšiť od hesla k vášmu účtu."; +"key_backup_setup_passphrase_info" = "Šifrovanú kópiu vašich kľúčov uložíme na našom serveri. Chráňte svoju zálohu frázou, aby bola bezpečná.\n\nV záujme maximálneho zabezpečenia by sa mala líšiť od hesla k vášmu účtu Matrix."; "key_backup_setup_intro_info" = "Správy v šifrovaných miestnostiach sú zabezpečené end-to-end šifrovaním. Kľúče na čítanie týchto správ máte len vy a príjemca (príjemcovia).\n\nKľúče si bezpečne zálohujte, aby ste ich nestratili."; "secure_key_backup_setup_existing_backup_error_delete_it" = "Vymazať"; "secure_key_backup_setup_existing_backup_error_unlock_it" = "Odomknúť"; @@ -1572,7 +1572,7 @@ "room_details_access_section_anyone_apart_from_guest_for_dm" = "Ktokoľvek, kto pozná odkaz, okrem hostí"; "room_details_access_section_anyone" = "Ktokoľvek, kto pozná odkaz na miestnosť, vrátane hostí"; "room_details_access_section_invited_only" = "Iba ľudia, ktorí boli pozvaní"; -"room_details_access_section_for_dm" = "Kto má k tomuto prístup?"; +"room_details_access_section_for_dm" = "Kto má sem prístup?"; "room_details_access_section" = "Kto má prístup do tejto miestnosti?"; "identity_server_settings_alert_error_invalid_identity_server" = "%@ nie je platný server totožností."; "identity_server_settings_alert_disconnect" = "Odpojiť sa od servera totožností %@?"; @@ -1580,13 +1580,13 @@ // AuthenticatedSessionViewControllerFactory "authenticated_session_flow_not_supported" = "Táto aplikácia nepodporuje mechanizmus overovania na vašom domovskom serveri."; -"security_settings_user_password_description" = "Potvrďte svoju totožnosť zadaním hesla k účtu"; +"security_settings_user_password_description" = "Potvrďte svoju totožnosť zadaním hesla k účtu Matrix"; "security_settings_coming_soon" = "Prepáčte. Táto akcia zatiaľ nie je dostupná v systéme %@ iOS. Na jej nastavenie použite iného klienta Matrix. Systém %@ iOS to bude používať."; "security_settings_complete_security_alert_title" = "Dokončiť zabezpečenie"; "security_settings_complete_security_alert_message" = "Najprv by ste mali dokončiť zabezpečenie aktuálnej relácie."; "security_settings_blacklist_unverified_devices_description" = "Overte všetky relácie používateľov, aby ste ich mohli označiť za dôveryhodné a odosielať im správy."; "security_settings_secure_backup_info_valid" = "Táto relácia zálohuje vaše kľúče."; -"settings_show_NSFW_public_rooms" = "Zobraziť verejné miestnosti nevhodné do práce"; +"settings_show_NSFW_public_rooms" = "Zobraziť aj verejné miestnosti nevhodné do práce"; "settings_identity_server_no_is" = "Nebol nastavený server totožností"; "settings_discovery_three_pid_details_enter_sms_code_action" = "Zadajte aktivačný kód SMS"; "settings_discovery_three_pid_details_information_email" = "Spravujte predvoľby pre túto e-mailovú adresu, ktorú môžu ostatní používatelia použiť na vaše objavenie a pozvanie do miestností. Pridávajte alebo odstraňujte e-mailové adresy v časti Účty."; @@ -1610,7 +1610,7 @@ "settings_key_backup_info_signout_warning" = "Zálohujte si šifrovacie kľúče pred odhlásením, aby ste o ne neprišli."; "settings_key_backup_info_none" = "Vaše kľúče sa z tejto relácie nezálohujú."; "settings_key_backup_info" = "Šifrované správy sú zabezpečené end-to-end šifrovaním. Kľúče na čítanie týchto správ máte len vy a príjemca (príjemcovia)."; -"settings_add_3pid_password_message" = "Aby ste mohli pokračovať, prosím zadajte svoje heslo"; +"settings_add_3pid_password_message" = "Aby ste mohli pokračovať, prosím zadajte svoje heslo k účtu Matrix"; "settings_labs_message_reaction" = "Reagujte na správy pomocou emoji"; "settings_labs_e2e_encryption_prompt_message" = "Ak chcete dokončiť nastavenie šifrovania, musíte sa znova prihlásiť."; "settings_contacts_enable_sync_description" = "Na prepojenie s vašimi kontaktmi sa použije váš server totožností a pomôže im vás nájsť."; @@ -1627,7 +1627,7 @@ "rage_shake_prompt" = "Zdá sa, že rozčúlene trasiete telefónom. Chceli by ste odoslať hlásenie o chybe?"; "room_details_addresses_disable_main_address_prompt_msg" = "Nebudete mať zadanú žiadnu hlavnú adresu. Predvolená hlavná adresa pre túto miestnosť sa vyberie náhodne"; "settings_enable_rageshake" = "Zúrivo potraste pre nahlásenie chyby"; -"settings_ui_theme_picker_message_match_system_theme" = "\"Auto\" zodpovedá systémovej téme vášho zariadenia"; +"settings_ui_theme_picker_message_match_system_theme" = "\"Automatický\" zodpovedá systémovej téme vášho zariadenia"; "settings_pin_rooms_with_unread" = "Pripnúť miestnosti s neprečítanými správami"; "settings_pin_rooms_with_missed_notif" = "Pripnúť miestnosti so zmeškanými oznámeniami"; "settings_confirm_media_size" = "Potvrdiť veľkosť pri odosielaní"; @@ -1688,7 +1688,7 @@ "poll_timeline_total_one_vote" = "1 odovzdaný hlas"; "poll_edit_form_poll_type_closed" = "Uzavretá anketa"; "poll_edit_form_post_failure_title" = "Nepodarilo sa odoslať anketu"; -"call_transfer_error_message" = "Prenos hovoru zlyhal"; +"call_transfer_error_message" = "Presmerovanie hovoru zlyhalo"; "user_verification_session_details_information_untrusted_other_user" = " sa prihlásil pomocou novej relácie:"; "key_verification_bootstrap_not_setup_message" = "Najprv musíte zaviesť krížové podpisovanie."; "device_verification_emoji_pin" = "Špendlík"; @@ -1706,6 +1706,48 @@ "room_details_addresses_disable_main_address_prompt_title" = "Upozornenie na hlavnú adresu"; "manage_session_trusted" = "Dôveryhodný pre vás"; "settings_contacts_phonebook_country" = "Krajina telefónneho zoznamu"; -"settings_ui_theme_picker_message_invert_colours" = "\"Auto\" používa nastavenia \"Invertovať farby\" vášho zariadenia"; +"settings_ui_theme_picker_message_invert_colours" = "\"Automatický\" používa nastavenia \"Invertovať farby\" vášho zariadenia"; "external_link_confirmation_title" = "Prekontrolujte tento odkaz"; "callbar_only_single_active_group" = "Ťuknutím sa pripojíte k skupinovému hovoru (%@)"; + +// MARK: - Call Transfer +"call_transfer_title" = "Presmerovať"; + +// Events formatter +"event_formatter_member_updates" = "%tu zmeny členstva"; +"location_sharing_post_failure_subtitle" = "%@ sa nepodarilo odoslať vašu polohu. Skúste to prosím neskôr."; +"location_sharing_post_failure_title" = "Nepodarilo sa nám odoslať vašu polohu"; +"space_tag" = "priestor"; +"home_context_menu_leave" = "Opustiť"; +"home_context_menu_normal_priority" = "Normálna priorita"; +"home_context_menu_low_priority" = "Nízka priorita"; +"home_context_menu_unfavourite" = "Odstrániť z obľúbených"; +"home_context_menu_favourite" = "Obľúbené"; +"home_context_menu_unmute" = "Zrušiť stlmenie"; +"home_context_menu_mute" = "Stlmiť"; +"home_context_menu_notifications" = "Oznámenia"; +"home_context_menu_make_dm" = "Presunúť do Ľudí"; +"bug_report_progress_uploading" = "Nahrávanie záznamu"; +"event_formatter_message_deleted" = "Správa vymazaná"; +"room_event_copy_link_info" = "Odkaz skopírovaný do schránky."; +"room_event_action_view_in_room" = "Zobraziť v miestnosti"; +"home_context_menu_make_room" = "Presunúť do miestností"; +"settings_labs_enable_threads" = "Správy vo vláknach"; +"message_from_a_thread" = "Z vlákna"; +"threads_empty_show_all_threads" = "Zobraziť všetky vlákna"; +"threads_empty_tip" = "Tip: Ťuknite na správu a použite \"Vlákno\" pre začatie nového."; +"threads_empty_info_my" = "Odpovedzte na prebiehajúce vlákno alebo ťuknite na správu a použite \"Vlákno\" pre začatie nového."; +"threads_empty_info_all" = "Vlákna pomáhajú udržiavať konverzácie v téme a ľahké sledovanie."; +"threads_empty_title" = "Udržujte diskusie organizované pomocou vlákien"; +"threads_action_my_threads" = "Moje vlákna"; +"threads_action_all_threads" = "Všetky vlákna"; +"threads_title" = "Vlákna"; +"thread_copy_link_to_thread" = "Kopírovať odkaz na vlákno"; + +// MARK: Threads +"room_thread_title" = "Vlákno"; +"room_accessibility_thread_more" = "Viac"; +"room_accessibility_threads" = "Vlákna"; +"room_event_action_reply_in_thread" = "Vlákno"; +"settings_calls_stun_server_fallback_button" = "Povoliť náhradnú službu hovorov asistenčného servera"; +"settings_calls_stun_server_fallback_description" = "Povoľte náhradné službu hovorov asistenčného servera %@, keď ho váš domovský server neponúka (vaša IP adresa by bola počas volania zdieľaná)."; From 514bdb4705bc175a2e90424aff45781001b3c180 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Sat, 12 Feb 2022 17:18:52 +0000 Subject: [PATCH 057/188] Add new loading indicators --- Podfile | 6 +- Podfile.lock | 17 +-- Riot/Categories/UIView+Toast.swift | 102 +--------------- .../Application/AppAlertPresenter.swift | 44 ------- Riot/Modules/Application/AppCoordinator.swift | 3 - Riot/Modules/Application/AppNavigator.swift | 1 - Riot/Modules/Common/Activities/Activity.swift | 91 ++++++++++++++ .../Common/Activities/ActivityCenter.swift | 60 ++++++++++ .../ActivityDismissal.swift} | 23 +--- .../Activities/ActivityPresentable.swift | 25 ++++ .../Common/Activities/ActivityRequest.swift | 25 ++++ .../GlobalActivityCenterPresenter.swift | 69 +++++++++++ .../Common/Recents/RecentsViewController.m | 18 +++ .../ActivityIndicatorToastPresenter.swift | 70 +++++++++++ .../Toasts/ActivityIndicatorToastView.swift | 83 +++++++++++++ .../Common/Toasts/BasicToastView.swift | 112 ++++++++++++++++++ ...ollerWithBannerWrapperViewController.swift | 4 + .../MXKActivityHandlingViewController.m | 12 +- .../Controllers/MXKRecentListViewController.m | 2 +- .../MatrixKit/Controllers/MXKViewController.h | 5 + .../MatrixKit/Controllers/MXKViewController.m | 15 ++- .../MXKViewControllerActivityHandling.h | 8 ++ Riot/Modules/Room/MXKRoomViewController.m | 18 ++- .../Settings/RoomSettingsViewController.m | 3 - 24 files changed, 628 insertions(+), 188 deletions(-) delete mode 100644 Riot/Modules/Application/AppAlertPresenter.swift create mode 100644 Riot/Modules/Common/Activities/Activity.swift create mode 100644 Riot/Modules/Common/Activities/ActivityCenter.swift rename Riot/Modules/Common/{Alert/AlertPresentable.swift => Activities/ActivityDismissal.swift} (51%) create mode 100644 Riot/Modules/Common/Activities/ActivityPresentable.swift create mode 100644 Riot/Modules/Common/Activities/ActivityRequest.swift create mode 100644 Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift create mode 100644 Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift create mode 100644 Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift create mode 100644 Riot/Modules/Common/Toasts/BasicToastView.swift diff --git a/Podfile b/Podfile index 09f7811c9..edd7e4fbb 100644 --- a/Podfile +++ b/Podfile @@ -13,9 +13,9 @@ use_frameworks! # - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixSDKVersion = '= 0.22.0' +# $matrixSDKVersion = '= 0.22.0' # $matrixSDKVersion = :local -# $matrixSDKVersion = { :branch => 'develop'} +$matrixSDKVersion = { :branch => 'develop'} # $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } } ######################################## @@ -154,4 +154,4 @@ post_install do |installer| config.build_settings['OTHER_SWIFT_FLAGS'] ||= ['$(inherited)', '-Xcc', '-Wno-nullability-completeness'] end end -end \ No newline at end of file +end diff --git a/Podfile.lock b/Podfile.lock index 9f181b4bc..88ead762f 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -45,7 +45,6 @@ PODS: - GBDeviceInfo/Core (= 6.6.0) - GBDeviceInfo/Core (6.6.0) - GZIP (1.3.0) - - HPGrowingTextView (1.1) - Introspect (0.1.3) - JitsiMeetSDK (3.10.2) - KeychainAccess (4.2.2) @@ -112,13 +111,12 @@ DEPENDENCIES: - FLEX (~> 4.5.0) - FlowCommoniOS (~> 1.12.0) - GBDeviceInfo (~> 6.6.0) - - HPGrowingTextView (~> 1.1) - Introspect (~> 0.1) - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.22.0) - - MatrixSDK/JingleCallStack (= 0.22.0) + - MatrixSDK (from `https://github.com/matrix-org/matrix-ios-sdk.git`, branch `develop`) + - MatrixSDK/JingleCallStack (from `https://github.com/matrix-org/matrix-ios-sdk.git`, branch `develop`) - OLMKit - PostHog (~> 1.4.4) - ReadMoreTextView (~> 3.0.1) @@ -149,7 +147,6 @@ SPEC REPOS: - FlowCommoniOS - GBDeviceInfo - GZIP - - HPGrowingTextView - Introspect - JitsiMeetSDK - KeychainAccess @@ -159,7 +156,6 @@ SPEC REPOS: - libPhoneNumber-iOS - LoggerAPI - Logging - - MatrixSDK - OLMKit - PostHog - ReadMoreTextView @@ -180,11 +176,17 @@ EXTERNAL SOURCES: AnalyticsEvents: :branch: release/swift :git: https://github.com/matrix-org/matrix-analytics-events.git + MatrixSDK: + :branch: develop + :git: https://github.com/matrix-org/matrix-ios-sdk.git CHECKOUT OPTIONS: AnalyticsEvents: :commit: 8058dc6ec07ce0acfe5fdb19eb7e309b0c13845c :git: https://github.com/matrix-org/matrix-analytics-events.git + MatrixSDK: + :commit: 7be07981c3f2932b0205797f234982ca32da7dff + :git: https://github.com/matrix-org/matrix-ios-sdk.git SPEC CHECKSUMS: AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce @@ -202,7 +204,6 @@ SPEC CHECKSUMS: FlowCommoniOS: ca92071ab526dc89905495a37844fd7e78d1a7f2 GBDeviceInfo: ed0db16230d2fa280e1cbb39a5a7f60f6946aaec GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3 - HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19 Introspect: 2be020f30f084ada52bb4387fff83fa52c5c400e JitsiMeetSDK: 2f118fa770f23e518f3560fc224fae3ac7062223 KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 @@ -229,6 +230,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 2a13c9d4f4894152af066c746582fde2e731cbff +PODFILE CHECKSUM: 9b4be35779b652e3d0ad333d84069240ec58dc96 COCOAPODS: 1.11.2 diff --git a/Riot/Categories/UIView+Toast.swift b/Riot/Categories/UIView+Toast.swift index e395578e3..b89d63ac1 100644 --- a/Riot/Categories/UIView+Toast.swift +++ b/Riot/Categories/UIView+Toast.swift @@ -60,7 +60,7 @@ extension UIView { duration: TimeInterval = Constants.defaultDuration, position: ToastPosition = Constants.defaultPosition, additionalMargin: CGFloat = 0.0) { - let view = ToastView(withMessage: message, image: image) + let view = BasicToastView(withMessage: message, image: image) vc_toast(view: view, duration: duration, position: position, additionalMargin: additionalMargin) } @@ -91,6 +91,9 @@ extension UIView { // MARK: - ToastOperation /// Async toast UI operation. Will run on the main thread. +/// +/// Note: a more recent `Activity` and `ActivityCenter` aim to achieve the same goal of abstracting away the scheduling and display +/// of visual notifications, without using `OperationQueue`. private class ToastOperation: AsyncOperation { private enum Constants { @@ -212,100 +215,3 @@ private class ToastOperation: AsyncOperation { } } - -// MARK: - ToastView - -/// Default view for a basic toast. -private class ToastView: UIView, Themable { - - private enum Constants { - static let padding: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) - static let cornerRadius: CGFloat = 8.0 - } - - private lazy var imageView: UIImageView = { - let view = UIImageView() - view.translatesAutoresizingMaskIntoConstraints = false - view.backgroundColor = .clear - return view - }() - - private lazy var messageLabel: UILabel = { - let label = UILabel() - label.font = ThemeService.shared().theme.fonts.body - label.backgroundColor = .clear - label.numberOfLines = 0 - label.textAlignment = .left - label.translatesAutoresizingMaskIntoConstraints = false - return label - }() - - private lazy var stackView: UIStackView = { - let result = UIStackView() - result.axis = .horizontal - result.distribution = .fill - result.alignment = .center - result.spacing = 8.0 - result.backgroundColor = .clear - - addSubview(result) - result.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - result.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Constants.padding.left), - result.topAnchor.constraint(equalTo: topAnchor, constant: Constants.padding.top), - result.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Constants.padding.right), - result.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -Constants.padding.bottom) - ]) - - return result - }() - - init(withMessage message: String?, - image: UIImage? = nil) { - super.init(frame: .zero) - - if let image = image { - imageView.image = image - NSLayoutConstraint.activate([ - imageView.widthAnchor.constraint(equalToConstant: image.size.width), - imageView.heightAnchor.constraint(equalToConstant: image.size.height) - ]) - stackView.addArrangedSubview(imageView) - } - - messageLabel.text = message - stackView.addArrangedSubview(messageLabel) - - stackView.layoutIfNeeded() - layer.cornerRadius = Constants.cornerRadius - layer.masksToBounds = true - registerThemeServiceDidChangeThemeNotification() - themeDidChange() - } - - required init?(coder: NSCoder) { - fatalError("init(coder:) has not been implemented") - } - - private func registerThemeServiceDidChangeThemeNotification() { - NotificationCenter.default.addObserver(self, - selector: #selector(themeDidChange), - name: .themeServiceDidChangeTheme, - object: nil) - } - - @objc - private func themeDidChange() { - self.update(theme: ThemeService.shared().theme) - } - - // MARK: Themable - - func update(theme: Theme) { - backgroundColor = theme.colors.quinaryContent - imageView.tintColor = theme.colors.tertiaryContent - messageLabel.textColor = theme.colors.primaryContent - messageLabel.font = theme.fonts.body - } - -} diff --git a/Riot/Modules/Application/AppAlertPresenter.swift b/Riot/Modules/Application/AppAlertPresenter.swift deleted file mode 100644 index f60a5ef34..000000000 --- a/Riot/Modules/Application/AppAlertPresenter.swift +++ /dev/null @@ -1,44 +0,0 @@ -// -// Copyright 2021 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 - -class AppAlertPresenter: AlertPresentable { - - // MARK: - Properties - - // swiftlint:disable weak_delegate - private let legacyAppDelegate: LegacyAppDelegate - // swiftlint:enable weak_delegate - - // MARK: - Setup - - init(legacyAppDelegate: LegacyAppDelegate) { - self.legacyAppDelegate = legacyAppDelegate - } - - // MARK: - Public - - func showError(_ error: Error, animated: Bool, completion: (() -> Void)?) { - // FIXME: Present an error on coordinator.toPresentable() - self.legacyAppDelegate.showError(asAlert: error) - } - - func show(title: String?, message: String?, animated: Bool, completion: (() -> Void)?) { - // FIXME: Present an error on coordinator.toPresentable() - self.legacyAppDelegate.showAlert(withTitle: title, message: message) - } -} diff --git a/Riot/Modules/Application/AppCoordinator.swift b/Riot/Modules/Application/AppCoordinator.swift index 03cdc9d6e..95e6dde74 100755 --- a/Riot/Modules/Application/AppCoordinator.swift +++ b/Riot/Modules/Application/AppCoordinator.swift @@ -288,8 +288,6 @@ fileprivate class AppNavigator: AppNavigatorProtocol { private unowned let appCoordinator: AppCoordinator - let alert: AlertPresentable - lazy var sideMenu: SideMenuPresentable = { guard let sideMenuCoordinator = appCoordinator.sideMenuCoordinator else { fatalError("sideMenuCoordinator is not initialized") @@ -302,7 +300,6 @@ fileprivate class AppNavigator: AppNavigatorProtocol { init(appCoordinator: AppCoordinator) { self.appCoordinator = appCoordinator - self.alert = AppAlertPresenter(legacyAppDelegate: appCoordinator.legacyAppDelegate) } // MARK: - Public diff --git a/Riot/Modules/Application/AppNavigator.swift b/Riot/Modules/Application/AppNavigator.swift index d3b7eddf4..16c95fb4f 100644 --- a/Riot/Modules/Application/AppNavigator.swift +++ b/Riot/Modules/Application/AppNavigator.swift @@ -22,7 +22,6 @@ import Foundation protocol AppNavigatorProtocol { var sideMenu: SideMenuPresentable { get } - var alert: AlertPresentable { get } /// Navigate to a destination screen or a state /// Do not use protocol with associatedtype for the moment like presented here https://www.swiftbysundell.com/articles/navigation-in-swift/#where-to-navigator use a separate enum diff --git a/Riot/Modules/Common/Activities/Activity.swift b/Riot/Modules/Common/Activities/Activity.swift new file mode 100644 index 000000000..b7bc0d083 --- /dev/null +++ b/Riot/Modules/Common/Activities/Activity.swift @@ -0,0 +1,91 @@ +// +// Copyright 2021 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 + +/// An `Activity` represents a temporary visual indicator, such as activity indicator, success notification or an error message. +/// +/// More than one `Activity` may be requested by the system at the same time (e.g. global syncing vs local refresh), +/// and the `ActivityCenter` will ensure that only one activity is shown at a given time, putting the other in a pending queue. +/// +/// A client that requests an activity can specify a default timeout after which the activity is dismissed, or it has to be manually +/// responsible for dismissing it via `cancel` method, or by deallocating itself. +class Activity { + enum State { + case pending + case executing + case completed + } + + private let request: ActivityRequest + private let completion: () -> Void + + private(set) var state: State + + init(request: ActivityRequest, completion: @escaping () -> Void) { + self.request = request + self.completion = completion + + state = .pending + } + + deinit { + cancel() + } + + /// Start the activity + /// + /// Note: clients should not call this method manually if the activity is added into an `ActivityCenter` + func start() { + guard state == .pending else { + return + } + + state = .executing + request.presenter.present() + + switch request.dismissal { + case .manual: + break + case .timeout(let interval): + Timer.scheduledTimer(withTimeInterval: interval, repeats: false) { [weak self] _ in + self?.complete() + } + } + } + + + /// Cancel the activity, triggering any dismissal action / animation + /// + /// Note: clients can call this method directly, if they have access to the `Activity`. + /// Once cancelled, `ActivityCenter` will automatically start the next `Activity` in the queue. + func cancel() { + complete() + } + + private func complete() { + guard state != .completed else { + return + } + if state == .executing { + request.presenter.dismiss() + } + + state = .completed + completion() + } +} diff --git a/Riot/Modules/Common/Activities/ActivityCenter.swift b/Riot/Modules/Common/Activities/ActivityCenter.swift new file mode 100644 index 000000000..f27d23e53 --- /dev/null +++ b/Riot/Modules/Common/Activities/ActivityCenter.swift @@ -0,0 +1,60 @@ +// +// Copyright 2021 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 + +/// A shared activity center with a single FIFO queue which will ensure only one activity is shown at a given time. +/// +/// `ActivityCenter` offers a `shared` center that can be used by any clients, but clients are also allowed +/// to create local `ActivityCenter` if the context requres multiple simultaneous activities. +class ActivityCenter { + private class Weak { + weak var element: T? + init(_ element: T) { + self.element = element + } + } + + static let shared = ActivityCenter() + private var queue = [Weak]() + + /// Add a new activity to the queue by providing a request. + /// + /// The queue will start the activity right away, if there are no currently running activities, + /// otherwise the activity will be put on hold. + func add(_ request: ActivityRequest) -> Activity { + let activity = Activity(request: request) { [weak self] in + self?.startNextIfIdle() + } + + queue.append(Weak(activity)) + startNextIfIdle() + return activity + } + + private func startNextIfIdle() { + cleanup() + if let activity = queue.first?.element, activity.state == .pending { + activity.start() + } + } + + private func cleanup() { + queue.removeAll { + $0.element == nil || $0.element?.state == .completed + } + } +} diff --git a/Riot/Modules/Common/Alert/AlertPresentable.swift b/Riot/Modules/Common/Activities/ActivityDismissal.swift similarity index 51% rename from Riot/Modules/Common/Alert/AlertPresentable.swift rename to Riot/Modules/Common/Activities/ActivityDismissal.swift index d0ee0dcd4..dbb6cb83a 100644 --- a/Riot/Modules/Common/Alert/AlertPresentable.swift +++ b/Riot/Modules/Common/Activities/ActivityDismissal.swift @@ -16,21 +16,10 @@ import Foundation -/// AlertPresentable absracts an alert presenter -protocol AlertPresentable { - - func showError(_ error: Error, animated: Bool, completion: (() -> Void)?) - func show(title: String?, message: String?, animated: Bool, completion: (() -> Void)?) -} - -// MARK: Default implementation -extension AlertPresentable { - - func showError(_ error: Error) { - self.showError(error, animated: true, completion: nil) - } - - func show(title: String?, message: String?) { - self.show(title: title, message: message, animated: true, completion: nil) - } +/// Different ways in which an `Activity` can be dismissed +enum ActivityDismissal { + /// The `Activity` will not manage the dismissal, but will expect the calling client to do so manually + case manual + /// The `Activity` will be automatically dismissed after `TimeInterval` + case timeout(TimeInterval) } diff --git a/Riot/Modules/Common/Activities/ActivityPresentable.swift b/Riot/Modules/Common/Activities/ActivityPresentable.swift new file mode 100644 index 000000000..b6e7b46df --- /dev/null +++ b/Riot/Modules/Common/Activities/ActivityPresentable.swift @@ -0,0 +1,25 @@ +// +// Copyright 2021 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 + +/// A presenter associated with and called by an `Activity`, and responsible for the underlying view shown on the screen. +protocol ActivityPresentable { + /// Called when the `Activity` is started (manually or by the `ActivityCenter`) + func present() + /// Called when the `Activity` is manually cancelled or completed + func dismiss() +} diff --git a/Riot/Modules/Common/Activities/ActivityRequest.swift b/Riot/Modules/Common/Activities/ActivityRequest.swift new file mode 100644 index 000000000..872699758 --- /dev/null +++ b/Riot/Modules/Common/Activities/ActivityRequest.swift @@ -0,0 +1,25 @@ +// +// Copyright 2021 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 + +/// A request used to create an underlying `Activity`, allowing clients to only specify the visual aspects of an activity. +struct ActivityRequest { + /// Presenter which will manage the underlying view shown on screen + let presenter: ActivityPresentable + // A method in which the activity is eventually dismissed + let dismissal: ActivityDismissal +} diff --git a/Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift b/Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift new file mode 100644 index 000000000..b2c35e018 --- /dev/null +++ b/Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift @@ -0,0 +1,69 @@ +// +// Copyright 2021 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 +import MatrixSDK + +/// Activity indicator presenter which uses a shared `ActivityCenter` to coordinate different activity indicators, +/// and which uses the root navigation view controller to display the activities. +@objc final class GlobalActivityCenterPresenter: NSObject, ActivityIndicatorPresenterType { + private var loadingActivity: Activity? + + private var rootNavigationController: UINavigationController? { + guard + let delegate = UIApplication.shared.delegate as? AppDelegate, + let rootVC = delegate.window?.rootViewController + else { + MXLog.error("[ActivityIndicatorPresenter] Missing root view controller") + return nil + } + + if let vc = (rootVC as? UISplitViewController)?.viewControllers.first as? UINavigationController { + return vc + } else if let vc = rootVC as? UINavigationController { + return vc + } else if let vc = rootVC.navigationController { + return vc + } + return nil + } + + @objc func presentActivityIndicator(animated: Bool) { + guard let vc = rootNavigationController else { + MXLog.error("[ActivityIndicatorPresenter] Missing available navigation controller") + return + } + + let presenter = ActivityIndicatorToastPresenter( + text: VectorL10n.roomParticipantsSecurityLoading, + navigationController: vc + ) + let request = ActivityRequest( + presenter: presenter, + dismissal: .manual + ) + loadingActivity = ActivityCenter.shared.add(request) + } + + func presentActivityIndicator(on view: UIView, animated: Bool, completion: (() -> Void)?) { + MXLog.error("[ActivityIndicatorPresenter] Shared activity indicator needs to be presented on a view controller") + } + + @objc func removeCurrentActivityIndicator(animated: Bool, completion: (() -> Void)?) { + loadingActivity = nil + } +} diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 41b8c20ae..32dda7621 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -80,6 +80,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro @property (nonatomic, strong) RoomNotificationSettingsCoordinatorBridgePresenter *roomNotificationSettingsCoordinatorBridgePresenter; +@property (nonatomic, strong) GlobalActivityCenterPresenter *activityPresenter; + @end @implementation RecentsViewController @@ -135,6 +137,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. + self.activityPresenter = [[GlobalActivityCenterPresenter alloc] init]; + self.recentsTableView.accessibilityIdentifier = @"RecentsVCTableView"; // Register here the customized cell view class used to render recents @@ -2390,4 +2394,18 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro self.roomNotificationSettingsCoordinatorBridgePresenter = nil; } +#pragma mark - Activity Indicator + +- (BOOL)providesCustomActivityIndicator { + return YES; +} + +- (void)startActivityIndicator { + [self.activityPresenter presentActivityIndicatorWithAnimated:YES]; +} + +- (void)stopActivityIndicator { + [self.activityPresenter removeCurrentActivityIndicatorWithAnimated:YES completion:nil]; +} + @end diff --git a/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift b/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift new file mode 100644 index 000000000..bccef0df7 --- /dev/null +++ b/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift @@ -0,0 +1,70 @@ +// +// Copyright 2021 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 + +class ActivityIndicatorToastPresenter: ActivityPresentable { + private weak var view: UIView? + + init(text: String, navigationController: UINavigationController) { + let view = ActivityIndicatorToastView(text: text) + + view.translatesAutoresizingMaskIntoConstraints = false + navigationController.view.addSubview(view) + NSLayoutConstraint.activate([ + view.centerXAnchor.constraint(equalTo: navigationController.navigationBar.centerXAnchor), + view.centerYAnchor.constraint(equalTo: navigationController.navigationBar.bottomAnchor) + ]) + + view.isHidden = true + self.view = view + } + + func present() { + guard let view = view else { + return + } + + view.alpha = 0 + view.isHidden = false + view.transform = .init(translationX: 0, y: 10) + UIView.animate(withDuration: 0.2) { + view.alpha = 1 + view.transform = .identity + } + } + + func dismiss() { + guard let view = view, view.superview != nil else { + return + } + + // If `present` and `dismiss` are called right after each other without delay, + // the view does not correctly pick up `currentState` of alpha. Dispatching onto + // the main queue skips a few run loops, giving the system time to render + // current state. + DispatchQueue.main.async { + UIView.animate(withDuration: 0.2, delay: 0, options: .beginFromCurrentState) { + view.alpha = 0 + view.transform = .init(translationX: 0, y: -10) + } completion: { _ in + view.removeFromSuperview() + self.view = nil + } + } + } +} diff --git a/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift b/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift new file mode 100644 index 000000000..a4bd67259 --- /dev/null +++ b/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift @@ -0,0 +1,83 @@ +// +// Copyright 2021 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 +import DesignKit + +class ActivityIndicatorToastView: UIView, Themable { + private struct Constants { + static let padding: UIEdgeInsets = UIEdgeInsets(top: 10, left: 12, bottom: 10, right: 12) + } + + private lazy var stackView: UIStackView = { + let stack = UIStackView() + stack.axis = .horizontal + stack.spacing = 5 + + addSubview(stack) + stack.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + stack.topAnchor.constraint(equalTo: topAnchor, constant: Constants.padding.top), + stack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -Constants.padding.bottom), + stack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Constants.padding.left), + stack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Constants.padding.right) + ]) + + return stack + }() + + private lazy var activityIndicator: UIActivityIndicatorView = { + let view = UIActivityIndicatorView() + view.transform = .init(scaleX: 0.75, y: 0.75) + view.startAnimating() + return view + }() + + private lazy var label: UILabel = { + return UILabel() + }() + + init(text: String) { + super.init(frame: .zero) + setup(text: text) + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func setup(text: String) { + setupLayer() + stackView.addArrangedSubview(activityIndicator) + stackView.addArrangedSubview(label) + label.text = text + update(theme: ThemeService.shared().theme) + } + + private func setupLayer() { + layer.cornerRadius = 20 + layer.shadowColor = UIColor.black.cgColor + layer.shadowOffset = .init(width: 0, height: 4) + layer.shadowRadius = 12 + layer.shadowOpacity = 0.1 + } + + func update(theme: Theme) { + backgroundColor = UIColor.white + label.font = theme.fonts.subheadline + } +} diff --git a/Riot/Modules/Common/Toasts/BasicToastView.swift b/Riot/Modules/Common/Toasts/BasicToastView.swift new file mode 100644 index 000000000..a4b9a39b6 --- /dev/null +++ b/Riot/Modules/Common/Toasts/BasicToastView.swift @@ -0,0 +1,112 @@ +// +// Copyright 2021 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 + +class BasicToastView: UIView, Themable { + + private enum Constants { + static let padding: UIEdgeInsets = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16) + static let cornerRadius: CGFloat = 8.0 + } + + private lazy var imageView: UIImageView = { + let view = UIImageView() + view.translatesAutoresizingMaskIntoConstraints = false + view.backgroundColor = .clear + return view + }() + + private lazy var messageLabel: UILabel = { + let label = UILabel() + label.font = ThemeService.shared().theme.fonts.body + label.backgroundColor = .clear + label.numberOfLines = 0 + label.textAlignment = .left + label.translatesAutoresizingMaskIntoConstraints = false + return label + }() + + private lazy var stackView: UIStackView = { + let result = UIStackView() + result.axis = .horizontal + result.distribution = .fill + result.alignment = .center + result.spacing = 8.0 + result.backgroundColor = .clear + + addSubview(result) + result.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + result.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Constants.padding.left), + result.topAnchor.constraint(equalTo: topAnchor, constant: Constants.padding.top), + result.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Constants.padding.right), + result.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -Constants.padding.bottom) + ]) + + return result + }() + + init(withMessage message: String?, + image: UIImage? = nil) { + super.init(frame: .zero) + + if let image = image { + imageView.image = image + NSLayoutConstraint.activate([ + imageView.widthAnchor.constraint(equalToConstant: image.size.width), + imageView.heightAnchor.constraint(equalToConstant: image.size.height) + ]) + stackView.addArrangedSubview(imageView) + } + + messageLabel.text = message + stackView.addArrangedSubview(messageLabel) + + stackView.layoutIfNeeded() + layer.cornerRadius = Constants.cornerRadius + layer.masksToBounds = true + registerThemeServiceDidChangeThemeNotification() + themeDidChange() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, + selector: #selector(themeDidChange), + name: .themeServiceDidChangeTheme, + object: nil) + } + + @objc + private func themeDidChange() { + self.update(theme: ThemeService.shared().theme) + } + + // MARK: Themable + + func update(theme: Theme) { + backgroundColor = theme.colors.quinaryContent + imageView.tintColor = theme.colors.tertiaryContent + messageLabel.textColor = theme.colors.primaryContent + messageLabel.font = theme.fonts.body + } + +} diff --git a/Riot/Modules/Home/VersionCheck/HomeViewControllerWithBannerWrapperViewController.swift b/Riot/Modules/Home/VersionCheck/HomeViewControllerWithBannerWrapperViewController.swift index 764dc2d59..1c6c24173 100644 --- a/Riot/Modules/Home/VersionCheck/HomeViewControllerWithBannerWrapperViewController.swift +++ b/Riot/Modules/Home/VersionCheck/HomeViewControllerWithBannerWrapperViewController.swift @@ -95,6 +95,10 @@ class HomeViewControllerWithBannerWrapperViewController: UIViewController, MXKVi homeViewController.activityIndicator = newValue } } + + var providesCustomActivityIndicator: Bool { + return homeViewController.providesCustomActivityIndicator + } func startActivityIndicator() { homeViewController.startActivityIndicator() diff --git a/Riot/Modules/MatrixKit/Controllers/MXKActivityHandlingViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKActivityHandlingViewController.m index 5628c7396..97cce741e 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKActivityHandlingViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKActivityHandlingViewController.m @@ -29,6 +29,11 @@ { [super viewDidLoad]; + if ([self providesCustomActivityIndicator]) { + // If a subclass provides custom activity indicator, the default one will not even be initialized. + return; + } + // Add default activity indicator activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; activityIndicator.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0]; @@ -56,9 +61,13 @@ #pragma mark - Activity indicator +- (BOOL)providesCustomActivityIndicator { + return NO; +} + - (void)startActivityIndicator { - if (activityIndicator) + if (activityIndicator && ![self providesCustomActivityIndicator]) { [self.view bringSubviewToFront:activityIndicator]; [activityIndicator startAnimating]; @@ -79,5 +88,4 @@ [activityIndicator stopAnimating]; } - @end diff --git a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m index 1bcd93011..25b50ee61 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKRecentListViewController.m @@ -220,7 +220,7 @@ if ([MXKRoomDataSourceManager sharedManagerForMatrixSession:mxSession].isServerSyncInProgress) { // sync is in progress for at least one data source, keep running the loading wheel - [self.activityIndicator startAnimating]; + [self startActivityIndicator]; break; } } diff --git a/Riot/Modules/MatrixKit/Controllers/MXKViewController.h b/Riot/Modules/MatrixKit/Controllers/MXKViewController.h index e75d42e11..66237c8d6 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKViewController.h +++ b/Riot/Modules/MatrixKit/Controllers/MXKViewController.h @@ -48,5 +48,10 @@ */ @property CGFloat keyboardHeight; +/** + Returns `YES` if any `MXSession` currently requires the display of an activity indicator. + */ +@property (nonatomic, readonly) BOOL shouldShowActivityIndicator; + @end diff --git a/Riot/Modules/MatrixKit/Controllers/MXKViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKViewController.m index a4e559b4c..118e72455 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKViewController.m @@ -492,18 +492,21 @@ const CGFloat MXKViewControllerMaxExternalKeyboardHeight = 80; #pragma mark - Activity indicator -- (void)stopActivityIndicator -{ - // Check whether all conditions are satisfied before stopping loading wheel - BOOL isActivityInProgress = NO; +- (BOOL)shouldShowActivityIndicator { for (MXSession *mxSession in mxSessionArray) { if (mxSession.shouldShowActivityIndicator) { - isActivityInProgress = YES; + return YES; } } - if (!isActivityInProgress) + return NO; +} + +- (void)stopActivityIndicator +{ + // Check whether all conditions are satisfied before stopping loading wheel + if (!self.shouldShowActivityIndicator) { [super stopActivityIndicator]; } diff --git a/Riot/Modules/MatrixKit/Controllers/MXKViewControllerActivityHandling.h b/Riot/Modules/MatrixKit/Controllers/MXKViewControllerActivityHandling.h index 299071230..f80d2990d 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKViewControllerActivityHandling.h +++ b/Riot/Modules/MatrixKit/Controllers/MXKViewControllerActivityHandling.h @@ -35,6 +35,14 @@ */ @property (nonatomic) UIActivityIndicatorView *activityIndicator; +/** + A view controller may choose to implement a completely custom activity indicator (e.g. shared toast notification), + + In this case the default `activityIndicator` will be hidden, and the view controller is responsible for overriding + `startActivityIndicator` and `stopActivityIndicator` methods to show / hide the custom activity indicator. + */ +@property (nonatomic, readonly) BOOL providesCustomActivityIndicator; + /** Bring the activity indicator to the front and start it. */ diff --git a/Riot/Modules/Room/MXKRoomViewController.m b/Riot/Modules/Room/MXKRoomViewController.m index 702802342..0d0acb6ef 100644 --- a/Riot/Modules/Room/MXKRoomViewController.m +++ b/Riot/Modules/Room/MXKRoomViewController.m @@ -154,6 +154,8 @@ */ @property (nonatomic, weak) MXKAttachmentsViewController *attachmentsViewer; +@property (nonatomic, strong) GlobalActivityCenterPresenter *activityPresenter; + @end @implementation MXKRoomViewController @@ -221,6 +223,8 @@ { [super viewDidLoad]; + _activityPresenter = [[GlobalActivityCenterPresenter alloc] init]; + // Check whether the view controller has been pushed via storyboard if (!_bubblesTableView) { @@ -1772,6 +1776,15 @@ #pragma mark - activity indicator +- (BOOL)providesCustomActivityIndicator { + return YES; +} + +- (void)startActivityIndicator +{ + [self.activityPresenter presentActivityIndicatorWithAnimated:YES]; +} + - (void)stopActivityIndicator { // Keep the loading wheel displayed while we are joining the room @@ -1787,8 +1800,9 @@ return; } - // Leave super decide - [super stopActivityIndicator]; + if (![self shouldShowActivityIndicator]) { + [self.activityPresenter removeCurrentActivityIndicatorWithAnimated:YES completion:nil]; + } } #pragma mark - Pagination diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 4d07543fe..ff018f732 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -165,9 +165,6 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti // The pending http operation MXHTTPOperation* pendingOperation; - // the updating spinner - UIActivityIndicatorView* updatingSpinner; - UIAlertController *currentAlert; // listen to more events than the mother class From d1eb5ba3f62d8918d0521c49ba5746d3e01d3ede Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=90=D7=9C=D7=95=D7=9F=20=D7=92=D7=9C=D7=A1=D7=9E=D7=9F?= Date: Tue, 15 Feb 2022 07:39:30 +0000 Subject: [PATCH 058/188] Added translation using Weblate (Hebrew) --- Riot/Assets/he.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) create mode 100644 Riot/Assets/he.lproj/Vector.strings diff --git a/Riot/Assets/he.lproj/Vector.strings b/Riot/Assets/he.lproj/Vector.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Riot/Assets/he.lproj/Vector.strings @@ -0,0 +1 @@ + From 61d3172d0819b38274c3ea8b4593f61ab62070fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=90=D7=9C=D7=95=D7=9F=20=D7=92=D7=9C=D7=A1=D7=9E=D7=9F?= Date: Tue, 15 Feb 2022 07:40:01 +0000 Subject: [PATCH 059/188] Added translation using Weblate (Hebrew) --- Riot/Assets/he.lproj/Localizable.strings | 1 + 1 file changed, 1 insertion(+) create mode 100644 Riot/Assets/he.lproj/Localizable.strings diff --git a/Riot/Assets/he.lproj/Localizable.strings b/Riot/Assets/he.lproj/Localizable.strings new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Riot/Assets/he.lproj/Localizable.strings @@ -0,0 +1 @@ + From 0595b5b5fb0b566081c9f20cd781d11d730c4f79 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 12:03:08 +0100 Subject: [PATCH 060/188] BubbleRoomCellLayoutConstants: Update constants and add new ones. --- .../BubbleRoomCellLayoutConstants.swift | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift index 2a978f82d..37442a342 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift @@ -21,9 +21,26 @@ import Foundation @objcMembers final class BubbleRoomCellLayoutConstants: NSObject { + /// Inner content view margins + static let innerContentViewMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 5.0, right: 0) + + // Text message bubbles margins from cell content view + static let outgoingBubbleBackgroundMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 80, bottom: 0, right: 34) - static let incomingBubbleBackgroundMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 80) + static let incomingBubbleBackgroundMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 48, bottom: 0, right: 80) + + static let bubbleTextViewInsets: UIEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 45) + + // Voice message + + static let voiceMessagePlaybackViewRightMargin: CGFloat = 40 + + // Polls + + static let pollBubbleBackgroundInsets: UIEdgeInsets = UIEdgeInsets(top: 2, left: 10, bottom: 0, right: 10) + + // Decoration margins static let threadSummaryViewMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 5, right: 0) } From 4b9afa0ee3891d8a35c851863b121f78a1a19098 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 12:05:31 +0100 Subject: [PATCH 061/188] Text message bubbles: Use constants. --- .../Common/TextMessageBaseBubbleCell.swift | 36 +------------------ .../TextMessageBubbleCellContentView.xib | 2 +- .../TextMessageIncomingBubbleCell.swift | 6 ++-- ...eOutgoingWithoutSenderInfoBubbleCell.swift | 5 ++- 4 files changed, 8 insertions(+), 41 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index f64e0d873..2c24723d3 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -40,15 +40,7 @@ class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDispla return } - // TODO: Use constants - - let messageLeftMargin: CGFloat = 48 - - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = messageLeftMargin - - self.bubbleCellContentView?.innerContentViewBottomContraint.constant = 5.0 - - self.bubbleCellContentView?.innerContentViewTrailingConstraint.constant = 34.0 + bubbleCellContentView?.innerContentViewBottomContraint.constant = BubbleRoomCellLayoutConstants.innerContentViewMargins.bottom let textMessageContentView = TextMessageBubbleCellContentView.instantiate() @@ -63,32 +55,6 @@ class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDispla if let messageTextView = self.messageTextView { messageTextView.tintColor = theme.tintColor } - -// self.setupDebug() - } - - // MARK: - Private - - private func setupDebug() { - - self.bubbleCellContentView?.innerContentView.backgroundColor = .yellow - - self.bubbleCellContentView?.layer.borderWidth = 1.0 - self.bubbleCellContentView?.layer.borderColor = UIColor.red.cgColor - - self.textMessageContentView?.layer.borderColor = UIColor.blue.cgColor - self.textMessageContentView?.layer.borderWidth = 1.0 - - - self.bubbleCellContentView?.readReceiptsContainerView.layer.borderColor = UIColor.yellow.cgColor - self.bubbleCellContentView?.readReceiptsContainerView.layer.borderWidth = 1.0 - - self.bubbleCellContentView?.reactionsContainerView.layer.borderColor = UIColor.blue.cgColor - self.bubbleCellContentView?.reactionsContainerView.layer.borderWidth = 1.0 - self.bubbleCellContentView?.reactionsContentView.backgroundColor = .blue - - self.bubbleCellContentView?.threadSummaryContainerView.layer.borderColor = UIColor.purple.cgColor - self.bubbleCellContentView?.threadSummaryContainerView.layer.borderWidth = 1.0 } } diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib index 90fba0291..0a09502f1 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib @@ -39,7 +39,7 @@ - + diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift index 7d133e2f2..d2aa686ec 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift @@ -39,10 +39,8 @@ class TextMessageIncomingBubbleCell: TextMessageBaseBubbleCell, BubbleIncomingRo private func setupBubbleConstraints() { - self.textMessageContentView?.bubbleBackgroundViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + self.bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left - let innerContentViewTrailingMargin = self.bubbleCellContentView?.innerContentViewTrailingConstraint.constant ?? 0 - - self.textMessageContentView?.bubbleBackgroundViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right - innerContentViewTrailingMargin + self.bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right } } diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift index 992d83ad9..edc945b31 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift @@ -39,6 +39,9 @@ class TextMessageOutgoingWithoutSenderInfoBubbleCell: TextMessageBaseBubbleCell, private func setupBubbleConstraints() { + self.bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + self.bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + guard let containerView = self.textMessageContentView, let bubbleBackgroundView = containerView.bubbleBackgroundView else { return } @@ -57,7 +60,7 @@ class TextMessageOutgoingWithoutSenderInfoBubbleCell: TextMessageBaseBubbleCell, // Setup new constraints - let leadingConstraint = bubbleBackgroundView.leadingAnchor.constraint(greaterThanOrEqualTo: containerView.leadingAnchor, constant: BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left) + let leadingConstraint = bubbleBackgroundView.leadingAnchor.constraint(greaterThanOrEqualTo: containerView.leadingAnchor) let trailingConstraint = bubbleBackgroundView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: 0) From dd43be272b1c423fa88d319efb407f79f3028528 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 12:07:41 +0100 Subject: [PATCH 062/188] File cells: Use constants. --- .../FileWithoutThumbnailIncomingBubbleCell.swift | 8 ++------ ...houtThumbnailOutoingWithoutSenderInfoBubbleCell.swift | 9 ++------- 2 files changed, 4 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift index bcc52efa8..dcf4ef447 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift @@ -23,12 +23,8 @@ class FileWithoutThumbnailIncomingBubbleCell: FileWithoutThumbnailBaseBubbleCell bubbleCellContentView?.showSenderInfo = true - // TODO: Use constants - let messageViewMarginRight: CGFloat = 80 - let messageLeftMargin: CGFloat = 48 - - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = messageViewMarginRight - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = messageLeftMargin + bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift index 4f2283770..f3d5e8a3a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift @@ -23,13 +23,8 @@ class FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell: FileWithoutThumbna bubbleCellContentView?.showSenderInfo = false - // TODO: Use constants - // Same as outgoing message - let rightMargin: CGFloat = 34.0 - let leftMargin: CGFloat = 80.0 - - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin + bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right self.setupBubbleDecorations() } From 9a9f4ebf7a967a05f246e7b04abf37b26c1efae3 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 12:09:13 +0100 Subject: [PATCH 063/188] Location sharing cells: Use constants. --- .../Location/Incoming/LocationIncomingBubbleCell.swift | 8 ++------ .../LocationOutgoingWithoutSenderInfoBubbleCell.swift | 3 +-- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift index 4a7fb08b5..97a80a5ca 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift @@ -21,12 +21,8 @@ class LocationIncomingBubbleCell: LocationBubbleCell, BubbleIncomingRoomCellProt override func setupViews() { super.setupViews() - // TODO: Use constants - let messageViewMarginRight: CGFloat = 80 - let messageLeftMargin: CGFloat = 48 - - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = messageViewMarginRight - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = messageLeftMargin + bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift index ef2061224..3d30a86b0 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift @@ -23,9 +23,8 @@ class LocationOutgoingWithoutSenderInfoBubbleCell: LocationBubbleCell, BubbleOut bubbleCellContentView?.showSenderInfo = false - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right self.setupBubbleDecorations() } From 106f1ad6c4855f6644d1efd86ee7dbb5b065b7a2 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 12:10:32 +0100 Subject: [PATCH 064/188] Poll cells: Use constants. --- .../Cells/Poll/Incoming/PollIncomingBubbleCell.swift | 10 ++++------ .../PollOutgoingWithoutSenderInfoBubbleCell.swift | 9 +++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift index c71810ef5..aee7f1030 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift @@ -21,13 +21,11 @@ class PollIncomingBubbleCell: PollBaseBubbleCell, BubbleIncomingRoomCellProtocol override func setupViews() { super.setupViews() - // TODO: Use constants - let bubbleBackgroundSideMargin: CGFloat = 10 - let messageViewMarginRight: CGFloat = 80 + bubbleBackgroundSideMargin - let messageLeftMargin: CGFloat = 48 + bubbleBackgroundSideMargin + let leftMargin: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.left + let rightMargin: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.right - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = messageViewMarginRight - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = messageLeftMargin + bubbleCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift index b16150d6c..2525b2af8 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift @@ -22,12 +22,9 @@ class PollOutgoingWithoutSenderInfoBubbleCell: PollBaseBubbleCell, BubbleOutgoin super.setupViews() bubbleCellContentView?.showSenderInfo = false - - // TODO: Use constants - // Same as outgoing message - let bubbleBackgroundSideMargin: CGFloat = 10 - let rightMargin: CGFloat = 34.0 + bubbleBackgroundSideMargin - let leftMargin: CGFloat = 80.0 + bubbleBackgroundSideMargin + + let leftMargin: CGFloat = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.left + let rightMargin: CGFloat = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.right bubbleCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin bubbleCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin From 8aafab94dd1cbfb4dc8c484e6d7d178f29a0c2ba Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 12:12:49 +0100 Subject: [PATCH 065/188] Voice message cells: Use constants. --- .../Incoming/VoiceMessageIncomingBubbleCell.swift | 13 ++++--------- ...essageOutgoingWithoutSenderInfoBubbleCell.swift | 14 ++++---------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift index febaf8720..b8907847f 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift @@ -20,16 +20,11 @@ class VoiceMessageIncomingBubbleCell: VoiceMessageBubbleCell, BubbleIncomingRoom override func setupViews() { super.setupViews() + + bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right - // TODO: Use constants - let messageViewMarginRight: CGFloat = 80 - let messageLeftMargin: CGFloat = 48 - let playbackViewRightMargin: CGFloat = 40 - - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = messageViewMarginRight - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = messageLeftMargin - - playbackController.playbackView.stackViewTrailingContraint.constant = playbackViewRightMargin + playbackController.playbackView.stackViewTrailingContraint.constant = BubbleRoomCellLayoutConstants.voiceMessagePlaybackViewRightMargin self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift index 5b0bffd7e..60964b9b4 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift @@ -22,17 +22,11 @@ class VoiceMessageOutgoingWithoutSenderInfoBubbleCell: VoiceMessageBubbleCell, B super.setupViews() bubbleCellContentView?.showSenderInfo = false - - // TODO: Use constants - // Same as outgoing message - let rightMargin: CGFloat = 34.0 - let leftMargin: CGFloat = 80.0 - let playbackViewRightMargin: CGFloat = 40 - - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin + + bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right - playbackController.playbackView.stackViewTrailingContraint.constant = playbackViewRightMargin + playbackController.playbackView.stackViewTrailingContraint.constant = BubbleRoomCellLayoutConstants.voiceMessagePlaybackViewRightMargin self.setupBubbleDecorations() } From 5dd278f7ead77d2b845e6cc4d6bbd9c6de19d04e Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 15 Feb 2022 15:46:22 +0300 Subject: [PATCH 066/188] Display thread list api errors --- Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift index 2242250ba..e63a63703 100644 --- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift +++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift @@ -269,6 +269,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol { self.threadsLoaded() case .failure(let error): MXLog.error("[ThreadListViewModel] loadData: error: \(error)") + self.viewState = .error(error) } } } From cbbff45a7a31fb7c4af7234ca1802e19945230b6 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Tue, 15 Feb 2022 10:55:06 +0000 Subject: [PATCH 067/188] Add CommonKit and Activity Signed-off-by: Andy Uhnak --- CommonKit/Common.xcconfig | 28 ++++ CommonKit/CommonKit.h | 27 ++++ CommonKit/Debug.xcconfig | 20 +++ CommonKit/Info.plist | 22 +++ CommonKit/Release.xcconfig | 20 +++ CommonKit/Source/Activity/Activity.swift | 94 +++++++++++++ .../Source/Activity/ActivityCenter.swift | 60 +++++++++ .../Source/Activity/ActivityDismissal.swift | 25 ++++ .../Source/Activity/ActivityPresentable.swift | 25 ++++ .../Source/Activity/ActivityRequest.swift | 28 ++++ .../Activity/Tests/ActivityCenterTests.swift | 55 ++++++++ .../Activity/Tests/ActivityPresenterSpy.swift | 29 ++++ .../Source/Activity/Tests/ActivityTests.swift | 127 ++++++++++++++++++ CommonKit/target.yml | 40 ++++++ CommonKit/targetUnitTests.yml | 42 ++++++ Riot/target.yml | 1 + project.yml | 4 +- 17 files changed, 646 insertions(+), 1 deletion(-) create mode 100644 CommonKit/Common.xcconfig create mode 100644 CommonKit/CommonKit.h create mode 100644 CommonKit/Debug.xcconfig create mode 100644 CommonKit/Info.plist create mode 100644 CommonKit/Release.xcconfig create mode 100644 CommonKit/Source/Activity/Activity.swift create mode 100644 CommonKit/Source/Activity/ActivityCenter.swift create mode 100644 CommonKit/Source/Activity/ActivityDismissal.swift create mode 100644 CommonKit/Source/Activity/ActivityPresentable.swift create mode 100644 CommonKit/Source/Activity/ActivityRequest.swift create mode 100644 CommonKit/Source/Activity/Tests/ActivityCenterTests.swift create mode 100644 CommonKit/Source/Activity/Tests/ActivityPresenterSpy.swift create mode 100644 CommonKit/Source/Activity/Tests/ActivityTests.swift create mode 100644 CommonKit/target.yml create mode 100644 CommonKit/targetUnitTests.yml diff --git a/CommonKit/Common.xcconfig b/CommonKit/Common.xcconfig new file mode 100644 index 000000000..38afbcfe3 --- /dev/null +++ b/CommonKit/Common.xcconfig @@ -0,0 +1,28 @@ +// +// Copyright 2021 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Config/AppIdentifiers.xcconfig" +#include "Config/AppVersion.xcconfig" + +PRODUCT_NAME = CommonKit +PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).commonkit + +INFOPLIST_FILE = CommonKit/Info.plist + +SKIP_INSTALL = YES diff --git a/CommonKit/CommonKit.h b/CommonKit/CommonKit.h new file mode 100644 index 000000000..b057961e6 --- /dev/null +++ b/CommonKit/CommonKit.h @@ -0,0 +1,27 @@ +// +// Copyright 2021 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 + +//! Project version number for CommonKit. +FOUNDATION_EXPORT double CommonKitVersionNumber; + +//! Project version string for CommonKit. +FOUNDATION_EXPORT const unsigned char CommonKitVersionString[]; + +// In this header, you should import all the public headers of your framework using statements like #import + + diff --git a/CommonKit/Debug.xcconfig b/CommonKit/Debug.xcconfig new file mode 100644 index 000000000..11a7288a4 --- /dev/null +++ b/CommonKit/Debug.xcconfig @@ -0,0 +1,20 @@ +// +// Copyright 2021 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Common.xcconfig" diff --git a/CommonKit/Info.plist b/CommonKit/Info.plist new file mode 100644 index 000000000..c0701c6d7 --- /dev/null +++ b/CommonKit/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + $(MARKETING_VERSION) + CFBundleVersion + $(CURRENT_PROJECT_VERSION) + + diff --git a/CommonKit/Release.xcconfig b/CommonKit/Release.xcconfig new file mode 100644 index 000000000..11a7288a4 --- /dev/null +++ b/CommonKit/Release.xcconfig @@ -0,0 +1,20 @@ +// +// Copyright 2021 Vector Creations Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +// Configuration settings file format documentation can be found at: +// https://help.apple.com/xcode/#/dev745c5c974 + +#include "Common.xcconfig" diff --git a/CommonKit/Source/Activity/Activity.swift b/CommonKit/Source/Activity/Activity.swift new file mode 100644 index 000000000..d72e87800 --- /dev/null +++ b/CommonKit/Source/Activity/Activity.swift @@ -0,0 +1,94 @@ +// +// Copyright 2021 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 + +/// An `Activity` represents the state of a temporary visual indicator, such as activity indicator, success notification or an error message. It does not directly manage the UI, instead it delegates to a `presenter` +/// whenever the UI should be shown or hidden. +/// +/// More than one `Activity` may be requested by the system at the same time (e.g. global syncing vs local refresh), +/// and the `ActivityCenter` will ensure that only one activity is shown at a given time, putting the other in a pending queue. +/// +/// A client that requests an activity can specify a default timeout after which the activity is dismissed, or it has to be manually +/// responsible for dismissing it via `cancel` method, or by deallocating itself. +public class Activity { + enum State { + case pending + case executing + case completed + } + + private let request: ActivityRequest + private let completion: () -> Void + + private(set) var state: State + + public init(request: ActivityRequest, completion: @escaping () -> Void) { + self.request = request + self.completion = completion + + state = .pending + } + + deinit { + cancel() + } + + internal func start() { + guard state == .pending else { + return + } + + state = .executing + request.presenter.present() + + switch request.dismissal { + case .manual: + break + case .timeout(let interval): + Timer.scheduledTimer(withTimeInterval: interval, repeats: false) { [weak self] _ in + self?.complete() + } + } + } + + /// Cancel the activity, triggering any dismissal action / animation + /// + /// Note: clients can call this method directly, if they have access to the `Activity`. + /// Once cancelled, `ActivityCenter` will automatically start the next `Activity` in the queue. + func cancel() { + complete() + } + + private func complete() { + guard state != .completed else { + return + } + if state == .executing { + request.presenter.dismiss() + } + + state = .completed + completion() + } +} + +public extension Activity { + func store(in collection: inout C) where C: RangeReplaceableCollection, C.Element == Activity { + collection.append(self) + } +} diff --git a/CommonKit/Source/Activity/ActivityCenter.swift b/CommonKit/Source/Activity/ActivityCenter.swift new file mode 100644 index 000000000..9d9e0c704 --- /dev/null +++ b/CommonKit/Source/Activity/ActivityCenter.swift @@ -0,0 +1,60 @@ +// +// Copyright 2021 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 + +/// A shared activity center with a single FIFO queue which will ensure only one activity is shown at a given time. +/// +/// `ActivityCenter` offers a `shared` center that can be used by any clients, but clients are also allowed +/// to create local `ActivityCenter` if the context requres multiple simultaneous activities. +public class ActivityCenter { + private class Weak { + weak var element: T? + init(_ element: T) { + self.element = element + } + } + + public static let shared = ActivityCenter() + private var queue = [Weak]() + + /// Add a new activity to the queue by providing a request. + /// + /// The queue will start the activity right away, if there are no currently running activities, + /// otherwise the activity will be put on hold. + public func add(_ request: ActivityRequest) -> Activity { + let activity = Activity(request: request) { [weak self] in + self?.startNextIfIdle() + } + + queue.append(Weak(activity)) + startNextIfIdle() + return activity + } + + private func startNextIfIdle() { + cleanup() + if let activity = queue.first?.element, activity.state == .pending { + activity.start() + } + } + + private func cleanup() { + queue.removeAll { + $0.element == nil || $0.element?.state == .completed + } + } +} diff --git a/CommonKit/Source/Activity/ActivityDismissal.swift b/CommonKit/Source/Activity/ActivityDismissal.swift new file mode 100644 index 000000000..69405c579 --- /dev/null +++ b/CommonKit/Source/Activity/ActivityDismissal.swift @@ -0,0 +1,25 @@ +// +// Copyright 2021 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 + +/// Different ways in which an `Activity` can be dismissed +public enum ActivityDismissal { + /// The `Activity` will not manage the dismissal, but will expect the calling client to do so manually + case manual + /// The `Activity` will be automatically dismissed after `TimeInterval` + case timeout(TimeInterval) +} diff --git a/CommonKit/Source/Activity/ActivityPresentable.swift b/CommonKit/Source/Activity/ActivityPresentable.swift new file mode 100644 index 000000000..5bb489fcc --- /dev/null +++ b/CommonKit/Source/Activity/ActivityPresentable.swift @@ -0,0 +1,25 @@ +// +// Copyright 2021 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 + +/// A presenter associated with and called by an `Activity`, and responsible for the underlying view shown on the screen. +public protocol ActivityPresentable { + /// Called when the `Activity` is started (manually or by the `ActivityCenter`) + func present() + /// Called when the `Activity` is manually cancelled or completed + func dismiss() +} diff --git a/CommonKit/Source/Activity/ActivityRequest.swift b/CommonKit/Source/Activity/ActivityRequest.swift new file mode 100644 index 000000000..f009fc211 --- /dev/null +++ b/CommonKit/Source/Activity/ActivityRequest.swift @@ -0,0 +1,28 @@ +// +// Copyright 2021 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 + +/// A request used to create an underlying `Activity`, allowing clients to only specify the visual aspects of an activity. +public struct ActivityRequest { + internal let presenter: ActivityPresentable + internal let dismissal: ActivityDismissal + + public init(presenter: ActivityPresentable, dismissal: ActivityDismissal) { + self.presenter = presenter + self.dismissal = dismissal + } +} diff --git a/CommonKit/Source/Activity/Tests/ActivityCenterTests.swift b/CommonKit/Source/Activity/Tests/ActivityCenterTests.swift new file mode 100644 index 000000000..a1e375851 --- /dev/null +++ b/CommonKit/Source/Activity/Tests/ActivityCenterTests.swift @@ -0,0 +1,55 @@ +// +// Copyright 2021 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 XCTest + +class ActivityCenterTests: XCTestCase { + var activities: [Activity]! + var center: ActivityCenter! + + override func setUp() { + activities = [] + center = ActivityCenter() + } + + func makeRequest() -> ActivityRequest { + return ActivityRequest( + presenter: ActivityPresenterSpy(), + dismissal: .manual + ) + } + + func testStartsActivityWhenAdded() { + let activity = center.add(makeRequest()) + XCTAssertEqual(activity.state, .executing) + } + + func testSecondActivityIsPending() { + center.add(makeRequest()).store(in: &activities) + let activity = center.add(makeRequest()) + XCTAssertEqual(activity.state, .pending) + } + + func testSecondActivityIsExecutingWhenFirstCompleted() { + let first = center.add(makeRequest()) + let second = center.add(makeRequest()) + + first.cancel() + + XCTAssertEqual(second.state, .executing) + } +} diff --git a/CommonKit/Source/Activity/Tests/ActivityPresenterSpy.swift b/CommonKit/Source/Activity/Tests/ActivityPresenterSpy.swift new file mode 100644 index 000000000..2a0d03249 --- /dev/null +++ b/CommonKit/Source/Activity/Tests/ActivityPresenterSpy.swift @@ -0,0 +1,29 @@ +// +// Copyright 2021 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 + +class ActivityPresenterSpy: ActivityPresentable { + var intel = [String]() + + func present() { + intel.append(#function) + } + + func dismiss() { + intel.append(#function) + } +} diff --git a/CommonKit/Source/Activity/Tests/ActivityTests.swift b/CommonKit/Source/Activity/Tests/ActivityTests.swift new file mode 100644 index 000000000..11cc7eec2 --- /dev/null +++ b/CommonKit/Source/Activity/Tests/ActivityTests.swift @@ -0,0 +1,127 @@ +// +// Copyright 2021 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 XCTest + +class ActivityTests: XCTestCase { + var presenter: ActivityPresenterSpy! + + override func setUp() { + super.setUp() + presenter = ActivityPresenterSpy() + } + + func makeActivity(dismissal: ActivityDismissal = .manual, callback: @escaping () -> Void = {}) -> Activity { + let request = ActivityRequest( + presenter: presenter, + dismissal: dismissal + ) + return Activity( + request: request, + completion: callback + ) + } + + // MARK: - State + + func testNewActivityIsPending() { + let activity = makeActivity() + XCTAssertEqual(activity.state, .pending) + } + + func testStartedActivityIsExecuting() { + let activity = makeActivity() + activity.start() + XCTAssertEqual(activity.state, .executing) + } + + func testCancelledActivityIsCompleted() { + let activity = makeActivity() + activity.cancel() + XCTAssertEqual(activity.state, .completed) + } + + // MARK: - Presenter + + func testStartingActivityPresentsUI() { + let activity = makeActivity() + activity.start() + XCTAssertEqual(presenter.intel, ["present()"]) + } + + func testAllowStartingOnlyOnce() { + let activity = makeActivity() + activity.start() + presenter.intel = [] + + activity.start() + + XCTAssertEqual(presenter.intel, []) + } + + func testCancellingActivityDismissesUI() { + let activity = makeActivity() + activity.start() + presenter.intel = [] + + activity.cancel() + + XCTAssertEqual(presenter.intel, ["dismiss()"]) + } + + func testAllowCancellingOnlyOnce() { + let activity = makeActivity() + activity.start() + activity.cancel() + presenter.intel = [] + + activity.cancel() + + XCTAssertEqual(presenter.intel, []) + } + + // MARK: - Dismissal + + func testDismissAfterTimeout() { + let interval: TimeInterval = 0.01 + let activity = makeActivity(dismissal: .timeout(interval)) + + activity.start() + + let exp = expectation(description: "") + DispatchQueue.main.asyncAfter(deadline: .now() + interval) { + exp.fulfill() + } + waitForExpectations(timeout: 1) + + XCTAssertEqual(activity.state, .completed) + } + + // MARK: - Completion callback + + func testTriggersCallbackWhenCompleted() { + var didComplete = false + let activity = makeActivity { + didComplete = true + } + activity.start() + + activity.cancel() + + XCTAssertTrue(didComplete) + } +} diff --git a/CommonKit/target.yml b/CommonKit/target.yml new file mode 100644 index 000000000..fad6e8375 --- /dev/null +++ b/CommonKit/target.yml @@ -0,0 +1,40 @@ +name: CommonKit + +schemes: + CommonKit: + analyze: + config: Debug + archive: + config: Release + build: + targets: + CommonKit: + - running + - testing + - profiling + - analyzing + - archiving + profile: + config: Release + run: + config: Debug + disableMainThreadChecker: true + test: + config: Debug + disableMainThreadChecker: true + targets: + - CommonKitUnitTests + +targets: + CommonKit: + type: framework + platform: iOS + + configFiles: + Debug: Debug.xcconfig + Release: Release.xcconfig + + sources: + - path: . + excludes: + - "**/Tests/**" diff --git a/CommonKit/targetUnitTests.yml b/CommonKit/targetUnitTests.yml new file mode 100644 index 000000000..4a8f8a7b2 --- /dev/null +++ b/CommonKit/targetUnitTests.yml @@ -0,0 +1,42 @@ +name: CommonKitUnitTests + +schemes: + CommonKitUnitTests: + analyze: + config: Debug + archive: + config: Release + build: + targets: + CommonKitUnitTests: + - running + - testing + - profiling + - analyzing + - archiving + profile: + config: Release + run: + config: Debug + disableMainThreadChecker: true + test: + config: Debug + disableMainThreadChecker: true + targets: + - CommonKitUnitTests + +targets: + CommonKitUnitTests: + type: bundle.unit-test + platform: iOS + + dependencies: + - target: CommonKit + + configFiles: + Debug: Debug.xcconfig + Release: Release.xcconfig + + sources: + - path: . + diff --git a/Riot/target.yml b/Riot/target.yml index f8f52a7da..1abcaae6c 100644 --- a/Riot/target.yml +++ b/Riot/target.yml @@ -35,6 +35,7 @@ targets: - target: SiriIntents - target: RiotNSE - target: DesignKit + - target: CommonKit - package: Mapbox configFiles: diff --git a/project.yml b/project.yml index dcd15f63b..7bb2ef0a0 100644 --- a/project.yml +++ b/project.yml @@ -35,9 +35,11 @@ include: - path: RiotSwiftUI/target.yml - path: RiotSwiftUI/targetUnitTests.yml - path: RiotSwiftUI/targetUITests.yml + - path: CommonKit/target.yml + - path: CommonKit/targetUnitTests.yml packages: Mapbox: url: https://github.com/maplibre/maplibre-gl-native-distribution minVersion: 5.12.2 - maxVersion: 5.13.0 \ No newline at end of file + maxVersion: 5.13.0 From 70751a6aaa2ed4b890d7b59ce6a2e3a0db9ce04f Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 14:46:54 +0100 Subject: [PATCH 068/188] PollBaseBubbleCell: Use constants. --- .../Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift index 99a6afe56..bac34614c 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift @@ -57,10 +57,10 @@ class PollBaseBubbleCell: PollBubbleCell { private func addBubbleBackgroundView(_ bubbleBackgroundView: RoomMessageBubbleBackgroundView, to pollView: UIView) { - let topMargin: CGFloat = 2.0 - let leftMargin: CGFloat = 10.0 - let rightMargin: CGFloat = 10.0 // Add extra space for timestamp - let bottomMargin: CGFloat = 0.0 // + let topMargin = BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.top + let leftMargin = BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.left + let rightMargin = BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.right + let bottomMargin = BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.bottom let topAnchor = pollView.topAnchor let leadingAnchor = pollView.leadingAnchor From 0e5d1a97c50376d6419f939280d7756ce9558e61 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Tue, 15 Feb 2022 13:49:29 +0000 Subject: [PATCH 069/188] Changelog --- changelog.d/4829.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4829.change diff --git a/changelog.d/4829.change b/changelog.d/4829.change new file mode 100644 index 000000000..e4f187451 --- /dev/null +++ b/changelog.d/4829.change @@ -0,0 +1 @@ +CommonKit: Create a new framework with common functionality and create Activity and ActivityCenter From 1a4ba860d9db8fdbd97a7ba370e51f0e6ab1fb3a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 15:53:52 +0100 Subject: [PATCH 070/188] BubbleRoomCellLayoutUpdater: User constants. --- .../BubbleCells/RoomBubbleCellLayout.swift | 3 +++ .../Bubble/BubbleRoomCellLayoutUpdater.swift | 21 +++++++------------ 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift b/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift index 641bc0677..46ba7e618 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift +++ b/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift @@ -20,6 +20,9 @@ import Foundation @objcMembers final class RoomBubbleCellLayout: NSObject { + /// Inner content view margins + static let innerContentViewMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 57, bottom: 0.0, right: 0) + // Reactions static let reactionsViewTopMargin: CGFloat = 1.0 diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift index 4cd22c10b..f619471f7 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift @@ -152,11 +152,10 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { private func getIncomingMessageTextViewInsets(from bubbleCell: MXKRoomBubbleTableViewCell) -> UIEdgeInsets { - let bubbleBgRightMargin: CGFloat = 45 let messageViewMarginTop: CGFloat = 0 - let messageViewMarginBottom: CGFloat = -0 + let messageViewMarginBottom: CGFloat = 0 let messageViewMarginLeft: CGFloat = 0 - let messageViewMarginRight: CGFloat = 80 + bubbleBgRightMargin + let messageViewMarginRight: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.right let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight) @@ -180,13 +179,12 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { } private func getOutgoingMessageTextViewMargins(from bubbleCell: MXKRoomBubbleTableViewCell) -> UIEdgeInsets { - - let innerContentLeftMargin: CGFloat = 57 let messageViewMarginTop: CGFloat = 0 let messageViewMarginBottom: CGFloat = 0 - let messageViewMarginLeft: CGFloat = 80.0 + innerContentLeftMargin - let messageViewMarginRight: CGFloat = 78.0 + let messageViewMarginLeft = + BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + RoomBubbleCellLayout.innerContentViewMargins.left + let messageViewMarginRight = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.right let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight) @@ -230,10 +228,8 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { } let contentView = cell.contentView - - // TODO: Use constants - // Same as URL preview - let rightMargin: CGFloat = 34.0 + + let rightMargin = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right if let attachViewLeadingConstraint = cell.attachViewLeadingConstraint { attachViewLeadingConstraint.isActive = false @@ -263,8 +259,7 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { let contentView = cell.contentView - // TODO: Use constants - let leftMargin: CGFloat = 67 + let leftMargin: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left let leftConstraint = attachmentView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: -leftMargin) From 16aa2b18769bb0e4fd74c435fed6b659bac20a64 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 17:11:03 +0100 Subject: [PATCH 071/188] BubbleRoomCellLayoutConstants: Add new decoration constraints. --- .../Bubble/BubbleRoomCellLayoutConstants.swift | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift index 37442a342..52e264b13 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift @@ -32,6 +32,8 @@ final class BubbleRoomCellLayoutConstants: NSObject { static let bubbleTextViewInsets: UIEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 45) + static let bubbleCornerRadius: CGFloat = 12.0 + // Voice message static let voiceMessagePlaybackViewRightMargin: CGFloat = 40 @@ -42,5 +44,15 @@ final class BubbleRoomCellLayoutConstants: NSObject { // Decoration margins - static let threadSummaryViewMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 5, right: 0) + // Timestamp margins + + /// Timestamp margins for sticker cell, margin is relative to the image view + static let stickerTimestampViewMargins = UIEdgeInsets(top: 0, left: 0, bottom: 20, right: -27) // Right margin is not reliable there, if the text size change this one is not working anymore + + /// Timestamp margins inside bubble + static let bubbleTimestampViewMargins = UIEdgeInsets(top: 0, left: 0, bottom: 4.0, right: 8.0) + + static let reactionsViewMargins = UIEdgeInsets(top: 4, left: 0, bottom: 0, right: 0) + + static let threadSummaryViewMargins: UIEdgeInsets = UIEdgeInsets(top: 8.0, left: 0, bottom: 5, right: 0) } From 9fc323331287aa3722180cea5bfe940e03c6e498 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 17:11:41 +0100 Subject: [PATCH 072/188] RoomMessageBubbleBackgroundView: Use constants. --- .../Bubble/RoomMessageBubbleBackgroundView.swift | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift index da79211b2..45ad8e1be 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift @@ -19,12 +19,6 @@ import UIKit class RoomMessageBubbleBackgroundView: UIView { - // MARK: - Constant - - private enum Constants { - static let cornerRadius: CGFloat = 12.0 - } - // MARK: - Properties private var heightConstraint: NSLayoutConstraint? @@ -49,7 +43,7 @@ class RoomMessageBubbleBackgroundView: UIView { private func commonInit() { self.translatesAutoresizingMaskIntoConstraints = false self.layer.masksToBounds = true - self.layer.cornerRadius = Constants.cornerRadius + self.layer.cornerRadius = BubbleRoomCellLayoutConstants.bubbleCornerRadius } // MARK: - Public @@ -82,7 +76,7 @@ extension RoomMessageBubbleBackgroundView: TimestampDisplayable { self.removeTimestampView() - self.addTimestampView(timestampView, rightMargin: 8.0, bottomMargin: 4.0) + self.addTimestampView(timestampView, rightMargin: BubbleRoomCellLayoutConstants.bubbleTimestampViewMargins.right, bottomMargin: BubbleRoomCellLayoutConstants.bubbleTimestampViewMargins.bottom) self.timestampView = timestampView } From d392791ec38c08c490203795354e3d4ec74fe866 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 17:11:51 +0100 Subject: [PATCH 073/188] FileWithoutThumbnailCellContentView: Use constants. --- .../Common/FileWithoutThumbnailCellContentView.swift | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift index ce0471dad..1d2058a27 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift @@ -19,13 +19,6 @@ import Reusable final class FileWithoutThumbnailCellContentView: UIView, NibLoadable { - // MARK: - Constants - - private enum Constants { - // TODO: Reuse constants, same as bubble bg - static let cornerRadius: CGFloat = 12.0 - } - // MARK: - Properties // MARK: Outlets @@ -61,7 +54,7 @@ final class FileWithoutThumbnailCellContentView: UIView, NibLoadable { override func layoutSubviews() { super.layoutSubviews() - self.layer.cornerRadius = Constants.cornerRadius + self.layer.cornerRadius = BubbleRoomCellLayoutConstants.bubbleCornerRadius } // MARK: - Public From 3db5c7a59e9e3429d573817a533bc375caa02973 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 15 Feb 2022 17:27:44 +0100 Subject: [PATCH 074/188] BubbleRoomTimelineCellDecorator: Use layout constants. --- .../BubbleRoomTimelineCellDecorator.swift | 52 ++++++++----------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift index 7feac51fb..44efeceb1 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift @@ -44,8 +44,8 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { let attachmentView = cell.attachmentView { // Prevent overlap with send status icon - let bottomMargin: CGFloat = 20.0 - let rightMargin: CGFloat = -27.0 + let bottomMargin: CGFloat = BubbleRoomCellLayoutConstants.stickerTimestampViewMargins.bottom + let rightMargin: CGFloat = BubbleRoomCellLayoutConstants.stickerTimestampViewMargins.right self.addTimestampLabel(timestampLabel, to: cell, @@ -105,43 +105,38 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { let cellContentView = cell.contentView cellContentView.addSubview(reactionsView) - - // TODO: Use constants - let topMargin: CGFloat = 4.0 + + let topMargin: CGFloat = RoomBubbleCellLayout.reactionsViewTopMargin let leftMargin: CGFloat let rightMargin: CGFloat // Incoming message if cellData.isIncoming { - var incomingLeftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + var incomingLeftMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left if cellData.containsBubbleComponentWithEncryptionBadge { incomingLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin } - leftMargin = incomingLeftMargin - 6.0 + leftMargin = incomingLeftMargin - // TODO: Use constants - let messageViewMarginRight: CGFloat = 42.0 + rightMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right - rightMargin = messageViewMarginRight } else { // Outgoing message reactionsView.alignment = .right - - // TODO: Use constants - var outgoingLeftMargin: CGFloat = 80.0 + + var outgoingLeftMargin = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left if cellData.containsBubbleComponentWithEncryptionBadge { outgoingLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin } leftMargin = outgoingLeftMargin - - // TODO: Use constants - rightMargin = 33 + + rightMargin = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right } let leadingConstraint = reactionsView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin) @@ -190,14 +185,11 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin } - leftMargin-=5.0 - leadingOrTrailingConstraint = urlPreviewView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin) } else { // Outgoing message - // TODO: Use constants - let rightMargin: CGFloat = 34.0 + let rightMargin: CGFloat = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right leadingOrTrailingConstraint = urlPreviewView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin) } @@ -238,14 +230,12 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { // Incoming message if cellData.isIncoming { - leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + leftMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left if cellData.containsBubbleComponentWithEncryptionBadge { leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin } - leftMargin-=5.0 - - rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin + rightMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right leadingConstraint = threadSummaryView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin) @@ -253,10 +243,9 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { constant: -rightMargin) } else { // Outgoing message - - // TODO: Use constants - leftMargin = 80.0 - rightMargin = 34.0 + + leftMargin = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + rightMargin = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right leadingConstraint = threadSummaryView.leadingAnchor.constraint(greaterThanOrEqualTo: cellContentView.leadingAnchor, constant: leftMargin) @@ -264,7 +253,8 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { constant: -rightMargin) } - let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin + 15.0 + let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin + let height = ThreadSummaryView.contentViewHeight(forThread: threadSummaryView.thread, fitting: cellData.maxTextViewWidth) @@ -376,8 +366,8 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { to cell: MXKRoomBubbleTableViewCell, on containerView: UIView, constrainingView: UIView, - rightMargin: CGFloat = 8.0, - bottomMargin: CGFloat = 4.0) { + rightMargin: CGFloat = BubbleRoomCellLayoutConstants.bubbleTimestampViewMargins.right, + bottomMargin: CGFloat = BubbleRoomCellLayoutConstants.bubbleTimestampViewMargins.bottom) { timestampLabel.translatesAutoresizingMaskIntoConstraints = false cell.addTemporarySubview(timestampLabel) From e5bbfa9a30239f3375ec980538eadf7ea1e6293b Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 15 Feb 2022 17:54:17 +0000 Subject: [PATCH 075/188] Add support for UserProperties to analytics and capture FTUE use case selection. Additionally update taps to interactions following updates in the analytics event repo. --- Riot/Modules/Analytics/Analytics.swift | 43 ++++++++++++++----- .../Analytics/AnalyticsClientProtocol.swift | 11 ++++- Riot/Modules/Analytics/AnalyticsScreen.swift | 12 ++++++ .../Analytics/AnalyticsUIElement.swift | 12 +++--- ...erSessionPropertiesUseCase+Analytics.swift | 33 ++++++++++++++ .../Analytics/PostHogAnalyticsClient.swift | 9 +++- .../Onboarding/OnboardingCoordinator.swift | 12 ++++-- changelog.d/5590.change | 1 + 8 files changed, 111 insertions(+), 22 deletions(-) create mode 100644 Riot/Modules/Analytics/Helpers/UserSessionPropertiesUseCase+Analytics.swift create mode 100644 changelog.d/5590.change diff --git a/Riot/Modules/Analytics/Analytics.swift b/Riot/Modules/Analytics/Analytics.swift index d3b9c3ac1..6f6a67597 100644 --- a/Riot/Modules/Analytics/Analytics.swift +++ b/Riot/Modules/Analytics/Analytics.swift @@ -108,6 +108,7 @@ import AnalyticsEvents !RiotSettings.shared.isIdentifiedForAnalytics else { return } + let userProperties = makeUserProperties(for: session) let service = AnalyticsService(session: session) self.service = service @@ -116,7 +117,7 @@ import AnalyticsEvents switch result { case .success(let settings): - self.identify(with: settings) + self.identify(with: settings, and: userProperties) self.service = nil case .failure: MXLog.error("[Analytics] Failed to use analytics settings. Will continue to run without analytics ID.") @@ -149,17 +150,30 @@ import AnalyticsEvents /// Identify (pseudonymously) any future events with the ID from the analytics account data settings. /// - Parameter settings: The settings to use for identification. The ID must be set *before* calling this method. - private func identify(with settings: AnalyticsSettings) { + /// - Parameter userProperties: Any user properties that should be set for creating cohorts etc. + private func identify(with settings: AnalyticsSettings, and userProperties: AnalyticsEvent.UserProperties) { guard let id = settings.id else { MXLog.error("[Analytics] identify(with:) called before an ID has been generated.") return } - client.identify(id: id) + client.identify(id: id, userProperties: userProperties) MXLog.debug("[Analytics] Identified.") RiotSettings.shared.isIdentifiedForAnalytics = true } + /// Returns the user properties for use when identifying a session. + /// - Parameter session: The session to gather any user properties from. + /// - Returns: The properties to be set. + private func makeUserProperties(for session: MXSession) -> AnalyticsEvent.UserProperties { + var useCaseSelection: AnalyticsEvent.UserProperties.FtueUseCaseSelection? + if let userId = session.credentials.userId, let userSession = UserSessionsService.shared.userSession(withUserId: userId) { + useCaseSelection = userSession.userProperties.useCase?.analyticsName + } + + return AnalyticsEvent.UserProperties(ftueUseCaseSelection: useCaseSelection, numSpaces: nil) + } + /// Capture an event in the `client`. /// - Parameter event: The event to capture. private func capture(event: AnalyticsEventProtocol) { @@ -171,6 +185,14 @@ import AnalyticsEvents // The following methods are exposed for compatibility with Objective-C as // the `capture` method and the generated events cannot be bridged from Swift. extension Analytics { + /// Updates any user properties to help with creating cohorts. + /// + /// Only non-nil properties will be updated when calling this method. + func updateUserProperties(ftueUseCase: UserSessionProperties.UseCase? = nil) { + let userProperties = AnalyticsEvent.UserProperties(ftueUseCaseSelection: ftueUseCase?.analyticsName, numSpaces: nil) + client.updateUserProperties(userProperties) + } + /// Track the presentation of a screen /// - Parameters: /// - screen: The screen that was shown. @@ -186,20 +208,21 @@ extension Analytics { trackScreen(screen, duration: nil) } - /// Track an element that has been tapped + /// Track an element that has been interacted with /// - Parameters: - /// - tap: The element that was tapped + /// - uiElement: The element that was interacted with + /// - interactionType: The way in with the element was interacted with /// - index: The index of the element, if it's in a list of elements - func trackTap(_ tap: AnalyticsUIElement, index: Int?) { - let event = AnalyticsEvent.Click(index: index, name: tap.elementName) + func trackInteraction(_ uiElement: AnalyticsUIElement, interactionType: AnalyticsEvent.Interaction.InteractionType, index: Int?) { + let event = AnalyticsEvent.Interaction(index: index, interactionType: interactionType, name: uiElement.name) client.capture(event) } /// Track an element that has been tapped without including an index /// - Parameters: - /// - tap: The element that was tapped - func trackTap(_ tap: AnalyticsUIElement) { - trackTap(tap, index: nil) + /// - uiElement: The element that was tapped + func trackInteraction(_ uiElement: AnalyticsUIElement) { + trackInteraction(uiElement, interactionType: .Touch, index: nil) } /// Track an E2EE error that occurred diff --git a/Riot/Modules/Analytics/AnalyticsClientProtocol.swift b/Riot/Modules/Analytics/AnalyticsClientProtocol.swift index af07a58fb..5ae391f61 100644 --- a/Riot/Modules/Analytics/AnalyticsClientProtocol.swift +++ b/Riot/Modules/Analytics/AnalyticsClientProtocol.swift @@ -26,7 +26,10 @@ protocol AnalyticsClientProtocol { /// Associate the client with an ID. This is persisted until `reset` is called. /// - Parameter id: The ID to associate with the user. - func identify(id: String) + /// - Parameter userProperties: Any user properties that should be included. + /// + /// Only non-nil user properties will be updated when calling this method. + func identify(id: String, userProperties: AnalyticsEvent.UserProperties) /// Reset all stored properties and any event queues on the client. Note that /// the client will remain active, but in a fresh unidentified state. @@ -45,4 +48,10 @@ protocol AnalyticsClientProtocol { /// Capture the supplied analytics screen event. /// - Parameter event: The screen event to capture. func screen(_ event: AnalyticsScreenProtocol) + + /// Updates any user properties to help with creating cohorts. + /// - Parameter userProperties: The user properties to be updated. + /// + /// Only non-nil properties will be updated when calling this method. + func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) } diff --git a/Riot/Modules/Analytics/AnalyticsScreen.swift b/Riot/Modules/Analytics/AnalyticsScreen.swift index 86f567acd..048e484e8 100644 --- a/Riot/Modules/Analytics/AnalyticsScreen.swift +++ b/Riot/Modules/Analytics/AnalyticsScreen.swift @@ -18,6 +18,10 @@ import Foundation import AnalyticsEvents @objc enum AnalyticsScreen: Int { + case welcome + case login + case register + case forgotPassword case sidebar case home case favourites @@ -51,6 +55,14 @@ import AnalyticsEvents /// The screen name reported to the AnalyticsEvent. var screenName: AnalyticsEvent.Screen.ScreenName { switch self { + case .welcome: + return .Welcome + case .login: + return .Login + case .register: + return .Register + case .forgotPassword: + return .ForgotPassword case .sidebar: return .MobileSidebar case .home: diff --git a/Riot/Modules/Analytics/AnalyticsUIElement.swift b/Riot/Modules/Analytics/AnalyticsUIElement.swift index 93a08e7e2..5a25d453e 100644 --- a/Riot/Modules/Analytics/AnalyticsUIElement.swift +++ b/Riot/Modules/Analytics/AnalyticsUIElement.swift @@ -16,17 +16,17 @@ import AnalyticsEvents -/// A tappable UI element that can be track in Analytics. +/// A tappable UI element that can be tracked in Analytics. @objc enum AnalyticsUIElement: Int { - case sendMessageButton + case removeMe /// The element name reported to the AnalyticsEvent. - var elementName: AnalyticsEvent.Click.Name { + var name: AnalyticsEvent.Interaction.Name { switch self { // Note: This is a test element that doesn't need to be captured. - // It will likely be removed when the AnalyticsEvent.Click is updated. - case .sendMessageButton: - return .SendMessageButton + // It can be removed when some elements are added that relate to mobile. + case .removeMe: + return .WebRoomSettingsLeaveButton } } } diff --git a/Riot/Modules/Analytics/Helpers/UserSessionPropertiesUseCase+Analytics.swift b/Riot/Modules/Analytics/Helpers/UserSessionPropertiesUseCase+Analytics.swift new file mode 100644 index 000000000..c5e601b37 --- /dev/null +++ b/Riot/Modules/Analytics/Helpers/UserSessionPropertiesUseCase+Analytics.swift @@ -0,0 +1,33 @@ +// +// Copyright 2021 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 AnalyticsEvents + +extension UserSessionProperties.UseCase { + var analyticsName: AnalyticsEvent.UserProperties.FtueUseCaseSelection { + switch self { + case .personalMessaging: + return .PersonalMessaging + case .workMessaging: + return .WorkMessaging + case .communityMessaging: + return .CommunityMessaging + case .skipped: + return .Skip + } + } +} diff --git a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift index 1c7172112..69724a5d0 100644 --- a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift +++ b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift @@ -35,8 +35,9 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { postHog?.enable() } - func identify(id: String) { - postHog?.identify(id) + func identify(id: String, userProperties: AnalyticsEvent.UserProperties) { + // As user properties overwrite old ones, compactMap the dictionary to avoid resetting any missing properties + postHog?.identify(id, properties: userProperties.properties.compactMapValues { $0 }) } func reset() { @@ -62,4 +63,8 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { postHog?.screen(event.screenName.rawValue, properties: event.properties) } + func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) { + // As user properties overwrite old ones via $set, compactMap the dictionary to avoid resetting any missing properties + postHog?.capture("$identify", properties: ["$set": userProperties.properties.compactMapValues { $0 }]) + } } diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 571140f43..2047e4834 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -222,12 +222,18 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { completion?() isShowingAuthentication = false - // Handle the chosen use case if appropriate + // Handle the chosen use case where applicable if authenticationType == MXKAuthenticationTypeRegister, - let useCaseResult = useCaseResult, + let useCase = useCaseResult?.userSessionPropertyValue, let userSession = UserSessionsService.shared.mainUserSession { // Store the value in the user's session - userSession.userProperties.useCase = useCaseResult.userSessionPropertyValue + userSession.userProperties.useCase = useCase + + // Capture the use case if analytics are running. + // Otherwise it will be included when identifying if opted in. + if Analytics.shared.isRunning { + Analytics.shared.updateUserProperties(ftueUseCase: useCase) + } } } } diff --git a/changelog.d/5590.change b/changelog.d/5590.change new file mode 100644 index 000000000..493e2d5a3 --- /dev/null +++ b/changelog.d/5590.change @@ -0,0 +1 @@ +Add support for UserProperties to analytics and capture FTUE use case selection. \ No newline at end of file From 9dc663b0409b86e5d680228a4804175a521dab0f Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 15 Feb 2022 20:53:45 +0000 Subject: [PATCH 076/188] Update launch screen tint colour. --- Riot/Assets/Base.lproj/LaunchScreen.storyboard | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/Base.lproj/LaunchScreen.storyboard b/Riot/Assets/Base.lproj/LaunchScreen.storyboard index 47f7c6d30..07c996ecf 100644 --- a/Riot/Assets/Base.lproj/LaunchScreen.storyboard +++ b/Riot/Assets/Base.lproj/LaunchScreen.storyboard @@ -1,9 +1,10 @@ - + - + + @@ -21,14 +22,14 @@ - + - + @@ -42,5 +43,8 @@ + + + From 38e4375f305d4ad280ea13d9ad71b85b003babb5 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 09:36:52 +0100 Subject: [PATCH 077/188] Room timeline: Move files in explicit folders. --- .../BaseBubbleCell/BaseBubbleCell.swift | 0 .../BaseBubbleCell/BubbleCellContentView.swift | 0 .../BaseBubbleCell/BubbleCellContentView.xib | 0 .../BaseBubbleCell/BubbleCellReactionsDisplayable.swift | 0 .../BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift | 0 .../BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift | 0 .../BaseBubbleCell/RoomCellDecorationAlignment.swift | 0 .../BaseBubbleCell/RoomCellURLPreviewDisplayable.swift | 0 .../BaseBubbleCell/TimestampDisplayable.swift | 0 .../Call/CallBubbleCellBaseContentView.swift | 0 .../Call/CallBubbleCellBaseContentView.xib | 0 .../Call/Common/CallTileActionButton.swift | 0 .../Call/Common/HorizontalButtonsContainerView.swift | 0 .../Call/Common/HorizontalButtonsContainerView.xib | 0 .../Call/Direct/RoomDirectCallStatusBubbleCell.swift | 0 .../Call/Group/RoomGroupCallStatusBubbleCell.swift | 0 .../Call/RoomBaseCallBubbleCell.swift | 0 .../BubbleCells => TimelineCells}/Call/RoomBaseCallBubbleCell.xib | 0 .../Common/MXKRoomBubbleTableViewCell.h | 0 .../Common/MXKRoomBubbleTableViewCell.m | 0 .../Common/MXKRoomIOSBubbleTableViewCell.h | 0 .../Common/MXKRoomIOSBubbleTableViewCell.m | 0 .../Common/MXKRoomIOSOutgoingBubbleTableViewCell.h | 0 .../Common/MXKRoomIOSOutgoingBubbleTableViewCell.m | 0 .../Common/MXKRoomIOSOutgoingBubbleTableViewCell.xib | 0 .../Common/MXKRoomIncomingBubbleTableViewCell.h | 0 .../Common/MXKRoomIncomingBubbleTableViewCell.m | 0 .../Common/MXKRoomOutgoingBubbleTableViewCell.h | 0 .../Common/MXKRoomOutgoingBubbleTableViewCell.m | 0 .../EmptyContent/MXKRoomEmptyBubbleTableViewCell.h | 0 .../EmptyContent/MXKRoomEmptyBubbleTableViewCell.m | 0 .../EmptyContent/MXKRoomEmptyBubbleTableViewCell.xib | 0 .../EmptyContent/RoomEmptyBubbleCell.h | 0 .../EmptyContent/RoomEmptyBubbleCell.m | 0 .../EmptyContent/RoomEmptyBubbleCell.xib | 0 .../Encryption/RoomEncryptedDataBubbleCell.h | 0 .../Encryption/RoomEncryptedDataBubbleCell.m | 0 .../KeyVerification/KeyVerificationBaseBubbleCell.swift | 0 .../KeyVerification/KeyVerificationCellInnerContentView.swift | 0 .../KeyVerification/KeyVerificationCellInnerContentView.xib | 0 .../KeyVerification/KeyVerificationConclusionBubbleCell.swift | 0 .../KeyVerification/KeyVerificationConclusionViewData.swift | 0 .../KeyVerificationConclusionWithPaginationTitleBubbleCell.swift | 0 .../KeyVerificationIncomingRequestApprovalBubbleCell.swift | 0 .../KeyVerificationIncomingRequestApprovalViewData.swift | 0 ...tionIncomingRequestApprovalWithPaginationTitleBubbleCell.swift | 0 .../KeyVerification/KeyVerificationRequestStatusBubbleCell.swift | 0 .../KeyVerification/KeyVerificationRequestStatusViewData.swift | 0 ...eyVerificationRequestStatusWithPaginationTitleBubbleCell.swift | 0 .../MessageTyping/RoomTypingBubbleCell.swift | 0 .../MessageTyping/RoomTypingBubbleCell.xib | 0 .../RoomCreation/RoomCreationCollapsedBubbleCell.h | 0 .../RoomCreation/RoomCreationCollapsedBubbleCell.m | 0 .../RoomCreation/RoomCreationCollapsedBubbleCell.xib | 0 .../RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.h | 0 .../RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.m | 0 .../RoomCreationWithPaginationCollapsedBubbleCell.xib | 0 .../RoomCreationIntro/RoomCreationIntroCell.swift | 0 .../RoomCreationIntro/RoomCreationIntroCellContentView.swift | 0 .../RoomCreationIntro/RoomCreationIntroCellContentView.xib | 0 .../RoomCreationIntro/RoomCreationIntroViewData.swift | 0 .../RoomMembership/RoomMembershipBubbleCell.h | 0 .../RoomMembership/RoomMembershipBubbleCell.m | 0 .../RoomMembership/RoomMembershipBubbleCell.xib | 0 .../RoomMembership/RoomMembershipCollapsedBubbleCell.h | 0 .../RoomMembership/RoomMembershipCollapsedBubbleCell.m | 0 .../RoomMembership/RoomMembershipCollapsedBubbleCell.xib | 0 .../RoomMembershipCollapsedWithPaginationTitleBubbleCell.h | 0 .../RoomMembershipCollapsedWithPaginationTitleBubbleCell.m | 0 .../RoomMembershipCollapsedWithPaginationTitleBubbleCell.xib | 0 .../RoomMembership/RoomMembershipExpandedBubbleCell.h | 0 .../RoomMembership/RoomMembershipExpandedBubbleCell.m | 0 .../RoomMembership/RoomMembershipExpandedBubbleCell.xib | 0 .../RoomMembershipExpandedWithPaginationTitleBubbleCell.h | 0 .../RoomMembershipExpandedWithPaginationTitleBubbleCell.m | 0 .../RoomMembershipExpandedWithPaginationTitleBubbleCell.xib | 0 .../RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.h | 0 .../RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.m | 0 .../RoomMembershipWithPaginationTitleBubbleCell.xib | 0 .../RoomPredecessor/RoomPredecessorBubbleCell.h | 0 .../RoomPredecessor/RoomPredecessorBubbleCell.m | 0 .../RoomPredecessor/RoomPredecessorBubbleCell.xib | 0 .../BubbleCells => TimelineCells}/RoomTimelineCellIdentifier.h | 0 .../BubbleCells => TimelineCells}/RoomTimelineConfiguration.swift | 0 .../SizableCell/SizableBubbleCell.swift | 0 .../SizableCell/SizingViewHeight.swift | 0 .../SizableCell/SizingViewHeightStore.swift | 0 .../Styles/Bubble/BubbleRoomCellLayoutConstants.swift | 0 .../Styles/Bubble/BubbleRoomCellLayoutUpdater.swift | 0 .../Styles/Bubble/BubbleRoomTimelineCellDecorator.swift | 0 .../Styles/Bubble/BubbleRoomTimelineCellProvider.h | 0 .../Styles/Bubble/BubbleRoomTimelineCellProvider.m | 0 .../Styles/Bubble/BubbleRoomTimelineStyle.swift | 0 .../Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift | 0 .../Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift | 0 .../Styles/Bubble/Cells/BubbleRoomCellProtocol.swift | 0 .../Common/FileWithoutThumbnailBaseBubbleCell.swift | 0 .../Common/FileWithoutThumbnailCellContentView.swift | 0 .../Common/FileWithoutThumbnailCellContentView.xib | 0 .../Incoming/FileWithoutThumbnailIncomingBubbleCell.swift | 0 ...ileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift | 0 .../FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift | 0 ...FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift | 0 .../FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift | 0 .../Cells/Location/Incoming/LocationIncomingBubbleCell.swift | 0 .../Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift | 0 .../Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift | 0 .../Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift | 0 .../Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift | 0 .../Bubble/Cells/MXKRoomBubbleTableViewCell+BubbleStyle.swift | 0 .../Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift | 0 .../Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift | 0 .../Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift | 0 .../Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift | 0 .../Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift | 0 .../Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift | 0 .../Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift | 0 .../TextMessage/Common/TextMessageBubbleCellContentView.swift | 0 .../Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib | 0 .../TextMessage/Incoming/TextMessageIncomingBubbleCell.swift | 0 .../TextMessageIncomingWithPaginationTitleBubbleCell.swift | 0 ...geIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift | 0 .../Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift | 0 .../Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift | 0 .../TextMessageOutgoingWithPaginationTitleBubbleCell.swift | 0 ...geOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift | 0 .../Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift | 0 .../VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift | 0 .../VoiceMessageIncomingWithPaginationTitleBubbleCell.swift | 0 .../VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift | 0 .../VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift | 0 .../VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift | 0 .../Styles/Bubble/RoomMessageBubbleBackgroundView.swift | 0 .../Incoming/Clear/RoomIncomingAttachmentBubbleCell.h | 0 .../Incoming/Clear/RoomIncomingAttachmentBubbleCell.m | 0 .../Incoming/Clear/RoomIncomingAttachmentBubbleCell.xib | 0 .../Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h | 0 .../Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m | 0 .../Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib | 0 .../Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h | 0 .../Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m | 0 .../Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib | 0 .../Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.h | 0 .../Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m | 0 .../Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.xib | 0 .../Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h | 0 .../Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.m | 0 .../MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib | 0 .../Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.h | 0 .../Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.m | 0 .../Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.xib | 0 ...RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h | 0 ...RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m | 0 ...omIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib | 0 .../RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h | 0 .../RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m | 0 ...RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib | 0 .../Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.h | 0 .../Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.m | 0 .../Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.xib | 0 .../Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h | 0 .../Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m | 0 .../Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib | 0 ...oingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h | 0 ...oingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.m | 0 ...ngAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.xib | 0 .../Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h | 0 .../Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m | 0 .../Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib | 0 .../Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.h | 0 .../Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.m | 0 .../Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.xib | 0 .../Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h | 0 .../Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m | 0 .../MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib | 0 .../Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.h | 0 .../Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.m | 0 .../Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.xib | 0 ...RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h | 0 ...RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m | 0 ...omOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.xib | 0 .../RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h | 0 .../RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m | 0 ...RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib | 0 .../Styles/Plain/Cells}/Location/LocationBubbleCell.swift | 0 .../Cells}/Location/LocationWithPaginationTitleBubbleCell.swift | 0 .../Cells}/Location/LocationWithoutSenderInfoBubbleCell.swift | 0 .../Styles/Plain/Cells}/Poll/PollBubbleCell.swift | 0 .../Plain/Cells}/Poll/PollWithPaginationTitleBubbleCell.swift | 0 .../Plain/Cells}/Poll/PollWithoutSenderInfoBubbleCell.swift | 0 .../Styles/Plain/Cells}/Sticker/RoomSelectedStickerBubbleCell.h | 0 .../Styles/Plain/Cells}/Sticker/RoomSelectedStickerBubbleCell.m | 0 .../Styles/Plain/Cells}/Sticker/RoomSelectedStickerBubbleCell.xib | 0 .../TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.h | 0 .../TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.m | 0 .../TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.xib | 0 .../Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h | 0 .../Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m | 0 .../Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib | 0 ...ncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h | 0 ...ncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m | 0 ...omingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib | 0 .../Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h | 0 .../Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m | 0 .../Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib | 0 .../Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.h | 0 .../Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m | 0 .../Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib | 0 .../Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.h | 0 .../Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.m | 0 .../Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.xib | 0 .../Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h | 0 .../Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.m | 0 .../Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib | 0 .../Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.h | 0 .../Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.m | 0 .../Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.xib | 0 .../RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h | 0 .../RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m | 0 .../RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.xib | 0 ...cryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h | 0 ...cryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m | 0 ...yptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib | 0 .../RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h | 0 .../RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m | 0 .../RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib | 0 .../RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h | 0 .../RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m | 0 .../RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib | 0 .../TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.h | 0 .../TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.m | 0 .../TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.xib | 0 .../Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h | 0 .../Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m | 0 .../Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.xib | 0 ...utgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h | 0 ...utgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m | 0 ...goingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib | 0 .../Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h | 0 .../Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m | 0 .../Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib | 0 .../Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h | 0 .../Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m | 0 .../Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib | 0 .../Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.h | 0 .../Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.m | 0 .../Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.xib | 0 .../Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h | 0 .../Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m | 0 .../Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib | 0 .../Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.h | 0 .../Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.m | 0 .../Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.xib | 0 .../RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h | 0 .../RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m | 0 .../RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib | 0 ...cryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h | 0 ...cryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m | 0 ...yptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib | 0 .../RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h | 0 .../RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m | 0 .../RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib | 0 .../RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h | 0 .../RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m | 0 .../RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib | 0 .../Styles/Plain/Cells}/VoiceMessage/VoiceMessageBubbleCell.swift | 0 .../VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift | 0 .../VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift | 0 .../Styles/Plain/PlainRoomTimelineCellDecorator.swift | 0 .../Styles/Plain/PlainRoomTimelineCellProvider.h | 0 .../Styles/Plain/PlainRoomTimelineCellProvider.m | 0 .../Styles/Plain/PlainRoomTimelineStyle.swift | 0 .../Styles/Plain}/RoomBubbleCellLayout.swift | 0 .../Styles/RoomCellLayoutUpdating.swift | 0 .../Styles/RoomTimelineCellDecorator.swift | 0 .../Styles/RoomTimelineCellProvider.h | 0 .../BubbleCells => TimelineCells}/Styles/RoomTimelineStyle.swift | 0 .../Styles/RoomTimelineStyleIdentifier.swift | 0 .../Reactions}/BubbleReactionActionViewCell.swift | 0 .../Reactions}/BubbleReactionActionViewCell.xib | 0 .../Reactions}/BubbleReactionViewCell.swift | 0 .../Reactions}/BubbleReactionViewCell.xib | 0 .../Reactions}/BubbleReactionViewData.swift | 0 .../Reactions}/BubbleReactionsView.swift | 0 .../Reactions}/BubbleReactionsView.xib | 0 .../Reactions}/BubbleReactionsViewModel.swift | 0 .../Reactions}/BubbleReactionsViewModelBuilder.swift | 0 .../Reactions}/BubbleReactionsViewModelType.swift | 0 .../Reactions}/BubbleReactionsViewSizer.h | 0 .../Reactions}/BubbleReactionsViewSizer.m | 0 .../ReadReceipts}/MXKReceiptSendersContainer.h | 0 .../ReadReceipts}/MXKReceiptSendersContainer.m | 0 .../Threads/From/FromAThreadView.swift | 0 .../Threads/From/FromAThreadView.xib | 0 .../Threads/Summary/ThreadSummaryModel.swift | 0 .../Threads/Summary/ThreadSummaryView.swift | 0 .../Threads/Summary/ThreadSummaryView.xib | 0 .../URLPreviews/URLPreviewView.swift | 0 .../{Views => TimelineDecorations}/URLPreviews/URLPreviewView.xib | 0 .../URLPreviews/URLPreviewViewSizer.swift | 0 300 files changed, 0 insertions(+), 0 deletions(-) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/BaseBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/BubbleCellContentView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/BubbleCellContentView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/BubbleCellReactionsDisplayable.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/RoomCellDecorationAlignment.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/BaseBubbleCell/TimestampDisplayable.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/CallBubbleCellBaseContentView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/CallBubbleCellBaseContentView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/Common/CallTileActionButton.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/Common/HorizontalButtonsContainerView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/Common/HorizontalButtonsContainerView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/Direct/RoomDirectCallStatusBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/Group/RoomGroupCallStatusBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/RoomBaseCallBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Call/RoomBaseCallBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomBubbleTableViewCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomBubbleTableViewCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIOSBubbleTableViewCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIOSBubbleTableViewCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIOSOutgoingBubbleTableViewCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIOSOutgoingBubbleTableViewCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIOSOutgoingBubbleTableViewCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIncomingBubbleTableViewCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomIncomingBubbleTableViewCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomOutgoingBubbleTableViewCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Common/MXKRoomOutgoingBubbleTableViewCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/EmptyContent/MXKRoomEmptyBubbleTableViewCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/EmptyContent/MXKRoomEmptyBubbleTableViewCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/EmptyContent/MXKRoomEmptyBubbleTableViewCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/EmptyContent/RoomEmptyBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/EmptyContent/RoomEmptyBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/EmptyContent/RoomEmptyBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Encryption/RoomEncryptedDataBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Encryption/RoomEncryptedDataBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationBaseBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationCellInnerContentView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationCellInnerContentView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationConclusionBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationConclusionViewData.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationIncomingRequestApprovalBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationIncomingRequestApprovalViewData.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationRequestStatusBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationRequestStatusViewData.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/MessageTyping/RoomTypingBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/MessageTyping/RoomTypingBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreation/RoomCreationCollapsedBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreation/RoomCreationCollapsedBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreation/RoomCreationCollapsedBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreationIntro/RoomCreationIntroCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreationIntro/RoomCreationIntroCellContentView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreationIntro/RoomCreationIntroCellContentView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomCreationIntro/RoomCreationIntroViewData.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipCollapsedBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipCollapsedBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipCollapsedBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipExpandedBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipExpandedBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipExpandedBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomPredecessor/RoomPredecessorBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomPredecessor/RoomPredecessorBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomPredecessor/RoomPredecessorBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomTimelineCellIdentifier.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/RoomTimelineConfiguration.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/SizableCell/SizableBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/SizableCell/SizingViewHeight.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/SizableCell/SizingViewHeightStore.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/BubbleRoomCellLayoutConstants.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/BubbleRoomTimelineCellProvider.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/BubbleRoomTimelineCellProvider.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/BubbleRoomTimelineStyle.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/MXKRoomBubbleTableViewCell+BubbleStyle.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Bubble/RoomMessageBubbleBackgroundView.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Location/LocationBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Location/LocationWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Location/LocationWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Poll/PollBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Poll/PollWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Poll/PollWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Sticker/RoomSelectedStickerBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Sticker/RoomSelectedStickerBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/Sticker/RoomSelectedStickerBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/VoiceMessage/VoiceMessageBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain/Cells}/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Plain/PlainRoomTimelineCellDecorator.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Plain/PlainRoomTimelineCellProvider.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Plain/PlainRoomTimelineCellProvider.m (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/Plain/PlainRoomTimelineStyle.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells/Styles/Plain}/RoomBubbleCellLayout.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/RoomCellLayoutUpdating.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/RoomTimelineCellDecorator.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/RoomTimelineCellProvider.h (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/RoomTimelineStyle.swift (100%) rename Riot/Modules/Room/{Views/BubbleCells => TimelineCells}/Styles/RoomTimelineStyleIdentifier.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionActionViewCell.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionActionViewCell.xib (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionViewCell.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionViewCell.xib (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionViewData.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsView.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsView.xib (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsViewModel.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsViewModelBuilder.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsViewModelType.swift (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsViewSizer.h (100%) rename Riot/Modules/Room/{BubbleReactions => TimelineDecorations/Reactions}/BubbleReactionsViewSizer.m (100%) rename Riot/Modules/{MatrixKit/Views => Room/TimelineDecorations/ReadReceipts}/MXKReceiptSendersContainer.h (100%) rename Riot/Modules/{MatrixKit/Views => Room/TimelineDecorations/ReadReceipts}/MXKReceiptSendersContainer.m (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/Threads/From/FromAThreadView.swift (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/Threads/From/FromAThreadView.xib (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/Threads/Summary/ThreadSummaryModel.swift (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/Threads/Summary/ThreadSummaryView.swift (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/Threads/Summary/ThreadSummaryView.xib (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/URLPreviews/URLPreviewView.swift (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/URLPreviews/URLPreviewView.xib (100%) rename Riot/Modules/Room/{Views => TimelineDecorations}/URLPreviews/URLPreviewViewSizer.swift (100%) diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BaseBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/BaseBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellContentView.xib rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellReactionsDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReactionsDisplayable.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellReactionsDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReactionsDisplayable.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/RoomCellDecorationAlignment.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellDecorationAlignment.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/RoomCellDecorationAlignment.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellDecorationAlignment.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/TimestampDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseBubbleCell/TimestampDisplayable.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/TimestampDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseBubbleCell/TimestampDisplayable.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/CallBubbleCellBaseContentView.swift b/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/CallBubbleCellBaseContentView.swift rename to Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/CallBubbleCellBaseContentView.xib b/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/CallBubbleCellBaseContentView.xib rename to Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/Common/CallTileActionButton.swift b/Riot/Modules/Room/TimelineCells/Call/Common/CallTileActionButton.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/Common/CallTileActionButton.swift rename to Riot/Modules/Room/TimelineCells/Call/Common/CallTileActionButton.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/Common/HorizontalButtonsContainerView.swift b/Riot/Modules/Room/TimelineCells/Call/Common/HorizontalButtonsContainerView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/Common/HorizontalButtonsContainerView.swift rename to Riot/Modules/Room/TimelineCells/Call/Common/HorizontalButtonsContainerView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/Common/HorizontalButtonsContainerView.xib b/Riot/Modules/Room/TimelineCells/Call/Common/HorizontalButtonsContainerView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/Common/HorizontalButtonsContainerView.xib rename to Riot/Modules/Room/TimelineCells/Call/Common/HorizontalButtonsContainerView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/Direct/RoomDirectCallStatusBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Call/Direct/RoomDirectCallStatusBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/Direct/RoomDirectCallStatusBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Call/Direct/RoomDirectCallStatusBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/Group/RoomGroupCallStatusBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Call/Group/RoomGroupCallStatusBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/Group/RoomGroupCallStatusBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Call/Group/RoomGroupCallStatusBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/RoomBaseCallBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/RoomBaseCallBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Call/RoomBaseCallBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Call/RoomBaseCallBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.h rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomBubbleTableViewCell.m rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSBubbleTableViewCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSBubbleTableViewCell.h rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSBubbleTableViewCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSBubbleTableViewCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSBubbleTableViewCell.m rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSBubbleTableViewCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.h rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.m rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.xib b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.xib rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIOSOutgoingBubbleTableViewCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIncomingBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIncomingBubbleTableViewCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIncomingBubbleTableViewCell.h rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIncomingBubbleTableViewCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIncomingBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomIncomingBubbleTableViewCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomIncomingBubbleTableViewCell.m rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomIncomingBubbleTableViewCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomOutgoingBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/Common/MXKRoomOutgoingBubbleTableViewCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomOutgoingBubbleTableViewCell.h rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomOutgoingBubbleTableViewCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomOutgoingBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomOutgoingBubbleTableViewCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Common/MXKRoomOutgoingBubbleTableViewCell.m rename to Riot/Modules/Room/TimelineCells/Common/MXKRoomOutgoingBubbleTableViewCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.h rename to Riot/Modules/Room/TimelineCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.m rename to Riot/Modules/Room/TimelineCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.xib b/Riot/Modules/Room/TimelineCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.xib rename to Riot/Modules/Room/TimelineCells/EmptyContent/MXKRoomEmptyBubbleTableViewCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/EmptyContent/RoomEmptyBubbleCell.h b/Riot/Modules/Room/TimelineCells/EmptyContent/RoomEmptyBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/EmptyContent/RoomEmptyBubbleCell.h rename to Riot/Modules/Room/TimelineCells/EmptyContent/RoomEmptyBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/EmptyContent/RoomEmptyBubbleCell.m b/Riot/Modules/Room/TimelineCells/EmptyContent/RoomEmptyBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/EmptyContent/RoomEmptyBubbleCell.m rename to Riot/Modules/Room/TimelineCells/EmptyContent/RoomEmptyBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/EmptyContent/RoomEmptyBubbleCell.xib b/Riot/Modules/Room/TimelineCells/EmptyContent/RoomEmptyBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/EmptyContent/RoomEmptyBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/EmptyContent/RoomEmptyBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h b/Riot/Modules/Room/TimelineCells/Encryption/RoomEncryptedDataBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Encryption/RoomEncryptedDataBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.m b/Riot/Modules/Room/TimelineCells/Encryption/RoomEncryptedDataBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Encryption/RoomEncryptedDataBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationBaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationCellInnerContentView.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationCellInnerContentView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationCellInnerContentView.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationCellInnerContentView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationCellInnerContentView.xib b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationCellInnerContentView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationCellInnerContentView.xib rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationCellInnerContentView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationConclusionBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationConclusionBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationConclusionViewData.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionViewData.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationConclusionViewData.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionViewData.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationIncomingRequestApprovalBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationIncomingRequestApprovalBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationIncomingRequestApprovalViewData.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalViewData.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationIncomingRequestApprovalViewData.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalViewData.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationRequestStatusBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationRequestStatusBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationRequestStatusViewData.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusViewData.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationRequestStatusViewData.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusViewData.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/MessageTyping/RoomTypingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/MessageTyping/RoomTypingBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/MessageTyping/RoomTypingBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/MessageTyping/RoomTypingBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/MessageTyping/RoomTypingBubbleCell.xib b/Riot/Modules/Room/TimelineCells/MessageTyping/RoomTypingBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/MessageTyping/RoomTypingBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/MessageTyping/RoomTypingBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationCollapsedBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationCollapsedBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationCollapsedBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationCollapsedBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationCollapsedBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationCollapsedBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationCollapsedBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationCollapsedBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationCollapsedBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationCollapsedBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationCollapsedBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationCollapsedBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomCreation/RoomCreationWithPaginationCollapsedBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroCell.swift b/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroCell.swift rename to Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroCellContentView.swift b/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCellContentView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroCellContentView.swift rename to Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCellContentView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroCellContentView.xib b/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCellContentView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroCellContentView.xib rename to Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCellContentView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroViewData.swift b/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroViewData.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomCreationIntro/RoomCreationIntroViewData.swift rename to Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroViewData.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipCollapsedWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipExpandedWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomMembership/RoomMembershipWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessor/RoomPredecessorBubbleCell.h b/Riot/Modules/Room/TimelineCells/RoomPredecessor/RoomPredecessorBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomPredecessor/RoomPredecessorBubbleCell.h rename to Riot/Modules/Room/TimelineCells/RoomPredecessor/RoomPredecessorBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessor/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/TimelineCells/RoomPredecessor/RoomPredecessorBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomPredecessor/RoomPredecessorBubbleCell.m rename to Riot/Modules/Room/TimelineCells/RoomPredecessor/RoomPredecessorBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessor/RoomPredecessorBubbleCell.xib b/Riot/Modules/Room/TimelineCells/RoomPredecessor/RoomPredecessorBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomPredecessor/RoomPredecessorBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/RoomPredecessor/RoomPredecessorBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTimelineCellIdentifier.h b/Riot/Modules/Room/TimelineCells/RoomTimelineCellIdentifier.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomTimelineCellIdentifier.h rename to Riot/Modules/Room/TimelineCells/RoomTimelineCellIdentifier.h diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomTimelineConfiguration.swift b/Riot/Modules/Room/TimelineCells/RoomTimelineConfiguration.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomTimelineConfiguration.swift rename to Riot/Modules/Room/TimelineCells/RoomTimelineConfiguration.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/SizableCell/SizableBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizingViewHeight.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizingViewHeight.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/SizableCell/SizingViewHeight.swift rename to Riot/Modules/Room/TimelineCells/SizableCell/SizingViewHeight.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/SizableCell/SizingViewHeightStore.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizingViewHeightStore.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/SizableCell/SizingViewHeightStore.swift rename to Riot/Modules/Room/TimelineCells/SizableCell/SizingViewHeightStore.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellProvider.h b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellProvider.h rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellProvider.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineStyle.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineStyle.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomTimelineStyle.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineStyle.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.xib b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.xib rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailCellContentView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/MXKRoomBubbleTableViewCell+BubbleStyle.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/MXKRoomBubbleTableViewCell+BubbleStyle.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/MXKRoomBubbleTableViewCell+BubbleStyle.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/MXKRoomBubbleTableViewCell+BubbleStyle.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift rename to Riot/Modules/Room/TimelineCells/Styles/Bubble/RoomMessageBubbleBackgroundView.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Clear/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Encrypted/RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithPaginationTitleWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Clear/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Common/MXKRoomOutgoingAttachmentWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Outgoing/Encrypted/RoomOutgoingEncryptedAttachmentWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/Location/LocationBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Location/LocationBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Location/LocationWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Location/LocationWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Location/LocationWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Location/LocationWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Poll/PollBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Poll/PollBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Poll/PollWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Poll/PollWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Poll/PollWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Poll/PollWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Sticker/RoomSelectedStickerBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Sticker/RoomSelectedStickerBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Sticker/RoomSelectedStickerBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Sticker/RoomSelectedStickerBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Sticker/RoomSelectedStickerBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Sticker/RoomSelectedStickerBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Sticker/RoomSelectedStickerBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Clear/RoomIncomingTextMsgWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Common/MXKRoomIncomingTextMsgWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Incoming/Encrypted/RoomIncomingEncryptedTextMsgWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Clear/RoomOutgoingTextMsgWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Common/MXKRoomOutgoingTextMsgWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderInfoBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.h diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.m diff --git a/Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/TextMessage/Outgoing/Encrypted/RoomOutgoingEncryptedTextMsgWithoutSenderNameBubbleCell.xib diff --git a/Riot/Modules/Room/Views/BubbleCells/VoiceMessage/VoiceMessageBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/VoiceMessage/VoiceMessageBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellProvider.h b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellProvider.h rename to Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellProvider.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.m similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineCellProvider.m rename to Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellProvider.m diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineStyle.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineStyle.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/Plain/PlainRoomTimelineStyle.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineStyle.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/RoomBubbleCellLayout.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/RoomBubbleCellLayout.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/RoomBubbleCellLayout.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/RoomCellLayoutUpdating.swift b/Riot/Modules/Room/TimelineCells/Styles/RoomCellLayoutUpdating.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/RoomCellLayoutUpdating.swift rename to Riot/Modules/Room/TimelineCells/Styles/RoomCellLayoutUpdating.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellDecorator.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineCellDecorator.swift rename to Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellDecorator.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineCellProvider.h b/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellProvider.h similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineCellProvider.h rename to Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellProvider.h diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyle.swift b/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyle.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyle.swift rename to Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyle.swift diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyleIdentifier.swift b/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift similarity index 100% rename from Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyleIdentifier.swift rename to Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionActionViewCell.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionActionViewCell.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.xib b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionActionViewCell.xib similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionActionViewCell.xib rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionActionViewCell.xib diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionViewCell.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionViewCell.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionViewCell.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionViewCell.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionViewCell.xib b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionViewCell.xib similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionViewCell.xib rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionViewCell.xib diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionViewData.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionViewData.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionViewData.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionViewData.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsView.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsView.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsView.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsView.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsView.xib b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsView.xib similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsView.xib rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsView.xib diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModel.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewModel.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModel.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewModel.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelBuilder.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewModelBuilder.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelBuilder.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewModelBuilder.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewModelType.swift similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewModelType.swift diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.h b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewSizer.h similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.h rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewSizer.h diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m b/Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewSizer.m similarity index 100% rename from Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m rename to Riot/Modules/Room/TimelineDecorations/Reactions/BubbleReactionsViewSizer.m diff --git a/Riot/Modules/MatrixKit/Views/MXKReceiptSendersContainer.h b/Riot/Modules/Room/TimelineDecorations/ReadReceipts/MXKReceiptSendersContainer.h similarity index 100% rename from Riot/Modules/MatrixKit/Views/MXKReceiptSendersContainer.h rename to Riot/Modules/Room/TimelineDecorations/ReadReceipts/MXKReceiptSendersContainer.h diff --git a/Riot/Modules/MatrixKit/Views/MXKReceiptSendersContainer.m b/Riot/Modules/Room/TimelineDecorations/ReadReceipts/MXKReceiptSendersContainer.m similarity index 100% rename from Riot/Modules/MatrixKit/Views/MXKReceiptSendersContainer.m rename to Riot/Modules/Room/TimelineDecorations/ReadReceipts/MXKReceiptSendersContainer.m diff --git a/Riot/Modules/Room/Views/Threads/From/FromAThreadView.swift b/Riot/Modules/Room/TimelineDecorations/Threads/From/FromAThreadView.swift similarity index 100% rename from Riot/Modules/Room/Views/Threads/From/FromAThreadView.swift rename to Riot/Modules/Room/TimelineDecorations/Threads/From/FromAThreadView.swift diff --git a/Riot/Modules/Room/Views/Threads/From/FromAThreadView.xib b/Riot/Modules/Room/TimelineDecorations/Threads/From/FromAThreadView.xib similarity index 100% rename from Riot/Modules/Room/Views/Threads/From/FromAThreadView.xib rename to Riot/Modules/Room/TimelineDecorations/Threads/From/FromAThreadView.xib diff --git a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryModel.swift b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryModel.swift similarity index 100% rename from Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryModel.swift rename to Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryModel.swift diff --git a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift similarity index 100% rename from Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.swift rename to Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift diff --git a/Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.xib b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.xib similarity index 100% rename from Riot/Modules/Room/Views/Threads/Summary/ThreadSummaryView.xib rename to Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.xib diff --git a/Riot/Modules/Room/Views/URLPreviews/URLPreviewView.swift b/Riot/Modules/Room/TimelineDecorations/URLPreviews/URLPreviewView.swift similarity index 100% rename from Riot/Modules/Room/Views/URLPreviews/URLPreviewView.swift rename to Riot/Modules/Room/TimelineDecorations/URLPreviews/URLPreviewView.swift diff --git a/Riot/Modules/Room/Views/URLPreviews/URLPreviewView.xib b/Riot/Modules/Room/TimelineDecorations/URLPreviews/URLPreviewView.xib similarity index 100% rename from Riot/Modules/Room/Views/URLPreviews/URLPreviewView.xib rename to Riot/Modules/Room/TimelineDecorations/URLPreviews/URLPreviewView.xib diff --git a/Riot/Modules/Room/Views/URLPreviews/URLPreviewViewSizer.swift b/Riot/Modules/Room/TimelineDecorations/URLPreviews/URLPreviewViewSizer.swift similarity index 100% rename from Riot/Modules/Room/Views/URLPreviews/URLPreviewViewSizer.swift rename to Riot/Modules/Room/TimelineDecorations/URLPreviews/URLPreviewViewSizer.swift From 0ea89fd835d98c8607eaccbddfbf5b9b6e50760d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 09:46:17 +0100 Subject: [PATCH 078/188] Xcodegen: Fix RoomTimelineStyleIdentifier.swift location in all targets. --- RiotNSE/target.yml | 2 +- RiotShareExtension/target.yml | 2 +- RiotTests/target.yml | 2 +- SiriIntents/target.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/RiotNSE/target.yml b/RiotNSE/target.yml index 1f15351ef..77e72852f 100644 --- a/RiotNSE/target.yml +++ b/RiotNSE/target.yml @@ -68,4 +68,4 @@ targets: excludes: - "**/*.md" # excludes all files with the .md extension - path: ../Riot/Generated/MatrixKitStrings.swift - - path: ../Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyleIdentifier.swift + - path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift diff --git a/RiotShareExtension/target.yml b/RiotShareExtension/target.yml index 945d77d7a..f1d16a60f 100644 --- a/RiotShareExtension/target.yml +++ b/RiotShareExtension/target.yml @@ -74,4 +74,4 @@ targets: excludes: - "**/*.md" # excludes all files with the .md extension - path: ../Riot/Generated/MatrixKitStrings.swift - - path: ../Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyleIdentifier.swift + - path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift diff --git a/RiotTests/target.yml b/RiotTests/target.yml index ad56a52c5..089ce208f 100644 --- a/RiotTests/target.yml +++ b/RiotTests/target.yml @@ -64,6 +64,6 @@ targets: - path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift - path: ../Riot/Managers/KeyValueStorage/ - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift - - path: ../Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyleIdentifier.swift + - path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift - path: ../Riot/Modules/Room/EventMenu/EventMenuBuilder.swift - path: ../Riot/Modules/Room/EventMenu/EventMenuItemType.swift diff --git a/SiriIntents/target.yml b/SiriIntents/target.yml index ddb51c5eb..a048b5c46 100644 --- a/SiriIntents/target.yml +++ b/SiriIntents/target.yml @@ -59,4 +59,4 @@ targets: excludes: - "**/*.md" # excludes all files with the .md extension - path: ../Riot/Generated/MatrixKitStrings.swift - - path: ../Riot/Modules/Room/Views/BubbleCells/Styles/RoomTimelineStyleIdentifier.swift + - path: ../Riot/Modules/Room/TimelineCells/Styles/RoomTimelineStyleIdentifier.swift From e02f6a3b59bb52daba335a2fc8907d3a15a4f621 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 09:56:13 +0100 Subject: [PATCH 079/188] Rename BaseBubbleCell folder to BaseRoomCell. --- .../{BaseBubbleCell => BaseRoomCell}/BaseBubbleCell.swift | 0 .../{BaseBubbleCell => BaseRoomCell}/BubbleCellContentView.swift | 0 .../{BaseBubbleCell => BaseRoomCell}/BubbleCellContentView.xib | 0 .../BubbleCellReactionsDisplayable.swift | 0 .../BubbleCellReadReceiptsDisplayable.swift | 0 .../BubbleCellThreadSummaryDisplayable.swift | 0 .../RoomCellDecorationAlignment.swift | 0 .../RoomCellURLPreviewDisplayable.swift | 0 .../{BaseBubbleCell => BaseRoomCell}/TimestampDisplayable.swift | 0 9 files changed, 0 insertions(+), 0 deletions(-) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/BaseBubbleCell.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/BubbleCellContentView.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/BubbleCellContentView.xib (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/BubbleCellReactionsDisplayable.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/BubbleCellReadReceiptsDisplayable.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/BubbleCellThreadSummaryDisplayable.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/RoomCellDecorationAlignment.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/RoomCellURLPreviewDisplayable.swift (100%) rename Riot/Modules/Room/TimelineCells/{BaseBubbleCell => BaseRoomCell}/TimestampDisplayable.swift (100%) diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseBubbleCell.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/BaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseBubbleCell.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellContentView.xib rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReactionsDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReactionsDisplayable.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReactionsDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReactionsDisplayable.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReadReceiptsDisplayable.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellReadReceiptsDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReadReceiptsDisplayable.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellThreadSummaryDisplayable.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/BubbleCellThreadSummaryDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellThreadSummaryDisplayable.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellDecorationAlignment.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellDecorationAlignment.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellDecorationAlignment.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellDecorationAlignment.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellURLPreviewDisplayable.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/RoomCellURLPreviewDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellURLPreviewDisplayable.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseBubbleCell/TimestampDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/TimestampDisplayable.swift similarity index 100% rename from Riot/Modules/Room/TimelineCells/BaseBubbleCell/TimestampDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/TimestampDisplayable.swift From f0a09f054a382ebd216f062dc86eeff3d37cfd43 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:09:11 +0100 Subject: [PATCH 080/188] Rename BaseBubbleCell to BaseRoomCell. Rename BaseBubbleCellType to BaseRoomCellProtocol. --- ...BaseBubbleCell.swift => BaseRoomCell.swift} | 18 +++++++++--------- .../SizableCell/SizableBubbleCell.swift | 4 ++-- 2 files changed, 11 insertions(+), 11 deletions(-) rename Riot/Modules/Room/TimelineCells/BaseRoomCell/{BaseBubbleCell.swift => BaseRoomCell.swift} (92%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift similarity index 92% rename from Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index 1365d0e18..dd65cdd3c 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -16,13 +16,13 @@ limitations under the License. import UIKit -@objc protocol BaseBubbleCellType: Themable { +@objc protocol BaseRoomCellProtocol: Themable { var bubbleCellContentView: BubbleCellContentView? { get } } -/// `BaseBubbleCell` allows a bubble cell that inherits from this class to embed and manage the default room message outer views and add an inner content view. +/// `BaseRoomCell` allows a bubble cell that inherits from this class to embed and manage the default room message outer views and add an inner content view. @objcMembers -class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { +class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { // MARK: - Constants @@ -41,7 +41,7 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { override var bubbleInfoContainer: UIView! { get { guard let infoContainer = self.bubbleCellContentView?.bubbleInfoContainer else { - fatalError("[BaseBubbleCell] bubbleInfoContainer should not be used before set") + fatalError("[BaseRoomCell] bubbleInfoContainer should not be used before set") } return infoContainer } @@ -53,7 +53,7 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { override var bubbleOverlayContainer: UIView! { get { guard let overlayContainer = self.bubbleCellContentView?.bubbleOverlayContainer else { - fatalError("[BaseBubbleCell] bubbleOverlayContainer should not be used before set") + fatalError("[BaseRoomCell] bubbleOverlayContainer should not be used before set") } return overlayContainer } @@ -65,7 +65,7 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { override var bubbleInfoContainerTopConstraint: NSLayoutConstraint! { get { guard let infoContainerTopConstraint = self.bubbleCellContentView?.bubbleInfoContainerTopConstraint else { - fatalError("[BaseBubbleCell] bubbleInfoContainerTopConstraint should not be used before set") + fatalError("[BaseRoomCell] bubbleInfoContainerTopConstraint should not be used before set") } return infoContainerTopConstraint } @@ -82,7 +82,7 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { } guard let pictureView = self.bubbleCellContentView?.avatarImageView else { - fatalError("[BaseBubbleCell] pictureView should not be used before set") + fatalError("[BaseRoomCell] pictureView should not be used before set") } return pictureView } @@ -98,7 +98,7 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { } guard let userNameLabel = bubbleCellContentView.userNameLabel else { - fatalError("[BaseBubbleCell] userNameLabel should not be used before set") + fatalError("[BaseRoomCell] userNameLabel should not be used before set") } return userNameLabel } @@ -115,7 +115,7 @@ class BaseBubbleCell: MXKRoomBubbleTableViewCell, BaseBubbleCellType { } guard let userNameTapGestureMaskView = self.bubbleCellContentView?.userNameTouchMaskView else { - fatalError("[BaseBubbleCell] userNameTapGestureMaskView should not be used before set") + fatalError("[BaseRoomCell] userNameTapGestureMaskView should not be used before set") } return userNameTapGestureMaskView } diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift index 99aa2af4a..ccf4b52c9 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift @@ -17,13 +17,13 @@ import UIKit import MatrixSDK -@objc protocol SizableBaseBubbleCellType: BaseBubbleCellType { +@objc protocol SizableBaseBubbleCellType: BaseRoomCellProtocol { static func sizingViewHeightHashValue(from bubbleCellData: MXKRoomBubbleCellData) -> Int } /// `SizableBaseBubbleCell` allows a cell using Auto Layout that inherits from this class to automatically return the height of the cell and cache the result. @objcMembers -class SizableBaseBubbleCell: BaseBubbleCell, SizableBaseBubbleCellType { +class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { // MARK: - Constants From bc5b05de8ee7ad91896c4d360f56e366bb144835 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:11:35 +0100 Subject: [PATCH 081/188] Rename BubbleCellContentView to RoomCellContentView. --- .../BaseRoomCell/BaseRoomCell.swift | 6 +++--- .../BaseRoomCell/BubbleCellContentView.xib | 4 +--- ...ntentView.swift => RoomCellContentView.swift} | 16 ++++++++-------- .../RoomCellDecorationAlignment.swift | 2 +- .../KeyVerificationBaseBubbleCell.swift | 4 ++-- .../Bubble/Cells/BubbleRoomCellProtocol.swift | 2 +- 6 files changed, 16 insertions(+), 18 deletions(-) rename Riot/Modules/Room/TimelineCells/BaseRoomCell/{BubbleCellContentView.swift => RoomCellContentView.swift} (94%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index dd65cdd3c..d280a1d67 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -17,7 +17,7 @@ limitations under the License. import UIKit @objc protocol BaseRoomCellProtocol: Themable { - var bubbleCellContentView: BubbleCellContentView? { get } + var bubbleCellContentView: RoomCellContentView? { get } } /// `BaseRoomCell` allows a bubble cell that inherits from this class to embed and manage the default room message outer views and add an inner content view. @@ -32,7 +32,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { // MARK: Public - weak var bubbleCellContentView: BubbleCellContentView? + weak var bubbleCellContentView: RoomCellContentView? private(set) var theme: Theme? @@ -240,7 +240,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { guard self.bubbleCellContentView == nil else { return } - let bubbleCellContentView = BubbleCellContentView.instantiate() + let bubbleCellContentView = RoomCellContentView.instantiate() self.contentView.vc_addSubViewMatchingParent(bubbleCellContentView) self.bubbleCellContentView = bubbleCellContentView } diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib index cdaf09edd..6d7b652d1 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib @@ -1,8 +1,6 @@ - - @@ -10,7 +8,7 @@ - + diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift similarity index 94% rename from Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index a0f7fbd22..1774b8e06 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -17,9 +17,9 @@ import UIKit import Reusable -/// `BubbleCellContentView` is a container view that display the default room message outer views and enables to manage them. Like pagination title, sender info, read receipts, reactions, encryption status. +/// `RoomCellContentView` is a container view that display the default room message outer views and enables to manage them. Like pagination title, sender info, read receipts, reactions, encryption status. @objcMembers -final class BubbleCellContentView: UIView, NibLoadable { +final class RoomCellContentView: UIView, NibLoadable { // MARK: - Properties @@ -158,8 +158,8 @@ final class BubbleCellContentView: UIView, NibLoadable { // MARK: - Setup - class func instantiate() -> BubbleCellContentView { - return BubbleCellContentView.loadFromNib() + class func instantiate() -> RoomCellContentView { + return RoomCellContentView.loadFromNib() } // MARK: - Public @@ -172,7 +172,7 @@ final class BubbleCellContentView: UIView, NibLoadable { } // MARK: - BubbleCellReadReceiptsDisplayable -extension BubbleCellContentView: BubbleCellReadReceiptsDisplayable { +extension RoomCellContentView: BubbleCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { self.readReceiptsContentView.vc_removeAllSubviews() @@ -187,7 +187,7 @@ extension BubbleCellContentView: BubbleCellReadReceiptsDisplayable { } // MARK: - BubbleCellReactionsDisplayable -extension BubbleCellContentView: BubbleCellReactionsDisplayable { +extension RoomCellContentView: BubbleCellReactionsDisplayable { func addReactionsView(_ reactionsView: UIView) { self.reactionsContentView.vc_removeAllSubviews() @@ -219,7 +219,7 @@ extension BubbleCellContentView: BubbleCellReactionsDisplayable { } // MARK: - BubbleCellThreadSummaryDisplayable -extension BubbleCellContentView: BubbleCellThreadSummaryDisplayable { +extension RoomCellContentView: BubbleCellThreadSummaryDisplayable { func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { @@ -261,7 +261,7 @@ extension BubbleCellContentView: BubbleCellThreadSummaryDisplayable { } // MARK: - RoomCellURLPreviewDisplayable -extension BubbleCellContentView: RoomCellURLPreviewDisplayable { +extension RoomCellContentView: RoomCellURLPreviewDisplayable { func addURLPreviewView(_ urlPreviewView: UIView) { diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellDecorationAlignment.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellDecorationAlignment.swift index 4aa7f7d53..f5fc67ae2 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellDecorationAlignment.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellDecorationAlignment.swift @@ -16,7 +16,7 @@ import Foundation -/// BubbleCellContentView decoration view items alignment +/// RoomCellContentView decoration view items alignment enum RoomCellDecorationAlignment { case left case right diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift index 0344b20b9..b40f760fb 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift @@ -31,7 +31,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { weak var keyVerificationCellInnerContentView: KeyVerificationCellInnerContentView? - weak var bubbleCellContentView: BubbleCellContentView? + weak var bubbleCellContentView: RoomCellContentView? override var bubbleInfoContainer: UIView! { get { @@ -202,7 +202,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { private func setupContentView() { if self.bubbleCellContentView == nil { - let bubbleCellContentView = BubbleCellContentView.instantiate() + let bubbleCellContentView = RoomCellContentView.instantiate() let innerContentView = KeyVerificationCellInnerContentView.instantiate() diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift index 8567af631..3dbbcef1f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift @@ -18,7 +18,7 @@ import Foundation protocol BubbleRoomCellProtocol { - var bubbleCellContentView: BubbleCellContentView? { get } + var bubbleCellContentView: RoomCellContentView? { get } func setupBubbleDecorations() } From 2382ce857de3ba88a653ebb25c05f0529c0e4846 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:40:39 +0100 Subject: [PATCH 082/188] BaseRoomCell: Rename bubbleCellContentView property to roomCellContentView. --- .../BaseRoomCell/BaseRoomCell.swift | 68 +++++++++---------- .../SizableCell/SizableBubbleCell.swift | 6 +- 2 files changed, 37 insertions(+), 37 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index d280a1d67..711c9c02f 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -17,10 +17,10 @@ limitations under the License. import UIKit @objc protocol BaseRoomCellProtocol: Themable { - var bubbleCellContentView: RoomCellContentView? { get } + var roomCellContentView: RoomCellContentView? { get } } -/// `BaseRoomCell` allows a bubble cell that inherits from this class to embed and manage the default room message outer views and add an inner content view. +/// `BaseRoomCell` allows a room cell that inherits from this class to embed and manage the default room message outer views and add an inner content view. @objcMembers class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { @@ -32,7 +32,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { // MARK: Public - weak var bubbleCellContentView: RoomCellContentView? + weak var roomCellContentView: RoomCellContentView? private(set) var theme: Theme? @@ -40,7 +40,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override var bubbleInfoContainer: UIView! { get { - guard let infoContainer = self.bubbleCellContentView?.bubbleInfoContainer else { + guard let infoContainer = self.roomCellContentView?.bubbleInfoContainer else { fatalError("[BaseRoomCell] bubbleInfoContainer should not be used before set") } return infoContainer @@ -52,7 +52,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override var bubbleOverlayContainer: UIView! { get { - guard let overlayContainer = self.bubbleCellContentView?.bubbleOverlayContainer else { + guard let overlayContainer = self.roomCellContentView?.bubbleOverlayContainer else { fatalError("[BaseRoomCell] bubbleOverlayContainer should not be used before set") } return overlayContainer @@ -64,7 +64,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override var bubbleInfoContainerTopConstraint: NSLayoutConstraint! { get { - guard let infoContainerTopConstraint = self.bubbleCellContentView?.bubbleInfoContainerTopConstraint else { + guard let infoContainerTopConstraint = self.roomCellContentView?.bubbleInfoContainerTopConstraint else { fatalError("[BaseRoomCell] bubbleInfoContainerTopConstraint should not be used before set") } return infoContainerTopConstraint @@ -76,12 +76,12 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override var pictureView: MXKImageView! { get { - guard let bubbleCellContentView = self.bubbleCellContentView, - bubbleCellContentView.showSenderAvatar else { + guard let roomCellContentView = self.roomCellContentView, + roomCellContentView.showSenderAvatar else { return nil } - guard let pictureView = self.bubbleCellContentView?.avatarImageView else { + guard let pictureView = self.roomCellContentView?.avatarImageView else { fatalError("[BaseRoomCell] pictureView should not be used before set") } return pictureView @@ -93,11 +93,11 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override var userNameLabel: UILabel! { get { - guard let bubbleCellContentView = self.bubbleCellContentView, bubbleCellContentView.showSenderName else { + guard let roomCellContentView = self.roomCellContentView, roomCellContentView.showSenderName else { return nil } - guard let userNameLabel = bubbleCellContentView.userNameLabel else { + guard let userNameLabel = roomCellContentView.userNameLabel else { fatalError("[BaseRoomCell] userNameLabel should not be used before set") } return userNameLabel @@ -109,12 +109,12 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override var userNameTapGestureMaskView: UIView! { get { - guard let bubbleCellContentView = self.bubbleCellContentView, - bubbleCellContentView.showSenderName else { + guard let roomCellContentView = self.roomCellContentView, + roomCellContentView.showSenderName else { return nil } - guard let userNameTapGestureMaskView = self.bubbleCellContentView?.userNameTouchMaskView else { + guard let userNameTapGestureMaskView = self.roomCellContentView?.userNameTouchMaskView else { fatalError("[BaseRoomCell] userNameTapGestureMaskView should not be used before set") } return userNameTapGestureMaskView @@ -174,7 +174,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { override func setupViews() { super.setupViews() - let showEncryptionStatus = bubbleCellContentView?.showEncryptionStatus ?? false + let showEncryptionStatus = roomCellContentView?.showEncryptionStatus ?? false if showEncryptionStatus { self.setupEncryptionStatusViewTapGestureRecognizer() @@ -197,17 +197,17 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { super.render(cellData) - guard let bubbleCellContentView = self.bubbleCellContentView else { + guard let roomCellContentView = self.roomCellContentView else { return } if let bubbleData = self.bubbleData, let paginationDate = bubbleData.date, - bubbleCellContentView.showPaginationTitle { - bubbleCellContentView.paginationLabel.text = bubbleData.eventFormatter.dateString(from: paginationDate, withTime: false)?.uppercased() + roomCellContentView.showPaginationTitle { + roomCellContentView.paginationLabel.text = bubbleData.eventFormatter.dateString(from: paginationDate, withTime: false)?.uppercased() } - if bubbleCellContentView.showEncryptionStatus { + if roomCellContentView.showEncryptionStatus { self.updateEncryptionStatusViewImage() } @@ -223,7 +223,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { func update(theme: Theme) { self.theme = theme - self.bubbleCellContentView?.update(theme: theme) + self.roomCellContentView?.update(theme: theme) } // MARK: - Private @@ -237,67 +237,67 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { } private func setupContentView() { - guard self.bubbleCellContentView == nil else { + guard self.roomCellContentView == nil else { return } - let bubbleCellContentView = RoomCellContentView.instantiate() - self.contentView.vc_addSubViewMatchingParent(bubbleCellContentView) - self.bubbleCellContentView = bubbleCellContentView + let roomCellContentView = RoomCellContentView.instantiate() + self.contentView.vc_addSubViewMatchingParent(roomCellContentView) + self.roomCellContentView = roomCellContentView } // MARK: - RoomCellURLPreviewDisplayable // Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReadReceiptsDisplayable method below will be used func addURLPreviewView(_ urlPreviewView: UIView) { - self.bubbleCellContentView?.addURLPreviewView(urlPreviewView) + self.roomCellContentView?.addURLPreviewView(urlPreviewView) // tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell self.addTemporarySubview(urlPreviewView) } func removeURLPreviewView() { - self.bubbleCellContentView?.removeURLPreviewView() + self.roomCellContentView?.removeURLPreviewView() } // MARK: - BubbleCellReadReceiptsDisplayable // Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReadReceiptsDisplayable method below will be used func addReadReceiptsView(_ readReceiptsView: UIView) { - self.bubbleCellContentView?.addReadReceiptsView(readReceiptsView) + self.roomCellContentView?.addReadReceiptsView(readReceiptsView) // tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell self.addTemporarySubview(readReceiptsView) } func removeReadReceiptsView() { - self.bubbleCellContentView?.removeReadReceiptsView() + self.roomCellContentView?.removeReadReceiptsView() } // MARK: - BubbleCellReactionsDisplayable // Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReactionsDisplayable method below will be used func addReactionsView(_ reactionsView: UIView) { - self.bubbleCellContentView?.addReactionsView(reactionsView) + self.roomCellContentView?.addReactionsView(reactionsView) // tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell self.addTemporarySubview(reactionsView) } func removeReactionsView() { - self.bubbleCellContentView?.removeReactionsView() + self.roomCellContentView?.removeReactionsView() } // MARK: - BubbleCellThreadSummaryDisplayable func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { - self.bubbleCellContentView?.addThreadSummaryView(threadSummaryView) + self.roomCellContentView?.addThreadSummaryView(threadSummaryView) // tmpSubviews is used for touch detection in MXKRoomBubbleTableViewCell self.addTemporarySubview(threadSummaryView) } func removeThreadSummaryView() { - self.bubbleCellContentView?.removeThreadSummaryView() + self.roomCellContentView?.removeThreadSummaryView() } // Encryption status @@ -306,13 +306,13 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { guard let component = self.bubbleData.getFirstBubbleComponentWithDisplay() else { return } - self.bubbleCellContentView?.encryptionImageView.image = RoomEncryptedDataBubbleCell.encryptionIcon(for: component) + self.roomCellContentView?.encryptionImageView.image = RoomEncryptedDataBubbleCell.encryptionIcon(for: component) } private func setupEncryptionStatusViewTapGestureRecognizer() { let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(handleEncryptionStatusContainerViewTap(_:))) tapGestureRecognizer.delegate = self - self.bubbleCellContentView?.encryptionImageView.isUserInteractionEnabled = true + self.roomCellContentView?.encryptionImageView.isUserInteractionEnabled = true } @objc private func handleEncryptionStatusContainerViewTap(_ gestureRecognizer: UITapGestureRecognizer) { diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift index ccf4b52c9..1275adac3 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift @@ -128,7 +128,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { let roomBubbleCellData = cellData as? RoomBubbleCellData, let bubbleReactionsViewModel = self.reactionsViewModelBuilder.buildForFirstVisibleComponent(of: roomBubbleCellData) { - let reactionWidth = sizingView.bubbleCellContentView?.reactionsContentView.frame.width ?? roomBubbleCellData.maxTextViewWidth + let reactionWidth = sizingView.roomCellContentView?.reactionsContentView.frame.width ?? roomBubbleCellData.maxTextViewWidth let reactionsHeight = self.reactionsViewSizer.height(for: bubbleReactionsViewModel, fittingWidth: reactionWidth) height+=reactionsHeight @@ -139,7 +139,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { let roomBubbleCellData = cellData as? RoomBubbleCellData, roomBubbleCellData.hasThreadRoot { - let bottomMargin = sizingView.bubbleCellContentView?.threadSummaryContentViewBottomConstraint.constant ?? 0 + let bottomMargin = sizingView.roomCellContentView?.threadSummaryContentViewBottomConstraint.constant ?? 0 height += RoomBubbleCellLayout.threadSummaryViewHeight height += bottomMargin @@ -150,7 +150,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { let roomBubbleCellData = cellData as? RoomBubbleCellData, let firstBubbleComponent = roomBubbleCellData.getFirstBubbleComponentWithDisplay(), firstBubbleComponent.showURLPreview, let urlPreviewData = firstBubbleComponent.urlPreviewData as? URLPreviewData { - let urlPreviewMaxWidth = sizingView.bubbleCellContentView?.urlPreviewContentView.frame.width ?? roomBubbleCellData.maxTextViewWidth + let urlPreviewMaxWidth = sizingView.roomCellContentView?.urlPreviewContentView.frame.width ?? roomBubbleCellData.maxTextViewWidth let urlPreviewHeight = self.urlPreviewViewSizer.height(for: urlPreviewData, fittingWidth: urlPreviewMaxWidth) height+=urlPreviewHeight From 861faacc7d419c6f3cfdfd3f1c205ecc02124fb8 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:40:56 +0100 Subject: [PATCH 083/188] BaseRoomCell: Rename bubbleCellContentView property to roomCellContentView (2). --- .../KeyVerificationBaseBubbleCell.swift | 30 ++++++++-------- ...clusionWithPaginationTitleBubbleCell.swift | 4 +-- ...pprovalWithPaginationTitleBubbleCell.swift | 4 +-- ...tStatusWithPaginationTitleBubbleCell.swift | 4 +-- .../RoomCreationIntroCell.swift | 22 ++++++------ .../BubbleIncomingRoomCellProtocol.swift | 10 +++--- .../BubbleOutgoingRoomCellProtocol.swift | 34 +++++++++---------- .../Bubble/Cells/BubbleRoomCellProtocol.swift | 2 +- .../FileWithoutThumbnailBaseBubbleCell.swift | 4 +-- ...leWithoutThumbnailIncomingBubbleCell.swift | 6 ++-- ...ncomingWithPaginationTitleBubbleCell.swift | 2 +- ...lIncomingWithoutSenderInfoBubbleCell.swift | 2 +- ...OutoingWithPaginationTitleBubbleCell.swift | 2 +- ...ilOutoingWithoutSenderInfoBubbleCell.swift | 6 ++-- .../Incoming/LocationIncomingBubbleCell.swift | 4 +-- ...ncomingWithPaginationTitleBubbleCell.swift | 2 +- ...nIncomingWithoutSenderInfoBubbleCell.swift | 2 +- ...utgoingWithPaginationTitleBubbleCell.swift | 2 +- ...nOutgoingWithoutSenderInfoBubbleCell.swift | 6 ++-- .../Incoming/PollIncomingBubbleCell.swift | 4 +-- ...ncomingWithPaginationTitleBubbleCell.swift | 2 +- ...lIncomingWithoutSenderInfoBubbleCell.swift | 2 +- ...utgoingWithPaginationTitleBubbleCell.swift | 2 +- ...lOutgoingWithoutSenderInfoBubbleCell.swift | 6 ++-- .../Cells/Poll/PollBaseBubbleCell.swift | 4 +-- .../Common/TextMessageBaseBubbleCell.swift | 6 ++-- .../TextMessageIncomingBubbleCell.swift | 6 ++-- ...ncomingWithPaginationTitleBubbleCell.swift | 2 +- ...tionTitleWithoutSenderNameBubbleCell.swift | 2 +- ...eIncomingWithoutSenderInfoBubbleCell.swift | 2 +- ...eIncomingWithoutSenderNameBubbleCell.swift | 2 +- ...utgoingWithPaginationTitleBubbleCell.swift | 2 +- ...tionTitleWithoutSenderNameBubbleCell.swift | 2 +- ...eOutgoingWithoutSenderInfoBubbleCell.swift | 6 ++-- .../VoiceMessageIncomingBubbleCell.swift | 4 +-- ...ncomingWithPaginationTitleBubbleCell.swift | 2 +- ...eIncomingWithoutSenderInfoBubbleCell.swift | 2 +- ...utgoingWithPaginationTitleBubbleCell.swift | 2 +- ...eOutgoingWithoutSenderInfoBubbleCell.swift | 6 ++-- .../Cells/Location/LocationBubbleCell.swift | 8 ++--- ...ocationWithPaginationTitleBubbleCell.swift | 2 +- .../LocationWithoutSenderInfoBubbleCell.swift | 2 +- .../Plain/Cells/Poll/PollBubbleCell.swift | 8 ++--- .../PollWithPaginationTitleBubbleCell.swift | 2 +- .../PollWithoutSenderInfoBubbleCell.swift | 2 +- .../VoiceMessage/VoiceMessageBubbleCell.swift | 8 ++--- ...MessageWithPaginationTitleBubbleCell.swift | 2 +- ...ceMessageWithoutSenderInfoBubbleCell.swift | 2 +- 48 files changed, 125 insertions(+), 125 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift index b40f760fb..ac2d528b5 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift @@ -31,11 +31,11 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { weak var keyVerificationCellInnerContentView: KeyVerificationCellInnerContentView? - weak var bubbleCellContentView: RoomCellContentView? + weak var roomCellContentView: RoomCellContentView? override var bubbleInfoContainer: UIView! { get { - guard let infoContainer = self.bubbleCellContentView?.bubbleInfoContainer else { + guard let infoContainer = self.roomCellContentView?.bubbleInfoContainer else { fatalError("[KeyVerificationBaseBubbleCell] bubbleInfoContainer should not be used before set") } return infoContainer @@ -47,7 +47,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { override var bubbleOverlayContainer: UIView! { get { - guard let overlayContainer = self.bubbleCellContentView?.bubbleOverlayContainer else { + guard let overlayContainer = self.roomCellContentView?.bubbleOverlayContainer else { fatalError("[KeyVerificationBaseBubbleCell] bubbleOverlayContainer should not be used before set") } return overlayContainer @@ -59,7 +59,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { override var bubbleInfoContainerTopConstraint: NSLayoutConstraint! { get { - guard let infoContainerTopConstraint = self.bubbleCellContentView?.bubbleInfoContainerTopConstraint else { + guard let infoContainerTopConstraint = self.roomCellContentView?.bubbleInfoContainerTopConstraint else { fatalError("[KeyVerificationBaseBubbleCell] bubbleInfoContainerTopConstraint should not be used before set") } return infoContainerTopConstraint @@ -92,7 +92,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { // MARK: - Public func update(theme: Theme) { - self.bubbleCellContentView?.update(theme: theme) + self.roomCellContentView?.update(theme: theme) self.keyVerificationCellInnerContentView?.update(theme: theme) } @@ -190,27 +190,27 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { super.render(cellData) if let bubbleData = self.bubbleData, - let bubbleCellContentView = self.bubbleCellContentView, + let roomCellContentView = self.roomCellContentView, let paginationDate = bubbleData.date, - bubbleCellContentView.showPaginationTitle { - bubbleCellContentView.paginationLabel.text = bubbleData.eventFormatter.dateString(from: paginationDate, withTime: false)?.uppercased() + roomCellContentView.showPaginationTitle { + roomCellContentView.paginationLabel.text = bubbleData.eventFormatter.dateString(from: paginationDate, withTime: false)?.uppercased() } } // MARK: - Private private func setupContentView() { - if self.bubbleCellContentView == nil { + if self.roomCellContentView == nil { - let bubbleCellContentView = RoomCellContentView.instantiate() + let roomCellContentView = RoomCellContentView.instantiate() let innerContentView = KeyVerificationCellInnerContentView.instantiate() - bubbleCellContentView.innerContentView.vc_addSubViewMatchingParent(innerContentView) + roomCellContentView.innerContentView.vc_addSubViewMatchingParent(innerContentView) - self.contentView.vc_addSubViewMatchingParent(bubbleCellContentView) + self.contentView.vc_addSubViewMatchingParent(roomCellContentView) - self.bubbleCellContentView = bubbleCellContentView + self.roomCellContentView = roomCellContentView self.keyVerificationCellInnerContentView = innerContentView } } @@ -252,10 +252,10 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { extension KeyVerificationBaseBubbleCell: BubbleCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { - self.bubbleCellContentView?.addReadReceiptsView(readReceiptsView) + self.roomCellContentView?.addReadReceiptsView(readReceiptsView) } func removeReadReceiptsView() { - self.bubbleCellContentView?.removeReadReceiptsView() + self.roomCellContentView?.removeReadReceiptsView() } } diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift index 7cc1b8277..386d12e81 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationConclusionWithPaginationTitleBubbleCell.swift @@ -37,11 +37,11 @@ final class KeyVerificationConclusionWithPaginationTitleBubbleCell: KeyVerificat } private func commonInit() { - guard let bubbleCellContentView = self.bubbleCellContentView else { + guard let roomCellContentView = self.roomCellContentView else { fatalError("[KeyVerificationConclusionWithPaginationTitleBubbleCell] bubbleCellContentView should not be nil") } - bubbleCellContentView.showPaginationTitle = true + roomCellContentView.showPaginationTitle = true } // MARK: - Overrides diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift index 6b4b529f1..8a13a24c7 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell.swift @@ -37,11 +37,11 @@ final class KeyVerificationIncomingRequestApprovalWithPaginationTitleBubbleCell: } private func commonInit() { - guard let bubbleCellContentView = self.bubbleCellContentView else { + guard let roomCellContentView = self.roomCellContentView else { fatalError("[KeyVerificationRequestStatusWithPaginationTitleBubbleCell] bubbleCellContentView should not be nil") } - bubbleCellContentView.showPaginationTitle = true + roomCellContentView.showPaginationTitle = true } // MARK: - Overrides diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift index f9c0e6465..1e2b7f5b6 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationRequestStatusWithPaginationTitleBubbleCell.swift @@ -37,11 +37,11 @@ final class KeyVerificationRequestStatusWithPaginationTitleBubbleCell: KeyVerifi } private func commonInit() { - guard let bubbleCellContentView = self.bubbleCellContentView else { + guard let roomCellContentView = self.roomCellContentView else { fatalError("[KeyVerificationRequestStatusWithPaginationTitleBubbleCell] bubbleCellContentView should not be nil") } - bubbleCellContentView.showPaginationTitle = true + roomCellContentView.showPaginationTitle = true } // MARK: - Overrides diff --git a/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift b/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift index f53c943c2..dbe4f7520 100644 --- a/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift +++ b/Riot/Modules/Room/TimelineCells/RoomCreationIntro/RoomCreationIntroCell.swift @@ -32,7 +32,7 @@ class RoomCreationIntroCell: MXKRoomBubbleTableViewCell { // MARK: - Properties - private weak var bubbleCellContentView: RoomCreationIntroCellContentView? + private weak var roomCellContentView: RoomCreationIntroCellContentView? // MARK: - Setup @@ -57,7 +57,7 @@ class RoomCreationIntroCell: MXKRoomBubbleTableViewCell { // MARK: - Public func update(theme: Theme) { - self.bubbleCellContentView?.update(theme: theme) + self.roomCellContentView?.update(theme: theme) } // MARK: - Overrides @@ -92,7 +92,7 @@ class RoomCreationIntroCell: MXKRoomBubbleTableViewCell { override func render(_ cellData: MXKCellData!) { super.render(cellData) - guard let bubbleCellContentView = self.bubbleCellContentView else { + guard let roomCellContentView = self.roomCellContentView else { MXLog.debug("[RoomCreationIntroCell] Fail to load content view") return } @@ -103,7 +103,7 @@ class RoomCreationIntroCell: MXKRoomBubbleTableViewCell { return } - bubbleCellContentView.fill(with: viewData) + roomCellContentView.fill(with: viewData) } // MARK: - Private @@ -140,23 +140,23 @@ class RoomCreationIntroCell: MXKRoomBubbleTableViewCell { } private func setupContentView() { - guard self.bubbleCellContentView == nil else { + guard self.roomCellContentView == nil else { return } - let bubbleCellContentView = RoomCreationIntroCellContentView.instantiate() - self.contentView.vc_addSubViewMatchingParent(bubbleCellContentView) - self.bubbleCellContentView = bubbleCellContentView + let roomCellContentView = RoomCreationIntroCellContentView.instantiate() + self.contentView.vc_addSubViewMatchingParent(roomCellContentView) + self.roomCellContentView = roomCellContentView - bubbleCellContentView.roomAvatarView?.action = { [weak self] in + roomCellContentView.roomAvatarView?.action = { [weak self] in self?.notifyDelegate(with: RoomCreationIntroCell.tapOnAvatarView) } - bubbleCellContentView.didTapTopic = { [weak self] in + roomCellContentView.didTapTopic = { [weak self] in self?.notifyDelegate(with: RoomCreationIntroCell.tapOnAddTopic) } - bubbleCellContentView.didTapAddParticipants = { [weak self] in + roomCellContentView.didTapAddParticipants = { [weak self] in self?.notifyDelegate(with: RoomCreationIntroCell.tapOnAddParticipants) } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift index 32597da8e..f166e6635 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleIncomingRoomCellProtocol.swift @@ -24,7 +24,7 @@ extension BubbleIncomingRoomCellProtocol { // MARK: - Public func setupBubbleDecorations() { - self.bubbleCellContentView?.decorationViewsAlignment = .left + self.roomCellContentView?.decorationViewsAlignment = .left self.setupDecorationConstraints() } @@ -39,16 +39,16 @@ extension BubbleIncomingRoomCellProtocol { private func setupReactionsContentViewContraints() { - self.bubbleCellContentView?.reactionsContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + self.roomCellContentView?.reactionsContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right } private func setupThreadSummaryViewContentViewContraints() { - self.bubbleCellContentView?.threadSummaryContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + self.roomCellContentView?.threadSummaryContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right - self.bubbleCellContentView?.threadSummaryContentViewBottomConstraint.constant = BubbleRoomCellLayoutConstants.threadSummaryViewMargins.bottom + self.roomCellContentView?.threadSummaryContentViewBottomConstraint.constant = BubbleRoomCellLayoutConstants.threadSummaryViewMargins.bottom } private func setupURLPreviewContentViewContraints() { - self.bubbleCellContentView?.urlPreviewContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + self.roomCellContentView?.urlPreviewContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift index 2c548f80b..435074a57 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleOutgoingRoomCellProtocol.swift @@ -26,7 +26,7 @@ extension BubbleOutgoingRoomCellProtocol { // MARK: - Public func setupBubbleDecorations() { - self.bubbleCellContentView?.decorationViewsAlignment = .right + self.roomCellContentView?.decorationViewsAlignment = .right self.setupDecorationConstraints() } @@ -40,72 +40,72 @@ extension BubbleOutgoingRoomCellProtocol { } private func setupReactionsContentViewContraints() { - guard let bubbleCellContentView = self.bubbleCellContentView, let reactionsContentView = bubbleCellContentView.reactionsContentView, let reactionsContainerView = bubbleCellContentView.reactionsContainerView else { + guard let roomCellContentView = self.roomCellContentView, let reactionsContentView = roomCellContentView.reactionsContentView, let reactionsContainerView = roomCellContentView.reactionsContainerView else { return } // Remove leading constraint - bubbleCellContentView.reactionsContentViewLeadingConstraint.isActive = false - bubbleCellContentView.reactionsContentViewLeadingConstraint = nil + roomCellContentView.reactionsContentViewLeadingConstraint.isActive = false + roomCellContentView.reactionsContentViewLeadingConstraint = nil // Setup new leading constraint let leadingConstraint = self.setupDecorationViewLeadingContraint(containerView: reactionsContainerView, contentView: reactionsContentView) - bubbleCellContentView.reactionsContentViewLeadingConstraint = leadingConstraint + roomCellContentView.reactionsContentViewLeadingConstraint = leadingConstraint // Update trailing constraint - bubbleCellContentView.reactionsContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + roomCellContentView.reactionsContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right } private func setupThreadSummaryViewContentViewContraints() { - guard let bubbleCellContentView = self.bubbleCellContentView, let threadSummaryContentView = bubbleCellContentView.threadSummaryContentView, let threadSummaryContainerView = bubbleCellContentView.threadSummaryContainerView else { + guard let roomCellContentView = self.roomCellContentView, let threadSummaryContentView = roomCellContentView.threadSummaryContentView, let threadSummaryContainerView = roomCellContentView.threadSummaryContainerView else { return } // Remove leading constraint - bubbleCellContentView.threadSummaryContentViewLeadingConstraint.isActive = false - bubbleCellContentView.threadSummaryContentViewLeadingConstraint = nil + roomCellContentView.threadSummaryContentViewLeadingConstraint.isActive = false + roomCellContentView.threadSummaryContentViewLeadingConstraint = nil // Setup new leading constraint let leadingConstraint = self.setupDecorationViewLeadingContraint(containerView: threadSummaryContainerView, contentView: threadSummaryContentView) - bubbleCellContentView.threadSummaryContentViewLeadingConstraint = leadingConstraint + roomCellContentView.threadSummaryContentViewLeadingConstraint = leadingConstraint // Update trailing constraint - bubbleCellContentView.threadSummaryContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + roomCellContentView.threadSummaryContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right // Update bottom constraint - bubbleCellContentView.threadSummaryContentViewBottomConstraint.constant = BubbleRoomCellLayoutConstants.threadSummaryViewMargins.bottom + roomCellContentView.threadSummaryContentViewBottomConstraint.constant = BubbleRoomCellLayoutConstants.threadSummaryViewMargins.bottom } private func setupURLPreviewContentViewContraints() { - guard let bubbleCellContentView = self.bubbleCellContentView, let contentView = bubbleCellContentView.urlPreviewContentView, let containerView = bubbleCellContentView.urlPreviewContainerView else { + guard let roomCellContentView = self.roomCellContentView, let contentView = roomCellContentView.urlPreviewContentView, let containerView = roomCellContentView.urlPreviewContainerView else { return } // Remove leading constraint - bubbleCellContentView.urlPreviewContentViewLeadingConstraint.isActive = false - bubbleCellContentView.urlPreviewContentViewLeadingConstraint = nil + roomCellContentView.urlPreviewContentViewLeadingConstraint.isActive = false + roomCellContentView.urlPreviewContentViewLeadingConstraint = nil // Setup new leading constraint let leadingConstraint = self.setupDecorationViewLeadingContraint(containerView: containerView, contentView: contentView) - bubbleCellContentView.urlPreviewContentViewLeadingConstraint = leadingConstraint + roomCellContentView.urlPreviewContentViewLeadingConstraint = leadingConstraint // Update trailing constraint - bubbleCellContentView.urlPreviewContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + roomCellContentView.urlPreviewContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right } private func setupDecorationViewLeadingContraint(containerView: UIView, diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift index 3dbbcef1f..8ae817999 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/BubbleRoomCellProtocol.swift @@ -18,7 +18,7 @@ import Foundation protocol BubbleRoomCellProtocol { - var bubbleCellContentView: RoomCellContentView? { get } + var roomCellContentView: RoomCellContentView? { get } func setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift index 32dfe9612..904dcf1b6 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift @@ -31,9 +31,9 @@ class FileWithoutThumbnailBaseBubbleCell: SizableBaseBubbleCell, BubbleCellReact override func setupViews() { super.setupViews() - bubbleCellContentView?.backgroundColor = .clear + roomCellContentView?.backgroundColor = .clear - guard let contentView = bubbleCellContentView?.innerContentView else { + guard let contentView = roomCellContentView?.innerContentView else { return } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift index dcf4ef447..8a768d1de 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingBubbleCell.swift @@ -21,10 +21,10 @@ class FileWithoutThumbnailIncomingBubbleCell: FileWithoutThumbnailBaseBubbleCell override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = true + roomCellContentView?.showSenderInfo = true - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift index 518f4fc95..7ef12d6d4 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell.swift @@ -21,6 +21,6 @@ class FileWithoutThumbnailIncomingWithPaginationTitleBubbleCell: FileWithoutThum override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift index 1db1510ca..efc1d471b 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Incoming/FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell.swift @@ -21,6 +21,6 @@ class FileWithoutThumbnailIncomingWithoutSenderInfoBubbleCell: FileWithoutThumbn override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift index 0cf7acb6c..1a276f1f2 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell.swift @@ -21,6 +21,6 @@ class FileWithoutThumbnailOutoingWithPaginationTitleBubbleCell: FileWithoutThumb override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift index f3d5e8a3a..d9742637b 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Outgoing/FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell.swift @@ -21,10 +21,10 @@ class FileWithoutThumbnailOutoingWithoutSenderInfoBubbleCell: FileWithoutThumbna override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift index 97a80a5ca..769b2b555 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingBubbleCell.swift @@ -21,8 +21,8 @@ class LocationIncomingBubbleCell: LocationBubbleCell, BubbleIncomingRoomCellProt override func setupViews() { super.setupViews() - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift index 77b1e17e1..f08217b3c 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithPaginationTitleBubbleCell.swift @@ -20,6 +20,6 @@ class LocationIncomingWithPaginationTitleBubbleCell: LocationIncomingBubbleCell override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift index 880e7c286..5cddbb3c7 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Incoming/LocationIncomingWithoutSenderInfoBubbleCell.swift @@ -20,6 +20,6 @@ class LocationIncomingWithoutSenderInfoBubbleCell: LocationIncomingBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift index f1158043f..0199dea51 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithPaginationTitleBubbleCell.swift @@ -20,6 +20,6 @@ class LocationOutgoingWithPaginationTitleBubbleCell: LocationOutgoingWithoutSend override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift index 3d30a86b0..831a11a94 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Location/Outgoing/LocationOutgoingWithoutSenderInfoBubbleCell.swift @@ -21,10 +21,10 @@ class LocationOutgoingWithoutSenderInfoBubbleCell: LocationBubbleCell, BubbleOut override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift index aee7f1030..b8d92394e 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingBubbleCell.swift @@ -24,8 +24,8 @@ class PollIncomingBubbleCell: PollBaseBubbleCell, BubbleIncomingRoomCellProtocol let leftMargin: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.left let rightMargin: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.right - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin + roomCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin + roomCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift index b797637a0..252308a14 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithPaginationTitleBubbleCell.swift @@ -21,7 +21,7 @@ class PollIncomingWithPaginationTitleBubbleCell: PollIncomingBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift index b9cdbd633..5cb6dad1f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Incoming/PollIncomingWithoutSenderInfoBubbleCell.swift @@ -21,7 +21,7 @@ class PollIncomingWithoutSenderInfoBubbleCell: PollIncomingBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift index c8a9453e9..61b6decd0 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithPaginationTitleBubbleCell.swift @@ -21,7 +21,7 @@ class PollOutgoingWithPaginationTitleBubbleCell: PollOutgoingWithoutSenderInfoBu override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift index 2525b2af8..ce644496d 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/Outgoing/PollOutgoingWithoutSenderInfoBubbleCell.swift @@ -21,13 +21,13 @@ class PollOutgoingWithoutSenderInfoBubbleCell: PollBaseBubbleCell, BubbleOutgoin override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false let leftMargin: CGFloat = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.left let rightMargin: CGFloat = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.pollBubbleBackgroundInsets.right - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin + roomCellContentView?.innerContentViewTrailingConstraint.constant = rightMargin + roomCellContentView?.innerContentViewLeadingConstraint.constant = leftMargin self.setupBubbleDecorations() } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift index bac34614c..769eb82e5 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/Poll/PollBaseBubbleCell.swift @@ -77,12 +77,12 @@ class PollBaseBubbleCell: PollBubbleCell { private func setupBubbleBackgroundView() { let bubbleBackgroundView = RoomMessageBubbleBackgroundView() - self.bubbleCellContentView?.insertSubview(bubbleBackgroundView, at: 0) + self.roomCellContentView?.insertSubview(bubbleBackgroundView, at: 0) } // The extension property MXKRoomBubbleTableViewCell.messageBubbleBackgroundView is not working there even by doing recursion private func getBubbleBackgroundView() -> RoomMessageBubbleBackgroundView? { - guard let contentView = self.bubbleCellContentView else { + guard let contentView = self.roomCellContentView else { return nil } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 2c24723d3..3cd7d847c 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -34,13 +34,13 @@ class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDispla override func setupViews() { super.setupViews() - bubbleCellContentView?.backgroundColor = .clear + roomCellContentView?.backgroundColor = .clear - guard let contentView = bubbleCellContentView?.innerContentView else { + guard let contentView = roomCellContentView?.innerContentView else { return } - bubbleCellContentView?.innerContentViewBottomContraint.constant = BubbleRoomCellLayoutConstants.innerContentViewMargins.bottom + roomCellContentView?.innerContentViewBottomContraint.constant = BubbleRoomCellLayoutConstants.innerContentViewMargins.bottom let textMessageContentView = TextMessageBubbleCellContentView.instantiate() diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift index d2aa686ec..3c54e5640 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingBubbleCell.swift @@ -23,7 +23,7 @@ class TextMessageIncomingBubbleCell: TextMessageBaseBubbleCell, BubbleIncomingRo override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = true + roomCellContentView?.showSenderInfo = true self.setupBubbleConstraints() self.setupBubbleDecorations() @@ -39,8 +39,8 @@ class TextMessageIncomingBubbleCell: TextMessageBaseBubbleCell, BubbleIncomingRo private func setupBubbleConstraints() { - self.bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + self.roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left - self.bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + self.roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift index 7b47ab409..2db0ee1d5 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleBubbleCell.swift @@ -21,6 +21,6 @@ class TextMessageIncomingWithPaginationTitleBubbleCell: TextMessageIncomingBubbl override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift index 8f2c5fcc6..c13c6856f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell.swift @@ -21,6 +21,6 @@ class TextMessageIncomingWithPaginationTitleWithoutSenderNameBubbleCell: TextMes override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderName = false + roomCellContentView?.showSenderName = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift index abeed3435..5018b34fd 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderInfoBubbleCell.swift @@ -21,6 +21,6 @@ class TextMessageIncomingWithoutSenderInfoBubbleCell: TextMessageIncomingBubbleC override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift index 15bbacf0c..f1724e46f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Incoming/TextMessageIncomingWithoutSenderNameBubbleCell.swift @@ -21,6 +21,6 @@ class TextMessageIncomingWithoutSenderNameBubbleCell: TextMessageIncomingBubbleC override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderName = false + roomCellContentView?.showSenderName = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift index 1ffb87c80..18c7420b0 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleBubbleCell.swift @@ -21,6 +21,6 @@ class TextMessageOutgoingWithPaginationTitleBubbleCell: TextMessageOutgoingWitho override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift index dd9a345e3..7beb377c1 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell.swift @@ -19,6 +19,6 @@ class TextMessageOutgoingWithPaginationTitleWithoutSenderNameBubbleCell: TextMes override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderName = false + roomCellContentView?.showSenderName = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift index edc945b31..de15e91d3 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Outgoing/TextMessageOutgoingWithoutSenderInfoBubbleCell.swift @@ -23,7 +23,7 @@ class TextMessageOutgoingWithoutSenderInfoBubbleCell: TextMessageBaseBubbleCell, override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false self.setupBubbleConstraints() self.setupBubbleDecorations() @@ -39,8 +39,8 @@ class TextMessageOutgoingWithoutSenderInfoBubbleCell: TextMessageBaseBubbleCell, private func setupBubbleConstraints() { - self.bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left - self.bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + self.roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + self.roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right guard let containerView = self.textMessageContentView, let bubbleBackgroundView = containerView.bubbleBackgroundView else { return diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift index b8907847f..c1f2e477c 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingBubbleCell.swift @@ -21,8 +21,8 @@ class VoiceMessageIncomingBubbleCell: VoiceMessageBubbleCell, BubbleIncomingRoom override func setupViews() { super.setupViews() - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right + roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left + roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right playbackController.playbackView.stackViewTrailingContraint.constant = BubbleRoomCellLayoutConstants.voiceMessagePlaybackViewRightMargin diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift index bd6f1fb38..d408e2abf 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithPaginationTitleBubbleCell.swift @@ -21,6 +21,6 @@ class VoiceMessageIncomingWithPaginationTitleBubbleCell: VoiceMessageIncomingBub override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift index f0d5385e6..191a16127 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Incoming/VoiceMessageIncomingWithoutSenderInfoBubbleCell.swift @@ -20,6 +20,6 @@ class VoiceMessageIncomingWithoutSenderInfoBubbleCell: VoiceMessageIncomingBubbl override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift index 9f77e7843..e80bb9b2e 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithPaginationTitleBubbleCell.swift @@ -21,6 +21,6 @@ class VoiceMessageOutgoingWithPaginationTitleBubbleCell: VoiceMessageOutgoingWit override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift index 60964b9b4..2b76d0188 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/VoiceMessage/Outgoing/VoiceMessageOutgoingWithoutSenderInfoBubbleCell.swift @@ -21,10 +21,10 @@ class VoiceMessageOutgoingWithoutSenderInfoBubbleCell: VoiceMessageBubbleCell, B override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false - bubbleCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left - bubbleCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + roomCellContentView?.innerContentViewLeadingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + roomCellContentView?.innerContentViewTrailingConstraint.constant = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right playbackController.playbackView.stackViewTrailingContraint.constant = BubbleRoomCellLayoutConstants.voiceMessagePlaybackViewRightMargin diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift index a0c375569..d0858a44a 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift @@ -55,12 +55,12 @@ class LocationBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable override func setupViews() { super.setupViews() - bubbleCellContentView?.backgroundColor = .clear - bubbleCellContentView?.showSenderInfo = true - bubbleCellContentView?.showPaginationTitle = false + roomCellContentView?.backgroundColor = .clear + roomCellContentView?.showSenderInfo = true + roomCellContentView?.showPaginationTitle = false guard #available(iOS 14.0, *), - let contentView = bubbleCellContentView?.innerContentView else { + let contentView = roomCellContentView?.innerContentView else { return } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithPaginationTitleBubbleCell.swift index e3f6dd84f..690bf10e1 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithPaginationTitleBubbleCell.swift @@ -20,6 +20,6 @@ class LocationWithPaginationTitleBubbleCell: LocationBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithoutSenderInfoBubbleCell.swift index 1329221dd..cda0d9899 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationWithoutSenderInfoBubbleCell.swift @@ -20,6 +20,6 @@ class LocationWithoutSenderInfoBubbleCell: LocationBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift index c1dc7a770..3bbdf917f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift @@ -25,7 +25,7 @@ class PollBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { super.render(cellData) guard #available(iOS 14.0, *), - let contentView = bubbleCellContentView?.innerContentView, + let contentView = roomCellContentView?.innerContentView, let bubbleData = cellData as? RoomBubbleCellData, let event = bubbleData.events.last, event.eventType == __MXEventType.pollStart, @@ -40,9 +40,9 @@ class PollBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { override func setupViews() { super.setupViews() - bubbleCellContentView?.backgroundColor = .clear - bubbleCellContentView?.showSenderInfo = true - bubbleCellContentView?.showPaginationTitle = false + roomCellContentView?.backgroundColor = .clear + roomCellContentView?.showSenderInfo = true + roomCellContentView?.showPaginationTitle = false } // The normal flow for tapping on cell content views doesn't work for bubbles without attributed strings diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithPaginationTitleBubbleCell.swift index de6e92041..969c7864d 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithPaginationTitleBubbleCell.swift @@ -21,7 +21,7 @@ class PollWithPaginationTitleBubbleCell: PollBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithoutSenderInfoBubbleCell.swift index 880ef0cd4..2663996a8 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollWithoutSenderInfoBubbleCell.swift @@ -21,7 +21,7 @@ class PollWithoutSenderInfoBubbleCell: PollBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift index 55c7f2487..ebecb1ad1 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift @@ -41,11 +41,11 @@ class VoiceMessageBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplaya override func setupViews() { super.setupViews() - bubbleCellContentView?.backgroundColor = .clear - bubbleCellContentView?.showSenderInfo = true - bubbleCellContentView?.showPaginationTitle = false + roomCellContentView?.backgroundColor = .clear + roomCellContentView?.showSenderInfo = true + roomCellContentView?.showPaginationTitle = false - guard let contentView = bubbleCellContentView?.innerContentView else { + guard let contentView = roomCellContentView?.innerContentView else { return } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift index b7e516675..f4640031e 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithPaginationTitleBubbleCell.swift @@ -20,6 +20,6 @@ class VoiceMessageWithPaginationTitleBubbleCell: VoiceMessageBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showPaginationTitle = true + roomCellContentView?.showPaginationTitle = true } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift index cc091b39d..84a302d5d 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageWithoutSenderInfoBubbleCell.swift @@ -20,6 +20,6 @@ class VoiceMessageWithoutSenderInfoBubbleCell: VoiceMessageBubbleCell { override func setupViews() { super.setupViews() - bubbleCellContentView?.showSenderInfo = false + roomCellContentView?.showSenderInfo = false } } From b531af320da26e132303cf2d0e39e29d1fb11641 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:41:31 +0100 Subject: [PATCH 084/188] BaseRoomCell: Rename bubbleCellContentView property to roomCellContentView (2). --- .../{BubbleCellContentView.xib => RoomCellContentView.xib} | 2 ++ 1 file changed, 2 insertions(+) rename Riot/Modules/Room/TimelineCells/BaseRoomCell/{BubbleCellContentView.xib => RoomCellContentView.xib} (99%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib similarity index 99% rename from Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib index 6d7b652d1..9244e2dd0 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellContentView.xib +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib @@ -1,6 +1,8 @@ + + From 09520f2de3dc9b16e2d3fe3b308a4fe94d028d51 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:42:19 +0100 Subject: [PATCH 085/188] Rename BubbleCellReactionsDisplayable to RoomCellReactionsDisplayable. --- .../Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift | 2 +- .../Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift | 2 +- ...nsDisplayable.swift => RoomCellReactionsDisplayable.swift} | 4 ++-- .../Room/TimelineCells/SizableCell/SizableBubbleCell.swift | 2 +- .../Styles/Bubble/BubbleRoomTimelineCellDecorator.swift | 2 +- .../Common/FileWithoutThumbnailBaseBubbleCell.swift | 2 +- .../Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift | 2 +- .../Styles/Plain/Cells/Location/LocationBubbleCell.swift | 2 +- .../Styles/Plain/Cells/Poll/PollBubbleCell.swift | 2 +- .../Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift | 2 +- .../Styles/Plain/PlainRoomTimelineCellDecorator.swift | 2 +- 11 files changed, 12 insertions(+), 12 deletions(-) rename Riot/Modules/Room/TimelineCells/BaseRoomCell/{BubbleCellReactionsDisplayable.swift => RoomCellReactionsDisplayable.swift} (81%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index 711c9c02f..24f6a81b6 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -148,7 +148,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { bubbleCellReadReceiptsDisplayable.removeReadReceiptsView() } - if let bubbleCellReactionsDisplayable = self as? BubbleCellReactionsDisplayable { + if let bubbleCellReactionsDisplayable = self as? RoomCellReactionsDisplayable { bubbleCellReactionsDisplayable.removeReactionsView() } diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index 1774b8e06..7d8b6ffe8 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -187,7 +187,7 @@ extension RoomCellContentView: BubbleCellReadReceiptsDisplayable { } // MARK: - BubbleCellReactionsDisplayable -extension RoomCellContentView: BubbleCellReactionsDisplayable { +extension RoomCellContentView: RoomCellReactionsDisplayable { func addReactionsView(_ reactionsView: UIView) { self.reactionsContentView.vc_removeAllSubviews() diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReactionsDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReactionsDisplayable.swift similarity index 81% rename from Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReactionsDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReactionsDisplayable.swift index 91eb3de41..ff8671f7f 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReactionsDisplayable.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReactionsDisplayable.swift @@ -16,8 +16,8 @@ import Foundation -/// `BubbleCellReactionsDisplayable` is a protocol indicating that a cell support displaying reactions. -@objc protocol BubbleCellReactionsDisplayable { +/// `RoomCellReactionsDisplayable` is a protocol indicating that a cell support displaying reactions. +@objc protocol RoomCellReactionsDisplayable { func addReactionsView(_ reactionsView: UIView) func removeReactionsView() } diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift index 1275adac3..46f1c9fc2 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift @@ -124,7 +124,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { } // Add reactions view height if needed - if sizingView is BubbleCellReactionsDisplayable, + if sizingView is RoomCellReactionsDisplayable, let roomBubbleCellData = cellData as? RoomBubbleCellData, let bubbleReactionsViewModel = self.reactionsViewModelBuilder.buildForFirstVisibleComponent(of: roomBubbleCellData) { diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift index 44efeceb1..51d4e324c 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift @@ -93,7 +93,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { override func addReactionView(_ reactionsView: BubbleReactionsView, toCell cell: MXKRoomBubbleTableViewCell, cellData: RoomBubbleCellData, contentViewPositionY: CGFloat, upperDecorationView: UIView?) { - if let reactionsDisplayable = cell as? BubbleCellReactionsDisplayable { + if let reactionsDisplayable = cell as? RoomCellReactionsDisplayable { reactionsDisplayable.addReactionsView(reactionsView) return } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift index 904dcf1b6..d2732155f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift @@ -16,7 +16,7 @@ import UIKit -class FileWithoutThumbnailBaseBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { +class FileWithoutThumbnailBaseBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { weak var fileAttachementView: FileWithoutThumbnailCellContentView? diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 3cd7d847c..5fc4de018 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -16,7 +16,7 @@ import UIKit -class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, BubbleCellReactionsDisplayable, BubbleCellThreadSummaryDisplayable, BubbleCellReadReceiptsDisplayable { +class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, BubbleCellThreadSummaryDisplayable, BubbleCellReadReceiptsDisplayable { // MARK: - Properties diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift index d0858a44a..724ac8459 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift @@ -16,7 +16,7 @@ import Foundation -class LocationBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { +class LocationBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { private var locationView: RoomTimelineLocationView! diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift index 3bbdf917f..dfa193cb6 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift @@ -16,7 +16,7 @@ import Foundation -class PollBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { +class PollBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { private var pollView: UIView? private var event: MXEvent? diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift index ebecb1ad1..76f4037e2 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift @@ -16,7 +16,7 @@ import Foundation -class VoiceMessageBubbleCell: SizableBaseBubbleCell, BubbleCellReactionsDisplayable { +class VoiceMessageBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { private(set) var playbackController: VoiceMessagePlaybackController! diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift index a4e4bb8ae..11951db56 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift @@ -76,7 +76,7 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cell.addTemporarySubview(reactionsView) - if let reactionsDisplayable = cell as? BubbleCellReactionsDisplayable { + if let reactionsDisplayable = cell as? RoomCellReactionsDisplayable { reactionsDisplayable.addReactionsView(reactionsView) } else { reactionsView.translatesAutoresizingMaskIntoConstraints = false From 2837acfc0a46a26e1d9e4ab99cd0986bd888e5db Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:43:21 +0100 Subject: [PATCH 086/188] Rename BubbleCellReadReceiptsDisplayable to RoomCellReadReceiptsDisplayable. --- .../Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift | 2 +- .../Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift | 2 +- ...isplayable.swift => RoomCellReadReceiptsDisplayable.swift} | 4 ++-- .../TimelineCells/Call/CallBubbleCellBaseContentView.swift | 2 +- .../Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift | 2 +- .../KeyVerification/KeyVerificationBaseBubbleCell.swift | 2 +- .../Room/TimelineCells/SizableCell/SizableBubbleCell.swift | 2 +- .../Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift | 2 +- .../Styles/Plain/PlainRoomTimelineCellDecorator.swift | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) rename Riot/Modules/Room/TimelineCells/BaseRoomCell/{BubbleCellReadReceiptsDisplayable.swift => RoomCellReadReceiptsDisplayable.swift} (80%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index 24f6a81b6..f6171b403 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -144,7 +144,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { // MARK: - Public func removeDecorationViews() { - if let bubbleCellReadReceiptsDisplayable = self as? BubbleCellReadReceiptsDisplayable { + if let bubbleCellReadReceiptsDisplayable = self as? RoomCellReadReceiptsDisplayable { bubbleCellReadReceiptsDisplayable.removeReadReceiptsView() } diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index 7d8b6ffe8..ce0d7ad0d 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -172,7 +172,7 @@ final class RoomCellContentView: UIView, NibLoadable { } // MARK: - BubbleCellReadReceiptsDisplayable -extension RoomCellContentView: BubbleCellReadReceiptsDisplayable { +extension RoomCellContentView: RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { self.readReceiptsContentView.vc_removeAllSubviews() diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReadReceiptsDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadReceiptsDisplayable.swift similarity index 80% rename from Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReadReceiptsDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadReceiptsDisplayable.swift index 4184944fd..6e443832a 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellReadReceiptsDisplayable.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadReceiptsDisplayable.swift @@ -16,8 +16,8 @@ import Foundation -/// `BubbleCellReadReceiptsDisplayable` is a protocol indicating that a cell support displaying read receipts. -@objc protocol BubbleCellReadReceiptsDisplayable { +/// `RoomCellReadReceiptsDisplayable` is a protocol indicating that a cell support displaying read receipts. +@objc protocol RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) func removeReadReceiptsView() } diff --git a/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift b/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift index 5fbf6e51d..f17c652ea 100644 --- a/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift +++ b/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift @@ -114,7 +114,7 @@ extension CallBubbleCellBaseContentView: Themable { // MARK: - BubbleCellReadReceiptsDisplayable -extension CallBubbleCellBaseContentView: BubbleCellReadReceiptsDisplayable { +extension CallBubbleCellBaseContentView: RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { self.readReceiptsContentView.vc_removeAllSubviews() diff --git a/Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift index d760d83bd..b7efc965b 100644 --- a/Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Call/RoomBaseCallBubbleCell.swift @@ -144,7 +144,7 @@ class RoomBaseCallBubbleCell: MXKRoomBubbleTableViewCell { } -extension RoomBaseCallBubbleCell: BubbleCellReadReceiptsDisplayable { +extension RoomBaseCallBubbleCell: RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { innerContentView.addReadReceiptsView(readReceiptsView) diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift index ac2d528b5..8f50ffd85 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift @@ -249,7 +249,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { } // MARK: - BubbleCellReadReceiptsDisplayable -extension KeyVerificationBaseBubbleCell: BubbleCellReadReceiptsDisplayable { +extension KeyVerificationBaseBubbleCell: RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { self.roomCellContentView?.addReadReceiptsView(readReceiptsView) diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift index 46f1c9fc2..19a07c57c 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift @@ -119,7 +119,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { var height = sizingView.systemLayoutSizeFitting(fittingSize).height // Add read receipt height if needed - if let roomBubbleCellData = cellData as? RoomBubbleCellData, let readReceipts = roomBubbleCellData.readReceipts, readReceipts.count > 0, sizingView is BubbleCellReadReceiptsDisplayable { + if let roomBubbleCellData = cellData as? RoomBubbleCellData, let readReceipts = roomBubbleCellData.readReceipts, readReceipts.count > 0, sizingView is RoomCellReadReceiptsDisplayable { height+=RoomBubbleCellLayout.readReceiptsViewHeight } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 5fc4de018..4fe5d2ed6 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -16,7 +16,7 @@ import UIKit -class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, BubbleCellThreadSummaryDisplayable, BubbleCellReadReceiptsDisplayable { +class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, BubbleCellThreadSummaryDisplayable, RoomCellReadReceiptsDisplayable { // MARK: - Properties diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift index 11951db56..9e7008a14 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift @@ -118,7 +118,7 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cell.addTemporarySubview(readReceiptsView) - if let readReceiptsDisplayable = cell as? BubbleCellReadReceiptsDisplayable { + if let readReceiptsDisplayable = cell as? RoomCellReadReceiptsDisplayable { readReceiptsDisplayable.addReadReceiptsView(readReceiptsView) } else { From d078e10a7d703b5b2e95cde19e16b8f078953f86 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:44:11 +0100 Subject: [PATCH 087/188] Rename BubbleCellThreadSummaryDisplayable to RoomCellThreadSummaryDisplayable. --- .../Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift | 2 +- .../Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift | 2 +- ...splayable.swift => RoomCellThreadSummaryDisplayable.swift} | 4 ++-- .../Room/TimelineCells/SizableCell/SizableBubbleCell.swift | 2 +- .../Styles/Bubble/BubbleRoomTimelineCellDecorator.swift | 2 +- .../Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift | 2 +- .../Styles/Plain/Cells/Poll/PollBubbleCell.swift | 2 +- .../Styles/Plain/PlainRoomTimelineCellDecorator.swift | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) rename Riot/Modules/Room/TimelineCells/BaseRoomCell/{BubbleCellThreadSummaryDisplayable.swift => RoomCellThreadSummaryDisplayable.swift} (81%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index f6171b403..0513a5e01 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -152,7 +152,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { bubbleCellReactionsDisplayable.removeReactionsView() } - if let bubbleCellThreadSummaryDisplayable = self as? BubbleCellThreadSummaryDisplayable { + if let bubbleCellThreadSummaryDisplayable = self as? RoomCellThreadSummaryDisplayable { bubbleCellThreadSummaryDisplayable.removeThreadSummaryView() } diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index ce0d7ad0d..12db2bd5e 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -219,7 +219,7 @@ extension RoomCellContentView: RoomCellReactionsDisplayable { } // MARK: - BubbleCellThreadSummaryDisplayable -extension RoomCellContentView: BubbleCellThreadSummaryDisplayable { +extension RoomCellContentView: RoomCellThreadSummaryDisplayable { func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellThreadSummaryDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellThreadSummaryDisplayable.swift similarity index 81% rename from Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellThreadSummaryDisplayable.swift rename to Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellThreadSummaryDisplayable.swift index 6c2848e27..c84416050 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BubbleCellThreadSummaryDisplayable.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellThreadSummaryDisplayable.swift @@ -16,8 +16,8 @@ import Foundation -/// `BubbleCellThreadSummaryDisplayable` is a protocol indicating that a cell support displaying a thread summary. -@objc protocol BubbleCellThreadSummaryDisplayable { +/// `RoomCellThreadSummaryDisplayable` is a protocol indicating that a cell support displaying a thread summary. +@objc protocol RoomCellThreadSummaryDisplayable { func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) func removeThreadSummaryView() } diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift index 19a07c57c..02c790171 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift @@ -135,7 +135,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { } // Add thread summary view height if needed - if sizingView is BubbleCellThreadSummaryDisplayable, + if sizingView is RoomCellThreadSummaryDisplayable, let roomBubbleCellData = cellData as? RoomBubbleCellData, roomBubbleCellData.hasThreadRoot { diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift index 51d4e324c..3c3cb45e0 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift @@ -210,7 +210,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { contentViewPositionY: CGFloat, upperDecorationView: UIView?) { - if let threadSummaryDisplayable = cell as? BubbleCellThreadSummaryDisplayable { + if let threadSummaryDisplayable = cell as? RoomCellThreadSummaryDisplayable { threadSummaryDisplayable.addThreadSummaryView(threadSummaryView) } else { diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 4fe5d2ed6..96ef294bc 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -16,7 +16,7 @@ import UIKit -class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, BubbleCellThreadSummaryDisplayable, RoomCellReadReceiptsDisplayable { +class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, RoomCellThreadSummaryDisplayable, RoomCellReadReceiptsDisplayable { // MARK: - Properties diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift index dfa193cb6..1adb96dda 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift @@ -62,4 +62,4 @@ class PollBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { } } -extension PollBubbleCell: BubbleCellThreadSummaryDisplayable {} +extension PollBubbleCell: RoomCellThreadSummaryDisplayable {} diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift index 9e7008a14..118b7cc2b 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift @@ -159,7 +159,7 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cell.addTemporarySubview(threadSummaryView) - if let threadSummaryDisplayable = cell as? BubbleCellThreadSummaryDisplayable { + if let threadSummaryDisplayable = cell as? RoomCellThreadSummaryDisplayable { threadSummaryDisplayable.addThreadSummaryView(threadSummaryView) } else { threadSummaryView.translatesAutoresizingMaskIntoConstraints = false From 756b6d496063b78924d6d184b5ea4c6786aae720 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:48:08 +0100 Subject: [PATCH 088/188] BaseRoomCell make some rename. --- .../BaseRoomCell/BaseRoomCell.swift | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index 0513a5e01..a26bcb1b7 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -144,16 +144,16 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { // MARK: - Public func removeDecorationViews() { - if let bubbleCellReadReceiptsDisplayable = self as? RoomCellReadReceiptsDisplayable { - bubbleCellReadReceiptsDisplayable.removeReadReceiptsView() + if let roomCellReadReceiptsDisplayable = self as? RoomCellReadReceiptsDisplayable { + roomCellReadReceiptsDisplayable.removeReadReceiptsView() } - if let bubbleCellReactionsDisplayable = self as? RoomCellReactionsDisplayable { - bubbleCellReactionsDisplayable.removeReactionsView() + if let roomCellReactionsDisplayable = self as? RoomCellReactionsDisplayable { + roomCellReactionsDisplayable.removeReactionsView() } - if let bubbleCellThreadSummaryDisplayable = self as? RoomCellThreadSummaryDisplayable { - bubbleCellThreadSummaryDisplayable.removeThreadSummaryView() + if let roomCellThreadSummaryDisplayable = self as? RoomCellThreadSummaryDisplayable { + roomCellThreadSummaryDisplayable.removeThreadSummaryView() } if let timestampDisplayable = self as? TimestampDisplayable { @@ -246,7 +246,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { } // MARK: - RoomCellURLPreviewDisplayable - // Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReadReceiptsDisplayable method below will be used + // Cannot use default implementation with ObjC protocol, if self conforms to RoomCellURLPreviewDisplayable method below will be used func addURLPreviewView(_ urlPreviewView: UIView) { self.roomCellContentView?.addURLPreviewView(urlPreviewView) @@ -259,8 +259,8 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { self.roomCellContentView?.removeURLPreviewView() } - // MARK: - BubbleCellReadReceiptsDisplayable - // Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReadReceiptsDisplayable method below will be used + // MARK: - RoomCellReadReceiptsDisplayable + // Cannot use default implementation with ObjC protocol, if self conforms to RoomCellReadReceiptsDisplayable method below will be used func addReadReceiptsView(_ readReceiptsView: UIView) { self.roomCellContentView?.addReadReceiptsView(readReceiptsView) @@ -273,8 +273,8 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { self.roomCellContentView?.removeReadReceiptsView() } - // MARK: - BubbleCellReactionsDisplayable - // Cannot use default implementation with ObjC protocol, if self conforms to BubbleCellReactionsDisplayable method below will be used + // MARK: - RoomCellReactionsDisplayable + // Cannot use default implementation with ObjC protocol, if self conforms to RoomCellReactionsDisplayable method below will be used func addReactionsView(_ reactionsView: UIView) { self.roomCellContentView?.addReactionsView(reactionsView) @@ -287,7 +287,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { self.roomCellContentView?.removeReactionsView() } - // MARK: - BubbleCellThreadSummaryDisplayable + // MARK: - RoomCellThreadSummaryDisplayable func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { self.roomCellContentView?.addThreadSummaryView(threadSummaryView) From 53a088383bf202cbae7babe7e173ba9fd4d0a0a8 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:51:06 +0100 Subject: [PATCH 089/188] Rename RoomBubbleCellLayout to PlainRoomCellLayoutConstants. --- .../BaseRoomCell/RoomCellContentView.swift | 2 +- .../KeyVerificationBaseBubbleCell.swift | 2 +- .../SizableCell/SizableBubbleCell.swift | 4 +-- .../Bubble/BubbleRoomCellLayoutUpdater.swift | 2 +- .../BubbleRoomTimelineCellDecorator.swift | 16 +++++----- ...ift => PlainRoomCellLayoutConstants.swift} | 4 +-- .../PlainRoomTimelineCellDecorator.swift | 30 +++++++++---------- .../Threads/Summary/ThreadSummaryView.swift | 4 +-- 8 files changed, 32 insertions(+), 32 deletions(-) rename Riot/Modules/Room/TimelineCells/Styles/Plain/{RoomBubbleCellLayout.swift => PlainRoomCellLayoutConstants.swift} (94%) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index 12db2bd5e..4420bec45 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -246,7 +246,7 @@ extension RoomCellContentView: RoomCellThreadSummaryDisplayable { NSLayoutConstraint.activate([ leadingConstraint, threadSummaryView.topAnchor.constraint(equalTo: containerView.topAnchor), - threadSummaryView.heightAnchor.constraint(equalToConstant: RoomBubbleCellLayout.threadSummaryViewHeight), + threadSummaryView.heightAnchor.constraint(equalToConstant: PlainRoomCellLayoutConstants.threadSummaryViewHeight), threadSummaryView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), trailingConstraint ]) diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift index 8f50ffd85..af1014bea 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift @@ -241,7 +241,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { var height = sizingView.systemLayoutSizeFitting(fittingSize).height if let roomBubbleCellData = cellData as? RoomBubbleCellData, let readReceipts = roomBubbleCellData.readReceipts, readReceipts.count > 0 { - height+=RoomBubbleCellLayout.readReceiptsViewHeight + height+=PlainRoomCellLayoutConstants.readReceiptsViewHeight } return height diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift index 02c790171..cb8831b25 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift @@ -120,7 +120,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { // Add read receipt height if needed if let roomBubbleCellData = cellData as? RoomBubbleCellData, let readReceipts = roomBubbleCellData.readReceipts, readReceipts.count > 0, sizingView is RoomCellReadReceiptsDisplayable { - height+=RoomBubbleCellLayout.readReceiptsViewHeight + height+=PlainRoomCellLayoutConstants.readReceiptsViewHeight } // Add reactions view height if needed @@ -141,7 +141,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { let bottomMargin = sizingView.roomCellContentView?.threadSummaryContentViewBottomConstraint.constant ?? 0 - height += RoomBubbleCellLayout.threadSummaryViewHeight + height += PlainRoomCellLayoutConstants.threadSummaryViewHeight height += bottomMargin } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift index f619471f7..32bced0bf 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift @@ -183,7 +183,7 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { let messageViewMarginTop: CGFloat = 0 let messageViewMarginBottom: CGFloat = 0 let messageViewMarginLeft = - BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + RoomBubbleCellLayout.innerContentViewMargins.left + BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + PlainRoomCellLayoutConstants.innerContentViewMargins.left let messageViewMarginRight = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.right let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift index 3c3cb45e0..f3d80259f 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomTimelineCellDecorator.swift @@ -106,7 +106,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { cellContentView.addSubview(reactionsView) - let topMargin: CGFloat = RoomBubbleCellLayout.reactionsViewTopMargin + let topMargin: CGFloat = PlainRoomCellLayoutConstants.reactionsViewTopMargin let leftMargin: CGFloat let rightMargin: CGFloat @@ -116,7 +116,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { var incomingLeftMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left if cellData.containsBubbleComponentWithEncryptionBadge { - incomingLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + incomingLeftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } leftMargin = incomingLeftMargin @@ -131,7 +131,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { var outgoingLeftMargin = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left if cellData.containsBubbleComponentWithEncryptionBadge { - outgoingLeftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + outgoingLeftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } leftMargin = outgoingLeftMargin @@ -180,9 +180,9 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { // Incoming message if cellData.isIncoming { - var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + var leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin if cellData.containsBubbleComponentWithEncryptionBadge { - leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + leftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } leadingOrTrailingConstraint = urlPreviewView.leadingAnchor.constraint(equalTo: cellContentView.leadingAnchor, constant: leftMargin) @@ -194,7 +194,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { leadingOrTrailingConstraint = urlPreviewView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -rightMargin) } - let topMargin = contentViewPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin + let topMargin = contentViewPositionY + PlainRoomCellLayoutConstants.urlPreviewViewTopMargin + PlainRoomCellLayoutConstants.reactionsViewTopMargin // Set the preview view's origin NSLayoutConstraint.activate([ @@ -232,7 +232,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { leftMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left if cellData.containsBubbleComponentWithEncryptionBadge { - leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + leftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } rightMargin = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.right @@ -253,7 +253,7 @@ class BubbleRoomTimelineCellDecorator: PlainRoomTimelineCellDecorator { constant: -rightMargin) } - let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin + let topMargin = PlainRoomCellLayoutConstants.threadSummaryViewTopMargin let height = ThreadSummaryView.contentViewHeight(forThread: threadSummaryView.thread, fitting: cellData.maxTextViewWidth) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/RoomBubbleCellLayout.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomCellLayoutConstants.swift similarity index 94% rename from Riot/Modules/Room/TimelineCells/Styles/Plain/RoomBubbleCellLayout.swift rename to Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomCellLayoutConstants.swift index 46ba7e618..7ae41d8ac 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/RoomBubbleCellLayout.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomCellLayoutConstants.swift @@ -16,9 +16,9 @@ import Foundation -/// MXKRoomBubbleTableViewCell layout constants +/// Plain room cells layout constants @objcMembers -final class RoomBubbleCellLayout: NSObject { +final class PlainRoomCellLayoutConstants: NSObject { /// Inner content view margins static let innerContentViewMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 57, bottom: 0.0, right: 0) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift index 118b7cc2b..509e44870 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift @@ -54,12 +54,12 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { urlPreviewView.availableWidth = cellData.maxTextViewWidth cellContentView.addSubview(urlPreviewView) - var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + var leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin if cellData.containsBubbleComponentWithEncryptionBadge { - leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + leftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } - let topMargin = contentViewPositionY + RoomBubbleCellLayout.urlPreviewViewTopMargin + RoomBubbleCellLayout.reactionsViewTopMargin + let topMargin = contentViewPositionY + PlainRoomCellLayoutConstants.urlPreviewViewTopMargin + PlainRoomCellLayoutConstants.reactionsViewTopMargin // Set the preview view's origin NSLayoutConstraint.activate([ @@ -85,14 +85,14 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cellContentView.addSubview(reactionsView) - var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + var leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin if cellData.containsBubbleComponentWithEncryptionBadge { - leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + leftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } - let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin - let topMargin = RoomBubbleCellLayout.reactionsViewTopMargin + let rightMargin = PlainRoomCellLayoutConstants.reactionsViewRightMargin + let topMargin = PlainRoomCellLayoutConstants.reactionsViewTopMargin // The top constraint may need to include the URL preview view let topConstraint: NSLayoutConstraint @@ -127,13 +127,13 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cellContentView.addSubview(readReceiptsView) // Force receipts container size - let widthConstraint = readReceiptsView.widthAnchor.constraint(equalToConstant: RoomBubbleCellLayout.readReceiptsViewWidth) - let heightConstraint = readReceiptsView.heightAnchor.constraint(equalToConstant: RoomBubbleCellLayout.readReceiptsViewHeight) + let widthConstraint = readReceiptsView.widthAnchor.constraint(equalToConstant: PlainRoomCellLayoutConstants.readReceiptsViewWidth) + let heightConstraint = readReceiptsView.heightAnchor.constraint(equalToConstant: PlainRoomCellLayoutConstants.readReceiptsViewHeight) // Force receipts container position - let trailingConstraint = readReceiptsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -RoomBubbleCellLayout.readReceiptsViewRightMargin) + let trailingConstraint = readReceiptsView.trailingAnchor.constraint(equalTo: cellContentView.trailingAnchor, constant: -PlainRoomCellLayoutConstants.readReceiptsViewRightMargin) - let topMargin = RoomBubbleCellLayout.readReceiptsViewTopMargin + let topMargin = PlainRoomCellLayoutConstants.readReceiptsViewTopMargin let topConstraint: NSLayoutConstraint if let upperDecorationView = upperDecorationView { @@ -168,14 +168,14 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { cellContentView.addSubview(threadSummaryView) - var leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin + var leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin if cellData.containsBubbleComponentWithEncryptionBadge { - leftMargin += RoomBubbleCellLayout.encryptedContentLeftMargin + leftMargin += PlainRoomCellLayoutConstants.encryptedContentLeftMargin } - let rightMargin = RoomBubbleCellLayout.reactionsViewRightMargin - let topMargin = RoomBubbleCellLayout.threadSummaryViewTopMargin + let rightMargin = PlainRoomCellLayoutConstants.reactionsViewRightMargin + let topMargin = PlainRoomCellLayoutConstants.threadSummaryViewTopMargin let height = ThreadSummaryView.contentViewHeight(forThread: threadSummaryView.thread, fitting: cellData.maxTextViewWidth) diff --git a/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift index c1da2d9dd..40714866a 100644 --- a/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift +++ b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift @@ -52,7 +52,7 @@ class ThreadSummaryView: UIView { self.thread = thread super.init(frame: CGRect(origin: .zero, size: CGSize(width: Constants.viewDefaultWidth, - height: RoomBubbleCellLayout.threadSummaryViewHeight))) + height: PlainRoomCellLayoutConstants.threadSummaryViewHeight))) loadNibContent() update(theme: ThemeService.shared().theme) configure() @@ -60,7 +60,7 @@ class ThreadSummaryView: UIView { } static func contentViewHeight(forThread thread: MXThread?, fitting maxWidth: CGFloat) -> CGFloat { - return RoomBubbleCellLayout.threadSummaryViewHeight + return PlainRoomCellLayoutConstants.threadSummaryViewHeight } required init?(coder: NSCoder) { From 6276e6de889cb852d9883367eabf614f17a0e6c2 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 10:56:52 +0100 Subject: [PATCH 090/188] Rename RoomBubbleCellLayout to PlainRoomCellLayoutConstants. --- .../Categories/MXKRoomBubbleTableViewCell+Riot.m | 16 ++++++++-------- .../DataSources/HomeMessagesSearchDataSource.m | 12 ++++++------ Riot/Modules/Room/CellData/RoomBubbleCellData.m | 10 +++++----- Riot/Modules/Room/DataSources/RoomDataSource.m | 8 ++++---- .../Search/DataSources/RoomSearchDataSource.m | 12 ++++++------ 5 files changed, 29 insertions(+), 29 deletions(-) diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 98fde6a11..0f4e2fd9d 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -106,7 +106,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = CGFloat timeLabelPosX; CGFloat timeLabelPosY; - CGFloat timeLabelHeight = RoomBubbleCellLayout.timestampLabelHeight; + CGFloat timeLabelHeight = PlainRoomCellLayoutConstants.timestampLabelHeight; CGFloat timeLabelWidth; NSTextAlignment timeLabelTextAlignment; @@ -133,7 +133,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = } else { - timeLabelPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth; + timeLabelPosX = self.bubbleInfoContainer.frame.size.width - PlainRoomCellLayoutConstants.timestampLabelWidth; if (isFirstDisplayedComponent) { @@ -148,7 +148,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = timeLabelPosY = component.position.y + self.msgTextViewTopConstraint.constant - timeLabelHeight - self.bubbleInfoContainerTopConstraint.constant; } - timeLabelWidth = RoomBubbleCellLayout.timestampLabelWidth; + timeLabelWidth = PlainRoomCellLayoutConstants.timestampLabelWidth; timeLabelTextAlignment = NSTextAlignmentRight; } @@ -340,7 +340,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = NSDate *date = bubbleData.date; if (date) { - UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.bubbleInfoContainer.frame.size.width, RoomBubbleCellLayout.timestampLabelHeight)]; + UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.bubbleInfoContainer.frame.size.width, PlainRoomCellLayoutConstants.timestampLabelHeight)]; timeLabel.text = [bubbleData.eventFormatter dateStringFromDate:date withTime:NO]; timeLabel.textAlignment = NSTextAlignmentRight; @@ -387,7 +387,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:RoomBubbleCellLayout.timestampLabelHeight]; + constant:PlainRoomCellLayoutConstants.timestampLabelHeight]; // Available on iOS 8 and later [NSLayoutConstraint activateConstraints:@[rightConstraint, topConstraint, widthConstraint, heightConstraint]]; @@ -539,7 +539,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = CGFloat componentBottomY = componentFrameInContentView.origin.y + componentFrameInContentView.size.height; CGFloat x = 0; - CGFloat y = componentFrameInContentView.origin.y - RoomBubbleCellLayout.timestampLabelHeight; + CGFloat y = componentFrameInContentView.origin.y - PlainRoomCellLayoutConstants.timestampLabelHeight; CGFloat width = roomBubbleTableViewCell.contentView.frame.size.width; CGFloat height = componentBottomY - y; @@ -798,7 +798,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = { CGRect componentFrame = [self componentFrameInContentViewForIndex: index]; - tickView.frame = CGRectMake(self.contentView.bounds.size.width - tickView.frame.size.width - 2 * RoomBubbleCellLayout.readReceiptsViewRightMargin, CGRectGetMaxY(componentFrame) - tickView.frame.size.height, tickView.frame.size.width, tickView.frame.size.height); + tickView.frame = CGRectMake(self.contentView.bounds.size.width - tickView.frame.size.width - 2 * PlainRoomCellLayoutConstants.readReceiptsViewRightMargin, CGRectGetMaxY(componentFrame) - tickView.frame.size.height, tickView.frame.size.width, tickView.frame.size.height); [self.contentView addSubview:tickView]; } @@ -816,7 +816,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = // Define 'Edit' button frame UIImage *editIcon = [UIImage imageNamed:@"edit_icon"]; - CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth - 22 - editIcon.size.width / 2; + CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - PlainRoomCellLayoutConstants.timestampLabelWidth - 22 - editIcon.size.width / 2; CGFloat editBtnPosY = isFirstDisplayedComponent ? -13 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13; UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(editBtnPosX, editBtnPosY, 44, 44)]; diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 14a736b36..b5d9ccdf6 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -171,7 +171,7 @@ threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; [bubbleCell.contentView addSubview:threadSummaryView]; - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin; CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; @@ -182,9 +182,9 @@ [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor constant:leftMargin], [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + constant:bottomPositionY + PlainRoomCellLayoutConstants.threadSummaryViewTopMargin], [threadSummaryView.heightAnchor constraintEqualToConstant:height], - [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-PlainRoomCellLayoutConstants.reactionsViewRightMargin] ]]; } else if (event.isInThread) @@ -195,7 +195,7 @@ fromAThreadView.translatesAutoresizingMaskIntoConstraints = NO; [bubbleCell.contentView addSubview:fromAThreadView]; - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin; CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; @@ -206,9 +206,9 @@ [fromAThreadView.leadingAnchor constraintEqualToAnchor:fromAThreadView.superview.leadingAnchor constant:leftMargin], [fromAThreadView.topAnchor constraintEqualToAnchor:fromAThreadView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.fromAThreadViewTopMargin], + constant:bottomPositionY + PlainRoomCellLayoutConstants.fromAThreadViewTopMargin], [fromAThreadView.heightAnchor constraintEqualToConstant:height], - [fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + [fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-PlainRoomCellLayoutConstants.reactionsViewRightMargin] ]]; } } diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 3ba7dab34..085bc137d 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -701,7 +701,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat // component is not a thread root return 0; } - return RoomBubbleCellLayout.threadSummaryViewTopMargin + + return PlainRoomCellLayoutConstants.threadSummaryViewTopMargin + [ThreadSummaryView contentViewHeightForThread:component.thread fitting:self.maxTextViewWidth]; } @@ -728,7 +728,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat // event is not in a thread return 0; } - return RoomBubbleCellLayout.fromAThreadViewTopMargin + + return PlainRoomCellLayoutConstants.fromAThreadViewTopMargin + [FromAThreadView contentViewHeightForEvent:component.event fitting:self.maxTextViewWidth]; } @@ -740,7 +740,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat return 0; } - return RoomBubbleCellLayout.urlPreviewViewTopMargin + [URLPreviewView contentViewHeightFor:component.urlPreviewData + return PlainRoomCellLayoutConstants.urlPreviewViewTopMargin + [URLPreviewView contentViewHeightFor:component.urlPreviewData fitting:self.maxTextViewWidth]; } @@ -765,7 +765,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat BOOL showAllReactions = [self.eventsToShowAllReactions containsObject:eventId]; BubbleReactionsViewModel *viewModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId showAll:showAllReactions]; - height = [bubbleReactionsViewSizer heightForViewModel:viewModel fittingWidth:bubbleReactionsViewWidth] + RoomBubbleCellLayout.reactionsViewTopMargin; + height = [bubbleReactionsViewSizer heightForViewModel:viewModel fittingWidth:bubbleReactionsViewWidth] + PlainRoomCellLayoutConstants.reactionsViewTopMargin; } return height; @@ -777,7 +777,7 @@ NSString *const URLPreviewDidUpdateNotification = @"URLPreviewDidUpdateNotificat if (self.readReceipts[eventId].count) { - height = RoomBubbleCellLayout.readReceiptsViewHeight + RoomBubbleCellLayout.readReceiptsViewTopMargin; + height = PlainRoomCellLayoutConstants.readReceiptsViewHeight + PlainRoomCellLayoutConstants.readReceiptsViewTopMargin; } return height; diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index f4561638f..7dabecf90 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -512,7 +512,7 @@ const CGFloat kTypingCellHeight = 24; if (roomMembers.count) { // Define the read receipts container, positioned on the right border of the bubble cell (Note the right margin 6 pts). - avatarsContainer = [[MXKReceiptSendersContainer alloc] initWithFrame:CGRectMake(bubbleCell.frame.size.width - RoomBubbleCellLayout.readReceiptsViewWidth + RoomBubbleCellLayout.readReceiptsViewRightMargin, bottomPositionY + RoomBubbleCellLayout.readReceiptsViewTopMargin, RoomBubbleCellLayout.readReceiptsViewWidth, RoomBubbleCellLayout.readReceiptsViewHeight) andMediaManager:self.mxSession.mediaManager]; + avatarsContainer = [[MXKReceiptSendersContainer alloc] initWithFrame:CGRectMake(bubbleCell.frame.size.width - PlainRoomCellLayoutConstants.readReceiptsViewWidth + PlainRoomCellLayoutConstants.readReceiptsViewRightMargin, bottomPositionY + PlainRoomCellLayoutConstants.readReceiptsViewTopMargin, PlainRoomCellLayoutConstants.readReceiptsViewWidth, PlainRoomCellLayoutConstants.readReceiptsViewHeight) andMediaManager:self.mxSession.mediaManager]; // Custom avatar display avatarsContainer.maxDisplayedAvatars = 5; @@ -557,7 +557,7 @@ const CGFloat kTypingCellHeight = 24; if ([componentEventId isEqualToString:self.room.accountData.readMarkerEventId]) { - bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - RoomBubbleCellLayout.readMarkerViewHeight, bubbleCell.bubbleOverlayContainer.frame.size.width, RoomBubbleCellLayout.readMarkerViewHeight)]; + bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - PlainRoomCellLayoutConstants.readMarkerViewHeight, bubbleCell.bubbleOverlayContainer.frame.size.width, PlainRoomCellLayoutConstants.readMarkerViewHeight)]; 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; @@ -574,7 +574,7 @@ const CGFloat kTypingCellHeight = 24; toItem:bubbleCell.bubbleOverlayContainer attribute:NSLayoutAttributeTop multiplier:1.0 - constant:bottomPositionY - RoomBubbleCellLayout.readMarkerViewHeight]; + constant:bottomPositionY - PlainRoomCellLayoutConstants.readMarkerViewHeight]; bubbleCell.readMarkerViewLeadingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual @@ -596,7 +596,7 @@ const CGFloat kTypingCellHeight = 24; toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 - constant:RoomBubbleCellLayout.readMarkerViewHeight]; + constant:PlainRoomCellLayoutConstants.readMarkerViewHeight]; [NSLayoutConstraint activateConstraints:@[bubbleCell.readMarkerViewTopConstraint, bubbleCell.readMarkerViewLeadingConstraint, bubbleCell.readMarkerViewTrailingConstraint, bubbleCell.readMarkerViewHeightConstraint]]; } diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 5b99eea2d..dcdb258dd 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -150,7 +150,7 @@ threadSummaryView.translatesAutoresizingMaskIntoConstraints = NO; [bubbleCell.contentView addSubview:threadSummaryView]; - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin; CGFloat height = [ThreadSummaryView contentViewHeightForThread:thread fitting:cellData.maxTextViewWidth]; CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; @@ -161,9 +161,9 @@ [threadSummaryView.leadingAnchor constraintEqualToAnchor:threadSummaryView.superview.leadingAnchor constant:leftMargin], [threadSummaryView.topAnchor constraintEqualToAnchor:threadSummaryView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.threadSummaryViewTopMargin], + constant:bottomPositionY + PlainRoomCellLayoutConstants.threadSummaryViewTopMargin], [threadSummaryView.heightAnchor constraintEqualToConstant:height], - [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + [threadSummaryView.trailingAnchor constraintLessThanOrEqualToAnchor:threadSummaryView.superview.trailingAnchor constant:-PlainRoomCellLayoutConstants.reactionsViewRightMargin] ]]; } else if (event.isInThread) @@ -174,7 +174,7 @@ fromAThreadView.translatesAutoresizingMaskIntoConstraints = NO; [bubbleCell.contentView addSubview:fromAThreadView]; - CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin; + CGFloat leftMargin = PlainRoomCellLayoutConstants.reactionsViewLeftMargin; CGFloat height = [FromAThreadView contentViewHeightForEvent:event fitting:cellData.maxTextViewWidth]; CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:0]; @@ -185,9 +185,9 @@ [fromAThreadView.leadingAnchor constraintEqualToAnchor:fromAThreadView.superview.leadingAnchor constant:leftMargin], [fromAThreadView.topAnchor constraintEqualToAnchor:fromAThreadView.superview.topAnchor - constant:bottomPositionY + RoomBubbleCellLayout.fromAThreadViewTopMargin], + constant:bottomPositionY + PlainRoomCellLayoutConstants.fromAThreadViewTopMargin], [fromAThreadView.heightAnchor constraintEqualToConstant:height], - [fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin] + [fromAThreadView.trailingAnchor constraintLessThanOrEqualToAnchor:fromAThreadView.superview.trailingAnchor constant:-PlainRoomCellLayoutConstants.reactionsViewRightMargin] ]]; } } From 0b3ba64c261b41bcb206d9b61d7820d5c29f90c0 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 11:00:23 +0100 Subject: [PATCH 091/188] Rename SizableBaseRoomCell to SizableBaseBubbleCell. --- ...ubbleCell.swift => SizableBaseRoomCell.swift} | 16 ++++++++-------- .../FileWithoutThumbnailBaseBubbleCell.swift | 2 +- .../Common/TextMessageBaseBubbleCell.swift | 2 +- .../Cells/Location/LocationBubbleCell.swift | 2 +- .../Styles/Plain/Cells/Poll/PollBubbleCell.swift | 2 +- .../VoiceMessage/VoiceMessageBubbleCell.swift | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) rename Riot/Modules/Room/TimelineCells/SizableCell/{SizableBubbleCell.swift => SizableBaseRoomCell.swift} (91%) diff --git a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBaseRoomCell.swift similarity index 91% rename from Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift rename to Riot/Modules/Room/TimelineCells/SizableCell/SizableBaseRoomCell.swift index cb8831b25..29f0bfd57 100644 --- a/Riot/Modules/Room/TimelineCells/SizableCell/SizableBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/SizableCell/SizableBaseRoomCell.swift @@ -17,18 +17,18 @@ import UIKit import MatrixSDK -@objc protocol SizableBaseBubbleCellType: BaseRoomCellProtocol { +@objc protocol SizableBaseRoomCellType: BaseRoomCellProtocol { static func sizingViewHeightHashValue(from bubbleCellData: MXKRoomBubbleCellData) -> Int } -/// `SizableBaseBubbleCell` allows a cell using Auto Layout that inherits from this class to automatically return the height of the cell and cache the result. +/// `SizableBaseRoomCell` allows a cell using Auto Layout that inherits from this class to automatically return the height of the cell and cache the result. @objcMembers -class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { +class SizableBaseRoomCell: BaseRoomCell, SizableBaseRoomCellType { // MARK: - Constants private static let sizingViewHeightStore = SizingViewHeightStore() - private static var sizingViews: [String: SizableBaseBubbleCell] = [:] + private static var sizingViews: [String: SizableBaseRoomCell] = [:] private static let sizingReactionsView = BubbleReactionsView() private static let reactionsViewSizer = BubbleReactionsViewSizer() @@ -36,8 +36,8 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { private static let urlPreviewViewSizer = URLPreviewViewSizer() - private class var sizingView: SizableBaseBubbleCell { - let sizingView: SizableBaseBubbleCell + private class var sizingView: SizableBaseRoomCell { + let sizingView: SizableBaseRoomCell let reuseIdentifier: String = self.defaultReuseIdentifier() @@ -64,7 +64,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { return self.height(for: roomBubbleCellData, fitting: maxWidth) } - // MARK - SizableBaseBubbleCellType + // MARK - SizableBaseRoomCellType // Each sublcass should override this method, to indicate a unique identifier for a view height. // This means that the value should change if there is some data that modify the cell height. @@ -77,7 +77,7 @@ class SizableBaseBubbleCell: BaseRoomCell, SizableBaseBubbleCellType { // MARK: - Private - class func createSizingView() -> SizableBaseBubbleCell { + class func createSizingView() -> SizableBaseRoomCell { return self.init(style: .default, reuseIdentifier: self.defaultReuseIdentifier()) } diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift index d2732155f..ef30632bd 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/FileWithoutThumbnail/Common/FileWithoutThumbnailBaseBubbleCell.swift @@ -16,7 +16,7 @@ import UIKit -class FileWithoutThumbnailBaseBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { +class FileWithoutThumbnailBaseBubbleCell: SizableBaseRoomCell, RoomCellReactionsDisplayable { weak var fileAttachementView: FileWithoutThumbnailCellContentView? diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 96ef294bc..86584f9aa 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -16,7 +16,7 @@ import UIKit -class TextMessageBaseBubbleCell: SizableBaseBubbleCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, RoomCellThreadSummaryDisplayable, RoomCellReadReceiptsDisplayable { +class TextMessageBaseBubbleCell: SizableBaseRoomCell, RoomCellURLPreviewDisplayable, RoomCellReactionsDisplayable, RoomCellThreadSummaryDisplayable, RoomCellReadReceiptsDisplayable { // MARK: - Properties diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift index 724ac8459..6f98714c0 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Location/LocationBubbleCell.swift @@ -16,7 +16,7 @@ import Foundation -class LocationBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { +class LocationBubbleCell: SizableBaseRoomCell, RoomCellReactionsDisplayable { private var locationView: RoomTimelineLocationView! diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift index 1adb96dda..e0d04ed09 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/Poll/PollBubbleCell.swift @@ -16,7 +16,7 @@ import Foundation -class PollBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { +class PollBubbleCell: SizableBaseRoomCell, RoomCellReactionsDisplayable { private var pollView: UIView? private var event: MXEvent? diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift index 76f4037e2..ba4484cb1 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/VoiceMessage/VoiceMessageBubbleCell.swift @@ -16,7 +16,7 @@ import Foundation -class VoiceMessageBubbleCell: SizableBaseBubbleCell, RoomCellReactionsDisplayable { +class VoiceMessageBubbleCell: SizableBaseRoomCell, RoomCellReactionsDisplayable { private(set) var playbackController: VoiceMessagePlaybackController! From 329e655071fad40f844808a116b5301584f56e32 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 16 Feb 2022 12:45:10 +0200 Subject: [PATCH 092/188] Prepare for new sprint --- Config/AppVersion.xcconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Config/AppVersion.xcconfig b/Config/AppVersion.xcconfig index 3fe634b3f..de6ddc959 100644 --- a/Config/AppVersion.xcconfig +++ b/Config/AppVersion.xcconfig @@ -15,5 +15,5 @@ // // Version -MARKETING_VERSION = 1.8.1 -CURRENT_PROJECT_VERSION = 1.8.1 +MARKETING_VERSION = 1.8.2 +CURRENT_PROJECT_VERSION = 1.8.2 From 5e432d32b4b36169c37e65621e09cee79cf8ad7c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 11:59:35 +0100 Subject: [PATCH 093/188] BubbleRoomCellLayoutUpdater: Fix outgoing message issue. --- .../BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift index f619471f7..eaea8739d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift +++ b/Riot/Modules/Room/Views/BubbleCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift @@ -183,7 +183,7 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { let messageViewMarginTop: CGFloat = 0 let messageViewMarginBottom: CGFloat = 0 let messageViewMarginLeft = - BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + RoomBubbleCellLayout.innerContentViewMargins.left + BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.left let messageViewMarginRight = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.right let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight) From 762f1055425b9c575d03018bda590eadfe4b6309 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 12:03:14 +0100 Subject: [PATCH 094/188] Add changes --- changelog.d/5409.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5409.misc diff --git a/changelog.d/5409.misc b/changelog.d/5409.misc new file mode 100644 index 000000000..6442410ad --- /dev/null +++ b/changelog.d/5409.misc @@ -0,0 +1 @@ +Message bubbles: Use layout constants instead magic numbers. \ No newline at end of file From 5ae2ae20ad21a595351033103970b53e615154bd Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 12:09:55 +0100 Subject: [PATCH 095/188] Fix several MARK comments. --- .../TimelineCells/BaseRoomCell/RoomCellContentView.swift | 6 +++--- .../TimelineCells/Call/CallBubbleCellBaseContentView.swift | 2 +- .../KeyVerification/KeyVerificationBaseBubbleCell.swift | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index 4420bec45..ad9cd3abb 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -171,7 +171,7 @@ final class RoomCellContentView: UIView, NibLoadable { } } -// MARK: - BubbleCellReadReceiptsDisplayable +// MARK: - RoomCellReadReceiptsDisplayable extension RoomCellContentView: RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { @@ -186,7 +186,7 @@ extension RoomCellContentView: RoomCellReadReceiptsDisplayable { } } -// MARK: - BubbleCellReactionsDisplayable +// MARK: - RoomCellReactionsDisplayable extension RoomCellContentView: RoomCellReactionsDisplayable { func addReactionsView(_ reactionsView: UIView) { @@ -218,7 +218,7 @@ extension RoomCellContentView: RoomCellReactionsDisplayable { } } -// MARK: - BubbleCellThreadSummaryDisplayable +// MARK: - RoomCellThreadSummaryDisplayable extension RoomCellContentView: RoomCellThreadSummaryDisplayable { func addThreadSummaryView(_ threadSummaryView: ThreadSummaryView) { diff --git a/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift b/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift index f17c652ea..e150ac729 100644 --- a/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift +++ b/Riot/Modules/Room/TimelineCells/Call/CallBubbleCellBaseContentView.swift @@ -112,7 +112,7 @@ extension CallBubbleCellBaseContentView: Themable { } -// MARK: - BubbleCellReadReceiptsDisplayable +// MARK: - RoomCellReadReceiptsDisplayable extension CallBubbleCellBaseContentView: RoomCellReadReceiptsDisplayable { diff --git a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift index af1014bea..81b3d851a 100644 --- a/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/KeyVerification/KeyVerificationBaseBubbleCell.swift @@ -248,7 +248,7 @@ class KeyVerificationBaseBubbleCell: MXKRoomBubbleTableViewCell { } } -// MARK: - BubbleCellReadReceiptsDisplayable +// MARK: - RoomCellReadReceiptsDisplayable extension KeyVerificationBaseBubbleCell: RoomCellReadReceiptsDisplayable { func addReadReceiptsView(_ readReceiptsView: UIView) { From b0ee449c5d3358dd6f9221845df50db53f7a2dbf Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Tue, 15 Feb 2022 15:47:46 +0000 Subject: [PATCH 096/188] Implement home screen activity indicators --- Config/BuildSettings.swift | 9 ++ Riot/Modules/Application/AppCoordinator.swift | 28 +++++- Riot/Modules/Application/AppNavigator.swift | 9 ++ Riot/Modules/Common/Activities/Activity.swift | 91 ------------------- .../Common/Activities/ActivityCenter.swift | 60 ------------ .../Common/Activities/ActivityDismissal.swift | 25 ----- .../Activities/ActivityPresentable.swift | 25 ----- .../Common/Activities/ActivityRequest.swift | 25 ----- .../AppActivityIndicatorPresenter.swift | 47 ++++++++++ .../GlobalActivityCenterPresenter.swift | 69 -------------- .../Common/Recents/RecentsViewController.h | 6 ++ .../Common/Recents/RecentsViewController.m | 18 ++-- .../ActivityIndicatorToastPresenter.swift | 32 ++++--- .../Toasts/ActivityIndicatorToastView.swift | 46 ++++++---- .../MatrixKit/Controllers/MXKViewController.h | 5 - .../MatrixKit/Controllers/MXKViewController.m | 15 ++- Riot/Modules/Room/MXKRoomViewController.m | 18 +--- Riot/Modules/TabBar/TabBarCoordinator.swift | 4 + changelog.d/4829.change | 2 +- 19 files changed, 168 insertions(+), 366 deletions(-) delete mode 100644 Riot/Modules/Common/Activities/Activity.swift delete mode 100644 Riot/Modules/Common/Activities/ActivityCenter.swift delete mode 100644 Riot/Modules/Common/Activities/ActivityDismissal.swift delete mode 100644 Riot/Modules/Common/Activities/ActivityPresentable.swift delete mode 100644 Riot/Modules/Common/Activities/ActivityRequest.swift create mode 100644 Riot/Modules/Common/ActivityIndicator/AppActivityIndicatorPresenter.swift delete mode 100644 Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 0996ce2ef..3eb9c33a6 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -210,6 +210,15 @@ final class BuildSettings: NSObject { static let allowInviteExernalUsers: Bool = true + /// Whether a screen uses legacy local activity indicators or improved app-wide indicators + static var appActivityIndicators: Bool { + #if DEBUG + return true + #else + return false + #endif + } + // MARK: - Side Menu static let enableSideMenu: Bool = true static let sideMenuShowInviteFriends: Bool = true diff --git a/Riot/Modules/Application/AppCoordinator.swift b/Riot/Modules/Application/AppCoordinator.swift index 95e6dde74..bdefe2dba 100755 --- a/Riot/Modules/Application/AppCoordinator.swift +++ b/Riot/Modules/Application/AppCoordinator.swift @@ -17,9 +17,11 @@ import Foundation import Intents import MatrixSDK +import CommonKit #if DEBUG import FLEX +import UIKit #endif /// The AppCoordinator is responsible of screen navigation and data injection at root application level. It decides @@ -47,7 +49,7 @@ final class AppCoordinator: NSObject, AppCoordinatorType { return AppNavigator(appCoordinator: self) }() - private weak var splitViewCoordinator: SplitViewCoordinatorType? + fileprivate weak var splitViewCoordinator: SplitViewCoordinatorType? fileprivate weak var sideMenuCoordinator: SideMenuCoordinatorType? private let userSessionsService: UserSessionsService @@ -296,6 +298,18 @@ fileprivate class AppNavigator: AppNavigatorProtocol { return SideMenuPresenter(sideMenuCoordinator: sideMenuCoordinator) }() + private var appNavigationVC: UINavigationController { + guard + let splitVC = appCoordinator.splitViewCoordinator?.toPresentable() as? UISplitViewController, + // Picking out the first view controller currently works only on iPhones, not iPads + let navigationVC = splitVC.viewControllers.first as? UINavigationController + else { + MXLog.error("[AppNavigator] Missing root split view controller") + return UINavigationController() + } + return navigationVC + } + // MARK: - Setup init(appCoordinator: AppCoordinator) { @@ -307,4 +321,16 @@ fileprivate class AppNavigator: AppNavigatorProtocol { func navigate(to destination: AppNavigatorDestination) { self.appCoordinator.navigate(to: destination) } + + func addLoadingActivity() -> Activity { + let presenter = ActivityIndicatorToastPresenter( + text: VectorL10n.roomParticipantsSecurityLoading, + navigationController: appNavigationVC + ) + let request = ActivityRequest( + presenter: presenter, + dismissal: .manual + ) + return ActivityCenter.shared.add(request) + } } diff --git a/Riot/Modules/Application/AppNavigator.swift b/Riot/Modules/Application/AppNavigator.swift index 16c95fb4f..c33b572f4 100644 --- a/Riot/Modules/Application/AppNavigator.swift +++ b/Riot/Modules/Application/AppNavigator.swift @@ -15,6 +15,7 @@ // import Foundation +import CommonKit /// AppNavigatorProtocol abstract a navigator at app level. /// It enables to perform the navigation within the global app scope (open the side menu, open a room and so on) @@ -26,4 +27,12 @@ protocol AppNavigatorProtocol { /// Navigate to a destination screen or a state /// Do not use protocol with associatedtype for the moment like presented here https://www.swiftbysundell.com/articles/navigation-in-swift/#where-to-navigator use a separate enum func navigate(to destination: AppNavigatorDestination) + + /// Add loading activity to an app-wide queue of other activitie + /// + /// If the queue is empty, the activity will be displayed immediately, otherwise it will be pending + /// until the previously added activities have completed / been cancelled. + /// + /// To remove an activity indicator, cancel or deallocate the returned `Activity` + func addLoadingActivity() -> Activity } diff --git a/Riot/Modules/Common/Activities/Activity.swift b/Riot/Modules/Common/Activities/Activity.swift deleted file mode 100644 index b7bc0d083..000000000 --- a/Riot/Modules/Common/Activities/Activity.swift +++ /dev/null @@ -1,91 +0,0 @@ -// -// Copyright 2021 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 - -/// An `Activity` represents a temporary visual indicator, such as activity indicator, success notification or an error message. -/// -/// More than one `Activity` may be requested by the system at the same time (e.g. global syncing vs local refresh), -/// and the `ActivityCenter` will ensure that only one activity is shown at a given time, putting the other in a pending queue. -/// -/// A client that requests an activity can specify a default timeout after which the activity is dismissed, or it has to be manually -/// responsible for dismissing it via `cancel` method, or by deallocating itself. -class Activity { - enum State { - case pending - case executing - case completed - } - - private let request: ActivityRequest - private let completion: () -> Void - - private(set) var state: State - - init(request: ActivityRequest, completion: @escaping () -> Void) { - self.request = request - self.completion = completion - - state = .pending - } - - deinit { - cancel() - } - - /// Start the activity - /// - /// Note: clients should not call this method manually if the activity is added into an `ActivityCenter` - func start() { - guard state == .pending else { - return - } - - state = .executing - request.presenter.present() - - switch request.dismissal { - case .manual: - break - case .timeout(let interval): - Timer.scheduledTimer(withTimeInterval: interval, repeats: false) { [weak self] _ in - self?.complete() - } - } - } - - - /// Cancel the activity, triggering any dismissal action / animation - /// - /// Note: clients can call this method directly, if they have access to the `Activity`. - /// Once cancelled, `ActivityCenter` will automatically start the next `Activity` in the queue. - func cancel() { - complete() - } - - private func complete() { - guard state != .completed else { - return - } - if state == .executing { - request.presenter.dismiss() - } - - state = .completed - completion() - } -} diff --git a/Riot/Modules/Common/Activities/ActivityCenter.swift b/Riot/Modules/Common/Activities/ActivityCenter.swift deleted file mode 100644 index f27d23e53..000000000 --- a/Riot/Modules/Common/Activities/ActivityCenter.swift +++ /dev/null @@ -1,60 +0,0 @@ -// -// Copyright 2021 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 - -/// A shared activity center with a single FIFO queue which will ensure only one activity is shown at a given time. -/// -/// `ActivityCenter` offers a `shared` center that can be used by any clients, but clients are also allowed -/// to create local `ActivityCenter` if the context requres multiple simultaneous activities. -class ActivityCenter { - private class Weak { - weak var element: T? - init(_ element: T) { - self.element = element - } - } - - static let shared = ActivityCenter() - private var queue = [Weak]() - - /// Add a new activity to the queue by providing a request. - /// - /// The queue will start the activity right away, if there are no currently running activities, - /// otherwise the activity will be put on hold. - func add(_ request: ActivityRequest) -> Activity { - let activity = Activity(request: request) { [weak self] in - self?.startNextIfIdle() - } - - queue.append(Weak(activity)) - startNextIfIdle() - return activity - } - - private func startNextIfIdle() { - cleanup() - if let activity = queue.first?.element, activity.state == .pending { - activity.start() - } - } - - private func cleanup() { - queue.removeAll { - $0.element == nil || $0.element?.state == .completed - } - } -} diff --git a/Riot/Modules/Common/Activities/ActivityDismissal.swift b/Riot/Modules/Common/Activities/ActivityDismissal.swift deleted file mode 100644 index dbb6cb83a..000000000 --- a/Riot/Modules/Common/Activities/ActivityDismissal.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2021 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 - -/// Different ways in which an `Activity` can be dismissed -enum ActivityDismissal { - /// The `Activity` will not manage the dismissal, but will expect the calling client to do so manually - case manual - /// The `Activity` will be automatically dismissed after `TimeInterval` - case timeout(TimeInterval) -} diff --git a/Riot/Modules/Common/Activities/ActivityPresentable.swift b/Riot/Modules/Common/Activities/ActivityPresentable.swift deleted file mode 100644 index b6e7b46df..000000000 --- a/Riot/Modules/Common/Activities/ActivityPresentable.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2021 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 - -/// A presenter associated with and called by an `Activity`, and responsible for the underlying view shown on the screen. -protocol ActivityPresentable { - /// Called when the `Activity` is started (manually or by the `ActivityCenter`) - func present() - /// Called when the `Activity` is manually cancelled or completed - func dismiss() -} diff --git a/Riot/Modules/Common/Activities/ActivityRequest.swift b/Riot/Modules/Common/Activities/ActivityRequest.swift deleted file mode 100644 index 872699758..000000000 --- a/Riot/Modules/Common/Activities/ActivityRequest.swift +++ /dev/null @@ -1,25 +0,0 @@ -// -// Copyright 2021 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 - -/// A request used to create an underlying `Activity`, allowing clients to only specify the visual aspects of an activity. -struct ActivityRequest { - /// Presenter which will manage the underlying view shown on screen - let presenter: ActivityPresentable - // A method in which the activity is eventually dismissed - let dismissal: ActivityDismissal -} diff --git a/Riot/Modules/Common/ActivityIndicator/AppActivityIndicatorPresenter.swift b/Riot/Modules/Common/ActivityIndicator/AppActivityIndicatorPresenter.swift new file mode 100644 index 000000000..53a5d2453 --- /dev/null +++ b/Riot/Modules/Common/ActivityIndicator/AppActivityIndicatorPresenter.swift @@ -0,0 +1,47 @@ +// +// Copyright 2021 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 +import MatrixSDK +import CommonKit + +/// Presenter which displays activity / loading indicators using app-wide `AppNavigator`, thus displaying them in a unified way, +/// and `ActivityCenter`/`Activity`, which ensures that only one activity is shown at a given time. +/// +/// Note: clients can skip using `AppActivityIndicatorPresenter` and instead coordiinate with `AppNavigatorProtocol` directly. +/// The presenter exists mostly as a transition for view controllers already using `ActivityIndicatorPresenterType` and / or view controllers +/// written in objective-c. +@objc final class AppActivityIndicatorPresenter: NSObject, ActivityIndicatorPresenterType { + private let appNavigator: AppNavigatorProtocol + private var activity: Activity? + + init(appNavigator: AppNavigatorProtocol) { + self.appNavigator = appNavigator + } + + @objc func presentActivityIndicator() { + activity = appNavigator.addLoadingActivity() + } + + @objc func removeCurrentActivityIndicator(animated: Bool, completion: (() -> Void)?) { + activity = nil + } + + func presentActivityIndicator(on view: UIView, animated: Bool, completion: (() -> Void)?) { + MXLog.error("[AppActivityIndicatorPresenter] Shared activity indicator does not support presenting from custom views") + } +} diff --git a/Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift b/Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift deleted file mode 100644 index b2c35e018..000000000 --- a/Riot/Modules/Common/ActivityIndicator/GlobalActivityCenterPresenter.swift +++ /dev/null @@ -1,69 +0,0 @@ -// -// Copyright 2021 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 -import MatrixSDK - -/// Activity indicator presenter which uses a shared `ActivityCenter` to coordinate different activity indicators, -/// and which uses the root navigation view controller to display the activities. -@objc final class GlobalActivityCenterPresenter: NSObject, ActivityIndicatorPresenterType { - private var loadingActivity: Activity? - - private var rootNavigationController: UINavigationController? { - guard - let delegate = UIApplication.shared.delegate as? AppDelegate, - let rootVC = delegate.window?.rootViewController - else { - MXLog.error("[ActivityIndicatorPresenter] Missing root view controller") - return nil - } - - if let vc = (rootVC as? UISplitViewController)?.viewControllers.first as? UINavigationController { - return vc - } else if let vc = rootVC as? UINavigationController { - return vc - } else if let vc = rootVC.navigationController { - return vc - } - return nil - } - - @objc func presentActivityIndicator(animated: Bool) { - guard let vc = rootNavigationController else { - MXLog.error("[ActivityIndicatorPresenter] Missing available navigation controller") - return - } - - let presenter = ActivityIndicatorToastPresenter( - text: VectorL10n.roomParticipantsSecurityLoading, - navigationController: vc - ) - let request = ActivityRequest( - presenter: presenter, - dismissal: .manual - ) - loadingActivity = ActivityCenter.shared.add(request) - } - - func presentActivityIndicator(on view: UIView, animated: Bool, completion: (() -> Void)?) { - MXLog.error("[ActivityIndicatorPresenter] Shared activity indicator needs to be presented on a view controller") - } - - @objc func removeCurrentActivityIndicator(animated: Bool, completion: (() -> Void)?) { - loadingActivity = nil - } -} diff --git a/Riot/Modules/Common/Recents/RecentsViewController.h b/Riot/Modules/Common/Recents/RecentsViewController.h index 9e9e357a7..00f728d24 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.h +++ b/Riot/Modules/Common/Recents/RecentsViewController.h @@ -19,6 +19,7 @@ @class RootTabEmptyView; @class AnalyticsScreenTimer; +@class AppActivityIndicatorPresenter; /** Notification to be posted when recents data is ready. Notification object will be the RecentsViewController instance. @@ -96,6 +97,11 @@ FOUNDATION_EXPORT NSString *const RecentsViewControllerDataReadyNotification; */ @property (nonatomic) AnalyticsScreenTimer *screenTimer; +/** + Presenter for displaying app-wide activity / loading indicators. If not set, the view controller will use legacy activity indicators + */ +@property (nonatomic, strong) AppActivityIndicatorPresenter *activityPresenter; + /** Return the sticky header for the specified section of the table view diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 61efd306f..dbd280337 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -80,8 +80,6 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro @property (nonatomic, strong) RoomNotificationSettingsCoordinatorBridgePresenter *roomNotificationSettingsCoordinatorBridgePresenter; -@property (nonatomic, strong) GlobalActivityCenterPresenter *activityPresenter; - @end @implementation RecentsViewController @@ -141,8 +139,6 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. - self.activityPresenter = [[GlobalActivityCenterPresenter alloc] init]; - self.recentsTableView.accessibilityIdentifier = @"RecentsVCTableView"; // Register here the customized cell view class used to render recents @@ -2414,15 +2410,23 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro #pragma mark - Activity Indicator - (BOOL)providesCustomActivityIndicator { - return YES; + return self.activityPresenter != nil; } - (void)startActivityIndicator { - [self.activityPresenter presentActivityIndicatorWithAnimated:YES]; + if (self.activityPresenter) { + [self.activityPresenter presentActivityIndicator]; + } else { + [super startActivityIndicator]; + } } - (void)stopActivityIndicator { - [self.activityPresenter removeCurrentActivityIndicatorWithAnimated:YES completion:nil]; + if (self.activityPresenter) { + [self.activityPresenter removeCurrentActivityIndicatorWithAnimated:YES completion:nil]; + } else { + [super stopActivityIndicator]; + } } @end diff --git a/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift b/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift index bccef0df7..1c592a2a2 100644 --- a/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift +++ b/Riot/Modules/Common/Toasts/ActivityIndicatorToastPresenter.swift @@ -16,32 +16,38 @@ import Foundation import UIKit +import CommonKit +/// An `ActivityPresenter` responsible for showing / hiding a toast view for activity indicators, and managed by an `Activity`, +/// meaning the `present` and `dismiss` methods will be called when the parent `Activity` starts or completes. class ActivityIndicatorToastPresenter: ActivityPresentable { + private let text: String + private weak var navigationController: UINavigationController? private weak var view: UIView? init(text: String, navigationController: UINavigationController) { + self.text = text + self.navigationController = navigationController + } + + func present() { + guard let navigationController = navigationController else { + return + } + let view = ActivityIndicatorToastView(text: text) + view.update(theme: ThemeService.shared().theme) + self.view = view view.translatesAutoresizingMaskIntoConstraints = false navigationController.view.addSubview(view) NSLayoutConstraint.activate([ view.centerXAnchor.constraint(equalTo: navigationController.navigationBar.centerXAnchor), - view.centerYAnchor.constraint(equalTo: navigationController.navigationBar.bottomAnchor) + view.topAnchor.constraint(equalTo: navigationController.navigationBar.bottomAnchor) ]) - view.isHidden = true - self.view = view - } - - func present() { - guard let view = view else { - return - } - view.alpha = 0 - view.isHidden = false - view.transform = .init(translationX: 0, y: 10) + view.transform = .init(translationX: 0, y: 5) UIView.animate(withDuration: 0.2) { view.alpha = 1 view.transform = .identity @@ -60,7 +66,7 @@ class ActivityIndicatorToastPresenter: ActivityPresentable { DispatchQueue.main.async { UIView.animate(withDuration: 0.2, delay: 0, options: .beginFromCurrentState) { view.alpha = 0 - view.transform = .init(translationX: 0, y: -10) + view.transform = .init(translationX: 0, y: -5) } completion: { _ in view.removeFromSuperview() self.view = nil diff --git a/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift b/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift index a4bd67259..6964ec445 100644 --- a/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift +++ b/Riot/Modules/Common/Toasts/ActivityIndicatorToastView.swift @@ -20,34 +20,27 @@ import DesignKit class ActivityIndicatorToastView: UIView, Themable { private struct Constants { - static let padding: UIEdgeInsets = UIEdgeInsets(top: 10, left: 12, bottom: 10, right: 12) + static let padding = UIEdgeInsets(top: 10, left: 12, bottom: 10, right: 12) + static let shadowOffset = CGSize(width: 0, height: 4) + static let shadowRadius = CGFloat(12) + static let shadowOpacity = Float(0.1) } - private lazy var stackView: UIStackView = { + private let stackView: UIStackView = { let stack = UIStackView() stack.axis = .horizontal stack.spacing = 5 - - addSubview(stack) - stack.translatesAutoresizingMaskIntoConstraints = false - NSLayoutConstraint.activate([ - stack.topAnchor.constraint(equalTo: topAnchor, constant: Constants.padding.top), - stack.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -Constants.padding.bottom), - stack.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Constants.padding.left), - stack.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Constants.padding.right) - ]) - return stack }() - private lazy var activityIndicator: UIActivityIndicatorView = { + private let activityIndicator: UIActivityIndicatorView = { let view = UIActivityIndicatorView() view.transform = .init(scaleX: 0.75, y: 0.75) view.startAnimating() return view }() - private lazy var label: UILabel = { + private let label: UILabel = { return UILabel() }() @@ -62,18 +55,33 @@ class ActivityIndicatorToastView: UIView, Themable { private func setup(text: String) { setupLayer() + setupStackView() stackView.addArrangedSubview(activityIndicator) stackView.addArrangedSubview(label) label.text = text - update(theme: ThemeService.shared().theme) + } + + private func setupStackView() { + addSubview(stackView) + stackView.translatesAutoresizingMaskIntoConstraints = false + NSLayoutConstraint.activate([ + stackView.topAnchor.constraint(equalTo: topAnchor, constant: Constants.padding.top), + stackView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -Constants.padding.bottom), + stackView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: Constants.padding.left), + stackView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -Constants.padding.right) + ]) } private func setupLayer() { - layer.cornerRadius = 20 layer.shadowColor = UIColor.black.cgColor - layer.shadowOffset = .init(width: 0, height: 4) - layer.shadowRadius = 12 - layer.shadowOpacity = 0.1 + layer.shadowOffset = Constants.shadowOffset + layer.shadowRadius = Constants.shadowRadius + layer.shadowOpacity = Constants.shadowOpacity + } + + override func layoutSubviews() { + super.layoutSubviews() + layer.cornerRadius = layer.frame.height / 2 } func update(theme: Theme) { diff --git a/Riot/Modules/MatrixKit/Controllers/MXKViewController.h b/Riot/Modules/MatrixKit/Controllers/MXKViewController.h index 66237c8d6..e75d42e11 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKViewController.h +++ b/Riot/Modules/MatrixKit/Controllers/MXKViewController.h @@ -48,10 +48,5 @@ */ @property CGFloat keyboardHeight; -/** - Returns `YES` if any `MXSession` currently requires the display of an activity indicator. - */ -@property (nonatomic, readonly) BOOL shouldShowActivityIndicator; - @end diff --git a/Riot/Modules/MatrixKit/Controllers/MXKViewController.m b/Riot/Modules/MatrixKit/Controllers/MXKViewController.m index 118e72455..a4e559b4c 100644 --- a/Riot/Modules/MatrixKit/Controllers/MXKViewController.m +++ b/Riot/Modules/MatrixKit/Controllers/MXKViewController.m @@ -492,21 +492,18 @@ const CGFloat MXKViewControllerMaxExternalKeyboardHeight = 80; #pragma mark - Activity indicator -- (BOOL)shouldShowActivityIndicator { +- (void)stopActivityIndicator +{ + // Check whether all conditions are satisfied before stopping loading wheel + BOOL isActivityInProgress = NO; for (MXSession *mxSession in mxSessionArray) { if (mxSession.shouldShowActivityIndicator) { - return YES; + isActivityInProgress = YES; } } - return NO; -} - -- (void)stopActivityIndicator -{ - // Check whether all conditions are satisfied before stopping loading wheel - if (!self.shouldShowActivityIndicator) + if (!isActivityInProgress) { [super stopActivityIndicator]; } diff --git a/Riot/Modules/Room/MXKRoomViewController.m b/Riot/Modules/Room/MXKRoomViewController.m index 2473e9d46..a4a0f7dcf 100644 --- a/Riot/Modules/Room/MXKRoomViewController.m +++ b/Riot/Modules/Room/MXKRoomViewController.m @@ -154,8 +154,6 @@ */ @property (nonatomic, weak) MXKAttachmentsViewController *attachmentsViewer; -@property (nonatomic, strong) GlobalActivityCenterPresenter *activityPresenter; - @end @implementation MXKRoomViewController @@ -223,8 +221,6 @@ { [super viewDidLoad]; - _activityPresenter = [[GlobalActivityCenterPresenter alloc] init]; - // Check whether the view controller has been pushed via storyboard if (!_bubblesTableView) { @@ -1776,15 +1772,6 @@ #pragma mark - activity indicator -- (BOOL)providesCustomActivityIndicator { - return YES; -} - -- (void)startActivityIndicator -{ - [self.activityPresenter presentActivityIndicatorWithAnimated:YES]; -} - - (void)stopActivityIndicator { // Keep the loading wheel displayed while we are joining the room @@ -1800,9 +1787,8 @@ return; } - if (![self shouldShowActivityIndicator]) { - [self.activityPresenter removeCurrentActivityIndicatorWithAnimated:YES completion:nil]; - } + // Leave super decide + [super stopActivityIndicator]; } #pragma mark - Pagination diff --git a/Riot/Modules/TabBar/TabBarCoordinator.swift b/Riot/Modules/TabBar/TabBarCoordinator.swift index c0454e86c..30ce90bc0 100644 --- a/Riot/Modules/TabBar/TabBarCoordinator.swift +++ b/Riot/Modules/TabBar/TabBarCoordinator.swift @@ -227,6 +227,10 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType { homeViewController.tabBarItem.image = homeViewController.tabBarItem.image homeViewController.accessibilityLabel = VectorL10n.titleHome + if BuildSettings.appActivityIndicators { + homeViewController.activityPresenter = AppActivityIndicatorPresenter(appNavigator: parameters.appNavigator) + } + let wrapperViewController = HomeViewControllerWithBannerWrapperViewController(viewController: homeViewController) return wrapperViewController } diff --git a/changelog.d/4829.change b/changelog.d/4829.change index e4f187451..e55f8b1fd 100644 --- a/changelog.d/4829.change +++ b/changelog.d/4829.change @@ -1 +1 @@ -CommonKit: Create a new framework with common functionality and create Activity and ActivityCenter +ActivityCenter: Use ActivityCenter to show loading indicators on the home screen (in DEBUG builds only) From a6b5564c65226838c8bcef5ad4658f2c3fee3a68 Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Wed, 16 Feb 2022 11:56:33 +0000 Subject: [PATCH 097/188] Move import --- Riot/Modules/Application/AppCoordinator.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Application/AppCoordinator.swift b/Riot/Modules/Application/AppCoordinator.swift index bdefe2dba..8f1b61d58 100755 --- a/Riot/Modules/Application/AppCoordinator.swift +++ b/Riot/Modules/Application/AppCoordinator.swift @@ -18,10 +18,10 @@ import Foundation import Intents import MatrixSDK import CommonKit +import UIKit #if DEBUG import FLEX -import UIKit #endif /// The AppCoordinator is responsible of screen navigation and data injection at root application level. It decides From 4d89f64d38518b722648191dff958218d7d50107 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 16 Feb 2022 12:09:40 +0000 Subject: [PATCH 098/188] Fix reCaptcha failing to indicate success. --- .../Views/Authentication/MXKAuthenticationRecaptchaWebView.m | 2 +- changelog.d/5602.bugfix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/5602.bugfix diff --git a/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m b/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m index cfcafc744..776214b30 100644 --- a/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m +++ b/Riot/Modules/MatrixKit/Views/Authentication/MXKAuthenticationRecaptchaWebView.m @@ -102,7 +102,7 @@ var onloadCallback = function() { \ if ([urlString hasPrefix:@"js:"]) { // Listen only to scheme of the JS-WKWebView bridge - NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]]; + NSString *jsonString = [[[urlString componentsSeparatedByString:@"js:"] lastObject] stringByRemovingPercentEncoding]; NSData *jsonData = [jsonString dataUsingEncoding:NSUTF8StringEncoding]; NSError *error; diff --git a/changelog.d/5602.bugfix b/changelog.d/5602.bugfix new file mode 100644 index 000000000..eb499b83b --- /dev/null +++ b/changelog.d/5602.bugfix @@ -0,0 +1 @@ +Authentication: Fix reCaptcha failing to indicate success. \ No newline at end of file From 4e27be3b98d02e4f40730a2104ce8d5bb8301465 Mon Sep 17 00:00:00 2001 From: aringenbach <80891108+aringenbach@users.noreply.github.com> Date: Wed, 16 Feb 2022 15:37:56 +0100 Subject: [PATCH 099/188] Remove bubbles background from search screens (#5601) Co-authored-by: Arnaud Ringenbach --- .../Images.xcassets/Search/Contents.json | 6 +- .../Search/search_bg.imageset/Contents.json | 23 ----- .../Search/search_bg.imageset/search_bg.png | Bin 17008 -> 0 bytes .../search_bg.imageset/search_bg@2x.png | Bin 40774 -> 0 bytes .../search_bg.imageset/search_bg@3x.png | Bin 67320 -> 0 bytes Riot/Categories/UIViewController+RiotSearch.h | 23 ----- Riot/Categories/UIViewController+RiotSearch.m | 88 ----------------- Riot/Generated/Images.swift | 1 - .../UnifiedSearchViewController.m | 89 ------------------ .../Room/Search/RoomSearchViewController.m | 67 +------------ changelog.d/5471.change | 1 + 11 files changed, 5 insertions(+), 293 deletions(-) delete mode 100644 Riot/Assets/Images.xcassets/Search/search_bg.imageset/Contents.json delete mode 100644 Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg.png delete mode 100644 Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg@2x.png delete mode 100644 Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg@3x.png create mode 100644 changelog.d/5471.change diff --git a/Riot/Assets/Images.xcassets/Search/Contents.json b/Riot/Assets/Images.xcassets/Search/Contents.json index da4a164c9..73c00596a 100644 --- a/Riot/Assets/Images.xcassets/Search/Contents.json +++ b/Riot/Assets/Images.xcassets/Search/Contents.json @@ -1,6 +1,6 @@ { "info" : { - "version" : 1, - "author" : "xcode" + "author" : "xcode", + "version" : 1 } -} \ No newline at end of file +} diff --git a/Riot/Assets/Images.xcassets/Search/search_bg.imageset/Contents.json b/Riot/Assets/Images.xcassets/Search/search_bg.imageset/Contents.json deleted file mode 100644 index 568f8cb3f..000000000 --- a/Riot/Assets/Images.xcassets/Search/search_bg.imageset/Contents.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "filename" : "search_bg.png", - "scale" : "1x" - }, - { - "idiom" : "universal", - "filename" : "search_bg@2x.png", - "scale" : "2x" - }, - { - "idiom" : "universal", - "filename" : "search_bg@3x.png", - "scale" : "3x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} \ No newline at end of file diff --git a/Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg.png b/Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg.png deleted file mode 100644 index b78748b04fbc524c41f418b42a8cc3355c0ff2a4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17008 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 iuXAq-8a4P0x^>!%Xt!e> z)v_}F@a;p=r=+R*=QM;&Wxc}~VcoQZz4x3;B$t;$h?r1Ib=g8QDK}?#FU3&U`FCB{ z>rb?e=bYC(8V}EUh3xxNSDn+jcYB@tQ|)skP*|xc5&nIA=m$CX2)ZHQPAY`MwZ5L+ z$+C5yG(ktfg4Z1pftBUuTgv;P69ccsB0Zdh*bJ_G_Wzo1q&J^t3#`$9X*5lRH)mH}ZhHpP}^GTnl;3yj`RmZLg z3(8`<)ow)WEv(Y}CuPDxC-^Iz4b|1B_+p38rtT!OK{d!IGRZ&)>?z^huw_D%qkHnI zJf*HP8)^Sa7z>S_sEXkCk+6MiaG!>{Rc|Vf1qQ((oEx5(iG_5fjaWF*AY9dXUY^e; zthvXffr7mMdjgRj&WQMb{wPUF0IxX}$@6u-+?QVPwL-x|++%C1mTwLz-{^;e(Ae)p zgaL@CIS)nSeLIrcSItK)4v`;%M7T8+$VuOHUWb;~c}2+y#a8`UA7Y0z+94uf6+(+( ziwh~Ams$u5aeB?-gjeEfv)B@F@B3FNBuU8aL#c&Se~`G3B$WoJ9?!W4M#bC(?jTRzb)5Us(&RhIp60d2`rnn2e2&53sPZYA+K!_3XmU zG^&+3*_mCBd2D;|`4p!tKyco9FjM@{T~0eV2kA?RvPKBiPXoMAyZGh$DrnU33BlF4%Csqq!T`!HjMvsNN;p_ zRA)j4@sr2JC*sA|NJ8vV58h7c62Uh{I9M;`r+5K>j>S#DhA`}%>ugUbT2}Zdclge+ zpN1OBkm%&YyIWC&_^D(kA&sFl>-ayo5R-%%AT37L5p3rye4I=;hKhQe_gZgfd=0F9 z*bkZr_kB$%gbEoKs;veuTvl;p{%z&`Q-?SvW&I7Q{D{R zD4Xk4DZLYHA3|z`-L|GW-msYBy5J<&~Xrkdey_h9NI%>1)|-l!g(1=#~0UYamEV)Rc?lggL!P$pZGq zgvcRt(mM&?OW~efIsrC5FjkdK#j2Rs)rIy;ChTOf*Q~+dN}oD5sXFCg zTdldTNNc@GG2@M1*OvT$g| zLm{c(Z4U)tu?e5#69`JRLK3;lJ{;M~M+sZg4&={7bnS8@^|Q;W}^` z#l*C4*A3>VZ`)415T${u1?%fK3sic&w1`XlE$paGz?urpyupfwzJ@VLqA3Au@l9(De-U-P#6-bT+e@M=jKoTDM~^*f_r^C-KQXf#5<1xuNN zDqD?G-~`@YHvMrGU`b$5{N?j!Galcm3fh_byFRr6V<#CgyBh^Ljg|HrzTuG^O^%5p zDzFUj!iRh|NftB-!+Zt&|6HC=Djje~nZIPp6DWfynmz`-73cTre!JxjkGPgItwoMU zPP1Fq$(OZCW;<0YpTHKG0$;vS$%u6J!@ueKHr?|oDg6>vr{DGmDZ~xJ4*GVVW@J?c zV?GGeX*__gP4(X8B%xuq=s|h}rkHJ4W2%NVo5TKq8T+piUKY4wRV*F-&n%OSxAz%! zcq1h{w83pdG09PvX;Nd`Z={PCS=$*_e5|{Tl6CXD(YtM~hij8qBy7!g9ieQBB#&QA zeWEH=&G~Z%B|xdMWRC%-bVi^MoQLIqfFTJZgXbJdv<2s%q2=38epN5hNhTi__t$V; zTd;6)x##Na85JJ$uU!OThh(^!v!@~TVz8E1QkbmDy>>hN5w9zqR$gPhtiSYj8g#yT z9VD=DQhaIuWA^;V)YIPOegUX>;aE&J>u=rErvXIkO)PQhInUebAm7!d_hS0~w6=!E znYslmV|D&(X6Axc4|{GJM=}{Q+yqewN*G6RZ1``DS>OX4P$Ozp%+(jwe5X$pmy*mc z5q*DY_ON63hlHSUzZ|p7{4!m4=u<3!E8X-nPGKcQFFmE?@DtK9L-oIYquK;iM>DN5 zF<@UUM46+LV+}*g)s2FRUF@}*6x-I1(23d}|L8 zD#wKST1AF8`j0*Q_vwXu6)>q$eswD>674^lp`2n&xifE3ddkHsfza|@d;)^|&RsmO zb!8n(Xmb*hh;g22Zew`6QC`l3rh0yBXf)~};O^vqN+IyLyb*FKlDz4deGvMeJRlPw z*=m#G@7Oh;*d~kY_R&8QA`Dhm&|J=-+#8<2Ad=EOQFKTW2;J(d_6}no)gXgPDvBlB zwi^D4RzZ+j;BBU*R&?PcUnnPxT5@jTJba)d>>@cC!r;KH!hz8rh3}B$npR-l`4kGC zwCmTFQ!fYrr`!F(2q1r7Z+|!Ad^18Jw*)l{Az8f{tI7k;&v{(;zAs=9bD577$n9~d zNE%yEU8f`&^9*v&8e&9n5&SlOY;3?*bZ7(2n)DJa`b-s5u+;Z|OmbrnoEWxXAEZ5Q zghD(=nQ?_W=K_YGN&@EYQtP)gfl{e8bs1u zW9GG0aum+21P@>6+y$ID+@DJx(N8#a5Q1hDG1kIB5uIq^Hhh)Tb2MAI!YS0kE5)eg zlymI5^>2>@Nl)*YV+nbyTm9;ApM@eE^q3No6?JDj`~fB7fEP5`!+@+vE8_kf3rQ2l zo$j4#A0t4{Wi#iFzHdeUR7>lkKC}HVZiM0dg94kfXHTm?(n>TOfSecopAH;G=^Clp- ze<3Ytb@%?9muDJYR-O9LdgQTS_Xc6xrE0#KV|yWH>cpAQRx5OMLewSj)$}Q7@Z6Jn ztI%gP@zkL0zLX%l-BHzO>tTt+M$m7`t`PXBm3V?biKf7|L6!S&7U)_;2QH7M~F>KfFAiX8n+PT>!Bz`4^ z%SuZYb75Jv)dk(2Tx%c)6zq`1h2=Hyh?n;&;xqX?rrEwx^o8z70d^-Eyj@_!OVlJI>eN-Th~EZKk9`cV#P11%pj>?;OS~(x4h**WvEZ*x1_4 z%GWTJii!$cQ%LAf=!{Zo?0xy_Tz~fC&hqLLTKo~#?*dP&eZ&Ju4mhS{e8!S)MLesu9}5e2nEg<&B9d*|A}=0A)>6E{m5pKJ z+yq^v;?qW2;qYmC`q(5}k+Q^Sg?$@uSN>}f)KLToKYsjpZ6@o^5}q|1Yc4A;E>7#G z+cWY^wxT-M&rZm7(ANXQz~vo&K~f<-Y~*-Fq(>}U$wCC{Rjy$8f^uni!i!^Ie14Mx2~NiAZEcOos!+@+{i8?^4=vle0Xy0_L=odousMmbLNFWob#ab|FcnUvf!S}A397g=Vgy`{fEm_2AApRVrDhHRTPh;S>n%yP%3KQvq; znSJwVG(dDUa!}DIZ#9FL-YcZ&{bbP=26+1re6+@>ewUp9vWxTHi1(E~x76egr{N}l zxRVT^Q#M;9MgE{0CANi_=p~KSUwO>L0uA3b`C~+ zC3Epmdc$x`UECj61O%6I8Si(!t*9zvI@JnfG7^}iqV6sM<7e{KZi=JXN2h4xXAh0m zXetP4K3YHEHtrSHY*Vhl%2~=OdMRqAGxqgWRr|+f!D57=D*|so68KVhb`FZ_Y?9Zq=apWOVVU4O;TKya~6Fc_URq zx8&Z(GodkU?U13)z`<=2C&iFJ1YU6RrgX^@Hj6KmNDx8NvG2pxrppz#a7pr4cn zT|DrT$FvhRLgu{<&p{W*q+ZF#U6>@ibx(D48Uij8d!lLOo!D7eNKKU7m&jWyIn?wb zynIc?{EB?O)x!tjD_-4QAoYR(ylC~PkeJx~&-5ntpSeQ{XO~~p-#w{zlNw%kNW6c* zU>wg`R=Wk3QS0;92wc$VbHdM`Tq_}<8H6p)M_O9XY_s`$n#}kBm#o{K)~+f8UIMQL)sZ`%aj65ORFxTfbI3u4eNp{oI$wcW9)5q>K3X?OBUt%^RRfZ!1;lE-%(T`nbQP0#@tUI$Zo{bbz$o{EnVG4+s-H|iX;xrf7Hnz z=}n6PH*rCe{3{Rq9sBkE?aIx<+K4vO5rjIvX%XzG`bntabX#ToHbJGTMM7y>WU)IL zxTd-1@tT1qK0dx;teeqhawzD9@tuQWd8k+Z`ejJKS7Rr!0fK=5p%H@npW;q1Bu`5o zxbaU1?GRU2kx-cT)TOc>&89175*1u$3UyjkvQE=%$oz?CKyFPrj#`IH4M*W(mQPRS zZ`_|cd9UQsax7uPq#pa3C@M{4sgzslJKV3!It2+O{RYT!Z^kwWSvAXFrS9V^{JV}k z>c!cBmuF;_C7Rs6F#Zmshj-Uew&+q2O#>!BchxDj82s>C>m0fZbD$g`c{~J-DIfj~ z9Rb1n=;3CToVpUbM50&5IS`qdo#E8W7`qyo472XQO`G>7a$3LcoPX(oznxS3LJ5Ae zT}nzSv=cT3q;FCV&7At>|7bpF1<9v7GXZC)!DkhdeOuv4HBBnLUfVQi0nwnJZ4kJNa`0(h_% z1XZc$rJg)0rp-V-z4mr#9672|<|S*#z0*B-Fo+EP@ZMP_TPRSsv^JJLatJoJVQO*V zK{ykzn`>sRoyQ>~3HIz1#+YB@7l1&o!P|VT>f2aH< zMdWFH(?FPqk{h9M(^>6#Elfe9>kcUdLEu1mgoH(}txjk-RxdG<4m$xS=e|i@maXut zteZu?vxZ_5IcLbusxciRH*RP1&P0 zhlVK4_Yp~$*_tzqTPJ1W=q~m+gh0xEcfd+r~_Xhd!O>9%W1x6itCKsc_7=>#6A%!vZW03ktX$y^ZoyJZ_&Mj%Wv@%@(s#5z3tq$A zO2J}yw4l=uebiE?qpN#evmunh2Ak^6?TPSv@b*{4CCiMH{@}JV!#I0su?17~-{=wq zNkuaCDWcBP$ZaR0CXDK5W;^fLpDN%gC#j0}&piW*!r-HXORu!$ zpUK*thi}&Ft{%^0oLlhkZAv!bBBb^6FNdX3=pQ_6_ojdT^y#3`0$sQ8|Ev^5Js8Z0 z<9uWvDadeFiTTfc`RHN)d;x$jd5V)7y~O24d__gY@T>JK(*ND&6@rlFv>23kav?|B z>neFclfLJFe;}>t{$j)TOPjGX-XfiPLG|ur$GBXCKZPT})3D)AP|aK?&|r%aKYH^* zA|h6`9q%6x+DUzLgR?SoeOX-XENC8Qgzdt4i2wRYYHYomA3@~3#?>RK=h93~JMSjIbi1b} zCQgNTSv6kn$ox>GLpN8I!nu=@4=MHF5F4{Dfd_UYx8*fQtt+L#$B!RZ`ZyA(v@4ZU z`AbIpQE~4Z79Z%%H66XS)c3+qp}mBiT(dhFF8gWM>@iXNeL>k|NUV+SH@nq6r8L2M z&iow*D(51Ujo8|e-cEJ;)Lv8(j)V+hi#JuWIM%HjIFFV+a>1Klch$V zMBJe6m_weNAC_>o=^nMLmt7SD=n-LMUYay4t-EZ}ZSvxzs{j#K~T%%;N*5 zGM?PStMlW{#!d@?9LJZTQca`mj^^i=yH;dRI=fnj4lJiD$%Gw#4pyK_z0mtBEo>iu zP#fM3UEHrjooE1q6G#}Q{hP$%_;X15`U7~}fHrGd?TCcXzh;q+W2#=AGNUkW zRHL5SyQ3@8H(T45j2#VBl0>^|AC_^`B2|8tar4WXSDQ~2g+q}j+1rCtE|%3(w2Btl4!7Pj&F&& zrBi${<=CGt0t2_fI{LkZ@km91Zh@7O*x$MYpocCJlvaxkG(y~P?+bBc7Iey6+5M&i zlR|8~EZ#oy z)L*nZpy1GJGCvBQqZl&L{6->N$(X)UIo$0@ZVlJZa#LJXMhe&%ga<a8wUAk6ik(Lwq( zf^NrAz3x~XGc{4lcQu)2hj$(wS99eL>Zb8I!h7+L`BEbLFf8KJXen4DGbOWe=W<)F z*hnrIZDq8Mxi55--79JE;n^+9&#$%ITWFRSk>~Hg`8E1^KE_hjf*YgHK`U0j; z#N5N>^zPdVqUY%%Y}jLo<8ds_))R1u-vqSD(qET+)A)jSp(=jcy>hqga$uz^W?uTK zbdW;J8@cyzx?+zIT@^j}6YO0$YQ{H)=0r#QuDsvY%o0V^xWxxn75)DFgU_QU5rN+sNinU$4JXb3Reo`|K3iwhIYb=NAOMvSTwV(K*}RbB+Sn5Q7pWc%wl zu;Gh<&V!p2*Tao+r3}{?OSZ=s-oC!RRU1$2BQ}-{DKfZCl*ngavq>*BN=+<6Z7&L$ zSy{hU{C^GGyQbTvmGi~t#O6F)It3Tv5)a>$#q!P+_N<1^npBQ8QX=1Z&Ml}NdgQ#s z(fe!Tu-6CwC?R;y+uOeu1-mt|ZK*xf&1rkek)U!nCF`QwxctL6oXDD3mUiQ8?TR$ zmYJ$S4gM{ z?)=lDrH=Z61eCB7=4+jIg}_^cr_Y|Y!8{y3e9HrX)%VDwIOCn0e&uY9de`qmQLckn zG)fJfkyAvKnz79D_kwocMzEW04>TlS8bfc2e3w*Pgyp!`+iPoUDnGAvX4Uw~aD5~J zgQb5gumAVeB>pu$ zE|jNocD7})>K#u90MM+J!j=yR089cb>M!qew`hy39srTr&(6-Qsmfus6Z1h$SMnYn zmu<~{C@Evd)d^Ce1lu>|+09@MpGO0>GX z_&8IA+6VuiGDVAYW@e@y8gFedl*s+X#=;A!+QnuCE_7bYDF=pHWuhv3@!rUf=6&@y zQ5eDnC_>DK9R54i`#{-5x-CPU+A;lo812g4$Y?cK#}oC(QE-N^>jC3OOXNmrmI<3T zo9_GIE4v^FHPWam9as~M`HzWXGa&@6@^SEIRgmdliUTQvK0t0Exnxk-T=+4W^J(_U zwTS=a6_9ONR9>v&`BVdf?Ff+bxifO$_yEg08FwS>+sY+hZU$6}QU~D|6D~Vrz@0&W@Zlw4ky;p6+4EVmD_tyHJ(DxW z>lCeYLWwif3r_&z5`L)g->X#c7MSiUk3`WhnvgYzDaL15_X8Jq6+&Bsdvw-qW9+??uUY zttX20b5_@D?YmP0g7WS7%l4cETq46aUBfIA3ghe4(6tzeYT&iYTwsFT5YTNpgK7 zlhPIz<(EKv778*vcxW}iOZK~j?NdMpnO~>*DQ%1Q*n?-fmB9i_MGq>3M?m2866jw` zrydGikx$DoGc)TJ0BvF}{qi=tr|RleU-B51{65jyykK_U!mAT`>><56J2)6s!Us1O zuk`s-3}kfKRFGT!Pvb4h9LZF5Kqe}q^_mm8u2KX_D!%X*#)K`NPQ@lb<$E;C z{VfsY5pq^?QSQ!Cu@NHo%+ciHm>SX&Z6?8qiyUL>?|XkJ=dCKRo3&%X`UMsGUZ-L?oJ`lG2wXynYnHn z7+{Acx@lh||8oTJ)WwEf(X&b7D~kTh&h@;ZJTmxrc)e@QdU@k!fg&Okk{%_oT;Dtt ze~f1h5AVk3rdT#ieP}E51GL>~H2VqFtxjP>5C9_6b~|MkQDS9eDarE8jX?xt}JnKWS4QjoIlHfkELn^ig$5y&=T>R$mRY__0?oudIu zX;X`xnQw>R#|V07K1S<(23uw?oFESk&q1U;!bv#vyf^5w?jek}myNcg5`;Z+huc`V zx`Y)KUx?TyvvHMIrr2WA_9LB%)wfu1$q3wl@L=pglti2lpNem;C(7uCn0sRA6kUS1 zDJv;0&|>glI*5II@ZM{;&#%Og%WpZI!^+M%4O>JWj}=n+hk}l~3d{(%zY~*}7QUug zw9+fyqda`wug|UAP$sG{f4FhDJ|Je-76eYILOJ@`;h;{v-66;JxO~~F`I;%R^ck1H z6A0^$faX3EP+o@Y;OHSoUj^0fV?T(Dnh?5&^YbKLqpi_;Bu5d;jn(^kF?04auvJI% z@tFd#xcR{Y%@`At;dhj)ifIa2N`%CrV!F^Gq?pSlig&4K~mfS~IisyBa_5$%ygzMKO zHeR7W6w3$l3JNZsJw|0J232D}4Xs7TbG^x{AiQ7>ifi!#UFjsxu)LqE_LK3$r7o*jx{7kTz9qc*_zD?Iv&7KRV}MeyyuENfM}~%m z(umIBfm_qRlJu-r)tMFnOEygmOQZ7p*(g)$A z?YRu`FZO_8LTfMfT)9qyU$--4I{<$x>T~oLz#K9-Z(eVEoDiBZa{kr>8x8$>x8+J%yqH#& zH<9nDL*yAcZyHgcHl~eMtE&~c!K5Xlu{m<(ci~;=2fY^}BXG-!$Yq#!80Uw}S<5}Ktoq7n>au@RQ zeE7NE_zLj^eE60;@k{g*@%NIMWC+QsIb;yQTg0tT?QNQYBT=5ssA=^v&ej^~s5Q0= zcgSjj<7Xj(j|(&6UU%p6Gd>*$if=g2+=8b|EDo|S`otNrD$9RJF)GC=SZci5S-38^>Vi@P=;H24*mV4add zOR7Tt^hKQ@^`IifZbr$}Nuo5e0{MV{caC$mL|LtmSOi;09P4B6pf zS;_UZs$DmLkTMjNa;k%BDkC!pZ2cVkKs6{dW>};agaCbE@eRv%8!zP?79-&K ze;y6Qdvt5dCCQ+C6jnc=Tj7H*p&d2uP2x6zO@|tG`1#lDafv=fqGsFkDOLFXAJA%( zf*aEDHTCjt0*^aL9^@8uB5>T2gDJEK``t_r_DLkixg^h2u@7>(-+#s)>6+?IfD0c(W#@e$hFAm9*RA#0=bKYOq(Ore&SL&B7a{wa z4y_0q&mpLCRZ9GcF17KlbC+}0S@fq+ue|!aPzcC5aX^1?FZpR}>^`8M&j3Toj_Q=S zvDy|1Z*hkzJIZBgvh-FxE8)&%Ys3bFmBEV74^|- zYHC;b(_20%vuJ2&y@A%HZ}i7f-554Il9=#Z=f(Mwl)2*?4*=%$UL;WY@Un<2y%FxI zw6__G^DRNw4_R`$B3_p=6(9f@7Z*%Jev~2VX9h}h{4l~adZe8=+z_>U5Gi)$Vlc(6 z_6`t^85IDr33|IFZ=@qkZ-d4t?M{R{1m*IWR(DB{kwFFOS%Cw3%WqBWgx$mRytf;a z8Z9Q)vxSYXj*>Rm&}Togk=@iY9M zkr;R}P*??yr8t99)rIfRu(#C*xO1IbTz#NAMagYP+Q6I+bw~246$t}YvpKl z@Y;dT0cfN}gn;Pmrh^KBpx!3U3f!Ch0b^s%VNYi^z%yxt#T9dAvi)5zRVhZ99IT=BAbw8zT2MV>ru;PJx|{iW~D2Fp1;C0x*BmSMdv$ zfOu+10q<}1S^l%yx6^yW=*?!+Q|~=@{1D6vWTZJwUEsOlx90^rJiE0`^iG9ywv}tJ z+zhj#fd&Hz9>}_|Uqmb1cChH-C0{A$);i7;w6cl&F1Gv0#D4Ad*ip;Td$9E$KU+Hd z4aD?1xpYS=y3sg%X;4YcxMlzr)F}3Ki@uo6n!fHnAR$8{U`3Yvr#DJYNe|jGNErTv zKYbtPK~>6EcLk;|3O<|@uO)t-=qR2f<b93jAmm0IAh@{d zfhx6ll;z~)AeDGJVT%>7a#GU*lM>i|kc0I{f+u6nZHglc^7`B^|H#*?62cED*qw7H&kl>2smoz&z9w{m@CQX7_10iy?S8tjfDZ)b>oA;ASOUEnPXvFH+?Xl2S^V- z^3ShEP0#GGHFIsY#|CMe*|OVe`qYL*%KYH}QyIoq1avPs*!@;z29e%j5FLP#3mu8& zn4vzZs;c@w+3Z;=*IrdNZaSF%*GOne11wsI@U~M38ARnO9$>&(-!bqmtI&9~k@~ zAtQckN`QoJX5LQP-yE(gu9r7p1}#vnA&QB!3<129j{Ogx=+i3q0k$axKAP0Ed+zKl z;nYU~fPijvdCbZ;0+9tO)^l1iI0G78E1b){;WzHa-4xU}XBHjGc~W!QC4Y;LngYBv zXS6drZ~xT-@g~@Mjor%4@+t+$Z%$0&<4;(w!vsr?g)P#4@%WBGEdf@p1PT^;-PA^r z$IUj_@XiQtY@OGsb#HG$*ayf38iP(RbB#>tHD|3$F1UVal^95Yxw~c-4BD(|r?m6_ z+sgpplt;o#&)v!g83CY{l$5obF;kzptjRY{Y$SADvT4^`{NFjD5Ntp%P)gJcV{RO4 zo1C}Wi8FSySCt=4?DbP^ZIAybpr%ECD4;i!To$mN|EhV|DczUDlow(> z&Kqc*uu}2^cWfpZtznsrK4?4vDt>E~H}M%xTo_gV!aKBm*6h+V^=fUr!n1yqR`!=p z9l?$`IaY0KP`aSWr<=6T6#)c&&+}Y3!c;fn5nu6Jswu_h5Dj*tr`IG} z%DP4(t?nqTq#W|20mt0dm;W{5{ogkYf0EyLu5rpz8R=L?v0n#wok5wYSVgQH53s{l zfiXW=?L#NlED!Z6$*vRUl{1N|*SFmhpJMDx5bHI5si_o>~Ee|2~{~_StNb( zW?dXCaa6ZMQj{bh0AkT&y}v+_Jd(1EU3auX7Rv`xDs_N^rb4o4K%Q0cnb|c}+&j3y zPh&P-+KNA6L~&iI%J0uE3(3w*l~+ldI=c!Jy^mneP)`)1)YEV7EeaW-&Y<4k!pdYD zhgrx9X;T2ovl&CeYvJ;tuFhS)p!mC2S2S(yNS0Ux$+%pb$U95@f<4k}q#;k_uaexa z1Ku~@+zC>ex7o+0@6*+Dik;&48cxVoJ9{$p5j!a1>T?UqJL)o?pw3ZjJ{Nk}W?#IoC-W(M5@Mmrv} zb|T*>=-&ILnQ!*B+m+K+>QU{g1+}M%aYWvl?U*~~0O@DG!<*@lGV^xa^Rb+FJan1! z!nV+ibDkxqRu5-qgRbzl^Fb+r^iyzzP~U@fQnxppVP2m5KZ0nfQ4d+L=hHTMq1gDF zS91~f-dqjV8Yf?_QCpCDtMiF!aR*=S(``YIiVDI!46%}4w^1P;aC#YH+$enktF)Yk zLNqiczvGQOcepujCqKM#1W{kbzOFd#HgcH1+jnIwB0%(%2uU=>?q>(L%ur;bh9mWU z&F`KCW2aw(F0lke6KuGFaa0|H1vAIB0`>lz%UWRd8G9FACF{s%tpcTcgz9X~&xC)w z1scK{qT($X)cwUr6oh)A$7#X($$aDE>rdgH-Y8P!zBldk&<9bMtzC9#60y_SL}Ulj%(d+L?N~FGqKW1HO1H4%DvCpVoARp#_vYU|b}RPmcaG zmUz2BI*uOX*NL#=;CdTRe%OF_T;1Qp2SN63y8y+&tQxN7OfB+&pmXTx(oVlr!`<${ z7a9tbVq({c9KlX1_{pktP4p`v_{`^rXeR7ROox-R4Hj-3-dVvF;Ojp3zT)Id{4KAE zBHczyc(xFQyZSh`4+IQRPs3yITjG#z5xFnBfz|>S{61B(gQhJ~Jc^>plS0V)LNM_M zi~qE3b@1n~HE@SJ|H9cHDz{OGxaGex%L0*-uj1NZ9or7r+@l&paR4R)g(Xj1K?mYG zi4vNQACD2tEtpeePoDvC8UeEc|Or_s`P#LK?`Sx=nJi8=ZUo5 zHK~usmjU`dgM+hU-+Sme5dgC0lxSD2{3{Ub2MEmSg`|oD0o_dx@N%g>yzLGuQ}DU} z9keC_uxcE|q#FWF#nQgcJ3f^b^&%E^KNUW>e4Dx0`EN%P5x)FAeLd;0-Wy2*&(QCB zbq0rjeiuMcuidP8Rbmn6_F!!)%e=3Y=48xzdO;-B+_kv5*SuB{dfXj9g3=jvkVGHy zKt4ll|A90_XTo9)Rf^@>r(sK(DxI4tx$BxoY0R~bTJU>lDI?~MZT$CuNZ^m6l1kVe zLXG40zjXtZ0cclGk6V-lbYCF9I))Dmt6*U0-1FXu?3L(F5ZWIGoPcbT!oUnLbNc~r zmZ#y^NN`R2Cq=!-TjQBW)#}3xm01l9o~}2>PAZA_oq9cB$Q0F?!aQ6JihD{UCQT3^ zY8+!RoCe;lqM1XXn)8aapbq&n>pLl_H&t$yCKE~S!En-v`%=c90-)5l9rX(3y#DUx zHsqS!;1OEA+f?rbww*Kd2wzsVjnqz8bT9qHGTLVnM^K7jrbd*(6jsPUZ~I)hC3#nc zAe~lTzWFP_k!tKNLyG&;Mez@VJK1gpuMkpKD=*H?_AnpH?KXZqmIYYQqf`>_+*ed< zp3px+;L)0s7ST=DWZH;iUED#mzq-&}9JpqY3tW2yP%k@zPF}e;eR%j=B`KqjZkXBu z8sq)#)jeQaH<;N&gogB^>*jM3&Bg0w6P+iu9spX(c)re8LBaKsiiiKl^7(?~gXZ8p zP}e)@auOtA(-{Sd20xMSA69(P0&rl~sZ{Y)t0fRJ& zIV?`(LKYi6yPix(eU?Ja8IgjDu_Bv#iD>;xZnm5Gt}CrhUbi4Ax!h#uhVh&l27 zmMjaVB+bui{krt2 z=#2fqCbs#wP4(BRr5UtWOd1*b9-d9!@b=o#p&LfT`)`kaawfwW7fg3qz}hi-;SUn0 z0n)6KoLsOg|6nv7!p$sbJwFZ_fpyUPYl6zS3^mMzU- z|68;7g5WUCjfpz~H9EdOiFTXsAcb*Lzh$C+`>enw_%wx0fKbb(8TF^%F4a;bePR9% z^)B(4J(0Pw#VD{@Dxq<)P2QTlvxv`d8?$*SC&kO9(7eMlm3Ie+-<+gu_D{*?MwrzO8z$zwQXS5UVDO$v8pE3tX>P{xOgDV=0|_{$^5xO@wt-MVos+D-f`m6qN!YT z7Vy2ag1r=+$r z*_d^Uy^jaWtkth;`cYV))tSL^MUeCOYpcc81X6fn*DI;s?3mEBtCwlR8Ai|*Q{=S0 zK$ti*mZ9{a7EgcV(R+EM3;L$;EeP93tPyQ<{mpA;{UNJ@hdYGW5($HLXT)X=vI)tH zSFeglB`HM_a%u_JR|8UW(FJ6#yP34Y(tk~2`fH0B^ zTBMu0R?>w^_)$(NqAC!Q?Ns1SSaMmdw+PrGYI`*NIvQy>L2_ZZDm(dno{*(EqoUVC z@rH#kFyXl@_1-feGsH4-xFqr6dx88e9kNM?QM7J+tb(@envK9GbNHiWzBIX6ckR)) zcsMYJ%Fhx~sY{A?8qx)8WonD*wLtB_-%+8P;1XG2fV5XpT+cb|Tx)I&M1kPmc(qMC z7Hpjy$NFPMpRav7In!S@x<6Pw7yW^EEzeEW@l}*|*Q^xUwP?1ak^WMK=`Fs|3{6kZ z88Ts*L(pfIj=ZII>ZWk0i&eSt&eF>)R<+R=7vp=p8~l=)qAt;B?Rd+{Rq-GwEbsbi z|6#zwWnyuzz2aNi^gVI(Rt4EJplf|aXvE=HkWJ97-dZv~k=$%|wuPl{o^wC!82Q)z zm+oRrA4rcEH0>yRdtKs%=@DESD$GW5*aH{y7h)IrVi(bJFO4&}wAxZy7%LlR=CDoE zkecg$FhJ>~uAjfRQI2NyDg%}0LY~TT)T0^ceZzuFkzrxum1ra>A-}Uon$Sf0` zeKw?gtr|p~LhEH8cNBHE=|8)T(9-P$2cv> zzII-IWBGyaaX-c=Tlq51`imuDE7*EwEzSC93J0-K+$GI}ZN%(I)@z91D~cVRY*G|W zWUDMvBYnm|BR7WBi}79zF)#F*l9Kc#KP%_&+sjyn=lW|c!@y_j*rRww%PSjdA7NP3-G2Vv8isGXd<{*_;!% z7&cNGSL|;+z_^Y3X;JGnu~VN!p=*yhdn4DfgvEfCed|d|DoLg3F6873#XGsJVOh1v zzWI+=TbyJf4D&y}sTFOouwPfWb?&}*SW8mS!P)70N^{>U(=R5BxW=@udyd{gx@Q4` zyFe!tbok3PtoP^y%jpJG=>Y=(;G!`^Om_6J?49ejN9E?FQdCwH!_^{_r%6F3l7#sp zdp2P0N~O&C<7BACWA}!>sz<#TG+^HdoB+K9G)YW@V-NFQ^mIFJ;GKWEulOj9r=4&1d85^O0Cpq)`{qhe%{4U> z-Q>oCXkR#5_`RP`*-))QP^eM7Vhsep>fTU3twB^E+?-X=34~Fe6o}iOJy2qkz-|J z8j)x-$itTk6!$n`*yXKhnCz`K|E7QuxQH@-BZpv+NK3f(=(rsOSEk1tr;H+AasAS;+Gr2C6N-ENgF$LyWueDJygT~%&mI^$KF z-I{3#G!huFS;A6G-*y*sMVxnccMUM8d}{utj+3M^VAqy9u4Hv3VW7=9Gat`N>$kzgcS*;%>Y&{rzxkEDy1dJMh6*zeZ<|#UxK}ahrY>)W zDg3{ST=tEbkq1btmy4ob8#r3LBJC+z-5%5MT_>{(76JCww9D^+X!Y9_k$TqA`V95Y zcs{e}o%dgf-;m5V4cB9RpsqJ)wV#fTI!u*n-4Er2AmZv8ntMch&cMt;+15Y@G2)sd zmc{Tz@|8TtCBGlD177ZxRSkH1ELREPvgJ6FXq5ybdGB&S^u@VRAwHO>V`Jf#SxFHD zvvh~u){RFWKET>@?II2kc*s>%2g1e`EXNJcp}?{D4@A4l6G#?%rKINVf7$tzb`|G# zZZl`|TAt9~PN{e9C<)%17Hy|pD>jm>s|-r%J$0XO_AtRLo5j{VZ{38$IDj(otE`*7 z{KMUngqnKutV`~KKNTjy;ErDdXvnGRY|(-&rkRcM=^emGs&=d;or2- zt6^V#6QK6ALPfB8&WctCT6oWq zXg7uN+HXJp!jm++7W$UQ^C}Jo|~u%tv@NgKupl_TokNtJ?>d>!6v6% z&lUKWk&sCCMIINQy+D2q7sQJ0Ss-Rg=3eW#~bt5A!D^B5>{Kd8R z0LFs13Ni_#6&iru%~4N5gtO$8!+-#qQHq;M4UnR6sZ3z#{oqCm+Z7dfTL)&8|96jG zI}Tpsy@I#Ba+61NgMPTr9)<7eDt7^nD?bBF21B=>6@T8QB4$DUHWKX0Vu(!R=`^p) z*Vw;`579$JOG4`enXV&rplZ^K^Zcg$2L5{@FTS%k)yvI*l*0G!ECY2#kWBr6h;R-l znt6!g4hX&lws--~W`xFlW9k9@`RNUw#1$8e)ex=C!dwl_(EWZ7Rt~jVMCu$x_Cr*- z7c^9T;&IL)R71aHw=5|xTk?uh*SGvc)&6An{7sb0U*wDa^vsjll@@A6B#>onMKfk| zr?gX*i@U@K|NV?7@}@JC4ee3oWE^9Q&3u|`#w`SA#ss5a!dOb&Bi#MSdgBi2gw;}z z;~2z0x->$Hjg3tdg%o`!w8lk>;hpuH#ldlm(*#DnYOJRc{EW5GZ>^WZ1DJU&!E0$k zV+i&V``Bc!$1O$87hs6PnJG$cls-}e9t`!kleLqqLJM!&1b z7RUR_SR>r~Y9a-T&UGzKB+>$i5E{dN@6vd1?Dk(HbbR}xumeHGMc;uV`6arPZn&a9 z?d{KI_5w27A3x9qe`3$~e_XSyA2(5cJkyl6f$Ue*W=jxHz{c4#nT_s%&!zYZZO5`OU6de!(gsQzpqW}Do)er| zcUHq2XFdwVnpz)n!gNM&S*oaFJ+Is4#1C^@6e zOT77(Ru!gk^xKHl&N^+z-2(dCH;60|bni~e4_Dg@0+ShKE1d#9s09zk)@)7JUw3)q zn{k!V%KeR8lljGyhy+S{+_Omg)18B|xe39ub}r;qlP5)XoIzG-z#4yS1`da5Gcd7tj zpzp>4hU4B9mRbKzGhWXa6Xp6P$O8Hr8Xhe)D0iql@?1-E*pT8wX?3RLhBQ5WZAcpdQbx*X&7UurC#C;vQ7TB2 zye^<-)Mt0biiYK>(8`cJ|$r~H)(^Ef0Mf`6X2MqvR6 zn_m5*B+uX5;&i30a*G1WYV#*7fp3J^25vg9eA z(x@RxuqE83n3k-1meRfD+Kc3!@MGR9U&TWhE8KKd4O}%TKnK?7iV&@8Sl$G+B|;(IOnrg41E)Twz35D1~p`mN6-GUP|hM@-0mU0(wWUuou{jBJ<{k>-l)<#%LQxb4~xV|w^n zqD|stZgAN;P(^`{0jiz-4LUjk&tuZ1K>NE;{JWcEzS+3Ar8r^#_nn_2W#cU5%R-R) zESrC?IY^TTKzI)JF3!_pymZX960dwaWX2n5V+rUQXC&#MN0h>HH>AP(pX{Fkkeg#_ zln}%XX<^v~JDawy_h)Di4r|6?fUldb&pIiuT=aL|eFK29aR&>iETWC!ZAA~%+N>N& zV5!}Z#7L^i2U28P5ccKT*oAQ6KWCuVg^(`%SBL*)U;uG`B}9SUV1p|09<#*7Y945b zWhtT^?|uNj4ec-!%?2XltmK_;%A3SCqn$gnm^dzoZ)^7e7x}e~tXv(?ax7*z_)ZuJ2{5J=2RuKU}v5|;M`SwWtNlMFQ1&Zp5 z4c~n5uW-{}uQM+nb&iH{a5V?c+6G5KbUNkZ4&>MS6m^7dh3{^k6dwIsm@EDkbnDej zRP1{5th>xv_}o4B+$8aNyfSoj=dRG8A?>ZSX9Ewtn}yG^_E>(~?NOG{JOg|>J>c!Y zyHJduXyIq1jlE#C>Z4>;0DxaZXiVkbGv2so^8azE-R|qfQ*k`N{l292x?Bl>(ercw z){fs#2X+QT(KUvrrhGy4buo7t+DN~=i+CqgJzsO$oCu02;cp0*Zh1<{BUs=a9mkiq zs`qHEdpd7q0lT(N5FCp3q?L65NbL@#w~!Jbq<85KKgXU}E+23P`rOW*+<* zw1_(&DmhH?Q$jJMkW!w}k0+#vlf#irBLckw%gf98gD)>9tk}BbJ-ksEoebE}K3EN_ zE&!<0ozfaF9||B^eeEWs9Fv+h;KxV#X)JI#$FwR{9CM{WTs=m|j4kT_%B#73#*yF1 zzmVu)T%QmOrvFr_YT(`>!|?nSnXI^@D_{du{;aCNAo-;Bgxk;lLM5#?XPo}Y0bp#1 zBbV#9c@sE|S8Zg3yRo}0x}*lIWizOk@2xhu>@MiSzvYS96nsIR`FGMYs$rA;vN)jt z{5SYm+z}RAv2nn{2XRj0atIOPwlnmp_@j{va$%i)SWiRCw1`(TLDh^_-^NP z?3X#;=p$|nthmDdMl$KQHd-hvE3?wOiOZMIN|mWt{K9S}|BpV7f`S4axGsoG+0Y*U z_xvB{;Q|eeB~ZoC|3tWSTNAV4@6UUCL58~1ppe7|4;%z`nC00F`ophrZes>yWg*X3A#wtORKXS~M+EU_7JYd}|}0%X)k+Fb&afiQy6muII;$V`&0q`{sB z2hN`h^Z`of(G(yUNvq;JVC09E`84JQ&;p#QOW{|8{j?Npk`IF!Zz=}bH5SHcMs16|d==RHg()IKncmW( zAIr`%SJOP~6b$`^J#^Sl;uDBG`Y3^*Lea^2;-QN&s>A1_)g!MmFy(fo_b6Npsc^v0 z>tCVNv-Pa4ufLH#IsL;lu$58({4FkZ8)`=o3d5BH*W<;1kil^?;%w`E3^UTCet7ww z8yjtnGF1iUguCL8>1au)ePKBE-8*6G!Ng0JGVISn3IXbjGMH=cN4u`7+o;1Lq`B38 z4f0Ft#RP)TRDl$L@qc(tgDv}@ZMj?+ArI}qRFuHTwx)KQr?6lIszSr;5BL6gO^E^s zxpi{w&>-XbZx;ZmO%Kd?7bCd2S`;xy-rv6Frrgw&zK`tylsorkye-q7da=4nmDl`D zNiJJ(LYj`bkb$hsXpZM%QrDDXLf9SA)4sYWW@p8?nm8B1%(pKiCGr{04H?&Cf+r1G z{Co=OEbG>`EkUi2{)USF{sOPY^wS1LSs`CwJ$f`OYBUix$R`uDv_I`N2u5~_ZA8Y) z;@PtmKhDMg428xrz#K;~r4Ad^hAqn?KisI9zz&CX-F9tQotEdy`Y#6xfWi|2>8QA^mN^ z-+K9fm2#TFzJSv2KX2~=%p240-2VC&9q+pea)lWMaywD_Fyf1G47lt~KlI@^6-a?G z_JZ&H;3)64YHv*w$wN(DJM0|>6m7=LDGe{9RVnYr$u&+3XS1~fghQYJPE1iTN$&-wQog`ayv7~C5R-I@X4otAtt2o22xdcEaT{&G6`rgs!~(7y`8Kra^l zh|8YraBcBU4>*^d(V

NBG?biE6gZY)B_>iW9rXe_d<j0XL{+Bz6`U;*YtO&7T$)vzj0k$92KVc$PvG@J;=$Byqo{`@5>kc%CpXt_IsRN)KG2&)zq`-dodHrkbs?@Ww^^aH zH|a=tjwL$nDQ5N$UN{-BCScbsDen_9CO;8sVp3YGP+!|gjbr&5`+vc65D!B-JFp33 zD$4YYR@3t5m4b;a8ULFM+vmg`F-TQxL&a|Y*Max;pEsU40UR)cT-fG&2J?d%pU1($ zJy1wh_AR*$$C8dL^9J_|aSOGdVD9v?_(rYt*?Wa%!=P1`d&+@8qxSnw)pE-46^*`F*eAIY51A(rh-xXwL67`scFmnSt_1?`fMFt{rpD zZURfU;byyHt%-G9LFghNueG23{k94g#U_&rh>-jQfPnR#ZbfSAR*}b z;L|qI#2Ue&AZL=mZbzB@H)mKz{4s;9^PVTncP#M0DZ8MJzs`u=N}$^d$N}#UNs7w~ zos$6}SFCz#TA%&#r>VFsD2eOByfo>8+ARPfFS!U9>)!V;&r5rPRJRmuaw~E+fz^m{W_z&D)^tftbY(hNqW(WLc z5;`u>0li;3z9lzl+!ld5g%O&OK&St_EyMd4C3C|UpAfGMk(G&nt0}2kDZrg|Ql04k zr||_02}bpu(JS1|wS{K{^1*f*xEu;ZI-yW`0RP=Y> z!k%~IOC;G1(L4?wZad+f_^G2u#N!-*GRq(RRdbmJkQGoZ4*mw|cD!*s!KodySPFd_ zUHkjqR>=GjBL?fTL@}pXGe+J2Z^$%6q|*y_b-knlNgRWvR;)^QsPDj6y}>K5V1rwr z@#jDEQ~G)=j5AX1I4dD1z`>Ce<51l~-UZ&u(h_fbo2YmE3TpwhD+kD)R=$rP2N?tu za2`U$r&Tl^fOYmwOMcmtk8#;idLoSpSj5p@4(Rc63Qbv8%f`jnt##8?{2w%rWcejt zF_;TEefEw0T^dW#5=C>DZXVbYgpXbsp@6t_+vudkMH*nmZbA%}>2y^Pb(CinERAi=>hgs0wJj(7j>4kIH z)c>4Wg-s2l&e4N%5YqjOKQkVgpP1>8ouJM%*Mg6Y?R(2Kg(!TLX8n(DEo|OoyV<|r zZ6=2(wEpVI4aUcp-naf5C@}Wd%lB&VO7&!y11olO9q^)KMtW@3P=9VVhE+y36yR3)e`e(q@TSDX2N8c`j(|-gb^+3Ng%#>PKfMUi0{Kvv* z+76$MVYh~u*LCj%+q=XP1oIP%-IJd(T4%-Y;fi(lx*LpFC=V1u;$&2S@?(p_LA8^H~9GUSH?&VW9nX1XGnSKe_O2VMMq<5*>5^jO@|Sx@>z@cqaRw1fwPb zh%h*6=D#Fq48VaC%&1Pa|A+#8iZRL>3D8@PR<_Y6vb7Hyq$TKLzKCwdY zA9vFWC^6%U6i{{sNCqzWJ*Wuz=pdFx6Y#QA@W=0>2I;SrQ5r(eNnkK2@dPYYE1?3aR% z%|QG5*c<`k&5+auXu^5NE|S=_kJ5j${n*nNp8H9+9_v`wmvt~N1$XA(P3^VIk;4?; zcDs@7HZn8Db;_<0^-3W^cZSQzRwLWmtLgF8hQzWnI;dN%d^dPBNzG#(uc@htL2b?! z-@srzbuD0-K@{ARD<)U?tFX6$`)++@etyr~;x=Agf^Mw%L$3L-#LUF9*RoLXZ|Av- z0E66EQO4Ky%=m(Xme-#%L(uX?(rb68MFS4HR9AU z_xJDB%HL8|+_%1q>l~BsByp^r&?E&+r{6W)*Fn=2g8^q30kM=8wlx9x9BAEP|1RY4g2M0KXI`IEM1h}W^LeSx%o`{n%x>jQ>Ze@ zosj9#f_b+R<;r=cFon~Oem~GJ+^OyB(e%=s!e))Ve*WkMM2t#Cn-&a|peH zXBk%R-t7_ty`odiFs35Fwj6a$=?<}EJ)(4BC%Qzj!}Tbsa!D%WMoDVLXehXO(Q;|{ z`-JflbA&yJZ+RF?e5rPb=4FZb+@Q8(=V%aqtsvs|XV-*&%Cc($Ipa*6z($YU{KY#i zfnzm6*;gr1W}ug)q;1Cp=Pm2()D$`9CHeaT;@^y)KR*Q?_Gd))sqcLS6c;73EWPI@ z5v3mN%2Z5n%J;y|QO;!2kI3$G*Jp{c9;)v_=sLbJ@2ub#sp4F+`yTo@kX*g+sbt?r z(C_8xJ{Jv7lEZcT4U~I-3GEHzorHpz%>p%G=>|+*;=O>jeA}x$H&|l0H#P2u1lv3Y zZ=Lg_?FO3wQqhpWtK#q5M5RXzr=cj&iCYoa_yy(Qg7XE3O~a8R_=Xip zhzf?W&~<7TQ6HK+2E=A6k3^lBh$m|;Cgy-f%J7lNP;=9dEP5e}S`zD$p!Xdme7e2Z zDgXOx5-9=g$TQ+gz{GjS%looQlONJh?*7VFnZrleA+0jaNZ{})g{Y^7ZujF;gE3Ug z*px@dbNHmT56ul|Y*D`CLVHppL|R!M-oeL2!I>76(d*6+EWAC-vUwcJA%O!3bgZlP zj)%GGick#~_}E{S;*4S(L~_I(eFXouV=mn#0lShoOa;|-V4Ez`c6xkio?)>Ne{?zy zzo9|!x~87Ucsh+cqmd}Wj0SF>&umTWr04%sR83!eiP@E}+zw}(wh7H%-$XW7exc!g z*JaoY$*(d7+>uJ|=Wq3|1*VGa;+z%kwr0TXvWHwF-;YA4Rr$kuV5F2o!nTileYUC} zcS)}4o5(axw3@hv-QpsL0Q(i@_;Hkw<*^S+%glh}`%x08Wt05m?SX9IFH(9O?#;>a z(v_LgT}PJo_>#%()-B=-)XK;3taE3QntYw4`P1dN;mf>o1?0}G(16E46+ApQCU`1K zI-ZO!z`T&!Gh`>L#HZO00lL2SH*L1PCjDTQe&XSgkp`BAN91f(hk;I394H9mw9ag9cn?{K!iQC@aO$5y^E^Gd1H;SZVRNE0@= zHTm*GPH@N*{|9I#R(iQPrRM`p!vwttJWXzKVwLIjMFhaYp(R`q}1Z3(BWy1zv3|QqGuVg*TBzz9bNq)_?&Cf8| z4_A9rl<~DLlXl&sk3QdL^lw1tlY6rri|=SGc#+6fZ1AWa6b`lqvUNC*x2)QKYKo=@ zYsGvg9n4$>nhxcgch^WaGx7`pI!11Q%QG1d9N6ukC*VA7sP9G)ryeNsul5dGm9*$( z8+XrmI${1;+y5fv!$=n*WVCGI1+F!vcG`t|GO8C~SC8@gkBxOS@N}L=%{J8>i{S%e z(bWqY>VvZEY!?s0>U7qgRrL_9zmaWNym8}kJ=_$ z@+<@_PXElE`JFCWoH|st%{CYZxZ`5Qk9RTbwU)|S7_v4^`z!Vc95ZTudolvE23+lJ z(DE7M0XoX+ig8}RXeoEl$(3qTRm^u3W3$_dvNoZ_$?b`EAiCnNmsE`nUZO zgl;`3*dU>(7CZe-9XT*>6Sq?>_XE1oU81#ON+hM^q^EkoR@xHN~Fgs%2@nG!;*ersQv?2S{p9VjH)+IleLF5NLi*fsUjStTjX(Rs)h$yxqF|x8G=Nz0KlE_>lY`jCpC^mu zO`jOtBz=}}!++p?NQ$iG{G_UZ_vWK436HbsN;6za>6i*NSx_-j2=aF+Vz<8(n5)ZkOOUa2osnWz-F@_1v5CGTwSN|7FjlSwCG|9)gd`Z5VQ5`^vxS|pG z)0c!D$!n&Vg`ATYhv&+1wa4>T|DPc?2}Rw$_(3eevB*lLb)80m+OUBI%RJ}e$izQP z>Pc-l0HEfL<&WfC3>M_yoIrWm)+x){N5PtOWF9RlHr`)uCkWNp`7}mqN0&DckWHv@ z;^z%kD#@LY9FfRnI1^MRjk)E{gONN-YBl6M=tHub1E7t^&D?SV{VUIir*98&V`<5( z8ep#zz__ep$}^6d3>I1XI~ANoax!1;r~uHe@^a)?GwZ;4e|yy6R7+s|g|VlqnJW_= z{-_6UE=^){#0i|>0Rv1#((>y06TgWcHi&&muNQm3uKLD6-d;Q-59iC?7n(9fix*+M zG~M%<8%Qv2o0QcInm9v&LJ82qd{*LEF+r9VhQp+bfw_gWs+GzyR5&+z2@+{FP1}^2 zzQ0|xJ~duki3qy(<$wi++OWK|i}>aS5i87Pn$R$jjOB5c!z?l;I>58}Mm1{E^hq8l z9+O8e>LN4@OS{p0EOX}hn~LH_DmCz< z4GDvu>yN2D!!5dgB1ETsni@6-7s=X$GD^dwsRXljzC^*!(q;wpqcDex86Sucg|(K^#^(~H&y@R#)xw}}T_S&AgEs6d z`?vYc71ZzAyfJ9IO?cWrJlsvbI)H1@0IMmB4`H_wz&&q8DzFM+ZM!itDzQq&LcNrf zU%9QlM%L5FPj!3NZ@?V)dmA?%-UL3*OZ!;~UO$>#Cxf+wcsGup};fUd{_E`o5 zu?3He10Qu_2TCinf0hpUoZ!?z1gb9-u)K?J(lo`h7aAJlV`{t0XVvzCvefkcm4za( z3=4`*>#z)GW+Do{6?;?!_saC4)`sb?twHbMlihq14g&7GQJAv@fG{t~j4E-F?EQ;a zj9;-k;Hhcwh7`NrhYmew_WY9H>9z{0s!yZ;?%ZmjJNhk_xP$P^1a=bsvi{l=6@Qz& zaiWdmvZkx2N^mu)?@ONSq8L)&32}fXU=^GJR5d_4s{9%qfKeYCD)2iWvQAvBUBK-W5UiYFV=@$drI*_ZjJLnSoz*BfX%jDk`H zBG3d{`q~c=Oq@RFP4u4=F5%GhPpdk;{YWw?Ut~1;e2v$zIla>#f71f9{1WHBHw}(m zzdD$VeQ(#8zF8EqrXkciYKxq06X`Ql1@qT!b07{Hg>oj`4FHJo!idO@c|z$vm*98m z%Cq_Vllw;Diu=->5IKwV1x$i|7Nw1TmV7wbu$B2Zle$&Cpqi}DiR65wqIpY5Ihpd< zJVDBQIn1cEZ%+9VR3imZ#k4&|keMZRF{9dqQ_A0hUj{d14a^(=3CS{z!cqNqp0(gU zyMwa(PNrQamP0N4_wbwgibF#=FccOx`Hf7AQYBvcdbbL%8X52?^33!Ko~R9QzxPc5Z13n_74=u$3BwOwk#+5JGbPhD>7FPip6h* zp#T8+o!&IZ~hlo$w=V%mrizHbVu*S_`h+eqD;iDUL5haWtisL!v?9h zT-%6b&>{AG}?mbz;~}qA|nj< zN0h8Q1-<=Cs296Yw|5V2o3^rn0G8xhiiW;dh!LHPfq>ij7-*HB$7oN5Ay(j|)Q%U? zfj)>@F4Z@vZq?4}0jH2JS@G8SdadC*ZxZn4PX8J9dC=66Dmd(j;7J;dg-^m(F%ZN0 z-HrLV+iyJ?Z{RqcAl~$}tyjMK#?D@&lC7&d!Hx1gVv4C%R(ML-Rj%>oW*AuexV!9N z4z}HI^|vqwjiRp=yR!n~wq!YS!F%E%+Kz!?wcKssfkR}SRlyBTmE0)sPuQquEKV&Z z$cb%|_#GwS)hfCLKZ0}Wcn%w7xYsEx06}UllBDqbH_H!6QfKGVLJlP zDD@v4c2=rei|*xVgHkaKndaW>wsd)k=5zgil<`dBVN@0^(#3m!n+*EC0a79ZOC1AJ zYER8n-!>O4@0_eJt2;KFp$Js*u5ev{7zK_t<1e?;P4$KZww65Cn=#=1?d09G72czF zItK8CJ+3NqvW{al&i245pRQ#zeSecl#`Q5Ln}E=o;TI0<(?IyY#o_7A@fb_vKUY=y zK#stVfY-5tQSi(QzA2$&WhxLrTE*HtAn?95u)V|7Bnkaow1aF&)G>~m69-2jgR-Gl zG^PI{r`pr@B+tkiguv2R$q=mRnr!!=j6YnB1bm?^0^UHo5-+LpbHIqwnFzjKDNJ`IpDKQW@8;v43~!=H|BT`c9deGf|@=%;#cJJo1xp zV8hEA+hM9o6b)1X{tfD#6unux1{~&35?JpAArXh$8NBhgYD!V9nL=T^nFG5Mc^w}5 z=9DT4qX@{o_+dA24u&SqH?*88*{NCjKlbrH44-QfsMmb4nv{NRi(77Uj1X(S(e z4(BSN&N>&FQowgJ!R|D<7JK+mv>mN)x9PYQS$%yx1N66wyG0v=k`~~2VFqLb6R&^2 z)CR&W)ER11sd=uM`ht4SU7ZneOYJ|BeP7py{fUzy4|mmEsnza#-_lggKS_Wr11))V zF7MX7cdHn(&<2+20U^C^E@f!nD0bv+8MA^B@*NyH6iVlX!`5TPCui6M)PW5@sHP|7Yw?(Q_}N}VKn9T4jTBhM+E8`H1=W^p%< zCoQLOjV}|?KMpz^k8{WVl$CA0>zQ?|WHF3ZVhVCpU9!mYQ`{)NvF~=II+oQ`LPC+? z7d@Rjl>{_dL4F`)X)-^AZj=Y{mnBl^q`fQcc5#ROh&K+JR+xHPSh9i03j=2ow0LKa zUxj6=SIQ*vY!%w(V z79e3#EdTAz1C3DHi#wbv)rr)P0gP_xZ_oGdiIbO+bs8qi+QBYL7mo-o?IZ?3k2DD|FVSq{4C*)s z>Wm4aaqcSCt7-5y#d};A3D66IQPUwIFsIf}AstqKYWTD6Yf2M?-ig2OM!>Q6FLletDl-!Vu}a_EGwUEWZ25z&9Xh?-0<>~3C1Lx&qQ zUmuh~Bkb_#$NyPrFfkDiw)PdETuo;+;WCq9c1sXeL3SkNiFq9C8w6#3v8L^$dFi=T z9l!O2MeCq;;IwI+NM|j8Z-Z!voT-RXa8EYMC2YGAcvufH+Q7c%tkw}QIV`97STsp1 zjCeXvM!6atKY#3eRYUGo4D=aHfQbDr*r5FM_1^Sl#9*uANuGY2w%d?VBB*|A+wS0a z>ygsoYj_=X0QIF|>zwL~7v8DI*BX+M*VH|p8V)k&u$lWZ^?5(JU}Otuy%A@*9Q_8; zWEwcUqeth{JFfM=Y#+7C@kU$6glM}osxNV{<>vo3WwJwdM>A?se#g_mZ{;Y6$cXa4 z_d$+%Xrmg;|F2w0ln<;v_S3X5K}K7Nl}W8dSm0vsoX4Jrfg#zG5f}NI?2Il(znk_Y zObfW>kYM%ighaolPp;5AfAYo)Yvq@0UU*{K0hO1N_wCSTddpS6G(%F>xwUE|3geXB_~& zr54!*xm35tMQ^Vl3>DJ7{)dTgEBLhWupk672&qY14l+q z02mQDH}jj5p5>CT=^h910Qw)6+o~}_1Nhs{nSUVqH6qb2eb1LAk2QiPU)|tJ2N?-Y zlSUVljv&IvU2QmO87s@lB43K-4#-JJVqrlIuq!bw8G@>k`Fcn-oC6$AR6TUcq{Rhu z5f5i84OX+(*$y$u<3**(fFiB1#ZVfGIMw5rDoF^fZP{mO^PLd5&7RpaMaJk-W9+&A zZTBlU$eT19AkN7E15sAybvY3$pgU|u$NYH|-6c_f@sESpoo~03M(m70c90a{MvWIP zLVoph{$5Ua97N9RZVouZPK^C>)zN83kfjbh_eC+|U|Z~oW+gArIO}pIJQgt@_KmGk zGS+=8;kGr+zJvke6w0J-=l+x=D*c*jQ>=0#s3^3Bv@cqHwU%MJ|?oYvt%&|-*!5{uPVFd9dZoFu}wdyRVg7&fXN?$Ybui#F;PwLJW?^c+-DCiRq5|v;c z_f2iPs@#=U!eF13z&B!h7y)dj;)rN0D^T#cKb~91*YBBG--Pbr&X@Apj@80IX@*td z6PTr|jcb7Z@7^3+Cj0dMZ;u-A;$&k8Z;G|G6=9L;$ZS^fUp(WddAba0cVAwfMO4G1;bkF`EFp4ny zo9;{_PP6@3r~g^38!p@F%wM+zs~%z)4LCA(tkg*hDhK0|v-+EsikPFy*ZPZqmZb_9 zt%5(-@}B!#TGuVq?Y0C))P$+X$~}5uu}EZ`eBN3;cOMVba23p zVzp*t=0kH7uDs*AEc0}<_w6QP&R>pziIn3-AqJTBVWn`H=r#an++`opONhB@*=aH`CbtRn9 zBLw3|l+9H}gy$qz=n_BKFb;=~bo8)vlXQJS71#~O(zdI6YhQQSg5;qx>zaEz5W?M1 zk70Q605ZhqT+HjTR2m(=0@BUR$rFPn0ty$0c5K~L!Ui{?+Au!Z0OPVmt;cOqejyv) z(zw^>)uVq;Di+hZDB_rCP9Dy&ss`AS)47#TLWWNdSo0)ODRNrFyy?5orl@y$tUEjt zcb_$gwV1-wa{VSxv*CE(1aq?*u!W(K>QDF`Mg7d~^$T-fWhBUx>G1=EnO$bH@jq*{ zc#2t-#0K^}E6RVCki3QZ&2hxP`lf!D9IxeU{%d%y_%O9G# zdU{D1X7v=cY8BFK?A6pi(H#z@G#d4-cFi53?Ub7sh+Lo-at|N6sux0!EPF7*!|8K7 zv;9q0=Y#9LJTV@F@|cmGy$IB`EcjHlgfaN$#d(3>ItI%VKfPuk-w_eMP4x&krQuMG zi6*Aid>2=D?X)BfX>%fdK(!MsQPa&6+I`5b1H6)kepvkZ(mZK0;d~2?{NeR!e}cxZ zAeLw2gHiW}D=d?Gc_ zo24|tb5ChFFQTqw=XD9=%S#AzG`bz0;mvyc?0YzF-t#L3fok#-9J@{mZ(AgY4Pxx= z-8T`tb+zLUZ>Jb*9Wuokqdy}S9B{JNG)uxxWPWq-uMDkZR7m2|c#~)W7(;O?wJETo z2s0rFZF;s`(m%UNx~fP3*WFGviCT<1?y^s>=_1y)PMD^^*Occq|M#O~VZz2#$BKr! zy{?`fBQPk{Ekx2d4$=Gnm`MBa{DMDbC+=7p_<+w=Xe-vR7vyIG%VXZ8wUV{JOs2yRfJo-;%YL3d zdOZay5^H_92ELdcuO zjiL=bYA7U-6^65;K&QEx%1RB(t>fBn;KbrxX>(g$JwX2+{zzv1LDF@l-f6R+9e?q{ zS>F^Nt-I0VfIFB1BoXBYVk0JvEV~zLJqi5);eW(ga&*$}JTr(JUNiyx&;=TX^GfDt z2RWemj*N^dU$91eOYXhDx&s#r4qO+=J+-09v&WNWWLlV@QZIyV`i+e@8h^K3?g{lGLedyIr3f4BOH$`i9+QFvdj!N(DxVP5Op45r1HN#(HA{EwmkTc_L zPfOxw6XcqTZq*@1>Mf8BJ`#)I10CwGm4ti}b38d){g^ZLS|t37)>ubKH6TPdjT}^) z35THMi$%GU{Z`ffPG&Rkv-~sBABB=p{1du{&%YeQ;y~t_Ahp+AaMBp=N>X2GV{{qI zD;P1=u~OAREfZ zL_~G6WJpT7aws&#Iq}>}4TIailW3lJPwSG{cM-PjT^Jms;pDs@NPM7`Pp^u&8FqQr{E6E_k&>oQmtP-Uzst}VsayMJ4_GB% ziu(ceZR<6Sp0+mxS|5RgJQZVYy*|*QlbTU3=kBXg)!jH6CbL-#5*}wU3u+nHLPGN; z1d&4L^v&uv=QKgzKO#Q&BOMlGgEi*{J%EFARS$`vIsrx+IU+f4S6~VIObn-Rx`g?p zw+1DSxTK7py$G?FXZ`vw3UI%&+pNZ&`FQc0I*el*(|&FGRF z;_~o)Pj&&`T=K96=V2n}1FH;^3om{1GJ|0BR{HgI>I`M#XBlzVRvCxwX!~{Gl z*g0TKjV=07H~H}J;NY8q2GB|XBJCh~6;QjOG)gfIM#}zUlANc-uNC4`6SdIP)X(R_ z{la`O(I%WYEbe5dQE@VC`87d>ka74;gCrK1LB$0*l){9vC#R8Lug1F3!r#i${%GRA zCQ!&>Px)(bVUr;P!|xb*;0zc29w2C{+@GslJ3; zIJl+f*Zbv2)$`QZzTWkrsk(UuS}HGTWxU~Fu$1K1N^kTgWs_3|2c#*G-Jy{^_VVTb zE-#?U^;D}0@el0p}xP9`9LnU*dF@y?B5;oE)}@&Qef_NT?P<8B!7n+u_|GT+&o z`_29nAub!#f56@wy`JT~R`M&G@3%=`}pXPe5`+A5Jj#TiJ6kXir30q3q$RA{}v*6E?kIph$?; zOvyDExqgjZ26E?J5+^1IvQ^-8?)|Yt;|^RYei=E>TvTj3lCDNfLn$qhn=KleX~!MP z0$E3|S1WS>Qy>(^JpO2=_YjLuM$&-@1mqB^bKNO^>@GM%qEV90QHks)$z z<$9@VUVIoa1BNpS42TUFM%Il_m2kzUrULVd?)1Z5+yH3UL~sx{#g>A0%1LMi(2sS? zgMZIOHimHE_-Y$RT#wdl(9tPSYR2G0Tz9f@4{KO(YZFP#TbQoJ6_Rv=h6qMAAhYoY zkME)m^=OUA+*b;ZeP9sDf#4B3ad>7C5tZe}vr5Vv-y+-uF>kepc8%{Eu>m@**?+iO zJiSQKja;Q?2Xx#V6p-R_f@NJ;w5Ioi$o``YzC~a+(Q;-JXd~fS-tCx9?((L)>6{;ti9L6Ws$dE?qd#B9}cXm zIeC<`E_`3Kg?LXlOC>lZLTHkJVXkB0h2eAFyLrK-O(<@*O?N6?MUo#1t81r(m(#nl zF&Z-m8c$&XRlp{$(7O=8IvWL*(qC7Y_yTNkHSAPZIwq_laeFUEM>17i^D6HQ2%LVZ za-KAHFNZILiZ&-b+H&;J@@|@38<&U%QhU3tL8-pqm{Tv;4tcO1JBL9RNavI>vc;W- zacolZeJmCG{J&Upb{G~|K-m|V|KL1|T6v_ABsW5kV^hYQ%4>x5OB*C7i`RclH*(32 z^XnQJS!&`3b@3@ix#E2aUpJ_irz{;U+XZQ7?7rWwOEw-1o3j*z4A$()+*|{<=3p62 zeqoR%;@H170?Lr51(bg6T}-n-(!`Kk7xY8in{_k$sZHXm%ekrA$hcWUAPDFl(ELE(ceez7XuYkdPqUr&W!} z#HoHPx;H8$P2(NX|eHTTr9_h3^(P^|hsL4{i=Oj{7wMd2}6ukk@cstwn9QW+C)3e{N4M zKVRD9=KHUeTSwnQxr2dwwn-I!%ilCDu0>2?=Gz1w$zuzgjJgLOXl14#H&#``mQ(kh zx+Voon^O{ZQ5w z%mw1$qP9@yf@0FT#I;+9-J+cN5FrV8M*2B7g$fLzF@9rNDmt9bPk%M3)%`Tye5w+c zchF~%AY9pCm}Pa=C7-xnl@-r$3Dq&AJeerBKtQd{OXy=;R~GuK&}*jgEUq$-x>Kd1 zvMEo2s3eQ;5NjBOg9oHo)O1>)#jEYG+QZJmc+1UKlo%{=TRza@H^CD?!TL+!_*nBM zMJYXQsxD}9<4cxB8-d-as0PpehOMC{ttiEKVzez;=?x7X}liG?Z9OEpsTMpXCVmLEx1zGlg;A<2!3URbPiHlJI}i8E^S7ov*pH04x{ zhOE)6tykQ$kYP))L9egZ6CwA2)X@pfr}j%G!O%bd(zqncl3M=SXywSpM>WeM``}B} zb(6)RSB^hdit5z-!44nrGc;4;i1=LaEbnmK@!-Wn0fPejwl=WwEidEX;QGo3z-8yF zExjvxI^B8bcP6PBBBs3g`2_`Agr^6k?faamx+&@wg2rwz@3QNoNhOGa5A!h2hsv(N z*rBawmv%h{YVjGTs|eIh$WR?kE3CM+P+I$<@yiAT{2iF*?0ZPhG0+mNS((R19LWf$ z#$WQ_X5BdV)X`n~vWtj{{`da)MCa44uo+!x2L~&z6;{45Jk=jJ-?MNI3Uz+-Rw69^ zwHwgY&IahBT7`3H`1b3A9uVu=m2ug%^^8$BrIDadao0*ucM|4S zMFeaHYTlXL^Kb9LhPc3hEP!@kwbwdL=bRHypObA1k8E$X4rxudl3y+)lcgjoz^?p$ z;}t9S){J^ROOkUYto;=s;R z;?UzLz5b)F?5A*`gu%#OJa0A1427LGxlm8#H9&y4`kj1fd((_yVFSDR!ZK8Hh##Kgbyfy zZwFcaCPl6=$fG~da7~>(S;n+=IqEZx+EK6iTOolU#R0XGXyH(bDDefkN>Seis9^Yw z9m;2LnS0~#fyyIt;>%^^vwa>r;C`VsbSOHw9m_MMF!1t^)!fkEDhXu?_8S(R%^nt& zb(CeCHva~vnca7Dq+7E=)p4X-@;8DJyO;sD&cL9({$?ik4%CWvTVJ;~J8<{r?Y$>1 z-5}uy-sD~QMR~ONXYh&3njo$fd&5$L-%$H1z|2g!h7|{%pZRoZhsrk6O9KMR>0~d> z0S;^#S$|;dCsd3>Cd%4vK=+>>+yC?9D+9Vy+{gb14G-or;sA@p1gwwzButfti!2e{ z0aqKZwckvu)R*T_hb%73N2pR!J!-BOjR_Ni!{C$V#pnH%#-cB#m_h9o&x>3>}1mH;{AH2 zMfx{m86?zVYS`4OuROkQ!Rcbh5;5HTdY0S{X7Zr{f%}|Kbb^_{`d;fJMyIr-vUqnc zXg&_&oKJ>K!bA@i-@qqpmBP5gTqq=bbP##xvRo!m*rM8=3U5upmib%t+8U}D{$ZTT khsx%H|F)G8Cd^wr^WRQBY+5LJ%mn;&&KhXtYgqgJ2aK1OssI20 diff --git a/Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg@3x.png b/Riot/Assets/Images.xcassets/Search/search_bg.imageset/search_bg@3x.png deleted file mode 100644 index 4525d4f5a5ec133b12f910c11fc1e13d4b256c8b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 67320 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 Rra5#-U0LUL*-fjE{{d|mAr=4t diff --git a/Riot/Categories/UIViewController+RiotSearch.h b/Riot/Categories/UIViewController+RiotSearch.h index db29e0183..ac95a4139 100644 --- a/Riot/Categories/UIViewController+RiotSearch.h +++ b/Riot/Categories/UIViewController+RiotSearch.h @@ -33,15 +33,6 @@ */ @property (nonatomic, readonly) BOOL searchBarHidden; -/** - The Riot empty search background image (champagne bubbles). - The image adapts its width to its parent view width. - Its bottom is aligned to the top of the keyboard. - */ -@property (nonatomic, readonly) UIImageView *backgroundImageView; - -@property (nonatomic, readonly) NSLayoutConstraint *backgroundImageViewBottomConstraint; - /** Show/Hide the search bar. @@ -50,18 +41,4 @@ - (void)showSearch:(BOOL)animated; - (void)hideSearch:(BOOL)animated; -/** - Initialise `backgroundImageView` and add it to the passed parent view. - - @param view the view to add `backgroundImageView` to. - */ -- (void)addBackgroundImageViewToView:(UIView*)view; - -/** - Provide the new height of the keyboard to align `backgroundImageView` - - @param keyboardHeight the keyboard height. - */ -- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight; - @end diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index eef17866e..76d3af972 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -38,10 +38,6 @@ @property (nonatomic) UIBarButtonItem *backupLeftBarButtonItem; @property (nonatomic) UIBarButtonItem *backupRightBarButtonItem; -// The Riot empty search background image (champagne bubbles) -@property (nonatomic) UIImageView *backgroundImageView; -@property (nonatomic) NSLayoutConstraint *backgroundImageViewBottomConstraint; - @end @implementation UIViewControllerRiotSearchInternals @@ -70,16 +66,6 @@ return self.searchInternals.searchBarHidden; } -- (UIImageView*)backgroundImageView -{ - return self.searchInternals.backgroundImageView; -} - -- (NSLayoutConstraint *)backgroundImageViewBottomConstraint -{ - return self.searchInternals.backgroundImageViewBottomConstraint; -} - - (void)showSearch:(BOOL)animated { if (self.searchInternals.searchBarHidden) @@ -134,80 +120,6 @@ } } -- (void)addBackgroundImageViewToView:(UIView*)view -{ - UIImage *searchBgImage = [MXKTools paintImage:AssetImages.searchBg.image withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; - UIImageView *backgroundImageView = [[UIImageView alloc] initWithImage:searchBgImage]; - backgroundImageView.translatesAutoresizingMaskIntoConstraints = NO; - - [view addSubview:backgroundImageView]; - - // Keep it at left - NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeLeading - relatedBy:NSLayoutRelationEqual - toItem:backgroundImageView - attribute:NSLayoutAttributeLeading - multiplier:1.0 - constant:0]; - // Same width as parent - NSLayoutConstraint *widthConstraint = [NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeWidth - relatedBy:NSLayoutRelationEqual - toItem:backgroundImageView - attribute:NSLayoutAttributeWidth - multiplier:1.0f - constant:0.0f]; - - // Keep the image aspect ratio - NSLayoutConstraint *aspectRatioConstraint = [NSLayoutConstraint - constraintWithItem:backgroundImageView - attribute:NSLayoutAttributeHeight - relatedBy:NSLayoutRelationEqual - toItem:backgroundImageView - attribute:NSLayoutAttributeWidth - multiplier:(backgroundImageView.frame.size.height / backgroundImageView.frame.size.width) - constant:0]; - - // Set its position according to its bottom - NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:view - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:backgroundImageView - attribute:NSLayoutAttributeBottom - multiplier:1.0f - constant:216]; - - [NSLayoutConstraint activateConstraints:@[leftConstraint, - widthConstraint, - aspectRatioConstraint, - bottomConstraint - ]]; - - self.searchInternals.backgroundImageView = backgroundImageView; - self.searchInternals.backgroundImageViewBottomConstraint = bottomConstraint; - - // It will be showed once the keyboard appears - backgroundImageView.hidden = YES; -} - -- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight -{ - // keyboardHeight = 0 means no keyboard - if (keyboardHeight > 0) - { - self.searchInternals.backgroundImageView.hidden = NO; - - // 60 = 18 + 42 from the Riot design - self.searchInternals.backgroundImageViewBottomConstraint.constant = keyboardHeight - 60; - } - else - { - // Hide the search - self.searchInternals.backgroundImageView.hidden = YES; - } -} - #pragma mark - UISearchBarDelegate - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar2 diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index c74649f96..1f2851068 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -214,7 +214,6 @@ internal class Asset: NSObject { 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 secretsRecoveryKey = ImageAsset(name: "secrets_recovery_key") internal static let secretsRecoveryPassphrase = ImageAsset(name: "secrets_recovery_passphrase") diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index 78eeaa4b7..f701d8b08 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -105,9 +105,6 @@ [self initWithTitles:titles viewControllers:viewControllers defaultSelected:0]; [super viewDidLoad]; - - // Add the Riot background image when search bar is empty - [self addBackgroundImageViewToView:self.view]; // Initialize here the data sources if a matrix session has been already set. [self initializeDataSources]; @@ -118,18 +115,6 @@ [super showSearch:NO]; } -- (void)userInterfaceThemeDidChange -{ - [super userInterfaceThemeDidChange]; - - UIImageView *backgroundImageView = self.backgroundImageView; - if (backgroundImageView) - { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; - backgroundImageView.image = image; - } -} - - (void)destroy { [super destroy]; @@ -178,9 +163,6 @@ { [super viewDidAppear:animated]; - // Here the actual view size is available, check the background image display if any - [self checkAndShowBackgroundImage]; - if (self.splitViewController && !self.splitViewController.isCollapsed) { // In case of split view controller where the primary and secondary view controllers are displayed side-by-side onscreen, @@ -189,13 +171,6 @@ } } -- (void)viewDidLayoutSubviews -{ - [super viewDidLayoutSubviews]; - - [self checkAndShowBackgroundImage]; -} - - (UIStatusBarStyle)preferredStatusBarStyle { return ThemeService.shared.theme.statusBarStyle; @@ -326,15 +301,6 @@ #pragma mark - Override MXKViewController -- (void)setKeyboardHeight:(CGFloat)keyboardHeight -{ - [self setKeyboardHeightForBackgroundImage:keyboardHeight]; - - [super setKeyboardHeight:keyboardHeight]; - - [self checkAndShowBackgroundImage]; -} - - (void)startActivityIndicator { // Redirect the operation to the currently displayed VC @@ -352,58 +318,6 @@ } } -#pragma mark - Override UIViewController+VectorSearch - -- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight -{ - [super setKeyboardHeightForBackgroundImage:keyboardHeight]; - - if (keyboardHeight > 0) - { - [self checkAndShowBackgroundImage]; - } -} - -// Check conditions before displaying the background -- (void)checkAndShowBackgroundImage -{ - // Note: This background is hidden when keyboard is dismissed. - // The other conditions depend on the current selected view controller. - if (self.selectedViewController == recentsViewController) - { - self.backgroundImageView.hidden = YES; - } - else if (self.selectedViewController == messagesSearchViewController) - { - self.backgroundImageView.hidden = ((messagesSearchDataSource.serverCount != 0) || !messagesSearchViewController.noResultsLabel.isHidden || (self.keyboardHeight == 0)); - } - else if (self.selectedViewController == peopleSearchViewController) - { - self.backgroundImageView.hidden = (([peopleSearchViewController.contactsTableView numberOfSections] != 0) || (self.keyboardHeight == 0)); - } - else if (self.selectedViewController == filesSearchViewController) - { - self.backgroundImageView.hidden = ((filesSearchDataSource.serverCount != 0) || !filesSearchViewController.noResultsLabel.isHidden || (self.keyboardHeight == 0)); - } - else - { - self.backgroundImageView.hidden = (self.keyboardHeight == 0); - } - - if (!self.backgroundImageView.hidden) - { - [self.backgroundImageView layoutIfNeeded]; - [self.selectedViewController.view layoutIfNeeded]; - - // Check whether there is enough space to display this background - // For example, in landscape with the iPhone 5 & 6 screen size, the backgroundImageView must be hidden. - if (self.backgroundImageView.frame.origin.y < 0 || (self.selectedViewController.view.frame.size.height - self.backgroundImageViewBottomConstraint.constant) < self.backgroundImageView.frame.size.height) - { - self.backgroundImageView.hidden = YES; - } - } -} - #pragma mark - Override SegmentedViewController - (void)setSelectedIndex:(NSUInteger)selectedIndex @@ -463,7 +377,6 @@ if (self.searchBar.text.length) { recentsDataSource.hideRecents = NO; - self.backgroundImageView.hidden = YES; // Forward the search request to the data source if (self.selectedViewController == recentsViewController) @@ -524,8 +437,6 @@ [filesSearchDataSource searchMessages:nil force:NO]; } } - - [self checkAndShowBackgroundImage]; } #pragma mark - UISearchBarDelegate diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index 214f3f497..8a16c463d 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -73,10 +73,7 @@ [self initWithTitles:titles viewControllers:viewControllers defaultSelected:0]; [super viewDidLoad]; - - // Add the Riot background image when search bar is empty - [self addBackgroundImageViewToView:self.view]; - + // Initialize here the data sources if a matrix session has been already set. [self initializeDataSources]; @@ -87,13 +84,6 @@ { [super userInterfaceThemeDidChange]; - UIImageView *backgroundImageView = self.backgroundImageView; - if (backgroundImageView) - { - UIImage *image = [MXKTools paintImage:backgroundImageView.image withColor:ThemeService.shared.theme.matrixSearchBackgroundImageTintColor]; - backgroundImageView.image = image; - } - // Match the search bar color to the navigation bar color as it extends slightly outside the frame. self.searchBar.backgroundColor = ThemeService.shared.theme.baseColor; } @@ -227,15 +217,6 @@ #pragma mark - Override MXKViewController -- (void)setKeyboardHeight:(CGFloat)keyboardHeight -{ - [self setKeyboardHeightForBackgroundImage:keyboardHeight]; - - [super setKeyboardHeight:keyboardHeight]; - - [self checkAndShowBackgroundImage]; -} - - (void)startActivityIndicator { // Redirect the operation to the currently displayed VC @@ -283,48 +264,6 @@ [self.navigationController popViewControllerAnimated:YES]; } -- (void)setKeyboardHeightForBackgroundImage:(CGFloat)keyboardHeight -{ - [super setKeyboardHeightForBackgroundImage:keyboardHeight]; - - if (keyboardHeight > 0) - { - [self checkAndShowBackgroundImage]; - } -} - -// Check conditions before displaying the background -- (void)checkAndShowBackgroundImage -{ - // Note: This background is hidden when keyboard is dismissed. - // The other conditions depend on the current selected view controller. - if (self.selectedViewController == messagesSearchViewController) - { - self.backgroundImageView.hidden = ((messagesSearchDataSource.serverCount != 0) || !messagesSearchViewController.noResultsLabel.isHidden || (self.keyboardHeight == 0)); - } - else if (self.selectedViewController == filesSearchViewController) - { - self.backgroundImageView.hidden = ((filesSearchDataSource.serverCount != 0) || !filesSearchViewController.noResultsLabel.isHidden || (self.keyboardHeight == 0)); - } - else - { - self.backgroundImageView.hidden = (self.keyboardHeight == 0); - } - - if (!self.backgroundImageView.hidden) - { - [self.backgroundImageView layoutIfNeeded]; - [self.selectedViewController.view layoutIfNeeded]; - - // Check whether there is enough space to display this background - // For example, in landscape with the iPhone 5 & 6 screen size, the backgroundImageView must be hidden. - if (self.backgroundImageView.frame.origin.y < 0 || (self.selectedViewController.view.frame.size.height - self.backgroundImageViewBottomConstraint.constant) < self.backgroundImageView.frame.size.height) - { - self.backgroundImageView.hidden = YES; - } - } -} - #pragma mark - Override SegmentedViewController - (void)setSelectedIndex:(NSUInteger)selectedIndex @@ -341,8 +280,6 @@ { if (self.searchBar.text.length) { - self.backgroundImageView.hidden = YES; - // Forward the search request to the data source if (self.selectedViewController == messagesSearchViewController) { @@ -383,8 +320,6 @@ [filesSearchDataSource searchMessages:nil force:NO]; } } - - [self checkAndShowBackgroundImage]; } @end diff --git a/changelog.d/5471.change b/changelog.d/5471.change new file mode 100644 index 000000000..195a7737f --- /dev/null +++ b/changelog.d/5471.change @@ -0,0 +1 @@ +Search: remove bubbles background From 50beaa49fbd6dc4e0a1daefaad460d51a07ea331 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 17:36:49 +0100 Subject: [PATCH 100/188] Fix BubbleRoomCellLayoutUpdater. --- .../Styles/Bubble/BubbleRoomCellLayoutUpdater.swift | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift index 72c16495a..5b1124c5a 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift @@ -182,12 +182,8 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { let messageViewMarginTop: CGFloat = 0 let messageViewMarginBottom: CGFloat = 0 - let messageViewMarginLeft = -<<<<<<< HEAD - BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + PlainRoomCellLayoutConstants.innerContentViewMargins.left -======= - BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.left ->>>>>>> develop + let messageViewMarginLeft = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.left + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.left + let messageViewMarginRight = BubbleRoomCellLayoutConstants.outgoingBubbleBackgroundMargins.right + BubbleRoomCellLayoutConstants.bubbleTextViewInsets.right let messageViewInsets = UIEdgeInsets(top: messageViewMarginTop, left: messageViewMarginLeft, bottom: messageViewMarginBottom, right: messageViewMarginRight) From ecc9e16f2d38697319d30118e333385db87075ad Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 17:37:26 +0100 Subject: [PATCH 101/188] Fix ThreadSummaryView. --- .../TimelineDecorations/Threads/Summary/ThreadSummaryView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift index e7697d635..a57888aeb 100644 --- a/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift +++ b/Riot/Modules/Room/TimelineDecorations/Threads/Summary/ThreadSummaryView.swift @@ -62,7 +62,7 @@ class ThreadSummaryView: UIView { } static func contentViewHeight(forThread thread: MXThreadProtocol?, fitting maxWidth: CGFloat) -> CGFloat { - return RoomBubbleCellLayout.threadSummaryViewHeight + return PlainRoomCellLayoutConstants.threadSummaryViewHeight } required init?(coder: NSCoder) { From 89e7f349a7a6773b6faf58a4495160124d2feaf5 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 17:42:37 +0100 Subject: [PATCH 102/188] Fix MXKRoomBubbleTableViewCell categorie. --- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index f73887bff..6924cf8c6 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -816,7 +816,7 @@ NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = // Define 'Edit' button frame UIImage *editIcon = AssetImages.editIcon.image; - CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth - 22 - editIcon.size.width / 2; + CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - PlainRoomCellLayoutConstants.timestampLabelWidth - 22 - editIcon.size.width / 2; CGFloat editBtnPosY = isFirstDisplayedComponent ? -13 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13; UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(editBtnPosX, editBtnPosY, 44, 44)]; From 1c90fe20b4bfd5b7bd336e19f8484edef7224c9a Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Wed, 16 Feb 2022 19:44:49 +0000 Subject: [PATCH 103/188] Translated using Weblate (Japanese) Currently translated at 71.4% (5 of 7 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/ja/ --- Riot/Assets/ja.lproj/InfoPlist.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/ja.lproj/InfoPlist.strings b/Riot/Assets/ja.lproj/InfoPlist.strings index 7b9dfeb15..add92d1bb 100644 --- a/Riot/Assets/ja.lproj/InfoPlist.strings +++ b/Riot/Assets/ja.lproj/InfoPlist.strings @@ -3,3 +3,4 @@ "NSPhotoLibraryUsageDescription" = "フォトライブラリは、写真や動画の送信に使用されます。"; "NSMicrophoneUsageDescription" = "マイクは動画撮影や通話に使用されます。"; "NSContactsUsageDescription" = "連絡先のどれがElementまたはMatrixを既に使用しているかを表示するために、あなたのアドレス帳にあるメールアドレスと電話番号をMatrix Identity Serverに送信することができます。 New Vectorはこのデータを保存したり、他の目的に使用したりしません。 詳細については、アプリケーション設定のプライバシーポリシーページを参照してください。"; +"NSCalendarsUsageDescription" = "予定されている会議をアプリで確認することができます。"; From b19522c8cc794f8d824f982e4f16dd69c5c77290 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Wed, 16 Feb 2022 19:44:36 +0000 Subject: [PATCH 104/188] Translated using Weblate (Japanese) Currently translated at 71.4% (5 of 7 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/ja/ --- Riot/Assets/ja.lproj/InfoPlist.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/ja.lproj/InfoPlist.strings b/Riot/Assets/ja.lproj/InfoPlist.strings index add92d1bb..e6ddff578 100644 --- a/Riot/Assets/ja.lproj/InfoPlist.strings +++ b/Riot/Assets/ja.lproj/InfoPlist.strings @@ -1,6 +1,6 @@ // Permissions usage explanations "NSCameraUsageDescription" = "ビデオ通話や写真撮影、動画撮影などを行うときにカメラを使用します。"; "NSPhotoLibraryUsageDescription" = "フォトライブラリは、写真や動画の送信に使用されます。"; -"NSMicrophoneUsageDescription" = "マイクは動画撮影や通話に使用されます。"; -"NSContactsUsageDescription" = "連絡先のどれがElementまたはMatrixを既に使用しているかを表示するために、あなたのアドレス帳にあるメールアドレスと電話番号をMatrix Identity Serverに送信することができます。 New Vectorはこのデータを保存したり、他の目的に使用したりしません。 詳細については、アプリケーション設定のプライバシーポリシーページを参照してください。"; +"NSMicrophoneUsageDescription" = "Elementは通話、動画撮影、ボイスメッセージの録音にマイクへのアクセスを必要としています。"; +"NSContactsUsageDescription" = "Elementは、あなたが連絡先をチャットに招待できるように、連絡先を表示します。"; "NSCalendarsUsageDescription" = "予定されている会議をアプリで確認することができます。"; From 9f160c0eb584bea4c8253255bcac1bde83f19a9a Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Wed, 16 Feb 2022 19:45:37 +0000 Subject: [PATCH 105/188] Translated using Weblate (Japanese) Currently translated at 85.7% (6 of 7 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/ja/ --- Riot/Assets/ja.lproj/InfoPlist.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/ja.lproj/InfoPlist.strings b/Riot/Assets/ja.lproj/InfoPlist.strings index e6ddff578..7a18b8a82 100644 --- a/Riot/Assets/ja.lproj/InfoPlist.strings +++ b/Riot/Assets/ja.lproj/InfoPlist.strings @@ -4,3 +4,4 @@ "NSMicrophoneUsageDescription" = "Elementは通話、動画撮影、ボイスメッセージの録音にマイクへのアクセスを必要としています。"; "NSContactsUsageDescription" = "Elementは、あなたが連絡先をチャットに招待できるように、連絡先を表示します。"; "NSCalendarsUsageDescription" = "予定されている会議をアプリで確認することができます。"; +"NSFaceIDUsageDescription" = "Face IDはアプリへのアクセスに使用されます。"; From b9bf3a43c8304ec7bddaa7f2600da962a2c0fccf Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Wed, 16 Feb 2022 19:45:20 +0000 Subject: [PATCH 106/188] Translated using Weblate (Japanese) Currently translated at 85.7% (6 of 7 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/ja/ --- Riot/Assets/ja.lproj/InfoPlist.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/InfoPlist.strings b/Riot/Assets/ja.lproj/InfoPlist.strings index 7a18b8a82..ec4354666 100644 --- a/Riot/Assets/ja.lproj/InfoPlist.strings +++ b/Riot/Assets/ja.lproj/InfoPlist.strings @@ -3,5 +3,5 @@ "NSPhotoLibraryUsageDescription" = "フォトライブラリは、写真や動画の送信に使用されます。"; "NSMicrophoneUsageDescription" = "Elementは通話、動画撮影、ボイスメッセージの録音にマイクへのアクセスを必要としています。"; "NSContactsUsageDescription" = "Elementは、あなたが連絡先をチャットに招待できるように、連絡先を表示します。"; -"NSCalendarsUsageDescription" = "予定されている会議をアプリで確認することができます。"; +"NSCalendarsUsageDescription" = "予定されているミーティングをアプリで確認することができます。"; "NSFaceIDUsageDescription" = "Face IDはアプリへのアクセスに使用されます。"; From 0e53d1a2625bd5af7b0e0a0227aa2d95b3c0910e Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Wed, 16 Feb 2022 21:28:16 +0100 Subject: [PATCH 107/188] Message bubbles: Increase text message width. --- .../Styles/Bubble/BubbleRoomCellLayoutConstants.swift | 2 +- .../Common/TextMessageBubbleCellContentView.xib | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift index 52e264b13..3df3d5985 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift @@ -30,7 +30,7 @@ final class BubbleRoomCellLayoutConstants: NSObject { static let incomingBubbleBackgroundMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 48, bottom: 0, right: 80) - static let bubbleTextViewInsets: UIEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 45) + static let bubbleTextViewInsets: UIEdgeInsets = UIEdgeInsets(top: 5, left: 5, bottom: 12, right: 5) static let bubbleCornerRadius: CGFloat = 12.0 diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib index 0a09502f1..05341b741 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBubbleCellContentView.xib @@ -14,12 +14,15 @@ - + - + + + + @@ -27,10 +30,10 @@ - + - + From 13f736a602b81d2ff65887e27e4ae06ef4202f22 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 09:31:08 +0100 Subject: [PATCH 108/188] Update changes --- changelog.d/5550.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5550.bugfix diff --git a/changelog.d/5550.bugfix b/changelog.d/5550.bugfix new file mode 100644 index 000000000..194759b0d --- /dev/null +++ b/changelog.d/5550.bugfix @@ -0,0 +1 @@ +Message bubbles: Increase text message width. From 0b93868adf1c4db3df4a31162928dbb8ebf698e7 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 09:36:28 +0100 Subject: [PATCH 109/188] MXKRoomBubbleTableViewCell: UI components setup. --- .../Common/MXKRoomBubbleTableViewCell.h | 21 ++ .../Common/MXKRoomBubbleTableViewCell.m | 182 ++++++++++-------- 2 files changed, 125 insertions(+), 78 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.h b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.h index baf53c7ba..cd3d0ccdd 100644 --- a/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.h +++ b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.h @@ -337,10 +337,31 @@ extern NSString *const kMXKRoomBubbleCellUrlItemInteraction; */ - (void)setupViews; +/// Setup sender name label if needed +- (void)setupSenderNameLabel; + +/// Setup avatar view if needed +- (void)setupAvatarView; + +/// Setup message text view if needed +- (void)setupMessageTextView; + +/// Setup message text view long press gesture if needed +- (void)setupMessageTextViewLongPressGesture; + /// Add temporary subview to `tmpSubviews` property. - (void)addTemporarySubview:(UIView*)subview; /// Called when content view cell is tapped - (IBAction)onContentViewTap:(UITapGestureRecognizer*)sender; +/// Called when sender name is tapped +- (IBAction)onSenderNameTap:(UITapGestureRecognizer*)sender; + +/// Called when avatar view is tapped +- (IBAction)onAvatarTap:(UITapGestureRecognizer*)sender; + +/// Called when a UI component is long pressed +- (IBAction)onLongPressGesture:(UILongPressGestureRecognizer*)longPressGestureRecognizer; + @end diff --git a/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m index 555733c7f..fb2c9516d 100644 --- a/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m +++ b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m @@ -136,86 +136,11 @@ static BOOL _disableLongPressGestureOnEvent; - (void)setupViews { - if (self.userNameLabel) - { - // Listen to name tap - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSenderNameTap:)]; - [tapGesture setNumberOfTouchesRequired:1]; - [tapGesture setNumberOfTapsRequired:1]; - [tapGesture setDelegate:self]; - - if (self.userNameTapGestureMaskView) - { - [self.userNameTapGestureMaskView addGestureRecognizer:tapGesture]; - } - else - { - [self.userNameLabel addGestureRecognizer:tapGesture]; - self.userNameLabel.userInteractionEnabled = YES; - } - } + [self setupSenderNameLabel]; - if (self.pictureView) - { - self.pictureView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder; - - // Listen to avatar tap - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onAvatarTap:)]; - [tapGesture setNumberOfTouchesRequired:1]; - [tapGesture setNumberOfTapsRequired:1]; - [tapGesture setDelegate:self]; - [self.pictureView addGestureRecognizer:tapGesture]; - self.pictureView.userInteractionEnabled = YES; - - // Add a long gesture recognizer on avatar (in order to display for example the member details) - UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; - [self.pictureView addGestureRecognizer:longPress]; - } + [self setupAvatarView]; - if (self.messageTextView) - { - // Listen to textView tap - UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onMessageTap:)]; - [tapGesture setNumberOfTouchesRequired:1]; - [tapGesture setNumberOfTapsRequired:1]; - [tapGesture setDelegate:self]; - [self.messageTextView addGestureRecognizer:tapGesture]; - self.messageTextView.userInteractionEnabled = YES; - - // Recognise and make tappable phone numbers, address, etc. - self.messageTextView.dataDetectorTypes = UIDataDetectorTypeAll; - - // Listen to link click - self.messageTextView.delegate = self; - - if (_disableLongPressGestureOnEvent == NO) - { - // Add a long gesture recognizer on text view (in order to display for example the event details) - UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; - longPress.delegate = self; - - // MXKMessageTextView does not catch touches outside of links. Add a background view to handle long touch. - if ([self.messageTextView isKindOfClass:[MXKMessageTextView class]]) - { - UIView *messageTextBackgroundView = [[UIView alloc] initWithFrame:self.messageTextView.frame]; - messageTextBackgroundView.backgroundColor = [UIColor clearColor]; - [self.contentView insertSubview:messageTextBackgroundView belowSubview:self.messageTextView]; - messageTextBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; - [messageTextBackgroundView.leftAnchor constraintEqualToAnchor:self.messageTextView.leftAnchor].active = YES; - [messageTextBackgroundView.rightAnchor constraintEqualToAnchor:self.messageTextView.rightAnchor].active = YES; - [messageTextBackgroundView.topAnchor constraintEqualToAnchor:self.messageTextView.topAnchor].active = YES; - [messageTextBackgroundView.bottomAnchor constraintEqualToAnchor:self.messageTextView.bottomAnchor].active = YES; - - [messageTextBackgroundView addGestureRecognizer:longPress]; - - self.messageTextBackgroundView = messageTextBackgroundView; - } - else - { - [self.messageTextView addGestureRecognizer:longPress]; - } - } - } + [self setupMessageTextView]; if (self.playIconView) { @@ -250,6 +175,107 @@ static BOOL _disableLongPressGestureOnEvent; [self setupConstraintsConstantDefaultValues]; } +- (void)setupSenderNameLabel +{ + if (!self.userNameLabel) + { + return; + } + + // Listen to name tap + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onSenderNameTap:)]; + [tapGesture setNumberOfTouchesRequired:1]; + [tapGesture setNumberOfTapsRequired:1]; + [tapGesture setDelegate:self]; + + if (self.userNameTapGestureMaskView) + { + [self.userNameTapGestureMaskView addGestureRecognizer:tapGesture]; + } + else + { + [self.userNameLabel addGestureRecognizer:tapGesture]; + self.userNameLabel.userInteractionEnabled = YES; + } +} + +- (void)setupAvatarView +{ + if (!self.pictureView) + { + return; + } + + self.pictureView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder; + + // Listen to avatar tap + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onAvatarTap:)]; + [tapGesture setNumberOfTouchesRequired:1]; + [tapGesture setNumberOfTapsRequired:1]; + [tapGesture setDelegate:self]; + [self.pictureView addGestureRecognizer:tapGesture]; + self.pictureView.userInteractionEnabled = YES; + + // Add a long gesture recognizer on avatar (in order to display for example the member details) + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; + [self.pictureView addGestureRecognizer:longPress]; +} + +- (void)setupMessageTextView +{ + if (!self.messageTextView) + { + return; + } + + // Listen to textView tap + UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onMessageTap:)]; + [tapGesture setNumberOfTouchesRequired:1]; + [tapGesture setNumberOfTapsRequired:1]; + [tapGesture setDelegate:self]; + [self.messageTextView addGestureRecognizer:tapGesture]; + self.messageTextView.userInteractionEnabled = YES; + + // Recognise and make tappable phone numbers, address, etc. + self.messageTextView.dataDetectorTypes = UIDataDetectorTypeAll; + + // Listen to link click + self.messageTextView.delegate = self; + + [self setupMessageTextViewLongPressGesture]; +} + +- (void)setupMessageTextViewLongPressGesture +{ + if (_disableLongPressGestureOnEvent == NO) + { + // Add a long gesture recognizer on text view (in order to display for example the event details) + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; + longPress.delegate = self; + + // MXKMessageTextView does not catch touches outside of links. Add a background view to handle long touch. + if ([self.messageTextView isKindOfClass:[MXKMessageTextView class]]) + { + UIView *messageTextBackgroundView = [[UIView alloc] initWithFrame:self.messageTextView.frame]; + messageTextBackgroundView.backgroundColor = [UIColor clearColor]; + [self.contentView insertSubview:messageTextBackgroundView belowSubview:self.messageTextView]; + messageTextBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + [messageTextBackgroundView.leftAnchor constraintEqualToAnchor:self.messageTextView.leftAnchor].active = YES; + [messageTextBackgroundView.rightAnchor constraintEqualToAnchor:self.messageTextView.rightAnchor].active = YES; + [messageTextBackgroundView.topAnchor constraintEqualToAnchor:self.messageTextView.topAnchor].active = YES; + [messageTextBackgroundView.bottomAnchor constraintEqualToAnchor:self.messageTextView.bottomAnchor].active = YES; + + [messageTextBackgroundView addGestureRecognizer:longPress]; + + self.messageTextBackgroundView = messageTextBackgroundView; + } + else + { + [self.messageTextView addGestureRecognizer:longPress]; + } + } +} + - (void)customizeTableViewCellRendering { [super customizeTableViewCellRendering]; From 831e3e6500fd778f27c132ccbd41aa334ee1947b Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 09:38:52 +0100 Subject: [PATCH 110/188] TextMessageBaseBubbleCell: Fix message text view gesture recognizers. --- .../Common/TextMessageBaseBubbleCell.swift | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 86584f9aa..bcff96d17 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -32,21 +32,23 @@ class TextMessageBaseBubbleCell: SizableBaseRoomCell, RoomCellURLPreviewDisplaya // MARK: - Overrides override func setupViews() { - super.setupViews() roomCellContentView?.backgroundColor = .clear - guard let contentView = roomCellContentView?.innerContentView else { - return - } - roomCellContentView?.innerContentViewBottomContraint.constant = BubbleRoomCellLayoutConstants.innerContentViewMargins.bottom let textMessageContentView = TextMessageBubbleCellContentView.instantiate() - contentView.vc_addSubViewMatchingParent(textMessageContentView) + roomCellContentView?.innerContentView.vc_addSubViewMatchingParent(textMessageContentView) self.textMessageContentView = textMessageContentView + + // Setup messageTextView property first before running `setupMessageTextView` method + super.setupViews() + } + + override func setupMessageTextViewLongPressGesture() { + // Do nothing, otherwise default setup prevent link tap } override func update(theme: Theme) { From eb7edd42455f330c606bbb1795aa9c40a160451c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 09:39:34 +0100 Subject: [PATCH 111/188] BaseRoomCell: Fix sender name tap. Prepare avatar view tap. --- .../BaseRoomCell/BaseRoomCell.swift | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift index a26bcb1b7..fd46736ea 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/BaseRoomCell.swift @@ -133,6 +133,7 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) + self.commonInit() } private func commonInit() { @@ -181,6 +182,41 @@ class BaseRoomCell: MXKRoomBubbleTableViewCell, BaseRoomCellProtocol { } } + override func setupSenderNameLabel() { + + guard let userNameTouchMaskView = self.roomCellContentView?.userNameTouchMaskView else { + return + } + + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onSenderNameTap(_:))) + tapGesture.numberOfTouchesRequired = 1 + tapGesture.numberOfTapsRequired = 1 + tapGesture.delegate = self + + userNameTouchMaskView.addGestureRecognizer(tapGesture) + } + + override func setupAvatarView() { + + guard let avatarImageView = self.roomCellContentView?.avatarImageView else { + return + } + + avatarImageView.mediaFolder = kMXMediaManagerAvatarThumbnailFolder + + // Listen to avatar tap + let tapGesture = UITapGestureRecognizer(target: self, action: #selector(onAvatarTap(_:))) + tapGesture.numberOfTouchesRequired = 1 + tapGesture.numberOfTapsRequired = 1 + tapGesture.delegate = self + avatarImageView.addGestureRecognizer(tapGesture) + avatarImageView.isUserInteractionEnabled = true + + // Add a long gesture recognizer on avatar (in order to display for example the member details) + let longPress = UILongPressGestureRecognizer(target: self, action: #selector(onLongPressGesture(_:))) + avatarImageView.addGestureRecognizer(longPress) + } + override class func defaultReuseIdentifier() -> String! { return String(describing: self) } From 2299a5bcfc302737ebc19381e6f6c6dc123be731 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 09:42:33 +0100 Subject: [PATCH 112/188] Update changes --- changelog.d/5553.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5553.bugfix diff --git a/changelog.d/5553.bugfix b/changelog.d/5553.bugfix new file mode 100644 index 000000000..803d9f9c1 --- /dev/null +++ b/changelog.d/5553.bugfix @@ -0,0 +1 @@ +Message bubbles: Fix edited text message `edited` link not working. From 0340d3435a02af2c072abfa14adcf34d7033c184 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 10:38:48 +0100 Subject: [PATCH 113/188] RoomCellContentView: Fix avatar container view with no clear bg. --- .../TimelineCells/BaseRoomCell/RoomCellContentView.xib | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib index 9244e2dd0..b7519c04a 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib @@ -4,7 +4,6 @@ - @@ -68,7 +67,7 @@ - + @@ -76,7 +75,7 @@ - + @@ -87,7 +86,7 @@ - + - - - From c4702cf772d553aac72083f077291523d4e9710a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 10:39:51 +0100 Subject: [PATCH 114/188] Update changes --- changelog.d/5555.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5555.bugfix diff --git a/changelog.d/5555.bugfix b/changelog.d/5555.bugfix new file mode 100644 index 000000000..2e8304d61 --- /dev/null +++ b/changelog.d/5555.bugfix @@ -0,0 +1 @@ +Message bubbles: Fix horizontal lines between messages. From 8522a4283dc02327c6da4766d65898bb85012b31 Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 17 Feb 2022 11:19:32 +0000 Subject: [PATCH 115/188] Rename OnboardingUseCase to OnboardingUseCaseSelectionScreen Same for OnboardingUseCaseCoordinator. --- Riot/Modules/Onboarding/OnboardingCoordinator.swift | 6 +++--- RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift | 2 +- ....swift => OnboardingUseCaseSelectionCoordinator.swift} | 8 ++++---- .../UseCase/MockOnboardingUseCaseScreenState.swift | 8 ++++---- ...eCase.swift => OnboardingUseCaseSelectionScreen.swift} | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) rename RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/{OnboardingUseCaseCoordinator.swift => OnboardingUseCaseSelectionCoordinator.swift} (82%) rename RiotSwiftUI/Modules/Onboarding/UseCase/View/{OnboardingUseCase.swift => OnboardingUseCaseSelectionScreen.swift} (97%) diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 2047e4834..7be3f4370 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -147,10 +147,10 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { @available(iOS 14.0, *) /// Show the use case screen for new users. private func showUseCaseSelectionScreen() { - let coordinator = OnboardingUseCaseCoordinator() + let coordinator = OnboardingUseCaseSelectionCoordinator() coordinator.completion = { [weak self, weak coordinator] result in guard let self = self, let coordinator = coordinator else { return } - self.useCaseCoordinator(coordinator, didCompleteWith: result) + self.useCaseSelectionCoordinator(coordinator, didCompleteWith: result) } coordinator.start() @@ -166,7 +166,7 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { } /// Displays the next view in the flow after the use case screen. - private func useCaseCoordinator(_ coordinator: OnboardingUseCaseCoordinator, didCompleteWith result: OnboardingUseCaseViewModelResult) { + private func useCaseSelectionCoordinator(_ coordinator: OnboardingUseCaseSelectionCoordinator, didCompleteWith result: OnboardingUseCaseViewModelResult) { useCaseResult = result showAuthenticationScreen() } diff --git a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift index e2d3d4816..242e4c088 100644 --- a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift +++ b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift @@ -20,7 +20,7 @@ import Foundation @available(iOS 14.0, *) enum MockAppScreens { static let appScreens: [MockScreenState.Type] = [ - MockOnboardingUseCaseScreenState.self, + MockOnboardingUseCaseSelectionScreenState.self, MockOnboardingSplashScreenScreenState.self, MockLocationSharingScreenState.self, MockAnalyticsPromptScreenState.self, diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseSelectionCoordinator.swift similarity index 82% rename from RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift rename to RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseSelectionCoordinator.swift index f91c79861..0a2d7eae4 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseCoordinator.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/Coordinator/OnboardingUseCaseSelectionCoordinator.swift @@ -16,7 +16,7 @@ import SwiftUI -final class OnboardingUseCaseCoordinator: Coordinator, Presentable { +final class OnboardingUseCaseSelectionCoordinator: Coordinator, Presentable { // MARK: - Properties @@ -36,7 +36,7 @@ final class OnboardingUseCaseCoordinator: Coordinator, Presentable { @available(iOS 14.0, *) init() { let viewModel = OnboardingUseCaseViewModel() - let view = OnboardingUseCase(viewModel: viewModel.context) + let view = OnboardingUseCaseSelectionScreen(viewModel: viewModel.context) onboardingUseCaseViewModel = viewModel let hostingController = VectorHostingController(rootView: view) @@ -47,9 +47,9 @@ final class OnboardingUseCaseCoordinator: Coordinator, Presentable { // MARK: - Public func start() { - MXLog.debug("[OnboardingUseCaseCoordinator] did start.") + MXLog.debug("[OnboardingUseCaseSelectionCoordinator] did start.") onboardingUseCaseViewModel.completion = { [weak self] result in - MXLog.debug("[OnboardingUseCaseCoordinator] OnboardingUseCaseViewModel did complete with result: \(result).") + MXLog.debug("[OnboardingUseCaseSelectionCoordinator] OnboardingUseCaseViewModel did complete with result: \(result).") guard let self = self else { return } self.completion?(result) } diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift index 7cf850d9b..1cce35b23 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/MockOnboardingUseCaseScreenState.swift @@ -20,7 +20,7 @@ import SwiftUI /// Using an enum for the screen allows you define the different state cases with /// the relevant associated data for each case. @available(iOS 14.0, *) -enum MockOnboardingUseCaseScreenState: MockScreenState, CaseIterable { +enum MockOnboardingUseCaseSelectionScreenState: MockScreenState, CaseIterable { // A case for each state you want to represent // with specific, minimal associated data that will allow you // mock that screen. @@ -28,11 +28,11 @@ enum MockOnboardingUseCaseScreenState: MockScreenState, CaseIterable { /// The associated screen var screenType: Any.Type { - OnboardingUseCase.self + OnboardingUseCaseSelectionScreen.self } /// A list of screen state definitions - static var allCases: [MockOnboardingUseCaseScreenState] { + static var allCases: [MockOnboardingUseCaseSelectionScreenState] { // Each of the presence statuses [.default] } @@ -45,7 +45,7 @@ enum MockOnboardingUseCaseScreenState: MockScreenState, CaseIterable { return ( [self, viewModel], - AnyView(OnboardingUseCase(viewModel: viewModel.context) + AnyView(OnboardingUseCaseSelectionScreen(viewModel: viewModel.context) .addDependency(MockAvatarService.example)) ) } diff --git a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift similarity index 97% rename from RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift rename to RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift index f0f0ad403..34c9363ed 100644 --- a/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCase.swift +++ b/RiotSwiftUI/Modules/Onboarding/UseCase/View/OnboardingUseCaseSelectionScreen.swift @@ -18,7 +18,7 @@ import SwiftUI @available(iOS 14.0, *) /// The screen shown to a new user to select their use case for the app. -struct OnboardingUseCase: View { +struct OnboardingUseCaseSelectionScreen: View { // MARK: - Properties @@ -119,7 +119,7 @@ struct OnboardingUseCase: View { @available(iOS 14.0, *) struct OnboardingUseCase_Previews: PreviewProvider { - static let stateRenderer = MockOnboardingUseCaseScreenState.stateRenderer + static let stateRenderer = MockOnboardingUseCaseSelectionScreenState.stateRenderer static var previews: some View { NavigationView { stateRenderer.screenGroup() From 4d2c96433d190d4eb5c5aba8dd37cc729c8b2c75 Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 17 Feb 2022 12:39:11 +0000 Subject: [PATCH 116/188] Include user properties with the next sent event. --- Riot/Modules/Analytics/Analytics.swift | 20 +----- .../Analytics/AnalyticsClientProtocol.swift | 9 ++- .../Analytics/PostHogAnalyticsClient.swift | 44 +++++++++++-- .../Onboarding/OnboardingCoordinator.swift | 7 +- RiotTests/AnalyticsTests.swift | 65 +++++++++++++++++++ 5 files changed, 112 insertions(+), 33 deletions(-) diff --git a/Riot/Modules/Analytics/Analytics.swift b/Riot/Modules/Analytics/Analytics.swift index 6f6a67597..48716f78e 100644 --- a/Riot/Modules/Analytics/Analytics.swift +++ b/Riot/Modules/Analytics/Analytics.swift @@ -108,7 +108,6 @@ import AnalyticsEvents !RiotSettings.shared.isIdentifiedForAnalytics else { return } - let userProperties = makeUserProperties(for: session) let service = AnalyticsService(session: session) self.service = service @@ -117,7 +116,7 @@ import AnalyticsEvents switch result { case .success(let settings): - self.identify(with: settings, and: userProperties) + self.identify(with: settings) self.service = nil case .failure: MXLog.error("[Analytics] Failed to use analytics settings. Will continue to run without analytics ID.") @@ -150,30 +149,17 @@ import AnalyticsEvents /// Identify (pseudonymously) any future events with the ID from the analytics account data settings. /// - Parameter settings: The settings to use for identification. The ID must be set *before* calling this method. - /// - Parameter userProperties: Any user properties that should be set for creating cohorts etc. - private func identify(with settings: AnalyticsSettings, and userProperties: AnalyticsEvent.UserProperties) { + private func identify(with settings: AnalyticsSettings) { guard let id = settings.id else { MXLog.error("[Analytics] identify(with:) called before an ID has been generated.") return } - client.identify(id: id, userProperties: userProperties) + client.identify(id: id) MXLog.debug("[Analytics] Identified.") RiotSettings.shared.isIdentifiedForAnalytics = true } - /// Returns the user properties for use when identifying a session. - /// - Parameter session: The session to gather any user properties from. - /// - Returns: The properties to be set. - private func makeUserProperties(for session: MXSession) -> AnalyticsEvent.UserProperties { - var useCaseSelection: AnalyticsEvent.UserProperties.FtueUseCaseSelection? - if let userId = session.credentials.userId, let userSession = UserSessionsService.shared.userSession(withUserId: userId) { - useCaseSelection = userSession.userProperties.useCase?.analyticsName - } - - return AnalyticsEvent.UserProperties(ftueUseCaseSelection: useCaseSelection, numSpaces: nil) - } - /// Capture an event in the `client`. /// - Parameter event: The event to capture. private func capture(event: AnalyticsEventProtocol) { diff --git a/Riot/Modules/Analytics/AnalyticsClientProtocol.swift b/Riot/Modules/Analytics/AnalyticsClientProtocol.swift index 5ae391f61..e16b962e5 100644 --- a/Riot/Modules/Analytics/AnalyticsClientProtocol.swift +++ b/Riot/Modules/Analytics/AnalyticsClientProtocol.swift @@ -26,10 +26,7 @@ protocol AnalyticsClientProtocol { /// Associate the client with an ID. This is persisted until `reset` is called. /// - Parameter id: The ID to associate with the user. - /// - Parameter userProperties: Any user properties that should be included. - /// - /// Only non-nil user properties will be updated when calling this method. - func identify(id: String, userProperties: AnalyticsEvent.UserProperties) + func identify(id: String) /// Reset all stored properties and any event queues on the client. Note that /// the client will remain active, but in a fresh unidentified state. @@ -52,6 +49,8 @@ protocol AnalyticsClientProtocol { /// Updates any user properties to help with creating cohorts. /// - Parameter userProperties: The user properties to be updated. /// - /// Only non-nil properties will be updated when calling this method. + /// Only non-nil properties will be updated when calling this method. There might + /// be a delay when updating user properties as these are cached to be included + /// as part of the next event that gets captured. func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) } diff --git a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift index 69724a5d0..434ce978e 100644 --- a/Riot/Modules/Analytics/PostHogAnalyticsClient.swift +++ b/Riot/Modules/Analytics/PostHogAnalyticsClient.swift @@ -22,6 +22,9 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { /// The PHGPostHog object used to report events. private var postHog: PHGPostHog? + /// Any user properties to be included with the next captured event. + private(set) var pendingUserProperties: AnalyticsEvent.UserProperties? + var isRunning: Bool { postHog?.enabled ?? false } func start() { @@ -35,13 +38,19 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { postHog?.enable() } - func identify(id: String, userProperties: AnalyticsEvent.UserProperties) { - // As user properties overwrite old ones, compactMap the dictionary to avoid resetting any missing properties - postHog?.identify(id, properties: userProperties.properties.compactMapValues { $0 }) + func identify(id: String) { + if let userProperties = pendingUserProperties { + // As user properties overwrite old ones, compactMap the dictionary to avoid resetting any missing properties + postHog?.identify(id, properties: userProperties.properties.compactMapValues { $0 }) + pendingUserProperties = nil + } else { + postHog?.identify(id) + } } func reset() { postHog?.reset() + pendingUserProperties = nil } func stop() { @@ -56,15 +65,38 @@ class PostHogAnalyticsClient: AnalyticsClientProtocol { } func capture(_ event: AnalyticsEventProtocol) { - postHog?.capture(event.eventName, properties: event.properties) + postHog?.capture(event.eventName, properties: attachUserProperties(to: event.properties)) } func screen(_ event: AnalyticsScreenProtocol) { - postHog?.screen(event.screenName.rawValue, properties: event.properties) + postHog?.screen(event.screenName.rawValue, properties: attachUserProperties(to: event.properties)) } func updateUserProperties(_ userProperties: AnalyticsEvent.UserProperties) { + guard let pendingUserProperties = pendingUserProperties else { + pendingUserProperties = userProperties + return + } + + // Merge the updated user properties with the existing ones + self.pendingUserProperties = AnalyticsEvent.UserProperties(ftueUseCaseSelection: userProperties.ftueUseCaseSelection ?? pendingUserProperties.ftueUseCaseSelection, + numSpaces: userProperties.numSpaces ?? pendingUserProperties.numSpaces) + } + + // MARK: - Private + + /// Given a dictionary containing properties from an event, this method will return those properties + /// with any pending user properties included under the `$set` key. + /// - Parameter properties: A dictionary of properties from an event. + /// - Returns: The `properties` dictionary with any user properties included. + private func attachUserProperties(to properties: [String: Any]) -> [String: Any] { + guard isRunning, let userProperties = pendingUserProperties else { return properties } + + var properties = properties + // As user properties overwrite old ones via $set, compactMap the dictionary to avoid resetting any missing properties - postHog?.capture("$identify", properties: ["$set": userProperties.properties.compactMapValues { $0 }]) + properties["$set"] = userProperties.properties.compactMapValues { $0 } + pendingUserProperties = nil + return properties } } diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 7be3f4370..d123d7abc 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -229,11 +229,8 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { // Store the value in the user's session userSession.userProperties.useCase = useCase - // Capture the use case if analytics are running. - // Otherwise it will be included when identifying if opted in. - if Analytics.shared.isRunning { - Analytics.shared.updateUserProperties(ftueUseCase: useCase) - } + // Update the analytics user properties with the use case + Analytics.shared.updateUserProperties(ftueUseCase: useCase) } } } diff --git a/RiotTests/AnalyticsTests.swift b/RiotTests/AnalyticsTests.swift index 5e15bf523..148a23bc8 100644 --- a/RiotTests/AnalyticsTests.swift +++ b/RiotTests/AnalyticsTests.swift @@ -16,6 +16,7 @@ import XCTest @testable import Riot +import AnalyticsEvents class AnalyticsTests: XCTestCase { func testAnalyticsPromptNewUser() { @@ -70,4 +71,68 @@ class AnalyticsTests: XCTestCase { // Then no prompt should be shown. XCTAssertFalse(showPrompt, "A prompt should not be shown any more.") } + + func testAddingUserProperties() { + // Given a client with no user properties set + let client = PostHogAnalyticsClient() + XCTAssertNil(client.pendingUserProperties, "No user properties should have been set yet.") + + // When updating the user properties + client.updateUserProperties(AnalyticsEvent.UserProperties(ftueUseCaseSelection: .PersonalMessaging, numSpaces: 5)) + + // Then the properties should be cached + XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.") + XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.") + XCTAssertEqual(client.pendingUserProperties?.numSpaces, 5, "The number of spaces should match.") + } + + func testMergingUserProperties() { + // Given a client with a cached use case user properties + let client = PostHogAnalyticsClient() + client.updateUserProperties(AnalyticsEvent.UserProperties(ftueUseCaseSelection: .PersonalMessaging, numSpaces: nil)) + + XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.") + XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.") + XCTAssertNil(client.pendingUserProperties?.numSpaces, "The number of spaces should not be set.") + + // When updating the number of spaced + client.updateUserProperties(AnalyticsEvent.UserProperties(ftueUseCaseSelection: nil, numSpaces: 5)) + + // Then the new properties should be updated and the existing properties should remain unchanged + XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.") + XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection shouldn't have changed.") + XCTAssertEqual(client.pendingUserProperties?.numSpaces, 5, "The number of spaces should have been updated.") + } + + func testSendingUserProperties() { + // Given a client with user properties set + let client = PostHogAnalyticsClient() + client.updateUserProperties(AnalyticsEvent.UserProperties(ftueUseCaseSelection: .PersonalMessaging, numSpaces: nil)) + client.start() + + XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.") + XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.") + + // When sending an event (tests run under Debug configuration so this is sent to the development instance) + client.screen(AnalyticsEvent.Screen(durationMs: nil, screenName: .Home)) + + // Then the properties should be cleared + XCTAssertNil(client.pendingUserProperties, "The user properties should be cleared.") + } + + func testSendingUserPropertiesWithIdentify() { + // Given a client with user properties set + let client = PostHogAnalyticsClient() + client.updateUserProperties(AnalyticsEvent.UserProperties(ftueUseCaseSelection: .PersonalMessaging, numSpaces: nil)) + client.start() + + XCTAssertNotNil(client.pendingUserProperties, "The user properties should be cached.") + XCTAssertEqual(client.pendingUserProperties?.ftueUseCaseSelection, .PersonalMessaging, "The use case selection should match.") + + // When calling identify (tests run under Debug configuration so this is sent to the development instance) + client.identify(id: UUID().uuidString) + + // Then the properties should be cleared + XCTAssertNil(client.pendingUserProperties, "The user properties should be cleared.") + } } From 98620d121da8648dfeb14745415e67e559e03f8f Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Thu, 17 Feb 2022 13:08:27 +0000 Subject: [PATCH 117/188] Translated using Weblate (Japanese) Currently translated at 61.8% (887 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 247 +++++++++++++++------------- 1 file changed, 134 insertions(+), 113 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 6ee67bd59..eca920589 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -85,7 +85,7 @@ "auth_reset_password_next_step_button" = "自分用電子メールアドレスで認証をします"; "auth_reset_password_error_unauthorized" = "電子メールアドレスの確認に失敗しました: 電子メールのリンクをクリックしたことを確認してください"; "auth_reset_password_error_not_found" = "あなたの電子メールアドレスは、接続先サーバ上のMatrix IDと関連付けられていないようです。"; -"auth_reset_password_success_message" = "あなたのパスワードは初期化されました.\n\nあなたはすべてのセッションから切断しており、プッシュ通知を受け取ることはありません。通知を再度有効にするには、各端末に再度ログインします。"; +"auth_reset_password_success_message" = "あなたのパスワードは初期化されました.\n\nあなたは全てのセッションから切断しており、プッシュ通知を受け取ることはありません。通知を再度有効にするには、各端末に再度ログインします。"; "auth_add_email_and_phone_warning" = "電子メールと電話番号の同時登録は, まだシステムが対応できません. 電話番号だけの登録は可能です. お手数おかけしますが, 後ほど個人情報設定から電子メールアドレスを登録してください."; // Chat creation "room_creation_title" = "新しい対話"; @@ -152,8 +152,8 @@ "room_participants_add_participant" = "参加者を追加"; "room_participants_one_participant" = "参加者 1名"; "room_participants_multi_participants" = "参加者 %d名"; -"room_participants_leave_prompt_title" = "ルームを出る"; -"room_participants_leave_prompt_msg" = "ルームを退室して本当によろしいですか?"; +"room_participants_leave_prompt_title" = "ルームを退出"; +"room_participants_leave_prompt_msg" = "ルームを退出してよろしいですか?"; "room_participants_remove_prompt_title" = "確認"; "room_participants_remove_prompt_msg" = "本当に %@ さんをチャットから退去させますか?"; "room_participants_remove_third_party_invite_msg" = "サードパーティの招待を削除することは、APIが存在するまでサポートされていません"; @@ -172,7 +172,7 @@ "room_participants_ago" = "前"; "room_participants_action_section_admin_tools" = "管理者権限操作"; "room_participants_action_section_direct_chats" = "対話"; -"room_participants_action_section_devices" = "セッション"; +"room_participants_action_section_devices" = "セッション一覧"; "room_participants_action_section_other" = "オプション"; "room_participants_action_invite" = "招待"; "room_participants_action_leave" = "このルームを出る"; @@ -218,7 +218,7 @@ "room_event_action_view_source" = "ソースコードを表示"; "room_event_action_report" = "発言を報告"; "room_event_action_report_prompt_reason" = "この発言を報告する理由"; -"room_event_action_report_prompt_ignore_user" = "このユーザからのすべての発言を非表示にしますか?"; +"room_event_action_report_prompt_ignore_user" = "このユーザからの全ての発言を非表示にしますか?"; "room_event_action_save" = "保存"; "room_event_action_resend" = "再送信"; "room_event_action_delete" = "削除"; @@ -228,29 +228,29 @@ "room_warning_about_encryption" = "End-to-end 暗号化はベータ版であり、信頼性が低い場合があります。\n\n発言を保護するためにはまだ信用すべきではありません。\n\n端末が参加するより前の発言履歴を復号化することはまだできません。\n\n暗号化された発言は、まだ暗号化を実装していないクライアントでは表示されません。"; "room_event_failed_to_send" = "送信失敗"; // Unknown devices -"unknown_devices_alert_title" = "部屋に未知のセッションが存在します"; -"unknown_devices_alert" = "この部屋には、確認されていない未知のセッションが含まれています。\nすなわち、セッションがをユーザ本人が所有しているという保証はありません。\n続ける前に各セッションの確認を行うことをおすすめしますが、確認することなく発言を再送信することができます。"; +"unknown_devices_alert_title" = "ルームに未知のセッションが存在します"; +"unknown_devices_alert" = "このルームには、確認されていない未知のセッションが含まれています。\nすなわち、セッションがをユーザ本人が所有しているという保証はありません。\n続ける前に各セッションの確認を行うことをおすすめしますが、確認することなく発言を再送信することができます。"; "unknown_devices_send_anyway" = "とにかく送る"; "unknown_devices_call_anyway" = "とにかく通話する"; "unknown_devices_answer_anyway" = "とにかく応答する"; "unknown_devices_verify" = "確認…"; "unknown_devices_title" = "未知のセッション"; // Room Title -"room_title_new_room" = "新しい部屋"; +"room_title_new_room" = "新しいルーム"; "room_title_multiple_active_members" = "全%@人中 %@人が回線接続"; "room_title_one_active_member" = "全%@人中 %@人が回線接続"; "room_title_invite_members" = "招待中"; "room_title_members" = "%@名の参加者"; "room_title_one_member" = "1名の参加者"; // Room Preview -"room_preview_invitation_format" = "あなたは %@ さんに呼ばれてこの部屋へ参加しました"; -"room_preview_subtitle" = "これは部屋の下見です。発言があっても部屋は更新されません。"; +"room_preview_invitation_format" = "あなたは %@ さんに呼ばれてこのルームへ参加しました"; +"room_preview_subtitle" = "これはルームのプレビューです。ルームでのやり取りは無効化されています。"; "room_preview_unlinked_email_warning" = "このアカウントに関連付けられていない %@ 宛に招待が送信されました。別のアカウントでログインするか、メールアドレスをこのアカウントに追加することができます。"; "room_preview_try_join_an_unknown_room" = "あなたは %@ へ接続しようとしています。この会議に参加しますか?"; -"room_preview_try_join_an_unknown_room_default" = "部屋"; +"room_preview_try_join_an_unknown_room_default" = "ルーム"; // Settings "settings_title" = "設定"; -"account_logout_all" = "すべてのアカウントを回線切断する"; +"account_logout_all" = "全てのアカウントを回線切断する"; "settings_config_no_build_info" = "ビルド情報がありません"; "settings_mark_all_as_read" = "全ての発言を既読にする"; "settings_report_bug" = "不具合報告"; @@ -270,7 +270,7 @@ "settings_cryptography" = "暗号化"; "settings_sign_out" = "通信完全切断"; "settings_sign_out_confirmation" = "本当によろしいですか?"; -"settings_sign_out_e2e_warn" = "あなたはend-to-end暗号鍵を紛失してしまったようです。すなわち、この端末で暗号化された部屋の昔の発言を読むことができなくなります。"; +"settings_sign_out_e2e_warn" = "あなたはend-to-end暗号鍵を紛失してしまったようです。すなわち、この端末で暗号化されたルームの昔の発言を読むことができなくなります。"; "settings_profile_picture" = "自分のアイコン画像"; "settings_display_name" = "表示名"; "settings_first_name" = "名"; @@ -288,7 +288,7 @@ "settings_enable_push_notif" = "この端末での通知"; "settings_show_decrypted_content" = "復号化された文章を表示"; "settings_global_settings_info" = "あなたの %@ webクライアント上で、全体の通知設定が可能です"; -"settings_pin_rooms_with_missed_notif" = "通知の届かなかった部屋をピン止めする"; +"settings_pin_rooms_with_missed_notif" = "逃した通知があるルームをピン止めする"; "settings_callkit_info" = "画面がロックされているときに着信がありました。Elementの着信はシステムの通話履歴で確認できます。 iCloudが有効になっている場合、この通話履歴はAppleと共有されます。"; "settings_ui_language" = "言語"; "settings_ui_theme" = "外観"; @@ -300,7 +300,7 @@ "settings_unignore_user" = "%@さんからのメッセージを見ますか?"; "settings_contacts_discover_matrix_users" = "電子メールと電話番号をユーザの検索に使用"; "settings_contacts_phonebook_country" = "電話帳の国番号"; -"settings_labs_e2e_encryption" = "End-to-End暗号"; +"settings_labs_e2e_encryption" = "エンドツーエンド暗号化"; "settings_labs_e2e_encryption_prompt_message" = "暗号化の設定を完了するためには再度ログインしてください。"; "settings_labs_matrix_apps" = "Matrixアプリ"; "settings_labs_create_conference_with_jitsi" = "jitsiの会議通話を作成する"; @@ -325,24 +325,24 @@ "settings_crypto_export" = "暗号鍵を外部へ保存"; "settings_crypto_blacklist_unverified_devices" = "検証されたセッションのみで暗号化"; // Room Details -"room_details_title" = "部屋の詳細"; +"room_details_title" = "ルームの詳細"; "room_details_people" = "参加者"; "room_details_files" = "アップロード"; "room_details_settings" = "設定"; -"room_details_photo" = "部屋の画像アイコン"; -"room_details_room_name" = "部屋名"; +"room_details_photo" = "ルームの画像アイコン"; +"room_details_room_name" = "ルーム名"; "room_details_topic" = "トピック"; "room_details_favourite_tag" = "お気に入り"; "room_details_low_priority_tag" = "低優先度"; "room_details_mute_notifs" = "発言があっても通知しない"; "room_details_direct_chat" = "対話"; -"room_details_access_section" = "誰を部屋に入室可能としますか?"; -"room_details_access_section_invited_only" = "この部屋に招待された人のみ参加可能"; -"room_details_access_section_anyone_apart_from_guest" = "誰でも部屋に参加できる (ゲストユーザは不可)"; -"room_details_access_section_anyone" = "誰でも部屋に参加できる (ゲストユーザも許可)"; -"room_details_access_section_no_address_warning" = "この部屋へのリンクを作成するには、部屋の住所表記が必要です"; -"room_details_access_section_directory_toggle" = "部屋一覧へ公開する"; -"room_details_history_section" = "誰をこの部屋の発言履歴を読めるようにしますか?"; +"room_details_access_section" = "誰をルームに入室可能としますか?"; +"room_details_access_section_invited_only" = "このルームに招待された人のみ参加可能"; +"room_details_access_section_anyone_apart_from_guest" = "誰でもルームに参加できる (ゲストユーザは不可)"; +"room_details_access_section_anyone" = "誰でもルームに参加できる (ゲストユーザも許可)"; +"room_details_access_section_no_address_warning" = "このルームへのリンクを作成するには、ルームの住所表記が必要です"; +"room_details_access_section_directory_toggle" = "ルーム一覧へ公開する"; +"room_details_history_section" = "誰をこのルームの発言履歴を読めるようにしますか?"; "room_details_history_section_anyone" = "誰でも"; "room_details_history_section_members_only" = "参加者のみ (この設定を選択した時点から)"; "room_details_history_section_members_only_since_invited" = "参加者のみ (招待を送った時点から)"; @@ -350,38 +350,38 @@ "room_details_history_section_prompt_title" = "個人情報の警告"; "room_details_history_section_prompt_msg" = "発言履歴を読むことができる人の変更は、以後の発言にのみ適用されます。既存の発言履歴の可視性は変更されません。"; "room_details_addresses_section" = "住所表記"; -"room_details_no_local_addresses" = "この部屋はサーバ内住所表記がありません"; +"room_details_no_local_addresses" = "このルームはサーバ内住所表記がありません"; "room_details_new_address" = "新しい住所表記を追加"; "room_details_new_address_placeholder" = "新しいアドレスを追加(例 #foo%@)"; "room_details_addresses_invalid_address_prompt_title" = "住所表記が正しくありません"; "room_details_addresses_invalid_address_prompt_msg" = "%@ は正しくない形式の住所表記です"; "room_details_addresses_disable_main_address_prompt_title" = "代表住所表記の警告"; -"room_details_addresses_disable_main_address_prompt_msg" = "代表住所表記が設定されていません. この部屋の代表住所表記は無作為に選択、設定されます"; +"room_details_addresses_disable_main_address_prompt_msg" = "代表住所表記が設定されていません. このルームの代表住所表記は無作為に選択、設定されます"; "room_details_banned_users_section" = "ブロックされたユーザー"; "room_details_advanced_section" = "拡張設定"; -"room_details_advanced_room_id" = "部屋の固有ID:"; -"room_details_advanced_enable_e2e_encryption" = "暗号化を開始(警告: 部屋の暗号を中止することはできません!)"; -"room_details_advanced_e2e_encryption_enabled" = "この部屋の発言は暗号化されています"; -"room_details_advanced_e2e_encryption_disabled" = "この部屋の発言は暗号化されていません。"; +"room_details_advanced_room_id" = "ルームの固有ID:"; +"room_details_advanced_enable_e2e_encryption" = "暗号化を開始(警告: ルームの暗号を中止することはできません!)"; +"room_details_advanced_e2e_encryption_enabled" = "このルームの発言は暗号化されています"; +"room_details_advanced_e2e_encryption_disabled" = "このルームの発言は暗号化されていません。"; "room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "検証されたセッションのみで暗号化"; -"room_details_fail_to_update_avatar" = "部屋のアイコン画像の更新に失敗しました"; -"room_details_fail_to_update_room_name" = "部屋名の更新に失敗しました"; -"room_details_fail_to_update_topic" = "部屋の説明の更新に失敗しました"; -"room_details_fail_to_update_room_guest_access" = "部屋のゲスト参加者設定の更新に失敗しました"; +"room_details_fail_to_update_avatar" = "ルームのアイコン画像の更新に失敗しました"; +"room_details_fail_to_update_room_name" = "ルーム名の更新に失敗しました"; +"room_details_fail_to_update_topic" = "ルームの説明の更新に失敗しました"; +"room_details_fail_to_update_room_guest_access" = "ルームのゲスト参加者設定の更新に失敗しました"; "room_details_fail_to_update_room_join_rule" = "入室規則の更新に失敗しました"; -"room_details_fail_to_update_room_directory_visibility" = "部屋一覧の可視設定の更新に失敗しました"; +"room_details_fail_to_update_room_directory_visibility" = "ルーム一覧の可視設定の更新に失敗しました"; "room_details_fail_to_update_history_visibility" = "発言履歴の可視範囲の設定更新に失敗しました"; -"room_details_fail_to_add_room_aliases" = "部屋住所の新規追加に失敗しました"; -"room_details_fail_to_remove_room_aliases" = "部屋住所の削除に失敗しました"; -"room_details_fail_to_update_room_canonical_alias" = "代表部屋住所の更新に失敗しました"; -"room_details_fail_to_update_room_direct" = "部屋の対話タグの変更に失敗しました"; -"room_details_fail_to_enable_encryption" = "部屋の暗号化の開始に失敗しました"; +"room_details_fail_to_add_room_aliases" = "ルーム住所の新規追加に失敗しました"; +"room_details_fail_to_remove_room_aliases" = "ルーム住所の削除に失敗しました"; +"room_details_fail_to_update_room_canonical_alias" = "代表ルーム住所の更新に失敗しました"; +"room_details_fail_to_update_room_direct" = "ルームの対話タグの変更に失敗しました"; +"room_details_fail_to_enable_encryption" = "ルームの暗号化の開始に失敗しました"; "room_details_save_changes_prompt" = "変更を保存しますか?"; "room_details_set_main_address" = "代表住所表記を設定"; "room_details_unset_main_address" = "代表住所表記を設定解除"; -"room_details_copy_room_id" = "部屋固有IDをコピー"; -"room_details_copy_room_address" = "部屋の住所表記をコピー"; -"room_details_copy_room_url" = "部屋のURLをコピー"; +"room_details_copy_room_id" = "ルーム固有IDをコピー"; +"room_details_copy_room_address" = "ルームの住所表記をコピー"; +"room_details_copy_room_url" = "ルームのURLをコピー"; // Read Receipts "read_receipts_list" = "既読一覧を見る"; "receipt_status_read" = "既読状況: "; @@ -389,11 +389,11 @@ "media_picker_library" = "ライブラリ"; "media_picker_select" = "選択"; // Directory -"directory_title" = "部屋一覧"; -"directory_server_picker_title" = "部屋一覧を選択"; -"directory_server_all_rooms" = "%@ サーバ上の全ての部屋"; -"directory_server_all_native_rooms" = "全てのMatrix連携部屋"; -"directory_server_type_homeserver" = "公開部屋一覧を表示するための接続サーバを入力してください"; +"directory_title" = "ルーム一覧"; +"directory_server_picker_title" = "ルーム一覧を選択"; +"directory_server_all_rooms" = "%@ サーバ上の全てのルーム"; +"directory_server_all_native_rooms" = "全てのMatrix連携ルーム"; +"directory_server_type_homeserver" = "公開ルーム一覧を表示するための接続サーバを入力してください"; "directory_server_placeholder" = "matrix.org"; // Events formatter "event_formatter_member_updates" = "%tu 権限が変更されました"; @@ -407,7 +407,7 @@ "today" = "今日"; "yesterday" = "昨日"; "network_offline_prompt" = "インターネットへの接続が切れているようです。"; -"public_room_section_title" = "公開部屋 (at %@):"; +"public_room_section_title" = "公開ルーム (at %@):"; "bug_report_prompt" = "前回アプリが異常終了しました。不具合報告を送信しますか?"; "rage_shake_prompt" = "あなたは不満があって端末を揺らしているようです。不具合報告をしますか?"; "do_not_ask_again" = "再度質問しない"; @@ -446,33 +446,33 @@ "bug_report_progress_uploading" = "報告を送信しています"; "bug_report_send" = "送信"; // Widget -"widget_no_power_to_manage" = "あなたがこの部屋でウィジェットを管理するための権限が必要です"; +"widget_no_power_to_manage" = "あなたがこのルームでウィジェットを管理するための権限が必要です"; "widget_creation_failure" = "ウィジェットの作成に失敗しました"; // Widget Integration Manager "widget_integration_need_to_be_able_to_invite" = "それを行うにはユーザを招待する権限が必要です。"; "widget_integration_unable_to_create" = "ウィジェットを作成できません。"; "widget_integration_failed_to_send_request" = "リクエストの送信に失敗しました。"; -"widget_integration_room_not_recognised" = "この部屋では認められません。"; +"widget_integration_room_not_recognised" = "このルームでは認められません。"; "widget_integration_positive_power_level" = "権限の数値は正の整数で入力してください。"; -"widget_integration_must_be_in_room" = "あなたはこの部屋に所属していません。"; -"widget_integration_no_permission_in_room" = "あなたはこの部屋で権限がありません。"; -"widget_integration_missing_room_id" = "部屋固有IDの要求に失敗しました。"; +"widget_integration_must_be_in_room" = "あなたはこのルームに所属していません。"; +"widget_integration_no_permission_in_room" = "あなたはこのルームで権限がありません。"; +"widget_integration_missing_room_id" = "ルーム固有IDの要求に失敗しました。"; "widget_integration_missing_user_id" = "ユーザ固有IDの要求に失敗しました。"; -"widget_integration_room_not_visible" = "部屋 %@ は見えません。"; +"widget_integration_room_not_visible" = "ルーム %@ は見えません。"; // Share extension "share_extension_auth_prompt" = "コンテンツを共有するためにメインのアプリにログインする"; -"share_extension_failed_to_encrypt" = "送信に失敗しました。この部屋の暗号設定をメインの端末で確認して下さい"; +"share_extension_failed_to_encrypt" = "送信に失敗しました。このルームの暗号設定をメインの端末で確認して下さい"; "room_details_advanced_e2e_encryption_prompt_message" = "End-to-end暗号化は実験的なものであり、信頼性が低い場合があります。\n\n発言を保護するためにはまだそれを信用すべきではありません。\n\n端末は、まだ参加する前の発言履歴を復号化することはできません。\n\n部屋の暗号化が今から有効になったら、もう無効にすることはできません。\n\n暗号化された発言は、まだ暗号化を実装していないアプリでは表示されません。"; "settings_enable_callkit" = "呼び出しの統合"; -"settings_pin_rooms_with_unread" = "未読のある部屋をピン止めする"; -"title_groups" = "コミュニティ"; +"settings_pin_rooms_with_unread" = "未読のあるルームをピン止めする"; +"title_groups" = "コミュニティー"; "room_recents_server_notice_section" = "システムアラート"; // Groups tab "group_invite_section" = "招待"; -"group_section" = "コミュニティ"; +"group_section" = "コミュニティー"; "room_message_reply_to_placeholder" = "返信を送る (暗号化されていない)…"; "room_do_not_have_permission_to_post" = "このルームに投稿する権限がありません"; -"encrypted_room_message_reply_to_placeholder" = "暗号化された返信を送る…"; +"encrypted_room_message_reply_to_placeholder" = "暗号化された返信を送信…"; "room_message_reply_to_short_placeholder" = "返信を送る…"; "room_event_action_view_decrypted_source" = "復号化されたソースを見る"; "room_event_action_kick_prompt_reason" = "このユーザーを追放する理由"; @@ -480,7 +480,7 @@ "room_action_send_sticker" = "スタンプ送信"; "room_replacement_information" = "このルームは交換されており、もうアクティブではありません。"; "room_replacement_link" = "会話はここで続けられます。"; -"room_predecessor_information" = "この部屋は別の会話の続きです。"; +"room_predecessor_information" = "このルームは別の会話の続きです。"; "room_predecessor_link" = "より古いメッセージを見るにはここをタップしてください。"; "room_resource_limit_exceeded_message_contact_2_link" = "サービス管理者に連絡する"; "room_resource_limit_exceeded_message_contact_3" = " このサービスの使用を継続するには。"; @@ -492,22 +492,22 @@ "settings_labs_room_members_lazy_loading" = "遅延ロードルームのメンバー"; "settings_labs_room_members_lazy_loading_error_message" = "あなたのホームサーバーはまだルームメンバーの遅延ロードをサポートしていません。 後で試してください。"; "settings_deactivate_my_account" = "アカウントを無効にします"; -"room_details_flair_section" = "コミュニティの特色を表示"; -"room_details_new_flair_placeholder" = "新しいコミュニティIDを追加 (例 +foo%@)"; +"room_details_flair_section" = "コミュニティーの特色を表示"; +"room_details_new_flair_placeholder" = "新しいコミュニティーIDを追加 (例 +foo%@)"; "room_details_flair_invalid_id_prompt_title" = "無効な形式"; -"room_details_flair_invalid_id_prompt_msg" = "%@はコミュニティの有効な識別子ではありません"; -"room_details_fail_to_update_room_communities" = "関連コミュニティを更新できない"; +"room_details_flair_invalid_id_prompt_msg" = "%@はコミュニティーの有効な識別子ではありません"; +"room_details_fail_to_update_room_communities" = "関連コミュニティーを更新できない"; // Group Details -"group_details_title" = "コミュニティの詳細"; +"group_details_title" = "コミュニティーの詳細"; "group_details_home" = "ホーム"; "group_details_people" = "人々"; -"group_details_rooms" = "部屋"; +"group_details_rooms" = "ルーム"; // Group Home "group_home_one_member_format" = "1 メンバー"; "group_home_multi_members_format" = "%tu メンバー"; -"group_home_one_room_format" = "1 部屋"; -"group_home_multi_rooms_format" = "%tu 部屋"; -"group_invitation_format" = "%@がこのコミュニティにあなたを招待しました"; +"group_home_one_room_format" = "1 ルーム"; +"group_home_multi_rooms_format" = "%tu ルーム"; +"group_invitation_format" = "%@がこのコミュニティーにあなたを招待しました"; // Group participants "group_participants_add_participant" = "参加者を追加"; "group_participants_leave_prompt_title" = "グループを退出"; @@ -516,13 +516,13 @@ "group_participants_remove_prompt_msg" = "本当にこのグループから%@を削除しますか?"; "group_participants_invite_prompt_title" = "確認"; "group_participants_invite_prompt_msg" = "本当にこのグループに%@を招待しますか?"; -"group_participants_filter_members" = "コミュニティメンバーをフィルタリング"; +"group_participants_filter_members" = "コミュニティーメンバーをフィルタリング"; "group_participants_invite_another_user" = "ユーザーIDまたは名前による検索/招待"; "group_participants_invite_malformed_id_title" = "招待エラー"; "group_participants_invite_malformed_id" = "不正なID。 '@localpart:domain' のようなMatrix IDでなければなりません"; "group_participants_invited_section" = "招待した"; // Group rooms -"group_rooms_filter_rooms" = "コミュニティルームをフィルタリング"; +"group_rooms_filter_rooms" = "コミュニティールームをフィルタリング"; "event_formatter_rerequest_keys_part1_link" = "暗号鍵の再要求"; "event_formatter_rerequest_keys_part2" = " あなたの他のセッションから。"; "homeserver_connection_lost" = "ホームサーバーに接続できませんでした。"; @@ -539,12 +539,12 @@ "gdpr_consent_not_given_alert_message" = "%@ホームサーバーを引き続き使用するには、利用規約を確認して同意する必要があります。"; "gdpr_consent_not_given_alert_review_now_action" = "今レビュー"; "deactivate_account_title" = "無効なアカウント"; -"deactivate_account_informations_part1" = "これにより、アカウントは永久に使用できなくなります。 ログインすることはできず、誰も同じユーザーIDを再登録することはできません。 これにより、あなたのアカウントは参加しているすべての部屋から退去し、あなたのIDサーバーからアカウントの詳細が削除されます。 "; +"deactivate_account_informations_part1" = "これにより、アカウントは永久に使用できなくなります。 ログインすることはできず、誰も同じユーザーIDを再登録することはできません。 これにより、あなたのアカウントは参加している全てのルームから退去し、あなたのIDサーバーからアカウントの詳細が削除されます。 "; "deactivate_account_informations_part2_emphasize" = "この動作は元に戻せません。"; "deactivate_account_informations_part3" = "\n\nアカウントの無効化 "; "deactivate_account_informations_part4_emphasize" = "デフォルトではあなたが送信したメッセージを忘れることはありません。 "; "deactivate_account_informations_part5" = "あなたのメッセージを忘れたければ、下のボックスにチェックを入れてください\n\nMatrixのメッセージの可視性はEメールと似ています。 forgettingメッセージは、送信したメッセージは新規または未登録のユーザーと共有されませんが、既にこれらのメッセージにアクセスしている登録ユーザーは引き続き自分のコピーにアクセスできます。"; -"deactivate_account_forget_messages_information_part1" = "アカウントが無効になったときに送信したすべてのメッセージを忘れてください ("; +"deactivate_account_forget_messages_information_part1" = "アカウントが無効になったときに送信した全てのメッセージを忘れてください ("; "deactivate_account_forget_messages_information_part2_emphasize" = "警告"; "deactivate_account_forget_messages_information_part3" = ":これは将来のユーザーに会話の不完全なビューが表示される)"; "deactivate_account_validate_action" = "無効なアカウント"; @@ -573,22 +573,22 @@ "room_info_list_one_member" = "1 人のメンバー"; "create_room_placeholder_address" = "#testroom:matrix.org"; -"create_room_section_header_address" = "部屋のアドレス"; -"create_room_show_in_directory" = "この部屋をディレクトリに掲載する"; -"create_room_section_footer_type" = "プライベートな部屋は、部屋に招待された人のみ参加できます。"; -"create_room_type_public" = "公開された部屋"; -"create_room_type_private" = "プライベートな部屋"; -"create_room_section_header_type" = "部屋の種類"; +"create_room_section_header_address" = "ルームのアドレス"; +"create_room_show_in_directory" = "このルームをディレクトリに掲載する"; +"create_room_section_footer_type" = "プライベートなルームは、ルームに招待された人のみ参加できます。"; +"create_room_type_public" = "公開されたルーム"; +"create_room_type_private" = "プライベートなルーム"; +"create_room_section_header_type" = "ルームの種類"; "create_room_section_footer_encryption" = "暗号化はあとから無効にすることはできません。"; -"create_room_section_header_encryption" = "部屋の暗号化"; +"create_room_section_header_encryption" = "ルームの暗号化"; "create_room_placeholder_topic" = "トピック"; -"create_room_section_header_topic" = "部屋のトピック (任意)"; +"create_room_section_header_topic" = "ルームのトピック (任意)"; "create_room_placeholder_name" = "名前"; -"create_room_section_header_name" = "部屋の名前"; +"create_room_section_header_name" = "ルーム名"; // MARK: - Create Room -"create_room_title" = "新しい部屋"; +"create_room_title" = "新しいルーム"; "create_room_enable_encryption" = "暗号化を有効にする"; "room_details_room_name_for_dm" = "名前"; "room_participants_security_information_room_encrypted_for_dm" = "ここで送受信されるメッセージはエンドツーエンド暗号化されます。\n\nメッセージは安全に保護されており、あなたと宛先のみがメッセージの閲覧に必要な鍵を所持します。"; @@ -632,7 +632,7 @@ // Widget Picker "widget_picker_title" = "インテグレーションマネージャー"; "widget_integration_manager_disabled" = "設定でインテグレーションマネージャーを有効にする必要があります"; -"widget_menu_remove" = "すべて取り除く"; +"widget_menu_remove" = "全て取り除く"; "widget_menu_revoke_permission" = "アクセスを取り消す"; "widget_menu_open_outside" = "ブラウザを開く"; "widget_menu_refresh" = "リフレッシュ"; @@ -685,7 +685,7 @@ "room_details_access_section_for_dm" = "誰がアクセスできるのか?"; "room_details_photo_for_dm" = "写真"; "room_details_integrations" = "インテグレーション"; -"room_details_search" = "部屋(ルーム)を探す"; +"room_details_search" = "ルーム(部屋)を探す"; "room_details_title_for_dm" = "詳細"; "identity_server_settings_alert_error_invalid_identity_server" = "%@は有効なIDサーバーではありません。"; "identity_server_settings_alert_error_terms_not_accepted" = "IDサーバーとして設定するには%@の条件を受け入れる必要があります。"; @@ -705,8 +705,8 @@ "identity_server_settings_place_holder" = "IDサーバーを入力する"; "identity_server_settings_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり、発見できるようにするには、上記に追加してください。"; "identity_server_settings_description" = "あなたは%@を使って、あなたの知り合いを発見し、また向こうから発見できるようにしています。"; -"security_settings_complete_security_alert_title" = "セキュリティを完了します"; -"security_settings_crosssigning_complete_security" = "セキュリティーを完了する"; +"security_settings_complete_security_alert_title" = "完全なセキュリティー"; +"security_settings_crosssigning_complete_security" = "完全なセキュリティー"; "security_settings_crosssigning_bootstrap" = "独立したクロス署名"; "settings_devices_description" = "セッションのパブリックネームはコミュニケーションをとる相手に表示されます"; "settings_key_backup_delete_confirmation_prompt_title" = "バックアップの削除"; @@ -727,7 +727,7 @@ "room_multiple_typing_notification" = "%@とその他のユーザーが入力中です"; "external_link_confirmation_message" = "リンク%@は別のサイトに移動します: %@\n\n本当に続けますか?"; "room_event_action_delete_confirmation_title" = "未送信メッセージを削除"; -"room_unsent_messages_cancel_message" = "このルームにある未送信のメッセージをすべて削除してもよろしいですか?"; +"room_unsent_messages_cancel_message" = "このルームにある未送信のメッセージを全て削除してもよろしいですか?"; "room_unsent_messages_cancel_title" = "未送信メッセージを削除"; "room_message_replying_to" = "%@に返信中"; "room_message_editing" = "編集中"; @@ -741,15 +741,15 @@ "room_participants_security_loading" = "読み込み中…"; "room_participants_action_security_status_loading" = "読み込み中…"; "room_participants_action_security_status_warning" = "警告"; -"room_participants_action_security_status_complete_security" = "セキュリティーを完了する"; +"room_participants_action_security_status_complete_security" = "完全なセキュリティー"; "room_participants_action_security_status_verify" = "検証"; "room_participants_action_security_status_verified" = "検証済み"; -"room_participants_action_section_security" = "セキュリティ"; +"room_participants_action_section_security" = "セキュリティー"; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "IDサーバーが設定されていないため、メールアドレスを使って連絡先とチャットを開始することができません。"; "room_participants_filter_room_members_for_dm" = "メンバーをフィルター"; "room_participants_remove_third_party_invite_prompt_msg" = "招待を取り消してよろしいですか?"; "room_participants_leave_prompt_msg_for_dm" = "退出してよろしいですか?"; -"room_participants_leave_prompt_title_for_dm" = "退出する"; +"room_participants_leave_prompt_title_for_dm" = "退出"; "contacts_address_book_no_identity_server" = "IDサーバーが設定されていません"; "rooms_empty_view_information" = "ルームはプライベートでもパブリックでも、あらゆるグループチャットに最適です。+をタップすると、既にあるルームを見つけたり、新しいルームを作ることができます。"; "rooms_empty_view_title" = "ルーム"; @@ -768,9 +768,9 @@ // Social login "social_login_list_title_continue" = "続きはこちら"; -"auth_softlogout_clear_data_sign_out_msg" = "このデバイスに現在保存されているすべてのデータを消去してよろしいですか?再びサインインするとアカウントデータやメッセージにアクセスできます。"; -"auth_softlogout_clear_data_sign_out_title" = "本当によろしいですか?"; -"auth_softlogout_clear_data_button" = "すべてのデータをクリアする"; +"auth_softlogout_clear_data_sign_out_msg" = "このデバイスに現在保存されている全てのデータを消去してよろしいですか?再びサインインするとアカウントデータやメッセージにアクセスできます。"; +"auth_softlogout_clear_data_sign_out_title" = "続行してよろしいですか?"; +"auth_softlogout_clear_data_button" = "全てのデータをクリアする"; "auth_softlogout_clear_data_message_2" = "このデバイスの使用を終了する場合や、別のアカウントにサインインしたい場合は、クリアしてください。"; "auth_softlogout_clear_data_message_1" = "警告: 個人データ(暗号化キーを含む)がこのデバイスにまだ保存されています。"; "callbar_return" = "かけ直す"; @@ -779,7 +779,7 @@ "callbar_only_single_paused" = "通話の一時停止"; "store_promotional_text" = "オープンネットワーク上でプライバシーを保護したチャットアプリ。あなた自身でコントロールできるように非中央集権化(分散化)されています。データマイニング、バックドア、サードパーティによるアクセスはありません。"; "auth_softlogout_clear_data" = "個人データをクリアする"; -"auth_softlogout_recover_encryption_keys" = "サインインして、このデバイスにのみ保存されている暗号化キーを復元します。どのデバイスでも、あなたのセキュアなメッセージをすべて読むために必要です。"; +"auth_softlogout_recover_encryption_keys" = "サインインして、このデバイスにのみ保存されている暗号化キーを復元します。どのデバイスでも、あなたのセキュアなメッセージを全て読むために必要です。"; "auth_softlogout_reason" = "ホームサーバー(%1$@)の管理者が%2$@(%3$@)からサインアウトさせました。"; "auth_softlogout_sign_in" = "サインイン"; "auth_softlogout_signed_out" = "サインアウトしました"; @@ -813,16 +813,16 @@ "manage_session_title" = "セッションを管理"; "security_settings_user_password_description" = "アカウントのパスワードを入力して本人確認を行う"; "security_settings_coming_soon" = "申し訳ありません。このアクションはElement iOSではまだ利用できません。他のMatrixクライアントを使って設定してください。将来的にはElement iOSでも実装される予定です。"; -"security_settings_complete_security_alert_message" = "現在のセッションのセキュリティを完了させる必要があります。"; -"security_settings_blacklist_unverified_devices_description" = "すべてのセッションを検証して、信頼できるものとしてマークしメッセージを送信します。"; +"security_settings_complete_security_alert_message" = "現在のセッションのセキュリティーを完了させる必要があります。"; +"security_settings_blacklist_unverified_devices_description" = "全てのセッションを検証して、信頼できるものとしてマークしメッセージを送信します。"; "security_settings_blacklist_unverified_devices" = "信頼していないセッションにはメッセージを送信しない"; "security_settings_advanced" = "上級者向け"; "security_settings_export_keys_manually" = "手動でキーをエクスポートする"; "security_settings_cryptography" = "暗号技術"; "security_settings_crosssigning_reset" = "クロス署名をリセット"; "security_settings_crosssigning_info_ok" = "クロス署名が有効です。"; -"security_settings_crosssigning_info_trusted" = "クロス署名が有効になっています。クロス署名に基づいて他のユーザーや自分の他のセッションを信頼することはできますが、このセッションにはクロス署名用の秘密鍵がないため、このセッションからクロス署名を行うことはできません。このセッションのセキュリティを完了してください。"; -"security_settings_crosssigning_info_exists" = "アカウントにはクロス署名IDがありますが、このセッションはまだ信頼されていません。 このセッションのセキュリティを完了してください。"; +"security_settings_crosssigning_info_trusted" = "クロス署名が有効になっています。クロス署名に基づいて他のユーザーや自分の他のセッションを信頼することはできますが、このセッションにはクロス署名用の秘密鍵がないため、このセッションからクロス署名を行うことはできません。このセッションのセキュリティーを完了してください。"; +"security_settings_crosssigning_info_exists" = "アカウントにはクロス署名IDがありますが、このセッションはまだ信頼されていません。 このセッションのセキュリティーを完了してください。"; "security_settings_crosssigning_info_not_bootstrapped" = "クロス署名がまだ行われていません。"; "security_settings_crosssigning" = "クロス署名"; "security_settings_backup" = "メッセージのバックアップ"; @@ -836,7 +836,7 @@ "security_settings_crypto_sessions" = "セッション"; // Security settings -"security_settings_title" = "セキュリティ"; +"security_settings_title" = "セキュリティー"; "settings_show_NSFW_public_rooms" = "NSFWパブリックルームを表示する"; "settings_identity_server_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり発見されるようにするには1つ連絡先を追加します。"; "settings_identity_server_no_is" = "IDサーバーが設定されていません"; @@ -852,7 +852,7 @@ "settings_discovery_error_message" = "エラーが発生しました。再試行してください。"; "settings_discovery_three_pids_management_information_part3" = "。"; "settings_discovery_three_pids_management_information_part2" = "ユーザー設定"; -"settings_discovery_three_pids_management_information_part1" = "他のユーザーがあなたを発見したり、部屋に招待する際に使用するメールアドレスや電話番号を管理できます。このリストにメールアドレスや電話番号を追加したり、削除したりすることができます。 "; +"settings_discovery_three_pids_management_information_part1" = "他のユーザーがあなたを発見したり、ルームに招待する際に使用するメールアドレスや電話番号を管理できます。このリストにメールアドレスや電話番号を追加したり、削除したりすることができます。 "; "settings_discovery_terms_not_signed" = "メールアドレスや電話番号で自分を発見できるようにするには、IDサーバー(%@)の利用規約に同意する必要があります。"; "settings_discovery_no_identity_server" = "現在、IDサーバーを使用していません。知り合いがあなたを発見できるようにするには、IDサーバーを追加してください。"; "settings_key_backup_delete_confirmation_prompt_msg" = "よろしいですか?鍵が適切にバックアップされていないと、暗号化されたメッセージを失うことがあります。"; @@ -873,10 +873,10 @@ "settings_key_backup_info" = "暗号化されたメッセージはエンドツーエンドで暗号化されています。送信者と受信者だけがこのメッセージを読むための鍵を持っています。"; "settings_labs_message_reaction" = "絵文字でメッセージに反応する"; "settings_calls_stun_server_fallback_description" = "ホームサーバーがフォールバックコールアシストサーバーを提供していない場合は%@を許可します(IPアドレスは通話中に共有されます)。"; -"settings_security" = "セキュリティ"; +"settings_security" = "セキュリティー"; "settings_three_pids_management_information_part3" = ""; "settings_three_pids_management_information_part2" = "ディスカバリー"; -"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データ収集、バックドア、ユーザーの囲い込みから逃れることができます。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementはあなた自身でサーバーをホストすることも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、あなたは他のElementユーザーと話せるだけでなくオープンネットワークへのアクセスも可能です。\n\nElementは、オープンな分散型通信の標準規格であるMatrixで動作するため、これらすべてを実現することができています。\n\nどのサーバーがホストするか決めることができます。さまざまな方法で選択できます。\n\n1. 開発者がホストするmatrix.orgの公開サーバーで無料のアカウントを取得します。\n2. あなた自身がサーバーを動かし、アカウントを管理します。\n3. Element Matrix Servicesのホスティングプラットフォームに登録することで、カスタムサーバー上のアカウントを取得できます。\n\nなぜElementを選ぶべきなのか?\n\nデータを所有する: 自分でデータやメッセージを保管する場所を決めることができます。あなたが所有権を持ってコントロールすることで、第三者にあなたのデータを渡したり、ビッグデータを収集する巨大テック企業に依存する必要がなくなります。\n\n開かれたネットワークと共同作業: Matrixネットワーク内の他の誰とでも、あるいはElementや他のMatrixアプリを使っているかどうかに関わらず、またSlack、IRC、XMPPのような他のメッセージングシステムを使っているかどうかに関わらず、チャットすることができます。\n\nとても安全: 本物のエンドツーエンド暗号化(会話に参加している者のみがメッセージを読める)と会話参加者の真正性を確認するためクロス署名によって。\n\n完全なるコミュニケーションの訪れ: テキスト、音声通話、ビデオ通話、ファイル共有、画面共有、連携機能、ボット、ウィジェットなどのコミュニケーションに必要な機能の全てが実装されています。ルームやコミュニティを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでもどこにいても: すべてのデバイスとウェブでメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。https://app.element.io"; +"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データ収集、バックドア、ユーザーの囲い込みから逃れることができます。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementはあなた自身でサーバーをホストすることも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、あなたは他のElementユーザーと話せるだけでなくオープンネットワークへのアクセスも可能です。\n\nElementは、オープンな分散型通信の標準規格であるMatrixで動作するため、これら全てを実現することができています。\n\nどのサーバーがホストするか決めることができます。さまざまな方法で選択できます。\n\n1. 開発者がホストするmatrix.orgの公開サーバーで無料のアカウントを取得します。\n2. あなた自身がサーバーを動かし、アカウントを管理します。\n3. Element Matrix Servicesのホスティングプラットフォームに登録することで、カスタムサーバー上のアカウントを取得できます。\n\nなぜElementを選ぶべきなのか?\n\nデータを所有する: 自分でデータやメッセージを保管する場所を決めることができます。あなたが所有権を持ってコントロールすることで、第三者にあなたのデータを渡したり、ビッグデータを収集する巨大テック企業に依存する必要がなくなります。\n\n開かれたネットワークと共同作業: Matrixネットワーク内の他の誰とでも、あるいはElementや他のMatrixアプリを使っているかどうかに関わらず、またSlack、IRC、XMPPのような他のメッセージングシステムを使っているかどうかに関わらず、チャットすることができます。\n\nとても安全: 本物のエンドツーエンド暗号化(会話に参加している者のみがメッセージを読める)と会話参加者の真正性を確認するためクロス署名によって。\n\n完全なるコミュニケーションの訪れ: テキスト、音声通話、ビデオ通話、ファイル共有、画面共有、連携機能、ボット、ウィジェットなどのコミュニケーションに必要な機能の全てが実装されています。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでもどこにいても: 全てのデバイスとウェブでメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。https://app.element.io"; "user_verification_session_details_additional_information_untrusted_other_user" = "ユーザーがこのセッションを信頼するまでは、セッションとの間で送受信されるメッセージには警告が表示されます。また、手動で検証することもできます。"; "user_verification_session_details_information_untrusted_other_user" = " 新しいセッションを使ってサインインしました:"; "user_verification_session_details_information_untrusted_current_user" = "このセッションを検証することで、信頼できるものとしてマークし、暗号化されたメッセージへのアクセスを許可します。"; @@ -891,7 +891,7 @@ "user_verification_sessions_list_session_untrusted" = "信頼できない"; "user_verification_sessions_list_session_trusted" = "信頼済み"; "user_verification_sessions_list_table_title" = "セッション一覧"; -"user_verification_sessions_list_information" = "この部屋にいるこのユーザーとのメッセージはエンドツーエンドで暗号化されており第三者が読み取ることはできません。"; +"user_verification_sessions_list_information" = "このルームにいるこのユーザーとのメッセージはエンドツーエンドで暗号化されており第三者が読み取ることはできません。"; "user_verification_sessions_list_user_trust_level_unknown_title" = "未知"; "user_verification_sessions_list_user_trust_level_warning_title" = "警告"; @@ -901,7 +901,7 @@ "user_verification_start_additional_information" = "安心してご利用いただくために、直接お会いするか、別の方法でご連絡ください。"; "user_verification_start_waiting_partner" = "%@を待っています…"; "user_verification_start_information_part2" = " 両方のデバイスでワンタイムコードを確認します。"; -"user_verification_start_information_part1" = "セキュリティを高めるために "; +"user_verification_start_information_part1" = "セキュリティーを高めるために "; // MARK: - User verification @@ -1002,7 +1002,7 @@ "external_link_confirmation_title" = "このリンクを再確認してください"; "media_type_accessibility_sticker" = "スティッカー"; "media_type_accessibility_file" = "ファイル"; -"media_type_accessibility_location" = "場所"; +"media_type_accessibility_location" = "ロケーション"; "media_type_accessibility_video" = "動画"; "media_type_accessibility_audio" = "音声"; "media_type_accessibility_image" = "画像"; @@ -1021,11 +1021,11 @@ "room_action_camera" = "写真やビデオの撮影"; "room_event_action_reaction_history" = "反応の履歴"; "room_event_action_reaction_show_less" = "表示しない"; -"room_event_action_reaction_show_all" = "すべてを見る"; +"room_event_action_reaction_show_all" = "全てを見る"; "room_event_action_edit" = "編集"; "room_event_action_reply" = "返信"; "device_verification_security_advice_emoji" = "絵文字の順番はもう一方のログインと一致しますか?"; -"key_verification_verify_sas_validate_action" = "一致します"; +"key_verification_verify_sas_validate_action" = "一致しています"; "key_verification_verify_sas_cancel_action" = "一致しません"; // MARK: Verify @@ -1038,8 +1038,8 @@ // New login "device_verification_self_verify_alert_title" = "ログインしましたか?"; -"room_recents_suggested_rooms_section" = "おすすめの部屋"; -"settings_show_url_previews_description" = "プレビューは暗号化されていない部屋でのみ表示されます。"; +"room_recents_suggested_rooms_section" = "おすすめのルーム"; +"settings_show_url_previews_description" = "プレビューは暗号化されていないルームでのみ表示されます。"; "settings_show_url_previews" = "ウェブサイトプレビューを表示"; "biometrics_setup_enable_button_title_x" = "%@ を有効にする"; "biometrics_setup_title_x" = "%@ を有効にする"; @@ -1052,7 +1052,7 @@ "pin_protection_settings_enable_pin" = "PIN を有効にする"; "pin_protection_settings_section_header_with_biometrics" = "PIN と %@"; "pin_protection_settings_section_header" = "PIN"; -"settings_mentions_and_keywords_encryption_notice" = "モバイルでは、暗号化された部屋でのメンションとキーワードの通知は受信できません。"; +"settings_mentions_and_keywords_encryption_notice" = "モバイルでは、暗号化されたルームでのメンションとキーワードの通知は受信できません。"; "settings_new_keyword" = "キーワードを追加"; "settings_your_keywords" = "以下でキーワードを指定できます"; "settings_mentions_and_keywords" = "メンションとキーワード"; @@ -1074,3 +1074,24 @@ "spaces_home_space_title" = "ホーム"; "spaces_left_panel_title" = "スペース"; "spaces_suggested_room" = "おすすめ"; + +// MARK: Self verification wait + +"device_verification_self_verify_wait_title" = "完全なセキュリティー"; +"location_sharing_open_google_maps" = "Googleマップで開く"; +"location_sharing_settings_toggle_title" = "ロケーションの共有を有効にする"; +"threads_empty_show_all_threads" = "全てのスレッドを表示"; +"room_join_group_call" = "参加する"; +"room_accessibility_threads" = "スレッド"; +"threads_action_my_threads" = "自分のスレッド"; +"threads_action_all_threads" = "全てのスレッド"; +"threads_title" = "スレッド"; + +// MARK: Threads +"room_thread_title" = "スレッド"; +"thread_copy_link_to_thread" = "スレッドへのリンクをコピー"; +"room_event_action_reply_in_thread" = "スレッド"; +"settings_room_upgrades" = "ルームのアップグレード"; +"settings_messages_by_a_bot" = "ボットによるメッセージ"; +"settings_call_invitations" = "通話への招待"; +"settings_room_invitations" = "ルームへの招待"; From 41bcd9a5abfbaf32df0f028d2f95381cd158b97c Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Thu, 17 Feb 2022 13:09:59 +0000 Subject: [PATCH 118/188] Translated using Weblate (Japanese) Currently translated at 61.8% (887 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index eca920589..53df7b651 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -741,7 +741,7 @@ "room_participants_security_loading" = "読み込み中…"; "room_participants_action_security_status_loading" = "読み込み中…"; "room_participants_action_security_status_warning" = "警告"; -"room_participants_action_security_status_complete_security" = "完全なセキュリティー"; +"room_participants_action_security_status_complete_security" = "セキュリティを確認する"; "room_participants_action_security_status_verify" = "検証"; "room_participants_action_security_status_verified" = "検証済み"; "room_participants_action_section_security" = "セキュリティー"; From e10c0d95a2d2914fa4849899246f765f20b0d557 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 17:45:01 +0100 Subject: [PATCH 119/188] PlainRoomTimelineCellDecorator: Handle read marker add and animation. --- .../PlainRoomTimelineCellDecorator.swift | 83 +++++++++++++++++++ .../Styles/RoomTimelineCellDecorator.swift | 10 +++ 2 files changed, 93 insertions(+) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift index 509e44870..c32070d64 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/PlainRoomTimelineCellDecorator.swift @@ -148,6 +148,7 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { trailingConstraint, topConstraint ]) + } } @@ -203,4 +204,86 @@ class PlainRoomTimelineCellDecorator: RoomTimelineCellDecorator { func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell, withFailedEventIds failedEventIds: Set) { cell.updateTickView(withFailedEventIds: failedEventIds) } + + func addReadMarkerView(_ readMarkerView: UIView, + toCell cell: MXKRoomBubbleTableViewCell, + cellData: MXKRoomBubbleCellData, + contentViewPositionY: CGFloat) { + + guard let overlayContainer = cell.bubbleOverlayContainer else { + return + } + + // The read marker is added into the overlay container. + // CAUTION: Keep disabled the user interaction on this container to not disturb tap gesture handling. + overlayContainer.backgroundColor = UIColor.clear + overlayContainer.alpha = 1 + overlayContainer.isUserInteractionEnabled = false + overlayContainer.isHidden = false + + // Add read marker to overlayContainer + readMarkerView.translatesAutoresizingMaskIntoConstraints = false + overlayContainer.addSubview(readMarkerView) + cell.readMarkerView = readMarkerView + + // Force read marker constraints + let topConstraint = readMarkerView.topAnchor.constraint(equalTo: overlayContainer.topAnchor, constant: contentViewPositionY - PlainRoomCellLayoutConstants.readMarkerViewHeight) + + let leadingConstraint = readMarkerView.leadingAnchor.constraint(equalTo: overlayContainer.leadingAnchor) + + let trailingConstraint = readMarkerView.trailingAnchor.constraint(equalTo: overlayContainer.trailingAnchor) + + let heightConstraint = readMarkerView.heightAnchor.constraint(equalToConstant: PlainRoomCellLayoutConstants.readMarkerViewHeight) + + NSLayoutConstraint.activate([topConstraint, + leadingConstraint, + trailingConstraint, + heightConstraint]) + + cell.readMarkerViewTopConstraint = topConstraint + cell.readMarkerViewLeadingConstraint = leadingConstraint + cell.readMarkerViewTrailingConstraint = trailingConstraint + cell.readMarkerViewHeightConstraint = heightConstraint + } + + func dissmissReadMarkerView(forCell cell: MXKRoomBubbleTableViewCell, + cellData: RoomBubbleCellData, + animated: Bool, + completion: @escaping () -> Void) { + + guard let readMarkerView = cell.readMarkerView, let readMarkerContainerView = readMarkerView.superview else { + return + } + + // Do not display the marker if this is the last message. + if animated == false || (cellData.containsLastMessage && readMarkerView.tag == cellData.mostRecentComponentIndex) { + readMarkerView.isHidden = true + completion() + } else { + readMarkerView.isHidden = false + + // Animate the layout to hide the read marker + DispatchQueue.main.async { + + let readMarkerContainerViewHalfWidth = readMarkerContainerView.frame.size.width/2 + + cell.readMarkerViewLeadingConstraint.constant = readMarkerContainerViewHalfWidth + cell.readMarkerViewTrailingConstraint.constant = -readMarkerContainerViewHalfWidth + + UIView.animate(withDuration: 1.5, + delay: 0.3, + options: [.beginFromCurrentState, .curveEaseIn]) { + + readMarkerView.alpha = 0 + readMarkerContainerView.layoutIfNeeded() + + } completion: { finished in + readMarkerView.isHidden = true + readMarkerView.alpha = 1 + + completion() + } + } + } + } } diff --git a/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellDecorator.swift b/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellDecorator.swift index ec60bcbf4..5e383dc94 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellDecorator.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/RoomTimelineCellDecorator.swift @@ -50,4 +50,14 @@ protocol RoomTimelineCellDecorator { func addSendStatusView(toCell cell: MXKRoomBubbleTableViewCell, withFailedEventIds failedEventIds: Set) + + func addReadMarkerView(_ readMarkerView: UIView, + toCell cell: MXKRoomBubbleTableViewCell, + cellData: MXKRoomBubbleCellData, + contentViewPositionY: CGFloat) + + func dissmissReadMarkerView(forCell cell: MXKRoomBubbleTableViewCell, + cellData: RoomBubbleCellData, + animated: Bool, + completion: @escaping () -> Void) } From 87d58aa3def65a69a131236d8a1733d86ab813a3 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 17:45:43 +0100 Subject: [PATCH 120/188] RoomDataSource: Use RoomTimelineCellDecorator to add read marker. --- .../Modules/Room/DataSources/RoomDataSource.m | 49 ++++--------------- 1 file changed, 9 insertions(+), 40 deletions(-) diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 69d8f80e9..2341e692a 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -558,48 +558,17 @@ const CGFloat kTypingCellHeight = 24; if ([componentEventId isEqualToString:self.room.accountData.readMarkerEventId]) { - bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - PlainRoomCellLayoutConstants.readMarkerViewHeight, bubbleCell.bubbleOverlayContainer.frame.size.width, PlainRoomCellLayoutConstants.readMarkerViewHeight)]; - bubbleCell.readMarkerView.backgroundColor = ThemeService.shared.theme.tintColor; + UIView *readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - PlainRoomCellLayoutConstants.readMarkerViewHeight, bubbleCell.bubbleOverlayContainer.frame.size.width, PlainRoomCellLayoutConstants.readMarkerViewHeight)]; + 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; + readMarkerView.hidden = YES; + readMarkerView.tag = index; + readMarkerView.accessibilityIdentifier = @"readMarker"; - bubbleCell.readMarkerView.translatesAutoresizingMaskIntoConstraints = NO; - bubbleCell.readMarkerView.accessibilityIdentifier = @"readMarker"; - [bubbleCell.bubbleOverlayContainer addSubview:bubbleCell.readMarkerView]; - - // Force read marker constraints - bubbleCell.readMarkerViewTopConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:bubbleCell.bubbleOverlayContainer - attribute:NSLayoutAttributeTop - multiplier:1.0 - constant:bottomPositionY - PlainRoomCellLayoutConstants.readMarkerViewHeight]; - bubbleCell.readMarkerViewLeadingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView - attribute:NSLayoutAttributeLeading - relatedBy:NSLayoutRelationEqual - toItem:bubbleCell.bubbleOverlayContainer - attribute:NSLayoutAttributeLeading - multiplier:1.0 - constant:0]; - bubbleCell.readMarkerViewTrailingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.bubbleOverlayContainer - attribute:NSLayoutAttributeTrailing - relatedBy:NSLayoutRelationEqual - toItem:bubbleCell.readMarkerView - attribute:NSLayoutAttributeTrailing - multiplier:1.0 - constant:0]; - - bubbleCell.readMarkerViewHeightConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView - attribute:NSLayoutAttributeHeight - relatedBy:NSLayoutRelationEqual - toItem:nil - attribute:NSLayoutAttributeNotAnAttribute - multiplier:1.0 - constant:PlainRoomCellLayoutConstants.readMarkerViewHeight]; - - [NSLayoutConstraint activateConstraints:@[bubbleCell.readMarkerViewTopConstraint, bubbleCell.readMarkerViewLeadingConstraint, bubbleCell.readMarkerViewTrailingConstraint, bubbleCell.readMarkerViewHeightConstraint]]; + [cellDecorator addReadMarkerView:readMarkerView + toCell:bubbleCell + cellData:cellData + contentViewPositionY:bottomPositionY]; } } } From 3351af3e9d3e499b6e136baa8b38f234c5180144 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 17:46:26 +0100 Subject: [PATCH 121/188] RoomDataSource: Use RoomTimelineCellDecorator to animate read marker dismiss. --- Riot/Modules/Room/RoomViewController.m | 51 ++++++++------------------ 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 4eddef5bc..331c07ba4 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -5821,44 +5821,23 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; - (void)animateReadMarkerView { // Check whether the cell with the read marker is known and if the marker is not animated yet. - if (readMarkerTableViewCell && readMarkerTableViewCell.readMarkerView.isHidden) + + if (!readMarkerTableViewCell || readMarkerTableViewCell.readMarkerView.isHidden == NO) { - RoomBubbleCellData *cellData = (RoomBubbleCellData*)readMarkerTableViewCell.bubbleData; - - // Do not display the marker if this is the last message. - if (cellData.containsLastMessage && readMarkerTableViewCell.readMarkerView.tag == cellData.mostRecentComponentIndex) - { - readMarkerTableViewCell.readMarkerView.hidden = YES; - readMarkerTableViewCell = nil; - } - else - { - readMarkerTableViewCell.readMarkerView.hidden = NO; - - // Animate the layout to hide the read marker - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ - - [UIView animateWithDuration:1.5 delay:0 options:UIViewAnimationOptionBeginFromCurrentState | UIViewAnimationOptionCurveEaseIn - animations:^{ - - self->readMarkerTableViewCell.readMarkerViewLeadingConstraint.constant = self->readMarkerTableViewCell.readMarkerViewTrailingConstraint.constant = self->readMarkerTableViewCell.bubbleOverlayContainer.frame.size.width / 2; - self->readMarkerTableViewCell.readMarkerView.alpha = 0; - - // Force to render the view - [self->readMarkerTableViewCell.bubbleOverlayContainer layoutIfNeeded]; - - } - completion:^(BOOL finished){ - - self->readMarkerTableViewCell.readMarkerView.hidden = YES; - self->readMarkerTableViewCell.readMarkerView.alpha = 1; - - self->readMarkerTableViewCell = nil; - }]; - - }); - } + return; } + + RoomBubbleCellData *cellData = (RoomBubbleCellData*)readMarkerTableViewCell.bubbleData; + + id cellDecorator = [RoomTimelineConfiguration shared].currentStyle.cellDecorator; + + [cellDecorator dissmissReadMarkerViewForCell:readMarkerTableViewCell + cellData:cellData + animated:YES + completion:^{ + + self->readMarkerTableViewCell = nil; + }]; } - (void)refreshRemoveJitsiWidgetView From 6c680a73fff379bad49614225fd311ce42adfaca Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 17 Feb 2022 13:25:53 +0200 Subject: [PATCH 122/188] vector-im/element-ios/issues/5609 - Add attribution to location sharing maps. --- .../Location/RoomTimelineLocationView.swift | 2 + .../Location/RoomTimelineLocationView.xib | 80 ++++++++----- .../View/LocationSharingView.swift | 112 ++++++++++-------- changelog.d/5609.change | 1 + 4 files changed, 115 insertions(+), 80 deletions(-) create mode 100644 changelog.d/5609.change diff --git a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift index 882a277c9..5ffb88e15 100644 --- a/Riot/Modules/Room/Location/RoomTimelineLocationView.swift +++ b/Riot/Modules/Room/Location/RoomTimelineLocationView.swift @@ -35,6 +35,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat @IBOutlet private var descriptionContainerView: UIView! @IBOutlet private var descriptionLabel: UILabel! @IBOutlet private var descriptionIcon: UIImageView! + @IBOutlet private var attributionLabel: UILabel! private var mapView: MGLMapView! private var annotationView: LocationMarkerView? @@ -101,6 +102,7 @@ class RoomTimelineLocationView: UIView, NibLoadable, Themable, MGLMapViewDelegat descriptionLabel.textColor = theme.colors.primaryContent descriptionLabel.font = theme.fonts.footnote descriptionIcon.tintColor = theme.colors.accent + attributionLabel.textColor = theme.colors.accent layer.borderColor = theme.colors.quinaryContent.cgColor } diff --git a/Riot/Modules/Room/Location/RoomTimelineLocationView.xib b/Riot/Modules/Room/Location/RoomTimelineLocationView.xib index acc469b74..fb2e22a29 100644 --- a/Riot/Modules/Room/Location/RoomTimelineLocationView.xib +++ b/Riot/Modules/Room/Location/RoomTimelineLocationView.xib @@ -1,9 +1,9 @@ - + - + @@ -15,48 +15,72 @@ - - + + - - + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + - - - + + + + diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift index 0d40d14d9..5c69349cc 100644 --- a/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift +++ b/RiotSwiftUI/Modules/Room/LocationSharing/View/LocationSharingView.swift @@ -32,62 +32,70 @@ struct LocationSharingView: View { var body: some View { NavigationView { - LocationSharingMapView(tileServerMapURL: context.viewState.mapStyleURL, - avatarData: context.viewState.avatarData, - location: context.viewState.location, - errorSubject: context.viewState.errorSubject, - userLocation: $context.userLocation) - .toolbar { - ToolbarItem(placement: .navigationBarLeading) { - Button(VectorL10n.cancel, action: { - context.send(viewAction: .cancel) - }) - } - ToolbarItem(placement: .principal) { - Text(VectorL10n.locationSharingTitle) - .font(.headline) - .foregroundColor(theme.colors.primaryContent) - } - ToolbarItem(placement: .navigationBarTrailing) { - if context.viewState.location != nil { - Button { - context.send(viewAction: .share) - } label: { - Image(uiImage: Asset.Images.locationShareIcon.image) - .accessibilityIdentifier("LocationSharingView.shareButton") - } - .disabled(!context.viewState.shareButtonEnabled) - } else { - Button(VectorL10n.locationSharingShareAction, action: { - context.send(viewAction: .share) - }) - .disabled(!context.viewState.shareButtonEnabled) + ZStack(alignment: .bottom) { + LocationSharingMapView(tileServerMapURL: context.viewState.mapStyleURL, + avatarData: context.viewState.avatarData, + location: context.viewState.location, + errorSubject: context.viewState.errorSubject, + userLocation: $context.userLocation) + .ignoresSafeArea() + + HStack { + Link("© MapTiler", destination: URL(string: "https://www.maptiler.com/copyright/")!) + Link("© OpenStreetMap contributors", destination: URL(string: "https://www.openstreetmap.org/copyright")!) + } + .font(theme.fonts.caption1) + } + .toolbar { + ToolbarItem(placement: .navigationBarLeading) { + Button(VectorL10n.cancel, action: { + context.send(viewAction: .cancel) + }) + } + ToolbarItem(placement: .principal) { + Text(VectorL10n.locationSharingTitle) + .font(.headline) + .foregroundColor(theme.colors.primaryContent) + } + ToolbarItem(placement: .navigationBarTrailing) { + if context.viewState.location != nil { + Button { + context.send(viewAction: .share) + } label: { + Image(uiImage: Asset.Images.locationShareIcon.image) + .accessibilityIdentifier("LocationSharingView.shareButton") } - } - } - .navigationBarTitleDisplayMode(.inline) - .introspectNavigationController { navigationController in - ThemeService.shared().theme.applyStyle(onNavigationBar: navigationController.navigationBar) - } - .ignoresSafeArea() - .alert(item: $context.alertInfo) { info in - if let secondaryButton = info.secondaryButton { - return Alert(title: Text(info.title), - message: subtitleTextForAlertInfo(info), - primaryButton: .default(Text(info.primaryButton.title)) { - info.primaryButton.action?() - }, - secondaryButton: .default(Text(secondaryButton.title)) { - secondaryButton.action?() - }) + .disabled(!context.viewState.shareButtonEnabled) } else { - return Alert(title: Text(info.title), - message: subtitleTextForAlertInfo(info), - dismissButton: .default(Text(info.primaryButton.title)) { - info.primaryButton.action?() - }) + Button(VectorL10n.locationSharingShareAction, action: { + context.send(viewAction: .share) + }) + .disabled(!context.viewState.shareButtonEnabled) } } + } + .navigationBarTitleDisplayMode(.inline) + .introspectNavigationController { navigationController in + ThemeService.shared().theme.applyStyle(onNavigationBar: navigationController.navigationBar) + } + .alert(item: $context.alertInfo) { info in + if let secondaryButton = info.secondaryButton { + return Alert(title: Text(info.title), + message: subtitleTextForAlertInfo(info), + primaryButton: .default(Text(info.primaryButton.title)) { + info.primaryButton.action?() + }, + secondaryButton: .default(Text(secondaryButton.title)) { + secondaryButton.action?() + }) + } else { + return Alert(title: Text(info.title), + message: subtitleTextForAlertInfo(info), + dismissButton: .default(Text(info.primaryButton.title)) { + info.primaryButton.action?() + }) + } + } } .accentColor(theme.colors.accent) .activityIndicator(show: context.viewState.showLoadingIndicator) diff --git a/changelog.d/5609.change b/changelog.d/5609.change new file mode 100644 index 000000000..b33dea26b --- /dev/null +++ b/changelog.d/5609.change @@ -0,0 +1 @@ +Add attribution to location sharing maps. \ No newline at end of file From 993269447a40553817ff28a86e64a82e5e9fae60 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 17 Feb 2022 15:41:09 +0200 Subject: [PATCH 123/188] vector-im/element-ios/issues/5609 - Add open in OSM location sharing option. --- Riot/Assets/en.lproj/Vector.strings | 2 ++ Riot/Generated/Strings.swift | 4 ++++ .../Coordinator/LocationSharingCoordinator.swift | 3 ++- .../LocationSharing/Coordinator/ShareToMapsAppActivity.swift | 5 +++++ 4 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index ca75a5a65..63a0afa4d 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -1945,6 +1945,8 @@ Tap the + to start adding people."; "location_sharing_open_google_maps" = "Open in Google Maps"; +"location_sharing_open_open_street_maps" = "Open in OpenStreetMap"; + "location_sharing_settings_header" = "Location sharing"; "location_sharing_settings_toggle_title" = "Enable location sharing"; diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index 1313a6028..84b6970a6 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2267,6 +2267,10 @@ public class VectorL10n: NSObject { public static var locationSharingOpenGoogleMaps: String { return VectorL10n.tr("Vector", "location_sharing_open_google_maps") } + /// Open in OpenStreetMap + public static var locationSharingOpenOpenStreetMaps: String { + return VectorL10n.tr("Vector", "location_sharing_open_open_street_maps") + } /// %@ could not send your location. Please try again later. public static func locationSharingPostFailureSubtitle(_ p1: String) -> String { return VectorL10n.tr("Vector", "location_sharing_post_failure_subtitle", p1) diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift b/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift index 8edef1a65..b43f4f05d 100644 --- a/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/LocationSharingCoordinator.swift @@ -97,7 +97,8 @@ final class LocationSharingCoordinator: Coordinator, Presentable { static func shareLocationActivityController(_ location: CLLocationCoordinate2D) -> UIActivityViewController { return UIActivityViewController(activityItems: [ShareToMapsAppActivity.urlForMapsAppType(.apple, location: location)], applicationActivities: [ShareToMapsAppActivity(type: .apple, location: location), - ShareToMapsAppActivity(type: .google, location: location)]) + ShareToMapsAppActivity(type: .google, location: location), + ShareToMapsAppActivity(type: .osm, location: location)]) } // MARK: - Presentable diff --git a/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/ShareToMapsAppActivity.swift b/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/ShareToMapsAppActivity.swift index 57dad80f8..aeac582c3 100644 --- a/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/ShareToMapsAppActivity.swift +++ b/RiotSwiftUI/Modules/Room/LocationSharing/Coordinator/ShareToMapsAppActivity.swift @@ -24,6 +24,7 @@ class ShareToMapsAppActivity: UIActivity { enum MapsAppType { case apple case google + case osm } private let type: MapsAppType @@ -44,6 +45,8 @@ class ShareToMapsAppActivity: UIActivity { return URL(string: "https://maps.apple.com?ll=\(location.latitude),\(location.longitude)&q=Pin")! case .google: return URL(string: "https://www.google.com/maps/search/?api=1&query=\(location.latitude),\(location.longitude)")! + case .osm: + return URL(string: "https://www.openstreetmap.org/?mlat=\(location.latitude)&mlon=\(location.longitude)")! } } @@ -53,6 +56,8 @@ class ShareToMapsAppActivity: UIActivity { return VectorL10n.locationSharingOpenAppleMaps case .google: return VectorL10n.locationSharingOpenGoogleMaps + case .osm: + return VectorL10n.locationSharingOpenOpenStreetMaps } } From 2256b522ab4b445f7d37f0b4f45759ddc59e195d Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 17 Feb 2022 16:50:02 +0000 Subject: [PATCH 124/188] Move presentation of the loading spinner into AuthenticationCoordinator for new users. Also moves key verification out of a bridge presenter in AuthenticationVC and into the AuthenticationCoordinator. --- Riot/Modules/Application/LegacyAppDelegate.m | 6 + .../AuthenticationCoordinator.swift | 165 ++++++++++++++++- .../AuthenticationCoordinatorProtocol.swift | 14 +- .../AuthenticationViewController.h | 4 +- .../AuthenticationViewController.m | 169 +----------------- .../LaunchLoadingViewController.swift | 38 ++++ .../LaunchLoadingViewController.xib | 31 ++++ .../Onboarding/OnboardingCoordinator.swift | 26 ++- Riot/Modules/TabBar/MasterTabBarController.m | 6 +- changelog.d/5621.change | 1 + 10 files changed, 279 insertions(+), 181 deletions(-) create mode 100644 Riot/Modules/LaunchLoading/LaunchLoadingViewController.swift create mode 100644 Riot/Modules/LaunchLoading/LaunchLoadingViewController.xib create mode 100644 changelog.d/5621.change diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index a85047c69..1c74e5ede 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -2410,6 +2410,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni MXLogDebug(@"[AppDelegate] handleAppState: isLaunching: %@", isLaunching ? @"YES" : @"NO"); + if (self.masterTabBarController.isOnboardingInProgress) + { + MXLogDebug(@"[AppDelegate] handleAppState: Skipping LaunchLoadingView due to Onboarding."); + return; + } + if (isLaunching) { MXLogDebug(@"[AppDelegate] handleAppState: LaunchLoadingView"); diff --git a/Riot/Modules/Authentication/AuthenticationCoordinator.swift b/Riot/Modules/Authentication/AuthenticationCoordinator.swift index e2ba6ee2e..865161941 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinator.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinator.swift @@ -16,7 +16,6 @@ limitations under the License. */ -import Foundation import UIKit /// A coordinator that handles authentication, verification and setting a PIN. @@ -26,17 +25,27 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc // MARK: Private + private let navigationRouter: NavigationRouterType + private let authenticationViewController: AuthenticationViewController + private let crossSigningService = CrossSigningService() + + /// The password entered, for use when setting up cross-signing. + private var password: String? + /// The session created when successfully authenticated. + private var session: MXSession? // MARK: Public // Must be used only internally var childCoordinators: [Coordinator] = [] - var completion: ((MXKAuthenticationType) -> Void)? + var completion: ((AuthenticationCoordinatorResult) -> Void)? // MARK: - Setup - override init() { + init(parameters: AuthenticationCoordinatorParameters) { + self.navigationRouter = parameters.navigationRouter + let authenticationViewController = AuthenticationViewController() self.authenticationViewController = authenticationViewController @@ -81,11 +90,157 @@ final class AuthenticationCoordinator: NSObject, AuthenticationCoordinatorProtoc func continueSSOLogin(withToken loginToken: String, transactionID: String) -> Bool { authenticationViewController.continueSSOLogin(withToken: loginToken, txnId: transactionID) } + + // MARK: - Private + + private func showLoadingAnimation() { + let loadingViewController = LaunchLoadingViewController() + loadingViewController.modalPresentationStyle = .fullScreen + + // Replace the navigation stack with the loading animation + // as there is nothing to navigate back to. + navigationRouter.setRootModule(loadingViewController) + } + + private func presentCompleteSecurity(with session: MXSession) { + let isNewSignIn = true + let keyVerificationCoordinator = KeyVerificationCoordinator(session: session, flow: .completeSecurity(isNewSignIn)) + + keyVerificationCoordinator.delegate = self + let presentable = keyVerificationCoordinator.toPresentable() + presentable.presentationController?.delegate = self + navigationRouter.present(presentable, animated: true) + keyVerificationCoordinator.start() + add(childCoordinator: keyVerificationCoordinator) + } + + private func authenticationDidComplete() { + completion?(.didComplete(authenticationViewController.authType)) + } + + private func registerSessionStateChangeNotification(for session: MXSession) { + NotificationCenter.default.addObserver(self, selector: #selector(sessionStateDidChange), name: .mxSessionStateDidChange, object: session) + } + + private func unregisterSessionStateChangeNotification() { + NotificationCenter.default.removeObserver(self, name: .mxSessionStateDidChange, object: nil) + } + + @objc private func sessionStateDidChange(_ notification: Notification) { + guard let session = notification.object as? MXSession else { + MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Missing session in the notification") + return + } + + if session.state == .storeDataReady { + if let crypto = session.crypto, crypto.crossSigning != nil { + // Do not make key share requests while the "Complete security" is not complete. + // If the device is self-verified, the SDK will restore the existing key backup. + // Then, it will re-enable outgoing key share requests + crypto.setOutgoingKeyRequestsEnabled(false, onComplete: nil) + } + } else if session.state == .running { + unregisterSessionStateChangeNotification() + + if let crypto = session.crypto, let crossSigning = crypto.crossSigning { + crossSigning.refreshState { [weak self] stateUpdated in + guard let self = self else { return } + + MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: crossSigning.state: \(crossSigning.state)") + + switch crossSigning.state { + case .notBootstrapped: + // TODO: This is still not sure we want to disable the automatic cross-signing bootstrap + // if the admin disabled e2e by default. + // Do like riot-web for the moment + if session.vc_homeserverConfiguration().isE2EEByDefaultEnabled { + // Bootstrap cross-signing on user's account + // We do it for both registration and new login as long as cross-signing does not exist yet + if let password = self.password, !password.isEmpty { + MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap with password") + + crossSigning.setup(withPassword: password) { + MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap succeeded") + self.authenticationDidComplete() + } failure: { error in + MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap failed. Error: \(error)") + crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + self.authenticationDidComplete() + } + } else { + // Try to setup cross-signing without authentication parameters in case if a grace period is enabled + self.crossSigningService.setupCrossSigningWithoutAuthentication(for: session) { + MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Bootstrap succeeded without credentials") + self.authenticationDidComplete() + } failure: { error in + MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it.") + crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + self.authenticationDidComplete() + } + } + } else { + crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + self.authenticationDidComplete() + } + case .crossSigningExists: + MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Complete security") + self.presentCompleteSecurity(with: session) + default: + MXLog.debug("[AuthenticationCoordinator] sessionStateDidChange: Nothing to do") + + crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + self.authenticationDidComplete() + } + } failure: { [weak self] error in + MXLog.error("[AuthenticationCoordinator] sessionStateDidChange: Fail to refresh crypto state with error: \(error)") + crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + self?.authenticationDidComplete() + } + } else { + authenticationDidComplete() + } + } + } } // MARK: - AuthenticationViewControllerDelegate extension AuthenticationCoordinator: AuthenticationViewControllerDelegate { - func authenticationViewControllerDidDismiss(_ authenticationViewController: AuthenticationViewController!) { - completion?(authenticationViewController.authType) + func authenticationViewController(_ authenticationViewController: AuthenticationViewController!, didLoginWith session: MXSession!, andPassword password: String!) { + registerSessionStateChangeNotification(for: session) + + self.session = session + self.password = password + + self.showLoadingAnimation() + completion?(.didLogin(session)) + } +} + +// MARK: - KeyVerificationCoordinatorDelegate +extension AuthenticationCoordinator: KeyVerificationCoordinatorDelegate { + func keyVerificationCoordinatorDidComplete(_ coordinator: KeyVerificationCoordinatorType, otherUserId: String, otherDeviceId: String) { + if let crypto = session?.crypto, + !crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled { + MXLog.debug("[AuthenticationCoordinator][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys") + crypto.setOutgoingKeyRequestsEnabled(true, onComplete: nil) + } + + navigationRouter.dismissModule(animated: true) { [weak self] in + self?.authenticationDidComplete() + } + } + + func keyVerificationCoordinatorDidCancel(_ coordinator: KeyVerificationCoordinatorType) { + navigationRouter.dismissModule(animated: true) { [weak self] in + self?.authenticationDidComplete() + } + } +} + +// MARK: - UIAdaptivePresentationControllerDelegate +extension AuthenticationCoordinator: UIAdaptivePresentationControllerDelegate { + func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool { + // Prevent Key Verification from using swipe to dismiss + return false } } diff --git a/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift b/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift index 14a3d1186..c024cddbe 100644 --- a/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift +++ b/Riot/Modules/Authentication/AuthenticationCoordinatorProtocol.swift @@ -18,9 +18,21 @@ import Foundation +struct AuthenticationCoordinatorParameters { + let navigationRouter: NavigationRouterType +} + +enum AuthenticationCoordinatorResult { + /// The user has authenticated but key verification is yet to happen. The session value is + /// for a fresh session that still needs to load, sync etc before being ready. + case didLogin(MXSession) + /// All of the required authentication steps including key verification is complete. + case didComplete(MXKAuthenticationType) +} + /// `AuthenticationCoordinatorProtocol` is a protocol describing a Coordinator that handle's the authentication navigation flow. protocol AuthenticationCoordinatorProtocol: Coordinator, Presentable { - var completion: ((MXKAuthenticationType) -> Void)? { get set } + var completion: ((AuthenticationCoordinatorResult) -> Void)? { get set } /// Update the screen to display registration or login. func update(authenticationType: MXKAuthenticationType) diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index 6671863a2..dd76303a4 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -62,6 +62,8 @@ @protocol AuthenticationViewControllerDelegate -- (void)authenticationViewControllerDidDismiss:(AuthenticationViewController *)authenticationViewController; +- (void)authenticationViewController:(AuthenticationViewController *)authenticationViewController + didLoginWithSession:(MXSession *)session + andPassword:(NSString *)password; @end; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index 776e23373..425fb4da6 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -28,7 +28,7 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; -@interface AuthenticationViewController () @@ -63,7 +63,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; } @property (nonatomic, readonly) BOOL isIdentityServerConfigured; -@property (nonatomic, strong) KeyVerificationCoordinatorBridgePresenter *keyVerificationCoordinatorBridgePresenter; @property (nonatomic, strong) SetPinCoordinatorBridgePresenter *setPinCoordinatorBridgePresenter; @property (nonatomic, strong) KeyboardAvoider *keyboardAvoider; @@ -78,8 +77,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; // Current SSO transaction id used to identify and validate the SSO authentication callback @property (nonatomic, strong) NSString *ssoCallbackTxnId; -@property (nonatomic, strong) CrossSigningService *crossSigningService; - @property (nonatomic, getter = isFirstViewAppearing) BOOL firstViewAppearing; @property (nonatomic, strong) MXKErrorAlertPresentation *errorPresenter; @@ -118,7 +115,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; _firstViewAppearing = YES; - self.crossSigningService = [CrossSigningService new]; self.errorPresenter = [MXKErrorAlertPresentation new]; } @@ -318,11 +314,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; { self.firstViewAppearing = NO; } - - if (self.keyVerificationCoordinatorBridgePresenter) - { - return; - } // Verify that the app does not show the authentication screen whereas // the user has already logged in. @@ -379,7 +370,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self.authenticationActivityIndicator removeObserver:self forKeyPath:@"hidden"]; autoDiscovery = nil; - _keyVerificationCoordinatorBridgePresenter = nil; _keyboardAvoider = nil; } @@ -557,30 +547,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; } } -- (void)presentCompleteSecurityWithSession:(MXSession*)session -{ - KeyVerificationCoordinatorBridgePresenter *keyVerificationCoordinatorBridgePresenter = [[KeyVerificationCoordinatorBridgePresenter alloc] initWithSession:session]; - keyVerificationCoordinatorBridgePresenter.delegate = self; - - [keyVerificationCoordinatorBridgePresenter presentCompleteSecurityFrom:self isNewSignIn:YES animated:YES]; - - self.keyVerificationCoordinatorBridgePresenter = keyVerificationCoordinatorBridgePresenter; -} - -- (void)dismiss -{ - self.userInteractionEnabled = YES; - [self.authenticationActivityIndicator stopAnimating]; - - // Dismiss (key verification) on successful login - [self.presentingViewController dismissViewControllerAnimated:YES completion:nil]; - - if (self.authVCDelegate) - { - [self.authVCDelegate authenticationViewControllerDidDismiss:self]; - } -} - - (BOOL)continueSSOLoginWithToken:(NSString*)loginToken txnId:(NSString*)txnId { // Check if transaction id is the same as expected @@ -1377,119 +1343,8 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; }]; } - // Wait for session change to present complete security screen if needed - [self registerSessionStateChangeNotificationForSession:session]; -} - -- (void)registerSessionStateChangeNotificationForSession:(MXSession*)session -{ - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(sessionStateDidChangeNotification:) name:kMXSessionStateDidChangeNotification object:session]; -} - -- (void)unregisterSessionStateChangeNotification -{ - [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionStateDidChangeNotification object:nil]; -} - -- (void)sessionStateDidChangeNotification:(NSNotification*)notification -{ - MXSession *session = (MXSession*)notification.object; - - if (session.state == MXSessionStateStoreDataReady) - { - if (session.crypto.crossSigning) - { - // Do not make key share requests while the "Complete security" is not complete. - // If the device is self-verified, the SDK will restore the existing key backup. - // Then, it will re-enable outgoing key share requests - [session.crypto setOutgoingKeyRequestsEnabled:NO onComplete:nil]; - } - } - else if (session.state == MXSessionStateRunning) - { - [self unregisterSessionStateChangeNotification]; - - if (session.crypto.crossSigning) - { - [session.crypto.crossSigning refreshStateWithSuccess:^(BOOL stateUpdated) { - - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: crossSigning.state: %@", @(session.crypto.crossSigning.state)); - - switch (session.crypto.crossSigning.state) - { - case MXCrossSigningStateNotBootstrapped: - { - // TODO: This is still not sure we want to disable the automatic cross-signing bootstrap - // if the admin disabled e2e by default. - // Do like riot-web for the moment - if ([session vc_homeserverConfiguration].isE2EEByDefaultEnabled) - { - // Bootstrap cross-signing on user's account - // We do it for both registration and new login as long as cross-signing does not exist yet - if (self.authInputsView.password.length) - { - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap with password"); - - [session.crypto.crossSigning setupWithPassword:self.authInputsView.password success:^{ - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap succeeded"); - [self dismiss]; - } failure:^(NSError * _Nonnull error) { - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap failed. Error: %@", error); - [session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; - [self dismiss]; - }]; - } - else - { - // Try to setup cross-signing without authentication parameters in case if a grace period is enabled - [self.crossSigningService setupCrossSigningWithoutAuthenticationFor:session success:^{ - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Bootstrap succeeded without credentials"); - [self dismiss]; - } failure:^(NSError * _Nonnull error) { - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Do not know how to bootstrap cross-signing. Skip it."); - [session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; - [self dismiss]; - }]; - } - } - else - { - [session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; - [self dismiss]; - } - break; - } - case MXCrossSigningStateCrossSigningExists: - { - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Complete security"); - - // Ask the user to verify this session - self.userInteractionEnabled = YES; - [self.authenticationActivityIndicator stopAnimating]; - - [self presentCompleteSecurityWithSession:session]; - break; - } - - default: - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Nothing to do"); - - [session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; - [self dismiss]; - break; - } - - } failure:^(NSError * _Nonnull error) { - MXLogDebug(@"[AuthenticationVC] sessionStateDidChange: Fail to refresh crypto state with error: %@", error); - [session.crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; - [self dismiss]; - }]; - } - else - { - [self dismiss]; - } - } + // Ask the coordinator to show the loading spinner whilst waiting. + [self.authVCDelegate authenticationViewController:self didLoginWithSession:session andPassword:self.authInputsView.password]; } #pragma mark - MXKAuthInputsViewDelegate @@ -1621,24 +1476,6 @@ static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; [self setCustomServerFieldsVisible:YES]; } -#pragma mark - KeyVerificationCoordinatorBridgePresenterDelegate - -- (void)keyVerificationCoordinatorBridgePresenterDelegateDidComplete:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter otherUserId:(NSString * _Nonnull)otherUserId otherDeviceId:(NSString * _Nonnull)otherDeviceId -{ - MXCrypto *crypto = coordinatorBridgePresenter.session.crypto; - if (!crypto.backup.hasPrivateKeyInCryptoStore || !crypto.backup.enabled) - { - MXLogDebug(@"[AuthenticationVC][MXKeyVerification] requestAllPrivateKeys: Request key backup private keys"); - [crypto setOutgoingKeyRequestsEnabled:YES onComplete:nil]; - } - [self dismiss]; -} - -- (void)keyVerificationCoordinatorBridgePresenterDelegateDidCancel:(KeyVerificationCoordinatorBridgePresenter * _Nonnull)coordinatorBridgePresenter -{ - [self dismiss]; -} - #pragma mark - SetPinCoordinatorBridgePresenterDelegate - (void)setPinCoordinatorBridgePresenterDelegateDidComplete:(SetPinCoordinatorBridgePresenter *)coordinatorBridgePresenter diff --git a/Riot/Modules/LaunchLoading/LaunchLoadingViewController.swift b/Riot/Modules/LaunchLoading/LaunchLoadingViewController.swift new file mode 100644 index 000000000..bd7dba409 --- /dev/null +++ b/Riot/Modules/LaunchLoading/LaunchLoadingViewController.swift @@ -0,0 +1,38 @@ +// +// Copyright 2021 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 + +class LaunchLoadingViewController: UIViewController, Reusable { + + required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } + + init() { + super.init(nibName: "LaunchLoadingViewController", bundle: nil) + + let launchLoadingView = LaunchLoadingView.instantiate() + launchLoadingView.update(theme: ThemeService.shared().theme) + view.vc_addSubViewMatchingParent(launchLoadingView) + + // The launch time isn't profiled for analytics as it's presentation length + // will be artificially changed based on other views in the flow. + } + + override func viewWillAppear(_ animated: Bool) { + navigationController?.setNavigationBarHidden(true, animated: false) + } +} diff --git a/Riot/Modules/LaunchLoading/LaunchLoadingViewController.xib b/Riot/Modules/LaunchLoading/LaunchLoadingViewController.xib new file mode 100644 index 000000000..19628372f --- /dev/null +++ b/Riot/Modules/LaunchLoading/LaunchLoadingViewController.xib @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Onboarding/OnboardingCoordinator.swift b/Riot/Modules/Onboarding/OnboardingCoordinator.swift index 571140f43..4f01eacfb 100644 --- a/Riot/Modules/Onboarding/OnboardingCoordinator.swift +++ b/Riot/Modules/Onboarding/OnboardingCoordinator.swift @@ -54,8 +54,8 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { private var navigationRouter: NavigationRouterType { parameters.router } - // Keep a strong ref as we need to init authVC early to preload its view (it is *really* slow to do in realtime) - private var authenticationCoordinator: AuthenticationCoordinatorProtocol = AuthenticationCoordinator() + // Keep a strong ref as we need to init authVC early to preload its view + private let authenticationCoordinator: AuthenticationCoordinatorProtocol private var isShowingAuthentication = false // MARK: Screen results @@ -72,6 +72,11 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { init(parameters: OnboardingCoordinatorParameters) { self.parameters = parameters + + // Preload the authVC (it is *really* slow to load in realtime) + let authenticationParameters = AuthenticationCoordinatorParameters(navigationRouter: parameters.router) + authenticationCoordinator = AuthenticationCoordinator(parameters: authenticationParameters) + super.init() } @@ -178,9 +183,16 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { MXLog.debug("[OnboardingCoordinator] showAuthenticationScreen") let coordinator = authenticationCoordinator - coordinator.completion = { [weak self, weak coordinator] authenticationType in + coordinator.completion = { [weak self, weak coordinator] result in guard let self = self, let coordinator = coordinator else { return } - self.authenticationCoordinator(coordinator, didCompleteWith: authenticationType) + + switch result { + case .didLogin(let session): + self.authenticationCoordinator(coordinator, didLoginWith: session) + case .didComplete(let authenticationType): + self.authenticationCoordinator(coordinator, didCompleteWith: authenticationType) + } + } // Due to needing to preload the authVC, this breaks the Coordinator init/start pattern. @@ -200,7 +212,6 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { coordinator.start() add(childCoordinator: coordinator) - authenticationCoordinator = coordinator if customHomeserver != nil || customIdentityServer != nil { coordinator.updateHomeserver(customHomeserver, andIdentityServer: customIdentityServer) @@ -217,6 +228,11 @@ final class OnboardingCoordinator: NSObject, OnboardingCoordinatorProtocol { isShowingAuthentication = true } + private func authenticationCoordinator(_ coordinator: AuthenticationCoordinatorProtocol, didLoginWith session: MXSession) { + // TODO: Show next screens whilst waiting for the everything to load. + // May need to move the spinner and key verification up to here in order to coordinate properly. + } + /// Displays the next view in the flow after the authentication screen. private func authenticationCoordinator(_ coordinator: AuthenticationCoordinatorProtocol, didCompleteWith authenticationType: MXKAuthenticationType) { completion?() diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 5484b0c2f..65ed41122 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -119,9 +119,9 @@ self.delegate = self; - _isOnboardingInProgress = NO; + self.isOnboardingInProgress = NO; - // Note: UITabBarViewController shoud not be embed in a UINavigationController (https://github.com/vector-im/riot-ios/issues/3086) + // Note: UITabBarViewController should not be embed in a UINavigationController (https://github.com/vector-im/riot-ios/issues/3086) [self vc_removeBackTitle]; [self setupTitleView]; @@ -520,7 +520,7 @@ [self.onboardingCoordinatorBridgePresenter dismissWithAnimated:YES completion:nil]; self.onboardingCoordinatorBridgePresenter = nil; - self.isOnboardingInProgress = NO; + self.isOnboardingInProgress = NO; // Must be set before calling didCompleteAuthentication [self.masterTabBarDelegate masterTabBarControllerDidCompleteAuthentication:self]; }; diff --git a/changelog.d/5621.change b/changelog.d/5621.change new file mode 100644 index 000000000..fbf80128c --- /dev/null +++ b/changelog.d/5621.change @@ -0,0 +1 @@ +Onboarding: Use a different green spinner during onboarding and use the one presented by the LegacyAppDelegate only when logged in. From 1c87ca788193a6b875f33fb5057d91a822a7b95d Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 19:20:39 +0100 Subject: [PATCH 125/188] Add RoomCellReadMarkerDisplayable protocol. --- .../RoomCellReadMarkerDisplayable.swift | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadMarkerDisplayable.swift diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadMarkerDisplayable.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadMarkerDisplayable.swift new file mode 100644 index 000000000..cde2ceff4 --- /dev/null +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellReadMarkerDisplayable.swift @@ -0,0 +1,23 @@ +// +// Copyright 2021 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 + +/// `RoomCellReadMarkerDisplayable` is a protocol indicating that a cell support displaying read marker. +@objc protocol RoomCellReadMarkerDisplayable { + func addReadMarkerView(_ readMarkerView: UIView) + func removeReadMarkerView() +} From e043a9133199de2aa0e09f4387263132f47e6f85 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 17 Feb 2022 19:21:33 +0100 Subject: [PATCH 126/188] RoomCellContentView: Handle read marker view. --- .../BaseRoomCell/RoomCellContentView.swift | 58 +++++++++++++++++++ .../BaseRoomCell/RoomCellContentView.xib | 21 +++++++ 2 files changed, 79 insertions(+) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index ad9cd3abb..792e1818f 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -56,6 +56,12 @@ final class RoomCellContentView: UIView, NibLoadable { @IBOutlet weak var readReceiptsContainerView: UIView! @IBOutlet weak var readReceiptsContentView: UIView! + @IBOutlet weak var readMarkerContainerView: UIView! + @IBOutlet weak var readMarkerContentView: UIView! + + var readMarkerViewLeadingConstraint: NSLayoutConstraint? + var readMarkerViewTrailingConstraint: NSLayoutConstraint? + @IBOutlet weak var reactionsContainerView: UIView! @IBOutlet weak var reactionsContentView: UIView! @IBOutlet weak var reactionsContentViewLeadingConstraint: NSLayoutConstraint! @@ -154,6 +160,15 @@ final class RoomCellContentView: UIView, NibLoadable { } } + var showReadMarker: Bool { + get { + return !self.readMarkerContainerView.isHidden + } + set { + self.readMarkerContainerView.isHidden = !newValue + } + } + var decorationViewsAlignment: RoomCellDecorationAlignment = .left // MARK: - Setup @@ -304,3 +319,46 @@ extension RoomCellContentView: RoomCellURLPreviewDisplayable { self.urlPreviewContentView.vc_removeAllSubviews() } } + +// MARK: - RoomCellReadMarkerDisplayable +extension RoomCellContentView: RoomCellReadMarkerDisplayable { + + func addReadMarkerView(_ readMarkerView: UIView) { + guard let containerView = self.readMarkerContainerView else { + return + } + + self.readMarkerContentView.vc_removeAllSubviews() + + readMarkerView.translatesAutoresizingMaskIntoConstraints = false + + self.readMarkerContentView.addSubview(readMarkerView) + + // Force read marker constraints + let topConstraint = readMarkerView.topAnchor.constraint(equalTo: containerView.topAnchor) + + let leadingConstraint = readMarkerView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor) + + let trailingConstraint = readMarkerView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor) + + let heightConstraint = readMarkerView.heightAnchor.constraint(equalToConstant: PlainRoomCellLayoutConstants.readMarkerViewHeight) + + let bottomContraint = readMarkerView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor) + + NSLayoutConstraint.activate([topConstraint, + leadingConstraint, + trailingConstraint, + heightConstraint, + bottomContraint]) + + self.readMarkerViewLeadingConstraint = leadingConstraint + self.readMarkerViewTrailingConstraint = trailingConstraint + + self.showReadMarker = true + } + + func removeReadMarkerView() { + self.showReadMarker = false + self.readMarkerContentView.vc_removeAllSubviews() + } +} diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib index 9244e2dd0..41dbba82e 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib @@ -223,6 +223,25 @@ +

Test1:\n<#_foonetic_xkcd:matrix.org>\nhttp://google.com/_thing_\nhttps://matrix.org/_matrix/client/foo/123_\n<#_foonetic_xkcd:matrix.org>

", + "

Test1A:\n<#_foonetic_xkcd:matrix.org>\nhttp://google.com/_thing_\nhttps://matrix.org/_matrix/client/foo/123_\n<#_foonetic_xkcd:matrix.org>

", + "

Test2:\nhttp://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg\nhttp://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg

", + "

Test3:\nhttps://riot.im/app/#/room/#_foonetic_xkcd:matrix.org\nhttps://riot.im/app/#/room/#_foonetic_xkcd:matrix.org

", + "", + ].joined(separator: "\n") + testRenderHTML(input: input, expectedOutput: expectedOutput) + } + + /// Test links with markdown formatting conflict. + func testRenderRepairedLinks() { + let input = [ + "Test1:", + "#_foonetic_xkcd:matrix.org", + "http://google.com/_thing_", + "https://matrix.org/_matrix/client/foo/123_", + "#_foonetic_xkcd:matrix.org", + "", + "Test1A:", + "#_foonetic_xkcd:matrix.org", + "http://google.com/_thing_", + "https://matrix.org/_matrix/client/foo/123_", + "#_foonetic_xkcd:matrix.org", + "", + "Test2:", + "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg", + "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg", + "", + "Test3:", + "https://riot.im/app/#/room/#_foonetic_xkcd:matrix.org", + "https://riot.im/app/#/room/#_foonetic_xkcd:matrix.org", + ].joined(separator: "\n") + let expectedOutput = [ + "

Test1:\n#_foonetic_xkcd:matrix.org\nhttp://google.com/_thing_\nhttps://matrix.org/_matrix/client/foo/123_\n#_foonetic_xkcd:matrix.org

", + "

Test1A:\n#_foonetic_xkcd:matrix.org\nhttp://google.com/_thing_\nhttps://matrix.org/_matrix/client/foo/123_\n#_foonetic_xkcd:matrix.org

", + "

Test2:\nhttp://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg\nhttp://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg

", + "

Test3:\nhttps://riot.im/app/#/room/#_foonetic_xkcd:matrix.org\nhttps://riot.im/app/#/room/#_foonetic_xkcd:matrix.org

", + "", + ].joined(separator: "\n") + testRenderHTML(input: input, expectedOutput: expectedOutput) + } + + /// Test links with markdown strong formatting conflict. + func testRenderRepairedLinksWithStrongFormatting() { + let input = "https://github.com/matrix-org/synapse/blob/develop/synapse/module_api/__init__.py" + + " " + + "https://github.com/matrix-org/synapse/blob/develop/synapse/module_api/__init__.py" + let expectedOutput = "

https://github.com/matrix-org/synapse/blob/develop/synapse/module_api/__init__.py" + + " " + + "https://github.com/matrix-org/synapse/blob/develop/synapse/module_api/__init__.py

" + + "\n" + testRenderHTML(input: input, expectedOutput: expectedOutput) + } + + /// Test links with markdown formatting conflict and actual markdown in between. + func testRenderRepairedLinksWithMarkdownInBetween() { + let input = "__Some bold text__ " + + "https://github.com/matrix-org/synapse/blob/develop/synapse/module_api/__init__.py" + + " _some emphased text_ " + + "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg" + let expectedOutput = "

Some bold text " + + "https://github.com/matrix-org/synapse/blob/develop/synapse/module_api/__init__.py" + + " some emphased text " + + "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg

" + + "\n" + testRenderHTML(input: input, expectedOutput: expectedOutput) + } + + /// Test links inside codeblocks. + func testRenderLinksInCodeblock() { + let input = "```" + + [ + "Test1:", + "#_foonetic_xkcd:matrix.org", + "http://google.com/_thing_", + "https://matrix.org/_matrix/client/foo/123_", + "#_foonetic_xkcd:matrix.org", + "", + "Test1A:", + "#_foonetic_xkcd:matrix.org", + "http://google.com/_thing_", + "https://matrix.org/_matrix/client/foo/123_", + "#_foonetic_xkcd:matrix.org", + "", + "Test2:", + "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg", + "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg", + "", + "Test3:", + "https://riot.im/app/#/room/#_foonetic_xkcd:matrix.org", + "https://riot.im/app/#/room/#_foonetic_xkcd:matrix.org", + ].joined(separator: "\n") + + "```" + let expectedOutput = [ + "
#_foonetic_xkcd:matrix.org",
+            "http://google.com/_thing_",
+            "https://matrix.org/_matrix/client/foo/123_",
+            "#_foonetic_xkcd:matrix.org",
+            "",
+            "Test1A:",
+            "#_foonetic_xkcd:matrix.org",
+            "http://google.com/_thing_",
+            "https://matrix.org/_matrix/client/foo/123_",
+            "#_foonetic_xkcd:matrix.org",
+            "",
+            "Test2:",
+            "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg",
+            "http://domain.xyz/foo/bar-_stuff-like-this_-in-it.jpg",
+            "",
+            "Test3:",
+            "https://riot.im/app/#/room/#_foonetic_xkcd:matrix.org",
+            "https://riot.im/app/#/room/#_foonetic_xkcd:matrix.org```",
+            "
", + "", + ].joined(separator: "\n") + testRenderHTML(input: input, expectedOutput: expectedOutput) + } + + // MARK: - Private + private func testRenderHTML(input: String, expectedOutput: String) { + let output = MarkdownToHTMLRenderer().renderToHTML(markdown: input) + XCTAssertEqual(output, expectedOutput) + } +} diff --git a/changelog.d/5355.bugfix b/changelog.d/5355.bugfix new file mode 100644 index 000000000..131d61af5 --- /dev/null +++ b/changelog.d/5355.bugfix @@ -0,0 +1 @@ +Markdown/HTML: Fix HTTP links containing Markdown formatting From fe8879de392f0429e967ffcc20f08564a0f4c02b Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Fri, 18 Feb 2022 09:16:03 +0000 Subject: [PATCH 135/188] Translated using Weblate (Japanese) Currently translated at 62.6% (898 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 53df7b651..db35ef76a 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -1095,3 +1095,5 @@ "settings_messages_by_a_bot" = "ボットによるメッセージ"; "settings_call_invitations" = "通話への招待"; "settings_room_invitations" = "ルームへの招待"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "コピーをしました"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "コピーする"; From 2ab9955fb8591e7de7dcebe68dee7b8d5337a66a Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 09:15:52 +0000 Subject: [PATCH 136/188] Translated using Weblate (Japanese) Currently translated at 62.6% (898 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 31 +++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index db35ef76a..93f6c0180 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -11,7 +11,7 @@ "continue" = "続く"; "create" = "作成"; "start" = "開始"; -"leave" = "保存しない"; +"leave" = "退出"; "remove" = "削除"; "invite" = "招待"; "retry" = "再試行"; @@ -22,7 +22,7 @@ "join" = "参加"; "decline" = "断る"; "accept" = "受諾"; -"preview" = "下見"; +"preview" = "プレビュー"; "camera" = "カメラ"; "voice" = "音声"; "video" = "映像"; @@ -69,7 +69,7 @@ "auth_phone_in_use" = "この電話番号は既に使用されています"; "auth_untrusted_id_server" = "この認証サーバは信用されていません"; "auth_password_dont_match" = "パスワードが一致しません"; -"auth_username_in_use" = "ユーザ名はすでに使用されています"; +"auth_username_in_use" = "ユーザ名は既に使用されています"; "auth_forgot_password" = "パスワードを忘れましたか?"; "auth_email_not_found" = "電子メールの送信に失敗しました: メールアドレスが見つかりません"; "auth_use_server_options" = "接続先サーバを指定する(追加設定)"; @@ -101,7 +101,7 @@ "room_creation_make_public_prompt_msg" = "このチャットをパブリックしてもよろしいですか? 誰でもあなたのメッセージを読んでチャットに参加できます。"; "room_creation_keep_private" = "プライベートに保つ"; "room_creation_make_private" = "プライベートにする"; -"room_creation_wait_for_creation" = "ルームはすでに作成されています。 お待ちください。"; +"room_creation_wait_for_creation" = "ルームは既に作成されています。 お待ちください。"; "room_creation_invite_another_user" = "ユーザID, 表示名, 電子メールで検索と招待"; // Room recents "room_recents_directory_section" = "ルーム一覧"; @@ -424,7 +424,7 @@ "call_incoming_video_prompt" = "%@ さんから映像つき通話の着信中"; "call_incoming_voice" = "通話着信中…"; "call_incoming_video" = "ビデオ通話の着信中…"; -"call_already_displayed" = "すでに通話中です。"; +"call_already_displayed" = "既に通話中です。"; "call_jitsi_error" = "会議通話への参加に失敗しました。"; // No VoIP support "no_voip_title" = "通話着信中"; @@ -634,7 +634,7 @@ "widget_integration_manager_disabled" = "設定でインテグレーションマネージャーを有効にする必要があります"; "widget_menu_remove" = "全て取り除く"; "widget_menu_revoke_permission" = "アクセスを取り消す"; -"widget_menu_open_outside" = "ブラウザを開く"; +"widget_menu_open_outside" = "ブラウザーで開く"; "widget_menu_refresh" = "リフレッシュ"; "widget_integrations_server_failed_to_connect" = "インテグレーションサーバーへの説を句が失敗しました"; @@ -705,8 +705,8 @@ "identity_server_settings_place_holder" = "IDサーバーを入力する"; "identity_server_settings_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり、発見できるようにするには、上記に追加してください。"; "identity_server_settings_description" = "あなたは%@を使って、あなたの知り合いを発見し、また向こうから発見できるようにしています。"; -"security_settings_complete_security_alert_title" = "完全なセキュリティー"; -"security_settings_crosssigning_complete_security" = "完全なセキュリティー"; +"security_settings_complete_security_alert_title" = "セキュリティーを確認"; +"security_settings_crosssigning_complete_security" = "セキュリティーを確認"; "security_settings_crosssigning_bootstrap" = "独立したクロス署名"; "settings_devices_description" = "セッションのパブリックネームはコミュニケーションをとる相手に表示されます"; "settings_key_backup_delete_confirmation_prompt_title" = "バックアップの削除"; @@ -741,7 +741,7 @@ "room_participants_security_loading" = "読み込み中…"; "room_participants_action_security_status_loading" = "読み込み中…"; "room_participants_action_security_status_warning" = "警告"; -"room_participants_action_security_status_complete_security" = "セキュリティを確認する"; +"room_participants_action_security_status_complete_security" = "セキュリティーを確認"; "room_participants_action_security_status_verify" = "検証"; "room_participants_action_security_status_verified" = "検証済み"; "room_participants_action_section_security" = "セキュリティー"; @@ -1077,7 +1077,7 @@ // MARK: Self verification wait -"device_verification_self_verify_wait_title" = "完全なセキュリティー"; +"device_verification_self_verify_wait_title" = "セキュリティーを確認"; "location_sharing_open_google_maps" = "Googleマップで開く"; "location_sharing_settings_toggle_title" = "ロケーションの共有を有効にする"; "threads_empty_show_all_threads" = "全てのスレッドを表示"; @@ -1097,3 +1097,14 @@ "settings_room_invitations" = "ルームへの招待"; "key_backup_setup_success_from_recovery_key_made_copy_action" = "コピーをしました"; "key_backup_setup_success_from_recovery_key_make_copy_action" = "コピーする"; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "セキュリティーキー"; + +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "あなたの鍵はバックアップされています。\n\nこのセキュリティーキーをコピーして、安全なところに保管してください。"; +"key_backup_setup_success_from_passphrase_done_action" = "完了"; +"room_notifs_settings_cancel_action" = "キャンセル"; +"room_notifs_settings_done_action" = "完了"; +"key_backup_recover_done_action" = "完了"; +"done" = "完了"; +"open" = "開く"; +"enable" = "有効にする"; From a3479f441eb1e68c74914c0ea143ccacf01ff5b7 Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Fri, 18 Feb 2022 09:16:46 +0000 Subject: [PATCH 137/188] Translated using Weblate (Japanese) Currently translated at 62.8% (900 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 93f6c0180..1361264c8 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -1108,3 +1108,5 @@ "done" = "完了"; "open" = "開く"; "enable" = "有効にする"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "パスフレーズを入力する"; +"key_backup_recover_from_passphrase_passphrase_title" = "入力"; From adf50495a83452abfbaf137a79c61d2e7975c05f Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 09:16:10 +0000 Subject: [PATCH 138/188] Translated using Weblate (Japanese) Currently translated at 62.8% (900 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 1361264c8..f73ce3615 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -1095,7 +1095,7 @@ "settings_messages_by_a_bot" = "ボットによるメッセージ"; "settings_call_invitations" = "通話への招待"; "settings_room_invitations" = "ルームへの招待"; -"key_backup_setup_success_from_recovery_key_made_copy_action" = "コピーをしました"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "コピーしました"; "key_backup_setup_success_from_recovery_key_make_copy_action" = "コピーする"; "key_backup_setup_success_from_recovery_key_recovery_key_title" = "セキュリティーキー"; From 01ae028c935521855ba0377d5621b920ca4c99fd Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 18 Feb 2022 11:21:46 +0000 Subject: [PATCH 139/188] Update analytics event pod. --- Podfile.lock | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/Podfile.lock b/Podfile.lock index 942bc098f..6d6029a4c 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -45,7 +45,6 @@ PODS: - GBDeviceInfo/Core (= 6.6.0) - GBDeviceInfo/Core (6.6.0) - GZIP (1.3.0) - - HPGrowingTextView (1.1) - Introspect (0.1.3) - JitsiMeetSDK (3.10.2) - KeychainAccess (4.2.2) @@ -112,7 +111,6 @@ DEPENDENCIES: - FLEX (~> 4.5.0) - FlowCommoniOS (~> 1.12.0) - GBDeviceInfo (~> 6.6.0) - - HPGrowingTextView (~> 1.1) - Introspect (~> 0.1) - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) @@ -149,7 +147,6 @@ SPEC REPOS: - FlowCommoniOS - GBDeviceInfo - GZIP - - HPGrowingTextView - Introspect - JitsiMeetSDK - KeychainAccess @@ -183,7 +180,7 @@ EXTERNAL SOURCES: CHECKOUT OPTIONS: AnalyticsEvents: - :commit: 8058dc6ec07ce0acfe5fdb19eb7e309b0c13845c + :commit: 53844e3f6f9fefa88384a996b2bf5e60bb301b94 :git: https://github.com/matrix-org/matrix-analytics-events.git SPEC CHECKSUMS: @@ -202,7 +199,6 @@ SPEC CHECKSUMS: FlowCommoniOS: ca92071ab526dc89905495a37844fd7e78d1a7f2 GBDeviceInfo: ed0db16230d2fa280e1cbb39a5a7f60f6946aaec GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3 - HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19 Introspect: 2be020f30f084ada52bb4387fff83fa52c5c400e JitsiMeetSDK: 2f118fa770f23e518f3560fc224fae3ac7062223 KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 @@ -229,6 +225,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: ae70a46e98aae87f130ad3d246711fc6b6ae7286 +PODFILE CHECKSUM: 03d59acfc44f69c0727a98aff6c5cbc2470844ef COCOAPODS: 1.11.2 From d6147db250cd1b16124e764fb059b667c049aa9d Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Feb 2022 14:27:29 +0300 Subject: [PATCH 140/188] Stop pagination when root event received --- Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index 88bd02a44..099d358d2 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -1448,6 +1448,16 @@ typedef NS_ENUM (NSUInteger, MXKRoomDataSourceError) { return NO; } } + + if (!USE_THREAD_TIMELINE && direction == MXTimelineDirectionBackwards && self.threadId) + { + // when not using a thread timeline, data source will desperately fill the screen with events by filtering them locally. + // we can stop when we see the thread root event when paginating backwards + if ([event.eventId isEqualToString:self.threadId]) + { + self.shouldStopBackPagination = YES; + } + } return YES; } From 86c30542689004fb0a2a42d7983168034650fba4 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Fri, 18 Feb 2022 14:37:25 +0300 Subject: [PATCH 141/188] Add changelog --- changelog.d/5582.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5582.change diff --git a/changelog.d/5582.change b/changelog.d/5582.change new file mode 100644 index 000000000..ba0081209 --- /dev/null +++ b/changelog.d/5582.change @@ -0,0 +1 @@ +MXKRoomDataSource: Stop pagination in a thread when the root event received. From d66a950fd4a77c5eda553ab679ad1e68946927b7 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 10:03:01 +0000 Subject: [PATCH 142/188] Translated using Weblate (Japanese) Currently translated at 63.1% (905 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index f73ce3615..4a670a46d 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -130,14 +130,14 @@ "search_default_placeholder" = "検索"; "search_people_placeholder" = "ユーザID, 表示名, 電子メールで検索"; "search_no_result" = "結果なし"; -"search_in_progress" = "検索中…"; +"search_in_progress" = "検索しています…"; // Directory "directory_cell_title" = "ルーム一覧を見る"; "directory_cell_description" = "%tu ルーム"; "directory_search_results_title" = "ルーム一覧検索結果"; "directory_search_results" = "%tu 件の検索結果 for %@"; "directory_search_results_more_than" = ">%tu 件の検索結果 for %@"; -"directory_searching_title" = "ルーム一覧を検索中…"; +"directory_searching_title" = "ルーム一覧を検索しています…"; "directory_search_fail" = "一覧を取得できませんでした"; // Contacts "contacts_address_book_section" = "端末の電話帳"; @@ -714,7 +714,7 @@ "settings_key_backup_info_algorithm" = "アルゴリズム: %@"; "settings_key_backup_info_version" = "キーのバックアップバージョン: %@"; "settings_key_backup_info_none" = "あなたのキーはこのセッションからバックアップされていません。"; -"settings_key_backup_info_checking" = "確認中…"; +"settings_key_backup_info_checking" = "確認しています…"; "settings_add_3pid_password_message" = "続けるにはパスワードを入力してください"; "settings_add_3pid_invalid_password_message" = "無効な認証情報"; "settings_add_3pid_password_title_email" = "メールアドレスを追加する"; @@ -738,8 +738,8 @@ "room_member_power_level_short_admin" = "管理者"; "room_member_power_level_moderator_in" = "モデレーターは%@"; "room_member_power_level_admin_in" = "管理者は%@"; -"room_participants_security_loading" = "読み込み中…"; -"room_participants_action_security_status_loading" = "読み込み中…"; +"room_participants_security_loading" = "読み込んでいます…"; +"room_participants_action_security_status_loading" = "読み込んでいます…"; "room_participants_action_security_status_warning" = "警告"; "room_participants_action_security_status_complete_security" = "セキュリティーを確認"; "room_participants_action_security_status_verify" = "検証"; @@ -831,8 +831,8 @@ "security_settings_secure_backup_setup" = "セットアップ"; "security_settings_secure_backup_description" = "暗号化キーをサーバーにバックアップすることにより、暗号化されたメッセージとデータへのアクセスが失われるのを防ぎます。"; "security_settings_secure_backup" = "安全なバックアップ"; -"security_settings_crypto_sessions_description_2" = "ログインが認識されない場合は、パスワードを変更してバックアップをリセットしてください。"; -"security_settings_crypto_sessions_loading" = "セッションを読み込み中…"; +"security_settings_crypto_sessions_description_2" = "見覚えのないログインがある場合は、Matrixアカウントのパスワードを変更し、バックアップをリセットしてください。"; +"security_settings_crypto_sessions_loading" = "セッションを読み込んでいます…"; "security_settings_crypto_sessions" = "セッション"; // Security settings @@ -1108,5 +1108,9 @@ "done" = "完了"; "open" = "開く"; "enable" = "有効にする"; -"key_backup_recover_from_passphrase_passphrase_placeholder" = "パスフレーズを入力する"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "パスフレーズを入力"; "key_backup_recover_from_passphrase_passphrase_title" = "入力"; +"analytics_prompt_terms_link_new_user" = "ここ"; +"secrets_setup_recovery_key_done_action" = "完了"; +"secrets_setup_recovery_passphrase_validate_action" = "完了"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "バックアップ"; From 58b5992164907081f3667ce621cffbbb3bd1740f Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Fri, 18 Feb 2022 10:02:17 +0000 Subject: [PATCH 143/188] Translated using Weblate (Japanese) Currently translated at 63.1% (905 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 4a670a46d..989d8b97d 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -422,7 +422,7 @@ // Call "call_incoming_voice_prompt" = "%@ さんから通話の着信中"; "call_incoming_video_prompt" = "%@ さんから映像つき通話の着信中"; -"call_incoming_voice" = "通話着信中…"; +"call_incoming_voice" = "着信中…"; "call_incoming_video" = "ビデオ通話の着信中…"; "call_already_displayed" = "既に通話中です。"; "call_jitsi_error" = "会議通話への参加に失敗しました。"; From e606fcd349148fd59aadfb63a9ecc1df0b39eacb Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 09:22:41 +0000 Subject: [PATCH 144/188] Translated using Weblate (Japanese) Currently translated at 84.1% (372 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 133 +++++++++--------- 1 file changed, 67 insertions(+), 66 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index c4918a35e..dc8d8ecf7 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -14,9 +14,9 @@ "close" = "閉じる"; "continue" = "続く"; "sign_up" = "登録"; -"resend_message" = "メッセージを再送信する"; +"resend_message" = "メッセージを再送信"; "select_all" = "全て選択"; -"show_details" = "詳細を表示する"; +"show_details" = "詳細を表示"; "login_identity_server_info" = "Matrixは、どの電子メールなどがどのMatrix IDに属しているかを追跡するアイデンティティサーバーを提供します。 現在 https://matrix.org のみが存在します。"; "login_user_id_placeholder" = "Matrix ID(例 @bob:matrix.org または bob)"; "login_optional_field" = "オプション"; @@ -25,16 +25,16 @@ "login_prompt_email_token" = "メールの検証トークンを入力してください:"; "login_error_title" = "ログインに失敗しました"; "login_error_no_login_flow" = "このホームサーバーから認証情報を取得できませんでした"; -"login_error_do_not_support_login_flows" = "現在、このホームサーバーによって定義されたログインフローの一部またはすべてをサポートしていません"; +"login_error_do_not_support_login_flows" = "現在、このホームサーバーによって定義されたログインフローの一部または全てをサポートしていません"; "login_error_registration_is_not_supported" = "登録は現在サポートされていません"; "login_error_forbidden" = "無効なユーザー名/パスワード"; "login_error_unknown_token" = "指定されたアクセストークンが認識されませんでした"; "login_error_bad_json" = "不正な形式のJSON"; "login_error_not_json" = "有効なJSONを含んでいませんでした"; "login_error_limit_exceeded" = "あまりにも多くのリクエストが送られました"; -"login_error_user_in_use" = "このユーザー名はすでに使用されています"; +"login_error_user_in_use" = "このユーザー名は既に使用されています"; "login_error_login_email_not_yet" = "まだクリックされていないメールリンク"; -"login_use_fallback" = "フォールバックページを使用する"; +"login_use_fallback" = "フォールバックページを使用"; "login_leave_fallback" = "キャンセル"; "login_invalid_param" = "無効なパラメーター"; "register_error_title" = "登録に失敗しました"; @@ -46,10 +46,10 @@ "login_error_resource_limit_exceeded_message_default" = "このホームサーバーは、リソース制限の1つを超えています。"; "login_error_resource_limit_exceeded_message_monthly_active_user" = "このホームサーバーは、月間アクティブユーザー制限を超えています。"; "login_error_resource_limit_exceeded_message_contact" = "\n\nこのサービスを続行するには、サービス管理者に連絡してください。"; -"login_error_resource_limit_exceeded_contact_button" = "管理者に連絡する"; -"abort" = "中断する"; +"login_error_resource_limit_exceeded_contact_button" = "管理者に連絡"; +"abort" = "中断"; "discard" = "破棄"; -"dismiss" = "却下する"; +"dismiss" = "却下"; "retry" = "再試行"; "submit" = "提出"; "submit_code" = "コードを送信"; @@ -67,25 +67,25 @@ "reset_to_default" = "デフォルトにリセット"; "cancel_upload" = "アップロードをキャンセル"; "cancel_download" = "ダウンロードをキャンセル"; -"answer_call" = "通話に応答する"; -"reject_call" = "通話を拒否する"; +"answer_call" = "通話に応答"; +"reject_call" = "通話を拒否"; "end_call" = "通話終了"; "ignore" = "無視"; // Events formatter "notice_avatar_changed_too" = "(アバターも変わった)"; -"notice_room_name_removed" = "%@は部屋名を削除しました"; +"notice_room_name_removed" = "%@はルーム名を削除しました"; "notice_room_topic_removed" = "%@はトピックを削除しました"; "notice_event_redacted" = "<編集された%@>"; "notice_event_redacted_by" = " %@により"; "notice_event_redacted_reason" = " [理由: %@]"; "notice_profile_change_redacted" = "%@は彼らのプロフィール %@を更新しました"; -"notice_room_created" = "%@は部屋を作成しました"; +"notice_room_created" = "%@はルームを作成しました"; "notice_room_join_rule" = "結合ルールは次のとおり: %@"; "notice_room_power_level_intro" = "ルームメンバーの権限レベル:"; "notice_room_power_level_acting_requirement" = "アクション前にユーザーの必要な最小権限レベル:"; "notice_room_power_level_event_requirement" = "イベントに関連する最小権限レベル:"; "notice_room_aliases" = "ルームエイリアス: %@"; -"notice_room_related_groups" = "この部屋に関連付けられたグループ: %@"; +"notice_room_related_groups" = "このルームに関連付けられたグループ: %@"; "notice_encrypted_message" = "暗号化されたメッセージ"; "notice_encryption_enabled" = "%@はエンドツーエンド暗号化を有効にする (アルゴリズム %@)"; "notice_image_attachment" = "画像添付"; @@ -100,16 +100,16 @@ "notice_error_unsupported_event" = "サポートされていないイベント"; "notice_error_unexpected_event" = "予期しないイベント"; "notice_error_unknown_event_type" = "不明なイベントタイプ"; -"notice_room_history_visible_to_anyone" = "%@ 誰でも将来の部屋履歴を表示されます。"; -"notice_room_history_visible_to_members" = "%@ ルームメンバー全員に将来の部屋履歴を表示されます。"; -"notice_room_history_visible_to_members_from_invited_point" = "%@ ルームメンバー全員に招待した時点からの部屋履歴を表示されます。"; -"notice_room_history_visible_to_members_from_joined_point" = "%@ ルームメンバー全員に参加した時点からの部屋履歴を表示されます。"; +"notice_room_history_visible_to_anyone" = "%@ 誰でも将来のルーム履歴を表示されます。"; +"notice_room_history_visible_to_members" = "%@ ルームメンバー全員に将来のルーム履歴を表示されます。"; +"notice_room_history_visible_to_members_from_invited_point" = "%@ ルームメンバー全員に招待した時点からのルーム履歴を表示されます。"; +"notice_room_history_visible_to_members_from_joined_point" = "%@ ルームメンバー全員に参加した時点からのルーム履歴を表示されます。"; "notice_crypto_unable_to_decrypt" = "** 復号化できません: %@ **"; "notice_crypto_error_unknown_inbound_session_id" = "送信者のセッションからこのメッセージのキーが送信されていません。"; "notice_sticker" = "ステッカー"; "notice_in_reply_to" = "に返信"; // room display name -"room_displayname_empty_room" = "空の部屋"; +"room_displayname_empty_room" = "空のルーム"; "room_displayname_two_members" = "%@ と %@"; "room_displayname_more_than_two_members" = "%@ と %@ 他"; // Settings @@ -117,7 +117,7 @@ "settings_enable_inapp_notifications" = "アプリ内通知を有効にする"; "settings_enable_push_notifications" = "プッシュ通知を有効にする"; "settings_enter_validation_token_for" = "%@の検証トークンを入力:"; -"notification_settings_room_rule_title" = "部屋: '%@'"; +"notification_settings_room_rule_title" = "ルーム: '%@'"; // Devices "device_details_title" = "セッション情報\n"; "device_details_name" = "名前\n"; @@ -136,7 +136,7 @@ "room_event_encryption_info_event_algorithm" = "アルゴリズム\n"; "room_event_encryption_info_event_session_id" = "セッションID\n"; "room_event_encryption_info_event_decryption_error" = "復号化エラー\n"; -"room_event_encryption_info_event_unencrypted" = "暗号化されていない"; +"room_event_encryption_info_event_unencrypted" = "暗号化されていません"; "room_event_encryption_info_event_none" = "なし"; "room_event_encryption_info_device" = "\n送信者セッション情報\n"; "room_event_encryption_info_device_unknown" = "未知のセッション\n"; @@ -152,7 +152,7 @@ "room_event_encryption_info_block" = "ブラックリスト"; "room_event_encryption_info_unblock" = "ブラックでないリスト"; "room_event_encryption_verify_title" = "セッション検証\n\n"; -"room_event_encryption_verify_message" = "このセッションが信頼できることを確認するには、他の方法(個人や電話など)で所有者に連絡し、セッションのユーザー設定で表示される鍵が以下のキーと一致するかどうかを尋ねます。\n\nセッション名: %@\nセッションID: %@\nセッションkey: %@\n\n一致する場合は、下の確認ボタンを押します。 それ以外の人がこのセッションを傍受している場合は、代わりにブラックリストボタンを押してください。\n\n将来この検証プロセスはより洗練されたものになるでしょう。"; +"room_event_encryption_verify_message" = "このセッションが信頼できることを確認するには、他の方法(個人や電話など)で所有者に連絡し、セッションのユーザー設定で表示される鍵が以下のキーと一致するかどうかを尋ねます。\n\nセッション名: %@\nセッションID: %@\nセッションkey: %@\n\n一致する場合は、下の確認ボタンを押します。 それ以外の人がこのセッションを傍受している場合は、代わりにブラックリストボタンを押してください。\n\n将来この検証プロセスはより洗練されたものになります。"; "room_event_encryption_verify_ok" = "検証"; // Account "account_save_changes" = "変更を保存"; @@ -172,24 +172,24 @@ "account_error_msisdn_wrong_title" = "無効な電話番号"; "account_error_msisdn_wrong_description" = "これは有効な電話番号ではないようです"; // Room creation -"room_creation_name_title" = "部屋名:"; +"room_creation_name_title" = "ルーム名:"; "room_creation_name_placeholder" = "(例 ランチグループ)"; -"room_creation_alias_title" = "部屋の別名:"; +"room_creation_alias_title" = "ルームの別名:"; "room_creation_alias_placeholder" = "(例 #foo:example.org)"; "room_creation_alias_placeholder_with_homeserver" = "(例 #foo%@)"; "room_creation_participants_title" = "参加者:"; "room_creation_participants_placeholder" = "(例 @bob:homeserver1; @john:homeserver2...)"; // Room -"room_please_select" = "部屋を選択してください"; -"room_error_join_failed_title" = "部屋に参加できませんでした"; -"room_error_join_failed_empty_room" = "現在空の部屋に再参加することはできません。"; -"room_error_name_edition_not_authorized" = "この部屋の名前を編集する権限がありません"; -"room_error_topic_edition_not_authorized" = "この部屋のトピックを編集する権限がありません"; +"room_please_select" = "ルームを選択してください"; +"room_error_join_failed_title" = "ルームに参加できませんでした"; +"room_error_join_failed_empty_room" = "現在空のルームに再参加することはできません。"; +"room_error_name_edition_not_authorized" = "このルームの名前を編集する権限がありません"; +"room_error_topic_edition_not_authorized" = "このルームのトピックを編集する権限がありません"; "room_error_cannot_load_timeline" = "タイムラインの読み込みに失敗しました"; "room_error_timeline_event_not_found_title" = "タイムラインの位置を読み込めませんでした"; "room_error_timeline_event_not_found" = "アプリケーションがこのルームのタイムラインに特定のポイントをロードしようとしましたが、それを見つけることができませんでした"; -"room_left" = "あなたは部屋を出ました"; -"room_no_power_to_create_conference_call" = "この部屋で会議を開始するために招待する権限が必要です"; +"room_left" = "あなたはルームを出ました"; +"room_no_power_to_create_conference_call" = "このルームで会議を開始するために招待する権限が必要です"; "room_no_conference_call_in_encrypted_rooms" = "暗号化された会議室では会議通話はサポートされません"; // Reply to message "message_reply_to_sender_sent_an_image" = "画像を送信しました。"; @@ -198,7 +198,7 @@ "message_reply_to_sender_sent_a_file" = "ファイルを送信しました。"; "message_reply_to_message_to_reply_to_prefix" = "に返信"; // Room members -"room_member_ignore_prompt" = "このユーザーからのすべてのメッセージを非表示にしますか?"; +"room_member_ignore_prompt" = "このユーザーからの全てのメッセージを非表示にしますか?"; "room_member_power_level_prompt" = "この変更を元に戻すことはできません。ユーザーが自分と同じレベルの権限を持つように促しますが、よろしいですか?"; // Attachment "attachment_size_prompt" = "次のように送信しますか:"; @@ -228,7 +228,7 @@ "format_time_d" = "日"; // E2E import "e2e_import_room_keys" = "ルームキーをインポート"; -"e2e_import_prompt" = "このプロセスでは、以前に別のMatrixクライアントからエクスポートした暗号化キーをインポートできます。 これにより、他のクライアントが解読できるすべてのメッセージを解読することができます。\nエクスポートファイルはパスフレーズで保護されています。 ファイルを解読するには、パスフレーズをここに入力する必要があります。"; +"e2e_import_prompt" = "このプロセスでは、以前に別のMatrixクライアントからエクスポートした暗号化キーをインポートできます。 これにより、他のクライアントが解読できる全てのメッセージを解読することができます。\nエクスポートファイルはパスフレーズで保護されています。 ファイルを解読するには、パスフレーズをここに入力する必要があります。"; "e2e_import" = "インポート"; "e2e_passphrase_enter" = "パスフレーズを入力"; // E2E export @@ -247,8 +247,8 @@ "error_common_message" = "エラーが発生しました。 後でもう一度お試しください。"; "not_supported_yet" = "まだサポートされていません"; "default" = "既定"; -"private" = "Private"; -"public" = "Public"; +"private" = "プライベート"; +"public" = "公開"; "power_level" = "権限レベル"; "network_error_not_reachable" = "ネットワーク接続を確認してください"; "user_id_placeholder" = "例: @bob:homeserver"; @@ -260,12 +260,12 @@ "local_contacts_access_discovery_warning_title" = "ユーザーの探索"; "local_contacts_access_discovery_warning" = "%@は、ユーザーを検索するためにあなたの連絡先から電子メールと電話番号をアップロードしたい"; // Country picker -"country_picker_title" = "国を選択する"; +"country_picker_title" = "国を選択"; // Language picker -"language_picker_title" = "言語を選択する"; +"language_picker_title" = "言語を選択"; "language_picker_default_language" = "既定値 (%@)"; "notice_room_invite" = "%@は%@を招待しました"; -"notice_room_third_party_invite" = "%@は、部屋に参加するよう%@へ招待状を送った"; +"notice_room_third_party_invite" = "%@は%@にルームへの招待状を送りました"; "notice_room_third_party_registered_invite" = "%@は%@の招待を受け入れました"; "notice_room_join" = "%@ は参加しました"; "notice_room_leave" = "%@ は退出しました"; @@ -280,7 +280,7 @@ "notice_display_name_changed_from" = "%@は表示名を%@から%@に変更しました"; "notice_display_name_removed" = "%@は表示名を削除しました"; "notice_topic_changed" = "%@はトピックを次のように変更しました: %@"; -"notice_room_name_changed" = "%@は部屋名を次のように変更しました: %@"; +"notice_room_name_changed" = "%@はルーム名を次のように変更しました: %@"; "notice_placed_voice_call" = "%@は電話をかけました"; "notice_placed_video_call" = "%@はビデオ電話をかけました"; "notice_answered_video_call" = "%@は通話に応答しました"; @@ -292,7 +292,7 @@ "ok" = "OK"; "cancel" = "キャンセル"; "save" = "保存"; -"leave" = "保存しない"; +"leave" = "退出"; "send" = "送信"; "copy_button_name" = "コピー"; "resend" = "再送信"; @@ -303,34 +303,34 @@ "view" = "表示"; // actions "action_logout" = "ログアウト"; -"create_room" = "部屋を作る"; +"create_room" = "ルームを作る"; "login" = "ログイン"; -"create_account" = "アカウントを作成する"; -"membership_invite" = "招待した"; -"membership_leave" = "退出"; -"membership_ban" = "追放"; +"create_account" = "アカウントを作成"; +"membership_invite" = "招待しました"; +"membership_leave" = "退出しました"; +"membership_ban" = "ブロックしました"; "num_members_one" = "%@ ユーザー"; "num_members_other" = "%@ ユーザー"; "invite" = "招待"; -"kick" = "追い出す"; -"ban" = "追放"; -"unban" = "追放解除"; -"message_unsaved_changes" = "保存されていない変更があります。 放置すると捨てられます。"; +"kick" = "キック"; +"ban" = "ブロック"; +"unban" = "ブロック解除"; +"message_unsaved_changes" = "保存されていない変更があります。 退出すると変更は取り消されます。"; // Login Screen "login_error_already_logged_in" = "ログイン済み"; "login_error_must_start_http" = "URLは http[s]:// で始まる必要があります"; // room details dialog screen -"room_details_title" = "部屋の詳細"; +"room_details_title" = "ルームの詳細"; // contacts list screen "invitation_message" = "私はmatrixであなたとチャットしたい。 詳細はウェブサイトhttp://matrix.orgをお尋ねください。"; // Settings screen "settings_title_config" = "構成"; "settings_title_notifications" = "通知"; // Notification settings screen -"notification_settings_disable_all" = "すべての通知を無効にする"; +"notification_settings_disable_all" = "全ての通知を無効にする"; "notification_settings_enable_notifications" = "通知を有効にする"; -"notification_settings_enable_notifications_warning" = "現在、すべての端末ですべての通知が無効になっています。"; -"notification_settings_global_info" = "通知設定はユーザーアカウントに保存され、デスクトップ通知を含むすべてのクライアント間で共有されます。\n\nルールは順番に適用されます。 一致する最初のルールは、メッセージの結果を定義します。\nだから:単語ごとの通知は、送信者ごとの通知よりも重要な部屋ごとの通知よりも重要です。\n同じ種類の複数のルールの場合、一致するリストの最初のルールが優先されます。"; +"notification_settings_enable_notifications_warning" = "現在、全ての端末で全ての通知が無効になっています。"; +"notification_settings_global_info" = "通知設定はユーザーアカウントに保存され、デスクトップ通知を含む全てのクライアント間で共有されます。\n\nルールは順番に適用されます。 一致する最初のルールは、メッセージの結果を定義します。\nだから:単語ごとの通知は、送信者ごとの通知よりも重要なルームごとの通知よりも重要です。\n同じ種類の複数のルールの場合、一致するリストの最初のルールが優先されます。"; "notification_settings_per_word_notifications" = "単語単位の通知"; "notification_settings_per_word_info" = "単語は大文字と小文字を区別せずに一致させ、*ワイルドカードを含めることができます。 従って:\nfooは、区切り文字で囲まれた文字列foo(例 句読点や空白、行の開始/終了)と一致します。\nfoo*は、fooで始まる単語に一致します。\n*foo*は、3文字のfooを含む単語に一致します。"; "notification_settings_always_notify" = "常に通知"; @@ -338,20 +338,20 @@ "notification_settings_word_to_match" = "一致する単語"; "notification_settings_highlight" = "Highlight"; "notification_settings_custom_sound" = "カスタムサウンド"; -"notification_settings_per_room_notifications" = "1部屋あたりの通知"; +"notification_settings_per_room_notifications" = "1ルームあたりの通知"; "notification_settings_per_sender_notifications" = "送信者ごとの通知"; "notification_settings_sender_hint" = "@user:domain.com"; -"notification_settings_select_room" = "部屋を選択"; +"notification_settings_select_room" = "ルームを選択"; "notification_settings_other_alerts" = "その他のアラート"; "notification_settings_contain_my_user_name" = "私のユーザー名を含むメッセージについて音で私に通知してください"; -"notification_settings_contain_my_display_name" = "私の表示名が含まれているメッセージについて音で私に通知する"; +"notification_settings_contain_my_display_name" = "私の表示名が含まれているメッセージが届いた際に音で通知"; "notification_settings_just_sent_to_me" = "私に送られたメッセージについての音で私に知らせる"; -"notification_settings_invite_to_a_new_room" = "私が新しい部屋に招待されたときに知らせる"; -"notification_settings_people_join_leave_rooms" = "人が部屋に入退室したときに私に通知する"; -"notification_settings_receive_a_call" = "通話を受信したときに通知する"; -"notification_settings_suppress_from_bots" = "ボットからの通知を抑制する"; +"notification_settings_invite_to_a_new_room" = "私が新しいルームに招待されたときに知らせる"; +"notification_settings_people_join_leave_rooms" = "誰かがルームに参加もしくは退出したときに通知"; +"notification_settings_receive_a_call" = "通話を受信したときに通知"; +"notification_settings_suppress_from_bots" = "ボットからの通知を抑制"; "notification_settings_by_default" = "既定値では..."; -"notification_settings_notify_all_other" = "他のすべてのメッセージ/部屋について通知する"; +"notification_settings_notify_all_other" = "他の全てのメッセージ/ルームについて通知"; // gcm section "settings_config_home_server" = "ホームサーバー: %@"; "settings_config_identity_server" = "IDサーバー: %@"; @@ -374,18 +374,18 @@ "ssl_cert_new_account_expl" = "サーバー管理者がこれが予期されると述べた場合は、以下の指紋が提供された指紋と一致することを確認してください。"; "ssl_unexpected_existing_expl" = "証明書は、お使いの携帯電話にて信頼されたものから変更されました。 これは非常に珍しいことです。 この新しい証明書に同意しないことをお勧めします。"; "ssl_expected_existing_expl" = "証明書が以前に信頼されたものから信頼されていないものに変更されました。 サーバーが証明書を更新した可能性があります。 予想される指紋については、サーバー管理者にお問い合わせください。"; -"ssl_only_accept" = "サーバー管理者が上記のものと一致する指紋を発行した場合にのみ、証明書を受け入れます。"; +"ssl_only_accept" = "サーバー管理者が上記のものと一致する指紋を発行した場合にのみ、証明書を受け入れてください。"; "unignore" = "無視しない"; "notice_encryption_enabled_ok" = "%@ がエンドツーエンド暗号化をオンにしました。"; "notice_encryption_enabled_unknown_algorithm" = "%1$@ がエンドツーエンド暗号化をオンにしました (不明なアルゴリズム %2$@)。"; "device_details_rename_prompt_title" = "セッション名"; "account_error_push_not_allowed" = "通知は許可されていません"; -"notice_room_third_party_revoked_invite" = "%@ は %@ の部屋への招待を取り消しました"; +"notice_room_third_party_revoked_invite" = "%@ は %@ のルームへの招待を取り消しました"; // Notice Events with "You" "notice_room_invite_by_you" = "%@を招待しました"; "notice_room_invite_you" = "%@があなたを招待しました"; "notice_room_join_by_you" = "参加しました"; -"notice_room_leave_by_you" = "退室しました"; +"notice_room_leave_by_you" = "退出しました"; "notice_room_kick_by_you" = "%@をキックしました"; "notice_room_unban_by_you" = "%@をBANしました"; "notice_room_ban_by_you" = "%@をBANしました"; @@ -394,16 +394,17 @@ "notice_display_name_changed_from_by_you" = "表示名を%@から%@に変更しました"; "notice_display_name_removed_by_you" = "表示名を削除しました"; "notice_topic_changed_by_you" = "トピックを変更しました: %@"; -"notice_room_name_changed_by_you" = "部屋の名前を変更しました: %@"; +"notice_room_name_changed_by_you" = "ルームの名前を変更しました: %@"; "notice_placed_voice_call_by_you" = "音声通話を開始しました"; "notice_placed_video_call_by_you" = "ビデオ通話を開始しました"; "notice_answered_video_call_by_you" = "電話に出ました"; "notice_ended_video_call_by_you" = "通話を終了しました"; "notice_conference_call_request_by_you" = "VoIP会議をリクエストしました"; -"notice_room_name_removed_by_you" = "部屋名を削除しました"; +"notice_room_name_removed_by_you" = "ルーム名を削除しました"; "notice_room_topic_removed_by_you" = "トピックを削除しました"; "notice_profile_change_redacted_by_you" = "プロフィール %@を更新しました"; -"notice_room_created_by_you" = "部屋を作成しました"; +"notice_room_created_by_you" = "ルームを作成しました"; "notice_encryption_enabled_ok_by_you" = "あなたはエンドツーエンド暗号化をオンにしました。"; "notice_encryption_enabled_unknown_algorithm_by_you" = "あなたはエンドツーエンド暗号化をオンにしました (不明なアルゴリズム %2$@)。"; "notice_redaction_by_you" = "イベントを編集しました (id: %@)"; +"auth_username_in_use" = "ユーザ名は既に使用されています"; From 92091d2b2435bb62f9bf58f5ad70173c5139f8e0 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Feb 2022 15:12:28 +0100 Subject: [PATCH 145/188] MXKRoomBubbleTableViewCell: Update setupMessageTextViewLongPressGesture method. --- .../Common/MXKRoomBubbleTableViewCell.m | 50 ++++++++++--------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m index fb2c9516d..c4367d598 100644 --- a/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m +++ b/Riot/Modules/Room/TimelineCells/Common/MXKRoomBubbleTableViewCell.m @@ -247,32 +247,34 @@ static BOOL _disableLongPressGestureOnEvent; - (void)setupMessageTextViewLongPressGesture { - if (_disableLongPressGestureOnEvent == NO) + if (_disableLongPressGestureOnEvent) { - // Add a long gesture recognizer on text view (in order to display for example the event details) - UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; - longPress.delegate = self; + return; + } + + // Add a long gesture recognizer on text view (in order to display for example the event details) + UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(onLongPressGesture:)]; + longPress.delegate = self; + + // MXKMessageTextView does not catch touches outside of links. Add a background view to handle long touch. + if ([self.messageTextView isKindOfClass:[MXKMessageTextView class]]) + { + UIView *messageTextBackgroundView = [[UIView alloc] initWithFrame:self.messageTextView.frame]; + messageTextBackgroundView.backgroundColor = [UIColor clearColor]; + [self.contentView insertSubview:messageTextBackgroundView belowSubview:self.messageTextView]; + messageTextBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; + [messageTextBackgroundView.leftAnchor constraintEqualToAnchor:self.messageTextView.leftAnchor].active = YES; + [messageTextBackgroundView.rightAnchor constraintEqualToAnchor:self.messageTextView.rightAnchor].active = YES; + [messageTextBackgroundView.topAnchor constraintEqualToAnchor:self.messageTextView.topAnchor].active = YES; + [messageTextBackgroundView.bottomAnchor constraintEqualToAnchor:self.messageTextView.bottomAnchor].active = YES; - // MXKMessageTextView does not catch touches outside of links. Add a background view to handle long touch. - if ([self.messageTextView isKindOfClass:[MXKMessageTextView class]]) - { - UIView *messageTextBackgroundView = [[UIView alloc] initWithFrame:self.messageTextView.frame]; - messageTextBackgroundView.backgroundColor = [UIColor clearColor]; - [self.contentView insertSubview:messageTextBackgroundView belowSubview:self.messageTextView]; - messageTextBackgroundView.translatesAutoresizingMaskIntoConstraints = NO; - [messageTextBackgroundView.leftAnchor constraintEqualToAnchor:self.messageTextView.leftAnchor].active = YES; - [messageTextBackgroundView.rightAnchor constraintEqualToAnchor:self.messageTextView.rightAnchor].active = YES; - [messageTextBackgroundView.topAnchor constraintEqualToAnchor:self.messageTextView.topAnchor].active = YES; - [messageTextBackgroundView.bottomAnchor constraintEqualToAnchor:self.messageTextView.bottomAnchor].active = YES; - - [messageTextBackgroundView addGestureRecognizer:longPress]; - - self.messageTextBackgroundView = messageTextBackgroundView; - } - else - { - [self.messageTextView addGestureRecognizer:longPress]; - } + [messageTextBackgroundView addGestureRecognizer:longPress]; + + self.messageTextBackgroundView = messageTextBackgroundView; + } + else + { + [self.messageTextView addGestureRecognizer:longPress]; } } From e45edac633fa6a2fd1c3ec6f61be16ddf593f85b Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 14:23:26 +0000 Subject: [PATCH 146/188] Translated using Weblate (Japanese) Currently translated at 63.1% (905 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index 989d8b97d..c4fb0d645 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -82,7 +82,7 @@ "auth_reset_password_missing_email" = "あなたのアカウントに登録された電子メールアドレスの入力が必要です."; "auth_reset_password_missing_password" = "新しいパスワードの入力が必要です."; "auth_reset_password_email_validation_message" = "%@ へ電子メールが送信されました. リンクをたどったら以下をクリックしてください."; -"auth_reset_password_next_step_button" = "自分用電子メールアドレスで認証をします"; +"auth_reset_password_next_step_button" = "メールアドレスを認証しました"; "auth_reset_password_error_unauthorized" = "電子メールアドレスの確認に失敗しました: 電子メールのリンクをクリックしたことを確認してください"; "auth_reset_password_error_not_found" = "あなたの電子メールアドレスは、接続先サーバ上のMatrix IDと関連付けられていないようです。"; "auth_reset_password_success_message" = "あなたのパスワードは初期化されました.\n\nあなたは全てのセッションから切断しており、プッシュ通知を受け取ることはありません。通知を再度有効にするには、各端末に再度ログインします。"; @@ -115,7 +115,7 @@ "room_recents_create_empty_room" = "ルームを作成"; "room_recents_join_room" = "ルームへ参加"; "room_recents_join_room_title" = "ルームへ参加"; -"room_recents_join_room_prompt" = "ルームIDまたはルームのエイリアスを入力します"; +"room_recents_join_room_prompt" = "ルームIDまたはルームのエイリアスを入力"; // People tab "people_invites_section" = "招待中"; "people_conversation_section" = "会話"; @@ -176,11 +176,11 @@ "room_participants_action_section_other" = "オプション"; "room_participants_action_invite" = "招待"; "room_participants_action_leave" = "このルームを出る"; -"room_participants_action_remove" = "このルームから退室させる"; -"room_participants_action_ban" = "このルームからブロックする"; +"room_participants_action_remove" = "このルームから削除"; +"room_participants_action_ban" = "このルームからブロック"; "room_participants_action_unban" = "ブロック解除"; "room_participants_action_ignore" = "この参加者の発言を全て非表示にする"; -"room_participants_action_unignore" = "この参加者の発言を全て表示する"; +"room_participants_action_unignore" = "この参加者の発言を全て表示"; "room_participants_action_set_default_power_level" = "権限を一般参加者へ変更"; "room_participants_action_set_moderator" = "権限を司会者へ変更"; "room_participants_action_set_admin" = "権限を管理者へ変更"; @@ -876,7 +876,7 @@ "settings_security" = "セキュリティー"; "settings_three_pids_management_information_part3" = ""; "settings_three_pids_management_information_part2" = "ディスカバリー"; -"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データ収集、バックドア、ユーザーの囲い込みから逃れることができます。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementはあなた自身でサーバーをホストすることも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、あなたは他のElementユーザーと話せるだけでなくオープンネットワークへのアクセスも可能です。\n\nElementは、オープンな分散型通信の標準規格であるMatrixで動作するため、これら全てを実現することができています。\n\nどのサーバーがホストするか決めることができます。さまざまな方法で選択できます。\n\n1. 開発者がホストするmatrix.orgの公開サーバーで無料のアカウントを取得します。\n2. あなた自身がサーバーを動かし、アカウントを管理します。\n3. Element Matrix Servicesのホスティングプラットフォームに登録することで、カスタムサーバー上のアカウントを取得できます。\n\nなぜElementを選ぶべきなのか?\n\nデータを所有する: 自分でデータやメッセージを保管する場所を決めることができます。あなたが所有権を持ってコントロールすることで、第三者にあなたのデータを渡したり、ビッグデータを収集する巨大テック企業に依存する必要がなくなります。\n\n開かれたネットワークと共同作業: Matrixネットワーク内の他の誰とでも、あるいはElementや他のMatrixアプリを使っているかどうかに関わらず、またSlack、IRC、XMPPのような他のメッセージングシステムを使っているかどうかに関わらず、チャットすることができます。\n\nとても安全: 本物のエンドツーエンド暗号化(会話に参加している者のみがメッセージを読める)と会話参加者の真正性を確認するためクロス署名によって。\n\n完全なるコミュニケーションの訪れ: テキスト、音声通話、ビデオ通話、ファイル共有、画面共有、連携機能、ボット、ウィジェットなどのコミュニケーションに必要な機能の全てが実装されています。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでもどこにいても: 全てのデバイスとウェブでメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。https://app.element.io"; +"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使うかを、ご自身で決めることができます。\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全てのデバイスとウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; "user_verification_session_details_additional_information_untrusted_other_user" = "ユーザーがこのセッションを信頼するまでは、セッションとの間で送受信されるメッセージには警告が表示されます。また、手動で検証することもできます。"; "user_verification_session_details_information_untrusted_other_user" = " 新しいセッションを使ってサインインしました:"; "user_verification_session_details_information_untrusted_current_user" = "このセッションを検証することで、信頼できるものとしてマークし、暗号化されたメッセージへのアクセスを許可します。"; From 0db9c983d62bafd5116430d46a4ffa5e5a98e4ea Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 14:39:25 +0000 Subject: [PATCH 147/188] Translated using Weblate (Japanese) Currently translated at 84.1% (372 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index dc8d8ecf7..8b4bbe069 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -56,7 +56,7 @@ "set_default_power_level" = "権限レベルをリセット"; "set_moderator" = "モデレーターを設定"; "set_admin" = "管理者を設定"; -"start_chat" = "チャットを始める"; +"start_chat" = "チャットを開始"; "start_voice_call" = "音声通話を開始"; "start_video_call" = "ビデオ通話を開始"; "mention" = "記載"; @@ -72,7 +72,7 @@ "end_call" = "通話終了"; "ignore" = "無視"; // Events formatter -"notice_avatar_changed_too" = "(アバターも変わった)"; +"notice_avatar_changed_too" = "(アバターも変更されました)"; "notice_room_name_removed" = "%@はルーム名を削除しました"; "notice_room_topic_removed" = "%@はトピックを削除しました"; "notice_event_redacted" = "<編集された%@>"; @@ -147,7 +147,7 @@ "room_event_encryption_info_device_verified" = "検証済み"; "room_event_encryption_info_device_not_verified" = "検証されていない"; "room_event_encryption_info_device_blocked" = "ブラックリストに載せた"; -"room_event_encryption_info_verify" = "検証中..."; +"room_event_encryption_info_verify" = "検証しています…"; "room_event_encryption_info_unverify" = "未検証"; "room_event_encryption_info_block" = "ブラックリスト"; "room_event_encryption_info_unblock" = "ブラックでないリスト"; @@ -220,7 +220,7 @@ "group_section" = "グループ"; // Search "search_no_results" = "結果がありません"; -"search_searching" = "検索中..."; +"search_searching" = "検索しています…"; // Time "format_time_s" = "秒"; "format_time_m" = "分"; From e654ab89f2040c11aaec09d367c0f87ce743fb7d Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 14:42:39 +0000 Subject: [PATCH 148/188] Translated using Weblate (Japanese) Currently translated at 84.1% (372 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index 8b4bbe069..caae6a410 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -2,9 +2,9 @@ // Login Screen "login_create_account" = "アカウント作成:"; "login_server_url_placeholder" = "URL (例 https://matrix.org)"; -"login_home_server_title" = "接続先サーバURL:"; -"login_home_server_info" = "あなたの接続先サーバは、あなたの全ての会話とアカウント情報を保存します"; -"login_identity_server_title" = "認証サーバURL:"; +"login_home_server_title" = "接続先サーバーURL:"; +"login_home_server_info" = "あなたの接続先サーバーは、あなたの全ての会話とアカウント情報を保存します"; +"login_identity_server_title" = "認証サーバーURL:"; "login_password_placeholder" = "パスワード"; "login_email_placeholder" = "メールアドレス"; // Action From d673c7cc20b680b127658083c95c6da6db19ad95 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Feb 2022 16:04:56 +0100 Subject: [PATCH 149/188] Message bubbles: Fix incoming attachment leading margin. --- .../Styles/Bubble/BubbleRoomCellLayoutUpdater.swift | 2 +- .../Common/MXKRoomIncomingAttachmentBubbleCell.m | 10 ++++++++++ .../TimelineCells/Styles/RoomCellLayoutUpdating.swift | 2 ++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift index 5b1124c5a..d1894d48b 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutUpdater.swift @@ -261,7 +261,7 @@ class BubbleRoomCellLayoutUpdater: RoomCellLayoutUpdating { let leftMargin: CGFloat = BubbleRoomCellLayoutConstants.incomingBubbleBackgroundMargins.left - let leftConstraint = attachmentView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: -leftMargin) + let leftConstraint = attachmentView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: leftMargin) NSLayoutConstraint.activate([ leftConstraint diff --git a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m index ecb9eaa3a..565a23c0e 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/TimelineCells/Styles/Plain/Cells/FileAttachment/Incoming/Common/MXKRoomIncomingAttachmentBubbleCell.m @@ -15,7 +15,17 @@ */ #import "MXKRoomIncomingAttachmentBubbleCell.h" +#import "GeneratedInterface-Swift.h" @implementation MXKRoomIncomingAttachmentBubbleCell +- (void)setupViews +{ + [super setupViews]; + + RoomTimelineConfiguration *timelineConfiguration = [RoomTimelineConfiguration shared]; + + [timelineConfiguration.currentStyle.cellLayoutUpdater setupLayoutForIncomingFileAttachmentCell:self]; +} + @end diff --git a/Riot/Modules/Room/TimelineCells/Styles/RoomCellLayoutUpdating.swift b/Riot/Modules/Room/TimelineCells/Styles/RoomCellLayoutUpdating.swift index 2c8b85e83..232253a79 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/RoomCellLayoutUpdating.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/RoomCellLayoutUpdating.swift @@ -26,6 +26,8 @@ protocol RoomCellLayoutUpdating: Themable { func setupLayout(forOutgoingTextMessageCell cell: MXKRoomBubbleTableViewCell) + func setupLayout(forIncomingFileAttachmentCell cell: MXKRoomBubbleTableViewCell) + func setupLayout(forOutgoingFileAttachmentCell cell: MXKRoomBubbleTableViewCell) func updateLayout(forSelectedStickerCell cell: RoomSelectedStickerBubbleCell) From 19d45ddf2122b5e72ac52d1e99f3deb4e6dc659f Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Feb 2022 16:26:09 +0100 Subject: [PATCH 150/188] RoomCellContentView: Expose new contraints. --- .../Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift | 4 ++++ .../Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib | 3 +++ 2 files changed, 7 insertions(+) diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift index 792e1818f..e8cc17639 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.swift @@ -33,11 +33,15 @@ final class RoomCellContentView: UIView, NibLoadable { @IBOutlet weak var userNameLabel: UILabel! @IBOutlet weak var userNameTouchMaskView: UIView! + @IBOutlet weak var userNameLabelTopConstraint: NSLayoutConstraint! + @IBOutlet weak var userNameLabelBottomConstraint: NSLayoutConstraint! + @IBOutlet weak var avatarContainerView: UIView! @IBOutlet weak var avatarImageView: MXKImageView! @IBOutlet weak var innerContentView: UIView! + @IBOutlet weak var innerContentViewTopConstraint: NSLayoutConstraint! @IBOutlet weak var innerContentViewLeadingConstraint: NSLayoutConstraint! @IBOutlet weak var innerContentViewTrailingConstraint: NSLayoutConstraint! @IBOutlet weak var innerContentViewBottomContraint: NSLayoutConstraint! diff --git a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib index 889ae11da..c05e9823a 100644 --- a/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib +++ b/Riot/Modules/Room/TimelineCells/BaseRoomCell/RoomCellContentView.xib @@ -300,6 +300,7 @@ + @@ -323,6 +324,8 @@ + + From c22d2bbe99df68be4bd0f2b76adbf0d4e187d5c9 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Feb 2022 16:26:35 +0100 Subject: [PATCH 151/188] TextMessageBaseBubbleCell: Reduce sender name bottom margin. --- .../Styles/Bubble/BubbleRoomCellLayoutConstants.swift | 4 ++++ .../Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift | 2 ++ 2 files changed, 6 insertions(+) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift index 3df3d5985..8e483174c 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/BubbleRoomCellLayoutConstants.swift @@ -24,6 +24,10 @@ final class BubbleRoomCellLayoutConstants: NSObject { /// Inner content view margins static let innerContentViewMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 0, bottom: 5.0, right: 0) + // Sender name margins + + static let senderNameLabelMargins: UIEdgeInsets = UIEdgeInsets(top: 10, left: 0, bottom: 0.0, right: 0) + // Text message bubbles margins from cell content view static let outgoingBubbleBackgroundMargins: UIEdgeInsets = UIEdgeInsets(top: 0, left: 80, bottom: 0, right: 34) diff --git a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift index 35e834591..73c465a94 100644 --- a/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift +++ b/Riot/Modules/Room/TimelineCells/Styles/Bubble/Cells/TextMessage/Common/TextMessageBaseBubbleCell.swift @@ -40,6 +40,8 @@ class TextMessageBaseBubbleCell: SizableBaseRoomCell, RoomCellURLPreviewDisplaya return } + roomCellContentView?.userNameLabelBottomConstraint.constant = BubbleRoomCellLayoutConstants.senderNameLabelMargins.bottom + roomCellContentView?.innerContentViewBottomContraint.constant = BubbleRoomCellLayoutConstants.innerContentViewMargins.bottom let textMessageContentView = TextMessageBubbleCellContentView.instantiate() From 48e70d6fb3037d4d9b62e604af6d20ac561c6047 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 18 Feb 2022 18:15:54 +0100 Subject: [PATCH 152/188] Add changes --- changelog.d/pr-5634.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/pr-5634.misc diff --git a/changelog.d/pr-5634.misc b/changelog.d/pr-5634.misc new file mode 100644 index 000000000..2be0bab62 --- /dev/null +++ b/changelog.d/pr-5634.misc @@ -0,0 +1 @@ +Message bubbles: Reduce sender name bottom margin for text message. \ No newline at end of file From 6603b0babb6865761354ebecb530f0d802e82137 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 19:33:52 +0000 Subject: [PATCH 153/188] Translated using Weblate (Japanese) Currently translated at 66.7% (957 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 108 ++++++++++++++-------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index c4fb0d645..febf0e49d 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -96,11 +96,11 @@ "room_creation_privacy" = "個人情報保護"; "room_creation_private_room" = "この会話は非公開です"; "room_creation_public_room" = "この会話は公開されます"; -"room_creation_make_public" = "パブリックにする"; -"room_creation_make_public_prompt_title" = "このチャットをパブリックしますか?"; -"room_creation_make_public_prompt_msg" = "このチャットをパブリックしてもよろしいですか? 誰でもあなたのメッセージを読んでチャットに参加できます。"; -"room_creation_keep_private" = "プライベートに保つ"; -"room_creation_make_private" = "プライベートにする"; +"room_creation_make_public" = "公開"; +"room_creation_make_public_prompt_title" = "このチャットを公開しますか?"; +"room_creation_make_public_prompt_msg" = "このチャットを公開してもよろしいですか? 誰でもあなたのメッセージを読んでチャットに参加できます。"; +"room_creation_keep_private" = "非公開に保つ"; +"room_creation_make_private" = "非公開にする"; "room_creation_wait_for_creation" = "ルームは既に作成されています。 お待ちください。"; "room_creation_invite_another_user" = "ユーザID, 表示名, 電子メールで検索と招待"; // Room recents @@ -231,8 +231,8 @@ "unknown_devices_alert_title" = "ルームに未知のセッションが存在します"; "unknown_devices_alert" = "このルームには、確認されていない未知のセッションが含まれています。\nすなわち、セッションがをユーザ本人が所有しているという保証はありません。\n続ける前に各セッションの確認を行うことをおすすめしますが、確認することなく発言を再送信することができます。"; "unknown_devices_send_anyway" = "とにかく送る"; -"unknown_devices_call_anyway" = "とにかく通話する"; -"unknown_devices_answer_anyway" = "とにかく応答する"; +"unknown_devices_call_anyway" = "とにかく通話"; +"unknown_devices_answer_anyway" = "とにかく応答"; "unknown_devices_verify" = "確認…"; "unknown_devices_title" = "未知のセッション"; // Room Title @@ -250,7 +250,7 @@ "room_preview_try_join_an_unknown_room_default" = "ルーム"; // Settings "settings_title" = "設定"; -"account_logout_all" = "全てのアカウントを回線切断する"; +"account_logout_all" = "全てのアカウントを回線切断"; "settings_config_no_build_info" = "ビルド情報がありません"; "settings_mark_all_as_read" = "全ての発言を既読にする"; "settings_report_bug" = "不具合報告"; @@ -288,7 +288,7 @@ "settings_enable_push_notif" = "この端末での通知"; "settings_show_decrypted_content" = "復号化された文章を表示"; "settings_global_settings_info" = "あなたの %@ webクライアント上で、全体の通知設定が可能です"; -"settings_pin_rooms_with_missed_notif" = "逃した通知があるルームをピン止めする"; +"settings_pin_rooms_with_missed_notif" = "逃した通知があるルームをピン止め"; "settings_callkit_info" = "画面がロックされているときに着信がありました。Elementの着信はシステムの通話履歴で確認できます。 iCloudが有効になっている場合、この通話履歴はAppleと共有されます。"; "settings_ui_language" = "言語"; "settings_ui_theme" = "外観"; @@ -303,7 +303,7 @@ "settings_labs_e2e_encryption" = "エンドツーエンド暗号化"; "settings_labs_e2e_encryption_prompt_message" = "暗号化の設定を完了するためには再度ログインしてください。"; "settings_labs_matrix_apps" = "Matrixアプリ"; -"settings_labs_create_conference_with_jitsi" = "jitsiの会議通話を作成する"; +"settings_labs_create_conference_with_jitsi" = "jitsiの会議通話を作成"; "settings_version" = "Version %@"; "settings_olm_version" = "Olm バージョン %@"; "settings_copyright" = "著作権"; @@ -341,7 +341,7 @@ "room_details_access_section_anyone_apart_from_guest" = "誰でもルームに参加できる (ゲストユーザは不可)"; "room_details_access_section_anyone" = "誰でもルームに参加できる (ゲストユーザも許可)"; "room_details_access_section_no_address_warning" = "このルームへのリンクを作成するには、ルームの住所表記が必要です"; -"room_details_access_section_directory_toggle" = "ルーム一覧へ公開する"; +"room_details_access_section_directory_toggle" = "ルーム一覧へ公開"; "room_details_history_section" = "誰をこのルームの発言履歴を読めるようにしますか?"; "room_details_history_section_anyone" = "誰でも"; "room_details_history_section_members_only" = "参加者のみ (この設定を選択した時点から)"; @@ -442,7 +442,7 @@ "bug_report_logs_description" = "開発者が問題を診断するために、このElementの動作記録が不具合報告と一緒に送信されます。上記文章のみを送信したい場合は以下のチェックを解除してください:"; "bug_report_send_logs" = "動作記録を送信"; "bug_report_send_screenshot" = "画面のスクリーンショット画像を送信"; -"bug_report_progress_zipping" = "動作記録を収集する"; +"bug_report_progress_zipping" = "動作記録を収集"; "bug_report_progress_uploading" = "報告を送信しています"; "bug_report_send" = "送信"; // Widget @@ -460,11 +460,11 @@ "widget_integration_missing_user_id" = "ユーザ固有IDの要求に失敗しました。"; "widget_integration_room_not_visible" = "ルーム %@ は見えません。"; // Share extension -"share_extension_auth_prompt" = "コンテンツを共有するためにメインのアプリにログインする"; +"share_extension_auth_prompt" = "メインのアプリにログインしてコンテンツを共有"; "share_extension_failed_to_encrypt" = "送信に失敗しました。このルームの暗号設定をメインの端末で確認して下さい"; "room_details_advanced_e2e_encryption_prompt_message" = "End-to-end暗号化は実験的なものであり、信頼性が低い場合があります。\n\n発言を保護するためにはまだそれを信用すべきではありません。\n\n端末は、まだ参加する前の発言履歴を復号化することはできません。\n\n部屋の暗号化が今から有効になったら、もう無効にすることはできません。\n\n暗号化された発言は、まだ暗号化を実装していないアプリでは表示されません。"; "settings_enable_callkit" = "呼び出しの統合"; -"settings_pin_rooms_with_unread" = "未読のあるルームをピン止めする"; +"settings_pin_rooms_with_unread" = "未読のあるルームをピン止め"; "title_groups" = "コミュニティー"; "room_recents_server_notice_section" = "システムアラート"; // Groups tab @@ -482,7 +482,7 @@ "room_replacement_link" = "会話はここで続けられます。"; "room_predecessor_information" = "このルームは別の会話の続きです。"; "room_predecessor_link" = "より古いメッセージを見るにはここをタップしてください。"; -"room_resource_limit_exceeded_message_contact_2_link" = "サービス管理者に連絡する"; +"room_resource_limit_exceeded_message_contact_2_link" = "サービス管理者に連絡"; "room_resource_limit_exceeded_message_contact_3" = " このサービスの使用を継続するには。"; "room_resource_usage_limit_reached_message_1_default" = "このホームサーバーはリソース制限の1つを超えています "; "room_resource_usage_limit_reached_message_1_monthly_active_user" = "このホームサーバーは月間アクティブユーザー数制限を超えています "; @@ -556,7 +556,7 @@ "room_event_action_ban_prompt_reason" = "このユーザーをブロックする理由"; "room_resource_limit_exceeded_message_contact_1" = " お願い "; "settings_ui_theme_black" = "Black"; -"settings_flair" = "特色を表示する"; +"settings_flair" = "特色を表示"; // String for App Store "store_short_description" = "セキュアな分散型チャット/VoIP"; "close" = "閉じる"; @@ -574,10 +574,10 @@ "room_info_list_one_member" = "1 人のメンバー"; "create_room_placeholder_address" = "#testroom:matrix.org"; "create_room_section_header_address" = "ルームのアドレス"; -"create_room_show_in_directory" = "このルームをディレクトリに掲載する"; -"create_room_section_footer_type" = "プライベートなルームは、ルームに招待された人のみ参加できます。"; +"create_room_show_in_directory" = "このルームを一覧に掲載"; +"create_room_section_footer_type" = "非公開のルームは、ルームに招待された人のみ参加できます。"; "create_room_type_public" = "公開されたルーム"; -"create_room_type_private" = "プライベートなルーム"; +"create_room_type_private" = "非公開のルーム"; "create_room_section_header_type" = "ルームの種類"; "create_room_section_footer_encryption" = "暗号化はあとから無効にすることはできません。"; "create_room_section_header_encryption" = "ルームの暗号化"; @@ -604,7 +604,7 @@ // Call Bar "callbar_only_single_active" = "アクティブな通話(%@)"; -"settings_add_3pid_password_title_msidsn" = "電話番号の追加する"; +"settings_add_3pid_password_title_msidsn" = "電話番号を追加"; "device_verification_emoji_scissors" = "ハサミ"; "device_verification_emoji_paperclip" = "ペーパークリップ"; "device_verification_emoji_pencil" = "鉛筆"; @@ -636,11 +636,11 @@ "widget_menu_revoke_permission" = "アクセスを取り消す"; "widget_menu_open_outside" = "ブラウザーで開く"; "widget_menu_refresh" = "リフレッシュ"; -"widget_integrations_server_failed_to_connect" = "インテグレーションサーバーへの説を句が失敗しました"; +"widget_integrations_server_failed_to_connect" = "インテグレーションサーバーへの接続が失敗しました"; // Widget "widget_no_integrations_server_configured" = "インテグレーションサーバーが設定されていません"; -"bug_report_background_mode" = "バックグラウンドで継続する"; +"bug_report_background_mode" = "バックグラウンドで継続"; "e2e_key_backup_wrong_version_button_wasme" = "これはわたしです"; "e2e_key_backup_wrong_version_button_settings" = "設定"; "e2e_key_backup_wrong_version" = "新しいメッセージキーのバックアップが検出されました。\n\nこれがあなたによるものでばい場合は、設定から新しいパスフレーズを設定してください。"; @@ -679,7 +679,7 @@ "room_details_advanced_e2e_encryption_enabled_for_dm" = "ここは暗号化が有効です"; "room_details_advanced_room_id_for_dm" = "ID:"; "room_details_no_local_addresses_for_dm" = "ここにはローカルアドレスがありません"; -"room_details_access_section_directory_toggle_for_dm" = "ルームディレクトリに掲載する"; +"room_details_access_section_directory_toggle_for_dm" = "ルーム一覧に掲載"; "room_details_access_section_anyone_apart_from_guest_for_dm" = "ゲスト以外のリンクを知っている人"; "room_details_access_section_anyone_for_dm" = "ゲストを含め、リンクを知っている人なら誰でも"; "room_details_access_section_for_dm" = "誰がアクセスできるのか?"; @@ -689,20 +689,20 @@ "room_details_title_for_dm" = "詳細"; "identity_server_settings_alert_error_invalid_identity_server" = "%@は有効なIDサーバーではありません。"; "identity_server_settings_alert_error_terms_not_accepted" = "IDサーバーとして設定するには%@の条件を受け入れる必要があります。"; -"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "とにかく切断する"; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "とにかく切断"; "identity_server_settings_alert_disconnect_still_sharing_3pid" = "あなたはまだIDサーバー%@で個人データを共有しています。\n\n切断する前にメールアドレスと電話番号をIDサーバーから削除することをお勧めします。"; "identity_server_settings_alert_disconnect_button" = "接続を解除"; "identity_server_settings_alert_disconnect" = "IDサーバー%@を接続解除しますか?"; "identity_server_settings_alert_disconnect_title" = "IDサーバーを接続解除"; "identity_server_settings_alert_change" = "IDサーバー%1$@を切断し、代わりに %2$@に接続しますか?"; -"identity_server_settings_alert_change_title" = "IDサーバーを変更する"; +"identity_server_settings_alert_change_title" = "IDサーバーを変更"; "identity_server_settings_alert_no_terms" = "選択したIDサーバーには利用規約がありません。そのサーバーの所有者を信頼できる場合にのみ続行してください。"; "identity_server_settings_alert_no_terms_title" = "IDサーバーには利用規約がありません"; "identity_server_settings_disconnect" = "接続を解除"; "identity_server_settings_disconnect_info" = "IDサーバーとの接続を解除すると、他のユーザーから発見されなくなり、メールや電話で他のユーザーを招待することができるようになります。"; -"identity_server_settings_change" = "変更する"; -"identity_server_settings_add" = "追加する"; -"identity_server_settings_place_holder" = "IDサーバーを入力する"; +"identity_server_settings_change" = "変更"; +"identity_server_settings_add" = "追加"; +"identity_server_settings_place_holder" = "IDサーバーを入力"; "identity_server_settings_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり、発見できるようにするには、上記に追加してください。"; "identity_server_settings_description" = "あなたは%@を使って、あなたの知り合いを発見し、また向こうから発見できるようにしています。"; "security_settings_complete_security_alert_title" = "セキュリティーを確認"; @@ -717,10 +717,10 @@ "settings_key_backup_info_checking" = "確認しています…"; "settings_add_3pid_password_message" = "続けるにはパスワードを入力してください"; "settings_add_3pid_invalid_password_message" = "無効な認証情報"; -"settings_add_3pid_password_title_email" = "メールアドレスを追加する"; +"settings_add_3pid_password_title_email" = "メールアドレスを追加"; "settings_integrations_allow_description" = "インテグレーションマネージャー(%@)を使用して、ボット、ブリッジ、ウィジェット、ステッカーパックを管理します。\n\n設定データを受け取り、お客様に代わってウィジェットの変更、ルーム招待の送信、権限の設定を行うことができます。"; "settings_integrations_allow_button" = "インテグレーションを管理"; -"settings_calls_stun_server_fallback_button" = "フォールバックコールアシストサーバを許可する"; +"settings_calls_stun_server_fallback_button" = "フォールバックコールアシストサーバを許可"; "settings_key_backup" = "キーのバックアップ"; "settings_integrations" = "インテグレーション"; "settings_discovery_settings" = "ディスカバリー"; @@ -768,18 +768,18 @@ // Social login "social_login_list_title_continue" = "続きはこちら"; -"auth_softlogout_clear_data_sign_out_msg" = "このデバイスに現在保存されている全てのデータを消去してよろしいですか?再びサインインするとアカウントデータやメッセージにアクセスできます。"; +"auth_softlogout_clear_data_sign_out_msg" = "この端末に現在保存されている全てのデータを消去してよろしいですか?再びサインインするとアカウントデータやメッセージにアクセスできます。"; "auth_softlogout_clear_data_sign_out_title" = "続行してよろしいですか?"; -"auth_softlogout_clear_data_button" = "全てのデータをクリアする"; -"auth_softlogout_clear_data_message_2" = "このデバイスの使用を終了する場合や、別のアカウントにサインインしたい場合は、クリアしてください。"; -"auth_softlogout_clear_data_message_1" = "警告: 個人データ(暗号化キーを含む)がこのデバイスにまだ保存されています。"; +"auth_softlogout_clear_data_button" = "全てのデータをクリア"; +"auth_softlogout_clear_data_message_2" = "この端末の使用を終了する場合や、別のアカウントにサインインしたい場合は、クリアしてください。"; +"auth_softlogout_clear_data_message_1" = "警告: 個人データ(暗号化キーを含む)がこの端末にまだ保存されています。"; "callbar_return" = "かけ直す"; "callbar_active_and_multiple_paused" = "アクティブな通話 (%@) · %@ の一時停止された通話"; "callbar_only_multiple_paused" = "一時停止した%@の通話"; "callbar_only_single_paused" = "通話の一時停止"; "store_promotional_text" = "オープンネットワーク上でプライバシーを保護したチャットアプリ。あなた自身でコントロールできるように非中央集権化(分散化)されています。データマイニング、バックドア、サードパーティによるアクセスはありません。"; -"auth_softlogout_clear_data" = "個人データをクリアする"; -"auth_softlogout_recover_encryption_keys" = "サインインして、このデバイスにのみ保存されている暗号化キーを復元します。どのデバイスでも、あなたのセキュアなメッセージを全て読むために必要です。"; +"auth_softlogout_clear_data" = "個人データをクリア"; +"auth_softlogout_recover_encryption_keys" = "サインインして、この端末にのみ保存されている暗号化キーを復元します。どの端末でも、あなたのセキュアなメッセージを全て読むために必要です。"; "auth_softlogout_reason" = "ホームサーバー(%1$@)の管理者が%2$@(%3$@)からサインアウトさせました。"; "auth_softlogout_sign_in" = "サインイン"; "auth_softlogout_signed_out" = "サインアウトしました"; @@ -817,7 +817,7 @@ "security_settings_blacklist_unverified_devices_description" = "全てのセッションを検証して、信頼できるものとしてマークしメッセージを送信します。"; "security_settings_blacklist_unverified_devices" = "信頼していないセッションにはメッセージを送信しない"; "security_settings_advanced" = "上級者向け"; -"security_settings_export_keys_manually" = "手動でキーをエクスポートする"; +"security_settings_export_keys_manually" = "手動でキーをエクスポート"; "security_settings_cryptography" = "暗号技術"; "security_settings_crosssigning_reset" = "クロス署名をリセット"; "security_settings_crosssigning_info_ok" = "クロス署名が有効です。"; @@ -837,16 +837,16 @@ // Security settings "security_settings_title" = "セキュリティー"; -"settings_show_NSFW_public_rooms" = "NSFWパブリックルームを表示する"; +"settings_show_NSFW_public_rooms" = "NSFWパブリックルームを表示"; "settings_identity_server_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり発見されるようにするには1つ連絡先を追加します。"; "settings_identity_server_no_is" = "IDサーバーが設定されていません"; "settings_identity_server_description" = "上記で設定したIDサーバーを使って、自分の知り合いを発見したり、発見されたりすることができます。"; -"settings_discovery_three_pid_details_enter_sms_code_action" = "SMSアクティベーションコードを入力する"; +"settings_discovery_three_pid_details_enter_sms_code_action" = "SMSアクティベーションコードを入力"; "settings_discovery_three_pid_details_cancel_email_validation_action" = "メールの検証をキャンセル"; "settings_discovery_three_pid_details_revoke_action" = "取り消し"; "settings_discovery_three_pid_details_share_action" = "共有"; -"settings_discovery_three_pid_details_title_email" = "メールアドレスを管理する"; -"settings_discovery_three_pid_details_title_phone_number" = "電話番号を管理する"; +"settings_discovery_three_pid_details_title_email" = "メールアドレスを管理"; +"settings_discovery_three_pid_details_title_phone_number" = "電話番号を管理"; "settings_discovery_three_pid_details_information_phone_number" = "他のユーザーがあなたを発見したり、ルームに招待する際に使用できる電話番号の設定を管理します。アカウントへ電話番号の追加や削除ができます。"; "settings_discovery_three_pid_details_information_email" = "他のユーザーがあなたを発見したり、ルームに招待する際に使用できるメールアドレスの設定を管理します。アカウントへメールアドレスの追加や削除ができます。"; "settings_discovery_error_message" = "エラーが発生しました。再試行してください。"; @@ -856,10 +856,10 @@ "settings_discovery_terms_not_signed" = "メールアドレスや電話番号で自分を発見できるようにするには、IDサーバー(%@)の利用規約に同意する必要があります。"; "settings_discovery_no_identity_server" = "現在、IDサーバーを使用していません。知り合いがあなたを発見できるようにするには、IDサーバーを追加してください。"; "settings_key_backup_delete_confirmation_prompt_msg" = "よろしいですか?鍵が適切にバックアップされていないと、暗号化されたメッセージを失うことがあります。"; -"settings_key_backup_button_connect" = "このセッションをキーバックアップに接続する"; +"settings_key_backup_button_connect" = "このセッションをキーバックアップに接続"; "settings_key_backup_button_delete" = "バックアップの消去"; "settings_key_backup_button_restore" = "バックアップからの復旧"; -"settings_key_backup_button_create" = "キーバックアップをする"; +"settings_key_backup_button_create" = "キーバックアップの使用を開始"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "バックアップには%@からの無効な署名があります"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "バックアップには%@からの無効な署名があります"; "settings_key_backup_info_trust_signature_valid_device_unverified" = "バックアップには%@からの署名があります"; @@ -869,14 +869,14 @@ "settings_key_backup_info_progress_done" = "キーのバックアップが完了しました"; "settings_key_backup_info_progress" = "%@のキーをバックアップしています…"; "settings_key_backup_info_not_valid" = "このセッションではキーをバックアップしていませんが、復元して今後追加できる既存のバックアップがあります。"; -"settings_key_backup_info_signout_warning" = "このデバイスにのみ存在するキーの消失を防ぐために、サインアウトする前にこのセッションをキーバックアップに接続してください。"; +"settings_key_backup_info_signout_warning" = "この端末にのみ存在するキーの消失を防ぐために、サインアウトする前にこのセッションをキーバックアップに接続してください。"; "settings_key_backup_info" = "暗号化されたメッセージはエンドツーエンドで暗号化されています。送信者と受信者だけがこのメッセージを読むための鍵を持っています。"; -"settings_labs_message_reaction" = "絵文字でメッセージに反応する"; +"settings_labs_message_reaction" = "絵文字でメッセージに反応"; "settings_calls_stun_server_fallback_description" = "ホームサーバーがフォールバックコールアシストサーバーを提供していない場合は%@を許可します(IPアドレスは通話中に共有されます)。"; "settings_security" = "セキュリティー"; "settings_three_pids_management_information_part3" = ""; "settings_three_pids_management_information_part2" = "ディスカバリー"; -"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使うかを、ご自身で決めることができます。\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全てのデバイスとウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; +"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使うかを、ご自身で決めることができます。\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全ての端末とウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; "user_verification_session_details_additional_information_untrusted_other_user" = "ユーザーがこのセッションを信頼するまでは、セッションとの間で送受信されるメッセージには警告が表示されます。また、手動で検証することもできます。"; "user_verification_session_details_information_untrusted_other_user" = " 新しいセッションを使ってサインインしました:"; "user_verification_session_details_information_untrusted_current_user" = "このセッションを検証することで、信頼できるものとしてマークし、暗号化されたメッセージへのアクセスを許可します。"; @@ -900,20 +900,20 @@ "user_verification_sessions_list_user_trust_level_trusted_title" = "信頼済み"; "user_verification_start_additional_information" = "安心してご利用いただくために、直接お会いするか、別の方法でご連絡ください。"; "user_verification_start_waiting_partner" = "%@を待っています…"; -"user_verification_start_information_part2" = " 両方のデバイスでワンタイムコードを確認します。"; +"user_verification_start_information_part2" = " 両方の端末でワンタイムコードを確認します。"; "user_verification_start_information_part1" = "セキュリティーを高めるために "; // MARK: - User verification // Start -"user_verification_start_verify_action" = "検証を開始する"; -"key_verification_scan_confirmation_scanned_device_information" = "もう一方のデバイスにも同じシールドが表示されていますか?"; +"user_verification_start_verify_action" = "検証を開始"; +"key_verification_scan_confirmation_scanned_device_information" = "もう一方の端末にも同じシールドが表示されていますか?"; "key_verification_scan_confirmation_scanned_user_information" = "%@は同じシールドを表示していますか?"; // Scanned "key_verification_scan_confirmation_scanned_title" = "まもなくです!"; -"key_verification_scan_confirmation_scanning_device_waiting_other" = "他のデバイスを待っています…"; +"key_verification_scan_confirmation_scanning_device_waiting_other" = "他の端末を待っています…"; // MARK: Scan confirmation @@ -932,7 +932,7 @@ // MARK: QR code -"key_verification_verify_qr_code_title" = "スキャンして確認する"; +"key_verification_verify_qr_code_title" = "スキャンして確認"; // Incoming key verification request @@ -1064,7 +1064,7 @@ "settings_group_messages" = "グループメッセージ"; "settings_encrypted_direct_messages" = "暗号化されたダイレクトメッセージ"; "settings_direct_messages" = "ダイレクトメッセージ"; -"settings_notify_me_for" = "以下がメッセージ含まれる場合通知します"; +"settings_notify_me_for" = "以下がメッセージに含まれる場合に通知"; "settings_phone_contacts" = "端末の連絡先"; "settings_notifications" = "通知"; "settings_links" = "リンク"; @@ -1081,7 +1081,7 @@ "location_sharing_open_google_maps" = "Googleマップで開く"; "location_sharing_settings_toggle_title" = "ロケーションの共有を有効にする"; "threads_empty_show_all_threads" = "全てのスレッドを表示"; -"room_join_group_call" = "参加する"; +"room_join_group_call" = "参加"; "room_accessibility_threads" = "スレッド"; "threads_action_my_threads" = "自分のスレッド"; "threads_action_all_threads" = "全てのスレッド"; @@ -1096,7 +1096,7 @@ "settings_call_invitations" = "通話への招待"; "settings_room_invitations" = "ルームへの招待"; "key_backup_setup_success_from_recovery_key_made_copy_action" = "コピーしました"; -"key_backup_setup_success_from_recovery_key_make_copy_action" = "コピーする"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "コピー"; "key_backup_setup_success_from_recovery_key_recovery_key_title" = "セキュリティーキー"; // Success from recovery key From 1e3caf076790baee65373cd6268b2a311d0f5af6 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 20:26:36 +0000 Subject: [PATCH 154/188] Translated using Weblate (Japanese) Currently translated at 84.3% (373 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index caae6a410..b6f1988a4 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -122,7 +122,7 @@ "device_details_title" = "セッション情報\n"; "device_details_name" = "名前\n"; "device_details_identifier" = "ID\n"; -"device_details_last_seen" = "ラストシーン\n"; +"device_details_last_seen" = "最終接続日\n"; "device_details_last_seen_format" = "%@ @ %@\n"; "device_details_rename_prompt_message" = "端末名:"; "device_details_delete_prompt_title" = "認証"; @@ -178,7 +178,7 @@ "room_creation_alias_placeholder" = "(例 #foo:example.org)"; "room_creation_alias_placeholder_with_homeserver" = "(例 #foo%@)"; "room_creation_participants_title" = "参加者:"; -"room_creation_participants_placeholder" = "(例 @bob:homeserver1; @john:homeserver2...)"; +"room_creation_participants_placeholder" = "(例 @bob:homeserver1; @john:homeserver2…)"; // Room "room_please_select" = "ルームを選択してください"; "room_error_join_failed_title" = "ルームに参加できませんでした"; @@ -211,7 +211,7 @@ "attachment_multiselection_size_prompt" = "画像を次のように送信しますか:"; "attachment_multiselection_original" = "実際のサイズ"; "attachment_e2e_keys_file_prompt" = "このファイルには、Matrixクライアントからエクスポートされた暗号化キーが含まれています。\nファイルの内容を表示するか、ファイルの内容をインポートしますか?"; -"attachment_e2e_keys_import" = "インポート..."; +"attachment_e2e_keys_import" = "インポート…"; // Contacts "contact_mx_users" = "Matrixユーザー"; "contact_local_contacts" = "ローカルの連絡先"; @@ -350,7 +350,7 @@ "notification_settings_people_join_leave_rooms" = "誰かがルームに参加もしくは退出したときに通知"; "notification_settings_receive_a_call" = "通話を受信したときに通知"; "notification_settings_suppress_from_bots" = "ボットからの通知を抑制"; -"notification_settings_by_default" = "既定値では..."; +"notification_settings_by_default" = "既定値では…"; "notification_settings_notify_all_other" = "他の全てのメッセージ/ルームについて通知"; // gcm section "settings_config_home_server" = "ホームサーバー: %@"; @@ -358,7 +358,7 @@ "settings_config_user_id" = "ユーザーID: %@"; // call string "call_waiting" = "待機中..."; -"call_connecting" = "通話接続中..."; +"call_connecting" = "通話接続中…"; "call_ended" = "通話終了"; "call_ring" = "呼び出し中..."; "incoming_video_call" = "着信ビデオ通話"; @@ -407,4 +407,4 @@ "notice_encryption_enabled_ok_by_you" = "あなたはエンドツーエンド暗号化をオンにしました。"; "notice_encryption_enabled_unknown_algorithm_by_you" = "あなたはエンドツーエンド暗号化をオンにしました (不明なアルゴリズム %2$@)。"; "notice_redaction_by_you" = "イベントを編集しました (id: %@)"; -"auth_username_in_use" = "ユーザ名は既に使用されています"; +"auth_username_in_use" = "ユーザー名は既に使用されています"; From 8ec58ed0914fdb1d916d43f15170c30dc701884b Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Fri, 18 Feb 2022 13:55:54 +0000 Subject: [PATCH 155/188] Translated using Weblate (Japanese) Currently translated at 67.3% (33 of 49 strings) Translation: Element iOS/Element iOS (Push) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-push/ja/ --- Riot/Assets/ja.lproj/Localizable.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/Localizable.strings b/Riot/Assets/ja.lproj/Localizable.strings index 290e9103c..b47601f88 100644 --- a/Riot/Assets/ja.lproj/Localizable.strings +++ b/Riot/Assets/ja.lproj/Localizable.strings @@ -53,7 +53,7 @@ /** Key verification **/ -"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@は検証したい"; +"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@は検証を求めています"; /* New message indicator on a room */ "MESSAGE_IN_X" = "%@ 内のメッセージ"; From 1702694c02c4ba6cfad6925656d04851c997c1c1 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Sat, 19 Feb 2022 08:59:35 +0000 Subject: [PATCH 156/188] Translated using Weblate (Japanese) Currently translated at 66.9% (959 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index febf0e49d..a336f05fb 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -209,13 +209,13 @@ "room_prompt_cancel" = "全て中止"; "room_resend_unsent_messages" = "未送信の文を再送信"; "room_delete_unsent_messages" = "未送信の文を削除"; -"room_event_action_copy" = "複写"; +"room_event_action_copy" = "コピー"; "room_event_action_quote" = "引用"; "room_event_action_redact" = "移動して削除"; "room_event_action_more" = "さらに"; "room_event_action_share" = "共有"; -"room_event_action_permalink" = "直リンク"; -"room_event_action_view_source" = "ソースコードを表示"; +"room_event_action_permalink" = "メッセージへのリンクをコピー"; +"room_event_action_view_source" = "ソースを表示"; "room_event_action_report" = "発言を報告"; "room_event_action_report_prompt_reason" = "この発言を報告する理由"; "room_event_action_report_prompt_ignore_user" = "このユーザからの全ての発言を非表示にしますか?"; @@ -876,7 +876,7 @@ "settings_security" = "セキュリティー"; "settings_three_pids_management_information_part3" = ""; "settings_three_pids_management_information_part2" = "ディスカバリー"; -"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使うかを、ご自身で決めることができます。\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全ての端末とウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; +"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使用するかを、ご自身で決めることができます。\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全ての端末とウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; "user_verification_session_details_additional_information_untrusted_other_user" = "ユーザーがこのセッションを信頼するまでは、セッションとの間で送受信されるメッセージには警告が表示されます。また、手動で検証することもできます。"; "user_verification_session_details_information_untrusted_other_user" = " 新しいセッションを使ってサインインしました:"; "user_verification_session_details_information_untrusted_current_user" = "このセッションを検証することで、信頼できるものとしてマークし、暗号化されたメッセージへのアクセスを許可します。"; @@ -1114,3 +1114,5 @@ "secrets_setup_recovery_key_done_action" = "完了"; "secrets_setup_recovery_passphrase_validate_action" = "完了"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "バックアップ"; +"room_event_action_forward" = "転送"; +"room_event_action_view_in_room" = "ルームに表示"; From b6313a4fd18229636da1731198fc15605e2803e2 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Sat, 19 Feb 2022 21:46:31 +0000 Subject: [PATCH 157/188] Translated using Weblate (Japanese) Currently translated at 84.6% (374 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index b6f1988a4..1fa78d1a5 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -63,7 +63,7 @@ "select_account" = "アカウントを選択"; "attach_media" = "ライブラリからメディアを添付"; "capture_media" = "写真/ビデオを撮る"; -"invite_user" = "matrixユーザーを招待"; +"invite_user" = "Matrixユーザーを招待"; "reset_to_default" = "デフォルトにリセット"; "cancel_upload" = "アップロードをキャンセル"; "cancel_download" = "ダウンロードをキャンセル"; @@ -100,7 +100,7 @@ "notice_error_unsupported_event" = "サポートされていないイベント"; "notice_error_unexpected_event" = "予期しないイベント"; "notice_error_unknown_event_type" = "不明なイベントタイプ"; -"notice_room_history_visible_to_anyone" = "%@ 誰でも将来のルーム履歴を表示されます。"; +"notice_room_history_visible_to_anyone" = "%@は、今後のルーム履歴を誰でも見えるように設定しました。"; "notice_room_history_visible_to_members" = "%@ ルームメンバー全員に将来のルーム履歴を表示されます。"; "notice_room_history_visible_to_members_from_invited_point" = "%@ ルームメンバー全員に招待した時点からのルーム履歴を表示されます。"; "notice_room_history_visible_to_members_from_joined_point" = "%@ ルームメンバー全員に参加した時点からのルーム履歴を表示されます。"; @@ -124,7 +124,7 @@ "device_details_identifier" = "ID\n"; "device_details_last_seen" = "最終接続日\n"; "device_details_last_seen_format" = "%@ @ %@\n"; -"device_details_rename_prompt_message" = "端末名:"; +"device_details_rename_prompt_message" = "セッションの公開名は、あなたとやり取りする人々に対して表示されます"; "device_details_delete_prompt_title" = "認証"; "device_details_delete_prompt_message" = "この操作には、追加の認証が必要です。\n続行するには、パスワードを入力してください。"; // Encryption information @@ -144,7 +144,7 @@ "room_event_encryption_info_device_id" = "ID\n"; "room_event_encryption_info_device_verification" = "検証\n"; "room_event_encryption_info_device_fingerprint" = "Ed25519 fingerprint\n"; -"room_event_encryption_info_device_verified" = "検証済み"; +"room_event_encryption_info_device_verified" = "検証済"; "room_event_encryption_info_device_not_verified" = "検証されていない"; "room_event_encryption_info_device_blocked" = "ブラックリストに載せた"; "room_event_encryption_info_verify" = "検証しています…"; @@ -247,7 +247,7 @@ "error_common_message" = "エラーが発生しました。 後でもう一度お試しください。"; "not_supported_yet" = "まだサポートされていません"; "default" = "既定"; -"private" = "プライベート"; +"private" = "非公開"; "public" = "公開"; "power_level" = "権限レベル"; "network_error_not_reachable" = "ネットワーク接続を確認してください"; @@ -317,7 +317,7 @@ "unban" = "ブロック解除"; "message_unsaved_changes" = "保存されていない変更があります。 退出すると変更は取り消されます。"; // Login Screen -"login_error_already_logged_in" = "ログイン済み"; +"login_error_already_logged_in" = "ログイン済"; "login_error_must_start_http" = "URLは http[s]:// で始まる必要があります"; // room details dialog screen "room_details_title" = "ルームの詳細"; @@ -408,3 +408,4 @@ "notice_encryption_enabled_unknown_algorithm_by_you" = "あなたはエンドツーエンド暗号化をオンにしました (不明なアルゴリズム %2$@)。"; "notice_redaction_by_you" = "イベントを編集しました (id: %@)"; "auth_username_in_use" = "ユーザー名は既に使用されています"; +"resume_call" = "再開"; From 66a64859d5dac38f5a6ec52370350c3f64d8529d Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Sun, 20 Feb 2022 15:25:47 +0000 Subject: [PATCH 158/188] Translated using Weblate (Japanese) Currently translated at 67.4% (967 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 470 ++++++++++++++-------------- 1 file changed, 239 insertions(+), 231 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index a336f05fb..c8c225d9c 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -27,11 +27,11 @@ "voice" = "音声"; "video" = "映像"; "active_call" = "通話開始"; -"active_call_details" = "通話開始 (%@)"; +"active_call_details" = "通話開始(%@)"; "later" = "後で"; "rename" = "名前変更"; "collapse" = "たたむ"; -"send_to" = "%@ さんへ送信"; +"send_to" = "%@さんへ送信"; "sending" = "送信中"; // Authentication "auth_login" = "ログイン"; @@ -40,69 +40,69 @@ "auth_skip" = "省く"; "auth_send_reset_email" = "初期化メール送信"; "auth_return_to_login" = "ログイン画面へ戻る"; -"auth_user_id_placeholder" = "ユーザ名または電子メール"; +"auth_user_id_placeholder" = "ユーザー名または電子メール"; "auth_password_placeholder" = "パスワード"; "auth_new_password_placeholder" = "新しいパスワード"; -"auth_user_name_placeholder" = "ユーザ名"; -"auth_optional_email_placeholder" = "電子メールアドレス (任意で)"; -"auth_email_placeholder" = "電子メールアドレス"; -"auth_optional_phone_placeholder" = "電話番号 (任意で)"; +"auth_user_name_placeholder" = "ユーザー名"; +"auth_optional_email_placeholder" = "メールアドレス(任意)"; +"auth_email_placeholder" = "メールアドレス"; +"auth_optional_phone_placeholder" = "電話番号(任意)"; "auth_phone_placeholder" = "電話番号"; "auth_repeat_password_placeholder" = "パスワード再確認"; "auth_repeat_new_password_placeholder" = "新しいパスワードを再確認"; "auth_home_server_placeholder" = "URL (例 https://matrix.org)"; "auth_identity_server_placeholder" = "URL (例 https://vector.im)"; -"auth_invalid_login_param" = "ユーザ名かパスワードが正しくありません"; -"auth_invalid_user_name" = "ユーザ名は半角英数字、ドット、ハイフン、アンダスコアのみで記して下さい"; +"auth_invalid_login_param" = "ユーザー名かパスワードが正しくありません"; +"auth_invalid_user_name" = "ユーザー名は半角英数字、ドット、ハイフン、アンダスコアのみで記して下さい"; "auth_invalid_password" = "パスワードが短すぎます(最小6文字)"; -"auth_invalid_email" = "正しくない電子メールアドレスのようです"; +"auth_invalid_email" = "正しくないメールアドレスのようです"; "auth_invalid_phone" = "正しくない電話番号のようです"; -"auth_missing_password" = "パスワードが違います"; +"auth_missing_password" = "パスワードが入力されていません"; "auth_add_email_message" = "電子メールアドレスを登録すると, 誰かがあなたを検索をしたり, パスワード紛失時に初期化のメールを送ることができます."; "auth_add_phone_message" = "電話番号を登録すると, 誰かがあなたを電話番号で検索できるようになります."; "auth_add_email_phone_message" = "電子メールアドレスや電話番号を登録すると, それらを使用して誰かがあなたを検索できるようになります. 電子メールアドレスは, パスワード紛失時に初期化の連絡をするためにも使用されます."; "auth_add_email_and_phone_message" = "電子メールアドレスや電話番号を登録すると, それらを使用して誰かがあなたを検索できるようになります. 電子メールアドレスは, パスワード紛失時に初期化の連絡をするためにも使用されます."; -"auth_missing_email" = "電子メールアドレスが違います"; -"auth_missing_phone" = "電話番号が違います"; -"auth_missing_email_or_phone" = "電子メールアドレスまたは電話番号が違います"; -"auth_email_in_use" = "この電子メールアドレスは既に使われています"; +"auth_missing_email" = "メールアドレスが入力されていません"; +"auth_missing_phone" = "電話番号が入力されていません"; +"auth_missing_email_or_phone" = "メールアドレスまたは電話番号が入力されていません"; +"auth_email_in_use" = "このメールアドレスは既に使われています"; "auth_phone_in_use" = "この電話番号は既に使用されています"; -"auth_untrusted_id_server" = "この認証サーバは信用されていません"; +"auth_untrusted_id_server" = "この認証サーバーは信用されていません"; "auth_password_dont_match" = "パスワードが一致しません"; -"auth_username_in_use" = "ユーザ名は既に使用されています"; +"auth_username_in_use" = "ユーザー名は既に使用されています"; "auth_forgot_password" = "パスワードを忘れましたか?"; -"auth_email_not_found" = "電子メールの送信に失敗しました: メールアドレスが見つかりません"; -"auth_use_server_options" = "接続先サーバを指定する(追加設定)"; +"auth_email_not_found" = "電子メールの送信に失敗しました:メールアドレスが見つかりません"; +"auth_use_server_options" = "接続先サーバーを指定する(追加設定)"; "auth_email_validation_message" = "登録を続行するには電子メールを確認して下さい"; "auth_msisdn_validation_title" = "認証を確認中"; -"auth_msisdn_validation_message" = "SMSで認証番号を送りました. 以下にその番号を入力してください."; +"auth_msisdn_validation_message" = "SMSで認証番号を送りました。以下にその番号を入力してください。"; "auth_msisdn_validation_error" = "電話番号を認証できません。"; -"auth_recaptcha_message" = "接続先サーバ側が、機械による自動登録ではなく、あなたが人間であることを確認したいとのことです"; -"auth_reset_password_message" = "パスワードを初期化するには, アカウントに登録されている電子メールアドレスを入力してください:"; -"auth_reset_password_missing_email" = "あなたのアカウントに登録された電子メールアドレスの入力が必要です."; -"auth_reset_password_missing_password" = "新しいパスワードの入力が必要です."; -"auth_reset_password_email_validation_message" = "%@ へ電子メールが送信されました. リンクをたどったら以下をクリックしてください."; +"auth_recaptcha_message" = "接続先サーバー側が、機械による自動登録ではなく、あなたが人間であることを確認したいとのことです"; +"auth_reset_password_message" = "パスワードを初期化するには、アカウントに登録されているメールアドレスを入力してください:"; +"auth_reset_password_missing_email" = "あなたのアカウントに登録されたメールアドレスの入力が必要です。"; +"auth_reset_password_missing_password" = "新しいパスワードの入力が必要です。"; +"auth_reset_password_email_validation_message" = "%@ へ電子メールが送信されました。リンクをたどったら以下をクリックしてください。"; "auth_reset_password_next_step_button" = "メールアドレスを認証しました"; -"auth_reset_password_error_unauthorized" = "電子メールアドレスの確認に失敗しました: 電子メールのリンクをクリックしたことを確認してください"; -"auth_reset_password_error_not_found" = "あなたの電子メールアドレスは、接続先サーバ上のMatrix IDと関連付けられていないようです。"; -"auth_reset_password_success_message" = "あなたのパスワードは初期化されました.\n\nあなたは全てのセッションから切断しており、プッシュ通知を受け取ることはありません。通知を再度有効にするには、各端末に再度ログインします。"; -"auth_add_email_and_phone_warning" = "電子メールと電話番号の同時登録は, まだシステムが対応できません. 電話番号だけの登録は可能です. お手数おかけしますが, 後ほど個人情報設定から電子メールアドレスを登録してください."; +"auth_reset_password_error_unauthorized" = "メールアドレスの確認に失敗しました:電子メールのリンクをクリックしたことを確認してください"; +"auth_reset_password_error_not_found" = "あなたのメールアドレスは、接続先サーバー上のMatrix IDと関連付けられていないようです。"; +"auth_reset_password_success_message" = "あなたのパスワードは初期化されました。\n\nあなたは全てのセッションから切断しており、プッシュ通知を受け取ることはありません。通知を再度有効にするには、各端末に再度ログインします。"; +"auth_add_email_and_phone_warning" = "電子メールと電話番号の同時登録は、まだシステムが対応できません。電話番号だけの登録は可能です。お手数おかけしますが、後ほど個人情報設定からメールアドレスを登録してください。"; // Chat creation "room_creation_title" = "新しい対話"; "room_creation_account" = "アカウント"; "room_creation_appearance" = "外観"; "room_creation_appearance_name" = "名前"; -"room_creation_appearance_picture" = "チャット画像 (任意)"; +"room_creation_appearance_picture" = "チャット画像(任意)"; "room_creation_privacy" = "個人情報保護"; "room_creation_private_room" = "この会話は非公開です"; "room_creation_public_room" = "この会話は公開されます"; "room_creation_make_public" = "公開"; "room_creation_make_public_prompt_title" = "このチャットを公開しますか?"; -"room_creation_make_public_prompt_msg" = "このチャットを公開してもよろしいですか? 誰でもあなたのメッセージを読んでチャットに参加できます。"; +"room_creation_make_public_prompt_msg" = "このチャットを公開してもよろしいですか?誰でもあなたのメッセージを読んでチャットに参加できます。"; "room_creation_keep_private" = "非公開に保つ"; "room_creation_make_private" = "非公開にする"; -"room_creation_wait_for_creation" = "ルームは既に作成されています。 お待ちください。"; -"room_creation_invite_another_user" = "ユーザID, 表示名, 電子メールで検索と招待"; +"room_creation_wait_for_creation" = "ルームは既に作成されています。お待ちください。"; +"room_creation_invite_another_user" = "ユーザーID、表示名、電子メールで検索と招待"; // Room recents "room_recents_directory_section" = "ルーム一覧"; "room_recents_favourites_section" = "お気に入り"; @@ -121,22 +121,22 @@ "people_conversation_section" = "会話"; "people_no_conversation" = "会話なし"; // Rooms tab -"room_directory_no_public_room" = "利用可能なパブリックのルームはありません"; +"room_directory_no_public_room" = "利用可能な公開ルームはありません"; // Search "search_rooms" = "ルーム"; -"search_messages" = "発言"; +"search_messages" = "メッセージ"; "search_people" = "対話"; "search_files" = "添付ファイル"; "search_default_placeholder" = "検索"; -"search_people_placeholder" = "ユーザID, 表示名, 電子メールで検索"; +"search_people_placeholder" = "ユーザーID、表示名、電子メールで検索"; "search_no_result" = "結果なし"; "search_in_progress" = "検索しています…"; // Directory "directory_cell_title" = "ルーム一覧を見る"; "directory_cell_description" = "%tu ルーム"; "directory_search_results_title" = "ルーム一覧検索結果"; -"directory_search_results" = "%tu 件の検索結果 for %@"; -"directory_search_results_more_than" = ">%tu 件の検索結果 for %@"; +"directory_search_results" = "%@の検索結果%tu件"; +"directory_search_results_more_than" = ">%@の検索結果%tu件"; "directory_searching_title" = "ルーム一覧を検索しています…"; "directory_search_fail" = "一覧を取得できませんでした"; // Contacts @@ -146,28 +146,28 @@ "contacts_address_book_permission_required" = "端末内電話帳へのアクセス権限が必要です"; "contacts_address_book_permission_denied" = "端末の電話帳をElementアプリが読み取ることは許可されていません"; "contacts_user_directory_section" = "利用者一覧"; -"contacts_user_directory_offline_section" = "利用者一覧 (切断中)"; +"contacts_user_directory_offline_section" = "利用者一覧(オフライン)"; // Chat participants "room_participants_title" = "参加者"; "room_participants_add_participant" = "参加者を追加"; -"room_participants_one_participant" = "参加者 1名"; -"room_participants_multi_participants" = "参加者 %d名"; +"room_participants_one_participant" = "参加者1名"; +"room_participants_multi_participants" = "参加者%d名"; "room_participants_leave_prompt_title" = "ルームを退出"; "room_participants_leave_prompt_msg" = "ルームを退出してよろしいですか?"; "room_participants_remove_prompt_title" = "確認"; -"room_participants_remove_prompt_msg" = "本当に %@ さんをチャットから退去させますか?"; +"room_participants_remove_prompt_msg" = "本当に%@をチャットから退去させますか?"; "room_participants_remove_third_party_invite_msg" = "サードパーティの招待を削除することは、APIが存在するまでサポートされていません"; "room_participants_invite_prompt_title" = "確認"; -"room_participants_invite_prompt_msg" = "本当に %@ さんをチャットへ招待しますか?"; -"room_participants_filter_room_members" = "参加者を検索"; -"room_participants_invite_another_user" = "ユーザID, 表示名, 電子メールで検索と招待"; +"room_participants_invite_prompt_msg" = "%@をチャットに招待してよろしいですか?"; +"room_participants_filter_room_members" = "ルームのメンバーを絞り込む"; +"room_participants_invite_another_user" = "ユーザーID、名前、電子メールで検索、招待"; "room_participants_invite_malformed_id_title" = "招待エラー"; -"room_participants_invite_malformed_id" = "不正なIDです。電子メールアドレスを用いるか、'@localpart:domain' のような Matrix IDを使用してください"; +"room_participants_invite_malformed_id" = "不正なIDです。メールアドレスを用いるか、'@localpart:domain'のようなMatrix IDを使用してください"; "room_participants_invited_section" = "招待中"; -"room_participants_online" = "接続中"; -"room_participants_offline" = "切断中"; -"room_participants_unknown" = "状態不明"; -"room_participants_idle" = "待機中"; +"room_participants_online" = "オンライン"; +"room_participants_offline" = "オフライン"; +"room_participants_unknown" = "不明"; +"room_participants_idle" = "アイドル"; "room_participants_now" = "現在"; "room_participants_ago" = "前"; "room_participants_action_section_admin_tools" = "管理者権限操作"; @@ -178,31 +178,31 @@ "room_participants_action_leave" = "このルームを出る"; "room_participants_action_remove" = "このルームから削除"; "room_participants_action_ban" = "このルームからブロック"; -"room_participants_action_unban" = "ブロック解除"; -"room_participants_action_ignore" = "この参加者の発言を全て非表示にする"; -"room_participants_action_unignore" = "この参加者の発言を全て表示"; -"room_participants_action_set_default_power_level" = "権限を一般参加者へ変更"; -"room_participants_action_set_moderator" = "権限を司会者へ変更"; +"room_participants_action_unban" = "ブロックを解除"; +"room_participants_action_ignore" = "このユーザーの発言を全て非表示にする"; +"room_participants_action_unignore" = "このユーザーの発言を全て表示"; +"room_participants_action_set_default_power_level" = "権限を一般ユーザーへ変更"; +"room_participants_action_set_moderator" = "権限をモデレーターへ変更"; "room_participants_action_set_admin" = "権限を管理者へ変更"; "room_participants_action_start_new_chat" = "対話を開始"; "room_participants_action_start_voice_call" = "音声通話を開始"; "room_participants_action_start_video_call" = "映像付き音声通話を開始"; -"room_participants_action_mention" = "指名して呼掛け"; +"room_participants_action_mention" = "メンション"; // Chat "room_jump_to_first_unread" = "最初の未読位置へ移動"; -"room_new_message_notification" = "%d 新しい発言"; -"room_new_messages_notification" = "%d 新しい発言"; -"room_one_user_is_typing" = "%@ さんが文字入力中…"; -"room_two_users_are_typing" = "%@ さん、 %@ さんが文字入力中…"; -"room_many_users_are_typing" = "%@ さん、 %@ さん他が文字入力中…"; -"room_message_placeholder" = "ここに送信文を入力 (暗号なし)…"; +"room_new_message_notification" = "%d件の新しい発言"; +"room_new_messages_notification" = "%d件の新しい発言"; +"room_one_user_is_typing" = "%@さんが入力しています…"; +"room_two_users_are_typing" = "%@さん、%@さんが入力しています…"; +"room_many_users_are_typing" = "%@さん、%@さん他が入力しています…"; +"room_message_placeholder" = "返信を送る(未暗号化)…"; "encrypted_room_message_placeholder" = "暗号文を送信…"; "room_message_short_placeholder" = "ここに送信文を入力…"; -"room_offline_notification" = "サーバとの接続が失われました."; -"room_unsent_messages_notification" = "文章が送信できませんでした."; -"room_unsent_messages_unknown_devices_notification" = "未知のセッションが存在するために文章が送信されませんでした."; -"room_ongoing_conference_call" = "会議通話実施中。 %@ または %@で参加してください。"; -"room_ongoing_conference_call_with_close" = "会議通話実施中。%@または%@で参加してください。 %@。"; +"room_offline_notification" = "サーバーとの接続が失われました。"; +"room_unsent_messages_notification" = "メッセージを送信できませんでした。"; +"room_unsent_messages_unknown_devices_notification" = "未知のセッションが存在するために文章が送信されませんでした。"; +"room_ongoing_conference_call" = "会議通話実施中。%@または%@で参加してください。"; +"room_ongoing_conference_call_with_close" = "会議通話実施中。%@または%@で参加してください。%@。"; "room_ongoing_conference_call_close" = "閉じる"; "room_conference_call_no_power" = "このルームで会議通話を管理する権限が必要です"; "room_prompt_resend" = "全て再送信"; @@ -218,18 +218,18 @@ "room_event_action_view_source" = "ソースを表示"; "room_event_action_report" = "発言を報告"; "room_event_action_report_prompt_reason" = "この発言を報告する理由"; -"room_event_action_report_prompt_ignore_user" = "このユーザからの全ての発言を非表示にしますか?"; +"room_event_action_report_prompt_ignore_user" = "このユーザーからの全ての発言を非表示にしますか?"; "room_event_action_save" = "保存"; "room_event_action_resend" = "再送信"; "room_event_action_delete" = "削除"; "room_event_action_cancel_send" = "送信中止"; "room_event_action_cancel_download" = "ダウンロード中止"; "room_event_action_view_encryption" = "暗号についての情報"; -"room_warning_about_encryption" = "End-to-end 暗号化はベータ版であり、信頼性が低い場合があります。\n\n発言を保護するためにはまだ信用すべきではありません。\n\n端末が参加するより前の発言履歴を復号化することはまだできません。\n\n暗号化された発言は、まだ暗号化を実装していないクライアントでは表示されません。"; +"room_warning_about_encryption" = "エンドツーエンド暗号化はベータ版であり、信頼性が低い場合があります。\n\n発言を保護するためにはまだ信用すべきではありません。\n\n端末が参加するより前の発言履歴を復号化することはまだできません。\n\n暗号化された発言は、まだ暗号化を実装していないクライアントでは表示されません。"; "room_event_failed_to_send" = "送信失敗"; // Unknown devices "unknown_devices_alert_title" = "ルームに未知のセッションが存在します"; -"unknown_devices_alert" = "このルームには、確認されていない未知のセッションが含まれています。\nすなわち、セッションがをユーザ本人が所有しているという保証はありません。\n続ける前に各セッションの確認を行うことをおすすめしますが、確認することなく発言を再送信することができます。"; +"unknown_devices_alert" = "このルームには、確認されていない未知のセッションが含まれています。\nすなわち、セッションがをユーザー本人が所有しているという保証はありません。\n続ける前に各セッションの確認を行うことをおすすめしますが、確認することなく発言を再送信することができます。"; "unknown_devices_send_anyway" = "とにかく送る"; "unknown_devices_call_anyway" = "とにかく通話"; "unknown_devices_answer_anyway" = "とにかく応答"; @@ -237,26 +237,26 @@ "unknown_devices_title" = "未知のセッション"; // Room Title "room_title_new_room" = "新しいルーム"; -"room_title_multiple_active_members" = "全%@人中 %@人が回線接続"; -"room_title_one_active_member" = "全%@人中 %@人が回線接続"; +"room_title_multiple_active_members" = "全%@人中%@人が回線接続"; +"room_title_one_active_member" = "全%@人中%@人が回線接続"; "room_title_invite_members" = "招待中"; -"room_title_members" = "%@名の参加者"; -"room_title_one_member" = "1名の参加者"; +"room_title_members" = "%@名のメンバー"; +"room_title_one_member" = "1名のメンバー"; // Room Preview -"room_preview_invitation_format" = "あなたは %@ さんに呼ばれてこのルームへ参加しました"; +"room_preview_invitation_format" = "あなたは%@さんに呼ばれてこのルームへ参加しました"; "room_preview_subtitle" = "これはルームのプレビューです。ルームでのやり取りは無効化されています。"; -"room_preview_unlinked_email_warning" = "このアカウントに関連付けられていない %@ 宛に招待が送信されました。別のアカウントでログインするか、メールアドレスをこのアカウントに追加することができます。"; -"room_preview_try_join_an_unknown_room" = "あなたは %@ へ接続しようとしています。この会議に参加しますか?"; +"room_preview_unlinked_email_warning" = "このアカウントに関連付けられていない%@宛に招待が送信されました。別のアカウントでログインするか、メールアドレスをこのアカウントに追加することができます。"; +"room_preview_try_join_an_unknown_room" = "あなたは%@へ接続しようとしています。この会議に参加しますか?"; "room_preview_try_join_an_unknown_room_default" = "ルーム"; // Settings "settings_title" = "設定"; "account_logout_all" = "全てのアカウントを回線切断"; "settings_config_no_build_info" = "ビルド情報がありません"; "settings_mark_all_as_read" = "全ての発言を既読にする"; -"settings_report_bug" = "不具合報告"; -"settings_config_home_server" = "接続先サーバは %@"; +"settings_report_bug" = "バグレポート"; +"settings_config_home_server" = "接続先サーバーは %@"; "settings_config_identity_server" = "認証サーバは %@"; -"settings_config_user_id" = "%@ でログインしています"; +"settings_config_user_id" = "%@でログインしています"; "settings_user_settings" = "利用者設定"; "settings_notifications_settings" = "通知設定"; "settings_calls_settings" = "通話"; @@ -270,26 +270,26 @@ "settings_cryptography" = "暗号化"; "settings_sign_out" = "通信完全切断"; "settings_sign_out_confirmation" = "本当によろしいですか?"; -"settings_sign_out_e2e_warn" = "あなたはend-to-end暗号鍵を紛失してしまったようです。すなわち、この端末で暗号化されたルームの昔の発言を読むことができなくなります。"; +"settings_sign_out_e2e_warn" = "あなたはエンドツーエンド暗号鍵を失ってしまいます。この端末で暗号化されたルームの昔の発言を読むことができなくなります。"; "settings_profile_picture" = "自分のアイコン画像"; "settings_display_name" = "表示名"; "settings_first_name" = "名"; "settings_surname" = "姓"; "settings_remove_prompt_title" = "確認"; -"settings_remove_email_prompt_msg" = "電子メールアドレス %@ を本当に削除してよろしいですか?"; +"settings_remove_email_prompt_msg" = "メールアドレス %@ を本当に削除してよろしいですか?"; "settings_remove_phone_prompt_msg" = "電話番号 %@ を本当に削除してよろしいですか?"; "settings_email_address" = "電子メール"; -"settings_email_address_placeholder" = "あなたの電子メールアドレスを入力してください"; -"settings_add_email_address" = "電子メールアドレスを追加"; +"settings_email_address_placeholder" = "あなたのメールアドレスを入力してください"; +"settings_add_email_address" = "メールアドレスを追加"; "settings_phone_number" = "電話番号"; "settings_add_phone_number" = "電話番号を追加"; "settings_night_mode" = "夜間おやすみモード"; "settings_fail_to_update_profile" = "自己紹介設定の更新に失敗しました"; "settings_enable_push_notif" = "この端末での通知"; "settings_show_decrypted_content" = "復号化された文章を表示"; -"settings_global_settings_info" = "あなたの %@ webクライアント上で、全体の通知設定が可能です"; +"settings_global_settings_info" = "あなたの%@ webクライアント上で、全体の通知設定が可能です"; "settings_pin_rooms_with_missed_notif" = "逃した通知があるルームをピン止め"; -"settings_callkit_info" = "画面がロックされているときに着信がありました。Elementの着信はシステムの通話履歴で確認できます。 iCloudが有効になっている場合、この通話履歴はAppleと共有されます。"; +"settings_callkit_info" = "画面がロックされているときに着信がありました。Elementの着信はシステムの通話履歴で確認できます。iCloudが有効になっている場合、この通話履歴はAppleと共有されます。"; "settings_ui_language" = "言語"; "settings_ui_theme" = "外観"; "settings_ui_theme_auto" = "自動"; @@ -304,14 +304,14 @@ "settings_labs_e2e_encryption_prompt_message" = "暗号化の設定を完了するためには再度ログインしてください。"; "settings_labs_matrix_apps" = "Matrixアプリ"; "settings_labs_create_conference_with_jitsi" = "jitsiの会議通話を作成"; -"settings_version" = "Version %@"; -"settings_olm_version" = "Olm バージョン %@"; +"settings_version" = "バージョン %@"; +"settings_olm_version" = "Olmバージョン %@"; "settings_copyright" = "著作権"; "settings_term_conditions" = "利用規約"; "settings_privacy_policy" = "個人情報保護方針"; "settings_third_party_notices" = "外部ライブラリの規約"; "settings_send_crash_report" = "匿名利用状況と誤動作情報を送信"; -"settings_enable_rageshake" = "バグ報告のため端末を揺さぶる"; +"settings_enable_rageshake" = "バグレポートのため端末を振る"; "settings_clear_cache" = "一時保存を消去"; "settings_change_password" = "パスワード変更"; "settings_old_password" = "今までのパスワード"; @@ -322,11 +322,11 @@ "settings_crypto_device_name" = "セッション名: "; "settings_crypto_device_id" = "\nセッションID: "; "settings_crypto_device_key" = "\nセッションキー:\n"; -"settings_crypto_export" = "暗号鍵を外部へ保存"; +"settings_crypto_export" = "鍵をエクスポート"; "settings_crypto_blacklist_unverified_devices" = "検証されたセッションのみで暗号化"; // Room Details "room_details_title" = "ルームの詳細"; -"room_details_people" = "参加者"; +"room_details_people" = "メンバー"; "room_details_files" = "アップロード"; "room_details_settings" = "設定"; "room_details_photo" = "ルームの画像アイコン"; @@ -336,82 +336,82 @@ "room_details_low_priority_tag" = "低優先度"; "room_details_mute_notifs" = "発言があっても通知しない"; "room_details_direct_chat" = "対話"; -"room_details_access_section" = "誰をルームに入室可能としますか?"; -"room_details_access_section_invited_only" = "このルームに招待された人のみ参加可能"; -"room_details_access_section_anyone_apart_from_guest" = "誰でもルームに参加できる (ゲストユーザは不可)"; -"room_details_access_section_anyone" = "誰でもルームに参加できる (ゲストユーザも許可)"; -"room_details_access_section_no_address_warning" = "このルームへのリンクを作成するには、ルームの住所表記が必要です"; +"room_details_access_section" = "誰がルームにアクセスできますか?"; +"room_details_access_section_invited_only" = "招待された人のみ"; +"room_details_access_section_anyone_apart_from_guest" = "ルームのリンクを知っている人なら誰でも(ゲストユーザーを除く)"; +"room_details_access_section_anyone" = "ルームのリンクを知っている人なら誰でも(ゲストユーザーを含む)"; +"room_details_access_section_no_address_warning" = "このルームへのリンクを作成するには、ルームのアドレスが必要です"; "room_details_access_section_directory_toggle" = "ルーム一覧へ公開"; "room_details_history_section" = "誰をこのルームの発言履歴を読めるようにしますか?"; "room_details_history_section_anyone" = "誰でも"; -"room_details_history_section_members_only" = "参加者のみ (この設定を選択した時点から)"; -"room_details_history_section_members_only_since_invited" = "参加者のみ (招待を送った時点から)"; -"room_details_history_section_members_only_since_joined" = "参加者のみ (参加した時点から)"; +"room_details_history_section_members_only" = "メンバーのみ (この設定を選択した時点から)"; +"room_details_history_section_members_only_since_invited" = "メンバーのみ(招待を送った時点から)"; +"room_details_history_section_members_only_since_joined" = "メンバーのみ (参加した時点から)"; "room_details_history_section_prompt_title" = "個人情報の警告"; "room_details_history_section_prompt_msg" = "発言履歴を読むことができる人の変更は、以後の発言にのみ適用されます。既存の発言履歴の可視性は変更されません。"; -"room_details_addresses_section" = "住所表記"; -"room_details_no_local_addresses" = "このルームはサーバ内住所表記がありません"; -"room_details_new_address" = "新しい住所表記を追加"; +"room_details_addresses_section" = "アドレス"; +"room_details_no_local_addresses" = "このルームにはローカルアドレスがありません"; +"room_details_new_address" = "新しいアドレスを追加"; "room_details_new_address_placeholder" = "新しいアドレスを追加(例 #foo%@)"; -"room_details_addresses_invalid_address_prompt_title" = "住所表記が正しくありません"; -"room_details_addresses_invalid_address_prompt_msg" = "%@ は正しくない形式の住所表記です"; -"room_details_addresses_disable_main_address_prompt_title" = "代表住所表記の警告"; -"room_details_addresses_disable_main_address_prompt_msg" = "代表住所表記が設定されていません. このルームの代表住所表記は無作為に選択、設定されます"; +"room_details_addresses_invalid_address_prompt_title" = "不正なエイリアスのフォーマット"; +"room_details_addresses_invalid_address_prompt_msg" = "%@はエイリアスの正しいフォーマットではありません"; +"room_details_addresses_disable_main_address_prompt_title" = "メインアドレスの警告"; +"room_details_addresses_disable_main_address_prompt_msg" = "メインアドレスが設定されていません。このルームのメインアドレスは無作為に選択、設定されます"; "room_details_banned_users_section" = "ブロックされたユーザー"; "room_details_advanced_section" = "拡張設定"; "room_details_advanced_room_id" = "ルームの固有ID:"; -"room_details_advanced_enable_e2e_encryption" = "暗号化を開始(警告: ルームの暗号を中止することはできません!)"; +"room_details_advanced_enable_e2e_encryption" = "暗号化を有効にする(警告: 有効後にこれを無効にすることはできません!)"; "room_details_advanced_e2e_encryption_enabled" = "このルームの発言は暗号化されています"; "room_details_advanced_e2e_encryption_disabled" = "このルームの発言は暗号化されていません。"; "room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "検証されたセッションのみで暗号化"; -"room_details_fail_to_update_avatar" = "ルームのアイコン画像の更新に失敗しました"; -"room_details_fail_to_update_room_name" = "ルーム名の更新に失敗しました"; -"room_details_fail_to_update_topic" = "ルームの説明の更新に失敗しました"; -"room_details_fail_to_update_room_guest_access" = "ルームのゲスト参加者設定の更新に失敗しました"; -"room_details_fail_to_update_room_join_rule" = "入室規則の更新に失敗しました"; -"room_details_fail_to_update_room_directory_visibility" = "ルーム一覧の可視設定の更新に失敗しました"; -"room_details_fail_to_update_history_visibility" = "発言履歴の可視範囲の設定更新に失敗しました"; -"room_details_fail_to_add_room_aliases" = "ルーム住所の新規追加に失敗しました"; -"room_details_fail_to_remove_room_aliases" = "ルーム住所の削除に失敗しました"; -"room_details_fail_to_update_room_canonical_alias" = "代表ルーム住所の更新に失敗しました"; -"room_details_fail_to_update_room_direct" = "ルームの対話タグの変更に失敗しました"; -"room_details_fail_to_enable_encryption" = "ルームの暗号化の開始に失敗しました"; +"room_details_fail_to_update_avatar" = "ルームのアイコン画像の更新に失敗"; +"room_details_fail_to_update_room_name" = "ルーム名の更新に失敗"; +"room_details_fail_to_update_topic" = "ルームの説明の更新に失敗"; +"room_details_fail_to_update_room_guest_access" = "ゲストによるルームへのアクセスの設定更新に失敗"; +"room_details_fail_to_update_room_join_rule" = "参加ルールの更新に失敗"; +"room_details_fail_to_update_room_directory_visibility" = "ルーム一覧の可視設定の更新に失敗"; +"room_details_fail_to_update_history_visibility" = "発言履歴の可視範囲の設定更新に失敗"; +"room_details_fail_to_add_room_aliases" = "新しいルームアドレスの追加に失敗"; +"room_details_fail_to_remove_room_aliases" = "ルームアドレスの削除に失敗"; +"room_details_fail_to_update_room_canonical_alias" = "メインアドレスの更新に失敗"; +"room_details_fail_to_update_room_direct" = "ルームの対話タグの変更に失敗"; +"room_details_fail_to_enable_encryption" = "ルームの暗号化の開始に失敗"; "room_details_save_changes_prompt" = "変更を保存しますか?"; -"room_details_set_main_address" = "代表住所表記を設定"; -"room_details_unset_main_address" = "代表住所表記を設定解除"; +"room_details_set_main_address" = "メインアドレスを設定"; +"room_details_unset_main_address" = "メインアドレスの設定を解除"; "room_details_copy_room_id" = "ルーム固有IDをコピー"; -"room_details_copy_room_address" = "ルームの住所表記をコピー"; +"room_details_copy_room_address" = "ルームのアドレスをコピー"; "room_details_copy_room_url" = "ルームのURLをコピー"; // Read Receipts "read_receipts_list" = "既読一覧を見る"; -"receipt_status_read" = "既読状況: "; +"receipt_status_read" = "既読状況: "; // Media picker "media_picker_library" = "ライブラリ"; "media_picker_select" = "選択"; // Directory "directory_title" = "ルーム一覧"; "directory_server_picker_title" = "ルーム一覧を選択"; -"directory_server_all_rooms" = "%@ サーバ上の全てのルーム"; +"directory_server_all_rooms" = "%@ サーバー上の全てのルーム"; "directory_server_all_native_rooms" = "全てのMatrix連携ルーム"; -"directory_server_type_homeserver" = "公開ルーム一覧を表示するための接続サーバを入力してください"; +"directory_server_type_homeserver" = "公開ルーム一覧を表示するための接続サーバーを入力してください"; "directory_server_placeholder" = "matrix.org"; // Events formatter -"event_formatter_member_updates" = "%tu 権限が変更されました"; -"event_formatter_widget_added" = "%@ ウィジェットが %@ さんにより追加されました"; -"event_formatter_widget_removed" = "%@ ウィジェットが %@ さんにより削除されました"; -"event_formatter_jitsi_widget_added" = "音声会議が %@ さんにより追加されました"; -"event_formatter_jitsi_widget_removed" = "音声会議が %@ さんにより削除されました"; +"event_formatter_member_updates" = "%tu権限が変更されました"; +"event_formatter_widget_added" = "%@ウィジェットが %@ さんにより追加されました"; +"event_formatter_widget_removed" = "%@ウィジェットが %@ さんにより削除されました"; +"event_formatter_jitsi_widget_added" = "音声会議が%@ さんにより追加されました"; +"event_formatter_jitsi_widget_removed" = "音声会議が%@ さんにより削除されました"; // Others "or" = "または"; "you" = "あなた"; "today" = "今日"; "yesterday" = "昨日"; "network_offline_prompt" = "インターネットへの接続が切れているようです。"; -"public_room_section_title" = "公開ルーム (at %@):"; -"bug_report_prompt" = "前回アプリが異常終了しました。不具合報告を送信しますか?"; -"rage_shake_prompt" = "あなたは不満があって端末を揺らしているようです。不具合報告をしますか?"; +"public_room_section_title" = "公開ルーム(%@ にて):"; +"bug_report_prompt" = "前回アプリが異常終了しました。バグレポートを送信しますか?"; +"rage_shake_prompt" = "あなたは不満があって端末を揺らしているようです。バグレポートをしますか?"; "do_not_ask_again" = "再度質問しない"; -"camera_access_not_granted" = "%@ はカメラを使用する権限を持っていません。個人情報保護設定の変更をお願いします"; +"camera_access_not_granted" = "%@はカメラを使用する権限を持っていません。個人情報保護設定の変更をお願いします"; "large_badge_value_k_format" = "%.1fK"; // room display name "room_displayname_invite_from" = "%@ から招待されました"; @@ -428,28 +428,28 @@ "call_jitsi_error" = "会議通話への参加に失敗しました。"; // No VoIP support "no_voip_title" = "通話着信中"; -"no_voip" = "%@ さんから通話の着信がありましたが、 %@ は通話をまだサポートしていません。\nこの通知を無視して、別の端末から着信に応答することも、拒否することもできます。"; +"no_voip" = "%@さんから通話の着信がありましたが、%@は通話をまだサポートしていません。\nこの通知を無視して、別の端末から着信に応答することも、拒否することもできます。"; // Crash report "google_analytics_use_prompt" = "匿名の誤動作報告と使用状況データを自動的に報告して%@の改善に役立てますか?"; // Crypto "e2e_enabling_on_app_update" = "Elementはエンドツーエンド暗号化をサポートするようになりましたが、有効にするには再びログインする必要があります。\n\nアプリの設定から再ログインできます。今すぐ、または後からでも構いません。"; -"e2e_need_log_in_again" = "このセッションのエンドツーエンド暗号化キーを生成し、公開キーをホームサーバーに送信するには、再度ログインする必要があります。\nこれは一度だけです。 ご不便おかけしてすみません。"; +"e2e_need_log_in_again" = "このセッションのエンドツーエンド暗号化キーを生成し、公開キーをホームサーバーに送信するには、再度ログインする必要があります。\nこれは一度だけです。ご迷惑をおかけしますが、ご了承ください。"; // Bug report -"bug_report_title" = "不具合報告"; +"bug_report_title" = "バグレポート"; "bug_report_description" = "誤動作の内容と状況の説明をお願い致します。あなたは何をしましたか?何が起こると思いますか?実際何が起こったのですか?"; "bug_crash_report_title" = "異常終了報告"; "bug_crash_report_description" = "異常停止する前にあなたがしていたことを記してください:"; -"bug_report_logs_description" = "開発者が問題を診断するために、このElementの動作記録が不具合報告と一緒に送信されます。上記文章のみを送信したい場合は以下のチェックを解除してください:"; -"bug_report_send_logs" = "動作記録を送信"; +"bug_report_logs_description" = "開発者が問題を診断するために、このElementのログがバグレポートと一緒に送信されます。上記文章のみを送信したい場合は以下のチェックを解除してください:"; +"bug_report_send_logs" = "ログを送信"; "bug_report_send_screenshot" = "画面のスクリーンショット画像を送信"; -"bug_report_progress_zipping" = "動作記録を収集"; +"bug_report_progress_zipping" = "ログを収集"; "bug_report_progress_uploading" = "報告を送信しています"; "bug_report_send" = "送信"; // Widget "widget_no_power_to_manage" = "あなたがこのルームでウィジェットを管理するための権限が必要です"; "widget_creation_failure" = "ウィジェットの作成に失敗しました"; // Widget Integration Manager -"widget_integration_need_to_be_able_to_invite" = "それを行うにはユーザを招待する権限が必要です。"; +"widget_integration_need_to_be_able_to_invite" = "それを行うにはユーザーを招待する権限が必要です。"; "widget_integration_unable_to_create" = "ウィジェットを作成できません。"; "widget_integration_failed_to_send_request" = "リクエストの送信に失敗しました。"; "widget_integration_room_not_recognised" = "このルームでは認められません。"; @@ -457,7 +457,7 @@ "widget_integration_must_be_in_room" = "あなたはこのルームに所属していません。"; "widget_integration_no_permission_in_room" = "あなたはこのルームで権限がありません。"; "widget_integration_missing_room_id" = "ルーム固有IDの要求に失敗しました。"; -"widget_integration_missing_user_id" = "ユーザ固有IDの要求に失敗しました。"; +"widget_integration_missing_user_id" = "ユーザー固有IDの要求に失敗しました。"; "widget_integration_room_not_visible" = "ルーム %@ は見えません。"; // Share extension "share_extension_auth_prompt" = "メインのアプリにログインしてコンテンツを共有"; @@ -470,7 +470,7 @@ // Groups tab "group_invite_section" = "招待"; "group_section" = "コミュニティー"; -"room_message_reply_to_placeholder" = "返信を送る (暗号化されていない)…"; +"room_message_reply_to_placeholder" = "返信を送る(暗号化されていない)…"; "room_do_not_have_permission_to_post" = "このルームに投稿する権限がありません"; "encrypted_room_message_reply_to_placeholder" = "暗号化された返信を送信…"; "room_message_reply_to_short_placeholder" = "返信を送る…"; @@ -493,34 +493,34 @@ "settings_labs_room_members_lazy_loading_error_message" = "あなたのホームサーバーはまだルームメンバーの遅延ロードをサポートしていません。 後で試してください。"; "settings_deactivate_my_account" = "アカウントを無効にします"; "room_details_flair_section" = "コミュニティーの特色を表示"; -"room_details_new_flair_placeholder" = "新しいコミュニティーIDを追加 (例 +foo%@)"; +"room_details_new_flair_placeholder" = "新しいコミュニティーIDを追加(例 +foo%@)"; "room_details_flair_invalid_id_prompt_title" = "無効な形式"; "room_details_flair_invalid_id_prompt_msg" = "%@はコミュニティーの有効な識別子ではありません"; -"room_details_fail_to_update_room_communities" = "関連コミュニティーを更新できない"; +"room_details_fail_to_update_room_communities" = "関連するコミュニティーの更新に失敗"; // Group Details "group_details_title" = "コミュニティーの詳細"; "group_details_home" = "ホーム"; "group_details_people" = "人々"; "group_details_rooms" = "ルーム"; // Group Home -"group_home_one_member_format" = "1 メンバー"; -"group_home_multi_members_format" = "%tu メンバー"; -"group_home_one_room_format" = "1 ルーム"; -"group_home_multi_rooms_format" = "%tu ルーム"; +"group_home_one_member_format" = "1メンバー"; +"group_home_multi_members_format" = "%tuメンバー"; +"group_home_one_room_format" = "1ルーム"; +"group_home_multi_rooms_format" = "%tuルーム"; "group_invitation_format" = "%@がこのコミュニティーにあなたを招待しました"; // Group participants "group_participants_add_participant" = "参加者を追加"; "group_participants_leave_prompt_title" = "グループを退出"; -"group_participants_leave_prompt_msg" = "本当にグループを退出しますか?"; +"group_participants_leave_prompt_msg" = "グループを退出してよろしいですか?"; "group_participants_remove_prompt_title" = "確認"; -"group_participants_remove_prompt_msg" = "本当にこのグループから%@を削除しますか?"; +"group_participants_remove_prompt_msg" = "このグループから%@を削除してよろしいですか?"; "group_participants_invite_prompt_title" = "確認"; -"group_participants_invite_prompt_msg" = "本当にこのグループに%@を招待しますか?"; -"group_participants_filter_members" = "コミュニティーメンバーをフィルタリング"; +"group_participants_invite_prompt_msg" = "このグループに%@を招待してよろしいですか?"; +"group_participants_filter_members" = "コミュニティーのメンバーを絞り込む"; "group_participants_invite_another_user" = "ユーザーIDまたは名前による検索/招待"; "group_participants_invite_malformed_id_title" = "招待エラー"; -"group_participants_invite_malformed_id" = "不正なID。 '@localpart:domain' のようなMatrix IDでなければなりません"; -"group_participants_invited_section" = "招待した"; +"group_participants_invite_malformed_id" = "不正なID。'@localpart:domain'のようなMatrix IDでなければなりません"; +"group_participants_invited_section" = "招待中"; // Group rooms "group_rooms_filter_rooms" = "コミュニティールームをフィルタリング"; "event_formatter_rerequest_keys_part1_link" = "暗号鍵の再要求"; @@ -530,8 +530,8 @@ "widget_sticker_picker_no_stickerpacks_alert_add_now" = "今すぐ追加しますか?"; // Room key request dialog "e2e_room_key_request_title" = "暗号化キー要求"; -"e2e_room_key_request_message_new_device" = "暗号化キーを要求している新しい端末 '%@'を追加しました。"; -"e2e_room_key_request_message" = "検証されていない端末 '%@'が暗号化キーを要求しています。"; +"e2e_room_key_request_message_new_device" = "暗号化キーを要求している新しい端末 '%@' を追加しました。"; +"e2e_room_key_request_message" = "検証されていない端末 '%@' が暗号化キーを要求しています。"; "e2e_room_key_request_start_verification" = "検証を始めます…"; "e2e_room_key_request_share_without_verifying" = "検証せずに共有"; "e2e_room_key_request_ignore_request" = "要求を無視"; @@ -539,7 +539,7 @@ "gdpr_consent_not_given_alert_message" = "%@ホームサーバーを引き続き使用するには、利用規約を確認して同意する必要があります。"; "gdpr_consent_not_given_alert_review_now_action" = "今レビュー"; "deactivate_account_title" = "無効なアカウント"; -"deactivate_account_informations_part1" = "これにより、アカウントは永久に使用できなくなります。 ログインすることはできず、誰も同じユーザーIDを再登録することはできません。 これにより、あなたのアカウントは参加している全てのルームから退去し、あなたのIDサーバーからアカウントの詳細が削除されます。 "; +"deactivate_account_informations_part1" = "これにより、アカウントは永久に使用できなくなります。ログインすることはできず、誰も同じユーザーIDを再登録することはできません。これにより、あなたのアカウントは参加している全てのルームから退去し、あなたのIDサーバーからアカウントの詳細が削除されます。 "; "deactivate_account_informations_part2_emphasize" = "この動作は元に戻せません。"; "deactivate_account_informations_part3" = "\n\nアカウントの無効化 "; "deactivate_account_informations_part4_emphasize" = "デフォルトではあなたが送信したメッセージを忘れることはありません。 "; @@ -567,11 +567,11 @@ "room_message_unable_open_link_error_message" = "リンクを開くことができません。"; "user_verification_session_details_verify_action_other_user" = "手動で確認"; "room_info_list_section_other" = "その他"; -"room_info_list_several_members" = "%@ 人のメンバー"; +"room_info_list_several_members" = "%@人のメンバー"; // MARK: - Room Info -"room_info_list_one_member" = "1 人のメンバー"; +"room_info_list_one_member" = "1人のメンバー"; "create_room_placeholder_address" = "#testroom:matrix.org"; "create_room_section_header_address" = "ルームのアドレス"; "create_room_show_in_directory" = "このルームを一覧に掲載"; @@ -582,7 +582,7 @@ "create_room_section_footer_encryption" = "暗号化はあとから無効にすることはできません。"; "create_room_section_header_encryption" = "ルームの暗号化"; "create_room_placeholder_topic" = "トピック"; -"create_room_section_header_topic" = "ルームのトピック (任意)"; +"create_room_section_header_topic" = "ルームのトピック(任意)"; "create_room_placeholder_name" = "名前"; "create_room_section_header_name" = "ルーム名"; @@ -591,19 +591,19 @@ "create_room_title" = "新しいルーム"; "create_room_enable_encryption" = "暗号化を有効にする"; "room_details_room_name_for_dm" = "名前"; -"room_participants_security_information_room_encrypted_for_dm" = "ここで送受信されるメッセージはエンドツーエンド暗号化されます。\n\nメッセージは安全に保護されており、あなたと宛先のみがメッセージの閲覧に必要な鍵を所持します。"; -"room_participants_security_information_room_not_encrypted_for_dm" = "ここで送受信されるメッセージはエンドツーエンド暗号化されません。"; +"room_participants_security_information_room_encrypted_for_dm" = "ここで送受信されるメッセージはエンドツーエンド暗号化されています。\n\nメッセージは安全に保護されており、メッセージのロックを解除するための固有の鍵は、あなたと受信者だけが持っています。"; +"room_participants_security_information_room_not_encrypted_for_dm" = "ここでのメッセージはエンドツーエンド暗号化されていません。"; // Mark: - Room creation introduction cell "room_intro_cell_add_participants_action" = "参加者を追加"; -"room_participants_security_information_room_encrypted" = "このルームで送受信されるメッセージはエンドツーエンド暗号化されます。\n\nメッセージは安全に保護されており、このルームの参加者のみがメッセージの閲覧に必要な鍵を所持します。"; +"room_participants_security_information_room_encrypted" = "このルームのメッセージはエンドツーエンド暗号化されています。\n\nメッセージは安全に保護されており、メッセージのロックを解除するための固有の鍵は、あなたと受信者だけが持っています。"; "room_participants_security_information_room_not_encrypted" = "このルームのメッセージはエンドツーエンド暗号化されていません。"; "room_intro_cell_information_dm_sentence1_part3" = ". "; -"callbar_active_and_single_paused" = "ひとつのアクティブな通話 (%@) · ひとつの一時停止された通話"; +"callbar_active_and_single_paused" = "1つのアクティブな通話(%@)· 1つの一時停止された通話"; // Call Bar -"callbar_only_single_active" = "アクティブな通話(%@)"; +"callbar_only_single_active" = "タップして通話(%@)に戻る"; "settings_add_3pid_password_title_msidsn" = "電話番号を追加"; "device_verification_emoji_scissors" = "ハサミ"; "device_verification_emoji_paperclip" = "ペーパークリップ"; @@ -655,19 +655,19 @@ "room_does_not_exist" = "%@は存在しません"; "photo_library_access_not_granted" = "%@はフォトライブラリにアクセスする権限がありません"; "camera_unavailable" = "お使いの端末ではカメラを利用できません"; -"event_formatter_widget_removed_by_you" = "ウィジェットを削除しました: %@"; +"event_formatter_widget_removed_by_you" = "ウィジェットを削除しました:%@"; "event_formatter_jitsi_widget_removed_by_you" = "VoIPカンファレンスを削除しました"; "event_formatter_jitsi_widget_added_by_you" = "VoIPカンファレンスを追加しました"; // Events formatter with you -"event_formatter_widget_added_by_you" = "ウィジェットを追加しました: %@"; +"event_formatter_widget_added_by_you" = "ウィジェットを追加しました:%@"; "event_formatter_call_back" = "かけ直す"; "event_formatter_call_you_declined" = "通話を拒否しました"; "event_formatter_call_you_currently_in" = "通話中です"; "event_formatter_call_has_ended" = "通話は有効です"; "event_formatter_call_video" = "ビデオ通話"; "event_formatter_call_voice" = "音声通話"; -"event_formatter_message_edited_mention" = "(編集済み)"; +"event_formatter_message_edited_mention" = "(編集済)"; "image_picker_action_library" = "ライブラリを選ぶ"; // Image picker @@ -680,9 +680,9 @@ "room_details_advanced_room_id_for_dm" = "ID:"; "room_details_no_local_addresses_for_dm" = "ここにはローカルアドレスがありません"; "room_details_access_section_directory_toggle_for_dm" = "ルーム一覧に掲載"; -"room_details_access_section_anyone_apart_from_guest_for_dm" = "ゲスト以外のリンクを知っている人"; -"room_details_access_section_anyone_for_dm" = "ゲストを含め、リンクを知っている人なら誰でも"; -"room_details_access_section_for_dm" = "誰がアクセスできるのか?"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "リンクを知っている人なら誰でも(ゲストユーザーを除く)"; +"room_details_access_section_anyone_for_dm" = "リンクを知っている人なら誰でも(ゲストユーザーを含む)"; +"room_details_access_section_for_dm" = "誰がアクセスできますか?"; "room_details_photo_for_dm" = "写真"; "room_details_integrations" = "インテグレーション"; "room_details_search" = "ルーム(部屋)を探す"; @@ -694,7 +694,7 @@ "identity_server_settings_alert_disconnect_button" = "接続を解除"; "identity_server_settings_alert_disconnect" = "IDサーバー%@を接続解除しますか?"; "identity_server_settings_alert_disconnect_title" = "IDサーバーを接続解除"; -"identity_server_settings_alert_change" = "IDサーバー%1$@を切断し、代わりに %2$@に接続しますか?"; +"identity_server_settings_alert_change" = "IDサーバー%1$@を切断し、代わりに%2$@に接続しますか?"; "identity_server_settings_alert_change_title" = "IDサーバーを変更"; "identity_server_settings_alert_no_terms" = "選択したIDサーバーには利用規約がありません。そのサーバーの所有者を信頼できる場合にのみ続行してください。"; "identity_server_settings_alert_no_terms_title" = "IDサーバーには利用規約がありません"; @@ -703,29 +703,29 @@ "identity_server_settings_change" = "変更"; "identity_server_settings_add" = "追加"; "identity_server_settings_place_holder" = "IDサーバーを入力"; -"identity_server_settings_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり、発見できるようにするには、上記に追加してください。"; +"identity_server_settings_no_is_description" = "現在、IDサーバーを使用していません。知り合いを発見したり、発見できるようにするには、上記に追加してください。"; "identity_server_settings_description" = "あなたは%@を使って、あなたの知り合いを発見し、また向こうから発見できるようにしています。"; "security_settings_complete_security_alert_title" = "セキュリティーを確認"; "security_settings_crosssigning_complete_security" = "セキュリティーを確認"; -"security_settings_crosssigning_bootstrap" = "独立したクロス署名"; -"settings_devices_description" = "セッションのパブリックネームはコミュニケーションをとる相手に表示されます"; +"security_settings_crosssigning_bootstrap" = "設定"; +"settings_devices_description" = "セッションの公開名は、あなたとやり取りする人々に対して表示されます"; "settings_key_backup_delete_confirmation_prompt_title" = "バックアップの削除"; -"settings_key_backup_info_valid" = "このセッションは鍵のバックアップをされています。"; -"settings_key_backup_info_algorithm" = "アルゴリズム: %@"; -"settings_key_backup_info_version" = "キーのバックアップバージョン: %@"; -"settings_key_backup_info_none" = "あなたのキーはこのセッションからバックアップされていません。"; +"settings_key_backup_info_valid" = "このセッションは鍵をバックアップしています。"; +"settings_key_backup_info_algorithm" = "アルゴリズム:%@"; +"settings_key_backup_info_version" = "鍵のバックアップのバージョン:%@"; +"settings_key_backup_info_none" = "あなたの鍵は、このセッションからバックアップされていません。"; "settings_key_backup_info_checking" = "確認しています…"; "settings_add_3pid_password_message" = "続けるにはパスワードを入力してください"; "settings_add_3pid_invalid_password_message" = "無効な認証情報"; "settings_add_3pid_password_title_email" = "メールアドレスを追加"; "settings_integrations_allow_description" = "インテグレーションマネージャー(%@)を使用して、ボット、ブリッジ、ウィジェット、ステッカーパックを管理します。\n\n設定データを受け取り、お客様に代わってウィジェットの変更、ルーム招待の送信、権限の設定を行うことができます。"; "settings_integrations_allow_button" = "インテグレーションを管理"; -"settings_calls_stun_server_fallback_button" = "フォールバックコールアシストサーバを許可"; -"settings_key_backup" = "キーのバックアップ"; +"settings_calls_stun_server_fallback_button" = "フォールバックコールアシストサーバーを許可"; +"settings_key_backup" = "鍵のバックアップ"; "settings_integrations" = "インテグレーション"; "settings_discovery_settings" = "ディスカバリー"; "room_multiple_typing_notification" = "%@とその他のユーザーが入力中です"; -"external_link_confirmation_message" = "リンク%@は別のサイトに移動します: %@\n\n本当に続けますか?"; +"external_link_confirmation_message" = "リンク%@は別のサイトに移動します:%@\n\n本当に続けますか?"; "room_event_action_delete_confirmation_title" = "未送信メッセージを削除"; "room_unsent_messages_cancel_message" = "このルームにある未送信のメッセージを全て削除してもよろしいですか?"; "room_unsent_messages_cancel_title" = "未送信メッセージを削除"; @@ -743,18 +743,18 @@ "room_participants_action_security_status_warning" = "警告"; "room_participants_action_security_status_complete_security" = "セキュリティーを確認"; "room_participants_action_security_status_verify" = "検証"; -"room_participants_action_security_status_verified" = "検証済み"; +"room_participants_action_security_status_verified" = "検証済"; "room_participants_action_section_security" = "セキュリティー"; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "IDサーバーが設定されていないため、メールアドレスを使って連絡先とチャットを開始することができません。"; -"room_participants_filter_room_members_for_dm" = "メンバーをフィルター"; +"room_participants_filter_room_members_for_dm" = "メンバーを絞り込む"; "room_participants_remove_third_party_invite_prompt_msg" = "招待を取り消してよろしいですか?"; "room_participants_leave_prompt_msg_for_dm" = "退出してよろしいですか?"; "room_participants_leave_prompt_title_for_dm" = "退出"; "contacts_address_book_no_identity_server" = "IDサーバーが設定されていません"; -"rooms_empty_view_information" = "ルームはプライベートでもパブリックでも、あらゆるグループチャットに最適です。+をタップすると、既にあるルームを見つけたり、新しいルームを作ることができます。"; +"rooms_empty_view_information" = "ルームは非公開でも公開でも、あらゆるグループチャットに最適です。+をタップすると、既にあるルームを見つけたり、新しいルームを作ったりすることができます。"; "rooms_empty_view_title" = "ルーム"; -"people_empty_view_information" = "誰とでも安全にチャットできます。+をタップすると会話相手を追加できます。"; -"people_empty_view_title" = "参加者"; +"people_empty_view_information" = "誰とでも安全にチャットできます。+をタップすると連絡先を追加できます。"; +"people_empty_view_title" = "連絡先"; "room_creation_error_invite_user_by_email_without_identity_server" = "IDサーバーが設定されていないため、メールで参加者を追加することができません。"; // Errors @@ -772,30 +772,30 @@ "auth_softlogout_clear_data_sign_out_title" = "続行してよろしいですか?"; "auth_softlogout_clear_data_button" = "全てのデータをクリア"; "auth_softlogout_clear_data_message_2" = "この端末の使用を終了する場合や、別のアカウントにサインインしたい場合は、クリアしてください。"; -"auth_softlogout_clear_data_message_1" = "警告: 個人データ(暗号化キーを含む)がこの端末にまだ保存されています。"; +"auth_softlogout_clear_data_message_1" = "警告:個人データ(暗号鍵を含む)がこの端末にまだ保存されています。"; "callbar_return" = "かけ直す"; -"callbar_active_and_multiple_paused" = "アクティブな通話 (%@) · %@ の一時停止された通話"; +"callbar_active_and_multiple_paused" = "アクティブな通話(%@)· %@の一時停止された通話"; "callbar_only_multiple_paused" = "一時停止した%@の通話"; "callbar_only_single_paused" = "通話の一時停止"; "store_promotional_text" = "オープンネットワーク上でプライバシーを保護したチャットアプリ。あなた自身でコントロールできるように非中央集権化(分散化)されています。データマイニング、バックドア、サードパーティによるアクセスはありません。"; "auth_softlogout_clear_data" = "個人データをクリア"; -"auth_softlogout_recover_encryption_keys" = "サインインして、この端末にのみ保存されている暗号化キーを復元します。どの端末でも、あなたのセキュアなメッセージを全て読むために必要です。"; +"auth_softlogout_recover_encryption_keys" = "暗号化されたメッセージがどの端末でも読めるように、サインインしてこの端末にのみ保存されている暗号鍵を取り戻してください。"; "auth_softlogout_reason" = "ホームサーバー(%1$@)の管理者が%2$@(%3$@)からサインアウトさせました。"; "auth_softlogout_sign_in" = "サインイン"; "auth_softlogout_signed_out" = "サインアウトしました"; "auth_autodiscover_invalid_response" = "無効なホームサーバー発見レスポンス"; "auth_accept_policies" = "このホームサーバーのポリシーを確認して同意してください:"; -"auth_reset_password_error_is_required" = "IDサーバーが設定されていません: パスワードをリセットするためにサーバーオプションに追加してください。"; -"auth_forgot_password_error_no_configured_identity_server" = "IDサーバーが設定されていません: パスワードをリセットするためにIDサーバーを追加してください。"; +"auth_reset_password_error_is_required" = "IDサーバーが設定されていません:パスワードをリセットするためにサーバーオプションに追加してください。"; +"auth_forgot_password_error_no_configured_identity_server" = "IDサーバーが設定されていません:パスワードをリセットするためにIDサーバーを追加してください。"; "auth_phone_is_required" = "IDサーバーが設定されていないので、パスワードをリセットするために電話番号を追加することはできません。"; "auth_email_is_required" = "IDサーバーが設定されていないので、パスワードをリセットするためにメールアドレスを追加することはできません。"; -"auth_add_email_phone_message_2" = "アカウント回復のためにメールを設定します。これを行うとメールアドレスや電話番号を使って、あなたのことを知っている人が発見できるようになります。"; -"auth_add_phone_message_2" = "電話番号を設定し、オプションとして自分を知っている人が発見できるようにします。"; -"auth_add_email_message_2" = "アカウント回復のためにメールを設定し、オプションとして自分のことを知っている人が発見できるようにします。"; +"auth_add_email_phone_message_2" = "アカウント復旧用のメールアドレスを設定します。後からオプションでメールアドレスや電話番号を使用して知人に見つけてもらえるようにできます。"; +"auth_add_phone_message_2" = "電話番号を設定します。後からオプションで知人に見つけてもらえるようにできます。"; +"auth_add_email_message_2" = "アカウント復旧用のメールアドレスを設定します。後からオプションで知人に見つけてもらえるようにできます。"; "less" = "たたむ"; "more" = "もっと"; "switch" = "切り替え"; -"joined" = "参加済み"; +"joined" = "参加済"; "skip" = "スキップ"; // Identity server settings @@ -804,8 +804,8 @@ // AuthenticatedSessionViewControllerFactory "authenticated_session_flow_not_supported" = "このアプリは、ホームサーバーの認証機構をサポートしていません。"; "manage_session_sign_out" = "セッションからサインアウト"; -"manage_session_not_trusted" = "信頼できない"; -"manage_session_trusted" = "信頼済み"; +"manage_session_not_trusted" = "信頼されていません"; +"manage_session_trusted" = "信頼済"; "manage_session_name" = "セッション名"; "manage_session_info" = "セッションの情報"; @@ -817,19 +817,19 @@ "security_settings_blacklist_unverified_devices_description" = "全てのセッションを検証して、信頼できるものとしてマークしメッセージを送信します。"; "security_settings_blacklist_unverified_devices" = "信頼していないセッションにはメッセージを送信しない"; "security_settings_advanced" = "上級者向け"; -"security_settings_export_keys_manually" = "手動でキーをエクスポート"; +"security_settings_export_keys_manually" = "手動で鍵をエクスポート"; "security_settings_cryptography" = "暗号技術"; "security_settings_crosssigning_reset" = "クロス署名をリセット"; "security_settings_crosssigning_info_ok" = "クロス署名が有効です。"; "security_settings_crosssigning_info_trusted" = "クロス署名が有効になっています。クロス署名に基づいて他のユーザーや自分の他のセッションを信頼することはできますが、このセッションにはクロス署名用の秘密鍵がないため、このセッションからクロス署名を行うことはできません。このセッションのセキュリティーを完了してください。"; -"security_settings_crosssigning_info_exists" = "アカウントにはクロス署名IDがありますが、このセッションはまだ信頼されていません。 このセッションのセキュリティーを完了してください。"; +"security_settings_crosssigning_info_exists" = "アカウントにはクロス署名IDがありますが、このセッションはまだ信頼されていません。このセッションのセキュリティーを完了してください。"; "security_settings_crosssigning_info_not_bootstrapped" = "クロス署名がまだ行われていません。"; "security_settings_crosssigning" = "クロス署名"; "security_settings_backup" = "メッセージのバックアップ"; -"security_settings_secure_backup_delete" = "削除"; +"security_settings_secure_backup_delete" = "バックアップの削除"; "security_settings_secure_backup_synchronise" = "同期"; -"security_settings_secure_backup_setup" = "セットアップ"; -"security_settings_secure_backup_description" = "暗号化キーをサーバーにバックアップすることにより、暗号化されたメッセージとデータへのアクセスが失われるのを防ぎます。"; +"security_settings_secure_backup_setup" = "設定"; +"security_settings_secure_backup_description" = "セッションにアクセスできなくなる場合に備えて、アカウントデータと暗号鍵をバックアップします。鍵は一意のセキュリティーキーで保護されます。"; "security_settings_secure_backup" = "安全なバックアップ"; "security_settings_crypto_sessions_description_2" = "見覚えのないログインがある場合は、Matrixアカウントのパスワードを変更し、バックアップをリセットしてください。"; "security_settings_crypto_sessions_loading" = "セッションを読み込んでいます…"; @@ -838,7 +838,7 @@ // Security settings "security_settings_title" = "セキュリティー"; "settings_show_NSFW_public_rooms" = "NSFWパブリックルームを表示"; -"settings_identity_server_no_is_description" = "現在、ID サーバーを使用していません。知り合いを発見したり発見されるようにするには1つ連絡先を追加します。"; +"settings_identity_server_no_is_description" = "現在、IDサーバーを使用していません。知り合いを発見したり発見されるようにするには1つ連絡先を追加します。"; "settings_identity_server_no_is" = "IDサーバーが設定されていません"; "settings_identity_server_description" = "上記で設定したIDサーバーを使って、自分の知り合いを発見したり、発見されたりすることができます。"; "settings_discovery_three_pid_details_enter_sms_code_action" = "SMSアクティベーションコードを入力"; @@ -856,40 +856,40 @@ "settings_discovery_terms_not_signed" = "メールアドレスや電話番号で自分を発見できるようにするには、IDサーバー(%@)の利用規約に同意する必要があります。"; "settings_discovery_no_identity_server" = "現在、IDサーバーを使用していません。知り合いがあなたを発見できるようにするには、IDサーバーを追加してください。"; "settings_key_backup_delete_confirmation_prompt_msg" = "よろしいですか?鍵が適切にバックアップされていないと、暗号化されたメッセージを失うことがあります。"; -"settings_key_backup_button_connect" = "このセッションをキーバックアップに接続"; -"settings_key_backup_button_delete" = "バックアップの消去"; +"settings_key_backup_button_connect" = "このセッションを鍵のバックアップに接続"; +"settings_key_backup_button_delete" = "バックアップの削除"; "settings_key_backup_button_restore" = "バックアップからの復旧"; -"settings_key_backup_button_create" = "キーバックアップの使用を開始"; -"settings_key_backup_info_trust_signature_invalid_device_unverified" = "バックアップには%@からの無効な署名があります"; -"settings_key_backup_info_trust_signature_invalid_device_verified" = "バックアップには%@からの無効な署名があります"; -"settings_key_backup_info_trust_signature_valid_device_unverified" = "バックアップには%@からの署名があります"; +"settings_key_backup_button_create" = "鍵のバックアップを使用開始"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "バックアップには%@による無効な署名があります"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "バックアップには%@による無効な署名があります"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "バックアップには%@による署名があります"; "settings_key_backup_info_trust_signature_valid_device_verified" = "バックアップには%@による有効な署名があります"; "settings_key_backup_info_trust_signature_valid" = "バックアップにはこのセッションの有効な署名があります"; -"settings_key_backup_info_trust_signature_unknown" = "バックアップにはID: %@によるセッションの署名があります"; -"settings_key_backup_info_progress_done" = "キーのバックアップが完了しました"; -"settings_key_backup_info_progress" = "%@のキーをバックアップしています…"; -"settings_key_backup_info_not_valid" = "このセッションではキーをバックアップしていませんが、復元して今後追加できる既存のバックアップがあります。"; -"settings_key_backup_info_signout_warning" = "この端末にのみ存在するキーの消失を防ぐために、サインアウトする前にこのセッションをキーバックアップに接続してください。"; -"settings_key_backup_info" = "暗号化されたメッセージはエンドツーエンドで暗号化されています。送信者と受信者だけがこのメッセージを読むための鍵を持っています。"; +"settings_key_backup_info_trust_signature_unknown" = "バックアップにはID:%@によるセッションの署名があります"; +"settings_key_backup_info_progress_done" = "全ての鍵がバックアップされています"; +"settings_key_backup_info_progress" = "%@の鍵をバックアップしています…"; +"settings_key_backup_info_not_valid" = "このセッションでは鍵をバックアップしていませんが、復元に使用したり、今後鍵を追加したりできるバックアップを持っています。"; +"settings_key_backup_info_signout_warning" = "鍵を失くさないよう、サインアウトする前にバックアップしてください。"; +"settings_key_backup_info" = "暗号化されたメッセージは、エンドツーエンドの暗号化によって保護されています。これらの暗号化されたメッセージを読むための鍵を持っているのは、あなたと受信者だけです。"; "settings_labs_message_reaction" = "絵文字でメッセージに反応"; "settings_calls_stun_server_fallback_description" = "ホームサーバーがフォールバックコールアシストサーバーを提供していない場合は%@を許可します(IPアドレスは通話中に共有されます)。"; "settings_security" = "セキュリティー"; "settings_three_pids_management_information_part3" = ""; "settings_three_pids_management_information_part2" = "ディスカバリー"; -"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使用するかを、ご自身で決めることができます。\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全ての端末とウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; +"store_full_description" = "Elementはまったく新しいメッセンジャーアプリです。\n\n1. あなた自身がプライバシーをコントロールすることを可能にします。\n2. Matrixネットワークにいる誰とでも通信できることはもちろん、Slackなどのアプリとの連携によって他のネットワークとも通信ができます。\n3. 広告、データマイニング、バックドア、ウォールドガーデンから、あなたを守ります。\n4. エンドツーエンド暗号化とクロス署名によってあなたを保護します。\n\nElementは分散型(非中央集権型)でオープンソースであるため、他のメッセンジャーアプリと完全に異なっています。\n\nElementでは、あなた自身がサーバーを運営することも、サーバーを選ぶこともできます。これによってあなたのデータと会話に関するプライバシーや所有権はあなた自身で管理できるようになります。さらに、Elementは開かれたネットワークにアクセスするので、Elementのユーザー以外とも話すことができます。しかもきわめて安全です。\n\nElementはMatrixーーオープンな分散型通信の標準規格ーーで動作するため、これら全てを実現することができています。\n\nElementでは、どのサーバーを使用するかを、ご自身でElementのアプリから決めることができます。\n\n1. 開発者がホストする matrix.org のパブリックサーバーで無料アカウントを取得する。\n2. あなた自身がサーバーを運営し、アカウントを管理する。\n3. Element Matrix Servicesのホスティングプラットフォームに加入し、カスタムサーバー上でアカウントを作る。\n\nなぜElementを選ぶべきなのか?\n\n自分のデータを、自分で所有: データやメッセージを保管する場所を自分で決めることができます。データを所有しコントロールするのは、あなた自身です。データを解析したり第三者にデータを渡したりする巨大IT企業ではありません。\n\nオープンなメッセージングとコラボレーション: Matrixネットワーク上の誰とでも、相手がElementや他のMatrixアプリを使っているか、さらにはSlack、IRC、XMPPのような他のメッセージングシステムを使っているかに関わらず、チャットをすることができます。\n\n非常に安全: 本物のエンド・ツー・エンドの暗号化(会話に参加している人だけがメッセージを復号化できる)と、会話参加者の真正性を確認するための相互署名を行います。\n\n包括的なコミュニケーション: メッセージング、音声およびビデオ通話、ファイル共有、画面共有、その他多くのインテグレーション、ボット、ウィジェットを提供します。ルームやコミュニティーを立ち上げて連絡を取り合い、物事をスムーズに成し遂げることができます。\n\nいつでも、どこにいても: 全ての端末とウェブ(https://app.element.io)でメッセージの履歴が同期されるため、どこにいても連絡を取ることができます。"; "user_verification_session_details_additional_information_untrusted_other_user" = "ユーザーがこのセッションを信頼するまでは、セッションとの間で送受信されるメッセージには警告が表示されます。また、手動で検証することもできます。"; "user_verification_session_details_information_untrusted_other_user" = " 新しいセッションを使ってサインインしました:"; "user_verification_session_details_information_untrusted_current_user" = "このセッションを検証することで、信頼できるものとしてマークし、暗号化されたメッセージへのアクセスを許可します。"; -"user_verification_session_details_information_trusted_other_user_part2" = " 検証済み:"; +"user_verification_session_details_information_trusted_other_user_part2" = " 検証済:"; "user_verification_session_details_information_trusted_other_user_part1" = "このセッションは安全なものとして信頼されています。なぜなら "; "user_verification_session_details_information_trusted_current_user" = "このセッションは、検証されたため安全なものとして信頼されています。"; -"user_verification_session_details_untrusted_title" = "信頼できない"; +"user_verification_session_details_untrusted_title" = "信頼されていません"; // Session details -"user_verification_session_details_trusted_title" = "信頼済み"; -"user_verification_sessions_list_session_untrusted" = "信頼できない"; -"user_verification_sessions_list_session_trusted" = "信頼済み"; +"user_verification_session_details_trusted_title" = "信頼済"; +"user_verification_sessions_list_session_untrusted" = "信頼されていません"; +"user_verification_sessions_list_session_trusted" = "信頼済"; "user_verification_sessions_list_table_title" = "セッション一覧"; "user_verification_sessions_list_information" = "このルームにいるこのユーザーとのメッセージはエンドツーエンドで暗号化されており第三者が読み取ることはできません。"; "user_verification_sessions_list_user_trust_level_unknown_title" = "未知"; @@ -897,7 +897,7 @@ // Sessions list -"user_verification_sessions_list_user_trust_level_trusted_title" = "信頼済み"; +"user_verification_sessions_list_user_trust_level_trusted_title" = "信頼済"; "user_verification_start_additional_information" = "安心してご利用いただくために、直接お会いするか、別の方法でご連絡ください。"; "user_verification_start_waiting_partner" = "%@を待っています…"; "user_verification_start_information_part2" = " 両方の端末でワンタイムコードを確認します。"; @@ -938,7 +938,7 @@ "key_verification_incoming_request_incoming_alert_message" = "%@は検証を求めています"; "key_verification_tile_conclusion_warning_title" = "信頼されていないサインイン"; -"key_verification_tile_conclusion_done_title" = "検証済み"; +"key_verification_tile_conclusion_done_title" = "検証済"; "key_verification_tile_request_incoming_approval_decline" = "却下"; "key_verification_tile_request_incoming_approval_accept" = "承認"; "key_verification_tile_request_status_accepted" = "あなたは承認しました"; @@ -1032,7 +1032,7 @@ "key_verification_verify_sas_title_emoji" = "絵文字の比較"; "device_verification_self_verify_alert_validate_action" = "検証"; -"device_verification_self_verify_alert_message" = "ログインを検証してください: %@"; +"device_verification_self_verify_alert_message" = "ログインを検証してください:%@"; // MARK: Self verification start @@ -1041,16 +1041,16 @@ "room_recents_suggested_rooms_section" = "おすすめのルーム"; "settings_show_url_previews_description" = "プレビューは暗号化されていないルームでのみ表示されます。"; "settings_show_url_previews" = "ウェブサイトプレビューを表示"; -"biometrics_setup_enable_button_title_x" = "%@ を有効にする"; -"biometrics_setup_title_x" = "%@ を有効にする"; -"biometrics_settings_enable_x" = "%@ を有効にする"; +"biometrics_setup_enable_button_title_x" = "%@を有効にする"; +"biometrics_setup_title_x" = "%@を有効にする"; +"biometrics_settings_enable_x" = "%@を有効にする"; "biometrics_mode_face_id" = "Face ID"; // MARK: - Biometrics Protection "biometrics_mode_touch_id" = "Touch ID"; -"pin_protection_settings_enable_pin" = "PIN を有効にする"; -"pin_protection_settings_section_header_with_biometrics" = "PIN と %@"; +"pin_protection_settings_enable_pin" = "PINを有効にする"; +"pin_protection_settings_section_header_with_biometrics" = "PINと%@"; "pin_protection_settings_section_header" = "PIN"; "settings_mentions_and_keywords_encryption_notice" = "モバイルでは、暗号化されたルームでのメンションとキーワードの通知は受信できません。"; "settings_new_keyword" = "キーワードを追加"; @@ -1116,3 +1116,11 @@ "sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "バックアップ"; "room_event_action_forward" = "転送"; "room_event_action_view_in_room" = "ルームに表示"; +"room_notifs_settings_encrypted_room_notice" = "暗号化されたルームでのメンションとキーワードによる通知は、携帯端末では利用できません。"; +"room_notifs_settings_mentions_and_keywords" = "メンションとキーワードのみ"; +"security_settings_secure_backup_info_valid" = "このセッションは鍵をバックアップしています。"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "鍵のバックアップを使用開始"; +"space_participants_action_ban" = "このスペースからブロック"; +"space_participants_action_remove" = "このスペースから削除"; +"accessibility_button_label" = "ボタン"; +"ok" = "OK"; From 743e734f92fc8edb53e3b7baf70aea5b34981e78 Mon Sep 17 00:00:00 2001 From: oksya8and8 Date: Sun, 20 Feb 2022 15:26:31 +0000 Subject: [PATCH 159/188] Translated using Weblate (Japanese) Currently translated at 67.4% (967 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index c8c225d9c..c7d6d62d9 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -433,7 +433,7 @@ "google_analytics_use_prompt" = "匿名の誤動作報告と使用状況データを自動的に報告して%@の改善に役立てますか?"; // Crypto "e2e_enabling_on_app_update" = "Elementはエンドツーエンド暗号化をサポートするようになりましたが、有効にするには再びログインする必要があります。\n\nアプリの設定から再ログインできます。今すぐ、または後からでも構いません。"; -"e2e_need_log_in_again" = "このセッションのエンドツーエンド暗号化キーを生成し、公開キーをホームサーバーに送信するには、再度ログインする必要があります。\nこれは一度だけです。ご迷惑をおかけしますが、ご了承ください。"; +"e2e_need_log_in_again" = "再度ログインして、このセッションのエンドツーエンドの暗号化キーを生成し、公開鍵をホームサーバーに送信する必要があります。\nご迷惑をおかけしますが、ご了承ください。"; // Bug report "bug_report_title" = "バグレポート"; "bug_report_description" = "誤動作の内容と状況の説明をお願い致します。あなたは何をしましたか?何が起こると思いますか?実際何が起こったのですか?"; From 5dd5276a75af71b259d5a9250014b6a0c0ee1ae6 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Sun, 20 Feb 2022 17:13:02 +0000 Subject: [PATCH 160/188] Translated using Weblate (Japanese) Currently translated at 84.6% (374 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index 1fa78d1a5..777c9e292 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -105,7 +105,7 @@ "notice_room_history_visible_to_members_from_invited_point" = "%@ ルームメンバー全員に招待した時点からのルーム履歴を表示されます。"; "notice_room_history_visible_to_members_from_joined_point" = "%@ ルームメンバー全員に参加した時点からのルーム履歴を表示されます。"; "notice_crypto_unable_to_decrypt" = "** 復号化できません: %@ **"; -"notice_crypto_error_unknown_inbound_session_id" = "送信者のセッションからこのメッセージのキーが送信されていません。"; +"notice_crypto_error_unknown_inbound_session_id" = "送信者のセッションからこのメッセージ用の鍵が送信されていません。"; "notice_sticker" = "ステッカー"; "notice_in_reply_to" = "に返信"; // room display name @@ -131,8 +131,8 @@ "room_event_encryption_info_title" = "エンドツーエンド暗号化情報\n\n"; "room_event_encryption_info_event" = "イベント情報\n"; "room_event_encryption_info_event_user_id" = "ユーザーID\n"; -"room_event_encryption_info_event_identity_key" = "Curve25519 identity key\n"; -"room_event_encryption_info_event_fingerprint_key" = "クレームされたEd25519指紋キー\n"; +"room_event_encryption_info_event_identity_key" = "Curve25519 固有鍵\n"; +"room_event_encryption_info_event_fingerprint_key" = "要求されたフィンガープリントキー Ed25519\n"; "room_event_encryption_info_event_algorithm" = "アルゴリズム\n"; "room_event_encryption_info_event_session_id" = "セッションID\n"; "room_event_encryption_info_event_decryption_error" = "復号化エラー\n"; @@ -152,16 +152,16 @@ "room_event_encryption_info_block" = "ブラックリスト"; "room_event_encryption_info_unblock" = "ブラックでないリスト"; "room_event_encryption_verify_title" = "セッション検証\n\n"; -"room_event_encryption_verify_message" = "このセッションが信頼できることを確認するには、他の方法(個人や電話など)で所有者に連絡し、セッションのユーザー設定で表示される鍵が以下のキーと一致するかどうかを尋ねます。\n\nセッション名: %@\nセッションID: %@\nセッションkey: %@\n\n一致する場合は、下の確認ボタンを押します。 それ以外の人がこのセッションを傍受している場合は、代わりにブラックリストボタンを押してください。\n\n将来この検証プロセスはより洗練されたものになります。"; +"room_event_encryption_verify_message" = "このセッションが信頼できることを確認するには、他の方法(対面や電話など)で所有者に連絡し、セッションのユーザー設定で表示される鍵が以下の鍵と一致するかどうかを訪ねてください。\n\nセッション名: %@\nセッションID: %@\nセッションキー: %@\n\n一致する場合は、下の確認ボタンを押します。 それ以外の人がこのセッションを傍受している場合は、代わりにブラックリストボタンを押してください。\n\n将来この検証プロセスはより洗練されたものになります。"; "room_event_encryption_verify_ok" = "検証"; // Account "account_save_changes" = "変更を保存"; "account_link_email" = "リンクメール"; "account_linked_emails" = "リンクされたメール"; -"account_email_validation_title" = "検証保留中"; +"account_email_validation_title" = "認証の保留中"; "account_email_validation_message" = "メールをチェックし、それに含まれているリンクをクリックしてください。 これが完了したら、[続行]をクリックします。"; "account_email_validation_error" = "メールアドレスを確認できません。 あなたのメールをチェックし、それに含まれているリンクをクリックしてください。 これが完了したら、[続行]をクリックします"; -"account_msisdn_validation_title" = "検証保留中"; +"account_msisdn_validation_title" = "認証の保留中"; "account_msisdn_validation_message" = "アクティベーションコード付きのSMSを送信しました。 以下にこのコードを入力してください。"; "account_msisdn_validation_error" = "電話番号を確認できません。"; "account_error_display_name_change_failed" = "表示名の変更に失敗しました"; @@ -210,7 +210,7 @@ "attachment_cancel_upload" = "アップロードをキャンセルしますか?"; "attachment_multiselection_size_prompt" = "画像を次のように送信しますか:"; "attachment_multiselection_original" = "実際のサイズ"; -"attachment_e2e_keys_file_prompt" = "このファイルには、Matrixクライアントからエクスポートされた暗号化キーが含まれています。\nファイルの内容を表示するか、ファイルの内容をインポートしますか?"; +"attachment_e2e_keys_file_prompt" = "このファイルには、Matrixクライアントからエクスポートされた暗号鍵が含まれています。\nファイルの内容を表示するか、ファイル内の鍵をインポートしますか?"; "attachment_e2e_keys_import" = "インポート…"; // Contacts "contact_mx_users" = "Matrixユーザー"; @@ -227,13 +227,13 @@ "format_time_h" = "時"; "format_time_d" = "日"; // E2E import -"e2e_import_room_keys" = "ルームキーをインポート"; -"e2e_import_prompt" = "このプロセスでは、以前に別のMatrixクライアントからエクスポートした暗号化キーをインポートできます。 これにより、他のクライアントが解読できる全てのメッセージを解読することができます。\nエクスポートファイルはパスフレーズで保護されています。 ファイルを解読するには、パスフレーズをここに入力する必要があります。"; +"e2e_import_room_keys" = "ルームの暗号鍵をインポート"; +"e2e_import_prompt" = "このプロセスでは、以前に別のMatrixクライアントからエクスポートした暗号鍵をインポートできます。 これにより、他のクライアントが解読できる全てのメッセージを解読することができます。\nエクスポートした暗号鍵のファイルは、パスフレーズで保護されています。 ファイルを復号化するには、パスフレーズをここに入力する必要があります。"; "e2e_import" = "インポート"; "e2e_passphrase_enter" = "パスフレーズを入力"; // E2E export -"e2e_export_room_keys" = "ルームキーのエクスポート"; -"e2e_export_prompt" = "このプロセスでは、暗号化されたルームで受信したメッセージのキーをローカルファイルにエクスポートできます。 その後、クライアントがこれらのメッセージを復号化できるように、ファイルを別のMatrixクライアントにインポートすることができます。\nエクスポートされたファイルは、誰でも閲覧できる暗号化されたメッセージを復号化することができるので、安全に保つように注意する必要があります。"; +"e2e_export_room_keys" = "ルームの暗号鍵をエクスポート"; +"e2e_export_prompt" = "このプロセスでは、暗号化されたルームで受信したメッセージの鍵をローカルファイルにエクスポートできます。 そのファイルを別のMatrixクライアントにインポートすると、クライアントはこれらのメッセージを復号化することができます。\nエクスポートしたファイルを使えば、誰でも暗号化されたメッセージを復号化できるので、ファイルを安全に保つように注意する必要があります。"; "e2e_export" = "エクスポート"; "e2e_passphrase_confirm" = "パスフレーズを確認"; "e2e_passphrase_empty" = "パスフレーズは空であってはいけません"; @@ -283,8 +283,8 @@ "notice_room_name_changed" = "%@はルーム名を次のように変更しました: %@"; "notice_placed_voice_call" = "%@は電話をかけました"; "notice_placed_video_call" = "%@はビデオ電話をかけました"; -"notice_answered_video_call" = "%@は通話に応答しました"; -"notice_ended_video_call" = "%@は通話を終了しました"; +"notice_answered_video_call" = "%@が電話に出ました"; +"notice_ended_video_call" = "%@が通話を終了しました"; "notice_conference_call_request" = "%@はVoIP会議をリクエストしました"; "notice_conference_call_started" = "VoIP会議が開始されました"; "notice_conference_call_finished" = "VoIP会議が終了しました"; From cfe6401106923d94970ba81f434ab0d69c00254f Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Sun, 20 Feb 2022 17:22:37 +0000 Subject: [PATCH 161/188] Translated using Weblate (Japanese) Currently translated at 84.6% (374 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 50 +++++++++---------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index 777c9e292..cc3594b9b 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -73,13 +73,13 @@ "ignore" = "無視"; // Events formatter "notice_avatar_changed_too" = "(アバターも変更されました)"; -"notice_room_name_removed" = "%@はルーム名を削除しました"; -"notice_room_topic_removed" = "%@はトピックを削除しました"; +"notice_room_name_removed" = "%@がルーム名を削除しました"; +"notice_room_topic_removed" = "%@がトピックを削除しました"; "notice_event_redacted" = "<編集された%@>"; "notice_event_redacted_by" = " %@により"; "notice_event_redacted_reason" = " [理由: %@]"; -"notice_profile_change_redacted" = "%@は彼らのプロフィール %@を更新しました"; -"notice_room_created" = "%@はルームを作成しました"; +"notice_profile_change_redacted" = "%@が彼らのプロフィール %@を更新しました"; +"notice_room_created" = "%@がルームを作成しました"; "notice_room_join_rule" = "結合ルールは次のとおり: %@"; "notice_room_power_level_intro" = "ルームメンバーの権限レベル:"; "notice_room_power_level_acting_requirement" = "アクション前にユーザーの必要な最小権限レベル:"; @@ -264,29 +264,29 @@ // Language picker "language_picker_title" = "言語を選択"; "language_picker_default_language" = "既定値 (%@)"; -"notice_room_invite" = "%@は%@を招待しました"; -"notice_room_third_party_invite" = "%@は%@にルームへの招待状を送りました"; -"notice_room_third_party_registered_invite" = "%@は%@の招待を受け入れました"; -"notice_room_join" = "%@ は参加しました"; -"notice_room_leave" = "%@ は退出しました"; -"notice_room_reject" = "%@は招待を拒否しました"; -"notice_room_kick" = "%@は%@を追い出しました"; -"notice_room_unban" = "%@は%@を追放解除した"; -"notice_room_ban" = "%@は%@を追放した"; -"notice_room_withdraw" = "%@は%@の招待を辞退しました"; +"notice_room_invite" = "%@が%@を招待しました"; +"notice_room_third_party_invite" = "%@が%@にルームへの招待状を送りました"; +"notice_room_third_party_registered_invite" = "%@が%@の招待を受け入れました"; +"notice_room_join" = "%@が参加しました"; +"notice_room_leave" = "%@が退出しました"; +"notice_room_reject" = "%@が招待を拒否しました"; +"notice_room_kick" = "%@が%@を追い出しました"; +"notice_room_unban" = "%@が%@を追放解除しました"; +"notice_room_ban" = "%@が%@を追放しました"; +"notice_room_withdraw" = "%@が%@の招待を辞退しました"; "notice_room_reason" = ". 理由: %@"; -"notice_avatar_url_changed" = "%@はアバターを変更しました"; -"notice_display_name_set" = "%@は表示名を%@に設定しました"; -"notice_display_name_changed_from" = "%@は表示名を%@から%@に変更しました"; -"notice_display_name_removed" = "%@は表示名を削除しました"; -"notice_topic_changed" = "%@はトピックを次のように変更しました: %@"; -"notice_room_name_changed" = "%@はルーム名を次のように変更しました: %@"; -"notice_placed_voice_call" = "%@は電話をかけました"; -"notice_placed_video_call" = "%@はビデオ電話をかけました"; +"notice_avatar_url_changed" = "%@がアバターを変更しました"; +"notice_display_name_set" = "%@が表示名を%@に設定しました"; +"notice_display_name_changed_from" = "%@が表示名を%@から%@に変更しました"; +"notice_display_name_removed" = "%@が表示名を削除しました"; +"notice_topic_changed" = "%@がトピックを次のように変更しました:%@"; +"notice_room_name_changed" = "%@がルーム名を次のように変更しました:%@"; +"notice_placed_voice_call" = "%@が電話をかけました"; +"notice_placed_video_call" = "%@がビデオ電話をかけました"; "notice_answered_video_call" = "%@が電話に出ました"; "notice_ended_video_call" = "%@が通話を終了しました"; -"notice_conference_call_request" = "%@はVoIP会議をリクエストしました"; -"notice_conference_call_started" = "VoIP会議が開始されました"; +"notice_conference_call_request" = "%@がVoIP会議をリクエストしました"; +"notice_conference_call_started" = "VoIP会議が開始しました"; "notice_conference_call_finished" = "VoIP会議が終了しました"; // button names "ok" = "OK"; @@ -380,7 +380,7 @@ "notice_encryption_enabled_unknown_algorithm" = "%1$@ がエンドツーエンド暗号化をオンにしました (不明なアルゴリズム %2$@)。"; "device_details_rename_prompt_title" = "セッション名"; "account_error_push_not_allowed" = "通知は許可されていません"; -"notice_room_third_party_revoked_invite" = "%@ は %@ のルームへの招待を取り消しました"; +"notice_room_third_party_revoked_invite" = "%@が%@のルームへの招待を取り消しました"; // Notice Events with "You" "notice_room_invite_by_you" = "%@を招待しました"; "notice_room_invite_you" = "%@があなたを招待しました"; From 2bd35f5934cbc19c6bc96ce27aa145ef681de2c4 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Sun, 20 Feb 2022 16:58:42 +0000 Subject: [PATCH 162/188] Translated using Weblate (Japanese) Currently translated at 68.1% (977 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 59 +++++++++++++++++++---------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index c7d6d62d9..d3eea910e 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -433,7 +433,7 @@ "google_analytics_use_prompt" = "匿名の誤動作報告と使用状況データを自動的に報告して%@の改善に役立てますか?"; // Crypto "e2e_enabling_on_app_update" = "Elementはエンドツーエンド暗号化をサポートするようになりましたが、有効にするには再びログインする必要があります。\n\nアプリの設定から再ログインできます。今すぐ、または後からでも構いません。"; -"e2e_need_log_in_again" = "再度ログインして、このセッションのエンドツーエンドの暗号化キーを生成し、公開鍵をホームサーバーに送信する必要があります。\nご迷惑をおかけしますが、ご了承ください。"; +"e2e_need_log_in_again" = "再度ログインして、このセッションのエンドツーエンド暗号鍵を生成し、公開鍵をホームサーバーに送信する必要があります。\nご迷惑をおかけしますが、ご了承ください。"; // Bug report "bug_report_title" = "バグレポート"; "bug_report_description" = "誤動作の内容と状況の説明をお願い致します。あなたは何をしましたか?何が起こると思いますか?実際何が起こったのですか?"; @@ -523,15 +523,15 @@ "group_participants_invited_section" = "招待中"; // Group rooms "group_rooms_filter_rooms" = "コミュニティールームをフィルタリング"; -"event_formatter_rerequest_keys_part1_link" = "暗号鍵の再要求"; -"event_formatter_rerequest_keys_part2" = " あなたの他のセッションから。"; +"event_formatter_rerequest_keys_part1_link" = "暗号鍵を再要求"; +"event_formatter_rerequest_keys_part2" = " あなたの他のセッションに。"; "homeserver_connection_lost" = "ホームサーバーに接続できませんでした。"; "widget_sticker_picker_no_stickerpacks_alert" = "現在、ステッカーパックを有効にしていません。"; "widget_sticker_picker_no_stickerpacks_alert_add_now" = "今すぐ追加しますか?"; // Room key request dialog -"e2e_room_key_request_title" = "暗号化キー要求"; -"e2e_room_key_request_message_new_device" = "暗号化キーを要求している新しい端末 '%@' を追加しました。"; -"e2e_room_key_request_message" = "検証されていない端末 '%@' が暗号化キーを要求しています。"; +"e2e_room_key_request_title" = "暗号鍵の要求"; +"e2e_room_key_request_message_new_device" = "暗号鍵を要求している新しい端末 '%@' を追加しました。"; +"e2e_room_key_request_message" = "検証されていない端末 '%@' が暗号鍵を要求しています。"; "e2e_room_key_request_start_verification" = "検証を始めます…"; "e2e_room_key_request_share_without_verifying" = "検証せずに共有"; "e2e_room_key_request_ignore_request" = "要求を無視"; @@ -551,8 +551,8 @@ "deactivate_account_password_alert_title" = "無効なアカウント"; "deactivate_account_password_alert_message" = "続行するには、パスワードを入力してください"; // Re-request confirmation dialog -"rerequest_keys_alert_title" = "リクエスト送信"; -"rerequest_keys_alert_message" = "この端末にキーを送信できるように、メッセージを復号化できる別の端末でElementを起動してください。"; +"rerequest_keys_alert_title" = "要求が送信されました"; +"rerequest_keys_alert_message" = "鍵をこのセッションに送信できるように、メッセージを復号化できる他の端末で%@を起動してください。"; "room_event_action_ban_prompt_reason" = "このユーザーをブロックする理由"; "room_resource_limit_exceeded_message_contact_1" = " お願い "; "settings_ui_theme_black" = "Black"; @@ -643,10 +643,10 @@ "bug_report_background_mode" = "バックグラウンドで継続"; "e2e_key_backup_wrong_version_button_wasme" = "これはわたしです"; "e2e_key_backup_wrong_version_button_settings" = "設定"; -"e2e_key_backup_wrong_version" = "新しいメッセージキーのバックアップが検出されました。\n\nこれがあなたによるものでばい場合は、設定から新しいパスフレーズを設定してください。"; +"e2e_key_backup_wrong_version" = "メッセージの鍵の新しい安全なバックアップが検出されました。\n\nこれがあなたによるものではない場合は、設定から新しいパスフレーズを設定してください。"; // Key backup wrong version -"e2e_key_backup_wrong_version_title" = "新しいキーのバックアップ"; +"e2e_key_backup_wrong_version_title" = "新しい鍵のバックアップ"; "call_no_stun_server_error_use_fallback_button" = "%@を使ってみてください"; "call_actions_unhold" = "やり直す"; "call_no_stun_server_error_message_2" = "代わりに、%@のパブリックサーバーを使用することもできますが、これは信頼性が低くあなたのIPアドレスがそのサーバーと共有されてしまいます。これは、設定から管理することができます"; @@ -858,7 +858,7 @@ "settings_key_backup_delete_confirmation_prompt_msg" = "よろしいですか?鍵が適切にバックアップされていないと、暗号化されたメッセージを失うことがあります。"; "settings_key_backup_button_connect" = "このセッションを鍵のバックアップに接続"; "settings_key_backup_button_delete" = "バックアップの削除"; -"settings_key_backup_button_restore" = "バックアップからの復旧"; +"settings_key_backup_button_restore" = "バックアップによる復元"; "settings_key_backup_button_create" = "鍵のバックアップを使用開始"; "settings_key_backup_info_trust_signature_invalid_device_unverified" = "バックアップには%@による無効な署名があります"; "settings_key_backup_info_trust_signature_invalid_device_verified" = "バックアップには%@による無効な署名があります"; @@ -925,20 +925,20 @@ "key_verification_verify_qr_code_other_scan_my_code_title" = "相手がQRコードを読み取ってくれましたか?"; "key_verification_verify_qr_code_start_emoji_action" = "絵文字による検証"; "key_verification_verify_qr_code_cannot_scan_action" = "スキャンできませんか?"; -"key_verification_verify_qr_code_scan_code_action" = "コードを読み取る"; -"key_verification_verify_qr_code_emoji_information" = "ユニークな絵文字を比較して検証します。"; +"key_verification_verify_qr_code_scan_code_action" = "コードをスキャン"; +"key_verification_verify_qr_code_emoji_information" = "絵文字の並びを比較して検証。"; "key_verification_verify_qr_code_information_other_device" = "以下のコードをスキャンして確認してください:"; "key_verification_verify_qr_code_information" = "コードをスキャンして、お互いをしっかりと確認します。"; // MARK: QR code -"key_verification_verify_qr_code_title" = "スキャンして確認"; +"key_verification_verify_qr_code_title" = "スキャンして検証"; // Incoming key verification request "key_verification_incoming_request_incoming_alert_message" = "%@は検証を求めています"; "key_verification_tile_conclusion_warning_title" = "信頼されていないサインイン"; -"key_verification_tile_conclusion_done_title" = "検証済"; +"key_verification_tile_conclusion_done_title" = "認証済"; "key_verification_tile_request_incoming_approval_decline" = "却下"; "key_verification_tile_request_incoming_approval_accept" = "承認"; "key_verification_tile_request_status_accepted" = "あなたは承認しました"; @@ -947,11 +947,11 @@ "key_verification_tile_request_status_expired" = "期限切れ"; "key_verification_tile_request_status_waiting" = "お待ちください…"; "key_verification_tile_request_status_data_loading" = "日時を読み込み…"; -"key_verification_tile_request_outgoing_title" = "検証の送信"; +"key_verification_tile_request_outgoing_title" = "認証を送信済"; // Tiles -"key_verification_tile_request_incoming_title" = "検証リクエスト"; +"key_verification_tile_request_incoming_title" = "認証の要求"; "key_verification_bootstrap_not_setup_message" = "まずはクロス署名を行う必要があります。"; // MARK: - Key Verification @@ -1052,7 +1052,7 @@ "pin_protection_settings_enable_pin" = "PINを有効にする"; "pin_protection_settings_section_header_with_biometrics" = "PINと%@"; "pin_protection_settings_section_header" = "PIN"; -"settings_mentions_and_keywords_encryption_notice" = "モバイルでは、暗号化されたルームでのメンションとキーワードの通知は受信できません。"; +"settings_mentions_and_keywords_encryption_notice" = "携帯端末では、暗号化されたルームでのメンションとキーワードの通知は受信できません。"; "settings_new_keyword" = "キーワードを追加"; "settings_your_keywords" = "以下でキーワードを指定できます"; "settings_mentions_and_keywords" = "メンションとキーワード"; @@ -1096,7 +1096,7 @@ "settings_call_invitations" = "通話への招待"; "settings_room_invitations" = "ルームへの招待"; "key_backup_setup_success_from_recovery_key_made_copy_action" = "コピーしました"; -"key_backup_setup_success_from_recovery_key_make_copy_action" = "コピー"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "コピーする"; "key_backup_setup_success_from_recovery_key_recovery_key_title" = "セキュリティーキー"; // Success from recovery key @@ -1124,3 +1124,24 @@ "space_participants_action_remove" = "このスペースから削除"; "accessibility_button_label" = "ボタン"; "ok" = "OK"; +"spaces_empty_space_detail" = "非公開で招待が必要なルームは表示されていません。"; +"spaces_empty_space_title" = "このスペースには(まだ)ルームがありません"; + +// MARK: - Favourites + +"favourites_empty_view_title" = "お気に入りのルームと連絡先"; +"call_transfer_dialpad" = "ダイヤルパッド"; + +// MARK: - Home + +"home_empty_view_title" = "%@へようこそ、\n%@"; +"threads_empty_tip" = "ヒント:メッセージをタップして「スレッド」を選択し、開始。"; +"threads_empty_info_all" = "スレッドを用いると、会話のテーマを保ったり、会話を追跡したりするのが容易になります。"; +"threads_empty_title" = "スレッドでディスカッションを整理して管理"; +"secure_key_backup_setup_intro_use_security_key_title" = "セキュリティーキーを使用"; + +// MARK: Secure backup setup + +// Intro + +"secure_key_backup_setup_intro_title" = "セキュアバックアップ"; From 6542d04d5013bfb3572defc21b751877aa46c2ee Mon Sep 17 00:00:00 2001 From: Doug Date: Sat, 19 Feb 2022 09:06:04 +0000 Subject: [PATCH 163/188] Expose room cells to voiceover on Home tab. --- .../Home/Views/AccessibleCollectionView.swift | 37 +++++++++++++++++++ .../Home/Views/RoomCollectionViewCell.m | 11 ++++++ .../Views/TableViewCellWithCollectionView.m | 5 +++ .../Views/TableViewCellWithCollectionView.xib | 11 ++++-- changelog.d/1433.bugfix | 1 + 5 files changed, 61 insertions(+), 4 deletions(-) create mode 100644 Riot/Modules/Home/Views/AccessibleCollectionView.swift create mode 100644 changelog.d/1433.bugfix diff --git a/Riot/Modules/Home/Views/AccessibleCollectionView.swift b/Riot/Modules/Home/Views/AccessibleCollectionView.swift new file mode 100644 index 000000000..9ac0d1f16 --- /dev/null +++ b/Riot/Modules/Home/Views/AccessibleCollectionView.swift @@ -0,0 +1,37 @@ +// +// Copyright 2021 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 + +/// A collection view that returns an accessibility element count equal to the number of +/// items in its first section. This allows voiceover user to swipe through the entire collection. +class AccessibleCollectionView: UICollectionView { + private var numberOfItemsInFirstSection = 0 + + override func accessibilityElementCount() -> Int { + return numberOfItemsInFirstSection + } + + override func numberOfItems(inSection section: Int) -> Int { + let numberOfItems = super.numberOfItems(inSection: section) + + if section == 0 { + numberOfItemsInFirstSection = numberOfItems + } + + return numberOfItems + } +} diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index f13d7bc3b..a6e115192 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -52,6 +52,8 @@ [path closePath]; // arrow top side arrowMaskLayer.path = path.CGPath; self.editionArrowView.layer.mask = arrowMaskLayer; + + self.isAccessibilityElement = YES; } - (void)customizeCollectionViewCellRendering @@ -86,6 +88,8 @@ self.roomTitle1.hidden = YES; self.roomTitle2.hidden = YES; + NSMutableString *accessibilityLabel = [self.roomTitle.text mutableCopy]; + // Check whether the room display name is an alias to keep visible the HS. if ([MXTools isMatrixRoomAlias:roomCellData.roomDisplayname]) { @@ -97,6 +101,7 @@ self.roomTitle1.text = [roomCellData.roomDisplayname substringToIndex:range.location + 1]; self.roomTitle2.hidden = NO; self.roomTitle2.text = [roomCellData.roomDisplayname substringFromIndex:range.location + 1]; + accessibilityLabel = [[NSString stringWithFormat:@"%@, %@", self.roomTitle1.text, self.roomTitle2.text] mutableCopy]; } } @@ -118,6 +123,10 @@ self.badgeLabel.hidden = NO; self.badgeLabel.badgeColor = roomCellData.highlightCount ? ThemeService.shared.theme.noticeColor : ThemeService.shared.theme.noticeSecondaryColor; self.badgeLabel.text = roomCellData.notificationCountStringValue; + + NSUInteger count = roomCellData.notificationCount; + NSString *newMessagesLabel = count == 1 ? [VectorL10n roomNewMessageNotification:count] : [VectorL10n roomNewMessagesNotification:count]; + [accessibilityLabel appendFormat:@", %@", newMessagesLabel]; } // Use bold font for the room title @@ -130,6 +139,8 @@ } + self.accessibilityLabel = accessibilityLabel; + [self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.avatarUrl roomId:roomCellData.roomIdentifier displayName:roomCellData.roomDisplayname diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m index 4da67b857..694a55089 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m @@ -30,6 +30,11 @@ static CGFloat const kEditionViewCornerRadius = 10.0; self.editionViewBottomConstraint.constant = 0; self.editionView.layer.masksToBounds = YES; + + // Hide both the cell and its collection view from voiceover. + // Instead we expose the individual cells as accessibility elements. + self.isAccessibilityElement = NO; + self.collectionView.isAccessibilityElement = NO; } - (void)customizeTableViewCellRendering diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.xib b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.xib index 2031df16a..518de25d1 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.xib +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.xib @@ -1,9 +1,9 @@ - + - + @@ -16,7 +16,7 @@ - + @@ -83,7 +83,7 @@ - + @@ -155,5 +155,8 @@ + + + diff --git a/changelog.d/1433.bugfix b/changelog.d/1433.bugfix new file mode 100644 index 000000000..c4a5d04c7 --- /dev/null +++ b/changelog.d/1433.bugfix @@ -0,0 +1 @@ +Home Tab: Initial support for navigating through the room lists using voiceover. \ No newline at end of file From 94e786106eba35347b51998ba8fa137fee09ad10 Mon Sep 17 00:00:00 2001 From: aringenbach <80891108+aringenbach@users.noreply.github.com> Date: Mon, 21 Feb 2022 10:41:03 +0100 Subject: [PATCH 164/188] Update create room avatar placeholder & add remove button (#5635) * Update create room avatar placeholder & add remove button * Remove unnecessary set corner radius * Add create room cells height to constants Co-authored-by: Arnaud Ringenbach --- .../capture_avatar.imageset/Contents.json | 39 +++++++++++- .../capture_avatar.imageset/Group 3153.png | Bin 1494 -> 0 bytes .../capture_avatar.imageset/Group 3153@2x.png | Bin 2758 -> 0 bytes .../capture_avatar.imageset/Group 3153@3x.png | Bin 4082 -> 0 bytes .../capture_avatar.png | Bin 0 -> 1914 bytes .../capture_avatar@2x.png | Bin 0 -> 3528 bytes .../capture_avatar@3x.png | Bin 0 -> 5405 bytes .../capture_avatar_dark.png | Bin 0 -> 1993 bytes .../capture_avatar_dark@2x.png | Bin 0 -> 3701 bytes .../capture_avatar_dark@3x.png | Bin 0 -> 5706 bytes .../delete_avatar.imageset/Contents.json | 56 ++++++++++++++++++ .../delete_avatar.imageset/delete_avatar.png | Bin 0 -> 1079 bytes .../delete_avatar@2x.png | Bin 0 -> 2438 bytes .../delete_avatar@3x.png | Bin 0 -> 4291 bytes .../delete_avatar_dark.png | Bin 0 -> 1350 bytes .../delete_avatar_dark@2x.png | Bin 0 -> 3133 bytes .../delete_avatar_dark@3x.png | Bin 0 -> 5537 bytes Riot/Generated/Images.swift | 1 + .../Cells/ChooseAvatarTableViewCell.swift | 19 +++++- .../Cells/ChooseAvatarTableViewCell.xib | 46 ++++++++------ .../EnterNewRoomDetailsViewAction.swift | 3 +- .../EnterNewRoomDetailsViewController.swift | 20 +++---- .../EnterNewRoomDetailsViewModel.swift | 7 +++ .../Models/RoomCreationParameters.swift | 3 +- changelog.d/5251.change | 1 + 25 files changed, 157 insertions(+), 38 deletions(-) delete mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153.png delete mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153@2x.png delete mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153@3x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar@2x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar@3x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar_dark.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar_dark@2x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar_dark@3x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar@2x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar@3x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark@2x.png create mode 100644 Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark@3x.png create mode 100644 changelog.d/5251.change diff --git a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Contents.json b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Contents.json index abf2a35a2..4d5b7ef83 100644 --- a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Contents.json +++ b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Contents.json @@ -1,17 +1,50 @@ { "images" : [ { - "filename" : "Group 3153.png", + "filename" : "capture_avatar.png", "idiom" : "universal", "scale" : "1x" }, { - "filename" : "Group 3153@2x.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "capture_avatar_dark.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "capture_avatar@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "Group 3153@3x.png", + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "capture_avatar_dark@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "capture_avatar@3x.png", + "idiom" : "universal", + "scale" : "3x" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "filename" : "capture_avatar_dark@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153.png b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153.png deleted file mode 100644 index 621edca32e530f207336dfa9f8a9306ed034c76b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1494 zcmeAS@N?(olHy`uVBq!ia0vp^k|4~%1|*NXY)uAIEa{HEjtmSN`?>!lvI6-E$sR$z z3=CCj3=9n|3=F@3LJcn%7)lKo7+xhXFj&oCU=S~uvn$XBDAAG{;hE;^%b*2hb1<+n z3NbJPS&Tr)z$nE4G7ZRL@M4sPvx68lplX;H7}_%#SfFa6fHVkr05M1pgl1mAh%j*h z6I`|A0%imoq;2)dU$H=nv%n*=n1O*?7=#%aX3dcRniiQE5>XQ2>tmIipR1RclAn~S zSCLx)(#2p?VFhI7rj{fsROII56h?X&sHg;q@=(~U%$M(T(8_%FTW^V-_X+1Qs2Nx-^fT8 zs6w~6GOr}DLN~8i8Da>`9GBGM=`oxCP&-a*{wU7VzhnL)mPGx@7m*{0+$|q{QY;iv~zoG z$wkF|LJRz^JYd!rRbjc@;Y9TI5{u6@oqAaCB6(wk*V3TKBQLxxPTi~jp|xwzw;0KUd5Y%7 zvw3u;>u-4QNsIemL}U=uFEXq@{#f#wRPV9GqaMM_&)+&6eqF*zQ0k42RJ^^(nyS6`7OGj_JhJ*l zlYm(7`jaUaE1K52B;C1RzN-B?du@r;UCViK?2He@6*Z=v;+nBe`sPUy_O%RGtV{H? zzP@|+E^4*o!{4*-Jvw`O9k%~UqU}z`6)78Hj6`A zd{cyu?U(g+U7@m$J#{UY!nCGV`F;L)OoE-A{UEblrTCR+Z0$ELa%Rn5`K9gf!}eCE z#IAoOJN$3Vbx}NETCliFokiaBlDpLhqX+~cE>s|yquSp z*A-g0=VVG!$@YfzK@&N`J=G?QZt2|P&JnAjEgVUZugMp0u_l2p00i_>zopr E04L`<(EtDd diff --git a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153@2x.png b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153@2x.png deleted file mode 100644 index 8ea43080b9da954fd7aa5929bb6158737a94947e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2758 zcmY*bXIN9q7Ci|?dPgM$h@scSpeP}LXb?gV2I&Yw=!B900Y!=+f{GLy1f>X4>hr!g=bN+F>{)xQ*>nD!Br6LeejW%9008_rW2`kZqF9rQ zllhj`zg)o#>|O@u1^`fTop;-fgSm#e8(W(LK%@cy#KZ%@4`wQc0RW*$09bGZ0Q4OI z*cX&tkH;`K;)!-RPjhoXg^9TU4v+}I#zY|I1Arg^OO1&D6OiN|Yze^Iq7T6S zo8!QYtdYu`teRhuEf@5!VlMa(88Ucs>q)_~H z;dbU$uoHnHMA%`CLmEi99uEu#!-RNvqOGwff0r{?x^Qm_B?yf`golS~gllR9hIkx^`Ec;93zdBeV**(N3h~g7Sg0Xbn&IX23bm4H8(Vy|_ zoD?6=f1OC=-)%7)M6h-c2Q`q0KibSv3@eMa4Dlf{omu*N2QfdH|CjsigF&#&|K~8j zI{letwyMX2LHxNkJsz_*MSJGQH^N~J2;LlH4vzi=!~OTj-%dwPxlF+KdIyM$b&j4b zdux4l!q_CP?FtWKA)_Pyh;-5hOi%bkzKArEUGB1AepPE0SBFYhzH+=3xQc^!sCtc) zW19YPBdXG?`rJU+;9}TJ{cbO1zJL9n`KSH*mEvb33o;*+xD`Jdeqc_+_)R=oe@E-J zwYB}|PLhu{%M2~e@#;>I@)a03;#IJBM4c03XOFtDz43MHq><6<=J2Ig-Nt7mFAedR zUo^&_m72Do3vPvlh3R>K=Aqf9MqZEdM3Oa4D@0OtEIBRiqQ&dU9|tT@`#xwrKYkQS z>V^gii`m^u&!^xY6nOHbW*H})S-jxq_bJNV-Cd`(GN5~;LuexE{P}G%m`)(X;$t4D zXW0o!7p_)A-?1QY_9X1{R0A}m8?KSw-#-JoBlfX?v$7K=8uIpvxTN?JD) zD|$^&oSHlMq3*70OAaA=E-YF5juN-NVb+QYd1MH%T(Yw;k}3%PCSp@W?7Ou&Gc$8L zrbfFa$z#iab|7%l+eecjb2FKsXr9q>Bla9Jmo4YdT*R5@xgZK$c7P0E+=9B`j5~4hkhBxs1Gfj_>@zoCys_JzWBB?S=%AL?+v#xhwXvJL zhV9S9;dZGX(NOB8EE-M5zJ@f*PdQY4Ms9F>b5#=F*%8hC?#)o3;oy3-CkMOj;^$pc z=r$b}q<$n$QzcFz;IERBG_7|D-cK~W2D~{qIF{=9J!X2xt8V}VHKl!HHsbm9A$W?{ z7Ktypc^4F1{{?!d@k9OSGIHI7=<4HsJdwVB5J`eXe;kx0_Eg!K3+sW`Sm8Dxf zk~X&L*>VZ6NsY9XlNtV8)avBP!6$t|?Fo5SO7OHNMmn7F z&yoWUzudu&PUw64O;@0tM*?aGQCU?dRzTByx8T(%IO1LGVax8TxrWTDMb~2 zqN1W7QJH0xeI(J*ts`2^aY%Xk7JEy1LZ}7p=xmr)Mxlh1(B)oo#}mB=x(6=y=nsTW z4v3&$Zls@s{?O?>w9O({P$O9PsInh3b^3 z!8-mco97?Cyp)bF#iQO88h5%ZT$PZP5RZ1LQ$aUa^Wqq@kTYSn=Io7Lt*gGvng)_@ zdE+CP9^-9o$8BM2C-+>xka(AJ-Ap!k9MQY1;6K=#^qq8yqIK@vIsJBR@AA5yOo;w z?4MZDtHuZ}%$~HKh8%lZ#RT~HJQ@gm zD|Sv!PTpV5UN!OU*QGA4^9cw@Wo>eqLB zu{|fq{FnUR)%mJMlv8^zItSgadrL7}(3iJ*B3jrc@Yz_ZAEB%q>l!DYC@6D5q~iHa zZLm9l-HK(~!?-KQMN-R8g|3fCF7&D@FP0AQ6rQE@4sYOZ8zFm2a)^~>zU)YksS}x1 zo-c+|pyw?i-^G9z(g!|=t=)G1luK~+b~0$J+4;TPQ_Mg?!sy=;E>Y<>hir$&mTIQ9If5n=8an h--p>FLH#$@5ZieR2sH;6W7gjp&d>t;=(ua#e*mUJqPqY9 diff --git a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153@3x.png b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/Group 3153@3x.png deleted file mode 100644 index c43b02a019566f57a25d57bd61c1b335fa9ec97e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4082 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 Ms_Lm!DLaJ!4~}0>j{pDw diff --git a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar.png b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar.png new file mode 100644 index 0000000000000000000000000000000000000000..ee020a419e718a93306e523c0b476040a456648f GIT binary patch literal 1914 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 bf0W4o+0)D*(#znI00000NkvXXu0mjfmRqGt literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar_dark@2x.png b/Riot/Assets/Images.xcassets/CreateRoom/capture_avatar.imageset/capture_avatar_dark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..3dd16d8a809db8b56931f4b95c6991361e79e9bc GIT binary patch literal 3701 zcmV-*4vO)KP)005u}1^@s6i_d2*00009a7bBm000&x z000&x0ZCFM@Bjb+0drDELIAGL9O(c600d`2O+f$vv5yPgoNUNgg`tb7CaQFlnqd+Dy_0n?a;0ViJX9L_hpWACo_GP^t1 zo$n_(zGS_QxBvdX%lXbZ0!$gYuBXuTX&oY=-sE=8GzS6k8401QzfM7jRN;|QukjRF z_4q8L%vv7{WQ8=(o0_%=Db7RY4P*XH28@M3jIqSFW$U;S)2MnO?ouzuXdPj>i$q4f z`i2BfLqi(Zu4W9w$RcLMN`M7-+qzdnepHIYgl}SViV~%O%$P!(!D>zk@?8TRPR9#S zA08RkOpHm1arN7dBT7i5rH11$&6AxPwmVXQ`tY!>naO=BZ<`FA%e9O&gp@O8&OF>n z&e$;mw8HDBZrmqK?2Vk$H48bTkkiK5xub|Ukr&{G+u;DHN{todib$Ke{Gq72Vq^tK zxt+-4V8^?iLsWR4j-n7FCqNcneWE7B$Ow=^t;i>ju<)D_6(NRRfK*&)U0V;Tr27Dv zrU|cV#{%My*3bHR3yaSRNp{0d+FoT2pOStKz-L8YH3V+nT6*z(vYk9 zhr{HC8bZd0o?9q(nlSOx@IfUFC*vARq#DK(27Zfso>`nMLa{&(RzVnD`vwR0k zR2lE>?bnx=KAwRGcq+hR*ySEy)KT4v-rk#2%S#vk443gtfSmJn7y=J?5sp0(Ad9bK zaXlw=U4XQ%tHk#bm`-K9udm-&c4@ZI)ulLVj*mvEn2tx9c-UB&O`}a*TM4n&c7-?w zCKd<{$8>#IN1M1JK$>b1X5s`b<$#F`DbbZwA{=dNN!1kr(nuAHFNO$=YF+uZrmNd7 zLW)Jl6qtCT+B2z}`Y*RS)Y?`NV_R>hMoaVINR*Y0j*mawf5T*&)ad`ux9L<_VW zf(tvV#9lBAA#h8oZ$M-(T}(IkZ7om?y^CO&3ZyjeZsst}mO^kb^fJsQtOEs_py?2- zRy!uuYR4oPrWyizGgWa@A-E8Fx#7$-L{-JfK_}Zhn+m~7d{Znw#sMj(4Qj^@$b|>f zEUGs+*r+$?*Z~Xf$1u)Oy}=_59|H%l`!TK3Xl%=o1G4)uts(^K=7J3!kll}ImwGPP z&;i-~n0Be>f^{8`-H&mLS`~3!2W0nSTw_aevf7s$h2SwTj0>nxyT97_eoX<=nlG<< zFfNk9r*e~(Urg3|w1Bn`F=uGUPTX_v{TSN06Foh>XouycCA@!b0dsTj;LPkhh$F%j z6Y5>r@qAT_khm8gB(|rXe#R1@7myf#`HP=pd3gzOqp}#OI*ygqQA0rP(|3-nf4)h8g+r=^ju_&X_-yEBQK*j>LRWu`+n;TAKuwGzhETE5 z)9b$*QJ(2lt{GaiIszHHw5pRG~21D5v_<%rX4q?jPyqHZU-VtRk$Nnp^tv)F$B%mC%+l9ideH^a9JaIaMuXk z(;M0Av&cyv{o-Rag-9XzwZFWIYu8q+&+WEL5XDC|;?q@4s$dBn5g{y}@o;V(+NC=e{UZ zqrqXXgz#M-4WQ=kAAbK^$0JkpIC`U132V}Y9kD8f98d@rU>z=e@Bv===}%gk*P{?k z!vz;2u`=O5#YVJb0oK5tPO(S0T6&JL?!Lj_*bi5sa}!FE6vUABef3lu}JUn+0)RJIXcnvU- zE)ifNjl>!lXHcVh59f64v6jrNPs4B_!uX5Kkmkz9v80qUU>F||5>)h7&I5`J7{&)o zO&+KBFaPN@Mn|>6=FKr2y|4WV}V&s5Lh42{FU( zfYG>uAXq~E8ksU}f4E72#=>km?CqGhJUFqS(+Kb0V`&)kXV#0|s=MMOhYT2ZR(a zgJE1krFN6X*}1axuJ*|Y*Sn^{`-K_TP{l`u_=uVUq^7hA0vaWaysMT=cxjGl6Cvfaz4TT|!_%=;<#GrN(+0KNk7y`BYh{F8kZF;6 z?ngK}ACO&;X_b2JM>rB7yCBmFjogoLd_t;BtbGFv(*%v&k8mtNs)$u6=Dr}~2q*4G zGs}0Z|R!qs7%T* zK_C|w&&~}weRNCLG)S1wgJG&5SM!fF^Z2GhuuXR9e)wTvzToIr( zzR&q!%#e$e_Zf!K)_-%?u4}c{icPq8rvVdYq~b{@YrTzd^}b*l+mh1cshJK(6&){> z9DU5}Xr8 z6D#b_&;AG=;)?(Y7Gb2I!{J`^BIm2bHvtls2z&Z3^YB8bQ9Wk!Sz~_gFnpk`dB9fD zcil0nM0ia7cpXfbSXSbD#H}W?69N$+p$`x1!c3fC5rzaQPsv=~mF2Z&@HGUNV$Bk6 z-F6h3+0DJeK#|sd@7#Z%HH?Li;4^_aU@7{}JqLs)4yq4RVEklRt?RyMyys88SB+2z zkl>K)GXaI%N<1mhLHwOE`GIsp>whMqvVUK%i8@UzNoL?{JlquMo- zs$FxCh1fQM=X$jWtO|C5HCx!G*7X@z51kaZa$3=5^4u5g~Bq-gvt-a zJ}`|agxlQOvq2Xbjfji@ZCHqPDF{!hBE!1%H2g$PfHo||G9o8Do5%{#WT)%p>-F>-1(@_Gnv0O2)9Z)Tt z3H2*(FMc`7zpJEM>?P!{qwIFo=tu#ULZe^Mv@w{NC~?NH|K8SR!Iskr{7wDa(^1Rq zoYL_EEX8uhT-PWP=7j1k-X%89HVpE0D7l$hxtz?;sP^n>0?4p;57v$}81-X?VKWLe@2kHFTcbn#f(cu@$ju`;AKfk{CkTvS+jf?^SJ)&nHc85okhUe|P5e1Y!d9=; z$3)hDw9I<%*Ons^Isc*3@m>qc2`O`~5a-p~v+Csp72F)Ro4t5 z^U}M~I@gB~*TD-fEVpZidLlhR>8vd4f>)Cra`T1V2=h`1aTQ*d*`;0T&HD(n;&rtV z=4&9tWiZ|~2g1AvAtrzMqabS!!fPIcIprbdF|TklFQ^~G4g#a4In1dH@nW?Z1*?RS z>IuEuo$K1`IAf{VKAEAEQC;VqqU*ZH_d^aUjqC@P@_sV@(Wd+{qFIPP3oK4}?d-~E(H%QlS*adFea8z^2ubj+$=8&#e5rjHO{h#Xh1Gq3wMbm-5R z5Z}CE^A0tAgaAWKRFH-BK0ohBb4C=lxPT=|yiC}21o0B;dAD8nf|vFo_5+N~3(zrK zH`=CikhKo+!1^tFq@ZUAptHPv%6)w|{Oat?#n(tP+J<;w!QBfww`je@LAh!J2gjwV6YBE-dM zB%Hzl<`H73)6-8K4>9I}!Eha)NA75d`6Lb%;BOIt*}NcUKYRVpbC)l@Low^vE++ft z-?&d?G6xADIiz&y&bUw1>_~|H?Sx&&30J5<^32M)`CH@M#u)o9rp5ih2rwj4ueXiS z-e^-yVh^z>WN@4;B%J6M-Cf_In8aGx^3KE(;voV^Izjz$ZJ3BH#Hd6=>InLL92M(W z3R@^-L5f9Q=!$$y%qLT#kOe7LEOZS;_WX}L#C)+C3R#eDqTlK+JVz0UbWCio-?UQ| zvM>$?;PG+xh7-Bji>E1Mk&TIQJ~Y4*k&KTc>rQ(YoRP2z07`nJm_LrBJI&Kc>J`q% z0;nX&4tv@u^zJmKlK>hDwObu}cUp~uUmye+pq@~>)uD#it45R1{@M$GjuSL&-@N5M z3PEVyX;h;Dnx?wdT?6f2qZ(REY!$k9A;17l=?!BMNGL6Fv6wYY0MINcrF*M0d1{PW z6iQ310=$O+pcO)p^|#c9wnOX}vnZ4SIzTFMk!#)HFtw=d5DOumCje-N5SDCt%Bigo z7pIhL0)RFN+upFbrRmwW3S0dfHcunO0HJAV%Bkg+7_Bfs=z3|{eACw%wH#uMg#p5+ zy2g(;dkRQPAx0|<5SgZ1T@(POmGpAsnzgiM?ON*X?V~7NxbOkZ&dkt< z>NRvsmafb1RIgvI^?*Pj76F=ch*nR}a=PR9w$UA5+(tdims6ZL$W!Oe(ocT$LzSTDU;UM!1#7fG!uD)8kn;PB#kzIAePC?>sg4l6)`J0bF zNt*|^P*-<1>0sdIb+mQs?R08loUUB?lpq#@GVayf<%=WLKH0FaB_v^PxC1!AUw`Z` zskblMac?VnSFNJ2f8(2xkI7+?Ao;agpR3yvtAf^$5Y{sUvC=ufCCgW=pv{{H(IUr2 zWV5}iM{_e5oyyNNXo;Sw_#%C3Bh>88kCH^-Zi4wv4o+MN~|7k4Yw(d-luKlYyO_t$-li3P24yo3F& zyRfh?27+8`xcmdv$HY?HLQqpHYnYe!)c*f)fVbXm{xr=Oifga^-n-PSiHVa{KfY=67UNsta$i!GD^-6;BU-!O|S&-?d2lX@-~9Up&b}lN4Kdl za1sMtiH9D?jy6C1DEFzVcyomx8!gJo_R379SV% z_M4+^|4~SY+37Rm-W16-A+|RT4hxswAn4Iw$cz6k`ZG$aQeLf!kEXsQ<}Mn#(B@dP=GW3&a1<5Y>Ea5Iz!w`Q6;>OW zC&gpqEa!HyCGMHWc$f&Suz>~!Zl=`gp0gK2To5*a(c1yjDx2;jLI~CX@nXEFK$J|9C70CHoy-*_`u%Lk=V76Umjoi~h1j1Xo+mILZwlaj&PU&Sx8c@34zzcJ!|i6>Isw=4Lrgtavg8K3 zZyYqm`*xeX1e_ns+xqy01D%w!zS5?c+%B8INEcLh`3K)W*!H$O4m5A?<39x0y=9h$ z_Y;G@j=VKWul&QeL)}-)VSeeaUi8ip12gz7ab9F`IG$O!#pIW${Kw&gUO_BLCvhf~ zRs3H}FBv520LT5`f%c#~Z5ZxC#~CdCZ=q|gH$TK!H*EwyTk0pT#osdin5*71IC@r7 z0xhvY_)@k`9NWs5q;cgM^n?%_g6Dxdd80zDTP&dS5Mo0d(O_JPBA1>JVgvB{XC3Y} zLTjuigxCN&-FScy>jxn=z&VYAGttH+au5xK*Z?|R5&GeW7rbgU=)(`O6b^xwcs#5X zDQO1RmFh&ICDz=h8eZp#mRK(cvF3DKDTUQrdhtV?kq!X_l!nXEP2z{R;N}Rlq~qrN ziY+lhtSde?M>lAR_2P&4N)JM;snW@my69Q40;gnZ#tX6IjB$t&WKHQ5nl(4B zA<#=%by^_An$qdI)f8VNswp|P7-ESEwXSZ{C^$HuS}#(H+(L+@kmm`s#A9L|!o#gF zj53Q7khIFW)A?l%f!26z{MASPJl1*Ro}T5n)U_kN1Y zJ@?&@0P8EqxxIE5lO%Mh4Zt@SesyQGEi$*j4?grT=7lvTi+Q~!#FFR)fe|(jZlPUI zJ{`#znZG7?p%Gy1d3mkaPb|<98-%;LyPkSF)T%XqE&iHo)?$6M<|GMuoZqOpS)41> zI48g)+@=2V_WS7zDtvq{^s!^_dHt-WzJ}^L-=@0g{53HCHHefy<5!~cKV#z*JyiIfu)C%qFm_+Yywp%#LAv%NI1ZXFE_tn<3&CT}m4>fiV5(@#>$ z$muiVUW?nc^i$-hXb%w>iNnZ+FMeShYCfln1I?e~4gJei%Zok1W>bH+MoMol39g(7s70WgYN0Gg9zxg(`_mWDW=IYa=Ux2taLme^mph0PEE z`jTUgbJ{7rS9Lx~Rr?MT0BA{6tgNg)DeQ_70stLJ*OJ!^d8>!GkQpHW(9_jrZ;hlorOt0Gd%#OG|TEd!e)_q;jeWH~yI?RlhS=j#hrC zW{92BT*6M@RMQ2GF7$?A((^l$jx%{`$zrU!Tb3lr1C%nS#!nKM<^7}YQ5r}ost$4M z?>ltUSKK;!^j&nR4Kj22GEJR3ODP~#Agea2bwli&9Unj&q6w6_!e8WaA6Gq%wqb~KxsR^&_N^W!K{llfkF~h+xpL*N zP`0<1gb)Os!{O!M$-n>WztFqy{FKtdTi`Kus%A^vMM1uZnqU@E3{whmi_9;)sh(S9 zoI%wYJno%3dp0HG-)r!Jc>C);AW+j{+e2BgY<`+jeD)SVXUOU4GZO>#9ueqhOJ1v~ zn)K8axBxm$1lYsS#QC)Degc3vNjG13vC)G9huE8=!p5Qg8MW0ED3VR+zPXqqx5m(|w8nAPg;Djf(oUu zRWA4O$GL3p^;d-ucM||ql2XWLopb;58igdX)6mha2B_-bbQ^QR)r8)iEn7CYS_Tp(Q0s$y4>X@APYl=W*E%5?x5r~{7fYegY z|NJMB9rql0h`mK1R^d*<_!!b@R?Zdvz;T?&4wsCyJ6(clCrGK#r<1CQCB!T@bLkz7 zk0C|4khR-6Gw~8dEcRQoF@FrHAm#hhlM`Dh2GJL`D){rqD0D%Rsrlf1;g2aMvA4v` z-nh{gZrA&SlQJQBR3U5r)+pwKYl*!jX5K;&mw4%!B!J|QvQT&=&H%I63R{(OGZ!6I zvHm$K){qcfiGI?VJavF#*0B&XuVTGwwJKQCFaek=wn}t09St$dUA{PiAcMh*0UnQR zMOGsn4>9wDe1olmjLXZxB*it+liUTUZk5Pwd6JmxSgCYC? zpE>ymX+WzGGXxnlr&WNNb|Gd6GH6P>05dH^%)B6D!vyG~RK)7|7`T$QA!fOmi?3n& z2{hnOBXzh6U5nNsW@Yop+o(fpy&=^)J`dc8_913oko!J+UI?+B5M+qYtd#C!&g4Yf z_a#Nis6g23Hw~#Ee@}he{R9vxIjsi44>*&j#z=F^A;{1SUcfOz z`N9Lvl>P;*S`yU_wKojDp#DM65xUpVn12$-|LQ$`6hz{l?5JKt18V3i9aE-{f-t^2 zUCFy`V&&QcWVt=6>h(K>Rv8v~>z^tAi-(=5Nrw_5(NAy`y`ac%eGM*N)su==3S;F| z^QMky?vuSyUTW4!sd-X+W935E_td|b_b4OG$>&#|$$cs*W8Yd*_hh!$Z`vt@cn)3c z#NrDHa+2f|&Y6i7UCuIO$mAju0g!hk1ZlXxj7S#n3QtIhB;43Br|JjT1t!4t4WrPi6qdR$-?SiAf} zm8HhJS3h|bt!{Jh#0x<&(7XI2b%jm%xdx$HU7@~f*T$@xgxaC<SI00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yPJ`@&2KGaL)V{bvAJqF=R2odxgEDZ$7f-r-Eiol2JrCy2x z8x&aty-6A-3zN*5vsAV@w|n}1*R!1S&Rzff;N#qT?)kpo`F`ho=Um2YLI_a>3&SF? zs945~?7IXDv8@7v)ycqi@nBOEfHRj_%!u_PPQGjd;8NDjf@0Wbm6>h@3>k};Buyrh zd&S1&ErvK^)|DbxFyLXK=i7nL;z8dtkw_-jWT0`+Uc6b=Zx}{|mTv`7-ZP(^oUB88 zu5dP^(I0GZ_#3-({|QT`QkFA*9T{NHUq;yA(6?3JIOivahK79kUS&|d!>&ORIT~*00oIh(7g4fsAU(D|?iKYIS7`G&L=^6sISdtf#`p{Z3 zBWpBjE^AeGDzRA1(bm@1jc47;vCQFMhY#&%Uq`;1y5|b z2Ib20GS`rKf|WorwP0ra^HwY7C291a_%)XmM!ytcNsbgi)^*$*Dr zx8mKUJMFl#@$qpEQj;e~<_H7=`ozS<7gbe*YdPnysY}<*%y;exn0tWUiveo>Q51z@ zld5LMCi&FV6whQbV|GbN-eMch3h8uukoa?aL@b(`npjOujWItzKVX;CXJ)L~B^TIK zufXxY!(3y?EFiIHZ*RY6mox{vhJLT z{ho@7iU2uwb#)z|o}PXxmi{J6Vs38kLq|u)3Ha`jF)HN#QCJBma-auBj=N!Xot>R0 zhKGl*QQ&+Pa4`Hp-$$(Ft(KOSBN!W!J^@Mqt<#E>uR%`IXqAnaxT+#T}`D@ zN}eCJxw_1fx!vwX)N2|(X}qT~w?*7c!Y*;{8<9Jt0;ZLhm#e6C1$%(wUy8;F^cm>O zdOV(trfF$RFoTV?h;N3pb%V?79kkruJ&JIlZ xWnjvl%EQ^%*jPr!mXxtgxRF_{ww3-gP<8+S002ovPDHLkV1f!O57Ynv literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar@2x.png b/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..2d2aa1c8f14af9b43c91999eb3bbd4427f442e9e GIT binary patch literal 2438 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 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark.png b/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..3326e8487e3e3dd23b045c0959117f72349554c2 GIT binary patch literal 1350 zcmV-M1-bf(P)ykaxi8Oi`lpuBH>^l@uVjc6C>+S_Bu>7CYr2-#CX|& ztMTN)=*f8FwqX@ljp5>jWg#%gj4-|1Gt=Ew<$Jx|?9j~iH17J6m!7VwuJ5bwy;oJk z-~`s0&2~l%aY;&fo&n2BfUMoYU>_v=O#=HN6ov11*4NjA&dGud>Kz(7B@D5I!^eY+ z$62qbLMiO*v?ikXb>d2)JCnU6O!;eIaQj1egEMinH#10Tfj?KDzQ-OP%;WcYcnD(* z3dOBk1;&^>5dm5`12GSez)=JMA%tMPOlQ) z9AJe)feA(Cz2GlgcoE)w>urc95`IATxL0Rh^EP)11HMFXdx3rg;ETn@Q}}q@+dll% z({TFCS(ttQ@&idsOitP0r_Vgwq*tEr@9$4LB$^T+W=vShRI|yy`DzI^Z*RcBz+h7n z1U~V~6qHJPuyEy*W>bJE)pw?+rxhaMn(85-wk1;^Mu7S_sl2^JTVBl z(NX)I+P&cAQVAYl?B|v1UqeGO+5|`vWToux?y7ptyn;=!W?wfW(c71Si!Vbw@{v=GqI#fV)6kw=;f(nEZ?WrfR?_3aY zin(8P95cbM>UXu3;o)IXE|&#qa%?9w^!nAH;I2_l1X04^;>YgpZiqx8lEO}A6UgWD zZe0o?s(85&*S#M<_xw5EZ1<9g$Kyx(G3MVM>}_w*S+KUYMg$0xHI^ZTBa%!e6O4t2 zqiyX!;d{!RAl=n{FWV8Qm34J>A=x7&EA_i~UXs%ME0IXlMn*>JxDRk>2!V85U@lme zRlCLc(WAJGs}BNB<^c!Jt$CUg=jO#?k@xiUNa>V8HNvOychQfxSaQ>Tfs;<{Fv=NA76yEHhlNsV*!Lj<39 z0PT5k!xOl8;f^{aK#DktVWC8ps;XwKRKz>&?t7KS(0EKXV`gT?@&gZSls9;nvz0)P;9+7XXf~UT zk>l@}(`F|u+&^Ul{q;MExs$56LL#F&#N4pB{=XaZ5c<#dFRp2>|E4We9{>OV07*qo IM6N<$f*t9CMgRZ+ literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark@2x.png b/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..119522a87e3b08ba37ea057a5ba0aec7f5713ae4 GIT binary patch literal 3133 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 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark@3x.png b/Riot/Assets/Images.xcassets/CreateRoom/delete_avatar.imageset/delete_avatar_dark@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..2f92588820ce31c052fe0f5a8874cb9b274425dd GIT binary patch literal 5537 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 - + - + @@ -18,39 +18,45 @@ - + - - + + - - - - - - - - + + - - + - + + - @@ -64,11 +70,13 @@ +
- + +
diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewAction.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewAction.swift index 93dc56de1..8833b80b9 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewAction.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewAction.swift @@ -16,12 +16,13 @@ limitations under the License. */ -import Foundation +import UIKit /// EnterNewRoomDetailsViewController view actions exposed to view model enum EnterNewRoomDetailsViewAction { case loadData case chooseAvatar(sourceView: UIView) + case removeAvatar case cancel case create } diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift index 63fe65197..914f3ce67 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewController.swift @@ -31,6 +31,8 @@ final class EnterNewRoomDetailsViewController: UIViewController { static let roomNameMaximumNumberOfChars = 50 static let roomAddressMaximumNumberOfChars = 50 static let roomTopicMaximumNumberOfChars = 250 + static let chooseAvatarTableViewCellHeight: CGFloat = 140 + static let textViewTableViewCellHeight: CGFloat = 150 } // MARK: - Properties @@ -481,9 +483,9 @@ extension EnterNewRoomDetailsViewController: UITableViewDelegate { switch row.type { case .avatar: - return 100 + return Constants.chooseAvatarTableViewCellHeight case .textView: - return 150 + return Constants.textViewTableViewCellHeight default: return UITableView.automaticDimension } @@ -512,7 +514,11 @@ extension EnterNewRoomDetailsViewController: ChooseAvatarTableViewCellDelegate { func chooseAvatarTableViewCellDidTapChooseAvatar(_ cell: ChooseAvatarTableViewCell, sourceView: UIView) { viewModel.process(viewAction: .chooseAvatar(sourceView: sourceView)) } - + + func chooseAvatarTableViewCellDidTapRemoveAvatar(_ cell: ChooseAvatarTableViewCell) { + viewModel.process(viewAction: .removeAvatar) + } + } // MARK: - EnterNewRoomDetailsViewModelViewDelegate @@ -532,14 +538,6 @@ extension EnterNewRoomDetailsViewController: UITextFieldDelegate { switch textField.tag { case Constants.roomNameTextFieldTag: viewModel.roomCreationParameters.name = textField.text - if viewModel.roomCreationParameters.userSelectedAvatar == nil { - // if no image selected by the user, set initials as image - let avatar = AvatarGenerator.generateAvatar(forMatrixItem: nil, - withDisplayName: textField.text, - size: 60, - andFontSize: 30) - viewModel.roomCreationParameters.initialsAvatar = avatar - } case Constants.roomAddressTextFieldTag: viewModel.roomCreationParameters.address = textField.text default: diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift index 0e4721b6e..407e0366b 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModel.swift @@ -62,6 +62,8 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType { self.loadData() case .chooseAvatar(let sourceView): self.chooseAvatar(sourceView: sourceView) + case .removeAvatar: + self.removeAvatar() case .cancel: self.cancelOperations() self.coordinatorDelegate?.enterNewRoomDetailsViewModelDidCancel(self) @@ -79,6 +81,11 @@ final class EnterNewRoomDetailsViewModel: EnterNewRoomDetailsViewModelType { private func chooseAvatar(sourceView: UIView) { self.coordinatorDelegate?.enterNewRoomDetailsViewModel(self, didTapChooseAvatar: sourceView) } + + private func removeAvatar() { + self.roomCreationParameters.userSelectedAvatar = nil + self.process(viewAction: .loadData) + } private func fixRoomAlias(alias: String?) -> String? { guard var alias = alias else { return nil } diff --git a/Riot/Modules/CreateRoom/Models/RoomCreationParameters.swift b/Riot/Modules/CreateRoom/Models/RoomCreationParameters.swift index f7149fc3a..c84f8eb27 100644 --- a/Riot/Modules/CreateRoom/Models/RoomCreationParameters.swift +++ b/Riot/Modules/CreateRoom/Models/RoomCreationParameters.swift @@ -21,7 +21,7 @@ struct RoomCreationParameters { var topic: String? var address: String? var avatarImage: UIImage? { - return userSelectedAvatar ?? initialsAvatar + return userSelectedAvatar } var isEncrypted: Bool = false var isPublic: Bool = false { @@ -36,5 +36,4 @@ struct RoomCreationParameters { var showInDirectory: Bool = false var userSelectedAvatar: UIImage? - var initialsAvatar: UIImage? } diff --git a/changelog.d/5251.change b/changelog.d/5251.change new file mode 100644 index 000000000..7526212a7 --- /dev/null +++ b/changelog.d/5251.change @@ -0,0 +1 @@ +Create Room: Update avatar placeholder & add remove button From 7304915fe61754d737ab3d2bc69131122b58d47e Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 21 Feb 2022 12:32:41 +0200 Subject: [PATCH 165/188] vector-im/element-ios/issues/5114 - Enabled poll editing and undisclosed polls. --- RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift | 3 +-- .../TimelinePoll/Coordinator/TimelinePollCoordinator.swift | 3 +-- changelog.d/5114.change | 2 +- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift index 7ea906593..c92acd3fa 100644 --- a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift +++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift @@ -35,8 +35,7 @@ struct PollEditForm: View { ScrollView { VStack(alignment: .leading, spacing: 32.0) { - // Intentionally disabled until platform parity. - // PollEditFormTypePicker(selectedType: $viewModel.type) + PollEditFormTypePicker(selectedType: $viewModel.type) VStack(alignment: .leading, spacing: 16.0) { Text(VectorL10n.pollEditFormPollQuestionOrTopic) diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift index 9502a6205..699cfec60 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/Coordinator/TimelinePollCoordinator.swift @@ -96,8 +96,7 @@ final class TimelinePollCoordinator: Coordinator, Presentable, PollAggregatorDel } func canEditPoll() -> Bool { - return false // Intentionally disabled until platform parity. - // return pollAggregator.poll.isClosed == false && pollAggregator.poll.totalAnswerCount == 0 + return pollAggregator.poll.isClosed == false && pollAggregator.poll.totalAnswerCount == 0 } func endPoll() { diff --git a/changelog.d/5114.change b/changelog.d/5114.change index 694524c66..b2b42307b 100644 --- a/changelog.d/5114.change +++ b/changelog.d/5114.change @@ -1 +1 @@ -Added support for unstable poll prefixes. \ No newline at end of file +Enabled poll editing and undisclosed polls. Added support for unstable poll prefixes. \ No newline at end of file From 3036601eee286c12f9b912d2a7ef9a140121d7f4 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 21 Feb 2022 13:50:27 +0200 Subject: [PATCH 166/188] vector-im/element-ios/issues/5114 - Fixed arithmetical exception errors when changing poll responses. --- .../Room/TimelinePoll/TimelinePollViewModel.swift | 11 ++++------- changelog.d/5114.bugfix | 1 + 2 files changed, 5 insertions(+), 7 deletions(-) create mode 100644 changelog.d/5114.bugfix diff --git a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift index e0574c0d7..a139442ef 100644 --- a/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift +++ b/RiotSwiftUI/Modules/Room/TimelinePoll/TimelinePollViewModel.swift @@ -81,11 +81,8 @@ class TimelinePollViewModel: TimelinePollViewModelType, TimelinePollViewModelPro state.poll.answerOptions.updateEach { answerOption in if answerOption.selected { answerOption.selected = false - - if(state.poll.answerOptions.count > 0) { - answerOption.count = answerOption.count - 1 - state.poll.totalAnswerCount -= 1 - } + answerOption.count = UInt(max(0, Int(answerOption.count) - 1)) + state.poll.totalAnswerCount = UInt(max(0, Int(state.poll.totalAnswerCount) - 1)) } if answerOption.id == selectedAnswerIdentifier { @@ -114,8 +111,8 @@ class TimelinePollViewModel: TimelinePollViewModelType, TimelinePollViewModelPro if answerOption.selected { answerOption.selected = false - answerOption.count -= 1 - state.poll.totalAnswerCount -= 1 + answerOption.count = UInt(max(0, Int(answerOption.count) - 1)) + state.poll.totalAnswerCount = UInt(max(0, Int(state.poll.totalAnswerCount) - 1)) } else { answerOption.selected = true answerOption.count += 1 diff --git a/changelog.d/5114.bugfix b/changelog.d/5114.bugfix new file mode 100644 index 000000000..cb283d2ae --- /dev/null +++ b/changelog.d/5114.bugfix @@ -0,0 +1 @@ +Fixed arithmetical exception errors when changing poll responses. \ No newline at end of file From d45a023edcfd5b53c4139680d0c70c6416702871 Mon Sep 17 00:00:00 2001 From: Johan Smits Date: Tue, 15 Feb 2022 18:51:58 +0000 Subject: [PATCH 167/188] Translated using Weblate (Dutch) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ --- Riot/Assets/nl.lproj/Vector.strings | 70 +++++++++++++++++++++-------- 1 file changed, 51 insertions(+), 19 deletions(-) diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 0152ef38c..ffe224e84 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -62,7 +62,7 @@ "auth_optional_phone_placeholder" = "Telefoonnummer (optioneel)"; "auth_phone_placeholder" = "Telefoonnummer"; "auth_repeat_password_placeholder" = "Wachtwoord herhalen"; -"auth_repeat_new_password_placeholder" = "Bevestig uw nieuwe wachtwoord"; +"auth_repeat_new_password_placeholder" = "Bevestig uw nieuwe Matrix account wachtwoord"; "auth_invalid_login_param" = "Onjuiste gebruikersnaam en/of wachtwoord"; "auth_invalid_user_name" = "Inlognamen mogen alleen letters, cijfers, punten, koppeltekens en onderstrepingstekens bevatten"; "auth_invalid_password" = "Het wachtwoord is te kort (min 6)"; @@ -78,21 +78,21 @@ "auth_missing_email_or_phone" = "E-mailadres of telefoonnummer ontbreekt"; "auth_password_dont_match" = "De wachtwoorden komen niet overeen"; "auth_username_in_use" = "Inlognaam al in gebruik"; -"auth_forgot_password" = "Wachtwoord vergeten?"; +"auth_forgot_password" = "Matrix account wachtwoord vergeten?"; "auth_use_server_options" = "Aangepaste serverinstellingen gebruiken (geavanceerd)"; "auth_email_validation_message" = "Bekijk uw e-mail om verder te gaan met de registratie"; "auth_msisdn_validation_title" = "Verificatie in afwachting"; "auth_msisdn_validation_message" = "We hebben een sms met een activatiecode gestuurd. Voer deze code hieronder in."; "auth_msisdn_validation_error" = "Kan het telefoonnummer niet verifiëren."; "auth_recaptcha_message" = "Deze server wil er graag zeker van zijn dat u geen robot bent"; -"auth_reset_password_message" = "Voer het e-mailadres dat met uw account verbonden is in om uw wachtwoord opnieuw in te stellen:"; +"auth_reset_password_message" = "Voer het e-mailadres dat met uw account verbonden is in om uw Matrix account wachtwoord opnieuw in te stellen:"; "auth_reset_password_missing_email" = "Het e-mailadres dat met uw account verbonden is moet ingevoerd worden."; "auth_reset_password_missing_password" = "Er moet een nieuw wachtwoord ingevoerd worden."; "auth_reset_password_email_validation_message" = "Er is een e-mail naar %@ gestuurd. Klik hieronder zodra u de koppeling erin hebt gevolgd."; "auth_reset_password_next_step_button" = "Ik heb mijn e-mailadres geverifieerd"; "auth_reset_password_error_unauthorized" = "Verifiëren van e-mailadres is mislukt: wees er zeker van dat u op de koppeling in de e-mail hebt getikt"; "auth_reset_password_error_not_found" = "Het ziet er niet naar uit dat uw e-mailadres met een Matrix-ID is verbonden op deze server."; -"auth_reset_password_success_message" = "Uw wachtwoord is opnieuw ingesteld.\n\nU bent op alle apparaten afgemeld en u zult geen pushmeldingen meer ontvangen. Om meldingen weer in te schakelen, meldt u zich op elk apparaat opnieuw aan."; +"auth_reset_password_success_message" = "Uw Matrix account wachtwoord is opnieuw ingesteld.\n\nU bent op alle apparaten afgemeld en u zult geen pushmeldingen meer ontvangen. Om meldingen weer in te schakelen, meldt u zich op elk apparaat opnieuw aan."; "auth_add_email_and_phone_warning" = "Registratie met e-mailadres en telefoonnummer tegelijkertijd wordt, totdat de API bestaat, nog niet ondersteund. Alleen het telefoonnummer zal worden gebruikt. U kunt uw e-mailadres later aan uw profiel in de instellingen toevoegen."; // Chat creation "room_creation_title" = "Nieuwe chat"; @@ -215,7 +215,7 @@ "room_event_action_redact" = "Verwijderen"; "room_event_action_more" = "Meer"; "room_event_action_share" = "Delen"; -"room_event_action_permalink" = "Permalink"; +"room_event_action_permalink" = "Kopieer link naar bericht"; "room_event_action_view_source" = "Bron weergeven"; "room_event_action_report" = "Inhoud melden"; "room_event_action_report_prompt_reason" = "Reden voor het melden van deze inhoud"; @@ -310,12 +310,12 @@ "settings_third_party_notices" = "Derdepartijmeldingen"; "settings_send_crash_report" = "Anonieme crash- en gebruiksgegevens versturen"; "settings_clear_cache" = "Cache verwijderen"; -"settings_change_password" = "Wachtwoord veranderen"; +"settings_change_password" = "Matrix account wachtwoord veranderen"; "settings_old_password" = "oud wachtwoord"; "settings_new_password" = "nieuw wachtwoord"; "settings_confirm_password" = "wachtwoord bevestigen"; -"settings_fail_to_update_password" = "Bijwerken van wachtwoord is mislukt"; -"settings_password_updated" = "Uw wachtwoord is bijgewerkt"; +"settings_fail_to_update_password" = "Bijwerken van Matrix account wachtwoord is mislukt"; +"settings_password_updated" = "Uw Matrix account wachtwoord is bijgewerkt"; "settings_crypto_device_name" = "Apparaatnaam: "; "settings_crypto_device_id" = "\nApparaats-ID: "; "settings_crypto_device_key" = "\nApparaatssleutel:\n"; @@ -557,7 +557,7 @@ "deactivate_account_forget_messages_information_part3" = ": dit zal er voor zorgen dat toekomstige gebruikers een onvolledig beeld krijgen van gesprekken)"; "deactivate_account_validate_action" = "Account deactiveren"; "deactivate_account_password_alert_title" = "Account deactiveren"; -"deactivate_account_password_alert_message" = "Voer uw wachtwoord in om verder te gaan"; +"deactivate_account_password_alert_message" = "Voer uw Matrix account wachtwoord in om verder te gaan"; "room_event_action_view_decrypted_source" = "Ontsleutelde bron weergeven"; "room_message_reply_to_placeholder" = "Stuur een antwoord (onversleuteld)…"; "encrypted_room_message_reply_to_placeholder" = "Stuur een versleuteld antwoord…"; @@ -622,7 +622,7 @@ "key_backup_setup_intro_manual_export_info" = "(Geavanceerd)"; "key_backup_setup_intro_manual_export_action" = "Sleutels handmatig exporteren"; "key_backup_setup_passphrase_title" = "Beveilig uw back-up met een veiligheidswachtwoord"; -"key_backup_setup_passphrase_info" = "We bewaren een versleutelde kopie van uw sleutels op onze server. Bescherm uw back-up met een veiligheidswachtwoord om deze veilig te houden.\n\nVoor maximale beveiliging zou dit moeten verschillen van uw accountwachtwoord."; +"key_backup_setup_passphrase_info" = "We bewaren een versleutelde kopie van uw sleutels op onze server. Bescherm uw back-up met een veiligheidswachtwoord om deze veilig te houden.\n\nVoor maximale beveiliging zou dit moeten verschillen van uw Matrix account wachtwoord."; "key_backup_setup_passphrase_passphrase_title" = "Invoeren"; "key_backup_setup_passphrase_passphrase_placeholder" = "Wachtwoord invoeren"; "key_backup_setup_passphrase_passphrase_valid" = "Top!"; @@ -824,7 +824,7 @@ "emoji_picker_flags_category" = "Vlaggen"; // MARK: Reaction history "reaction_history_title" = "Reacties"; -"auth_forgot_password_error_no_configured_identity_server" = "Er is geen identiteitsserver geconfigureerd: voeg er een toe om uw wachtwoord opnieuw in te stellen."; +"auth_forgot_password_error_no_configured_identity_server" = "Er is geen identiteitsserver geconfigureerd: voeg er een toe om uw Matrix account wachtwoord opnieuw in te stellen."; "room_creation_error_invite_user_by_email_without_identity_server" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen deelnemers toevoegen via e-mail."; "room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen gesprek beginnen met een contact via e-mail."; // Service terms @@ -856,9 +856,9 @@ "auth_add_email_message_2" = "Stel een e-mailadres in voor accountherstel en om later optioneel vindbaar te zijn voor mensen die u kennen."; "auth_add_phone_message_2" = "Stel een telefoon in om later optioneel vindbaar te zijn voor mensen die u kennen."; "auth_add_email_phone_message_2" = "Stel een e-mailadres in voor accountherstel. Gebruik later e-mail of telefoon om optioneel vindbaar te zijn voor mensen die u kennen."; -"auth_email_is_required" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen e-mailadres toevoegen om uw wachtwoord in de toekomst opnieuw in te stellen."; -"auth_phone_is_required" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen telefoonnummer toevoegen om uw wachtwoord in de toekomst opnieuw in te stellen."; -"auth_reset_password_error_is_required" = "Geen identiteitsserver ingesteld: voeg er één toe bij server opties om uw wachtwoord te wijzigen."; +"auth_email_is_required" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen e-mailadres toevoegen om uw Matrix account wachtwoord in de toekomst opnieuw in te stellen."; +"auth_phone_is_required" = "Er is geen identiteitsserver geconfigureerd, dus u kunt geen telefoonnummer toevoegen om uw Matrix account wachtwoord in de toekomst opnieuw in te stellen."; +"auth_reset_password_error_is_required" = "Geen identiteitsserver ingesteld: voeg er één toe bij server opties om uw Matrix account wachtwoord te wijzigen."; // MARK: - Secrets set up @@ -1009,7 +1009,7 @@ // Banner "cross_signing_setup_banner_title" = "Versleuteling instellen"; -"secrets_reset_authentication_message" = "Geef het wachtwoord van uw account om te bevestigen"; +"secrets_reset_authentication_message" = "Geef het Matrix account wachtwoord in om te bevestigen"; "secrets_reset_reset_action" = "Opnieuw instellen"; "secrets_reset_warning_message" = "U zult opnieuw starten zonder geschiedenis, berichten, vertrouwde apparaten en vertrouwde gebruikers."; "secrets_reset_warning_title" = "Als u alles terugzet"; @@ -1021,7 +1021,7 @@ "secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Wachtwoord bevestigen"; "secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Bevestigen"; "secrets_setup_recovery_passphrase_validate_action" = "Klaar"; -"secrets_setup_recovery_passphrase_additional_information" = "Gebruik niet het wachtwoord van uw account."; +"secrets_setup_recovery_passphrase_additional_information" = "Gebruik niet het Matrix account wachtwoord."; "secrets_setup_recovery_key_storage_alert_title" = "Bewaar hem op een veilige plaats"; "secrets_setup_recovery_key_done_action" = "Klaar"; "secrets_setup_recovery_key_export_action" = "Opslaan"; @@ -1326,7 +1326,7 @@ // Manage session "manage_session_title" = "Beheer sessie"; -"security_settings_user_password_description" = "Bevestig uw identiteit door uw accountwachtwoord in te voeren"; +"security_settings_user_password_description" = "Bevestig uw identiteit door uw Matrix account wachtwoord in te voeren"; "security_settings_coming_soon" = "Sorry. Deze actie is nog niet beschikbaar in %@ iOS. Gebruik een andere Matrix-app om het in te stellen. %@ iOS zal het dan wel gebruiken."; "security_settings_complete_security_alert_message" = "U moet de beveiliging van uw huidige sessie nog afronden."; "security_settings_complete_security_alert_title" = "Beveiliging afronden"; @@ -1349,7 +1349,7 @@ "security_settings_secure_backup_setup" = "Instellen"; "security_settings_secure_backup_description" = "Maak een back-up van uw versleutelingssleutel bij uw account data voor het geval u toegang verliest tot uw sessies. Uw sleutels zullen worden beveiligd met een unieke veiligheidssleutel."; "security_settings_secure_backup" = "VEILIGE BACK-UP"; -"security_settings_crypto_sessions_description_2" = "Als u deze inlog niet herkent, verander uw wachtwoord en reset uw Veilige Back-up."; +"security_settings_crypto_sessions_description_2" = "Als u deze inlog niet herkent, verander uw Matrix account wachtwoord en reset uw Veilige Back-up."; "security_settings_crypto_sessions_loading" = "Sessies laden…"; "security_settings_crypto_sessions" = "MIJN SESSIES"; @@ -1375,7 +1375,7 @@ "settings_discovery_no_identity_server" = "U gebruikt momenteel geen identiteitsserver. Om door de u bekende contacten vindbaar te zijn, voeg er een toe."; "settings_devices_description" = "De publieke naam van een sessie is zichtbaar voor de personen waarmee u communiceert"; "settings_add_3pid_invalid_password_message" = "Ongeldig wachtwoord"; -"settings_add_3pid_password_message" = "Geef uw wachtwoord om verder te gaan"; +"settings_add_3pid_password_message" = "Geef uw Matrix account wachtwoord om verder te gaan"; "settings_add_3pid_password_title_msidsn" = "Telefoonnummer toevoegen"; "settings_add_3pid_password_title_email" = "E-mailadres toevoegen"; "settings_integrations_allow_description" = "Gebruik een integratiebeheerder om bots, bruggen, widgets en stickerpakketten te beheren.\n\nIntegratiebeheerders ontvangen configuratiedata en kunnen widgets aanpassen, kameruitnodigingen versturen en bestuursniveaus instellen namens u."; @@ -1726,3 +1726,35 @@ "poll_edit_form_update_failure_subtitle" = "Probeer het opnieuw"; "poll_edit_form_update_failure_title" = "Kan poll niet bijwerken"; "poll_edit_form_poll_type" = "Poll type"; +"location_sharing_post_failure_subtitle" = "%@ kan uw locatie niet verzenden. Probeer het later opnieuw."; +"location_sharing_post_failure_title" = "We konden uw locatie niet verzenden"; +"home_context_menu_leave" = "Verlaten"; +"home_context_menu_normal_priority" = "Normale prioriteit"; +"home_context_menu_low_priority" = "Lage prioriteit"; +"home_context_menu_unfavourite" = "Verwijder uit favorieten"; +"home_context_menu_favourite" = "Favoriet"; +"home_context_menu_unmute" = "Dempen opheffen"; +"home_context_menu_mute" = "Dempen"; +"home_context_menu_notifications" = "Meldingen"; +"home_context_menu_make_room" = "Verplaatsen naar kamers"; +"home_context_menu_make_dm" = "Verplaatsen naar personen"; +"event_formatter_message_deleted" = "Bericht verwijderd"; +"settings_labs_enable_threads" = "Berichten met discussielijnen"; +"message_from_a_thread" = "Van een discussie"; +"threads_empty_show_all_threads" = "Toon alle discussies"; +"threads_empty_tip" = "Tip: Tik op een bericht en gebruik “Discussie” om er een te starten."; +"threads_empty_info_my" = "Reageer op een lopende discussie of tik op een bericht en gebruik “Discussie” om een nieuwe te starten."; +"threads_empty_info_all" = "Discussies helpen u gesprekken on-topic te houden en gemakkelijk bij te houden."; +"threads_empty_title" = "Houd discussies georganiseerd met discussielijnen"; +"threads_action_my_threads" = "Mijn discussies"; +"threads_action_all_threads" = "Alle discussies"; +"threads_title" = "Discussies"; +"thread_copy_link_to_thread" = "Kopieer link naar discussie"; + +// MARK: Threads +"room_thread_title" = "Discussies"; +"room_accessibility_thread_more" = "Meer"; +"room_accessibility_threads" = "Discussies"; +"room_event_copy_link_info" = "Link gekopieerd naar klembord."; +"room_event_action_reply_in_thread" = "Discussie"; +"room_event_action_view_in_room" = "Bekijk in kamer"; From 3b7ef83fcf03b4190f7d38afd03db571935b7809 Mon Sep 17 00:00:00 2001 From: JokerGermany Date: Fri, 18 Feb 2022 12:48:14 +0000 Subject: [PATCH 168/188] Translated using Weblate (German) Currently translated at 99.8% (1431 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/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 e058ec190..b249302d5 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -1476,7 +1476,7 @@ "spaces_empty_space_title" = "Dieser Space hat (noch) keine Räume"; "spaces_explore_rooms" = "Räume erkunden"; "leave_space_and_all_rooms_action" = "Alle Räume und Spaces verlassen"; -"leave_space_only_action" = "Keine Räume verlassen"; +"leave_space_only_action" = "Keine Räume und Subspaces verlassen"; "spaces_left_panel_title" = "Spaces"; "room_recents_suggested_rooms_section" = "VORGESCHLAGENE RÄUME"; "spaces_home_space_title" = "Start"; From 7dfab96277699a01688257acc27bf2f0ea8976f9 Mon Sep 17 00:00:00 2001 From: Azrty Date: Thu, 17 Feb 2022 15:47:29 +0000 Subject: [PATCH 169/188] Translated using Weblate (French) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fr/ --- Riot/Assets/fr.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/fr.lproj/Vector.strings b/Riot/Assets/fr.lproj/Vector.strings index a26d64064..0e0d9676b 100644 --- a/Riot/Assets/fr.lproj/Vector.strings +++ b/Riot/Assets/fr.lproj/Vector.strings @@ -1670,3 +1670,5 @@ "room_event_copy_link_info" = "Lien copié dans le presse-papier."; "room_event_action_reply_in_thread" = "Fil"; "room_event_action_view_in_room" = "Afficher dans le salon"; +"home_context_menu_normal_priority" = "Priorité normale"; +"home_context_menu_low_priority" = "Basse priorité"; From f04cd30bd3261bc3e2056c005ae9810d349ace1c Mon Sep 17 00:00:00 2001 From: Modificator Date: Thu, 17 Feb 2022 14:33:33 +0000 Subject: [PATCH 170/188] Translated using Weblate (Chinese (Simplified)) Currently translated at 94.4% (1354 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/zh_Hans/ --- Riot/Assets/zh_Hans.lproj/Vector.strings | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/zh_Hans.lproj/Vector.strings b/Riot/Assets/zh_Hans.lproj/Vector.strings index 12863f8fa..181d299c6 100644 --- a/Riot/Assets/zh_Hans.lproj/Vector.strings +++ b/Riot/Assets/zh_Hans.lproj/Vector.strings @@ -251,7 +251,7 @@ "settings_labs" = "实验室"; "settings_devices" = "会话"; "settings_cryptography" = "加密"; -"settings_sign_out" = "离开"; +"settings_sign_out" = "退出登陆"; "settings_sign_out_confirmation" = "你确定?"; "settings_sign_out_e2e_warn" = "您将丢失所有端对端加密密钥。这意味着在此设备上您将再也无法阅读已加密聊天室里的旧消息。"; "settings_profile_picture" = "档案图片"; @@ -1605,3 +1605,8 @@ "settings_analytics_and_crash_data" = "发送崩溃和分析数据"; "accessibility_button_label" = "按钮"; "enable" = "启用"; +"onboarding_splash_page_1_message" = "独立安全的通信,为您提供与家中面谈相同的私密性。"; +"onboarding_splash_page_1_title" = "掌控你的对话。"; + +// Onboarding +"onboarding_splash_register_button_title" = "注册"; From a79cd28a90fd2bcd09cd2e0b02e513027ee2081f Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Mon, 21 Feb 2022 09:34:32 +0000 Subject: [PATCH 171/188] Translated using Weblate (Japanese) Currently translated at 68.1% (977 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index d3eea910e..c62e28a30 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -78,7 +78,7 @@ "auth_msisdn_validation_message" = "SMSで認証番号を送りました。以下にその番号を入力してください。"; "auth_msisdn_validation_error" = "電話番号を認証できません。"; "auth_recaptcha_message" = "接続先サーバー側が、機械による自動登録ではなく、あなたが人間であることを確認したいとのことです"; -"auth_reset_password_message" = "パスワードを初期化するには、アカウントに登録されているメールアドレスを入力してください:"; +"auth_reset_password_message" = "Matrixのアカウントのパスワードを初期化するには、アカウントに登録されているメールアドレスを入力してください:"; "auth_reset_password_missing_email" = "あなたのアカウントに登録されたメールアドレスの入力が必要です。"; "auth_reset_password_missing_password" = "新しいパスワードの入力が必要です。"; "auth_reset_password_email_validation_message" = "%@ へ電子メールが送信されました。リンクをたどったら以下をクリックしてください。"; @@ -288,7 +288,7 @@ "settings_enable_push_notif" = "この端末での通知"; "settings_show_decrypted_content" = "復号化された文章を表示"; "settings_global_settings_info" = "あなたの%@ webクライアント上で、全体の通知設定が可能です"; -"settings_pin_rooms_with_missed_notif" = "逃した通知があるルームをピン止め"; +"settings_pin_rooms_with_missed_notif" = "逃した通知があるルームを固定"; "settings_callkit_info" = "画面がロックされているときに着信がありました。Elementの着信はシステムの通話履歴で確認できます。iCloudが有効になっている場合、この通話履歴はAppleと共有されます。"; "settings_ui_language" = "言語"; "settings_ui_theme" = "外観"; @@ -464,7 +464,7 @@ "share_extension_failed_to_encrypt" = "送信に失敗しました。このルームの暗号設定をメインの端末で確認して下さい"; "room_details_advanced_e2e_encryption_prompt_message" = "End-to-end暗号化は実験的なものであり、信頼性が低い場合があります。\n\n発言を保護するためにはまだそれを信用すべきではありません。\n\n端末は、まだ参加する前の発言履歴を復号化することはできません。\n\n部屋の暗号化が今から有効になったら、もう無効にすることはできません。\n\n暗号化された発言は、まだ暗号化を実装していないアプリでは表示されません。"; "settings_enable_callkit" = "呼び出しの統合"; -"settings_pin_rooms_with_unread" = "未読のあるルームをピン止め"; +"settings_pin_rooms_with_unread" = "未読のあるルームを固定"; "title_groups" = "コミュニティー"; "room_recents_server_notice_section" = "システムアラート"; // Groups tab From c1e0b4bb9df79502f63fa1329d49e4f29a57eac1 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 18 Feb 2022 15:40:34 +0000 Subject: [PATCH 172/188] Translated using Weblate (Central Atlas Tamazight) Currently translated at 0.7% (11 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/tzm/ --- Riot/Assets/tzm.lproj/Vector.strings | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Riot/Assets/tzm.lproj/Vector.strings b/Riot/Assets/tzm.lproj/Vector.strings index 229ee0c32..e41ca4a51 100644 --- a/Riot/Assets/tzm.lproj/Vector.strings +++ b/Riot/Assets/tzm.lproj/Vector.strings @@ -12,3 +12,8 @@ "invite" = "Ɣer"; "remove" = "Kkes"; "title_people" = "Midden"; +"settings_crypto_device_id" = ""; + +// MARK: - Home + +"home_empty_view_title" = ""; From 7e82fae66b76eaf52a6541900fe1c274d0584024 Mon Sep 17 00:00:00 2001 From: Linerly Date: Fri, 18 Feb 2022 16:05:57 +0000 Subject: [PATCH 173/188] Translated using Weblate (Indonesian) Currently translated at 100.0% (1433 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ --- Riot/Assets/id.lproj/Vector.strings | 30 ++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/Riot/Assets/id.lproj/Vector.strings b/Riot/Assets/id.lproj/Vector.strings index f1d9ec304..87c75e41c 100644 --- a/Riot/Assets/id.lproj/Vector.strings +++ b/Riot/Assets/id.lproj/Vector.strings @@ -522,8 +522,8 @@ "room_participants_now" = "sekarang"; "room_participants_idle" = "Idle"; "room_participants_unknown" = "Tidak diketahui"; -"room_participants_offline" = "Offline"; -"room_participants_online" = "Online"; +"room_participants_offline" = "Luring"; +"room_participants_online" = "Daring"; "room_participants_invited_section" = "DIUNDANG"; "room_participants_invite_prompt_title" = "Konfirmasi"; "room_participants_remove_prompt_title" = "Konfirmasi"; @@ -667,7 +667,7 @@ // GDPR "gdpr_consent_not_given_alert_message" = "Untuk terus menggunakan homeserver %@, Anda harus menyetujui syarat dan ketentuannya."; "share_extension_failed_to_encrypt" = "Gagal untuk mengirim. Periksa di aplikasi utama pengaturan enkripsi untuk ruangan ini"; -"bug_report_logs_description" = "Untuk mendiagnosis masalah, log dari klien ini akan dikirim dengan laporan bug ini. Jika Anda lebih memilih untuk hanya mengirim teks di atas, harap hapus centang:"; +"bug_report_logs_description" = "Untuk mendiagnosis masalah, catat dari klien ini akan dikirim dengan laporan kutu ini. Jika Anda lebih memilih untuk hanya mengirim teks di atas, harap hapus centang:"; "bug_report_description" = "Harap jelaskan bugnya. Apa yang Anda lakukan? Apa yang Anda harapkan terjadi? Apa yang sebenarnya terjadi?"; "e2e_key_backup_wrong_version" = "Cadangan kunci pesan aman baru telah terdeteksi.\n\nJika ini bukan Anda, atur Frasa Keamanan baru di Pengaturan."; @@ -680,7 +680,7 @@ "call_no_stun_server_error_message_1" = "Mohon hubungi administrator homeserver %@ Anda untuk mengatur sebuah server TURN supaya panggilan dapat bekerja dengan handal."; "rage_shake_prompt" = "Anda tampaknya menggoyangkan telepon dengan frustrasi. Apakah Anda ingin mengirimkan laporan bug?"; "bug_report_prompt" = "Aplikasi telah crash terakhir kali. Apakah Anda ingin mengirimkan laporan crash?"; -"room_notifs_settings_encrypted_room_notice" = "Harap dicatat bahwa notifikasi sebutan & keyword tidak tersedia di ruang terenkripsi di ponsel."; +"room_notifs_settings_encrypted_room_notice" = "Harap dicatat bahwa notifikasi sebutan & kata kunci tidak tersedia di ruang terenkripsi di ponsel."; "room_details_addresses_disable_main_address_prompt_msg" = "Anda tidak akan memiliki alamat utama yang ditentukan. Alamat utama default untuk ruangan ini akan dipilih secara acak"; "room_details_history_section_prompt_msg" = "Perubahan siapa yang dapat membaca riwayat hanya akan berlaku untuk pesan berikutnya di ruang ini. Visibilitas riwayat yang ada tidak akan berubah."; "identity_server_settings_alert_error_terms_not_accepted" = "Anda harus menerima syaratnya %@ untuk menyetelnya sebagai server identitas."; @@ -1438,7 +1438,7 @@ "settings_ui_theme_picker_message_invert_colours" = "\"Otomatis\" menggunakan pengaturan \"Balikkan Warna\" perangkat Anda"; "settings_ui_theme_picker_message_match_system_theme" = "\"Otomatis\" mencocokkan dengan tema sistem perangkat Anda"; "settings_calls_stun_server_fallback_description" = "Izinkan server panggilan %@ cadangan saat server homeserver Anda tidak menawarkannya (alamat IP Anda akan dibagikan selama panggilan)."; -"settings_mentions_and_keywords_encryption_notice" = "Anda tidak akan dapat notifikasi untuk sebutan & keyword di ruangan terenkripsi di ponsel."; +"settings_mentions_and_keywords_encryption_notice" = "Anda tidak akan dapat notifikasi untuk sebutan & kata kunci di ruangan terenkripsi di ponsel."; "settings_notifications_disabled_alert_message" = "Untuk mengaktifkan notifikasi, pergi ke pengaturan perangkat Anda."; "settings_global_settings_info" = "Pengaturan notifikasi global tersedia di klien web %@ Anda"; "settings_confirm_media_size_description" = "Saat ini aktif, Anda akan diminta untuk mengkonfirmasi ukuran gambar dan video yang akan dikirim."; @@ -1653,11 +1653,11 @@ "poll_edit_form_create_options" = "Buat opsi"; "poll_edit_form_input_placeholder" = "Tulis sesuatu"; "poll_edit_form_question_or_topic" = "Pertanyaan atau topik"; -"poll_edit_form_poll_question_or_topic" = "Pertanyaan atau topik poll"; +"poll_edit_form_poll_question_or_topic" = "Pertanyaan atau topik pemungutan suara"; // Mark: - Polls -"poll_edit_form_create_poll" = "Buat poll"; +"poll_edit_form_create_poll" = "Buat pemungutan suara"; "share_extension_send_now" = "Kirim sekarang"; "share_extension_low_quality_video_message" = "Kirim dalam %@ untuk kualitas yang lebih baik, atau kirim dengan kualitas rendah di bawah."; "share_extension_low_quality_video_title" = "Video akan dikirim dalam kualitas rendah"; @@ -1665,7 +1665,7 @@ "settings_about" = "TENTANG"; "poll_timeline_not_closed_action" = "OK"; "poll_timeline_not_closed_subtitle" = "Mohon coba lagi"; -"poll_timeline_not_closed_title" = "Gagal untuk mengakhiri poll"; +"poll_timeline_not_closed_title" = "Gagal untuk mengakhiri pemungutan suara"; "poll_timeline_vote_not_registered_action" = "OK"; "poll_timeline_vote_not_registered_subtitle" = "Maaf, suara Anda tidak diberikan, mohon coba lagi"; "poll_timeline_vote_not_registered_title" = "Suara tidak diberikan"; @@ -1680,10 +1680,10 @@ "poll_timeline_one_vote" = "1 suara"; "poll_edit_form_post_failure_action" = "OK"; "poll_edit_form_post_failure_subtitle" = "Silakan coba lagi"; -"poll_edit_form_post_failure_title" = "Gagal untuk mengirim poll"; +"poll_edit_form_post_failure_title" = "Gagal untuk mengirim pemungutan suara"; "settings_labs_enabled_polls" = "Poll"; -"room_event_action_end_poll" = "Akhiri poll"; -"room_event_action_remove_poll" = "Hapus poll"; +"room_event_action_end_poll" = "Akhiri pemungutan suara"; +"room_event_action_remove_poll" = "Hapus pemungutan suara"; "analytics_prompt_stop" = "Berhenti membagikan"; "analytics_prompt_yes" = "Iya, saya tidak keberatan"; "analytics_prompt_not_now" = "Jangan sekarang"; @@ -1735,13 +1735,13 @@ // Onboarding "onboarding_splash_register_button_title" = "Buat akun"; -"poll_edit_form_poll_type_closed_description" = "Hasil akan ditampilkan ketika Anda mengakhiri poll-nya"; +"poll_edit_form_poll_type_closed_description" = "Hasil akan ditampilkan ketika Anda mengakhiri pemungutan suara"; "poll_edit_form_poll_type_closed" = "Poll tertutup"; "poll_edit_form_poll_type_open_description" = "Pemberi suara akan melihat hasilnya ketika telah memberikan suara"; -"poll_edit_form_poll_type_open" = "Buka poll"; +"poll_edit_form_poll_type_open" = "Buka pemungutan suara"; "poll_edit_form_update_failure_subtitle" = "Silakan coba lagi"; -"poll_edit_form_update_failure_title" = "Gagal untuk memperbarui poll"; -"poll_edit_form_poll_type" = "Tipe poll"; +"poll_edit_form_update_failure_title" = "Gagal untuk memperbarui pemungutan suara"; +"poll_edit_form_poll_type" = "Tipe pemungutan suara"; "location_sharing_post_failure_subtitle" = "%@ tidak dapat mengirimkan lokasi Anda. Silakan coba lagi nanti."; "location_sharing_post_failure_title" = "Kami tidak dapat mengirimkan lokasi Anda"; "home_context_menu_leave" = "Tinggalkan"; From 57b41af9973d2f71ca4291fd41620d0c9e7310bf Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Fri, 18 Feb 2022 18:28:54 +0000 Subject: [PATCH 174/188] Translated using Weblate (Slovak) Currently translated at 99.3% (1424 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sk/ --- Riot/Assets/sk.lproj/Vector.strings | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/sk.lproj/Vector.strings b/Riot/Assets/sk.lproj/Vector.strings index 5f7977207..227ca56c1 100644 --- a/Riot/Assets/sk.lproj/Vector.strings +++ b/Riot/Assets/sk.lproj/Vector.strings @@ -1296,7 +1296,7 @@ "room_intro_cell_information_multiple_dm_sentence2" = "V tejto konverzácii ste len vy, pokiaľ niekto z vás niekoho nepozve, aby sa pripojil."; "room_intro_cell_information_dm_sentence2" = "V tejto konverzácii ste len vy dvaja, nikto iný sa nemôže pripojiť."; "room_intro_cell_information_room_without_topic_sentence2_part2" = " aby ľudia vedeli, o čom je táto miestnosť."; -"room_intro_cell_information_room_without_topic_sentence2_part1" = "Pridať tému"; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Pridajte tému"; "room_avatar_view_accessibility_hint" = "Zmeniť obrázok miestnosti"; "invite_friends_share_text" = "Ahoj, ozvi sa mi na %@: %@"; @@ -1751,3 +1751,9 @@ "room_event_action_reply_in_thread" = "Vlákno"; "settings_calls_stun_server_fallback_button" = "Povoliť náhradnú službu hovorov asistenčného servera"; "settings_calls_stun_server_fallback_description" = "Povoľte náhradné službu hovorov asistenčného servera %@, keď ho váš domovský server neponúka (vaša IP adresa by bola počas volania zdieľaná)."; +"deactivate_account_informations_part4_emphasize" = "štandardne nespôsobí, že zabudneme na správy, ktoré ste odoslali. "; +"room_details_fail_to_update_room_join_rule" = "Nepodarí sa aktualizovať pravidlo pripojenia"; +"settings_enable_callkit" = "Integrované volanie"; +"room_resource_usage_limit_reached_message_contact_3" = " aby ste tento limit zvýšili."; +"room_resource_limit_exceeded_message_contact_3" = " pokračovať v používaní tejto služby."; +"find_your_contacts_title" = "Začnite so zoznamom vašich kontaktov"; From e1bdd440bcda3681e460d4e9653c4eaa741aadb3 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Mon, 21 Feb 2022 09:34:48 +0000 Subject: [PATCH 175/188] Translated using Weblate (Japanese) Currently translated at 85.2% (377 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index cc3594b9b..b6596eab2 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -100,14 +100,14 @@ "notice_error_unsupported_event" = "サポートされていないイベント"; "notice_error_unexpected_event" = "予期しないイベント"; "notice_error_unknown_event_type" = "不明なイベントタイプ"; -"notice_room_history_visible_to_anyone" = "%@は、今後のルーム履歴を誰でも見えるように設定しました。"; -"notice_room_history_visible_to_members" = "%@ ルームメンバー全員に将来のルーム履歴を表示されます。"; -"notice_room_history_visible_to_members_from_invited_point" = "%@ ルームメンバー全員に招待した時点からのルーム履歴を表示されます。"; -"notice_room_history_visible_to_members_from_joined_point" = "%@ ルームメンバー全員に参加した時点からのルーム履歴を表示されます。"; +"notice_room_history_visible_to_anyone" = "%@が今後のルーム履歴を「誰でも」閲覧可能に設定しました。"; +"notice_room_history_visible_to_members" = "%@が今後のルーム履歴を「メンバーのみ」閲覧可能に設定しました。"; +"notice_room_history_visible_to_members_from_invited_point" = "%@が今後のルーム履歴を「メンバーのみ (招待された時点以降)」閲覧可能に設定しました。"; +"notice_room_history_visible_to_members_from_joined_point" = "%@が今後のルーム履歴を「メンバーのみ (参加した時点以降)」閲覧可能に設定しました。"; "notice_crypto_unable_to_decrypt" = "** 復号化できません: %@ **"; "notice_crypto_error_unknown_inbound_session_id" = "送信者のセッションからこのメッセージ用の鍵が送信されていません。"; "notice_sticker" = "ステッカー"; -"notice_in_reply_to" = "に返信"; +"notice_in_reply_to" = "返信先"; // room display name "room_displayname_empty_room" = "空のルーム"; "room_displayname_two_members" = "%@ と %@"; @@ -162,7 +162,7 @@ "account_email_validation_message" = "メールをチェックし、それに含まれているリンクをクリックしてください。 これが完了したら、[続行]をクリックします。"; "account_email_validation_error" = "メールアドレスを確認できません。 あなたのメールをチェックし、それに含まれているリンクをクリックしてください。 これが完了したら、[続行]をクリックします"; "account_msisdn_validation_title" = "認証の保留中"; -"account_msisdn_validation_message" = "アクティベーションコード付きのSMSを送信しました。 以下にこのコードを入力してください。"; +"account_msisdn_validation_message" = "SMSで認証番号を送りました。以下にその番号を入力してください。"; "account_msisdn_validation_error" = "電話番号を確認できません。"; "account_error_display_name_change_failed" = "表示名の変更に失敗しました"; "account_error_picture_change_failed" = "画像の変更に失敗しました"; @@ -376,8 +376,8 @@ "ssl_expected_existing_expl" = "証明書が以前に信頼されたものから信頼されていないものに変更されました。 サーバーが証明書を更新した可能性があります。 予想される指紋については、サーバー管理者にお問い合わせください。"; "ssl_only_accept" = "サーバー管理者が上記のものと一致する指紋を発行した場合にのみ、証明書を受け入れてください。"; "unignore" = "無視しない"; -"notice_encryption_enabled_ok" = "%@ がエンドツーエンド暗号化をオンにしました。"; -"notice_encryption_enabled_unknown_algorithm" = "%1$@ がエンドツーエンド暗号化をオンにしました (不明なアルゴリズム %2$@)。"; +"notice_encryption_enabled_ok" = "%@がエンドツーエンド暗号化をオンにしました。"; +"notice_encryption_enabled_unknown_algorithm" = "%1$@がエンドツーエンド暗号化をオンにしました(不明なアルゴリズム %2$@)。"; "device_details_rename_prompt_title" = "セッション名"; "account_error_push_not_allowed" = "通知は許可されていません"; "notice_room_third_party_revoked_invite" = "%@が%@のルームへの招待を取り消しました"; @@ -387,8 +387,8 @@ "notice_room_join_by_you" = "参加しました"; "notice_room_leave_by_you" = "退出しました"; "notice_room_kick_by_you" = "%@をキックしました"; -"notice_room_unban_by_you" = "%@をBANしました"; -"notice_room_ban_by_you" = "%@をBANしました"; +"notice_room_unban_by_you" = "%@のブロックを解除しました"; +"notice_room_ban_by_you" = "%@をブロックしました"; "notice_avatar_url_changed_by_you" = "アバターを変更しました"; "notice_display_name_set_by_you" = "表示名を%@に変更しました"; "notice_display_name_changed_from_by_you" = "表示名を%@から%@に変更しました"; @@ -409,3 +409,6 @@ "notice_redaction_by_you" = "イベントを編集しました (id: %@)"; "auth_username_in_use" = "ユーザー名は既に使用されています"; "resume_call" = "再開"; +"notice_room_history_visible_to_members_from_joined_point_for_dm" = "%@が今後のメッセージを「全員 (参加した時点以降)」閲覧可能に設定しました。"; +"notice_room_history_visible_to_members_from_invited_point_for_dm" = "%@が今後のメッセージを「メンバーのみ (招待された時点以降)」閲覧可能に設定しました。"; +"notice_room_history_visible_to_members_for_dm" = "%@が今後のメッセージを「メンバーのみ」閲覧可能に設定しました。"; From 91a2158ffab7f190c910d7a3402cd70f570c38a2 Mon Sep 17 00:00:00 2001 From: Jozef Gaal Date: Fri, 18 Feb 2022 18:25:54 +0000 Subject: [PATCH 176/188] Translated using Weblate (Slovak) Currently translated at 99.3% (439 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/sk/ --- .../sk.lproj/MatrixKit.strings | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings index b34fe6b79..0d7cc424a 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/sk.lproj/MatrixKit.strings @@ -14,7 +14,7 @@ "account_save_changes" = "Uložiť zmeny"; "room_event_encryption_verify_title" = "Overiť reláciu\n\n"; "room_event_encryption_info_device_not_verified" = "Neoverené"; -"room_event_encryption_info_device_fingerprint" = "Ed25519 odtlačok prsta\n"; +"room_event_encryption_info_device_fingerprint" = "Odtlačok Ed25519\n"; "room_event_encryption_info_device_name" = "Verejný názov\n"; "room_event_encryption_info_device_unknown" = "neznáma relácia\n"; "room_event_encryption_info_event_decryption_error" = "Chyba dešifrovania\n"; @@ -439,16 +439,16 @@ "notice_room_power_level_event_requirement" = "Minimálne úrovne oprávnenia súvisiace s udalosťami sú:"; "notice_room_join_rule_public_for_dm" = "%@ ju zverejnil/a."; "notice_room_join_rule_public" = "%@ zverejnil/a túto miestnosť."; -"notice_room_join_rule_invite_by_you_for_dm" = "Ste ju vytvorili len na pozvanie."; -"notice_room_join_rule_invite_for_dm" = "%@ ju vytvoril len na pozvanie."; +"notice_room_join_rule_invite_by_you_for_dm" = "Ste ju nastavili len na pozvanie."; +"notice_room_join_rule_invite_for_dm" = "%@ ju nastavil/a len na pozvanie."; "notice_event_redacted" = ""; "capture_media" = "Spraviť fotografiu/video"; "auth_reset_password_error_unauthorized" = "Neoprávnené"; "auth_invalid_user_name" = "Neplatné používateľské meno"; -"ssl_only_accept" = "Certifikát akceptujte IBA vtedy, ak správca servera zverejnil odtlačok prsta, ktorý sa zhoduje s vyššie uvedeným."; +"ssl_only_accept" = "Certifikát akceptujte IBA vtedy, ak správca servera zverejnil odtlačok, ktorý sa zhoduje s vyššie uvedeným."; "ssl_expected_existing_expl" = "Certifikát sa zmenil z predtým dôveryhodného na nedôveryhodný. Server mohol obnoviť svoj certifikát. Obráťte sa na správcu servera, aby vám poskytol očakávaný odtlačok."; "ssl_unexpected_existing_expl" = "Certifikát sa zmenil na iný, ktorému dôveroval váš telefón. To je VEĽMI NEOBVYKLÉ. Odporúča sa, aby ste tento nový certifikát NEPRIJALI."; -"ssl_cert_new_account_expl" = "Ak správca servera uviedol, že sa to očakáva, skontrolujte, či sa odtlačok prsta uvedený nižšie zhoduje s odtlačkom prsta, ktorý poskytol."; +"ssl_cert_new_account_expl" = "Ak správca servera uviedol, že sa to očakáva, skontrolujte, či sa odtlačok uvedený nižšie zhoduje s odtlačkom, ktorý poskytol."; "ssl_cert_not_trust" = "Môže to znamenať, že niekto úmyselne zachytáva vašu komunikáciu alebo že váš telefón nedôveruje certifikátu, ktorý poskytol vzdialený server."; "ssl_could_not_verify" = "Nepodarilo sa overiť identitu vzdialeného servera."; @@ -488,9 +488,9 @@ "settings_enter_validation_token_for" = "Zadajte overovací token pre %@:"; "notice_error_unexpected_event" = "Neočakávaná udalosť"; "notice_error_unsupported_event" = "Nepodporovaná udalosť"; -"notice_room_join_rule_invite_by_you" = "Urobili ste miestnosť len pre pozvaných."; +"notice_room_join_rule_invite_by_you" = "Nastavili ste miestnosť len pre pozvaných."; // New -"notice_room_join_rule_invite" = "%@ vytvoril miestnosť len na pozvanie."; +"notice_room_join_rule_invite" = "%@ nastavil/a miestnosť len na pozvanie."; // Old "notice_room_join_rule" = "Pravidlo pripojenia je: %@"; "notice_room_created" = "%@ vytvoril a nastavil miestnosť."; @@ -546,8 +546,12 @@ "message_reply_to_sender_sent_their_location" = "zdieľal/a svoju polohu."; "account_link_email" = "Prepojený email"; "account_linked_emails" = "Prepojené e-maily"; -"room_event_encryption_info_event_fingerprint_key" = "Deklarovaný kľúč odtlačkov prstov Ed25519\n"; +"room_event_encryption_info_event_fingerprint_key" = "Deklarovaný kľúč odtlačku Ed25519\n"; "notification_settings_notify_all_other" = "Oznámiť pre všetky ostatné správy/miestnosti"; "call_transfer_to_user" = "Presmerovať na používateľa %@"; "call_more_actions_transfer" = "Presmerovať"; "login_use_fallback" = "Použiť náhradnú stránku"; +"call_consulting_with_user" = "Konzultácia s %@"; +"notification_settings_per_sender_notifications" = "Oznámenia na odosielateľa"; +"notification_settings_per_room_notifications" = "Oznámenia na miestnosti"; +"notification_settings_per_word_notifications" = "Oznámenia na slovo"; From 6a3a9959b1c0fea798ee7d0b28a785d4f2a6541e Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Mon, 21 Feb 2022 12:50:50 +0000 Subject: [PATCH 177/188] Temporarily disable activity indicators --- Config/BuildSettings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 3eb9c33a6..3348ba964 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -213,7 +213,7 @@ final class BuildSettings: NSObject { /// Whether a screen uses legacy local activity indicators or improved app-wide indicators static var appActivityIndicators: Bool { #if DEBUG - return true + return false #else return false #endif From 313dbf7aa66504dfe437e2cd464fb7951dc25aed Mon Sep 17 00:00:00 2001 From: Andy Uhnak Date: Mon, 21 Feb 2022 17:21:51 +0000 Subject: [PATCH 178/188] Fix tableview scroll when opening notification Signed-off-by: Andy Uhnak --- Riot/Modules/Room/MXKRoomViewController.m | 6 ++++++ changelog.d/5639.bugfix | 1 + 2 files changed, 7 insertions(+) create mode 100644 changelog.d/5639.bugfix diff --git a/Riot/Modules/Room/MXKRoomViewController.m b/Riot/Modules/Room/MXKRoomViewController.m index a4a0f7dcf..1123358e1 100644 --- a/Riot/Modules/Room/MXKRoomViewController.m +++ b/Riot/Modules/Room/MXKRoomViewController.m @@ -2348,6 +2348,12 @@ { // Do a full reload [_bubblesTableView reloadData]; + if (shouldScrollToBottom) { + // If we need to scroll to the bottom after the reload, layout refresh needs to be triggered, + // otherwise contentSize of the table view will not be up-to-date + // e.g. https://stackoverflow.com/a/31324129 + [_bubblesTableView layoutIfNeeded]; + } } if (shouldScrollToBottom) diff --git a/changelog.d/5639.bugfix b/changelog.d/5639.bugfix new file mode 100644 index 000000000..757ab6fb4 --- /dev/null +++ b/changelog.d/5639.bugfix @@ -0,0 +1 @@ +Timeline: scroll to the bottom when opening a notification From 06e8f99e96c431ce6a072c8f85bcc0d919ed9c11 Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 21 Feb 2022 12:47:32 +0000 Subject: [PATCH 179/188] Add a `SharedFont` type to `ElementFonts`. Using iOS 13 as availability so the properties can be simplified when support for iOS 12 is dropped. --- DesignKit/Source/FontsSwiftUI.swift | 44 ++-- DesignKit/Source/FontsUIkit.swift | 40 ++-- DesignKit/Variants/Fonts/ElementFonts.swift | 246 ++++++++++++++++---- changelog.d/5027.bugfix | 1 + 4 files changed, 247 insertions(+), 84 deletions(-) create mode 100644 changelog.d/5027.bugfix diff --git a/DesignKit/Source/FontsSwiftUI.swift b/DesignKit/Source/FontsSwiftUI.swift index ddf6a1754..a12a537ff 100644 --- a/DesignKit/Source/FontsSwiftUI.swift +++ b/DesignKit/Source/FontsSwiftUI.swift @@ -23,7 +23,7 @@ import SwiftUI @available(iOS 14.0, *) public struct FontSwiftUI: Fonts { - public let uiFonts: ElementFonts + public let uiFonts: FontsUIKit public var largeTitle: Font @@ -66,27 +66,27 @@ public struct FontSwiftUI: Fonts { public var caption2SB: Font public init(values: ElementFonts) { - self.uiFonts = values + self.uiFonts = FontsUIKit(values: values) - self.largeTitle = Font(values.largeTitle) - self.largeTitleB = Font(values.largeTitleB) - self.title1 = Font(values.title1) - self.title1B = Font(values.title1B) - self.title2 = Font(values.title2) - self.title2B = Font(values.title2B) - self.title3 = Font(values.title3) - self.title3SB = Font(values.title3SB) - self.headline = Font(values.headline) - self.subheadline = Font(values.subheadline) - self.body = Font(values.body) - self.bodySB = Font(values.bodySB) - self.callout = Font(values.callout) - self.calloutSB = Font(values.calloutSB) - self.footnote = Font(values.footnote) - self.footnoteSB = Font(values.footnoteSB) - self.caption1 = Font(values.caption1) - self.caption1SB = Font(values.caption1SB) - self.caption2 = Font(values.caption2) - self.caption2SB = Font(values.caption2SB) + self.largeTitle = values.largeTitle.font + self.largeTitleB = values.largeTitleB.font + self.title1 = values.title1.font + self.title1B = values.title1B.font + self.title2 = values.title2.font + self.title2B = values.title2B.font + self.title3 = values.title3.font + self.title3SB = values.title3SB.font + self.headline = values.headline.font + self.subheadline = values.subheadline.font + self.body = values.body.font + self.bodySB = values.bodySB.font + self.callout = values.callout.font + self.calloutSB = values.calloutSB.font + self.footnote = values.footnote.font + self.footnoteSB = values.footnoteSB.font + self.caption1 = values.caption1.font + self.caption1SB = values.caption1SB.font + self.caption2 = values.caption2.font + self.caption2SB = values.caption2SB.font } } diff --git a/DesignKit/Source/FontsUIkit.swift b/DesignKit/Source/FontsUIkit.swift index 3067d03a1..ec65cdaa6 100644 --- a/DesignKit/Source/FontsUIkit.swift +++ b/DesignKit/Source/FontsUIkit.swift @@ -63,25 +63,25 @@ import UIKit public var caption2SB: UIFont public init(values: ElementFonts) { - self.largeTitle = values.largeTitle - self.largeTitleB = values.largeTitleB - self.title1 = values.title1 - self.title1B = values.title1B - self.title2 = values.title2 - self.title2B = values.title2B - self.title3 = values.title3 - self.title3SB = values.title3SB - self.headline = values.headline - self.subheadline = values.subheadline - self.body = values.body - self.bodySB = values.bodySB - self.callout = values.callout - self.calloutSB = values.calloutSB - self.footnote = values.footnote - self.footnoteSB = values.footnoteSB - self.caption1 = values.caption1 - self.caption1SB = values.caption1SB - self.caption2 = values.caption2 - self.caption2SB = values.caption2SB + self.largeTitle = values.largeTitle.uiFont + self.largeTitleB = values.largeTitleB.uiFont + self.title1 = values.title1.uiFont + self.title1B = values.title1B.uiFont + self.title2 = values.title2.uiFont + self.title2B = values.title2B.uiFont + self.title3 = values.title3.uiFont + self.title3SB = values.title3SB.uiFont + self.headline = values.headline.uiFont + self.subheadline = values.subheadline.uiFont + self.body = values.body.uiFont + self.bodySB = values.bodySB.uiFont + self.callout = values.callout.uiFont + self.calloutSB = values.calloutSB.uiFont + self.footnote = values.footnote.uiFont + self.footnoteSB = values.footnoteSB.uiFont + self.caption1 = values.caption1.uiFont + self.caption1SB = values.caption1SB.uiFont + self.caption2 = values.caption2.uiFont + self.caption2SB = values.caption2SB.uiFont } } diff --git a/DesignKit/Variants/Fonts/ElementFonts.swift b/DesignKit/Variants/Fonts/ElementFonts.swift index 6612d3dc1..d7538c905 100644 --- a/DesignKit/Variants/Fonts/ElementFonts.swift +++ b/DesignKit/Variants/Fonts/ElementFonts.swift @@ -14,12 +14,42 @@ // limitations under the License. // -import UIKit +import SwiftUI /// Fonts at https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=1362%3A0 @objcMembers public class ElementFonts { + // MARK: - Types + + /// A wrapper to provide both a `UIFont` and a SwiftUI `Font` in the same type. + /// The need for this comes from `Font` not adapting for dynamic type until the app + /// is restarted (or working at all in Xcode Previews) when initialised from a `UIFont` + /// (even if that font was created with the appropriate metrics). + public struct SharedFont { + public let uiFont: UIFont + /// The underlying font for the `font` property. This is stored + /// as an optional `Any` due to unavailability on iOS 12. + private let _font: Any? + + @available(iOS 13.0, *) + public var font: Font { + _font as! Font + } + + @available(iOS, deprecated: 13.0, message: "Use init(uiFont:font:) instead and remove this initialiser.") + init(uiFont: UIFont) { + self.uiFont = uiFont + self._font = nil + } + + @available(iOS 13.0, *) + init(uiFont: UIFont, font: Font) { + self.uiFont = uiFont + self._font = font + } + } + // MARK: - Setup public init() { @@ -35,85 +65,217 @@ public class ElementFonts { } // MARK: - Fonts protocol -extension ElementFonts: Fonts { +extension ElementFonts: Fonts { - public var largeTitle: UIFont { - return self.font(forTextStyle: .largeTitle) + public var largeTitle: SharedFont { + let uiFont = self.font(forTextStyle: .largeTitle) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .largeTitle) + } else { + return SharedFont(uiFont: uiFont) + } } - public var largeTitleB: UIFont { - return self.largeTitle.vc_bold + public var largeTitleB: SharedFont { + let uiFont = self.largeTitle.uiFont.vc_bold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .largeTitle.bold()) + } else { + return SharedFont(uiFont: uiFont) + } } - public var title1: UIFont { - return self.font(forTextStyle: .title1) + public var title1: SharedFont { + let uiFont = self.font(forTextStyle: .title1) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .title) + } else { + return SharedFont(uiFont: uiFont) + } } - public var title1B: UIFont { - return self.title1.vc_bold + public var title1B: SharedFont { + let uiFont = self.title1.uiFont.vc_bold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .title.bold()) + } else { + return SharedFont(uiFont: uiFont) + } } - public var title2: UIFont { - return self.font(forTextStyle: .title2) + public var title2: SharedFont { + let uiFont = self.font(forTextStyle: .title2) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: Font(uiFont)) + } else if #available(iOS 14.0, *) { + return SharedFont(uiFont: uiFont, font: .title2) + } else { + return SharedFont(uiFont: uiFont) + } } - public var title2B: UIFont { - return self.title2.vc_bold + public var title2B: SharedFont { + let uiFont = self.title2.uiFont.vc_bold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: Font(uiFont)) + } else if #available(iOS 14.0, *) { + return SharedFont(uiFont: uiFont, font: .title2.bold()) + } else { + return SharedFont(uiFont: uiFont) + } } - public var title3: UIFont { - return self.font(forTextStyle: .title3) + public var title3: SharedFont { + let uiFont = self.font(forTextStyle: .title3) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: Font(uiFont)) + } else if #available(iOS 14.0, *) { + return SharedFont(uiFont: uiFont, font: .title3) + } else { + return SharedFont(uiFont: uiFont) + } } - public var title3SB: UIFont { - return self.title3.vc_semiBold + public var title3SB: SharedFont { + let uiFont = self.title3.uiFont.vc_semiBold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: Font(uiFont)) + } else if #available(iOS 14.0, *) { + return SharedFont(uiFont: uiFont, font: .title3.weight(.semibold)) + } else { + return SharedFont(uiFont: uiFont) + } } - public var headline: UIFont { - return self.font(forTextStyle: .headline) + public var headline: SharedFont { + let uiFont = self.font(forTextStyle: .headline) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .headline) + } else { + return SharedFont(uiFont: uiFont) + } } - public var subheadline: UIFont { - return self.font(forTextStyle: .subheadline) + public var subheadline: SharedFont { + let uiFont = self.font(forTextStyle: .subheadline) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .subheadline) + } else { + return SharedFont(uiFont: uiFont) + } } - public var body: UIFont { - return self.font(forTextStyle: .body) + public var body: SharedFont { + let uiFont = self.font(forTextStyle: .body) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .body) + } else { + return SharedFont(uiFont: uiFont) + } } - public var bodySB: UIFont { - return self.body.vc_semiBold + public var bodySB: SharedFont { + let uiFont = self.body.uiFont.vc_semiBold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .body.weight(.semibold)) + } else { + return SharedFont(uiFont: uiFont) + } } - public var callout: UIFont { - return self.font(forTextStyle: .callout) + public var callout: SharedFont { + let uiFont = self.font(forTextStyle: .callout) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .callout) + } else { + return SharedFont(uiFont: uiFont) + } } - public var calloutSB: UIFont { - return self.callout.vc_semiBold + public var calloutSB: SharedFont { + let uiFont = self.callout.uiFont.vc_semiBold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .callout.weight(.semibold)) + } else { + return SharedFont(uiFont: uiFont) + } } - public var footnote: UIFont { - return self.font(forTextStyle: .footnote) + public var footnote: SharedFont { + let uiFont = self.font(forTextStyle: .footnote) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .footnote) + } else { + return SharedFont(uiFont: uiFont) + } } - public var footnoteSB: UIFont { - return self.footnote.vc_semiBold + public var footnoteSB: SharedFont { + let uiFont = self.footnote.uiFont.vc_semiBold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .footnote.weight(.semibold)) + } else { + return SharedFont(uiFont: uiFont) + } } - public var caption1: UIFont { - return self.font(forTextStyle: .caption1) + public var caption1: SharedFont { + let uiFont = self.font(forTextStyle: .caption1) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .caption) + } else { + return SharedFont(uiFont: uiFont) + } } - public var caption1SB: UIFont { - return self.caption1.vc_semiBold + public var caption1SB: SharedFont { + let uiFont = self.caption1.uiFont.vc_semiBold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: .caption.weight(.semibold)) + } else { + return SharedFont(uiFont: uiFont) + } } - public var caption2: UIFont { - return self.font(forTextStyle: .caption2) + public var caption2: SharedFont { + let uiFont = self.font(forTextStyle: .caption2) + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: Font(uiFont)) + } else if #available(iOS 14.0, *) { + return SharedFont(uiFont: uiFont, font: .caption2) + } else { + return SharedFont(uiFont: uiFont) + } } - public var caption2SB: UIFont { - return self.caption2.vc_semiBold + public var caption2SB: SharedFont { + let uiFont = self.caption2.uiFont.vc_semiBold + + if #available(iOS 13.0, *) { + return SharedFont(uiFont: uiFont, font: Font(uiFont)) + } else if #available(iOS 14.0, *) { + return SharedFont(uiFont: uiFont, font: .caption2.weight(.semibold)) + } else { + return SharedFont(uiFont: uiFont) + } } } diff --git a/changelog.d/5027.bugfix b/changelog.d/5027.bugfix new file mode 100644 index 000000000..0b947aed0 --- /dev/null +++ b/changelog.d/5027.bugfix @@ -0,0 +1 @@ +Fonts: Fix dynamic type only working after a fresh launch on SwiftUI views. \ No newline at end of file From 87615f86555b2c6533aead66621562cff2261a51 Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 22 Feb 2022 11:46:18 +0300 Subject: [PATCH 180/188] Enable usage of thread timelines --- Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m index 88bd02a44..9049ef4ec 100644 --- a/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m +++ b/Riot/Modules/MatrixKit/Models/Room/MXKRoomDataSource.m @@ -34,7 +34,7 @@ #import "MXKSendReplyEventStringLocalizer.h" #import "MXKSlashCommands.h" -const BOOL USE_THREAD_TIMELINE = NO; +const BOOL USE_THREAD_TIMELINE = YES; #pragma mark - Constant definitions From 0678fd3d1776eac83595fe200805b1699917cb0d Mon Sep 17 00:00:00 2001 From: ismailgulek Date: Tue, 22 Feb 2022 11:47:51 +0300 Subject: [PATCH 181/188] Add changelog --- changelog.d/5629.change | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5629.change diff --git a/changelog.d/5629.change b/changelog.d/5629.change new file mode 100644 index 000000000..d0d508b60 --- /dev/null +++ b/changelog.d/5629.change @@ -0,0 +1 @@ +MXKRoomDataSource: Enable usage of thread timelines. From 327c5faba18cfe896eefe7699ee0488dc77f47e6 Mon Sep 17 00:00:00 2001 From: tarekharms Date: Mon, 21 Feb 2022 13:54:49 +0000 Subject: [PATCH 182/188] Translated using Weblate (German) Currently translated at 99.8% (1431 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index b249302d5..c8244e25a 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -1076,8 +1076,8 @@ "key_verification_manually_verify_device_additional_information" = "Falls sie nicht übereinstimmen, wurde die Kommunikation vielleicht kompromittiert."; "key_verification_verified_new_session_title" = "Neue Sitzung verifiziert!"; "key_verification_verified_other_session_information" = "Du kannst nun sichere Nachrichten in deiner anderen Sitzung lesen. Andere Benutzer wissen, dass sie ihr vertrauen können."; -"key_verification_verified_new_session_information" = "Du kannst nun sichere Nachrichten auf deinem neuen Gerät lesen. Andere Benutzer wissen, dass sie es vertrauen können."; -"key_verification_verified_this_session_information" = "Du kannst nun sichere Nachrichten auf diesem Gerät lesen. Andere Benutzer wissen, dass sie es vertrauen können."; +"key_verification_verified_new_session_information" = "Du kannst nun sichere Nachrichten auf deinem neuen Gerät lesen. Andere Benutzer wissen, dass sie ihm vertrauen können."; +"key_verification_verified_this_session_information" = "Du kannst nun sichere Nachrichten auf diesem Gerät lesen. Andere Benutzer wissen, dass sie ihm vertrauen können."; "key_verification_verified_user_information" = "Nachrichten mit diesem Gegenüber sind Ende-zu-Ende verschlüsselt und können nicht von Dritten gelesen werden."; "key_verification_bootstrap_not_setup_title" = "Fehler"; "key_verification_bootstrap_not_setup_message" = "Du musst erst die Quersignatur einrichten."; From de0f7de89fbdb0505811866812fe8e8ef970ef5c Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Tue, 22 Feb 2022 09:06:29 +0000 Subject: [PATCH 183/188] Translated using Weblate (Japanese) Currently translated at 68.3% (980 of 1433 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ja/ --- Riot/Assets/ja.lproj/Vector.strings | 50 ++++++++++++++++------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/Riot/Assets/ja.lproj/Vector.strings b/Riot/Assets/ja.lproj/Vector.strings index c62e28a30..6e9584a13 100644 --- a/Riot/Assets/ja.lproj/Vector.strings +++ b/Riot/Assets/ja.lproj/Vector.strings @@ -1,14 +1,14 @@ // Titles "title_home" = "ホーム"; "title_favourites" = "お気に入り"; -"title_people" = "対話"; +"title_people" = "連絡先"; "title_rooms" = "ルーム"; "warning" = "警告"; // Actions "view" = "表示"; "next" = "次へ"; "back" = "戻る"; -"continue" = "続く"; +"continue" = "続ける"; "create" = "作成"; "start" = "開始"; "leave" = "退出"; @@ -55,7 +55,7 @@ "auth_invalid_login_param" = "ユーザー名かパスワードが正しくありません"; "auth_invalid_user_name" = "ユーザー名は半角英数字、ドット、ハイフン、アンダスコアのみで記して下さい"; "auth_invalid_password" = "パスワードが短すぎます(最小6文字)"; -"auth_invalid_email" = "正しくないメールアドレスのようです"; +"auth_invalid_email" = "メールアドレスの形式が正しくありません"; "auth_invalid_phone" = "正しくない電話番号のようです"; "auth_missing_password" = "パスワードが入力されていません"; "auth_add_email_message" = "電子メールアドレスを登録すると, 誰かがあなたを検索をしたり, パスワード紛失時に初期化のメールを送ることができます."; @@ -77,7 +77,7 @@ "auth_msisdn_validation_title" = "認証を確認中"; "auth_msisdn_validation_message" = "SMSで認証番号を送りました。以下にその番号を入力してください。"; "auth_msisdn_validation_error" = "電話番号を認証できません。"; -"auth_recaptcha_message" = "接続先サーバー側が、機械による自動登録ではなく、あなたが人間であることを確認したいとのことです"; +"auth_recaptcha_message" = "このホームサーバーは、あなたがロボットではないことの確認を求めています"; "auth_reset_password_message" = "Matrixのアカウントのパスワードを初期化するには、アカウントに登録されているメールアドレスを入力してください:"; "auth_reset_password_missing_email" = "あなたのアカウントに登録されたメールアドレスの入力が必要です。"; "auth_reset_password_missing_password" = "新しいパスワードの入力が必要です。"; @@ -88,7 +88,7 @@ "auth_reset_password_success_message" = "あなたのパスワードは初期化されました。\n\nあなたは全てのセッションから切断しており、プッシュ通知を受け取ることはありません。通知を再度有効にするには、各端末に再度ログインします。"; "auth_add_email_and_phone_warning" = "電子メールと電話番号の同時登録は、まだシステムが対応できません。電話番号だけの登録は可能です。お手数おかけしますが、後ほど個人情報設定からメールアドレスを登録してください。"; // Chat creation -"room_creation_title" = "新しい対話"; +"room_creation_title" = "チャットを開始"; "room_creation_account" = "アカウント"; "room_creation_appearance" = "外観"; "room_creation_appearance_name" = "名前"; @@ -106,12 +106,12 @@ // Room recents "room_recents_directory_section" = "ルーム一覧"; "room_recents_favourites_section" = "お気に入り"; -"room_recents_people_section" = "対話"; +"room_recents_people_section" = "連絡先"; "room_recents_conversations_section" = "ルーム"; "room_recents_no_conversation" = "ルームがありません"; "room_recents_low_priority_section" = "低優先度"; "room_recents_invites_section" = "招待中"; -"room_recents_start_chat_with" = "対話を開始"; +"room_recents_start_chat_with" = "チャットを開始"; "room_recents_create_empty_room" = "ルームを作成"; "room_recents_join_room" = "ルームへ参加"; "room_recents_join_room_title" = "ルームへ参加"; @@ -125,7 +125,7 @@ // Search "search_rooms" = "ルーム"; "search_messages" = "メッセージ"; -"search_people" = "対話"; +"search_people" = "連絡先"; "search_files" = "添付ファイル"; "search_default_placeholder" = "検索"; "search_people_placeholder" = "ユーザーID、表示名、電子メールで検索"; @@ -171,7 +171,7 @@ "room_participants_now" = "現在"; "room_participants_ago" = "前"; "room_participants_action_section_admin_tools" = "管理者権限操作"; -"room_participants_action_section_direct_chats" = "対話"; +"room_participants_action_section_direct_chats" = "非公開のチャット"; "room_participants_action_section_devices" = "セッション一覧"; "room_participants_action_section_other" = "オプション"; "room_participants_action_invite" = "招待"; @@ -184,7 +184,7 @@ "room_participants_action_set_default_power_level" = "権限を一般ユーザーへ変更"; "room_participants_action_set_moderator" = "権限をモデレーターへ変更"; "room_participants_action_set_admin" = "権限を管理者へ変更"; -"room_participants_action_start_new_chat" = "対話を開始"; +"room_participants_action_start_new_chat" = "チャットを開始"; "room_participants_action_start_voice_call" = "音声通話を開始"; "room_participants_action_start_video_call" = "映像付き音声通話を開始"; "room_participants_action_mention" = "メンション"; @@ -410,7 +410,7 @@ "public_room_section_title" = "公開ルーム(%@ にて):"; "bug_report_prompt" = "前回アプリが異常終了しました。バグレポートを送信しますか?"; "rage_shake_prompt" = "あなたは不満があって端末を揺らしているようです。バグレポートをしますか?"; -"do_not_ask_again" = "再度質問しない"; +"do_not_ask_again" = "再び表示しない"; "camera_access_not_granted" = "%@はカメラを使用する権限を持っていません。個人情報保護設定の変更をお願いします"; "large_badge_value_k_format" = "%.1fK"; // room display name @@ -478,10 +478,10 @@ "room_event_action_kick_prompt_reason" = "このユーザーを追放する理由"; "room_action_send_photo_or_video" = "写真か動画を送る"; "room_action_send_sticker" = "スタンプ送信"; -"room_replacement_information" = "このルームは交換されており、もうアクティブではありません。"; -"room_replacement_link" = "会話はここで続けられます。"; +"room_replacement_information" = "このルームは交換されており、使用されていません。"; +"room_replacement_link" = "こちらから継続中の会話を確認する。"; "room_predecessor_information" = "このルームは別の会話の続きです。"; -"room_predecessor_link" = "より古いメッセージを見るにはここをタップしてください。"; +"room_predecessor_link" = "以前のメッセージを見るには、ここをタップしてください。"; "room_resource_limit_exceeded_message_contact_2_link" = "サービス管理者に連絡"; "room_resource_limit_exceeded_message_contact_3" = " このサービスの使用を継続するには。"; "room_resource_usage_limit_reached_message_1_default" = "このホームサーバーはリソース制限の1つを超えています "; @@ -543,7 +543,7 @@ "deactivate_account_informations_part2_emphasize" = "この動作は元に戻せません。"; "deactivate_account_informations_part3" = "\n\nアカウントの無効化 "; "deactivate_account_informations_part4_emphasize" = "デフォルトではあなたが送信したメッセージを忘れることはありません。 "; -"deactivate_account_informations_part5" = "あなたのメッセージを忘れたければ、下のボックスにチェックを入れてください\n\nMatrixのメッセージの可視性はEメールと似ています。 forgettingメッセージは、送信したメッセージは新規または未登録のユーザーと共有されませんが、既にこれらのメッセージにアクセスしている登録ユーザーは引き続き自分のコピーにアクセスできます。"; +"deactivate_account_informations_part5" = "メッセージの履歴の消去を望む場合は、以下のボックスにチェックを入れてください。\n\nMatrixのメッセージの見え方は、電子メールと同様のものです。メッセージの履歴を消去すると、あなたが送信したメッセージは、新規または未登録のユーザーに共有されることはありませんが、既にメッセージを取得している登録ユーザーは、今後もそのコピーにアクセスできます。"; "deactivate_account_forget_messages_information_part1" = "アカウントが無効になったときに送信した全てのメッセージを忘れてください ("; "deactivate_account_forget_messages_information_part2_emphasize" = "警告"; "deactivate_account_forget_messages_information_part3" = ":これは将来のユーザーに会話の不完全なビューが表示される)"; @@ -689,7 +689,7 @@ "room_details_title_for_dm" = "詳細"; "identity_server_settings_alert_error_invalid_identity_server" = "%@は有効なIDサーバーではありません。"; "identity_server_settings_alert_error_terms_not_accepted" = "IDサーバーとして設定するには%@の条件を受け入れる必要があります。"; -"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "とにかく切断"; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "無視して切断"; "identity_server_settings_alert_disconnect_still_sharing_3pid" = "あなたはまだIDサーバー%@で個人データを共有しています。\n\n切断する前にメールアドレスと電話番号をIDサーバーから削除することをお勧めします。"; "identity_server_settings_alert_disconnect_button" = "接続を解除"; "identity_server_settings_alert_disconnect" = "IDサーバー%@を接続解除しますか?"; @@ -703,7 +703,7 @@ "identity_server_settings_change" = "変更"; "identity_server_settings_add" = "追加"; "identity_server_settings_place_holder" = "IDサーバーを入力"; -"identity_server_settings_no_is_description" = "現在、IDサーバーを使用していません。知り合いを発見したり、発見できるようにするには、上記に追加してください。"; +"identity_server_settings_no_is_description" = "現在、IDサーバーを使用していません。あなたの知っている連絡先を発見したり、その連絡先から発見されるようにするには、以上でIDサーバーを追加してください。"; "identity_server_settings_description" = "あなたは%@を使って、あなたの知り合いを発見し、また向こうから発見できるようにしています。"; "security_settings_complete_security_alert_title" = "セキュリティーを確認"; "security_settings_crosssigning_complete_security" = "セキュリティーを確認"; @@ -811,7 +811,7 @@ // Manage session "manage_session_title" = "セッションを管理"; -"security_settings_user_password_description" = "アカウントのパスワードを入力して本人確認を行う"; +"security_settings_user_password_description" = "アカウントのパスワードを入力して本人確認を行ってください"; "security_settings_coming_soon" = "申し訳ありません。このアクションはElement iOSではまだ利用できません。他のMatrixクライアントを使って設定してください。将来的にはElement iOSでも実装される予定です。"; "security_settings_complete_security_alert_message" = "現在のセッションのセキュリティーを完了させる必要があります。"; "security_settings_blacklist_unverified_devices_description" = "全てのセッションを検証して、信頼できるものとしてマークしメッセージを送信します。"; @@ -838,7 +838,7 @@ // Security settings "security_settings_title" = "セキュリティー"; "settings_show_NSFW_public_rooms" = "NSFWパブリックルームを表示"; -"settings_identity_server_no_is_description" = "現在、IDサーバーを使用していません。知り合いを発見したり発見されるようにするには1つ連絡先を追加します。"; +"settings_identity_server_no_is_description" = "現在、IDサーバーを使用していません。あなたの知っている連絡先を発見したり、その連絡先から発見されるようにするには、以上でIDサーバーを追加してください。"; "settings_identity_server_no_is" = "IDサーバーが設定されていません"; "settings_identity_server_description" = "上記で設定したIDサーバーを使って、自分の知り合いを発見したり、発見されたりすることができます。"; "settings_discovery_three_pid_details_enter_sms_code_action" = "SMSアクティベーションコードを入力"; @@ -853,8 +853,8 @@ "settings_discovery_three_pids_management_information_part3" = "。"; "settings_discovery_three_pids_management_information_part2" = "ユーザー設定"; "settings_discovery_three_pids_management_information_part1" = "他のユーザーがあなたを発見したり、ルームに招待する際に使用するメールアドレスや電話番号を管理できます。このリストにメールアドレスや電話番号を追加したり、削除したりすることができます。 "; -"settings_discovery_terms_not_signed" = "メールアドレスや電話番号で自分を発見できるようにするには、IDサーバー(%@)の利用規約に同意する必要があります。"; -"settings_discovery_no_identity_server" = "現在、IDサーバーを使用していません。知り合いがあなたを発見できるようにするには、IDサーバーを追加してください。"; +"settings_discovery_terms_not_signed" = "メールアドレスか電話番号でアカウントを見つけてもらえるようにするには、IDサーバー(%@)の利用規約への同意が必要です。"; +"settings_discovery_no_identity_server" = "現在、IDサーバーを使用していません。あなたの知っている連絡先から発見されるようにするには、IDサーバーを追加してください。"; "settings_key_backup_delete_confirmation_prompt_msg" = "よろしいですか?鍵が適切にバックアップされていないと、暗号化されたメッセージを失うことがあります。"; "settings_key_backup_button_connect" = "このセッションを鍵のバックアップに接続"; "settings_key_backup_button_delete" = "バックアップの削除"; @@ -1002,7 +1002,7 @@ "external_link_confirmation_title" = "このリンクを再確認してください"; "media_type_accessibility_sticker" = "スティッカー"; "media_type_accessibility_file" = "ファイル"; -"media_type_accessibility_location" = "ロケーション"; +"media_type_accessibility_location" = "位置情報"; "media_type_accessibility_video" = "動画"; "media_type_accessibility_audio" = "音声"; "media_type_accessibility_image" = "画像"; @@ -1079,7 +1079,7 @@ "device_verification_self_verify_wait_title" = "セキュリティーを確認"; "location_sharing_open_google_maps" = "Googleマップで開く"; -"location_sharing_settings_toggle_title" = "ロケーションの共有を有効にする"; +"location_sharing_settings_toggle_title" = "位置情報の共有を有効にする"; "threads_empty_show_all_threads" = "全てのスレッドを表示"; "room_join_group_call" = "参加"; "room_accessibility_threads" = "スレッド"; @@ -1145,3 +1145,7 @@ // Intro "secure_key_backup_setup_intro_title" = "セキュアバックアップ"; +"spaces_explore_rooms" = "ルームを探索"; +"secure_key_backup_setup_intro_use_security_key_info" = "セキュリティーキーを生成します。パスワードマネージャーもしくは金庫のような安全な場所で保管してください。"; +"secure_key_backup_setup_intro_info" = "サーバー上の暗号鍵をバックアップして、暗号化されたメッセージとデータへのアクセスが失われるのを防ぎましょう。"; +"secure_backup_setup_banner_subtitle" = "暗号化されたメッセージとデータへのアクセスが失われるのを防ぎましょう"; From 77040779367da9688b35c5822988be2d38f60c55 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Mon, 21 Feb 2022 14:03:17 +0000 Subject: [PATCH 184/188] Translated using Weblate (Japanese) Currently translated at 100.0% (7 of 7 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/ja/ --- Riot/Assets/ja.lproj/InfoPlist.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ja.lproj/InfoPlist.strings b/Riot/Assets/ja.lproj/InfoPlist.strings index 48a69c382..29532a6d2 100644 --- a/Riot/Assets/ja.lproj/InfoPlist.strings +++ b/Riot/Assets/ja.lproj/InfoPlist.strings @@ -5,4 +5,4 @@ "NSContactsUsageDescription" = "Elementは、あなたが連絡先をチャットに招待できるように、連絡先を表示します。"; "NSCalendarsUsageDescription" = "予定されているミーティングをアプリで確認することができます。"; "NSFaceIDUsageDescription" = "Face IDはアプリへのアクセスに使用されます。"; -"NSLocationWhenInUseUsageDescription" = "ロケーションを共有する際には、地図を表示するためのアクセスをElementに付与する必要があります。"; +"NSLocationWhenInUseUsageDescription" = "位置情報を共有する際には、地図を表示するためのアクセスをElementに付与する必要があります。"; From 1855c6c28dbe2b5eae5806fadb13a63ee7dbfc10 Mon Sep 17 00:00:00 2001 From: Suguru Hirahara Date: Tue, 22 Feb 2022 10:20:30 +0000 Subject: [PATCH 185/188] Translated using Weblate (Japanese) Currently translated at 85.2% (377 of 442 strings) Translation: Element iOS/Element iOS (MatrixKit) Translate-URL: https://translate.element.io/projects/riot-ios/element-ios-matrixkit/ja/ --- .../ja.lproj/MatrixKit.strings | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings index b6596eab2..b6611ded7 100644 --- a/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings +++ b/Riot/Modules/MatrixKit/Assets/MatrixKitAssets.bundle/ja.lproj/MatrixKit.strings @@ -12,7 +12,7 @@ "yes" = "はい"; "back" = "戻る"; "close" = "閉じる"; -"continue" = "続く"; +"continue" = "続ける"; "sign_up" = "登録"; "resend_message" = "メッセージを再送信"; "select_all" = "全て選択"; @@ -59,7 +59,7 @@ "start_chat" = "チャットを開始"; "start_voice_call" = "音声通話を開始"; "start_video_call" = "ビデオ通話を開始"; -"mention" = "記載"; +"mention" = "メンション"; "select_account" = "アカウントを選択"; "attach_media" = "ライブラリからメディアを添付"; "capture_media" = "写真/ビデオを撮る"; @@ -159,8 +159,8 @@ "account_link_email" = "リンクメール"; "account_linked_emails" = "リンクされたメール"; "account_email_validation_title" = "認証の保留中"; -"account_email_validation_message" = "メールをチェックし、それに含まれているリンクをクリックしてください。 これが完了したら、[続行]をクリックします。"; -"account_email_validation_error" = "メールアドレスを確認できません。 あなたのメールをチェックし、それに含まれているリンクをクリックしてください。 これが完了したら、[続行]をクリックします"; +"account_email_validation_message" = "電子メールを確認して、本文中のURLをクリックしてください。完了したら「続行する」をクリックしてください。"; +"account_email_validation_error" = "メールアドレスを認証できません。メールを確認して、記載されているリンクをクリックしてください。その後、「続行する」をクリックしてください"; "account_msisdn_validation_title" = "認証の保留中"; "account_msisdn_validation_message" = "SMSで認証番号を送りました。以下にその番号を入力してください。"; "account_msisdn_validation_error" = "電話番号を確認できません。"; @@ -168,9 +168,9 @@ "account_error_picture_change_failed" = "画像の変更に失敗しました"; "account_error_matrix_session_is_not_opened" = "Matrixセッションが開かれていません"; "account_error_email_wrong_title" = "無効な電子メールアドレス"; -"account_error_email_wrong_description" = "これは有効なメールアドレスではないようです"; +"account_error_email_wrong_description" = "メールアドレスの形式が正しくありません"; "account_error_msisdn_wrong_title" = "無効な電話番号"; -"account_error_msisdn_wrong_description" = "これは有効な電話番号ではないようです"; +"account_error_msisdn_wrong_description" = "電話番号の形式が正しくありません"; // Room creation "room_creation_name_title" = "ルーム名:"; "room_creation_name_placeholder" = "(例 ランチグループ)"; From 1dc0dadfd2de309dfd3bb4d260b82045a731193a Mon Sep 17 00:00:00 2001 From: Doug <6060466+pixlwave@users.noreply.github.com> Date: Tue, 22 Feb 2022 11:30:43 +0000 Subject: [PATCH 186/188] Update Vector.strings --- Riot/Assets/tzm.lproj/Vector.strings | 5 ----- 1 file changed, 5 deletions(-) diff --git a/Riot/Assets/tzm.lproj/Vector.strings b/Riot/Assets/tzm.lproj/Vector.strings index e41ca4a51..229ee0c32 100644 --- a/Riot/Assets/tzm.lproj/Vector.strings +++ b/Riot/Assets/tzm.lproj/Vector.strings @@ -12,8 +12,3 @@ "invite" = "Ɣer"; "remove" = "Kkes"; "title_people" = "Midden"; -"settings_crypto_device_id" = ""; - -// MARK: - Home - -"home_empty_view_title" = ""; From 8b466b4cd0633ab8f6006d2d8bbae1307dc78360 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 22 Feb 2022 12:19:37 +0000 Subject: [PATCH 187/188] changelog.d: Upgrade MatrixSDK version ([v0.22.2](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.22.2)). --- Podfile | 2 +- changelog.d/x-nolink-0.change | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/x-nolink-0.change diff --git a/Podfile b/Podfile index b37f3c61b..4fd6535ef 100644 --- a/Podfile +++ b/Podfile @@ -13,7 +13,7 @@ use_frameworks! # - `{ :specHash => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for MatrixSDK repo. Used by Fastfile during CI # # Warning: our internal tooling depends on the name of this variable name, so be sure not to change it -$matrixSDKVersion = '= 0.22.1' +$matrixSDKVersion = '= 0.22.2' # $matrixSDKVersion = :local # $matrixSDKVersion = { :branch => 'develop'} # $matrixSDKVersion = { :specHash => { git: 'https://git.io/fork123', branch: 'fix' } } diff --git a/changelog.d/x-nolink-0.change b/changelog.d/x-nolink-0.change new file mode 100644 index 000000000..c9ca904cc --- /dev/null +++ b/changelog.d/x-nolink-0.change @@ -0,0 +1 @@ +Upgrade MatrixSDK version ([v0.22.2](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.22.2)). \ No newline at end of file From 4f67d332476f7d50948376c93a7cdfbd89a12100 Mon Sep 17 00:00:00 2001 From: Doug Date: Tue, 22 Feb 2022 12:19:38 +0000 Subject: [PATCH 188/188] version++ --- CHANGES.md | 52 +++++++++++++++++++++++++++++++++++ changelog.d/1433.bugfix | 1 - changelog.d/3562.bugfix | 1 - changelog.d/3736.bugfix | 1 - changelog.d/4103.bugfix | 1 - changelog.d/4829.change | 1 - changelog.d/5027.bugfix | 1 - changelog.d/5114.bugfix | 1 - changelog.d/5114.change | 1 - changelog.d/5160.feature | 1 - changelog.d/5250.change | 1 - changelog.d/5251.change | 1 - changelog.d/5346.bugfix | 1 - changelog.d/5355.bugfix | 1 - changelog.d/5409.misc | 1 - changelog.d/5471.change | 1 - changelog.d/5498.change | 1 - changelog.d/5521.bugfix | 1 - changelog.d/5537.bugfix | 1 - changelog.d/5540.change | 1 - changelog.d/5545.bugfix | 1 - changelog.d/5550.bugfix | 1 - changelog.d/5553.bugfix | 1 - changelog.d/5555.bugfix | 1 - changelog.d/5559.bugfix | 1 - changelog.d/5562.change | 1 - changelog.d/5582.change | 1 - changelog.d/5590.change | 1 - changelog.d/5602.bugfix | 1 - changelog.d/5609.change | 1 - changelog.d/5621.change | 1 - changelog.d/5629.change | 1 - changelog.d/5639.bugfix | 1 - changelog.d/pr-5513.misc | 1 - changelog.d/pr-5533.misc | 1 - changelog.d/pr-5556.misc | 1 - changelog.d/pr-5634.misc | 1 - changelog.d/x-nolink-0.change | 1 - 38 files changed, 52 insertions(+), 37 deletions(-) delete mode 100644 changelog.d/1433.bugfix delete mode 100644 changelog.d/3562.bugfix delete mode 100644 changelog.d/3736.bugfix delete mode 100644 changelog.d/4103.bugfix delete mode 100644 changelog.d/4829.change delete mode 100644 changelog.d/5027.bugfix delete mode 100644 changelog.d/5114.bugfix delete mode 100644 changelog.d/5114.change delete mode 100644 changelog.d/5160.feature delete mode 100644 changelog.d/5250.change delete mode 100644 changelog.d/5251.change delete mode 100644 changelog.d/5346.bugfix delete mode 100644 changelog.d/5355.bugfix delete mode 100644 changelog.d/5409.misc delete mode 100644 changelog.d/5471.change delete mode 100644 changelog.d/5498.change delete mode 100644 changelog.d/5521.bugfix delete mode 100644 changelog.d/5537.bugfix delete mode 100644 changelog.d/5540.change delete mode 100644 changelog.d/5545.bugfix delete mode 100644 changelog.d/5550.bugfix delete mode 100644 changelog.d/5553.bugfix delete mode 100644 changelog.d/5555.bugfix delete mode 100644 changelog.d/5559.bugfix delete mode 100644 changelog.d/5562.change delete mode 100644 changelog.d/5582.change delete mode 100644 changelog.d/5590.change delete mode 100644 changelog.d/5602.bugfix delete mode 100644 changelog.d/5609.change delete mode 100644 changelog.d/5621.change delete mode 100644 changelog.d/5629.change delete mode 100644 changelog.d/5639.bugfix delete mode 100644 changelog.d/pr-5513.misc delete mode 100644 changelog.d/pr-5533.misc delete mode 100644 changelog.d/pr-5556.misc delete mode 100644 changelog.d/pr-5634.misc delete mode 100644 changelog.d/x-nolink-0.change diff --git a/CHANGES.md b/CHANGES.md index c8f9b1ae3..78d2df426 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,55 @@ +## Changes in 1.8.2 (2022-02-22) + +✨ Features + +- Add Onboarding Use Case selection screen after the splash screen. ([#5160](https://github.com/vector-im/element-ios/issues/5160)) + +🙌 Improvements + +- Upgrade MatrixSDK version ([v0.22.2](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.22.2)). +- ActivityCenter: Use ActivityCenter to show loading indicators on the home screen (in DEBUG builds only) ([#4829](https://github.com/vector-im/element-ios/issues/4829)) +- Enabled poll editing and undisclosed polls. Added support for unstable poll prefixes. ([#5114](https://github.com/vector-im/element-ios/issues/5114)) +- Filter: update placeholder text and icon ([#5250](https://github.com/vector-im/element-ios/issues/5250)) +- Create Room: Update avatar placeholder & add remove button ([#5251](https://github.com/vector-im/element-ios/issues/5251)) +- Search: remove bubbles background ([#5471](https://github.com/vector-im/element-ios/issues/5471)) +- Exclude all files and directories from iCloud and iTunes backup ([#5498](https://github.com/vector-im/element-ios/issues/5498)) +- ThreadListViewModel: Use new apis to fetch threads. ([#5540](https://github.com/vector-im/element-ios/issues/5540)) +- Search: Use bundled aggregations if provided. ([#5562](https://github.com/vector-im/element-ios/issues/5562)) +- MXKRoomDataSource: Stop pagination in a thread when the root event received. ([#5582](https://github.com/vector-im/element-ios/issues/5582)) +- Add support for UserProperties to analytics and capture FTUE use case selection. ([#5590](https://github.com/vector-im/element-ios/issues/5590)) +- Add attribution to location sharing maps. ([#5609](https://github.com/vector-im/element-ios/issues/5609)) +- Onboarding: Use a different green spinner during onboarding and use the one presented by the LegacyAppDelegate only when logged in. ([#5621](https://github.com/vector-im/element-ios/issues/5621)) +- MXKRoomDataSource: Enable usage of thread timelines. ([#5629](https://github.com/vector-im/element-ios/issues/5629)) + +🐛 Bugfixes + +- Home Tab: Initial support for navigating through the room lists using voiceover. ([#1433](https://github.com/vector-im/element-ios/issues/1433)) +- Authent: fix phone number validation through custom URL ([#3562](https://github.com/vector-im/element-ios/issues/3562)) +- Fix registration to be compliant with the Matrix specification. This allows registering for accounts on Conduit servers. Contributed by @aaronraimist. ([#3736](https://github.com/vector-im/element-ios/issues/3736)) +- Fix proximity sensor staying on and sleep timer staying disabled after call ends ([#4103](https://github.com/vector-im/element-ios/issues/4103)) +- Fonts: Fix dynamic type only working after a fresh launch on SwiftUI views. ([#5027](https://github.com/vector-im/element-ios/issues/5027)) +- Fixed arithmetical exception errors when changing poll responses. ([#5114](https://github.com/vector-im/element-ios/issues/5114)) +- Wordings: Replace "kick" and all affiliate word by "remove" ([#5346](https://github.com/vector-im/element-ios/issues/5346)) +- Markdown/HTML: Fix HTTP links containing Markdown formatting ([#5355](https://github.com/vector-im/element-ios/issues/5355)) +- Message Bubbles: Fix read marker appearing part way thru a message. ([#5521](https://github.com/vector-im/element-ios/issues/5521)) +- HomeViewController: Refresh section badges and tab bar badges on updates. ([#5537](https://github.com/vector-im/element-ios/issues/5537)) +- Update the tintColor in ThemeV1 to sRGB to match the Compound and ThemeV2. ([#5545](https://github.com/vector-im/element-ios/issues/5545)) +- Message bubbles: Increase text message width. ([#5550](https://github.com/vector-im/element-ios/issues/5550)) +- Message bubbles: Fix edited text message `edited` link not working. ([#5553](https://github.com/vector-im/element-ios/issues/5553)) +- Message bubbles: Fix horizontal lines between messages. ([#5555](https://github.com/vector-im/element-ios/issues/5555)) +- App Launch: Fix a potential issue where the green spinner is kept on screen when the room lists are ready. ([#5559](https://github.com/vector-im/element-ios/issues/5559)) +- Authentication: Fix reCaptcha failing to indicate success. ([#5602](https://github.com/vector-im/element-ios/issues/5602)) +- Timeline: scroll to the bottom when opening a notification ([#5639](https://github.com/vector-im/element-ios/issues/5639)) + +Others + +- Fixed or ignored various project warnings for better DevX ([#5513](https://github.com/vector-im/element-ios/pull/5513)) +- SwiftGen: Objective-C support for assets helpers ([#5533](https://github.com/vector-im/element-ios/pull/5533)) +- Fix introspect not being able to theme the SwiftUI navigation bars. ([#5556](https://github.com/vector-im/element-ios/pull/5556)) +- Message bubbles: Reduce sender name bottom margin for text message. ([#5634](https://github.com/vector-im/element-ios/pull/5634)) +- Message bubbles: Use layout constants instead magic numbers. ([#5409](https://github.com/vector-im/element-ios/issues/5409)) + + ## Changes in 1.8.1 (2022-02-16) 🙌 Improvements diff --git a/changelog.d/1433.bugfix b/changelog.d/1433.bugfix deleted file mode 100644 index c4a5d04c7..000000000 --- a/changelog.d/1433.bugfix +++ /dev/null @@ -1 +0,0 @@ -Home Tab: Initial support for navigating through the room lists using voiceover. \ No newline at end of file diff --git a/changelog.d/3562.bugfix b/changelog.d/3562.bugfix deleted file mode 100644 index 8259627ad..000000000 --- a/changelog.d/3562.bugfix +++ /dev/null @@ -1 +0,0 @@ -Authent: fix phone number validation through custom URL \ No newline at end of file diff --git a/changelog.d/3736.bugfix b/changelog.d/3736.bugfix deleted file mode 100644 index a573977ac..000000000 --- a/changelog.d/3736.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix registration to be compliant with the Matrix specification. This allows registering for accounts on Conduit servers. Contributed by @aaronraimist. \ No newline at end of file diff --git a/changelog.d/4103.bugfix b/changelog.d/4103.bugfix deleted file mode 100644 index 2093e302e..000000000 --- a/changelog.d/4103.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix proximity sensor staying on and sleep timer staying disabled after call ends diff --git a/changelog.d/4829.change b/changelog.d/4829.change deleted file mode 100644 index e55f8b1fd..000000000 --- a/changelog.d/4829.change +++ /dev/null @@ -1 +0,0 @@ -ActivityCenter: Use ActivityCenter to show loading indicators on the home screen (in DEBUG builds only) diff --git a/changelog.d/5027.bugfix b/changelog.d/5027.bugfix deleted file mode 100644 index 0b947aed0..000000000 --- a/changelog.d/5027.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fonts: Fix dynamic type only working after a fresh launch on SwiftUI views. \ No newline at end of file diff --git a/changelog.d/5114.bugfix b/changelog.d/5114.bugfix deleted file mode 100644 index cb283d2ae..000000000 --- a/changelog.d/5114.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fixed arithmetical exception errors when changing poll responses. \ No newline at end of file diff --git a/changelog.d/5114.change b/changelog.d/5114.change deleted file mode 100644 index b2b42307b..000000000 --- a/changelog.d/5114.change +++ /dev/null @@ -1 +0,0 @@ -Enabled poll editing and undisclosed polls. Added support for unstable poll prefixes. \ No newline at end of file diff --git a/changelog.d/5160.feature b/changelog.d/5160.feature deleted file mode 100644 index 2d567e205..000000000 --- a/changelog.d/5160.feature +++ /dev/null @@ -1 +0,0 @@ -Add Onboarding Use Case selection screen after the splash screen. diff --git a/changelog.d/5250.change b/changelog.d/5250.change deleted file mode 100644 index 7c4d2e83f..000000000 --- a/changelog.d/5250.change +++ /dev/null @@ -1 +0,0 @@ -Filter: update placeholder text and icon diff --git a/changelog.d/5251.change b/changelog.d/5251.change deleted file mode 100644 index 7526212a7..000000000 --- a/changelog.d/5251.change +++ /dev/null @@ -1 +0,0 @@ -Create Room: Update avatar placeholder & add remove button diff --git a/changelog.d/5346.bugfix b/changelog.d/5346.bugfix deleted file mode 100644 index bd7103e6b..000000000 --- a/changelog.d/5346.bugfix +++ /dev/null @@ -1 +0,0 @@ -Wordings: Replace "kick" and all affiliate word by "remove" \ No newline at end of file diff --git a/changelog.d/5355.bugfix b/changelog.d/5355.bugfix deleted file mode 100644 index 131d61af5..000000000 --- a/changelog.d/5355.bugfix +++ /dev/null @@ -1 +0,0 @@ -Markdown/HTML: Fix HTTP links containing Markdown formatting diff --git a/changelog.d/5409.misc b/changelog.d/5409.misc deleted file mode 100644 index 6442410ad..000000000 --- a/changelog.d/5409.misc +++ /dev/null @@ -1 +0,0 @@ -Message bubbles: Use layout constants instead magic numbers. \ No newline at end of file diff --git a/changelog.d/5471.change b/changelog.d/5471.change deleted file mode 100644 index 195a7737f..000000000 --- a/changelog.d/5471.change +++ /dev/null @@ -1 +0,0 @@ -Search: remove bubbles background diff --git a/changelog.d/5498.change b/changelog.d/5498.change deleted file mode 100644 index 091816db7..000000000 --- a/changelog.d/5498.change +++ /dev/null @@ -1 +0,0 @@ -Exclude all files and directories from iCloud and iTunes backup diff --git a/changelog.d/5521.bugfix b/changelog.d/5521.bugfix deleted file mode 100644 index 64e6bcb98..000000000 --- a/changelog.d/5521.bugfix +++ /dev/null @@ -1 +0,0 @@ -Message Bubbles: Fix read marker appearing part way thru a message. \ No newline at end of file diff --git a/changelog.d/5537.bugfix b/changelog.d/5537.bugfix deleted file mode 100644 index 5da0cca4c..000000000 --- a/changelog.d/5537.bugfix +++ /dev/null @@ -1 +0,0 @@ -HomeViewController: Refresh section badges and tab bar badges on updates. diff --git a/changelog.d/5540.change b/changelog.d/5540.change deleted file mode 100644 index f885fdd8c..000000000 --- a/changelog.d/5540.change +++ /dev/null @@ -1 +0,0 @@ -ThreadListViewModel: Use new apis to fetch threads. diff --git a/changelog.d/5545.bugfix b/changelog.d/5545.bugfix deleted file mode 100644 index a9b8dbd3c..000000000 --- a/changelog.d/5545.bugfix +++ /dev/null @@ -1 +0,0 @@ -Update the tintColor in ThemeV1 to sRGB to match the Compound and ThemeV2. \ No newline at end of file diff --git a/changelog.d/5550.bugfix b/changelog.d/5550.bugfix deleted file mode 100644 index 194759b0d..000000000 --- a/changelog.d/5550.bugfix +++ /dev/null @@ -1 +0,0 @@ -Message bubbles: Increase text message width. diff --git a/changelog.d/5553.bugfix b/changelog.d/5553.bugfix deleted file mode 100644 index 803d9f9c1..000000000 --- a/changelog.d/5553.bugfix +++ /dev/null @@ -1 +0,0 @@ -Message bubbles: Fix edited text message `edited` link not working. diff --git a/changelog.d/5555.bugfix b/changelog.d/5555.bugfix deleted file mode 100644 index 2e8304d61..000000000 --- a/changelog.d/5555.bugfix +++ /dev/null @@ -1 +0,0 @@ -Message bubbles: Fix horizontal lines between messages. diff --git a/changelog.d/5559.bugfix b/changelog.d/5559.bugfix deleted file mode 100644 index 7f27180a0..000000000 --- a/changelog.d/5559.bugfix +++ /dev/null @@ -1 +0,0 @@ -App Launch: Fix a potential issue where the green spinner is kept on screen when the room lists are ready. \ No newline at end of file diff --git a/changelog.d/5562.change b/changelog.d/5562.change deleted file mode 100644 index 729c93acc..000000000 --- a/changelog.d/5562.change +++ /dev/null @@ -1 +0,0 @@ -Search: Use bundled aggregations if provided. diff --git a/changelog.d/5582.change b/changelog.d/5582.change deleted file mode 100644 index ba0081209..000000000 --- a/changelog.d/5582.change +++ /dev/null @@ -1 +0,0 @@ -MXKRoomDataSource: Stop pagination in a thread when the root event received. diff --git a/changelog.d/5590.change b/changelog.d/5590.change deleted file mode 100644 index 493e2d5a3..000000000 --- a/changelog.d/5590.change +++ /dev/null @@ -1 +0,0 @@ -Add support for UserProperties to analytics and capture FTUE use case selection. \ No newline at end of file diff --git a/changelog.d/5602.bugfix b/changelog.d/5602.bugfix deleted file mode 100644 index eb499b83b..000000000 --- a/changelog.d/5602.bugfix +++ /dev/null @@ -1 +0,0 @@ -Authentication: Fix reCaptcha failing to indicate success. \ No newline at end of file diff --git a/changelog.d/5609.change b/changelog.d/5609.change deleted file mode 100644 index b33dea26b..000000000 --- a/changelog.d/5609.change +++ /dev/null @@ -1 +0,0 @@ -Add attribution to location sharing maps. \ No newline at end of file diff --git a/changelog.d/5621.change b/changelog.d/5621.change deleted file mode 100644 index fbf80128c..000000000 --- a/changelog.d/5621.change +++ /dev/null @@ -1 +0,0 @@ -Onboarding: Use a different green spinner during onboarding and use the one presented by the LegacyAppDelegate only when logged in. diff --git a/changelog.d/5629.change b/changelog.d/5629.change deleted file mode 100644 index d0d508b60..000000000 --- a/changelog.d/5629.change +++ /dev/null @@ -1 +0,0 @@ -MXKRoomDataSource: Enable usage of thread timelines. diff --git a/changelog.d/5639.bugfix b/changelog.d/5639.bugfix deleted file mode 100644 index 757ab6fb4..000000000 --- a/changelog.d/5639.bugfix +++ /dev/null @@ -1 +0,0 @@ -Timeline: scroll to the bottom when opening a notification diff --git a/changelog.d/pr-5513.misc b/changelog.d/pr-5513.misc deleted file mode 100644 index f39615d48..000000000 --- a/changelog.d/pr-5513.misc +++ /dev/null @@ -1 +0,0 @@ -Fixed or ignored various project warnings for better DevX \ No newline at end of file diff --git a/changelog.d/pr-5533.misc b/changelog.d/pr-5533.misc deleted file mode 100644 index 6ba114e65..000000000 --- a/changelog.d/pr-5533.misc +++ /dev/null @@ -1 +0,0 @@ -SwiftGen: Objective-C support for assets helpers diff --git a/changelog.d/pr-5556.misc b/changelog.d/pr-5556.misc deleted file mode 100644 index 83d944af7..000000000 --- a/changelog.d/pr-5556.misc +++ /dev/null @@ -1 +0,0 @@ -Fix introspect not being able to theme the SwiftUI navigation bars. \ No newline at end of file diff --git a/changelog.d/pr-5634.misc b/changelog.d/pr-5634.misc deleted file mode 100644 index 2be0bab62..000000000 --- a/changelog.d/pr-5634.misc +++ /dev/null @@ -1 +0,0 @@ -Message bubbles: Reduce sender name bottom margin for text message. \ No newline at end of file diff --git a/changelog.d/x-nolink-0.change b/changelog.d/x-nolink-0.change deleted file mode 100644 index c9ca904cc..000000000 --- a/changelog.d/x-nolink-0.change +++ /dev/null @@ -1 +0,0 @@ -Upgrade MatrixSDK version ([v0.22.2](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.22.2)). \ No newline at end of file