diff --git a/.swiftlint.yml b/.swiftlint.yml index 8682b5912..765c414b4 100755 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -2,7 +2,6 @@ disabled_rules: - trailing_whitespace - todo - - conditional_binding_cascade - mark - vertical_whitespace - syntactic_sugar diff --git a/CHANGES.rst b/CHANGES.rst index 65bed365e..8b6537681 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,40 @@ +Changes in 1.4.6 (2021-07-16) +================================================= + +✨ Features + * + +🙌 Improvements + * Room Notification Settings: Ability to change between "All Messages", "Mentions and Keywords" and "None". Not yet exposed in Element UI. (#4458). + * Add support for sending slow motion videos (#4483). + +🐛 Bugfix + * VoIP: Do not present ended calls. + * More fixes to Main.storyboard layout on iPhone 12 Pro Max (#4527) + * Fix crash on Apple Silicon Macs. + * Media Picker: Generate video thumbnails with the correct orientation (#4515). + * Directory List (pop-up one): Fix duplicate rooms being shown (#4537). + * Use different title for scan button for self verification (#4525). + * it's easy for the back button to trigger a leftpanel reveal (#4438). + * Show / hide reset button in secrets recovery screen (#4546). + * Share Extension: Fix layout when searching (#4258). + * Timeline: Fix incorrect crop of media thumbnails (#4552). + +⚠️ API Changes + * + +🗣 Translations + * + +🧱 Build + * + +Others + * Silenced some documentation, deprecations and SwiftLint warnings. + +Improvements: + * Upgrade MatrixKit version ([v0.15.4](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.15.4)). + Changes in 1.4.5 (2021-07-07) ================================================= @@ -15,10 +52,13 @@ Changes in 1.4.5 (2021-07-07) 🗣 Translations * - + 🧱 Build * +Others + * + Changes in 1.4.4 (2021-06-30) ================================================= diff --git a/Config/AppIdentifiers.xcconfig b/Config/AppIdentifiers.xcconfig index 391931749..758906cac 100644 --- a/Config/AppIdentifiers.xcconfig +++ b/Config/AppIdentifiers.xcconfig @@ -22,8 +22,8 @@ APPLICATION_GROUP_IDENTIFIER = group.im.vector APPLICATION_SCHEME = element // Version -MARKETING_VERSION = 1.4.5 -CURRENT_PROJECT_VERSION = 1.4.5 +MARKETING_VERSION = 1.4.6 +CURRENT_PROJECT_VERSION = 1.4.6 // Team diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 3cfcf65dc..19c2ec733 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -295,6 +295,7 @@ final class BuildSettings: NSObject { static let roomSettingsScreenShowFlairSettings: Bool = true static let roomSettingsScreenShowAdvancedSettings: Bool = true static let roomSettingsScreenAdvancedShowEncryptToVerifiedOption: Bool = true + static let roomSettingsScreenShowNotificationsV2: Bool = false // MARK: - Room Member Screen @@ -320,6 +321,9 @@ final class BuildSettings: NSObject { static let authScreenShowForgotPassword = true static let authScreenShowCustomServerOptions = true - // Mark: - Unified Search + // MARK: - Unified Search static let unifiedSearchScreenShowPublicDirectory = true + + // MARK: - Secrets Recovery + static let secretsRecoveryAllowReset = true } diff --git a/Podfile b/Podfile index d008c31f2..2c4471394 100644 --- a/Podfile +++ b/Podfile @@ -11,7 +11,7 @@ use_frameworks! # - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each 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 -$matrixKitVersion = '= 0.15.3' +$matrixKitVersion = '= 0.15.4' # $matrixKitVersion = :local # $matrixKitVersion = {'develop' => 'develop'} diff --git a/Podfile.lock b/Podfile.lock index 8c6193dfa..8b171f979 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -56,29 +56,29 @@ PODS: - MatomoTracker (7.4.1): - MatomoTracker/Core (= 7.4.1) - MatomoTracker/Core (7.4.1) - - MatrixKit (0.15.3): + - MatrixKit (0.15.4): - Down (~> 0.11.0) - DTCoreText (~> 1.6.25) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixKit/Core (= 0.15.3) - - MatrixSDK (= 0.19.3) - - MatrixKit/Core (0.15.3): + - MatrixKit/Core (= 0.15.4) + - MatrixSDK (= 0.19.4) + - MatrixKit/Core (0.15.4): - Down (~> 0.11.0) - DTCoreText (~> 1.6.25) - HPGrowingTextView (~> 1.1) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.19.3) - - MatrixSDK (0.19.3): - - MatrixSDK/Core (= 0.19.3) - - MatrixSDK/Core (0.19.3): + - MatrixSDK (= 0.19.4) + - MatrixSDK (0.19.4): + - MatrixSDK/Core (= 0.19.4) + - MatrixSDK/Core (0.19.4): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - OLMKit (~> 3.2.4) - Realm (= 10.7.6) - SwiftyBeaver (= 1.9.5) - - MatrixSDK/JingleCallStack (0.19.3): + - MatrixSDK/JingleCallStack (0.19.4): - JitsiMeetSDK (= 3.5.0) - MatrixSDK/Core - OLMKit (3.2.4): @@ -120,7 +120,7 @@ DEPENDENCIES: - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - MatomoTracker (~> 7.4.1) - - MatrixKit (= 0.15.3) + - MatrixKit (= 0.15.4) - MatrixSDK - MatrixSDK/JingleCallStack - OLMKit @@ -196,8 +196,8 @@ SPEC CHECKSUMS: LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d Logging: beeb016c9c80cf77042d62e83495816847ef108b MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb - MatrixKit: 6cbe65db11a5450ec8cc02d51660f43b5e95a141 - MatrixSDK: c15663c67bfd2991d897d973c1551ba4de900e25 + MatrixKit: 477690d6dd38b1526042f8e83ff34e3db87e3a00 + MatrixSDK: 0c9d1845a45d71abcfcabe82b706cadbda1297ae OLMKit: 2d73cd67d149b5c3e3a8eb8ecae93d0b429d8a02 ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d Realm: ed860452717c8db8f4bf832b6807f7f2ce708839 @@ -211,6 +211,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: c39d88adc5ec2df412af32b64ceb99a9a1ee92a8 +PODFILE CHECKSUM: 2b61b852a5b62fbb75643a30281e362fd4566f12 COCOAPODS: 1.10.1 diff --git a/Riot/Assets/Base.lproj/Main.storyboard b/Riot/Assets/Base.lproj/Main.storyboard index aec7a4605..c562c4d0b 100644 --- a/Riot/Assets/Base.lproj/Main.storyboard +++ b/Riot/Assets/Base.lproj/Main.storyboard @@ -151,7 +151,7 @@ - + @@ -177,7 +177,7 @@ - + @@ -463,7 +463,7 @@ - + @@ -581,7 +581,7 @@ - + diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/Contents.json b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/Contents.json new file mode 100644 index 000000000..f60c4497c --- /dev/null +++ b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "room_action_notification_muted.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "room_action_notification_muted@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "room_action_notification_muted@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted.png new file mode 100644 index 000000000..02ca4c76f Binary files /dev/null and b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted.png differ diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted@2x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted@2x.png new file mode 100644 index 000000000..c264ba430 Binary files /dev/null and b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted@2x.png differ diff --git a/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted@3x.png b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted@3x.png new file mode 100644 index 000000000..b9738ab8b Binary files /dev/null and b/Riot/Assets/Images.xcassets/Home/RoomContextualMenu/room_action_notification_muted.imageset/room_action_notification_muted@3x.png differ diff --git a/Riot/Assets/Images.xcassets/Room/notifications.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/notifications.imageset/Contents.json new file mode 100644 index 000000000..66a053751 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/notifications.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "notifications.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "notifications@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "notifications@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications.png b/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications.png new file mode 100644 index 000000000..6b100741d Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications.png differ diff --git a/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications@2x.png b/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications@2x.png new file mode 100644 index 000000000..98d86c152 Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications@2x.png differ diff --git a/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications@3x.png b/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications@3x.png new file mode 100644 index 000000000..ddc1a6e7a Binary files /dev/null and b/Riot/Assets/Images.xcassets/Room/notifications.imageset/notifications@3x.png differ diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 234022cf2..4954f8c88 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -710,6 +710,7 @@ Tap the + to start adding people."; "room_details_topic" = "Topic"; "room_details_favourite_tag" = "Favourite"; "room_details_low_priority_tag" = "Low priority"; +"room_details_notifs" = "Notifications"; "room_details_mute_notifs" = "Mute notifications"; "room_details_direct_chat" = "Direct Chat"; "room_details_access_section"="Who can access this room?"; @@ -772,6 +773,17 @@ Tap the + to start adding people."; "room_details_copy_room_address" = "Copy Room Address"; "room_details_copy_room_url" = "Copy Room URL"; +// Room Notification Settings +"room_notifs_settings_notify_me_for" = "Notify me for"; +"room_notifs_settings_all_messages" = "All Messages"; +"room_notifs_settings_mentions_and_keywords" = "Mentions and Keywords only"; +"room_notifs_settings_none" = "None"; +"room_notifs_settings_done_action" = "Done"; +"room_notifs_settings_cancel_action" = "Cancel"; +"room_notifs_settings_manage_notifications" = "You can manage notifications in %@"; +"room_notifs_settings_account_settings" = "Account settings"; +"room_notifs_settings_encrypted_room_notice" = "Please note that mentions & keyword notifications are not available in encrypted rooms on mobile."; + // Group Details "group_details_title" = "Community Details"; "group_details_home" = "Home"; @@ -1375,6 +1387,7 @@ Tap the + to start adding people."; "key_verification_verify_qr_code_information_other_device" = "Scan the code below to verify:"; "key_verification_verify_qr_code_emoji_information" = "Verify by comparing unique emoji."; "key_verification_verify_qr_code_scan_code_action" = "Scan their code"; +"key_verification_verify_qr_code_scan_code_other_device_action" = "Scan with this device"; "key_verification_verify_qr_code_cannot_scan_action" = "Can't scan?"; "key_verification_verify_qr_code_start_emoji_action" = "Verify by emoji"; diff --git a/Riot/Assets/ja.lproj/Localizable.strings b/Riot/Assets/ja.lproj/Localizable.strings index 51a5c3d85..a2cbb08e6 100644 --- a/Riot/Assets/ja.lproj/Localizable.strings +++ b/Riot/Assets/ja.lproj/Localizable.strings @@ -50,3 +50,27 @@ "SINGLE_UNREAD_IN_ROOM" = "%@にメッセージを受け取りました"; /* A single unread message */ "SINGLE_UNREAD" = "あなたはメッセージを受け取りました"; + +/** Key verification **/ + +"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@は検証したい"; + +/* New message indicator on a room */ +"MESSAGE_IN_X" = "%@ 内のメッセージ"; + +/* Sticker from a specific person, not referencing a room. */ +"STICKER_FROM_USER" = "%@ さんからのスタンプ"; +/* Message title for a specific person in a named room */ +"MSG_FROM_USER_IN_ROOM_TITLE" = "%@(%@ から)"; + +/* Group call from user, CallKit caller name */ +"GROUP_CALL_FROM_USER" = "%@ (グループ通話)"; +"MESSAGE_PROTECTED" = "新しいメッセージ"; + +/* New message indicator from a DM */ +"MESSAGE_FROM_X" = "%@ からのメッセージ"; + +/** Notification messages **/ + +/* New message indicator on unknown room */ +"MESSAGE" = "メッセージ"; diff --git a/Riot/Assets/nb-NO.lproj/Localizable.strings b/Riot/Assets/nb-NO.lproj/Localizable.strings index 26102b751..5f6a77573 100644 --- a/Riot/Assets/nb-NO.lproj/Localizable.strings +++ b/Riot/Assets/nb-NO.lproj/Localizable.strings @@ -111,3 +111,9 @@ "MSG_FROM_USER" = "%@ sendte en melding"; /* Message title for a specific person in a named room */ "MSG_FROM_USER_IN_ROOM_TITLE" = "%@ i %@"; + +/* Group call from user, CallKit caller name */ +"GROUP_CALL_FROM_USER" = "%@ (Gruppeanrop)"; + +/* A user added a Jitsi call to a room */ +"GROUP_CALL_STARTED" = "Gruppeanrop startet"; diff --git a/Riot/Assets/nb-NO.lproj/Vector.strings b/Riot/Assets/nb-NO.lproj/Vector.strings index c47bf5f51..74f8d9e00 100644 --- a/Riot/Assets/nb-NO.lproj/Vector.strings +++ b/Riot/Assets/nb-NO.lproj/Vector.strings @@ -479,7 +479,7 @@ "settings_discovery_error_message" = "Det oppstod en feil. Vennligst prøv igjen."; "security_settings_crypto_sessions" = "MINE ØKTER"; "security_settings_secure_backup_setup" = "Sett opp"; -"security_settings_secure_backup_delete" = "Slett"; +"security_settings_secure_backup_delete" = "Slett sikkerhetskopi"; "security_settings_crosssigning_complete_security" = "Komplett sikkerhet"; "security_settings_cryptography" = "KRYPTOGRAFI"; "security_settings_complete_security_alert_title" = "Komplett sikkerhet"; @@ -513,7 +513,7 @@ "key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Bekreft passordfrasen"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Passordfrasen samsvarer ikke"; "key_backup_setup_passphrase_set_passphrase_action" = "Velg passordfrase"; -"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Gjenopprettingsnøkkel"; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Sikkerhetsnøkkel"; "key_backup_setup_success_from_recovery_key_make_copy_action" = "Lag en kpi"; "key_backup_setup_success_from_recovery_key_made_copy_action" = "Jeg har laget en kopi"; "key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Skriv inn gjenopprettingsnøkkelen"; @@ -834,7 +834,7 @@ "settings_key_backup_info_not_valid" = "Denne økten sikkerhetskopierer ikke dine nøkler, men du har en eksisterende sikkerhetskopi du kan gjenopprette fra og legge til, for å gå videre."; "settings_key_backup_info_valid" = "Denne økten sikkerhetskopierer dine nøkler."; "settings_key_backup_info_version" = "Sikkerhetskopi av nøkler versjon : %@"; -"settings_key_backup_info_signout_warning" = "Før du logger ut, koble denne sesjonen til sikkerhetskopi av nøkler for å unngå tap av nøkler som kanskje bare er lagret på denne enheten."; +"settings_key_backup_info_signout_warning" = "Sikkerhetskopier nøklene dine før du logger av for å unngå å miste dem."; "settings_key_backup_info_none" = "Nøklene dine for denne sesjonen blir ikke sikkerhetskopiert."; "settings_third_party_notices" = "Tredjepartsmerknader"; "settings_labs_e2e_encryption_prompt_message" = "Vennligst logg inn igjen for å ferdigstille oppsett av kryptering."; @@ -864,7 +864,7 @@ "pin_protection_not_allowed_pin" = "Av sikkerhetsårsaker er denne PIN-koden ikke tilgjengelig. Prøv en annen PIN-kode"; "secrets_setup_recovery_passphrase_information" = "Skriv inn en sikkerhetsfrase bare du kjenner, brukes til å sikre hemmeligheter på serveren."; "secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "bruke gjenopprettingsnøkkelen din"; -"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "bruke gjenopprettingsnøkkelen"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "bruk sikkerhetsnøkkelen"; "room_details_access_section_for_dm" = "Hvem har tilgang til dette?"; "identity_server_settings_place_holder" = "Legg inn en identitetsserver"; "identity_server_settings_description" = "Du bruker for øyeblikket %@ for å finne og bli funnet av dine eksisterende kontakter."; @@ -920,13 +920,13 @@ "security_settings_crosssigning" = "KRYSS-SIGNERING"; "security_settings_backup" = "SIKKERHETSKOPI-MELDINGER"; "security_settings_secure_backup_synchronise" = "Synkroniser"; -"security_settings_secure_backup_description" = "Sikre deg mot å miste tilgang til krypterte meldinger og data ved å lagre sikkerhetskopi av krypteringsnøkler på din server."; +"security_settings_secure_backup_description" = "Sikkerhetskopier krypteringsnøklene med kontodataene dine hvis du mister tilgangen til øktene dine. Nøklene dine blir sikret med en unik sikkerhetsnøkkel."; "security_settings_secure_backup" = "SIKKERHETSKOPI"; "security_settings_crosssigning_info_trusted" = "Kryss-signering er aktivert. Du kan stole på andre brukere og dine andre økter basert på kryss-signering, men du kan ikke kryss-signere fra denne økten fordi den ikke har private nøkler for kryss-signering. Fullfør sikkerheten for denne økten."; "security_settings_export_keys_manually" = "Eksporter nøkler manuelt"; -"security_settings_crosssigning_reset" = "Tilbakestill kryss-signering"; -"security_settings_crosssigning_bootstrap" = "Bootstrap kryss-signering"; -"security_settings_crosssigning_info_ok" = "Kryss-signering er aktivert."; +"security_settings_crosssigning_reset" = "Nullstill"; +"security_settings_crosssigning_bootstrap" = "Sett opp"; +"security_settings_crosssigning_info_ok" = "Kryss-signering er klar til bruk."; "security_settings_blacklist_unverified_devices" = "Aldri send meldinger til ikke-klarerte økter"; // AuthenticatedSessionViewControllerFactory @@ -1052,7 +1052,7 @@ "bug_report_prompt" = "Applikasjonen krasjet sist gang. Vil du sende inn en krasj-rapport?"; "public_room_section_title" = "Offentlige rom (på %@):"; "call_no_stun_server_error_message_2" = "Alternativt kan du prøve å bruke den offentlige serveren ved %@, men denne vil være mindre pålitelig, og vil dele din IP-adresse med serveren. Du kan også administrere dette i innstillinger"; -"e2e_key_backup_wrong_version" = "Det har blitt oppdaget en ny sikkerhetskopi av meldingsnøkler .\n\nHvis dette ikke ble intitiert av deg bør du endre passordfrase i innstillinger."; +"e2e_key_backup_wrong_version" = "Det har blitt oppdaget en ny sikkerhetskopi av meldingsnøkler .\n\nHvis dette ikke var deg, angir du en ny sikkerhetsfrase i Innstillinger."; // Key backup wrong version "e2e_key_backup_wrong_version_title" = "Ny sikkerhetskopi av nøkler"; @@ -1136,7 +1136,7 @@ "secure_key_backup_setup_intro_title" = "Sikkert lagringsområde"; "secure_key_backup_setup_intro_use_security_key_info" = "Generer en sikkerhetsnøkkel og lagre den på et trygt sted som i en passordadministrator eller en safe."; "secure_key_backup_setup_intro_use_security_key_title" = "Bruk en sikkerhetsnøkkel"; -"secure_key_backup_setup_intro_use_security_passphrase_title" = "Bruk en passordfrase"; +"secure_key_backup_setup_intro_use_security_passphrase_title" = "Bruk en sikkerhetsfrase"; "key_backup_setup_intro_manual_export_action" = "Eksporter nøkler manuelt"; "key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Koble denne enheten til sikkerhetskopi av meldingsnøkler"; "key_backup_setup_skip_alert_message" = "Du kan miste dine krypterte meldinger dersom du logger ut eller mister enheten."; @@ -1154,12 +1154,12 @@ "secure_key_backup_setup_existing_backup_error_info" = "Lås den opp for å gjenbruke den på sikkert lagringsområde, eller slett den for å opprette en ny sikkerhetskopi av meldinger på sikkert lagringsområde."; "secure_key_backup_setup_existing_backup_error_title" = "Det finnes allerede en sikkerhetskopi for meldinger"; "secure_key_backup_setup_intro_use_security_passphrase_info" = "Skriv inn en hemmelig frase bare du vet, og generer en nøkkel for sikkerhetskopiering."; -"key_backup_setup_passphrase_setup_recovery_key_info" = "Eller sikre sikkerhetskopien din med en gjenopprettingsnøkkel, og lagre den på et trygt sted."; -"key_backup_setup_passphrase_info" = "Vi lagrer en kryptert kopi av nøklene dine på serveren vår. Beskytt sikkerhetskopien din med en passordfrase for å holde den sikker.\n\nFor maksimal sikkerhet bør dette være forskjellig fra kontopassordet ditt."; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Eller, sikre sikkerhetskopien med en sikkerhetsnøkkel, og lagre den et trygt sted."; +"key_backup_setup_passphrase_info" = "Vi lagrer en kryptert kopi av nøklene dine på serveren vår. Beskytt sikkerhetskopien med en setning for å holde den sikker.\n\nFor maksimal sikkerhet bør dette være forskjellig fra kontopassordet ditt."; // Passphrase -"key_backup_setup_passphrase_title" = "Gjør sikkerhetskopien din sikker med en passordfrase"; +"key_backup_setup_passphrase_title" = "Sikre sikkerhetskopien din med en sikkerhetsfrase"; "key_backup_setup_intro_info" = "Meldinger i krypterte rom er sikret med ende-til-ende-kryptering. Bare du og mottakeren(e) har nøklene til å lese disse meldingene.\n\nLagre nøklene dine på et trygt sted for å unngå å miste dem."; // MARK: Key backup recover @@ -1168,29 +1168,29 @@ // Success from recovery key "key_backup_setup_success_from_recovery_key_info" = "Nøklene dine blir sikkerhetskopiert.\n\nKopier denne gjenopprettingsnøkkelen og lagre den på et trygt sted."; -"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Lagre gjenopprettingsnøkkel"; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Lagre sikkerhetsnøkkel"; // Success from passphrase "key_backup_setup_success_from_passphrase_info" = "Nøklene dine blir sikkerhetskopiert.\n\nGjenopprettingsnøkkelen din er et sikkerhetsnett - du kan bruke den til å gjenopprette tilgangen til de krypterte meldingene dine hvis du glemmer passordfrasen.\n\nLagre gjenopprettingsnøkkelen din på en trygg måte, f.eks. ved hjelp av en passordadministrator (eller i en safe)."; -"key_backup_setup_passphrase_setup_recovery_key_action" = "(Avansert) Sett opp med gjenopprettingsnøkkel"; -"key_backup_recover_invalid_passphrase" = "Sikkerhetskopi kunne ikke dekrypteres med denne passordfrasen: Vennligst sjekk at du har angitt riktig passordfrase."; -"key_backup_recover_invalid_passphrase_title" = "Feil gjenopprettingsfrase"; -"key_backup_recover_invalid_recovery_key" = "Sikkerhetskopi kunne ikke dekrypteres med denne nøkkelen: bekreft at du skrev inn riktig gjenopprettingsnøkkel."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Avansert) Sett opp med sikkerhetsnøkkel"; +"key_backup_recover_invalid_passphrase" = "Sikkerhetskopiering kunne ikke dekrypteres med denne setningen: bekreft at du har skrevet riktig sikkerhetsfrase."; +"key_backup_recover_invalid_passphrase_title" = "Feil sikkerhetsfrase"; +"key_backup_recover_invalid_recovery_key" = "Sikkerhetskopiering kunne ikke dekrypteres med denne nøkkelen: bekreft at du har angitt riktig sikkerhetsnøkkel."; "key_backup_recover_invalid_recovery_key_title" = "Feil i gjenopprettingsnøkkel"; // Recover from passphrase -"key_backup_recover_from_passphrase_info" = "Bruk gjenopprettingspassordet for å låse opp historikken for dine sikrede meldinger"; +"key_backup_recover_from_passphrase_info" = "Bruk sikkerhetsfrasen for å låse opp den sikre meldingsloggen"; // Recover from private key "key_backup_recover_from_private_key_info" = "Gjenoppretter sikkerhetskopi …"; -"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Kjenner du ikke gjenopprettingspassordet ditt? Du kan "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Kjenner du ikke sikkerhetsfrasen din? Du kan "; "key_backup_recover_from_passphrase_recover_action" = "Lås opp historikk"; "key_backup_recover_from_passphrase_passphrase_placeholder" = "Skriv inn passordfrase"; // Recover from recovery key -"key_backup_recover_from_recovery_key_info" = "Bruk gjenopprettingsnøkkel for å låse opp historikken for sikrede meldinger"; +"key_backup_recover_from_recovery_key_info" = "Bruk sikkerhetsnøkkelen til å låse opp den sikre meldingsloggen"; "key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; "sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Begynn å bruke Sikkert lagringsområde"; "sign_out_non_existing_key_backup_alert_title" = "Du mister tilgangen til de krypterte meldingene dine hvis du logger ut nå"; @@ -1418,3 +1418,50 @@ "room_intro_cell_information_multiple_dm_sentence2" = "Bare dere er i denne samtalen, med mindre noen av dere inviterer andre til å bli med."; "room_intro_cell_information_dm_sentence2" = "Bare dere to er i denne samtalen, ingen andre kan bli med."; "room_intro_cell_information_dm_sentence1_part3" = ". "; +"side_menu_app_version" = "Versjon %@"; +"side_menu_action_feedback" = "Tilbakemelding"; +"side_menu_action_help" = "Hjelp"; +"side_menu_action_settings" = "Innstillinger"; +"side_menu_action_invite_friends" = "Inviter venner"; + +// Mark: - Side menu + +"side_menu_reveal_action_accessibility_label" = "Venstre panel"; +"user_avatar_view_accessibility_hint" = "Endre bruker avatar"; + +// Mark: - User avatar view + +"user_avatar_view_accessibility_label" = "avatar"; +"space_beta_announce_information" = "Plasser er en ny måte å gruppere rom og mennesker på. De er ikke på iOS ennå, men du kan bruke dem nå på nettet og på skrivebordet."; +"space_beta_announce_subtitle" = "Den nye versjonen av lokalsamfunn"; +"space_beta_announce_title" = "Plasser kommer snart"; +"space_beta_announce_badge" = "BETA"; +"space_feature_unavailable_information" = "Plasser er en ny måte å gruppere rom og mennesker på.\n\nDe kommer snart. For nå, hvis du blir med på en annen plattform, vil du kunne få tilgang til alle rom du blir med her."; +"space_feature_unavailable_subtitle" = "Plasser er ikke på iOS ennå, men du kan bruke dem nå på nettet og på skrivebordet"; + +// Mark: - Spaces + +"space_feature_unavailable_title" = "Plasser er ikke her ennå"; +"secrets_recovery_with_key_information_unlock_secure_backup_with_key" = "Skriv inn sikkerhetsnøkkelen din for å fortsette."; +"secrets_recovery_with_key_information_unlock_secure_backup_with_phrase" = "Skriv inn sikkerhetsfrasen for å fortsette."; + +// Success from secure backup +"key_backup_setup_success_from_secure_backup_info" = "Nøklene dine blir sikkerhetskopiert."; +"event_formatter_group_call_incoming" = "%@ i %@"; +"event_formatter_group_call_leave" = "Forlat"; +"event_formatter_group_call_join" = "Bli med"; +"event_formatter_group_call" = "Gruppeanrop"; +"event_formatter_call_end_call" = "Avslutt samtale"; +"event_formatter_call_retry" = "Prøv på nytt"; +"event_formatter_call_answer" = "Svar"; +"security_settings_secure_backup_restore" = "Gjenopprett fra sikkerhetskopi"; +"security_settings_secure_backup_reset" = "Nullstill"; +"security_settings_secure_backup_info_valid" = "Denne økten tar sikkerhetskopi av nøklene dine."; +"security_settings_secure_backup_info_checking" = "Sjekker…"; +"settings_ui_theme_picker_message_match_system_theme" = "\"Auto\" samsvarer med enhetens systemtema"; +"settings_ui_theme_picker_message_invert_colours" = "\"Auto\" bruker enhetens \"Inverter farger\" innstillinger"; + +// Chat +"room_slide_to_end_group_call" = "Skyv for å avslutte samtalen for alle"; +"room_recents_unknown_room_error_message" = "Finner ikke dette rommet. Forsikre deg om at den eksisterer"; +"room_creation_dm_error" = "Vi kunne ikke opprette DM. Kontroller brukerne du vil invitere, og prøv på nytt."; diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 4b144ba88..1b5064d3e 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -611,7 +611,7 @@ "room_does_not_exist" = "%@ bestaat niet"; // Key backup wrong version "e2e_key_backup_wrong_version_title" = "Nieuwe sleutelback-up"; -"e2e_key_backup_wrong_version" = "Er is een nieuwe sleutelback-up voor versleutelde berichten gedetecteerd.\n\nIndien deze niet van u komt, stel dan een nieuw wachtwoord in in de instellingen."; +"e2e_key_backup_wrong_version" = "Er is een nieuwe sleutelback-up voor versleutelde berichten gedetecteerd.\n\nIndien deze niet van u komt, stel dan een nieuw veiligheidswachtwoord in in de instellingen."; "e2e_key_backup_wrong_version_button_settings" = "Instellingen"; "e2e_key_backup_wrong_version_button_wasme" = "Ik was het"; "key_backup_setup_title" = "Sleutelback-up"; @@ -623,10 +623,10 @@ "key_backup_setup_intro_setup_action_without_existing_backup" = "Begin sleutelback-up te gebruiken"; "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 wachtwoord"; -"key_backup_setup_passphrase_info" = "We bewaren een versleutelde kopie van uw sleutels op onze server. Bescherm uw back-up met een wachtwoord om deze veilig te houden.\n\nVoor maximale beveiliging zou dit moeten verschillen van uw accountwachtwoord."; +"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_passphrase_title" = "Invoeren"; -"key_backup_setup_passphrase_passphrase_placeholder" = "Voer wachtwoord in"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Wachtwoord invoeren"; "key_backup_setup_passphrase_passphrase_valid" = "Top!"; "key_backup_setup_passphrase_passphrase_invalid" = "Probeer nog een woord toe te voegen"; "key_backup_setup_passphrase_confirm_passphrase_title" = "Bevestigen"; @@ -634,35 +634,35 @@ "key_backup_setup_passphrase_confirm_passphrase_valid" = "Top!"; "key_backup_setup_passphrase_confirm_passphrase_invalid" = "Wachtwoorden komen niet overeen"; "key_backup_setup_passphrase_set_passphrase_action" = "Wachtwoord instellen"; -"key_backup_setup_passphrase_setup_recovery_key_info" = "Of beveilig uw back-up met een herstelsleutel, en bewaar deze op een veilige plaats."; -"key_backup_setup_passphrase_setup_recovery_key_action" = "(Geavanceerd) Instellen met herstelsleutel"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Of beveilig uw back-up met een veiligheidssleutel en bewaar deze op een veilige plaats."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Geavanceerd) Instellen met veiligheidssleutel"; "key_backup_setup_success_title" = "Klaar!"; // Success from passphrase -"key_backup_setup_success_from_passphrase_info" = "Er wordt een back-up van uw sleutels gemaakt.\n\nUw herstelsleutel is een veiligheidsnet - u kunt deze gebruiken om de toegang tot uw versleutelde berichten te herstellen als u uw wachtwoord zou vergeten.\n\nBewaar uw herstelsleutel op een heel veilig plaats, zoals een wachtwoordbeheerder (of een kluis)."; -"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Herstelsleutel opslaan"; +"key_backup_setup_success_from_passphrase_info" = "Er wordt een back-up van uw sleutels gemaakt.\n\nUw veiligheidssleutel is een veiligheidsnet - u kunt deze gebruiken om de toegang tot uw versleutelde berichten te herstellen als u uw wachtwoord zou vergeten.\n\nBewaar uw veiligheidssleutel op een heel veilige plaats, zoals een wachtwoordbeheerder (of een kluis)."; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Veiligheidssleutel opslaan"; "key_backup_setup_success_from_passphrase_done_action" = "Klaar"; // Success from recovery key -"key_backup_setup_success_from_recovery_key_info" = "Er wordt een back-up van uw sleutels gemaakt.\n\nMaak een kopie van deze herstelsleutel en bewaar deze op een veilige plaats."; -"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Herstelsleutel"; +"key_backup_setup_success_from_recovery_key_info" = "Er wordt een back-up van uw sleutels gemaakt.\n\nMaak een kopie van deze veiligheidssleutel en bewaar deze op een veilige plaats."; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Veiligheidssleutel"; "key_backup_setup_success_from_recovery_key_make_copy_action" = "Maak een kopie"; "key_backup_setup_success_from_recovery_key_made_copy_action" = "Ik heb een kopie gemaakt"; "key_backup_recover_title" = "Versleutelde berichten"; -"key_backup_recover_invalid_passphrase_title" = "Onjuist herstelwachtwoord"; -"key_backup_recover_invalid_passphrase" = "De back-up kon niet ontsleuteld worden met dit wachtwoord: controleer of u het herstelwachtwoord juist hebt ingevoerd."; -"key_backup_recover_invalid_recovery_key_title" = "Herstelsleutel komt niet overeen"; -"key_backup_recover_invalid_recovery_key" = "De back-up kon niet ontsleuteld worden met deze sleutel: controleer of u de juiste herstelsleutel hebt ingevoerd."; -"key_backup_recover_from_passphrase_info" = "Gebruik uw herstelwachtwoord om uw versleutelde berichtgeschiedenis te ontgrendelen"; +"key_backup_recover_invalid_passphrase_title" = "Onjuist veiligheidswachtwoord"; +"key_backup_recover_invalid_passphrase" = "De back-up kon niet ontsleuteld worden met dit wachtwoord: controleer of u het veiligheidswachtwoord juist hebt ingevoerd."; +"key_backup_recover_invalid_recovery_key_title" = "Veiligheidssleutel komt niet overeen"; +"key_backup_recover_invalid_recovery_key" = "De back-up kon niet ontsleuteld worden met deze sleutel: controleer of u de juiste veiligheidssleutel hebt ingevoerd."; +"key_backup_recover_from_passphrase_info" = "Gebruik uw veiligheidswachtwoord om uw versleutelde berichtengeschiedenis te ontgrendelen"; "key_backup_recover_from_passphrase_passphrase_title" = "Invoeren"; -"key_backup_recover_from_passphrase_passphrase_placeholder" = "Voer wachtwoord in"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Wachtwoord invoeren"; "key_backup_recover_from_passphrase_recover_action" = "Geschiedenis ontgrendelen"; -"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Herstelwachtwoord vergeten? Dan kunt u "; -"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "uw herstelsleutel gebruiken"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Veiligheidswachtwoord vergeten? Dan kunt u "; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "uw veiligheidssleutel gebruiken"; "key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; -"key_backup_recover_from_recovery_key_info" = "Gebruik uw herstelsleutel om uw versleutelde berichtgeschiedenis te ontgrendelen"; +"key_backup_recover_from_recovery_key_info" = "Gebruik uw veiligheidssleutel om uw versleutelde berichtengeschiedenis te ontgrendelen"; "key_backup_recover_from_recovery_key_recovery_key_title" = "Invoeren"; -"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Voer herstelsleutel in"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Veiligheidssleutel invoeren"; "key_backup_recover_from_recovery_key_recover_action" = "Geschiedenis ontgrendelen"; -"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Herstelsleutel verloren? U kunt er een nieuwe aanmaken in de instellingen."; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Veiligheidssleutel verloren? U kunt er een nieuwe aanmaken in de instellingen."; "key_backup_recover_success_info" = "Back-up hersteld!"; "key_backup_recover_done_action" = "Klaar"; "key_backup_setup_banner_title" = "Verlies nooit uw versleutelde berichten"; @@ -913,7 +913,7 @@ // MARK: - Favourites "favourites_empty_view_title" = "Favoriete gesprekken en personen"; -"home_empty_view_information" = "De alles-in-één veilige chat app voor teams, vrienden en organisaties. Klik op de onderstaande + knop om gesprekken te starten met personen en groepen."; +"home_empty_view_information" = "De alles-in-één veilige chat-app voor teams, vrienden en organisaties. Druk op de + knop hieronder om personen en gesprekken toe te voegen."; // MARK: - Home @@ -1032,32 +1032,32 @@ "secrets_setup_recovery_key_done_action" = "Klaar"; "secrets_setup_recovery_key_export_action" = "Opslaan"; "secrets_setup_recovery_key_loading" = "Laden…"; -"secrets_setup_recovery_key_information" = "Bewaar uw Herstelsleutel op een veilige plek. Het kan gebruikt worden voor het ontgrendelen van uw versleutelde berichten en data."; -"secrets_recovery_with_key_invalid_recovery_key_message" = "Verifieer dat u de juiste herstelsleutel heeft ingevoerd."; +"secrets_setup_recovery_key_information" = "Bewaar uw veiligheidssleutel op een veilige plek. Deze kan gebruikt worden om uw versleutelde berichten en data te ontsleutelen."; +"secrets_recovery_with_key_invalid_recovery_key_message" = "Verifieer dat u de juiste veiligheidssleutel heeft ingevoerd."; "secrets_recovery_with_key_invalid_recovery_key_title" = "Geen toegang tot geheime opslag"; "secrets_recovery_with_key_recover_action" = "Gebruik sleutel"; -"secrets_recovery_with_key_recovery_key_placeholder" = "Voer de herstelsleutel in"; +"secrets_recovery_with_key_recovery_key_placeholder" = "Veiligheidssleutel invoeren"; "secrets_recovery_with_key_recovery_key_title" = "Invoeren"; -"secrets_recovery_with_key_information_verify_device" = "Gebruik uw herstelsleutel om dit apparaat te verifiëren."; -"secrets_recovery_with_key_information_default" = "Ontvang toegang tot uw versleutelde berichtengeschiedenis en uw kruislings ondertekenen ID voor het verifiëren van andere sessie door het invoeren van uw Herstelsleutel."; +"secrets_recovery_with_key_information_verify_device" = "Gebruik uw veiligheidssleutel om dit apparaat te verifiëren."; +"secrets_recovery_with_key_information_default" = "Ontvang toegang tot uw versleutelde berichtengeschiedenis en kruislings ondertekenen voor het verifiëren van andere sessie door het invoeren van uw veiligheidssleutel."; // Recover with key -"secrets_recovery_with_key_title" = "Herstelsleutel"; -"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Verifieer dat u het juiste Herstelwachtwoord heeft ingevoerd."; +"secrets_recovery_with_key_title" = "Veiligheidssleutel"; +"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Verifieer dat u het juiste veiligheidswachtwoord heeft ingevoerd."; "secrets_recovery_with_passphrase_invalid_passphrase_title" = "Geen toegang tot geheime opslag"; "secrets_recovery_with_passphrase_lost_passphrase_action_part3" = "."; -"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "uw Herstelsleutel gebruiken"; -"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Herstelwachtwoord vergeten? Dan kunt u "; -"secrets_recovery_with_passphrase_recover_action" = "Gebruik Wachtwoord"; -"secrets_recovery_with_passphrase_passphrase_placeholder" = "Voer uw Herstelwachtwoord in"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "uw veiligheidssleutel gebruiken"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Veiligheidswachtwoord vergeten? Dan kunt u "; +"secrets_recovery_with_passphrase_recover_action" = "Gebruik wachtwoord"; +"secrets_recovery_with_passphrase_passphrase_placeholder" = "Voer uw veiligheidswachtwoord in"; "secrets_recovery_with_passphrase_passphrase_title" = "Invoeren"; -"secrets_recovery_with_passphrase_information_verify_device" = "Gebruik uw Herstelwachtwoord om dit apparaat te verifiëren."; -"secrets_recovery_with_passphrase_information_default" = "Ontvang toegang tot uw versleutelde berichtengeschiedenis en uw kruislings ondertekenen ID voor het verifiëren van andere sessies door het invoeren van uw Herstelwachtwoord."; +"secrets_recovery_with_passphrase_information_verify_device" = "Gebruik uw veiligheidswachtwoord om dit apparaat te verifiëren."; +"secrets_recovery_with_passphrase_information_default" = "Ontvang toegang tot uw versleutelde berichtengeschiedenis en kruislings ondertekenen voor het verifiëren van andere sessies door het invoeren van uw veiligheidswachtwoord."; // Recover with passphrase -"secrets_recovery_with_passphrase_title" = "Herstelwachtwoord"; +"secrets_recovery_with_passphrase_title" = "Veiligheidswachtwoord"; "secrets_recovery_reset_action_part_2" = "Alles opnieuw instellen"; // MARK: - Secrets recovery @@ -1065,9 +1065,9 @@ "secrets_recovery_reset_action_part_1" = "Alle herstelopties vergeten of verloren? "; "user_verification_session_details_verify_action_other_user" = "Handmatig verifiëren"; "user_verification_session_details_verify_action_current_user_manually" = "Handmatig middels een tekst"; -"user_verification_session_details_verify_action_current_user" = "Interactief Verifiëren"; +"user_verification_session_details_verify_action_current_user" = "Interactief verifiëren"; "user_verification_session_details_additional_information_untrusted_current_user" = "Als u zich niet heeft aangemeld bij deze sessie, is uw account wellicht geschonden."; -"user_verification_session_details_additional_information_untrusted_other_user" = "Totdat deze persoon de sessie vertrouwd zijn berichten gelabeld met een waarschuwing. Een alternatief is handmatig verifiëren."; +"user_verification_session_details_additional_information_untrusted_other_user" = "Totdat deze persoon deze sessie vertrouwd, zijn berichten gelabeld met waarschuwingen. Een andere mogelijkheid is om de persoon handmatig te verifiëren."; "user_verification_session_details_information_untrusted_other_user" = " heeft zich in een nieuwe sessie aangemeld:"; "user_verification_session_details_information_untrusted_current_user" = "Verifieer deze sessie om het als vertrouwd te markeren en het toegang te geven tot versleutelde berichten:"; "user_verification_session_details_information_trusted_other_user_part2" = " verifieer het:"; @@ -1180,8 +1180,8 @@ "key_verification_verify_sas_title_emoji" = "Vergelijk de emoji's"; "device_verification_self_verify_wait_recover_secrets_checking_availability" = "Controleren op andere verificatie mogelijkheden..."; "device_verification_self_verify_wait_recover_secrets_additional_information" = "Wanneer u geen toegang meer heeft tot een bestaande sessie"; -"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Uw Herstelwachtwoord of -sleutel gebruiken"; -"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Herstelsleutel gebruiken"; +"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Uw veiligheidswachtwoord of -sleutel gebruiken"; +"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Veiligheidssleutel gebruiken"; "device_verification_self_verify_wait_additional_information" = "Dit werkt met Element en andere Matrix-apps die kruislings ondertekenen ondersteunen."; "device_verification_self_verify_wait_information" = "Verifieer deze sessie vanaf een van uw andere sessies, om toegang te krijgen tot de versleutelde berichten.\n\nGebruik de laatste versie van Element op uw andere apparaten:"; "device_verification_self_verify_wait_new_sign_in_title" = "Verifieer deze login"; @@ -1266,7 +1266,7 @@ // Room widget permissions "room_widget_permission_title" = "Widget laden"; "widget_picker_manage_integrations" = "Beheer integraties…"; -"widget_integration_manager_disabled" = "U moet een integratebeheerder inschakelen in uw instellingen"; +"widget_integration_manager_disabled" = "U moet integratiebeheer inschakelen in de instellingen"; "widget_menu_remove" = "Verwijderen voor iedereen"; "widget_menu_revoke_permission" = "Toegang intrekken voor mij"; "widget_menu_open_outside" = "Openen in browser"; @@ -1292,11 +1292,11 @@ "room_details_advanced_e2e_encryption_disabled_for_dm" = "Versleuteling is hier niet ingeschakeld."; "room_details_advanced_e2e_encryption_enabled_for_dm" = "Versleuteling is hier ingeschakeld"; "room_details_advanced_room_id_for_dm" = "ID:"; -"room_details_no_local_addresses_for_dm" = "Dit heeft geen lokaaladres"; +"room_details_no_local_addresses_for_dm" = "Geen lokaaladres bekend"; "room_details_access_section_directory_toggle_for_dm" = "Weergeven in publieke groepsgesprekkencatalogus"; "room_details_access_section_anyone_for_dm" = "Iedereen die de koppeling kent, inclusief gasten"; "room_details_access_section_anyone_apart_from_guest_for_dm" = "Iedereen die de koppeling kent, behalve gasten"; -"room_details_access_section_for_dm" = "Wie mag toegang hebben?"; +"room_details_access_section_for_dm" = "Wie heeft toegang?"; "room_details_room_name_for_dm" = "Naam"; "room_details_photo_for_dm" = "Foto"; "room_details_title_for_dm" = "Details"; @@ -1343,17 +1343,17 @@ "security_settings_cryptography" = "CRYPTOGRAFIE"; "security_settings_crosssigning_complete_security" = "Beveiliging afronden"; "security_settings_crosssigning_reset" = "Reset"; -"security_settings_crosssigning_bootstrap" = "Stel in"; -"security_settings_crosssigning_info_ok" = "Cross-signing is klaar voor gebruik."; +"security_settings_crosssigning_bootstrap" = "Instellen"; +"security_settings_crosssigning_info_ok" = "Kruiselings ondertekenen is klaar voor gebruik."; "security_settings_crosssigning_info_trusted" = "Kruislings ondertekenen is ingeschakeld. U kunt andere personen en sessies verifiëren met kruislings ondertekenen, maar u kunt dit nog niet vanaf deze sessie doordat de versleutelingssleutel ontbreekt. Rond de beveiliging van deze sessie af."; "security_settings_crosssigning_info_exists" = "Uw account heeft een kruislings ondertekenen ID, maar is nog niet geverifieerd door deze sessie. Rond de beveiliging van deze sessie af."; "security_settings_crosssigning_info_not_bootstrapped" = "Kruislings ondertekenen is nog niet ingesteld."; "security_settings_crosssigning" = "KRUISLINGS ONDERTEKENEN"; "security_settings_backup" = "BERICHTENBACK-UP"; -"security_settings_secure_backup_delete" = "Verwijder backup"; +"security_settings_secure_backup_delete" = "Back-up verwijderen"; "security_settings_secure_backup_synchronise" = "Synchroniseren"; "security_settings_secure_backup_setup" = "Instellen"; -"security_settings_secure_backup_description" = "Waarborg uw toegang tot uw versleutelde berichten & data door de versleutelingssleutels op te slaan. Uw sleutels zullen worden beveiligd met een unieke beveiligingssleutel."; +"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_loading" = "Sessies laden…"; diff --git a/Riot/Assets/si.lproj/Localizable.strings b/Riot/Assets/si.lproj/Localizable.strings index 432026982..ac8956825 100644 --- a/Riot/Assets/si.lproj/Localizable.strings +++ b/Riot/Assets/si.lproj/Localizable.strings @@ -17,3 +17,6 @@ /* New message from a specific person, not referencing a room. Content included. */ "MSG_FROM_USER_WITH_CONTENT" = "%@: %@"; + +/* Group call from user, CallKit caller name */ +"GROUP_CALL_FROM_USER" = "%@ (සමූහ ඇමතුම)"; diff --git a/Riot/Assets/si.lproj/Vector.strings b/Riot/Assets/si.lproj/Vector.strings index 982e41a3b..59e0d02cf 100644 --- a/Riot/Assets/si.lproj/Vector.strings +++ b/Riot/Assets/si.lproj/Vector.strings @@ -1,3 +1,16 @@ // Titles "title_home" = "මුල් පිටුව"; "warning" = "අවවාදයයි"; +"join" = "එක්වන්න"; +"save" = "සුරකින්න"; +"cancel" = "අවලංගු කරන්න"; +"remove" = "ඉවත් කරන්න"; +"leave" = "හැරයන්න"; +"start" = "අරඹන්න"; +"create" = "සාදන්න"; +"continue" = "ඉදිරියට"; +"back" = "ආපසු"; +"next" = "ඊලඟ"; +"title_rooms" = "කාමර"; +"title_people" = "මිනිසුන්"; +"title_favourites" = "ප්‍රියතමයින්"; diff --git a/Riot/Coordinators/Coordinator.swift b/Riot/Coordinators/Coordinator.swift index 4d7f27b6a..3345c2f94 100755 --- a/Riot/Coordinators/Coordinator.swift +++ b/Riot/Coordinators/Coordinator.swift @@ -19,7 +19,7 @@ import UIKit /// Protocol describing a [Coordinator](http://khanlou.com/2015/10/coordinators-redux/). /// Coordinators are the objects which control the navigation flow of the application. /// It helps to isolate and reuse view controllers and pass dependencies down the navigation hierarchy. -protocol Coordinator: class { +protocol Coordinator: AnyObject { /// Starts job of the coordinator. func start() diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index afc57884a..2cec2c63b 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -85,6 +85,7 @@ internal enum Asset { internal static let roomActionFavourite = ImageAsset(name: "room_action_favourite") internal static let roomActionLeave = ImageAsset(name: "room_action_leave") internal static let roomActionNotification = ImageAsset(name: "room_action_notification") + internal static let roomActionNotificationMuted = ImageAsset(name: "room_action_notification_muted") internal static let roomActionPriorityHigh = ImageAsset(name: "room_action_priority_high") internal static let roomActionPriorityLow = ImageAsset(name: "room_action_priority_low") internal static let homeEmptyScreenArtwork = ImageAsset(name: "home_empty_screen_artwork") @@ -144,6 +145,7 @@ internal enum Asset { internal static let membersListIcon = ImageAsset(name: "members_list_icon") internal static let modIcon = ImageAsset(name: "mod_icon") internal static let moreReactions = ImageAsset(name: "more_reactions") + internal static let notifications = ImageAsset(name: "notifications") internal static let scrollup = ImageAsset(name: "scrollup") internal static let roomsEmptyScreenArtwork = ImageAsset(name: "rooms_empty_screen_artwork") internal static let roomsEmptyScreenArtworkDark = ImageAsset(name: "rooms_empty_screen_artwork_dark") diff --git a/Riot/Generated/Storyboards.swift b/Riot/Generated/Storyboards.swift index c66d40f6a..0b77710ce 100644 --- a/Riot/Generated/Storyboards.swift +++ b/Riot/Generated/Storyboards.swift @@ -172,6 +172,11 @@ internal enum StoryboardScene { internal static let initialScene = InitialSceneType(storyboard: RoomInfoListViewController.self) } + internal enum RoomNotificationSettingsViewController: StoryboardType { + internal static let storyboardName = "RoomNotificationSettingsViewController" + + internal static let initialScene = InitialSceneType(storyboard: RoomNotificationSettingsViewController.self) + } internal enum SecretsRecoveryWithKeyViewController: StoryboardType { internal static let storyboardName = "SecretsRecoveryWithKeyViewController" diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index ba05c0233..3168d5ad4 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2014,6 +2014,10 @@ internal enum VectorL10n { internal static var keyVerificationVerifyQrCodeScanCodeAction: String { return VectorL10n.tr("Vector", "key_verification_verify_qr_code_scan_code_action") } + /// Scan with this device + internal static var keyVerificationVerifyQrCodeScanCodeOtherDeviceAction: String { + return VectorL10n.tr("Vector", "key_verification_verify_qr_code_scan_code_other_device_action") + } /// QR code has been successfully validated. internal static var keyVerificationVerifyQrCodeScanOtherCodeSuccessMessage: String { return VectorL10n.tr("Vector", "key_verification_verify_qr_code_scan_other_code_success_message") @@ -2710,6 +2714,10 @@ internal enum VectorL10n { internal static var roomDetailsNoLocalAddressesForDm: String { return VectorL10n.tr("Vector", "room_details_no_local_addresses_for_dm") } + /// Notifications + internal static var roomDetailsNotifs: String { + return VectorL10n.tr("Vector", "room_details_notifs") + } /// Members internal static var roomDetailsPeople: String { return VectorL10n.tr("Vector", "room_details_people") @@ -3018,6 +3026,42 @@ internal enum VectorL10n { internal static var roomNoPrivilegesToCreateGroupCall: String { return VectorL10n.tr("Vector", "room_no_privileges_to_create_group_call") } + /// Account settings + internal static var roomNotifsSettingsAccountSettings: String { + return VectorL10n.tr("Vector", "room_notifs_settings_account_settings") + } + /// All Messages + internal static var roomNotifsSettingsAllMessages: String { + return VectorL10n.tr("Vector", "room_notifs_settings_all_messages") + } + /// Cancel + internal static var roomNotifsSettingsCancelAction: String { + return VectorL10n.tr("Vector", "room_notifs_settings_cancel_action") + } + /// Done + internal static var roomNotifsSettingsDoneAction: String { + return VectorL10n.tr("Vector", "room_notifs_settings_done_action") + } + /// Please note that mentions & keyword notifications are not available in encrypted rooms on mobile. + internal static var roomNotifsSettingsEncryptedRoomNotice: String { + return VectorL10n.tr("Vector", "room_notifs_settings_encrypted_room_notice") + } + /// You can manage notifications in %@ + internal static func roomNotifsSettingsManageNotifications(_ p1: String) -> String { + return VectorL10n.tr("Vector", "room_notifs_settings_manage_notifications", p1) + } + /// Mentions and Keywords only + internal static var roomNotifsSettingsMentionsAndKeywords: String { + return VectorL10n.tr("Vector", "room_notifs_settings_mentions_and_keywords") + } + /// None + internal static var roomNotifsSettingsNone: String { + return VectorL10n.tr("Vector", "room_notifs_settings_none") + } + /// Notify me for + internal static var roomNotifsSettingsNotifyMeFor: String { + return VectorL10n.tr("Vector", "room_notifs_settings_notify_me_for") + } /// Connectivity to the server has been lost. internal static var roomOfflineNotification: String { return VectorL10n.tr("Vector", "room_offline_notification") diff --git a/Riot/Managers/Call/CallPresenter.swift b/Riot/Managers/Call/CallPresenter.swift index 4f5ad7e13..940ac98f3 100644 --- a/Riot/Managers/Call/CallPresenter.swift +++ b/Riot/Managers/Call/CallPresenter.swift @@ -393,7 +393,9 @@ class CallPresenter: NSObject { if let oldCallVC = self.callVCs.values.first, self.presentedCallVC == nil, !self.uiOperationQueue.containsPresentCallVCOperation, - !self.uiOperationQueue.containsEnterPiPOperation { + !self.uiOperationQueue.containsEnterPiPOperation, + let oldCall = oldCallVC.mxCall, + oldCall.state != .ended { // present the call screen after dismissing this one self.presentCallVC(oldCallVC) } diff --git a/Riot/Managers/Call/CallPresenterDelegate.swift b/Riot/Managers/Call/CallPresenterDelegate.swift index 9c7f44687..a9f6df03e 100644 --- a/Riot/Managers/Call/CallPresenterDelegate.swift +++ b/Riot/Managers/Call/CallPresenterDelegate.swift @@ -17,7 +17,7 @@ import Foundation @objc -protocol CallPresenterDelegate: class { +protocol CallPresenterDelegate: AnyObject { // Call screens func callPresenter(_ presenter: CallPresenter, presentCallViewController viewController: UIViewController, diff --git a/Riot/Managers/Call/PiPView.swift b/Riot/Managers/Call/PiPView.swift index 8f5a0587a..54a199044 100644 --- a/Riot/Managers/Call/PiPView.swift +++ b/Riot/Managers/Call/PiPView.swift @@ -23,7 +23,7 @@ import UIKit case topLeft } -@objc protocol PiPViewDelegate: class { +@objc protocol PiPViewDelegate: AnyObject { @objc optional func pipView(_ view: PiPView, didMoveTo position: PiPViewPosition) @objc optional func pipViewDidTap(_ view: PiPView) } diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 533702c2b..5a6817aca 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -80,6 +80,7 @@ final class RiotSettings: NSObject { static let roomMemberScreenShowIgnore = "roomMemberScreenShowIgnore" static let unifiedSearchScreenShowPublicDirectory = "unifiedSearchScreenShowPublicDirectory" static let hideSpaceBetaAnnounce = "hideSpaceBetaAnnounce" + static let secretsRecoveryAllowReset = "secretsRecoveryAllowReset" } static let shared = RiotSettings() @@ -695,7 +696,7 @@ final class RiotSettings: NSObject { } } - // Mark: - Unified Search + // MARK: - Unified Search var unifiedSearchScreenShowPublicDirectory: Bool { get { @@ -708,6 +709,19 @@ final class RiotSettings: NSObject { } } + // MARK: - Secrets Recovery + + var secretsRecoveryAllowReset: Bool { + get { + guard defaults.object(forKey: UserDefaultsKeys.secretsRecoveryAllowReset) != nil else { + return BuildSettings.secretsRecoveryAllowReset + } + return defaults.bool(forKey: UserDefaultsKeys.secretsRecoveryAllowReset) + } set { + defaults.set(newValue, forKey: UserDefaultsKeys.secretsRecoveryAllowReset) + } + } + // MARK: - Beta var hideSpaceBetaAnnounce: Bool { diff --git a/Riot/Managers/Theme/Themable.swift b/Riot/Managers/Theme/Themable.swift index f4f59f1e9..71931bfe8 100644 --- a/Riot/Managers/Theme/Themable.swift +++ b/Riot/Managers/Theme/Themable.swift @@ -16,6 +16,6 @@ import Foundation -@objc protocol Themable: class { +@objc protocol Themable: AnyObject { func update(theme: Theme) } diff --git a/Riot/Managers/Widgets/WidgetManager.h b/Riot/Managers/Widgets/WidgetManager.h index 09c2b2588..f5279a216 100644 --- a/Riot/Managers/Widgets/WidgetManager.h +++ b/Riot/Managers/Widgets/WidgetManager.h @@ -183,7 +183,7 @@ FOUNDATION_EXPORT NSString *const WidgetManagerErrorOpenIdTokenKey; /** Store the integration manager configuration for a user. - @param the integration manager configuration. + @param config the integration manager configuration. @param userId the user id. */ - (void)setConfig:(WidgetManagerConfig*)config forUser:(NSString*)userId; diff --git a/Riot/Model/Room/RoomPreviewData.h b/Riot/Model/Room/RoomPreviewData.h index 71280b099..c10295617 100644 --- a/Riot/Model/Room/RoomPreviewData.h +++ b/Riot/Model/Room/RoomPreviewData.h @@ -76,10 +76,17 @@ Contructors. @param roomId the id of the room. - @param emailInvitationParams, in case of an email invitation link, the query parameters extracted from the link. @param mxSession the session to open the room preview with. */ - (instancetype)initWithRoomId:(NSString*)roomId andSession:(MXSession*)mxSession; + +/** + Contructors. + + @param roomId the id of the room. + @param emailInvitationParams in case of an email invitation link, the query parameters extracted from the link. + @param mxSession the session to open the room preview with. + */ - (instancetype)initWithRoomId:(NSString*)roomId emailInvitationParams:(NSDictionary*)emailInvitationParams andSession:(MXSession*)mxSession; /** diff --git a/Riot/Modules/Application/AppCoordinator.swift b/Riot/Modules/Application/AppCoordinator.swift index 4469fbbfa..8a1949f75 100755 --- a/Riot/Modules/Application/AppCoordinator.swift +++ b/Riot/Modules/Application/AppCoordinator.swift @@ -21,8 +21,12 @@ import Intents import FLEX #endif -/// The AppCoordinator is responsible of screen navigation and data injection at root application level. It decides if authentication or home screen should be shown and inject data needed for these flows, it changes the navigation stack on deep link, displays global warning. -/// This class should avoid to contain too many data management code not related to screen navigation logic. For example `MXSession` or push notification management should be handled in dedicated classes and report only navigation changes to the AppCoordinator. +/// The AppCoordinator is responsible of screen navigation and data injection at root application level. It decides +/// if authentication or home screen should be shown and inject data needed for these flows, it changes the navigation +/// stack on deep link, displays global warning. +/// This class should avoid to contain too many data management code not related to screen navigation logic. For example +/// `MXSession` or push notification management should be handled in dedicated classes and report only navigation +/// changes to the AppCoordinator. final class AppCoordinator: NSObject, AppCoordinatorType { // MARK: - Constants @@ -83,7 +87,8 @@ final class AppCoordinator: NSObject, AppCoordinatorType { } func open(url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool { - // NOTE: As said in the Apple documentation be careful on security issues with Custom Scheme URL (see https://developer.apple.com/documentation/xcode/allowing_apps_and_websites_to_link_to_your_content/defining_a_custom_url_scheme_for_your_app) + // NOTE: As said in the Apple documentation be careful on security issues with Custom Scheme URL: + // https://developer.apple.com/documentation/xcode/allowing_apps_and_websites_to_link_to_your_content/defining_a_custom_url_scheme_for_your_app do { let deepLinkOption = try self.customSchemeURLParser.parse(url: url, options: options) diff --git a/Riot/Modules/Application/LegacyAppDelegate.h b/Riot/Modules/Application/LegacyAppDelegate.h index 78269f348..1b06d8cbe 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.h +++ b/Riot/Modules/Application/LegacyAppDelegate.h @@ -173,7 +173,7 @@ UINavigationControllerDelegate Log out all the accounts without confirmation. Show the authentication screen on successful logout. - @param sendLogoutRequest Indicate whether send logout request to homeserver. + @param sendLogoutServerRequest Indicate whether send logout request to homeserver. @param completion the block to execute at the end of the operation. */ - (void)logoutSendingRequestServer:(BOOL)sendLogoutServerRequest @@ -183,7 +183,7 @@ UINavigationControllerDelegate Present incoming key verification request to accept. @param incomingKeyVerificationRequest The incoming key verification request. - @param The matrix session. + @param session The matrix session. @return Indicate NO if the key verification screen could not be presented. */ - (BOOL)presentIncomingKeyVerificationRequest:(MXKeyVerificationRequest*)incomingKeyVerificationRequest diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index ff81e5f57..32010f9bb 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -351,6 +351,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni NSURL *messageSoundURL = [[NSBundle mainBundle] URLForResource:@"message" withExtension:@"caf"]; AudioServicesCreateSystemSoundID((__bridge CFURLRef)messageSoundURL, &_messageSound); + // Set app info now as Mac (Designed for iPad) accesses it before didFinishLaunching is called + self.appInfo = AppInfo.current; + MXLogDebug(@"[AppDelegate] willFinishLaunchingWithOptions: Done"); return YES; @@ -371,8 +374,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni _configuration = [AppConfiguration new]; - self.appInfo = AppInfo.current; - // Log app information NSString *appDisplayName = self.appInfo.displayName; NSString* appVersion = self.appVersion; diff --git a/Riot/Modules/Authentication/SocialLogin/SocialLoginListView.swift b/Riot/Modules/Authentication/SocialLogin/SocialLoginListView.swift index 6a66da782..e2e1a586f 100644 --- a/Riot/Modules/Authentication/SocialLogin/SocialLoginListView.swift +++ b/Riot/Modules/Authentication/SocialLogin/SocialLoginListView.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -@objc protocol SocialLoginListViewDelegate: class { +@objc protocol SocialLoginListViewDelegate: AnyObject { func socialLoginListView(_ socialLoginListView: SocialLoginListView, didTapSocialButtonWithIdentifier identifier: String) } diff --git a/Riot/Modules/Call/Dialpad/DialpadViewController.swift b/Riot/Modules/Call/Dialpad/DialpadViewController.swift index 23e2c21ce..ce9a9fc66 100644 --- a/Riot/Modules/Call/Dialpad/DialpadViewController.swift +++ b/Riot/Modules/Call/Dialpad/DialpadViewController.swift @@ -19,7 +19,7 @@ import UIKit import libPhoneNumber_iOS -@objc protocol DialpadViewControllerDelegate: class { +@objc protocol DialpadViewControllerDelegate: AnyObject { @objc optional func dialpadViewControllerDidTapCall(_ viewController: DialpadViewController, withPhoneNumber phoneNumber: String) @objc optional func dialpadViewControllerDidTapClose(_ viewController: DialpadViewController) diff --git a/Riot/Modules/CallTransfer/CallTransferMainViewController.swift b/Riot/Modules/CallTransfer/CallTransferMainViewController.swift index af4b093d1..f7e23d0cd 100644 --- a/Riot/Modules/CallTransfer/CallTransferMainViewController.swift +++ b/Riot/Modules/CallTransfer/CallTransferMainViewController.swift @@ -18,7 +18,7 @@ import UIKit -@objc protocol CallTransferMainViewControllerDelegate: class { +@objc protocol CallTransferMainViewControllerDelegate: AnyObject { func callTransferMainViewControllerDidComplete(_ viewController: CallTransferMainViewController, consult: Bool, contact: MXKContact?, diff --git a/Riot/Modules/CallTransfer/SelectContact/CallTransferSelectContactViewController.swift b/Riot/Modules/CallTransfer/SelectContact/CallTransferSelectContactViewController.swift index 786cc4f71..df5c0a5a8 100644 --- a/Riot/Modules/CallTransfer/SelectContact/CallTransferSelectContactViewController.swift +++ b/Riot/Modules/CallTransfer/SelectContact/CallTransferSelectContactViewController.swift @@ -19,7 +19,7 @@ import UIKit import Reusable -protocol CallTransferSelectContactViewControllerDelegate: class { +protocol CallTransferSelectContactViewControllerDelegate: AnyObject { func callTransferSelectContactViewControllerDidSelectContact(_ viewController: CallTransferSelectContactViewController, contact: MXKContact?) } diff --git a/Riot/Modules/Camera/CameraPresenter.swift b/Riot/Modules/Camera/CameraPresenter.swift index 749e9abe5..a39bda7c0 100644 --- a/Riot/Modules/Camera/CameraPresenter.swift +++ b/Riot/Modules/Camera/CameraPresenter.swift @@ -18,7 +18,7 @@ import Foundation import UIKit import AVFoundation -@objc protocol CameraPresenterDelegate: class { +@objc protocol CameraPresenterDelegate: AnyObject { func cameraPresenter(_ presenter: CameraPresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) func cameraPresenter(_ presenter: CameraPresenter, didSelectVideoAt url: URL) func cameraPresenterDidCancel(_ cameraPresenter: CameraPresenter) diff --git a/Riot/Modules/Common/Recents/RecentsViewController.h b/Riot/Modules/Common/Recents/RecentsViewController.h index b2b640d80..d3968cfd6 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.h +++ b/Riot/Modules/Common/Recents/RecentsViewController.h @@ -161,10 +161,15 @@ - (void)makeDirectEditedRoom:(BOOL)isDirect; /** - Enable/disable the notifications for the selected room. - */ +Enable/disable the notifications for the selected room. +*/ - (void)muteEditedRoomNotifications:(BOOL)mute; +/** + Edit notification settings for the selected room. + */ +- (void)changeEditedRoomNotificationSettings; + /** Show room directory. */ diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index 6ac8c618b..e76a83cab 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -34,7 +34,7 @@ #import "Riot-Swift.h" -@interface RecentsViewController () +@interface RecentsViewController () { // Tell whether a recents refresh is pending (suspended during editing mode). BOOL isRefreshPending; @@ -74,6 +74,8 @@ @property (nonatomic, strong) CustomSizedPresentationController *customSizedPresentationController; +@property (nonatomic, strong) RoomNotificationSettingsCoordinatorBridgePresenter *roomNotificationSettingsCoordinatorBridgePresenter; + @end @implementation RecentsViewController @@ -1031,12 +1033,31 @@ UIContextualAction *muteAction = [UIContextualAction contextualActionWithStyle:UIContextualActionStyleDestructive title:title handler:^(UIContextualAction * _Nonnull action, __kindof UIView * _Nonnull sourceView, void (^ _Nonnull completionHandler)(BOOL)) { - [self muteEditedRoomNotifications:!isMuted]; + + if ([BuildSettings roomSettingsScreenShowNotificationsV2]) + { + [self changeEditedRoomNotificationSettings]; + } + else + { + [self muteEditedRoomNotifications:!isMuted]; + } + + completionHandler(YES); }]; muteAction.backgroundColor = actionBackgroundColor; - UIImage *notificationImage = [UIImage imageNamed:@"room_action_notification"]; + UIImage *notificationImage; + if([BuildSettings roomSettingsScreenShowNotificationsV2]) + { + notificationImage = isMuted ? [UIImage imageNamed:@"room_action_notification_muted"] : [UIImage imageNamed:@"room_action_notification"]; + } + else + { + notificationImage = [UIImage imageNamed:@"room_action_notification"]; + } + notificationImage = [notificationImage vc_tintedImageUsingColor:isMuted ? unselectedColor : selectedColor]; muteAction.image = [notificationImage vc_notRenderedImage]; @@ -1298,6 +1319,23 @@ } } +- (void)changeEditedRoomNotificationSettings +{ + if (editedRoomId) + { + // Check whether the user didn't leave the room + MXRoom *room = [self.mainSession roomWithRoomId:editedRoomId]; + if (room) + { + // navigate + self.roomNotificationSettingsCoordinatorBridgePresenter = [[RoomNotificationSettingsCoordinatorBridgePresenter alloc] initWithRoom:room]; + self.roomNotificationSettingsCoordinatorBridgePresenter.delegate = self; + [self.roomNotificationSettingsCoordinatorBridgePresenter presentFrom:self animated:YES]; + } + [self cancelEditionMode:isRefreshPending]; + } +} + - (void)muteEditedRoomNotifications:(BOOL)mute { if (editedRoomId) @@ -1307,27 +1345,27 @@ if (room) { [self startActivityIndicator]; - + if (mute) { [room mentionsOnly:^{ - + [self stopActivityIndicator]; - + // Leave editing mode - [self cancelEditionMode:isRefreshPending]; - + [self cancelEditionMode:self->isRefreshPending]; + }]; } else { [room allMessages:^{ - + [self stopActivityIndicator]; - + // Leave editing mode - [self cancelEditionMode:isRefreshPending]; - + [self cancelEditionMode:self->isRefreshPending]; + }]; } } @@ -2219,4 +2257,11 @@ } } +#pragma mark - RoomNotificationSettingsCoordinatorBridgePresenterDelegate +-(void)roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete:(RoomNotificationSettingsCoordinatorBridgePresenter *)coordinatorBridgePresenter +{ + [coordinatorBridgePresenter dismissWithAnimated:YES completion:nil]; + self.roomNotificationSettingsCoordinatorBridgePresenter = nil; +} + @end diff --git a/Riot/Modules/Common/SectionHeaders/TitleHeaderView.swift b/Riot/Modules/Common/SectionHeaders/TitleHeaderView.swift new file mode 100644 index 000000000..a26d99820 --- /dev/null +++ b/Riot/Modules/Common/SectionHeaders/TitleHeaderView.swift @@ -0,0 +1,39 @@ +// +// 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 Reusable + +class TitleHeaderView: UITableViewHeaderFooterView { + + @IBOutlet weak var label: UILabel! + + func update(title: String) { + label.text = title.uppercased() + } + +} + + +extension TitleHeaderView: NibReusable {} +extension TitleHeaderView: Themable { + + func update(theme: Theme) { + contentView.backgroundColor = theme.headerBackgroundColor + label.textColor = theme.headerTextSecondaryColor + label.font = theme.fonts.body + } +} diff --git a/Riot/Modules/Common/SectionHeaders/TitleHeaderView.xib b/Riot/Modules/Common/SectionHeaders/TitleHeaderView.xib new file mode 100644 index 000000000..c49ab7fff --- /dev/null +++ b/Riot/Modules/Common/SectionHeaders/TitleHeaderView.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index a4e4151f7..8480205af 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -74,7 +74,7 @@ /** init the segmentedViewController with a list of UIViewControllers. @param titles the section tiles - @param viewControllers the list of viewControllers to display. + @param someViewControllers the list of viewControllers to display. @param defaultSelected index of the default selected UIViewController in the list. */ - (void)initWithTitles:(NSArray*)titles viewControllers:(NSArray*)someViewControllers defaultSelected:(NSUInteger)defaultSelected diff --git a/Riot/Modules/CreateRoom/CreateRoomCoordinatorType.swift b/Riot/Modules/CreateRoom/CreateRoomCoordinatorType.swift index 2bddc933c..585538ddb 100644 --- a/Riot/Modules/CreateRoom/CreateRoomCoordinatorType.swift +++ b/Riot/Modules/CreateRoom/CreateRoomCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol CreateRoomCoordinatorDelegate: class { +protocol CreateRoomCoordinatorDelegate: AnyObject { func createRoomCoordinator(_ coordinator: CreateRoomCoordinatorType, didCreateNewRoom room: MXRoom) func createRoomCoordinatorDidCancel(_ coordinator: CreateRoomCoordinatorType) } diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/Cells/ChooseAvatarTableViewCell.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/Cells/ChooseAvatarTableViewCell.swift index 82160a816..bcca816cf 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/Cells/ChooseAvatarTableViewCell.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/Cells/ChooseAvatarTableViewCell.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -protocol ChooseAvatarTableViewCellDelegate: class { +protocol ChooseAvatarTableViewCellDelegate: AnyObject { func chooseAvatarTableViewCellDidTapChooseAvatar(_ cell: ChooseAvatarTableViewCell, sourceView: UIView) } diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsCoordinatorType.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsCoordinatorType.swift index d2798fcb5..2d02d6cda 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsCoordinatorType.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol EnterNewRoomDetailsCoordinatorDelegate: class { +protocol EnterNewRoomDetailsCoordinatorDelegate: AnyObject { func enterNewRoomDetailsCoordinator(_ coordinator: EnterNewRoomDetailsCoordinatorType, didCreateNewRoom room: MXRoom) func enterNewRoomDetailsCoordinatorDidCancel(_ coordinator: EnterNewRoomDetailsCoordinatorType) } diff --git a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModelType.swift b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModelType.swift index ea6b388c2..be053323d 100644 --- a/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModelType.swift +++ b/Riot/Modules/CreateRoom/EnterNewRoomDetails/EnterNewRoomDetailsViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol EnterNewRoomDetailsViewModelViewDelegate: class { +protocol EnterNewRoomDetailsViewModelViewDelegate: AnyObject { func enterNewRoomDetailsViewModel(_ viewModel: EnterNewRoomDetailsViewModelType, didUpdateViewState viewSate: EnterNewRoomDetailsViewState) } -protocol EnterNewRoomDetailsViewModelCoordinatorDelegate: class { +protocol EnterNewRoomDetailsViewModelCoordinatorDelegate: AnyObject { func enterNewRoomDetailsViewModel(_ viewModel: EnterNewRoomDetailsViewModelType, didCreateNewRoom room: MXRoom) func enterNewRoomDetailsViewModel(_ viewModel: EnterNewRoomDetailsViewModelType, didTapChooseAvatar sourceView: UIView) func enterNewRoomDetailsViewModelDidCancel(_ viewModel: EnterNewRoomDetailsViewModelType) diff --git a/Riot/Modules/CrossSigning/Banners/CrossSigningSetupBannerCell.swift b/Riot/Modules/CrossSigning/Banners/CrossSigningSetupBannerCell.swift index 6a7161bea..f0c13b154 100644 --- a/Riot/Modules/CrossSigning/Banners/CrossSigningSetupBannerCell.swift +++ b/Riot/Modules/CrossSigning/Banners/CrossSigningSetupBannerCell.swift @@ -16,7 +16,7 @@ import UIKit -@objc protocol CrossSigningSetupBannerCellDelegate: class { +@objc protocol CrossSigningSetupBannerCellDelegate: AnyObject { func crossSigningSetupBannerCellDidTapCloseAction(_ cell: CrossSigningSetupBannerCell) } diff --git a/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinatorType.swift b/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinatorType.swift index 1dc620d3f..ccd85e17b 100644 --- a/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinatorType.swift +++ b/Riot/Modules/CrossSigning/Setup/CrossSigningSetupCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol CrossSigningSetupCoordinatorDelegate: class { +protocol CrossSigningSetupCoordinatorDelegate: AnyObject { func crossSigningSetupCoordinatorDidComplete(_ coordinator: CrossSigningSetupCoordinatorType) func crossSigningSetupCoordinatorDidCancel(_ coordinator: CrossSigningSetupCoordinatorType) func crossSigningSetupCoordinator(_ coordinator: CrossSigningSetupCoordinatorType, didFailWithError error: Error) diff --git a/Riot/Modules/GDPR/GDPRConsentViewController.swift b/Riot/Modules/GDPR/GDPRConsentViewController.swift index 29ebdc22c..4a5cdee8d 100644 --- a/Riot/Modules/GDPR/GDPRConsentViewController.swift +++ b/Riot/Modules/GDPR/GDPRConsentViewController.swift @@ -16,7 +16,7 @@ import Foundation -@objc protocol GDPRConsentViewControllerDelegate: class { +@objc protocol GDPRConsentViewControllerDelegate: AnyObject { func gdprConsentViewControllerDidConsentToGDPRWithSuccess(_ gdprConsentViewController: GDPRConsentViewController) } diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m index 63cdbfbce..26c103fb2 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m @@ -54,20 +54,20 @@ self.titleLabel.text = NSLocalizedStringFromTable(@"directory_search_results_title", @"Vector", nil); // Do we need to display like ">20 results found" or "18 results found"? - NSString *descriptionLabel = (publicRoomsDirectoryDataSource.moreThanRoomsCount && publicRoomsDirectoryDataSource.roomsCount > 0) ? NSLocalizedStringFromTable(@"directory_search_results_more_than", @"Vector", nil) : NSLocalizedStringFromTable(@"directory_search_results", @"Vector", nil); + NSString *descriptionLabel = (publicRoomsDirectoryDataSource.searchResultsCountIsLimited && publicRoomsDirectoryDataSource.searchResultsCount > 0) ? NSLocalizedStringFromTable(@"directory_search_results_more_than", @"Vector", nil) : NSLocalizedStringFromTable(@"directory_search_results", @"Vector", nil); self.descriptionLabel.text = [NSString stringWithFormat:descriptionLabel, - publicRoomsDirectoryDataSource.roomsCount, + publicRoomsDirectoryDataSource.searchResultsCount, publicRoomsDirectoryDataSource.searchPattern]; } else { self.titleLabel.text = NSLocalizedStringFromTable(@"directory_cell_title", @"Vector", nil); self.descriptionLabel.text = [NSString stringWithFormat:NSLocalizedStringFromTable(@"directory_cell_description", @"Vector", nil), - publicRoomsDirectoryDataSource.roomsCount]; + publicRoomsDirectoryDataSource.searchResultsCount]; } - if (publicRoomsDirectoryDataSource.roomsCount) + if (publicRoomsDirectoryDataSource.searchResultsCount) { self.userInteractionEnabled = YES; self.chevronImageView.hidden = NO; diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index d8d5382fc..74fef7d37 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -347,7 +347,16 @@ tableViewCell.notificationsButton.tag = room.isMute || room.isMentionsOnly; [tableViewCell.notificationsButton addTarget:self action:@selector(onNotificationsButtonPressed:) forControlEvents:UIControlEventTouchUpInside]; - tableViewCell.notificationsImageView.image = [UIImage imageNamed:@"room_action_notification"]; + + if ([BuildSettings roomSettingsScreenShowNotificationsV2]) + { + tableViewCell.notificationsImageView.image = tableViewCell.notificationsButton.tag ? [UIImage imageNamed:@"room_action_notification_muted"] : [UIImage imageNamed:@"room_action_notification"]; + } + else + { + tableViewCell.notificationsImageView.image = [UIImage imageNamed:@"room_action_notification"]; + } + tableViewCell.notificationsImageView.tintColor = tableViewCell.notificationsButton.tag ? unselectedColor : selectedColor; // Get the room tag (use only the first one). @@ -663,8 +672,15 @@ MXRoom *room = [self.mainSession roomWithRoomId:editedRoomId]; if (room) { - UIButton *button = (UIButton*)sender; - [self muteEditedRoomNotifications:!button.tag]; + if ([BuildSettings roomSettingsScreenShowNotificationsV2]) + { + [self changeEditedRoomNotificationSettings]; + } + else + { + UIButton *button = (UIButton*)sender; + [self muteEditedRoomNotifications:!button.tag]; + } } } } diff --git a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift index 30d9c34d3..52bb891ea 100644 --- a/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Recover/KeyBackupRecoverCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol KeyBackupRecoverCoordinatorDelegate: class { +protocol KeyBackupRecoverCoordinatorDelegate: AnyObject { func keyBackupRecoverCoordinatorDidRecover(_ keyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType) func keyBackupRecoverCoordinatorDidCancel(_ keyBackupRecoverCoordinator: KeyBackupRecoverCoordinatorType) } diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinatorType.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinatorType.swift index c33cdcf06..a3bc9030b 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol KeyBackupRecoverFromPassphraseCoordinatorDelegate: class { +protocol KeyBackupRecoverFromPassphraseCoordinatorDelegate: AnyObject { func keyBackupRecoverFromPassphraseCoordinatorDidRecover(_ keyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassphraseCoordinatorType) func keyBackupRecoverFromPassphraseCoordinatorDoNotKnowPassphrase(_ keyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassphraseCoordinatorType) func keyBackupRecoverFromPassphraseCoordinatorDidCancel(_ keyBackupRecoverFromPassphraseCoordinator: KeyBackupRecoverFromPassphraseCoordinatorType) diff --git a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift index 8b19bc589..69bc84b01 100644 --- a/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift +++ b/Riot/Modules/KeyBackup/Recover/Passphrase/KeyBackupRecoverFromPassphraseViewModelType.swift @@ -16,11 +16,11 @@ import Foundation -protocol KeyBackupRecoverFromPassphraseViewModelViewDelegate: class { +protocol KeyBackupRecoverFromPassphraseViewModelViewDelegate: AnyObject { func keyBackupRecoverFromPassphraseViewModel(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromPassphraseViewState) } -protocol KeyBackupRecoverFromPassphraseViewModelCoordinatorDelegate: class { +protocol KeyBackupRecoverFromPassphraseViewModelCoordinatorDelegate: AnyObject { func keyBackupRecoverFromPassphraseViewModelDidRecover(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType) func keyBackupRecoverFromPassphraseViewModelDidCancel(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType) func keyBackupRecoverFromPassphraseViewModelDoNotKnowPassphrase(_ viewModel: KeyBackupRecoverFromPassphraseViewModelType) diff --git a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyCoordinatorType.swift b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyCoordinatorType.swift index aab042ba5..7146eeeae 100644 --- a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyBackupRecoverFromPrivateKeyCoordinatorDelegate: class { +protocol KeyBackupRecoverFromPrivateKeyCoordinatorDelegate: AnyObject { func keyBackupRecoverFromPrivateKeyCoordinatorDidRecover(_ coordinator: KeyBackupRecoverFromPrivateKeyCoordinatorType) func keyBackupRecoverFromPrivateKeyCoordinatorDidPrivateKeyFail(_ coordinator: KeyBackupRecoverFromPrivateKeyCoordinatorType) func keyBackupRecoverFromPrivateKeyCoordinatorDidCancel(_ coordinator: KeyBackupRecoverFromPrivateKeyCoordinatorType) diff --git a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModelType.swift b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModelType.swift index 1188e0560..396f401f1 100644 --- a/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModelType.swift +++ b/Riot/Modules/KeyBackup/Recover/PrivateKey/KeyBackupRecoverFromPrivateKeyViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyBackupRecoverFromPrivateKeyViewModelViewDelegate: class { +protocol KeyBackupRecoverFromPrivateKeyViewModelViewDelegate: AnyObject { func keyBackupRecoverFromPrivateKeyViewModel(_ viewModel: KeyBackupRecoverFromPrivateKeyViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromPrivateKeyViewState) } -protocol KeyBackupRecoverFromPrivateKeyViewModelCoordinatorDelegate: class { +protocol KeyBackupRecoverFromPrivateKeyViewModelCoordinatorDelegate: AnyObject { func keyBackupRecoverFromPrivateKeyViewModelDidRecover(_ viewModel: KeyBackupRecoverFromPrivateKeyViewModelType) func keyBackupRecoverFromPrivateKeyViewModelDidPrivateKeyFail(_ viewModel: KeyBackupRecoverFromPrivateKeyViewModelType) func keyBackupRecoverFromPrivateKeyViewModelDidCancel(_ viewModel: KeyBackupRecoverFromPrivateKeyViewModelType) diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift index 11d528b4f..c354fd13f 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate: class { +protocol KeyBackupRecoverFromRecoveryKeyCoordinatorDelegate: AnyObject { func keyBackupRecoverFromPassphraseCoordinatorDidRecover(_ keyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType) func keyBackupRecoverFromPassphraseCoordinatorDidCancel(_ keyBackupRecoverFromRecoveryKeyCoordinator: KeyBackupRecoverFromRecoveryKeyCoordinatorType) } diff --git a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift index e952c70a3..366d547d0 100644 --- a/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift +++ b/Riot/Modules/KeyBackup/Recover/RecoveryKey/KeyBackupRecoverFromRecoveryKeyViewModelType.swift @@ -16,11 +16,11 @@ import Foundation -protocol KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate: class { +protocol KeyBackupRecoverFromRecoveryKeyViewModelViewDelegate: AnyObject { func keyBackupRecoverFromPassphraseViewModel(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType, didUpdateViewState viewSate: KeyBackupRecoverFromRecoveryKeyViewState) } -protocol KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate: class { +protocol KeyBackupRecoverFromRecoveryKeyViewModelCoordinatorDelegate: AnyObject { func keyBackupRecoverFromRecoveryKeyViewModelDidRecover(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) func keyBackupRecoverFromRecoveryKeyViewModelDidCancel(_ viewModel: KeyBackupRecoverFromRecoveryKeyViewModelType) } diff --git a/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift b/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift index dd5a834da..8b58b241a 100644 --- a/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift +++ b/Riot/Modules/KeyBackup/Recover/Success/KeyBackupRecoverSuccessViewController.swift @@ -16,7 +16,7 @@ import UIKit -protocol KeyBackupRecoverSuccessViewControllerDelegate: class { +protocol KeyBackupRecoverSuccessViewControllerDelegate: AnyObject { func keyBackupRecoverSuccessViewControllerDidTapDone(_ keyBackupRecoverSuccessViewController: KeyBackupRecoverSuccessViewController) } diff --git a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift index c968500ed..2f4284fbd 100644 --- a/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Intro/KeyBackupSetupIntroViewController.swift @@ -16,7 +16,7 @@ import UIKit -protocol KeyBackupSetupIntroViewControllerDelegate: class { +protocol KeyBackupSetupIntroViewControllerDelegate: AnyObject { func keyBackupSetupIntroViewControllerDidTapSetupAction(_ keyBackupSetupIntroViewController: KeyBackupSetupIntroViewController) func keyBackupSetupIntroViewControllerDidCancel(_ keyBackupSetupIntroViewController: KeyBackupSetupIntroViewController) } diff --git a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift index f5a5dd0b0..612be7a1d 100644 --- a/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Setup/KeyBackupSetupCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol KeyBackupSetupCoordinatorDelegate: class { +protocol KeyBackupSetupCoordinatorDelegate: AnyObject { func keyBackupSetupCoordinatorDidCancel(_ keyBackupSetupCoordinator: KeyBackupSetupCoordinatorType) func keyBackupSetupCoordinatorDidSetupRecoveryKey(_ keyBackupSetupCoordinator: KeyBackupSetupCoordinatorType) } diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift index f94722adb..24403a387 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol KeyBackupSetupPassphraseCoordinatorDelegate: class { +protocol KeyBackupSetupPassphraseCoordinatorDelegate: AnyObject { func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseCoordinator(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType, didCreateBackupFromRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseCoordinatorDidCancel(_ keyBackupSetupPassphraseCoordinator: KeyBackupSetupPassphraseCoordinatorType) diff --git a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift index 2f4b2dfaa..89da31b4d 100644 --- a/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift +++ b/Riot/Modules/KeyBackup/Setup/Passphrase/KeyBackupSetupPassphraseViewModelType.swift @@ -16,12 +16,12 @@ import Foundation -protocol KeyBackupSetupPassphraseViewModelViewDelegate: class { +protocol KeyBackupSetupPassphraseViewModelViewDelegate: AnyObject { func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didUpdateViewState viewSate: KeyBackupSetupPassphraseViewState) func keyBackupSetupPassphraseViewModelShowSkipAlert(_ viewModel: KeyBackupSetupPassphraseViewModelType) } -protocol KeyBackupSetupPassphraseViewModelCoordinatorDelegate: class { +protocol KeyBackupSetupPassphraseViewModelCoordinatorDelegate: AnyObject { func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromPassphraseWithResultingRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseViewModel(_ viewModel: KeyBackupSetupPassphraseViewModelType, didCreateBackupFromRecoveryKey recoveryKey: String) func keyBackupSetupPassphraseViewModelDidCancel(_ viewModel: KeyBackupSetupPassphraseViewModelType) diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift index 57fe04ba9..563d4b0b6 100644 --- a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromPassphraseViewController.swift @@ -16,7 +16,7 @@ import UIKit -protocol KeyBackupSetupSuccessFromPassphraseViewControllerDelegate: class { +protocol KeyBackupSetupSuccessFromPassphraseViewControllerDelegate: AnyObject { func keyBackupSetupSuccessFromPassphraseViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromPassphraseViewController) } diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift index 6f474f753..0c33c5915 100644 --- a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromRecoveryKeyViewController.swift @@ -16,7 +16,7 @@ import UIKit -protocol KeyBackupSetupSuccessFromRecoveryKeyViewControllerDelegate: class { +protocol KeyBackupSetupSuccessFromRecoveryKeyViewControllerDelegate: AnyObject { func keyBackupSetupSuccessFromRecoveryKeyViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromRecoveryKeyViewController) } diff --git a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromSecureBackupViewController.swift b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromSecureBackupViewController.swift index c369cb5e9..dcd23e6d6 100644 --- a/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromSecureBackupViewController.swift +++ b/Riot/Modules/KeyBackup/Setup/Success/KeyBackupSetupSuccessFromSecureBackupViewController.swift @@ -16,7 +16,7 @@ import UIKit -protocol KeyBackupSetupSuccessFromSecureBackupViewControllerDelegate: class { +protocol KeyBackupSetupSuccessFromSecureBackupViewControllerDelegate: AnyObject { func keyBackupSetupSuccessFromSecureBackupViewControllerDidTapDoneAction(_ viewController: KeyBackupSetupSuccessFromSecureBackupViewController) } diff --git a/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinatorType.swift b/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinatorType.swift index 901d6b11d..ca1731afd 100644 --- a/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Common/KeyVerificationCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationCoordinatorDelegate: class { +protocol KeyVerificationCoordinatorDelegate: AnyObject { func keyVerificationCoordinatorDidComplete(_ coordinator: KeyVerificationCoordinatorType, otherUserId: String, otherDeviceId: String) func keyVerificationCoordinatorDidCancel(_ coordinator: KeyVerificationCoordinatorType) } diff --git a/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingCoordinatorType.swift b/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingCoordinatorType.swift index 8a7ba1dae..f0ff8bfa2 100644 --- a/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationDataLoadingCoordinatorDelegate: class { +protocol KeyVerificationDataLoadingCoordinatorDelegate: AnyObject { func keyVerificationDataLoadingCoordinator(_ coordinator: KeyVerificationDataLoadingCoordinatorType, didLoadUser user: MXUser, device: MXDeviceInfo) func keyVerificationDataLoadingCoordinator(_ coordinator: KeyVerificationDataLoadingCoordinatorType, didAcceptKeyVerificationRequestWithTransaction transaction: MXKeyVerificationTransaction) func keyVerificationDataLoadingCoordinator(_ coordinator: KeyVerificationDataLoadingCoordinatorType, didAcceptKeyVerificationRequest keyVerificationRequest: MXKeyVerificationRequest) diff --git a/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModelType.swift b/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModelType.swift index d55bcc3bd..223ce6f50 100644 --- a/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModelType.swift +++ b/Riot/Modules/KeyVerification/Common/Loading/KeyVerificationDataLoadingViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationDataLoadingViewModelViewDelegate: class { +protocol KeyVerificationDataLoadingViewModelViewDelegate: AnyObject { func keyVerificationDataLoadingViewModel(_ viewModel: KeyVerificationDataLoadingViewModelType, didUpdateViewState viewSate: KeyVerificationDataLoadingViewState) } -protocol KeyVerificationDataLoadingViewModelCoordinatorDelegate: class { +protocol KeyVerificationDataLoadingViewModelCoordinatorDelegate: AnyObject { func keyVerificationDataLoadingViewModel(_ viewModel: KeyVerificationDataLoadingViewModelType, didLoadUser user: MXUser, device: MXDeviceInfo) func keyVerificationDataLoadingViewModel(_ viewModel: KeyVerificationDataLoadingViewModelType, didAcceptKeyVerificationWithTransaction transaction: MXKeyVerificationTransaction) func keyVerificationDataLoadingViewModel(_ viewModel: KeyVerificationDataLoadingViewModelType, didAcceptKeyVerificationRequest keyVerificationRequest: MXKeyVerificationRequest) diff --git a/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationCoordinatorType.swift b/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationCoordinatorType.swift index 35a2381c4..8087fadb2 100644 --- a/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationScanConfirmationCoordinatorDelegate: class { +protocol KeyVerificationScanConfirmationCoordinatorDelegate: AnyObject { func keyVerificationScanConfirmationCoordinatorDidComplete(_ coordinator: KeyVerificationScanConfirmationCoordinatorType) func keyVerificationScanConfirmationCoordinatorDidCancel(_ coordinator: KeyVerificationScanConfirmationCoordinatorType) } diff --git a/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationViewModelType.swift b/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationViewModelType.swift index 03d843560..fc11ea2bd 100644 --- a/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationViewModelType.swift +++ b/Riot/Modules/KeyVerification/Common/ScanConfirmation/KeyVerificationScanConfirmationViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationScanConfirmationViewModelViewDelegate: class { +protocol KeyVerificationScanConfirmationViewModelViewDelegate: AnyObject { func keyVerificationScanConfirmationViewModel(_ viewModel: KeyVerificationScanConfirmationViewModelType, didUpdateViewState viewSate: KeyVerificationScanConfirmationViewState) } -protocol KeyVerificationScanConfirmationViewModelCoordinatorDelegate: class { +protocol KeyVerificationScanConfirmationViewModelCoordinatorDelegate: AnyObject { func keyVerificationScanConfirmationViewModelDidComplete(_ viewModel: KeyVerificationScanConfirmationViewModelType) func keyVerificationScanConfirmationViewModelDidCancel(_ viewModel: KeyVerificationScanConfirmationViewModelType) } diff --git a/Riot/Modules/KeyVerification/Common/Verified/KeyVerificationVerifiedViewController.swift b/Riot/Modules/KeyVerification/Common/Verified/KeyVerificationVerifiedViewController.swift index ed869052f..32cd0cf6a 100644 --- a/Riot/Modules/KeyVerification/Common/Verified/KeyVerificationVerifiedViewController.swift +++ b/Riot/Modules/KeyVerification/Common/Verified/KeyVerificationVerifiedViewController.swift @@ -18,7 +18,7 @@ import UIKit -protocol KeyVerificationVerifiedViewControllerDelegate: class { +protocol KeyVerificationVerifiedViewControllerDelegate: AnyObject { func keyVerificationVerifiedViewControllerDidTapSetupAction(_ viewController: KeyVerificationVerifiedViewController) func keyVerificationVerifiedViewControllerDidCancel(_ viewController: KeyVerificationVerifiedViewController) } diff --git a/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASCoordinatorType.swift b/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASCoordinatorType.swift index 378e2517e..77ac567ff 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationVerifyBySASCoordinatorDelegate: class { +protocol KeyVerificationVerifyBySASCoordinatorDelegate: AnyObject { func keyVerificationVerifyBySASCoordinatorDidComplete(_ coordinator: KeyVerificationVerifyBySASCoordinatorType) func keyVerificationVerifyBySASCoordinatorDidCancel(_ coordinator: KeyVerificationVerifyBySASCoordinatorType) } diff --git a/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASViewModelType.swift b/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASViewModelType.swift index a5686bc7a..10c26756a 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASViewModelType.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/SAS/KeyVerificationVerifyBySASViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationVerifyBySASViewModelViewDelegate: class { +protocol KeyVerificationVerifyBySASViewModelViewDelegate: AnyObject { func keyVerificationVerifyBySASViewModel(_ viewModel: KeyVerificationVerifyBySASViewModelType, didUpdateViewState viewSate: KeyVerificationVerifyViewState) } -protocol KeyVerificationVerifyBySASViewModelCoordinatorDelegate: class { +protocol KeyVerificationVerifyBySASViewModelCoordinatorDelegate: AnyObject { func keyVerificationVerifyViewModelDidComplete(_ viewModel: KeyVerificationVerifyBySASViewModelType) func keyVerificationVerifyViewModelDidCancel(_ viewModel: KeyVerificationVerifyBySASViewModelType) } diff --git a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningCoordinatorType.swift b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningCoordinatorType.swift index 0bf2711f6..5df1ebde6 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationVerifyByScanningCoordinatorDelegate: class { +protocol KeyVerificationVerifyByScanningCoordinatorDelegate: AnyObject { func keyVerificationVerifyByScanningCoordinatorDidCancel(_ coordinator: KeyVerificationVerifyByScanningCoordinatorType) func keyVerificationVerifyByScanningCoordinator(_ coordinator: KeyVerificationVerifyByScanningCoordinatorType, didScanOtherQRCodeData qrCodeData: MXQRCodeData, withTransaction transaction: MXQRCodeTransaction) func keyVerificationVerifyByScanningCoordinator(_ coordinator: KeyVerificationVerifyByScanningCoordinatorType, qrCodeDidScannedByOtherWithTransaction transaction: MXQRCodeTransaction) diff --git a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewController.swift b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewController.swift index fc01906da..49f1a80ca 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewController.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewController.swift @@ -143,7 +143,9 @@ final class KeyVerificationVerifyByScanningViewController: UIViewController { self.titleLabel.text = VectorL10n.keyVerificationVerifyQrCodeTitle self.informationLabel.text = VectorL10n.keyVerificationVerifyQrCodeInformation - self.scanCodeButton.setTitle(VectorL10n.keyVerificationVerifyQrCodeScanCodeAction, for: .normal) + // Hide until we have the type of the verification request + self.scanCodeButton.isHidden = true + self.cannotScanButton.setTitle(VectorL10n.keyVerificationVerifyQrCodeCannotScanAction, for: .normal) } @@ -157,8 +159,8 @@ final class KeyVerificationVerifyByScanningViewController: UIViewController { self.render(error: error) case .scannedCodeValidated(let isValid): self.renderScannedCode(valid: isValid) - case .cancelled(let reason): - self.renderCancelled(reason: reason) + case .cancelled(let reason, let verificationKind): + self.renderCancelled(reason: reason, verificationKind: verificationKind) case .cancelledByMe(let reason): self.renderCancelledByMe(reason: reason) } @@ -195,10 +197,13 @@ final class KeyVerificationVerifyByScanningViewController: UIViewController { switch viewData.verificationKind { case .user: informationText = VectorL10n.keyVerificationVerifyQrCodeInformation + self.scanCodeButton.setTitle(VectorL10n.keyVerificationVerifyQrCodeScanCodeAction, for: .normal) default: informationText = VectorL10n.keyVerificationVerifyQrCodeInformationOtherDevice + self.scanCodeButton.setTitle(VectorL10n.keyVerificationVerifyQrCodeScanCodeOtherDeviceAction, for: .normal) } + self.scanCodeButton.isHidden = false self.informationLabel.text = informationText } } @@ -231,12 +236,21 @@ final class KeyVerificationVerifyByScanningViewController: UIViewController { } } - private func renderCancelled(reason: MXTransactionCancelCode) { + private func renderCancelled(reason: MXTransactionCancelCode, + verificationKind: KeyVerificationKind) { self.activityPresenter.removeCurrentActivityIndicator(animated: true) self.stopQRCodeScanningIfPresented() - self.errorPresenter.presentError(from: self.alertPresentingViewController, title: "", message: VectorL10n.deviceVerificationCancelled, animated: true) { + // if we're verifying with someone else, let the user know they cancelled. + // if we're verifying our own device, assume the user probably knows since it was them who + // cancelled on their other device + if verificationKind == .user { + self.errorPresenter.presentError(from: self.alertPresentingViewController, title: "", message: VectorL10n.deviceVerificationCancelled, animated: true) { + self.dismissQRCodeScanningIfPresented(animated: false) + self.viewModel.process(viewAction: .cancel) + } + } else { self.dismissQRCodeScanningIfPresented(animated: false) self.viewModel.process(viewAction: .cancel) } diff --git a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModel.swift b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModel.swift index 706a121d9..de4b9e189 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModel.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModel.swift @@ -225,7 +225,7 @@ final class KeyVerificationVerifyByScanningViewModel: KeyVerificationVerifyBySca return } self.unregisterTransactionDidStateChangeNotification() - self.update(viewState: .cancelled(reason)) + self.update(viewState: .cancelled(cancelCode: reason, verificationKind: verificationKind)) case MXSASTransactionStateCancelledByMe: guard let reason = transaction.reasonCancelCode else { return @@ -251,7 +251,7 @@ final class KeyVerificationVerifyByScanningViewModel: KeyVerificationVerifyBySca return } self.unregisterTransactionDidStateChangeNotification() - self.update(viewState: .cancelled(reason)) + self.update(viewState: .cancelled(cancelCode: reason, verificationKind: verificationKind)) case .cancelledByMe: guard let reason = transaction.reasonCancelCode else { return diff --git a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModelType.swift b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModelType.swift index 4be0568d5..d7eedfabc 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModelType.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationVerifyByScanningViewModelViewDelegate: class { +protocol KeyVerificationVerifyByScanningViewModelViewDelegate: AnyObject { func keyVerificationVerifyByScanningViewModel(_ viewModel: KeyVerificationVerifyByScanningViewModelType, didUpdateViewState viewSate: KeyVerificationVerifyByScanningViewState) } -protocol KeyVerificationVerifyByScanningViewModelCoordinatorDelegate: class { +protocol KeyVerificationVerifyByScanningViewModelCoordinatorDelegate: AnyObject { func keyVerificationVerifyByScanningViewModelDidCancel(_ viewModel: KeyVerificationVerifyByScanningViewModelType) func keyVerificationVerifyByScanningViewModel(_ viewModel: KeyVerificationVerifyByScanningViewModelType, didScanOtherQRCodeData qrCodeData: MXQRCodeData, withTransaction transaction: MXQRCodeTransaction) diff --git a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewState.swift b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewState.swift index b6323eb70..e3ecc8238 100644 --- a/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewState.swift +++ b/Riot/Modules/KeyVerification/Common/Verify/Scanning/KeyVerificationVerifyByScanningViewState.swift @@ -29,7 +29,7 @@ enum KeyVerificationVerifyByScanningViewState { case loading case loaded(viewData: KeyVerificationVerifyByScanningViewData) case scannedCodeValidated(isValid: Bool) - case cancelled(MXTransactionCancelCode) + case cancelled(cancelCode: MXTransactionCancelCode, verificationKind: KeyVerificationKind) case cancelledByMe(MXTransactionCancelCode) case error(Error) } diff --git a/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingCoordinatorType.swift b/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingCoordinatorType.swift index 46e135212..1d5e600ab 100644 --- a/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol DeviceVerificationIncomingCoordinatorDelegate: class { +protocol DeviceVerificationIncomingCoordinatorDelegate: AnyObject { func deviceVerificationIncomingCoordinator(_ coordinator: DeviceVerificationIncomingCoordinatorType, didAcceptTransaction message: MXSASTransaction) func deviceVerificationIncomingCoordinatorDidCancel(_ coordinator: DeviceVerificationIncomingCoordinatorType) } diff --git a/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingViewModelType.swift b/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingViewModelType.swift index 465fb4013..48b148aa1 100644 --- a/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/Incoming/DeviceVerificationIncomingViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol DeviceVerificationIncomingViewModelViewDelegate: class { +protocol DeviceVerificationIncomingViewModelViewDelegate: AnyObject { func deviceVerificationIncomingViewModel(_ viewModel: DeviceVerificationIncomingViewModelType, didUpdateViewState viewSate: DeviceVerificationIncomingViewState) } -protocol DeviceVerificationIncomingViewModelCoordinatorDelegate: class { +protocol DeviceVerificationIncomingViewModelCoordinatorDelegate: AnyObject { func deviceVerificationIncomingViewModel(_ viewModel: DeviceVerificationIncomingViewModelType, didAcceptTransaction transaction: MXSASTransaction) func deviceVerificationIncomingViewModelDidCancel(_ viewModel: DeviceVerificationIncomingViewModelType) } diff --git a/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyCoordinatorType.swift b/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyCoordinatorType.swift index 7f37b9564..ef098fcd2 100644 --- a/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationManuallyVerifyCoordinatorDelegate: class { +protocol KeyVerificationManuallyVerifyCoordinatorDelegate: AnyObject { func keyVerificationManuallyVerifyCoordinator(_ coordinator: KeyVerificationManuallyVerifyCoordinatorType, didVerifiedDeviceWithId deviceId: String, of userId: String) func keyVerificationManuallyVerifyCoordinatorDidCancel(_ coordinator: KeyVerificationManuallyVerifyCoordinatorType) } diff --git a/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyViewModelType.swift b/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyViewModelType.swift index 49f1972a5..1f1a73a57 100644 --- a/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/ManuallyVerify/KeyVerificationManuallyVerifyViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationManuallyVerifyViewModelViewDelegate: class { +protocol KeyVerificationManuallyVerifyViewModelViewDelegate: AnyObject { func keyVerificationManuallyVerifyViewModel(_ viewModel: KeyVerificationManuallyVerifyViewModelType, didUpdateViewState viewSate: KeyVerificationManuallyVerifyViewState) } -protocol KeyVerificationManuallyVerifyViewModelCoordinatorDelegate: class { +protocol KeyVerificationManuallyVerifyViewModelCoordinatorDelegate: AnyObject { func keyVerificationManuallyVerifyViewModel(_ viewModel: KeyVerificationManuallyVerifyViewModelType, didVerifiedDeviceWithId deviceId: String, of userId: String) func keyVerificationManuallyVerifyViewModelDidCancel(_ viewModel: KeyVerificationManuallyVerifyViewModelType) } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartCoordinatorType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartCoordinatorType.swift index faa2a8555..6799602d3 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationSelfVerifyStartCoordinatorDelegate: class { +protocol KeyVerificationSelfVerifyStartCoordinatorDelegate: AnyObject { func keyVerificationSelfVerifyStartCoordinator(_ coordinator: KeyVerificationSelfVerifyStartCoordinatorType, otherDidAcceptRequest request: MXKeyVerificationRequest) diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartViewModelType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartViewModelType.swift index 0de1eccf5..2f70b5a31 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyStart/KeyVerificationSelfVerifyStartViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationSelfVerifyStartViewModelViewDelegate: class { +protocol KeyVerificationSelfVerifyStartViewModelViewDelegate: AnyObject { func keyVerificationSelfVerifyStartViewModel(_ viewModel: KeyVerificationSelfVerifyStartViewModelType, didUpdateViewState viewSate: KeyVerificationSelfVerifyStartViewState) } -protocol KeyVerificationSelfVerifyStartViewModelCoordinatorDelegate: class { +protocol KeyVerificationSelfVerifyStartViewModelCoordinatorDelegate: AnyObject { func keyVerificationSelfVerifyStartViewModel(_ viewModel: KeyVerificationSelfVerifyStartViewModelType, otherDidAcceptRequest request: MXKeyVerificationRequest) func keyVerificationSelfVerifyStartViewModelDidCancel(_ viewModel: KeyVerificationSelfVerifyStartViewModelType) } diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift index 6c0219c4a..ba1b6c410 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol KeyVerificationSelfVerifyWaitCoordinatorDelegate: class { +protocol KeyVerificationSelfVerifyWaitCoordinatorDelegate: AnyObject { func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, didAcceptKeyVerificationRequest keyVerificationRequest: MXKeyVerificationRequest) func keyVerificationSelfVerifyWaitCoordinator(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType, didAcceptIncomingSASTransaction incomingSASTransaction: MXIncomingSASTransaction) func keyVerificationSelfVerifyWaitCoordinatorDidCancel(_ coordinator: KeyVerificationSelfVerifyWaitCoordinatorType) diff --git a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift index c6fc85ff0..264a73b83 100644 --- a/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/SelfVerifyWait/KeyVerificationSelfVerifyWaitViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol KeyVerificationSelfVerifyWaitViewModelViewDelegate: class { +protocol KeyVerificationSelfVerifyWaitViewModelViewDelegate: AnyObject { func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, didUpdateViewState viewSate: KeyVerificationSelfVerifyWaitViewState) } -protocol KeyVerificationSelfVerifyWaitViewModelCoordinatorDelegate: class { +protocol KeyVerificationSelfVerifyWaitViewModelCoordinatorDelegate: AnyObject { func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, didAcceptKeyVerificationRequest keyVerificationRequest: MXKeyVerificationRequest) func keyVerificationSelfVerifyWaitViewModel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType, didAcceptIncomingSASTransaction incomingSASTransaction: MXIncomingSASTransaction) func keyVerificationSelfVerifyWaitViewModelDidCancel(_ viewModel: KeyVerificationSelfVerifyWaitViewModelType) diff --git a/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartCoordinatorType.swift b/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartCoordinatorType.swift index 72871ee60..16a79760c 100644 --- a/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol DeviceVerificationStartCoordinatorDelegate: class { +protocol DeviceVerificationStartCoordinatorDelegate: AnyObject { func deviceVerificationStartCoordinator(_ coordinator: DeviceVerificationStartCoordinatorType, didCompleteWithOutgoingTransaction transaction: MXSASTransaction) func deviceVerificationStartCoordinator(_ coordinator: DeviceVerificationStartCoordinatorType, didTransactionCancelled transaction: MXSASTransaction) diff --git a/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartViewModelType.swift b/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartViewModelType.swift index 07da5a197..015e80faf 100644 --- a/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartViewModelType.swift +++ b/Riot/Modules/KeyVerification/Device/Start/DeviceVerificationStartViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol DeviceVerificationStartViewModelViewDelegate: class { +protocol DeviceVerificationStartViewModelViewDelegate: AnyObject { func deviceVerificationStartViewModel(_ viewModel: DeviceVerificationStartViewModelType, didUpdateViewState viewSate: DeviceVerificationStartViewState) } -protocol DeviceVerificationStartViewModelCoordinatorDelegate: class { +protocol DeviceVerificationStartViewModelCoordinatorDelegate: AnyObject { func deviceVerificationStartViewModelDidUseLegacyVerification(_ viewModel: DeviceVerificationStartViewModelType) func deviceVerificationStartViewModel(_ viewModel: DeviceVerificationStartViewModelType, didCompleteWithOutgoingTransaction transaction: MXSASTransaction) diff --git a/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusCoordinatorType.swift b/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusCoordinatorType.swift index 05d2c73b8..107fa42fa 100644 --- a/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol UserVerificationSessionStatusCoordinatorDelegate: class { +protocol UserVerificationSessionStatusCoordinatorDelegate: AnyObject { func userVerificationSessionStatusCoordinator(_ coordinator: UserVerificationSessionStatusCoordinatorType, wantsToVerifyDeviceWithId deviceId: String, for userId: String) func userVerificationSessionStatusCoordinator(_ coordinator: UserVerificationSessionStatusCoordinatorType, wantsToManuallyVerifyDeviceWithId deviceId: String, for userId: String) func userVerificationSessionStatusCoordinatorDidClose(_ coordinator: UserVerificationSessionStatusCoordinatorType) diff --git a/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusViewModelType.swift b/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusViewModelType.swift index 4598b4fa8..b600e235e 100644 --- a/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusViewModelType.swift +++ b/Riot/Modules/KeyVerification/User/SessionStatus/UserVerificationSessionStatusViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol UserVerificationSessionStatusViewModelViewDelegate: class { +protocol UserVerificationSessionStatusViewModelViewDelegate: AnyObject { func userVerificationSessionStatusViewModel(_ viewModel: UserVerificationSessionStatusViewModelType, didUpdateViewState viewSate: UserVerificationSessionStatusViewState) } -protocol UserVerificationSessionStatusViewModelCoordinatorDelegate: class { +protocol UserVerificationSessionStatusViewModelCoordinatorDelegate: AnyObject { func userVerificationSessionStatusViewModel(_ viewModel: UserVerificationSessionStatusViewModelType, wantsToVerifyDeviceWithId deviceId: String, for userId: String) func userVerificationSessionStatusViewModel(_ viewModel: UserVerificationSessionStatusViewModelType, wantsToManuallyVerifyDeviceWithId deviceId: String, for userId: String) func userVerificationSessionStatusViewModelDidClose(_ viewModel: UserVerificationSessionStatusViewModelType) diff --git a/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusCoordinatorType.swift b/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusCoordinatorType.swift index 46eccaaa5..67c39e688 100644 --- a/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol UserVerificationSessionsStatusCoordinatorDelegate: class { +protocol UserVerificationSessionsStatusCoordinatorDelegate: AnyObject { func userVerificationSessionsStatusCoordinatorDidClose(_ coordinator: UserVerificationSessionsStatusCoordinatorType) func userVerificationSessionsStatusCoordinator(_ coordinator: UserVerificationSessionsStatusCoordinatorType, didSelectDeviceWithId deviceId: String, for userId: String) } diff --git a/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModelType.swift b/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModelType.swift index 4df41221d..fe704b6ad 100644 --- a/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModelType.swift +++ b/Riot/Modules/KeyVerification/User/SessionsStatus/UserVerificationSessionsStatusViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol UserVerificationSessionsStatusViewModelViewDelegate: class { +protocol UserVerificationSessionsStatusViewModelViewDelegate: AnyObject { func userVerificationSessionsStatusViewModel(_ viewModel: UserVerificationSessionsStatusViewModelType, didUpdateViewState viewSate: UserVerificationSessionsStatusViewState) } -protocol UserVerificationSessionsStatusViewModelCoordinatorDelegate: class { +protocol UserVerificationSessionsStatusViewModelCoordinatorDelegate: AnyObject { func userVerificationSessionsStatusViewModel(_ viewModel: UserVerificationSessionsStatusViewModelType, didSelectDeviceWithId deviceId: String, for userId: String) func userVerificationSessionsStatusViewModelDidClose(_ viewModel: UserVerificationSessionsStatusViewModelType) } diff --git a/Riot/Modules/KeyVerification/User/Start/UserVerificationStartCoordinatorType.swift b/Riot/Modules/KeyVerification/User/Start/UserVerificationStartCoordinatorType.swift index ba5c677d9..7f0130b5a 100644 --- a/Riot/Modules/KeyVerification/User/Start/UserVerificationStartCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/User/Start/UserVerificationStartCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol UserVerificationStartCoordinatorDelegate: class { +protocol UserVerificationStartCoordinatorDelegate: AnyObject { func userVerificationStartCoordinator(_ coordinator: UserVerificationStartCoordinatorType, otherDidAcceptRequest request: MXKeyVerificationRequest) diff --git a/Riot/Modules/KeyVerification/User/Start/UserVerificationStartViewModelType.swift b/Riot/Modules/KeyVerification/User/Start/UserVerificationStartViewModelType.swift index 40582e0bf..b84043938 100644 --- a/Riot/Modules/KeyVerification/User/Start/UserVerificationStartViewModelType.swift +++ b/Riot/Modules/KeyVerification/User/Start/UserVerificationStartViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol UserVerificationStartViewModelViewDelegate: class { +protocol UserVerificationStartViewModelViewDelegate: AnyObject { func userVerificationStartViewModel(_ viewModel: UserVerificationStartViewModelType, didUpdateViewState viewSate: UserVerificationStartViewState) } -protocol UserVerificationStartViewModelCoordinatorDelegate: class { +protocol UserVerificationStartViewModelCoordinatorDelegate: AnyObject { func userVerificationStartViewModel(_ viewModel: UserVerificationStartViewModelType, otherDidAcceptRequest request: MXKeyVerificationRequest) diff --git a/Riot/Modules/KeyVerification/User/UserVerificationCoordinatorType.swift b/Riot/Modules/KeyVerification/User/UserVerificationCoordinatorType.swift index feeba8d3b..db665607e 100644 --- a/Riot/Modules/KeyVerification/User/UserVerificationCoordinatorType.swift +++ b/Riot/Modules/KeyVerification/User/UserVerificationCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol UserVerificationCoordinatorDelegate: class { +protocol UserVerificationCoordinatorDelegate: AnyObject { func userVerificationCoordinatorDidComplete(_ coordinator: UserVerificationCoordinatorType) } diff --git a/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift b/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift index d3b9c2c0d..61586be8d 100644 --- a/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift +++ b/Riot/Modules/MediaPicker/MediaPickerCoordinator.swift @@ -83,8 +83,8 @@ extension MediaPickerCoordinator: MediaPickerViewControllerDelegate { self.delegate?.mediaPickerCoordinator(self, didSelectImageData: imageData, withUTI: uti) } - func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelectVideo videoURL: URL!) { - self.delegate?.mediaPickerCoordinator(self, didSelectVideoAt: videoURL) + func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelectVideo videoAsset: AVAsset!) { + self.delegate?.mediaPickerCoordinator(self, didSelectVideo: videoAsset) } func mediaPickerController(_ mediaPickerController: MediaPickerViewController!, didSelect assets: [PHAsset]!) { diff --git a/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift b/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift index 0ba21d893..782662ea9 100644 --- a/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift +++ b/Riot/Modules/MediaPicker/MediaPickerCoordinatorBridgePresenter.swift @@ -20,7 +20,7 @@ import Foundation @objc protocol MediaPickerCoordinatorBridgePresenterDelegate { func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) - func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideoAt url: URL) + func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideo videoAsset: AVAsset) func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectAssets assets: [PHAsset]) func mediaPickerCoordinatorBridgePresenterDidCancel(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter) } @@ -110,8 +110,8 @@ extension MediaPickerCoordinatorBridgePresenter: MediaPickerCoordinatorDelegate self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectImageData: imageData, withUTI: uti) } - func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideoAt url: URL) { - self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectVideoAt: url) + func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideo videoAsset: AVAsset) { + self.delegate?.mediaPickerCoordinatorBridgePresenter(self, didSelectVideo: videoAsset) } func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectAssets assets: [PHAsset]) { diff --git a/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift b/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift index 53f154536..4f8fc5d8f 100644 --- a/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift +++ b/Riot/Modules/MediaPicker/MediaPickerCoordinatorType.swift @@ -18,9 +18,9 @@ import Foundation -protocol MediaPickerCoordinatorDelegate: class { +protocol MediaPickerCoordinatorDelegate: AnyObject { func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) - func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideoAt url: URL) + func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectVideo videoAsset: AVAsset) func mediaPickerCoordinator(_ coordinator: MediaPickerCoordinatorType, didSelectAssets assets: [PHAsset]) func mediaPickerCoordinatorDidCancel(_ coordinator: MediaPickerCoordinatorType) } diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.h b/Riot/Modules/MediaPicker/MediaPickerViewController.h index 99e9365fe..71487e1ea 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.h +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.h @@ -39,9 +39,9 @@ Tells the delegate that the user select a video. @param mediaPickerController the `MediaPickerViewController` instance. - @param videoURL the local url of the video to send. + @param videoAsset an `AVAsset` that represents the video to send. */ -- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(NSURL*)videoURL; +- (void)mediaPickerController:(MediaPickerViewController *)mediaPickerController didSelectVideo:(AVAsset*)videoAsset; /** Tells the delegate that the user wants to cancel media picking. diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index 6b7725a11..e34617241 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -608,28 +608,19 @@ if (asset) { - if ([asset isKindOfClass:[AVURLAsset class]]) - { - MXLogDebug(@"[MediaPickerVC] didSelectAsset: Got AVAsset for video"); - AVURLAsset *avURLAsset = (AVURLAsset*)asset; + MXLogDebug(@"[MediaPickerVC] didSelectAsset: Got AVAsset for video"); + + // Validate first the selected video + [self validateSelectedVideo:asset responseHandler:^(BOOL isValidated) { + + if (isValidated) + { + [self.delegate mediaPickerController:self didSelectVideo:asset]; + } - // Validate first the selected video - [self validateSelectedVideo:[avURLAsset URL] responseHandler:^(BOOL isValidated) { - - if (isValidated) - { - [self.delegate mediaPickerController:self didSelectVideo:[avURLAsset URL]]; - } - - self->isValidationInProgress = NO; - - }]; - } - else - { - MXLogDebug(@"[MediaPickerVC] Selected video asset is not initialized from an URL!"); self->isValidationInProgress = NO; - } + + }]; } else { @@ -693,7 +684,7 @@ [self setNeedsStatusBarAppearanceUpdate]; } -- (void)validateSelectedVideo:(NSURL*)selectedVideoURL responseHandler:(void (^)(BOOL isValidated))handler +- (void)validateSelectedVideo:(AVAsset*)selectedVideo responseHandler:(void (^)(BOOL isValidated))handler { [self dismissImageValidationView]; @@ -727,15 +718,16 @@ videoPlayer = [[AVPlayerViewController alloc] init]; if (videoPlayer) { + AVPlayerItem *item = [AVPlayerItem playerItemWithAsset:selectedVideo]; videoPlayer.allowsPictureInPicturePlayback = NO; videoPlayer.updatesNowPlayingInfoCenter = NO; - videoPlayer.player = [AVPlayer playerWithURL:selectedVideoURL]; + videoPlayer.player = [AVPlayer playerWithPlayerItem:item]; videoPlayer.videoGravity = AVLayerVideoGravityResizeAspect; videoPlayer.showsPlaybackControls = NO; // create a thumbnail for the first frame - AVAsset *asset = [AVAsset assetWithURL:selectedVideoURL]; - AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset]; + AVAssetImageGenerator *generator = [AVAssetImageGenerator assetImageGeneratorWithAsset:selectedVideo]; + generator.appliesPreferredTrackTransform = YES; CGImageRef thumbnailRef = [generator copyCGImageAtTime:kCMTimeZero actualTime:nil error:nil]; // set thumbnail on validationView diff --git a/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift b/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift index f8bc066ee..1a1d20169 100644 --- a/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift +++ b/Riot/Modules/MediaPicker/SingleImagePickerPresenter.swift @@ -18,7 +18,7 @@ import Foundation import UIKit import AVFoundation -@objc protocol SingleImagePickerPresenterDelegate: class { +@objc protocol SingleImagePickerPresenterDelegate: AnyObject { func singleImagePickerPresenter(_ presenter: SingleImagePickerPresenter, didSelectImageData imageData: Data, withUTI uti: MXKUTI?) func singleImagePickerPresenterDidCancel(_ presenter: SingleImagePickerPresenter) } @@ -135,7 +135,7 @@ extension SingleImagePickerPresenter: MediaPickerCoordinatorBridgePresenterDeleg self.delegate?.singleImagePickerPresenter(self, didSelectImageData: imageData, withUTI: uti) } - func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideoAt url: URL) { + func mediaPickerCoordinatorBridgePresenter(_ coordinatorBridgePresenter: MediaPickerCoordinatorBridgePresenter, didSelectVideo videoAsset: AVAsset) { self.delegate?.singleImagePickerPresenterDidCancel(self) } diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h index 752cce049..750daac05 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h @@ -62,11 +62,16 @@ @property (nonatomic, readonly) NSString *directoryServerDisplayname; /** - The number of public rooms matching `searchPattern`. - It is accurate only if 'moreThanRoomsCount' is NO. + The number of public rooms that have been fetched so far. */ @property (nonatomic, readonly) NSUInteger roomsCount; +/** + The total number of public rooms matching `searchPattern`. + It is accurate only if 'searchResultsCountIsLimited' is NO. + */ +@property (nonatomic, readonly) NSUInteger searchResultsCount; + /** In case of search with a lot of matching public rooms, we cannot return an accurate value except by paginating the full list of rooms, which is not expected. @@ -74,7 +79,7 @@ This flag indicates that we know that there is more matching rooms than we got so far. */ -@property (nonatomic, readonly) BOOL moreThanRoomsCount; +@property (nonatomic, readonly) BOOL searchResultsCountIsLimited; /** The maximum number of public rooms to retrieve during a pagination. diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m index e69035aa0..fa8ac0ab0 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m @@ -165,6 +165,11 @@ static NSString *const kNSFWKeyword = @"nsfw"; } } +- (NSUInteger)roomsCount +{ + return rooms.count; +} + - (NSIndexPath*)cellIndexPathWithRoomId:(NSString*)roomId andMatrixSession:(MXSession*)matrixSession { NSIndexPath *indexPath = nil; @@ -217,8 +222,8 @@ static NSString *const kNSFWKeyword = @"nsfw"; // Reset all pagination vars [rooms removeAllObjects]; nextBatch = nil; - _roomsCount = 0; - _moreThanRoomsCount = NO; + _searchResultsCount = 0; + _searchResultsCountIsLimited = NO; _hasReachedPaginationEnd = NO; } @@ -264,14 +269,14 @@ static NSString *const kNSFWKeyword = @"nsfw"; if (!self->_searchPattern) { // When there is no search, we can use totalRoomCountEstimate returned by the server - self->_roomsCount = publicRoomsResponse.totalRoomCountEstimate; - self->_moreThanRoomsCount = NO; + self->_searchResultsCount = publicRoomsResponse.totalRoomCountEstimate; + self->_searchResultsCountIsLimited = NO; } else { // Else we can only display something like ">20 matching rooms" - self->_roomsCount = self->rooms.count; - self->_moreThanRoomsCount = publicRoomsResponse.nextBatch ? YES : NO; + self->_searchResultsCount = self->rooms.count; + self->_searchResultsCountIsLimited = publicRoomsResponse.nextBatch ? YES : NO; } // Detect pagination end diff --git a/Riot/Modules/QRCode/Reader/QRCodeReaderViewController.swift b/Riot/Modules/QRCode/Reader/QRCodeReaderViewController.swift index 766795d63..4d35af705 100644 --- a/Riot/Modules/QRCode/Reader/QRCodeReaderViewController.swift +++ b/Riot/Modules/QRCode/Reader/QRCodeReaderViewController.swift @@ -17,7 +17,7 @@ import UIKit import ZXingObjC -protocol QRCodeReaderViewControllerDelegate: class { +protocol QRCodeReaderViewControllerDelegate: AnyObject { func qrCodeReaderViewController(_ viewController: QRCodeReaderViewController, didFound payloadData: Data) func qrCodeReaderViewControllerDidCancel(_ viewController: QRCodeReaderViewController) } diff --git a/Riot/Modules/Reauthentication/ReauthenticationCoordinatorType.swift b/Riot/Modules/Reauthentication/ReauthenticationCoordinatorType.swift index bdbc31ce2..96c48215d 100644 --- a/Riot/Modules/Reauthentication/ReauthenticationCoordinatorType.swift +++ b/Riot/Modules/Reauthentication/ReauthenticationCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol ReauthenticationCoordinatorDelegate: class { +protocol ReauthenticationCoordinatorDelegate: AnyObject { func reauthenticationCoordinatorDidComplete(_ coordinator: ReauthenticationCoordinatorType, withAuthenticationParameters: [String: Any]?) func reauthenticationCoordinatorDidCancel(_ coordinator: ReauthenticationCoordinatorType) func reauthenticationCoordinator(_ coordinator: ReauthenticationCoordinatorType, didFailWithError: Error) diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift index e67dcfdbd..77cab862e 100644 --- a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewModelType.swift @@ -39,7 +39,7 @@ enum BubbleReactionsViewState { } } -@objc protocol BubbleReactionsViewModelDelegate: class { +@objc protocol BubbleReactionsViewModelDelegate: AnyObject { func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didAddReaction reactionCount: MXReactionCount, forEventId eventId: String) func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didRemoveReaction reactionCount: MXReactionCount, forEventId eventId: String) func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didShowAllTappedForEventId eventId: String) @@ -47,7 +47,7 @@ enum BubbleReactionsViewState { func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didLongPressForEventId eventId: String) } -protocol BubbleReactionsViewModelViewDelegate: class { +protocol BubbleReactionsViewModelViewDelegate: AnyObject { func bubbleReactionsViewModel(_ viewModel: BubbleReactionsViewModel, didUpdateViewState viewState: BubbleReactionsViewState) } diff --git a/Riot/Modules/Room/ContextualMenu/ReactionsMenu/ReactionsMenuViewModelType.swift b/Riot/Modules/Room/ContextualMenu/ReactionsMenu/ReactionsMenuViewModelType.swift index fee8b41d9..2171e3ab5 100644 --- a/Riot/Modules/Room/ContextualMenu/ReactionsMenu/ReactionsMenuViewModelType.swift +++ b/Riot/Modules/Room/ContextualMenu/ReactionsMenu/ReactionsMenuViewModelType.swift @@ -16,11 +16,11 @@ import Foundation -protocol ReactionsMenuViewModelViewDelegate: class { +protocol ReactionsMenuViewModelViewDelegate: AnyObject { func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didUpdateViewState viewState: ReactionsMenuViewState) } -@objc protocol ReactionsMenuViewModelCoordinatorDelegate: class { +@objc protocol ReactionsMenuViewModelCoordinatorDelegate: AnyObject { func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didAddReaction reaction: String, forEventId eventId: String) func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didRemoveReaction reaction: String, forEventId eventId: String) func reactionsMenuViewModelDidTapMoreReactions(_ viewModel: ReactionsMenuViewModel, forEventId eventId: String) diff --git a/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift b/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift index 32052dc06..e236a6ec1 100644 --- a/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift +++ b/Riot/Modules/Room/ContextualMenu/RoomContextualMenuViewController.swift @@ -16,7 +16,7 @@ import UIKit -@objc protocol RoomContextualMenuViewControllerDelegate: class { +@objc protocol RoomContextualMenuViewControllerDelegate: AnyObject { func roomContextualMenuViewControllerDidTapBackgroundOverlay(_ viewController: RoomContextualMenuViewController) } diff --git a/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalCoordinatorType.swift b/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalCoordinatorType.swift index 02ff0e62e..0629043b0 100644 --- a/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalCoordinatorType.swift +++ b/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol RoomCreationEventsModalCoordinatorDelegate: class { +protocol RoomCreationEventsModalCoordinatorDelegate: AnyObject { func roomCreationEventsModalCoordinatorDidTapClose(_ coordinator: RoomCreationEventsModalCoordinatorType) } diff --git a/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalViewModelType.swift b/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalViewModelType.swift index 6a670c1f5..5378da659 100644 --- a/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalViewModelType.swift +++ b/Riot/Modules/Room/CreationModal/RoomCreationEventsModal/RoomCreationEventsModalViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol RoomCreationEventsModalViewModelViewDelegate: class { +protocol RoomCreationEventsModalViewModelViewDelegate: AnyObject { func roomCreationEventsModalViewModel(_ viewModel: RoomCreationEventsModalViewModelType, didUpdateViewState viewSate: RoomCreationEventsModalViewState) } -protocol RoomCreationEventsModalViewModelCoordinatorDelegate: class { +protocol RoomCreationEventsModalViewModelCoordinatorDelegate: AnyObject { func roomCreationEventsModalViewModelDidTapClose(_ viewModel: RoomCreationEventsModalViewModelType) } diff --git a/Riot/Modules/Room/CreationModal/RoomCreationModalCoordinatorType.swift b/Riot/Modules/Room/CreationModal/RoomCreationModalCoordinatorType.swift index 11f3a1c21..f1830a0c1 100644 --- a/Riot/Modules/Room/CreationModal/RoomCreationModalCoordinatorType.swift +++ b/Riot/Modules/Room/CreationModal/RoomCreationModalCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol RoomCreationModalCoordinatorDelegate: class { +protocol RoomCreationModalCoordinatorDelegate: AnyObject { func roomCreationModalCoordinatorDidComplete(_ coordinator: RoomCreationModalCoordinatorType) } diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 831f96634..434aee6ac 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -887,8 +887,10 @@ const CGFloat kTypingCellHeight = 24; success:(void (^)(NSString *eventId))success failure:(void (^)(NSError *error))failure { + AVURLAsset *videoAsset = [AVURLAsset assetWithURL:videoLocalURL]; UIImage *videoThumbnail = [MXKVideoThumbnailGenerator.shared generateThumbnailFrom:videoLocalURL]; - [self sendVideo:videoLocalURL withThumbnail:videoThumbnail success:success failure:failure]; + + [self sendVideoAsset:videoAsset withThumbnail:videoThumbnail success:success failure:failure]; } - (void)acceptVerificationRequestForEventId:(NSString*)eventId success:(void(^)(void))success failure:(void(^)(NSError*))failure @@ -1037,12 +1039,10 @@ const CGFloat kTypingCellHeight = 24; - (void)applyMaskToAttachmentViewOfBubbleCell:(MXKRoomBubbleTableViewCell *)cell { - if (cell.attachmentView && !cell.attachmentView.layer.mask) + if (cell.attachmentView) { - UIBezierPath *myClippingPath = [UIBezierPath bezierPathWithRoundedRect:cell.attachmentView.bounds cornerRadius:6]; - CAShapeLayer *mask = [CAShapeLayer layer]; - mask.path = myClippingPath.CGPath; - cell.attachmentView.layer.mask = mask; + cell.attachmentView.layer.cornerRadius = 6; + cell.attachmentView.layer.masksToBounds = YES; } } diff --git a/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorType.swift b/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorType.swift index 2f02bd705..61788b24b 100644 --- a/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorType.swift +++ b/Riot/Modules/Room/EditHistory/EditHistoryCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol EditHistoryCoordinatorDelegate: class { +protocol EditHistoryCoordinatorDelegate: AnyObject { func editHistoryCoordinatorDidComplete(_ coordinator: EditHistoryCoordinatorType) } diff --git a/Riot/Modules/Room/EditHistory/EditHistoryViewModelType.swift b/Riot/Modules/Room/EditHistory/EditHistoryViewModelType.swift index 4ed9ff707..25d73396d 100644 --- a/Riot/Modules/Room/EditHistory/EditHistoryViewModelType.swift +++ b/Riot/Modules/Room/EditHistory/EditHistoryViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol EditHistoryViewModelViewDelegate: class { +protocol EditHistoryViewModelViewDelegate: AnyObject { func editHistoryViewModel(_ viewModel: EditHistoryViewModelType, didUpdateViewState viewSate: EditHistoryViewState) } -protocol EditHistoryViewModelCoordinatorDelegate: class { +protocol EditHistoryViewModelCoordinatorDelegate: AnyObject { func editHistoryViewModelDidClose(_ viewModel: EditHistoryViewModelType) } diff --git a/Riot/Modules/Room/EmojiPicker/EmojiPickerCoordinatorType.swift b/Riot/Modules/Room/EmojiPicker/EmojiPickerCoordinatorType.swift index e414ea29b..5d99c6118 100644 --- a/Riot/Modules/Room/EmojiPicker/EmojiPickerCoordinatorType.swift +++ b/Riot/Modules/Room/EmojiPicker/EmojiPickerCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol EmojiPickerCoordinatorDelegate: class { +protocol EmojiPickerCoordinatorDelegate: AnyObject { func emojiPickerCoordinator(_ coordinator: EmojiPickerCoordinatorType, didAddEmoji emoji: String, forEventId eventId: String) func emojiPickerCoordinator(_ coordinator: EmojiPickerCoordinatorType, didRemoveEmoji emoji: String, forEventId eventId: String) func emojiPickerCoordinatorDidCancel(_ coordinator: EmojiPickerCoordinatorType) diff --git a/Riot/Modules/Room/EmojiPicker/EmojiPickerViewModelType.swift b/Riot/Modules/Room/EmojiPicker/EmojiPickerViewModelType.swift index 3f15484f1..ba9b44222 100644 --- a/Riot/Modules/Room/EmojiPicker/EmojiPickerViewModelType.swift +++ b/Riot/Modules/Room/EmojiPicker/EmojiPickerViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol EmojiPickerViewModelViewDelegate: class { +protocol EmojiPickerViewModelViewDelegate: AnyObject { func emojiPickerViewModel(_ viewModel: EmojiPickerViewModelType, didUpdateViewState viewSate: EmojiPickerViewState) } -protocol EmojiPickerViewModelCoordinatorDelegate: class { +protocol EmojiPickerViewModelCoordinatorDelegate: AnyObject { func emojiPickerViewModel(_ viewModel: EmojiPickerViewModelType, didAddEmoji emoji: String, forEventId eventId: String) func emojiPickerViewModel(_ viewModel: EmojiPickerViewModelType, didRemoveEmoji emoji: String, forEventId eventId: String) func emojiPickerViewModelDidCancel(_ viewModel: EmojiPickerViewModelType) diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsAvatarView.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsAvatarView.swift new file mode 100644 index 000000000..c9bf9af89 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsAvatarView.swift @@ -0,0 +1,51 @@ +// +// 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 Reusable + +class RoomNotificationSettingsAvatarView: UIView { + + @IBOutlet weak var avatarView: MXKImageView! + @IBOutlet weak var nameLabel: UILabel! + + func configure(viewData: AvatarViewDataProtocol) { + let avatarImage = AvatarGenerator.generateAvatar(forMatrixItem: viewData.matrixItemId, withDisplayName: viewData.displayName) + + if let avatarUrl = viewData.avatarUrl { + avatarView.enableInMemoryCache = true + + avatarView.setImageURI(avatarUrl, + withType: nil, + andImageOrientation: .up, + toFitViewSize: avatarView.frame.size, + with: MXThumbnailingMethodCrop, + previewImage: avatarImage, + mediaManager: viewData.mediaManager) + } else { + avatarView.image = avatarImage + } + nameLabel.text = viewData.displayName + } +} + +extension RoomNotificationSettingsAvatarView: NibLoadable { } +extension RoomNotificationSettingsAvatarView: Themable { + func update(theme: Theme) { + nameLabel?.font = theme.fonts.title3SB + nameLabel?.textColor = theme.textPrimaryColor + } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsAvatarView.xib b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsAvatarView.xib new file mode 100644 index 000000000..b9c21f892 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsAvatarView.xib @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsBridgePresenter.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsBridgePresenter.swift new file mode 100644 index 000000000..0be2f18a1 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsBridgePresenter.swift @@ -0,0 +1,100 @@ +// +// 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 + +@objc protocol RoomNotificationSettingsCoordinatorBridgePresenterDelegate { + func roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(_ coordinatorBridgePresenter: RoomNotificationSettingsCoordinatorBridgePresenter) +} + +/// RoomNotificationSettingsCoordinatorBridgePresenter enables to start RoomNotificationSettingsCoordinator 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. +@objcMembers +final class RoomNotificationSettingsCoordinatorBridgePresenter: NSObject { + + // MARK: - Properties + + // MARK: Private + + private let room: MXRoom + private var coordinator: RoomNotificationSettingsCoordinator? + + // MARK: Public + + weak var delegate: RoomNotificationSettingsCoordinatorBridgePresenterDelegate? + + // MARK: - Setup + + init(room: MXRoom) { + self.room = room + super.init() + } + + // MARK: - Public + + // NOTE: Default value feature is not compatible with Objective-C. + // func present(from viewController: UIViewController, animated: Bool) { + // self.present(from: viewController, animated: animated) + // } + + func present(from viewController: UIViewController, animated: Bool) { + let roomNotificationSettingsCoordinator = RoomNotificationSettingsCoordinator(room: room) + roomNotificationSettingsCoordinator.delegate = self + let presentable = roomNotificationSettingsCoordinator.toPresentable() + let navigationController = RiotNavigationController(rootViewController: presentable) + navigationController.modalPresentationStyle = .formSheet + presentable.presentationController?.delegate = self + viewController.present(navigationController, animated: animated, completion: nil) + roomNotificationSettingsCoordinator.start() + + self.coordinator = roomNotificationSettingsCoordinator + } + + func dismiss(animated: Bool, completion: (() -> Void)?) { + guard let coordinator = self.coordinator else { + return + } + coordinator.toPresentable().dismiss(animated: animated) { + self.coordinator = nil + + if let completion = completion { + completion() + } + } + } +} + +// MARK: - RoomNotificationSettingsCoordinatorDelegate +extension RoomNotificationSettingsCoordinatorBridgePresenter: RoomNotificationSettingsCoordinatorDelegate { + func roomNotificationSettingsCoordinatorDidCancel(_ coordinator: RoomNotificationSettingsCoordinatorType) { + self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + } + + func roomNotificationSettingsCoordinatorDidComplete(_ coordinator: RoomNotificationSettingsCoordinatorType) { + self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + } +} + +// MARK: - UIAdaptivePresentationControllerDelegate + +extension RoomNotificationSettingsCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate { + + func roomNotificationSettingsCoordinatorDidComplete(_ presentationController: UIPresentationController) { + self.delegate?.roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete(self) + } + +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCellViewData.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCellViewData.swift new file mode 100644 index 000000000..2b50835d1 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCellViewData.swift @@ -0,0 +1,22 @@ +// +// 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 + +struct RoomNotificationSettingsCellViewData { + let notificicationState: RoomNotificationState + let selected: Bool +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCoordinator.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCoordinator.swift new file mode 100644 index 000000000..2d8e48cee --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCoordinator.swift @@ -0,0 +1,75 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 + +final class RoomNotificationSettingsCoordinator: RoomNotificationSettingsCoordinatorType { + + // MARK: - Properties + + // MARK: Private + private var roomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType + private let roomNotificationSettingsViewController: RoomNotificationSettingsViewController + + // MARK: Public + + // Must be used only internally + var childCoordinators: [Coordinator] = [] + + weak var delegate: RoomNotificationSettingsCoordinatorDelegate? + + // MARK: - Setup + + init(room: MXRoom, showAvatar: Bool = true) { + let repository = RoomNotificationSettingsService(room: room) + + let avatarData = showAvatar ? RoomAvatarViewData( + roomId: room.roomId, + displayName: room.summary.displayname, + avatarUrl: room.summary.avatar, + mediaManager: room.mxSession.mediaManager + ) : nil + let roomNotificationSettingsViewModel = RoomNotificationSettingsViewModel(roomNotificationService: repository, roomEncrypted: room.summary.isEncrypted, avatarViewData: avatarData) + let roomNotificationSettingsViewController = RoomNotificationSettingsViewController.instantiate(with: roomNotificationSettingsViewModel) + self.roomNotificationSettingsViewModel = roomNotificationSettingsViewModel + self.roomNotificationSettingsViewController = roomNotificationSettingsViewController + } + + // MARK: - Public methods + + func start() { + self.roomNotificationSettingsViewModel.coordinatorDelegate = self + } + + func toPresentable() -> UIViewController { + return self.roomNotificationSettingsViewController + } +} + +// MARK: - RoomNotificationSettingsViewModelCoordinatorDelegate +extension RoomNotificationSettingsCoordinator: RoomNotificationSettingsViewModelCoordinatorDelegate { + + func roomNotificationSettingsViewModelDidComplete(_ viewModel: RoomNotificationSettingsViewModelType) { + self.delegate?.roomNotificationSettingsCoordinatorDidComplete(self) + } + + func roomNotificationSettingsViewModelDidCancel(_ viewModel: RoomNotificationSettingsViewModelType) { + self.delegate?.roomNotificationSettingsCoordinatorDidCancel(self) + } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCoordinatorType.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCoordinatorType.swift new file mode 100644 index 000000000..ac0c6288b --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsCoordinatorType.swift @@ -0,0 +1,29 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 RoomNotificationSettingsCoordinatorDelegate: AnyObject { + func roomNotificationSettingsCoordinatorDidComplete(_ coordinator: RoomNotificationSettingsCoordinatorType) + func roomNotificationSettingsCoordinatorDidCancel(_ coordinator: RoomNotificationSettingsCoordinatorType) +} + +/// `RoomNotificationSettingsCoordinatorType` is a protocol describing a Coordinator that handles changes to the room navigation settings navigation flow. +protocol RoomNotificationSettingsCoordinatorType: Coordinator, Presentable { + var delegate: RoomNotificationSettingsCoordinatorDelegate? { get } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsFooter.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsFooter.swift new file mode 100644 index 000000000..db5285192 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsFooter.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 UIKit +import Reusable + +class RoomNotificationSettingsFooter: UITableViewHeaderFooterView { + + struct State { + let showEncryptedNotice: Bool + let showAccountLink: Bool + } + + @IBOutlet weak var label: UILabel! + + func update(footerState: State) { + + // Don't include link until global settings in place +// let paragraphStyle = NSMutableParagraphStyle() +// paragraphStyle.lineHeightMultiple = 1.16 +// let paragraphAttributes: [NSAttributedString.Key: Any] = [ +// NSAttributedString.Key.kern: -0.08, +// NSAttributedString.Key.paragraphStyle: paragraphStyle, +// NSAttributedString.Key.font: UIFont.systemFont(ofSize: 13.0) +// ] +// let linkStr = VectorL10n.roomNotifsSettingsAccountSettings +// let formatStr = VectorL10n.roomNotifsSettingsManageNotifications(linkStr) +// +// let formattedStr = String(format: formatStr, arguments: [linkStr]) +// let footer0 = NSMutableAttributedString(string: formattedStr, attributes: paragraphAttributes) +// let linkRange = (footer0.string as NSString).range(of: linkStr) +// footer0.addAttribute(NSAttributedString.Key.link, value: Constants.linkToAccountSettings, range: linkRange) + + label.text = footerState.showEncryptedNotice ? VectorL10n.roomNotifsSettingsEncryptedRoomNotice : nil + + } +} + + +extension RoomNotificationSettingsFooter: NibReusable {} +extension RoomNotificationSettingsFooter: Themable { + + func update(theme: Theme) { + contentView.backgroundColor = theme.headerBackgroundColor + label.textColor = theme.headerTextSecondaryColor + } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsFooter.xib b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsFooter.xib new file mode 100644 index 000000000..48895dca9 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsFooter.xib @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsSerivceType.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsSerivceType.swift new file mode 100644 index 000000000..22961ad03 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsSerivceType.swift @@ -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 Foundation + +typealias UpdateRoomNotificationStateCompletion = () -> Void +typealias RoomNotificationStateCallback = (RoomNotificationState) -> Void + +protocol RoomNotificationSettingsServiceType { + + func observeNotificationState(listener: @escaping RoomNotificationStateCallback) + func update(state: RoomNotificationState, completion: @escaping UpdateRoomNotificationStateCompletion) + var notificationState: RoomNotificationState { get } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewAction.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewAction.swift new file mode 100644 index 000000000..5d42f64fa --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewAction.swift @@ -0,0 +1,26 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 +/// RoomNotificationSettingsViewController view actions exposed to view model +enum RoomNotificationSettingsViewAction { + case load + case selectNotificationState(RoomNotificationState) + case save + case cancel +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewController.storyboard b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewController.storyboard new file mode 100644 index 000000000..8d49ce878 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewController.storyboard @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewController.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewController.swift new file mode 100644 index 000000000..3e2adf89e --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewController.swift @@ -0,0 +1,233 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 + +final class RoomNotificationSettingsViewController: UIViewController { + + // MARK: - Properties + + private enum Constants { + static let linkToAccountSettings = "linkToAccountSettings" + } + + // MARK: Outlets + + @IBOutlet private weak var mainTableView: UITableView! + + // MARK: Private + + private var viewModel: RoomNotificationSettingsViewModelType! + private var theme: Theme! + private var errorPresenter: MXKErrorPresentation! + private var activityPresenter: ActivityIndicatorPresenter! + private lazy var avatarView: RoomNotificationSettingsAvatarView = { + RoomNotificationSettingsAvatarView.loadFromNib() + }() + + private struct Row { + var cellViewData: RoomNotificationSettingsCellViewData + var action: (() -> Void)? + } + + private struct Section { + var title: String + var rows: [Row] + var footerState: RoomNotificationSettingsFooter.State + } + + private var sections: [Section] = [] { + didSet { + mainTableView.reloadData() + } + } + + private var viewState: RoomNotificationSettingsViewStateType! + + // MARK: - Setup + + class func instantiate(with viewModel: RoomNotificationSettingsViewModelType) -> RoomNotificationSettingsViewController { + let viewController = StoryboardScene.RoomNotificationSettingsViewController.initialScene.instantiate() + viewController.viewModel = viewModel + viewController.theme = ThemeService.shared().theme + return viewController + } + + // MARK: - Life cycle + + override func viewDidLoad() { + super.viewDidLoad() + + // Do any additional setup after loading the view. + + setupViews() + activityPresenter = ActivityIndicatorPresenter() + errorPresenter = MXKErrorAlertPresentation() + + registerThemeServiceDidChangeThemeNotification() + update(theme: theme) + + viewModel.viewDelegate = self + viewModel.process(viewAction: .load) + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + return theme.statusBarStyle + } + + // MARK: - Private + + private func update(theme: Theme) { + self.theme = theme + + view.backgroundColor = theme.headerBackgroundColor + mainTableView.backgroundColor = theme.headerBackgroundColor + + if let navigationBar = navigationController?.navigationBar { + theme.applyStyle(onNavigationBar: navigationBar) + } + mainTableView.reloadData() + } + + private func registerThemeServiceDidChangeThemeNotification() { + NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil) + } + + @objc private func themeDidChange() { + update(theme: ThemeService.shared().theme) + } + + private func setupViews() { + + self.title = VectorL10n.roomDetailsNotifs + let doneBarButtonItem = MXKBarButtonItem(title: VectorL10n.roomNotifsSettingsDoneAction, style: .plain) { [weak self] in + self?.viewModel.process(viewAction: .save) + } + + let cancelBarButtonItem = MXKBarButtonItem(title: VectorL10n.roomNotifsSettingsCancelAction, style: .plain) { [weak self] in + self?.viewModel.process(viewAction: .cancel) + } + + if navigationController?.navigationBar.backItem == nil { + navigationItem.leftBarButtonItem = cancelBarButtonItem + } + navigationItem.rightBarButtonItem = doneBarButtonItem + mainTableView.register(cellType: RoomNotificationSettingsCell.self) + mainTableView.register(headerFooterViewType: RoomNotificationSettingsFooter.self) + mainTableView.register(headerFooterViewType: TitleHeaderView.self) + mainTableView.sectionFooterHeight = UITableView.automaticDimension + mainTableView.sectionHeaderHeight = UITableView.automaticDimension + mainTableView.estimatedSectionFooterHeight = 50 + mainTableView.estimatedSectionHeaderHeight = 30 + } + + private func render(viewState: RoomNotificationSettingsViewStateType) { + + if viewState.saving { + activityPresenter.presentActivityIndicator(on: view, animated: true) + } else { + activityPresenter.removeCurrentActivityIndicator(animated: true) + } + self.viewState = viewState + if let avatarData = viewState.avatarData { + mainTableView.tableHeaderView = avatarView + avatarView.configure(viewData: avatarData) + avatarView.update(theme: theme) + } + updateSections() + } + + private func updateSections() { + let rows = viewState.notificationOptions.map({ (setting) -> Row in + let cellViewData = RoomNotificationSettingsCellViewData(notificicationState: setting, selected: viewState.notificationState == setting) + return Row(cellViewData: cellViewData, + action: { + self.viewModel.process(viewAction: .selectNotificationState(setting)) + }) + }) + let footerState = RoomNotificationSettingsFooter.State(showEncryptedNotice: viewState.roomEncrypted, showAccountLink: false) + let section0 = Section(title: VectorL10n.roomNotifsSettingsNotifyMeFor, rows: rows, footerState: footerState) + sections = [ + section0 + ] + } +} + +// MARK: - UITableViewDataSource +extension RoomNotificationSettingsViewController: UITableViewDataSource { + + func numberOfSections(in tableView: UITableView) -> Int { + return sections.count + } + + func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + return sections[section].rows.count + } + + func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let row = sections[indexPath.section].rows[indexPath.row] + let cell: RoomNotificationSettingsCell = tableView.dequeueReusableCell(for: indexPath) + cell.update(state: row.cellViewData) + cell.update(theme: theme) + return cell + } + + func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { + return UITableView.automaticDimension + } + + func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return UITableView.automaticDimension + } + +} + +// MARK: - UITableViewDelegate +extension RoomNotificationSettingsViewController: UITableViewDelegate { + + func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { + guard let headerView: TitleHeaderView = tableView.dequeueReusableHeaderFooterView() else { return nil } + headerView.update(title: sections[section].title) + headerView.update(theme: theme) + return headerView + } + + func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + guard let footerView: RoomNotificationSettingsFooter = tableView.dequeueReusableHeaderFooterView() else { return nil } + let footerState = sections[section].footerState + footerView.update(footerState: footerState) + footerView.update(theme: theme) + return footerView + } + + func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + tableView.deselectRow(at: indexPath, animated: true) + + let row = sections[indexPath.section].rows[indexPath.row] + row.action?() + } + +} + +// MARK: - RoomNotificationSettingsViewModelViewDelegate +extension RoomNotificationSettingsViewController: RoomNotificationSettingsViewModelViewDelegate { + + func roomNotificationSettingsViewModel(_ viewModel: RoomNotificationSettingsViewModelType, didUpdateViewState viewSate: RoomNotificationSettingsViewStateType) { + render(viewState: viewSate) + } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewModel.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewModel.swift new file mode 100644 index 000000000..e9f5729df --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewModel.swift @@ -0,0 +1,89 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 + +final class RoomNotificationSettingsViewModel: RoomNotificationSettingsViewModelType { + + // MARK: - Properties + + // MARK: Private + + private let roomNotificationService: RoomNotificationSettingsServiceType + private var state: RoomNotificationSettingsViewState { + willSet { + update(viewState: newValue) + } + } + // MARK: Public + + weak var viewDelegate: RoomNotificationSettingsViewModelViewDelegate? + + weak var coordinatorDelegate: RoomNotificationSettingsViewModelCoordinatorDelegate? + + // MARK: - Setup + + init(roomNotificationService: RoomNotificationSettingsServiceType, roomEncrypted: Bool, avatarViewData: AvatarViewDataProtocol?) { + self.roomNotificationService = roomNotificationService + + let notificationState = Self.mapNotificationStateOnRead(encrypted: roomEncrypted, state: roomNotificationService.notificationState) + self.state = RoomNotificationSettingsViewState(roomEncrypted: roomEncrypted, saving: false, notificationState: notificationState, avatarData: avatarViewData) + self.roomNotificationService.observeNotificationState { [weak self] state in + guard let self = self else { return } + + self.state.notificationState = Self.mapNotificationStateOnRead(encrypted: roomEncrypted, state: state) + } + } + + // MARK: - Public + + func process(viewAction: RoomNotificationSettingsViewAction) { + switch viewAction { + case .load: + update(viewState: self.state) + case .selectNotificationState(let state): + self.state.notificationState = state + case .save: + self.state.saving = true + roomNotificationService.update(state: state.notificationState) { [weak self] in + guard let self = self else { return } + self.state.saving = false + self.coordinatorDelegate?.roomNotificationSettingsViewModelDidComplete(self) + } + case .cancel: + coordinatorDelegate?.roomNotificationSettingsViewModelDidCancel(self) + } + } + + // MARK: - Private + + private static func mapNotificationStateOnRead(encrypted: Bool, state: RoomNotificationState) -> RoomNotificationState { + if encrypted, case .mentionsAndKeywordsOnly = state { + // Notifications not supported on encrypted rooms, map mentionsOnly to mute on read + return .mute + } else { + return state + } + } + + private func update(viewState: RoomNotificationSettingsViewStateType) { + self.viewDelegate?.roomNotificationSettingsViewModel(self, didUpdateViewState: viewState) + } + + +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewModelType.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewModelType.swift new file mode 100644 index 000000000..e2fe135d4 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewModelType.swift @@ -0,0 +1,37 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 RoomNotificationSettingsViewModelViewDelegate: AnyObject { + func roomNotificationSettingsViewModel(_ viewModel: RoomNotificationSettingsViewModelType, didUpdateViewState viewState: RoomNotificationSettingsViewStateType) +} + +protocol RoomNotificationSettingsViewModelCoordinatorDelegate: AnyObject { + func roomNotificationSettingsViewModelDidComplete(_ viewModel: RoomNotificationSettingsViewModelType) + func roomNotificationSettingsViewModelDidCancel(_ viewModel: RoomNotificationSettingsViewModelType) +} + +/// Protocol describing the view model used by `RoomNotificationSettingsViewController` +protocol RoomNotificationSettingsViewModelType { + + var viewDelegate: RoomNotificationSettingsViewModelViewDelegate? { get set } + var coordinatorDelegate: RoomNotificationSettingsViewModelCoordinatorDelegate? { get set } + + func process(viewAction: RoomNotificationSettingsViewAction) +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewStateType.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewStateType.swift new file mode 100644 index 000000000..56de53b13 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationSettingsViewStateType.swift @@ -0,0 +1,42 @@ +// File created from ScreenTemplate +// $ createScreen.sh Room/NotificationSettings RoomNotificationSettings +/* + 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 + +/// RoomNotificationSettingsViewController view state +struct RoomNotificationSettingsViewState: RoomNotificationSettingsViewStateType { + let roomEncrypted: Bool + var saving: Bool + var notificationState: RoomNotificationState + var notificationOptions: [RoomNotificationState] { + if roomEncrypted { + return [.all, .mute] + } else { + return RoomNotificationState.allCases + } + } + let avatarData: AvatarViewDataProtocol? +} + +protocol RoomNotificationSettingsViewStateType { + var saving: Bool { get } + var roomEncrypted: Bool { get } + var notificationOptions: [RoomNotificationState] { get } + var notificationState: RoomNotificationState { get } + var avatarData: AvatarViewDataProtocol? { get } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationState.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationState.swift new file mode 100644 index 000000000..054993117 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationState.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 Foundation + +enum RoomNotificationState: CaseIterable { + case all + case mentionsAndKeywordsOnly + case mute +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsCell.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsCell.swift new file mode 100644 index 000000000..343c7bba4 --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsCell.swift @@ -0,0 +1,56 @@ +// +// 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 RoomNotificationSettingsCell: UITableViewCell { + + func update(state: RoomNotificationSettingsCellViewData) { + textLabel?.text = state.notificicationState.title + if state.selected { + accessoryView = UIImageView(image: Asset.Images.checkmark.image) + } else { + accessoryView = nil + } + } +} + +extension RoomNotificationSettingsCell: Reusable {} + +extension RoomNotificationSettingsCell: Themable { + func update(theme: Theme) { + textLabel?.font = theme.fonts.body + textLabel?.textColor = theme.textPrimaryColor + backgroundColor = theme.backgroundColor + contentView.backgroundColor = .clear + tintColor = theme.tintColor + selectedBackgroundView = UIView() + selectedBackgroundView?.backgroundColor = theme.selectedBackgroundColor + } +} + +fileprivate extension RoomNotificationState { + var title: String { + switch self { + case .all: + return VectorL10n.roomNotifsSettingsAllMessages + case .mentionsAndKeywordsOnly: + return VectorL10n.roomNotifsSettingsMentionsAndKeywords + case .mute: + return VectorL10n.roomNotifsSettingsNone + } + } +} diff --git a/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift b/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift new file mode 100644 index 000000000..1bd0e4b6b --- /dev/null +++ b/Riot/Modules/Room/NotificationSettings/RoomNotificationsSettingsService.swift @@ -0,0 +1,325 @@ +// +// 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 + +final class RoomNotificationSettingsService: RoomNotificationSettingsServiceType { + + typealias Completion = () -> Void + + // MARK: - Properties + + // MARK: Private + + private let room: MXRoom + + private var notificationCenterDidUpdateObserver: NSObjectProtocol? + private var notificationCenterDidFailObserver: NSObjectProtocol? + + private var observers: [ObjectIdentifier] = [] + + // MARK: Public + + var notificationState: RoomNotificationState { + room.notificationState + } + + // MARK: - Setup + + init(room: MXRoom) { + self.room = room + } + + deinit { + observers.forEach(NotificationCenter.default.removeObserver) + } + + // MARK: - Public + + func observeNotificationState(listener: @escaping RoomNotificationStateCallback) { + + let observer = NotificationCenter.default.addObserver( + forName: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules), + object: nil, + queue: OperationQueue.main) { [weak self] _ in + guard let self = self else { return } + listener(self.room.notificationState) + } + observers += [ObjectIdentifier(observer)] + } + + func update(state: RoomNotificationState, completion: @escaping Completion) { + switch state { + case .all: + allMessages(completion: completion) + case .mentionsAndKeywordsOnly: + mentionsOnly(completion: completion) + case .mute: + mute(completion: completion) + } + } + + // MARK: - Private + + private func mute(completion: @escaping Completion) { + guard !room.isMuted else { + completion() + return + } + + if let rule = room.roomPushRule { + removePushRule(rule: rule) { + self.mute(completion: completion) + } + return + } + + guard let rule = room.overridePushRule else { + self.addPushRuleToMute(completion: completion) + return + } + + guard notificationCenterDidUpdateObserver == nil else { + MXLog.debug("[RoomNotificationSettingsService] Request in progress: ignore push rule update") + completion() + return + } + + // if the user defined one, use it + if rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) { + enablePushRule(rule: rule, completion: completion) + } else { + removePushRule(rule: rule) { + self.addPushRuleToMute(completion: completion) + } + } + } + + private func mentionsOnly(completion: @escaping Completion) { + guard !room.isMentionsOnly else { + completion() + return + } + + if let rule = room.overridePushRule, room.isMuted { + removePushRule(rule: rule) { + self.mentionsOnly(completion: completion) + } + return + } + + guard let rule = room.roomPushRule else { + addPushRuleToMentionOnly(completion: completion) + return + } + + guard notificationCenterDidUpdateObserver == nil else { + MXLog.debug("[MXRoom+Riot] Request in progress: ignore push rule update") + completion() + return + } + + // if the user defined one, use it + if rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) { + enablePushRule(rule: rule, completion: completion) + } else { + removePushRule(rule: rule) { + self.addPushRuleToMentionOnly(completion: completion) + } + } + + } + + private func allMessages(completion: @escaping Completion) { + if !room.isMentionsOnly && !room.isMuted { + completion() + return + } + + if let rule = room.overridePushRule, room.isMuted { + removePushRule(rule: rule) { + self.allMessages(completion: completion) + } + return + } + + if let rule = room.roomPushRule, room.isMentionsOnly { + removePushRule(rule: rule, completion: completion) + } + } + + private func addPushRuleToMentionOnly(completion: @escaping Completion) { + handleUpdateCallback(completion) { [weak self] in + guard let self = self else { return true } + return self.room.roomPushRule != nil + } + handleFailureCallback(completion) + + room.mxSession.notificationCenter.addRoomRule( + room.roomId, + notify: false, + sound: false, + highlight: false) + } + + private func addPushRuleToMute(completion: @escaping Completion) { + guard let roomId = room.roomId else { + return + } + handleUpdateCallback(completion) { [weak self] in + guard let self = self else { return true } + return self.room.overridePushRule != nil + } + handleFailureCallback(completion) + + room.mxSession.notificationCenter.addOverrideRule( + withId: roomId, + conditions: [["kind": "event_match", "key": "room_id", "pattern": roomId]], + notify: false, + sound: false, + highlight: false + ) + } + + private func removePushRule(rule: MXPushRule, completion: @escaping Completion) { + handleUpdateCallback(completion) { [weak self] in + guard let self = self else { return true } + return self.room.mxSession.notificationCenter.rule(byId: rule.ruleId) == nil + } + handleFailureCallback(completion) + + room.mxSession.notificationCenter.removeRule(rule) + } + + private func enablePushRule(rule: MXPushRule, completion: @escaping Completion) { + handleUpdateCallback(completion) { + // No way to check whether this notification concerns the push rule. Consider the change is applied. + return true + } + handleFailureCallback(completion) + + room.mxSession.notificationCenter.enableRule(rule, isEnabled: true) + } + + private func handleUpdateCallback(_ completion: @escaping Completion, releaseCheck: @escaping () -> Bool) { + notificationCenterDidUpdateObserver = NotificationCenter.default.addObserver( + forName: NSNotification.Name(rawValue: kMXNotificationCenterDidUpdateRules), + object: nil, + queue: OperationQueue.main) { [weak self] _ in + guard let self = self else { return } + if releaseCheck() { + self.removeObservers() + completion() + } + } + } + + private func handleFailureCallback(_ completion: @escaping Completion) { + notificationCenterDidFailObserver = NotificationCenter.default.addObserver( + forName: NSNotification.Name(rawValue: kMXNotificationCenterDidFailRulesUpdate), + object: nil, + queue: OperationQueue.main) { [weak self] _ in + guard let self = self else { return } + self.removeObservers() + completion() + } + } + + func removeObservers() { + if let observer = self.notificationCenterDidUpdateObserver { + NotificationCenter.default.removeObserver(observer) + self.notificationCenterDidUpdateObserver = nil + } + + if let observer = self.notificationCenterDidFailObserver { + NotificationCenter.default.removeObserver(observer) + self.notificationCenterDidFailObserver = nil + } + } +} + +// We could move these to their own file and make available in global namespace or move to sdk but they are only used here at the moment +fileprivate extension MXRoom { + + typealias Completion = () -> Void + func getRoomRule(from rules: [Any]) -> MXPushRule? { + guard let pushRules = rules as? [MXPushRule] else { + return nil + } + + return pushRules.first(where: { self.roomId == $0.ruleId }) + } + + var overridePushRule: MXPushRule? { + getRoomRule(from: mxSession.notificationCenter.rules.global.override) + } + + var roomPushRule: MXPushRule? { + getRoomRule(from: mxSession.notificationCenter.rules.global.room) + } + + var notificationState: RoomNotificationState { + + if isMuted { + return .mute + } + if isMentionsOnly { + return .mentionsAndKeywordsOnly + } + return .all + } + + var isMuted: Bool { + // Check whether an override rule has been defined with the roomm id as rule id. + // This kind of rule is created to mute the room + guard let rule = self.overridePushRule, + rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify), + rule.conditionIsEnabled(kind: .eventMatch, for: roomId) else { + return false + } + return rule.enabled + } + + var isMentionsOnly: Bool { + // Check push rules at room level + guard let rule = roomPushRule else { return false } + return rule.enabled && rule.actionsContains(actionType: MXPushRuleActionTypeDontNotify) + } + +} + +fileprivate extension MXPushRule { + func actionsContains(actionType: MXPushRuleActionType) -> Bool { + guard let actions = actions as? [MXPushRuleAction] else { + return false + } + return actions.contains(where: { $0.actionType == actionType }) + } + + func conditionIsEnabled(kind: MXPushRuleConditionType, for roomId: String) -> Bool { + guard let conditions = conditions as? [MXPushRuleCondition] else { + return false + } + let ruleContainsCondition = conditions.contains { condition in + guard case kind = MXPushRuleConditionType(identifier: condition.kind), + let key = condition.parameters["key"] as? String, + let pattern = condition.parameters["pattern"] as? String + else { return false } + return key == "room_id" && pattern == roomId + } + return ruleContainsCondition && enabled + } +} diff --git a/Riot/Modules/Room/ReactionHistory/ReactionHistoryCoordinatorType.swift b/Riot/Modules/Room/ReactionHistory/ReactionHistoryCoordinatorType.swift index 420dc1fe2..95a5bfbe8 100644 --- a/Riot/Modules/Room/ReactionHistory/ReactionHistoryCoordinatorType.swift +++ b/Riot/Modules/Room/ReactionHistory/ReactionHistoryCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol ReactionHistoryCoordinatorDelegate: class { +protocol ReactionHistoryCoordinatorDelegate: AnyObject { func reactionHistoryCoordinatorDidClose(_ coordinator: ReactionHistoryCoordinatorType) } diff --git a/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModelType.swift b/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModelType.swift index 92c300d46..735ee7b16 100644 --- a/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModelType.swift +++ b/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol ReactionHistoryViewModelViewDelegate: class { +protocol ReactionHistoryViewModelViewDelegate: AnyObject { func reactionHistoryViewModel(_ viewModel: ReactionHistoryViewModelType, didUpdateViewState viewSate: ReactionHistoryViewState) } -protocol ReactionHistoryViewModelCoordinatorDelegate: class { +protocol ReactionHistoryViewModelCoordinatorDelegate: AnyObject { func reactionHistoryViewModelDidClose(_ viewModel: ReactionHistoryViewModelType) } diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift index f1efb7577..495d3468b 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinator.swift @@ -137,6 +137,12 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType { return coordinator } + private func createRoomNotificationSettingsCoordinator() -> RoomNotificationSettingsCoordinator { + let coordinator = RoomNotificationSettingsCoordinator(room: room, showAvatar: false) + coordinator.delegate = self + return coordinator + } + private func showRoomDetails(with target: RoomInfoListTarget, animated: Bool) { switch target { case .integrations: @@ -152,8 +158,16 @@ final class RoomInfoCoordinator: NSObject, RoomInfoCoordinatorType { self.navigationRouter.push(search, animated: animated, popCompletion: nil) } }) + case .notifications: + let coordinator = createRoomNotificationSettingsCoordinator() + coordinator.start() + self.add(childCoordinator: coordinator) + self.navigationRouter.push(coordinator, animated: true, popCompletion: nil) default: - segmentedViewController.selectedIndex = target.tabIndex + guard let tabIndex = target.tabIndex else { + fatalError("No settings tab index for this target.") + } + segmentedViewController.selectedIndex = tabIndex if case .settings(let roomSettingsField) = target { roomSettingsViewController?.selectedRoomSettingsField = roomSettingsField @@ -184,3 +198,14 @@ extension RoomInfoCoordinator: RoomParticipantsViewControllerDelegate { } } + +extension RoomInfoCoordinator: RoomNotificationSettingsCoordinatorDelegate { + func roomNotificationSettingsCoordinatorDidComplete(_ coordinator: RoomNotificationSettingsCoordinatorType) { + self.navigationRouter.popModule(animated: true) + } + + func roomNotificationSettingsCoordinatorDidCancel(_ coordinator: RoomNotificationSettingsCoordinatorType) { + + } + +} diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorType.swift b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorType.swift index c98c7a751..ff2e04626 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorType.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol RoomInfoCoordinatorDelegate: class { +protocol RoomInfoCoordinatorDelegate: AnyObject { func roomInfoCoordinatorDidComplete(_ coordinator: RoomInfoCoordinatorType) } diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListCoordinatorType.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListCoordinatorType.swift index db953c40b..7979d1aa8 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListCoordinatorType.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol RoomInfoListCoordinatorDelegate: class { +protocol RoomInfoListCoordinatorDelegate: AnyObject { func roomInfoListCoordinator(_ coordinator: RoomInfoListCoordinatorType, wantsToNavigateTo target: RoomInfoListTarget) func roomInfoListCoordinatorDidCancel(_ coordinator: RoomInfoListCoordinatorType) } diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift index 945d2844a..c6e0c8887 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewAction.swift @@ -24,25 +24,21 @@ enum RoomInfoListTarget: Equatable { case uploads case integrations case search - - var tabIndex: UInt { - let tabIndex: UInt - + case notifications + + var tabIndex: UInt? { switch self { case .members: - tabIndex = 0 + return 0 case .uploads: - tabIndex = 1 + return 1 case .settings: - tabIndex = 2 - case .integrations: - tabIndex = 3 - case .search: - tabIndex = 4 + return 2 + default: + return nil } - - return tabIndex } + } /// RoomInfoListViewController view actions exposed to view model diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift index bfc3396bf..ddc14d605 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift @@ -150,6 +150,9 @@ final class RoomInfoListViewController: UIViewController { let rowSettings = Row(type: .default, icon: Asset.Images.settingsIcon.image, text: VectorL10n.roomDetailsSettings, accessoryType: .disclosureIndicator) { self.viewModel.process(viewAction: .navigate(target: .settings())) } + let roomNotifications = Row(type: .default, icon: Asset.Images.notifications.image, text: VectorL10n.roomDetailsNotifs, accessoryType: .disclosureIndicator) { + self.viewModel.process(viewAction: .navigate(target: .notifications)) + } let text = viewData.numberOfMembers == 1 ? VectorL10n.roomInfoListOneMember : VectorL10n.roomInfoListSeveralMembers(String(viewData.numberOfMembers)) let rowMembers = Row(type: .default, icon: Asset.Images.userIcon.image, text: text, accessoryType: .disclosureIndicator) { self.viewModel.process(viewAction: .navigate(target: .members)) @@ -165,8 +168,11 @@ final class RoomInfoListViewController: UIViewController { } var rows = [rowSettings] - if (RiotSettings.shared.roomInfoScreenShowIntegrations) - { + + if BuildSettings.roomSettingsScreenShowNotificationsV2 { + rows.append(roomNotifications) + } + if RiotSettings.shared.roomInfoScreenShowIntegrations { rows.append(rowIntegrations) } rows.append(rowMembers) diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModelType.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModelType.swift index 439624dea..2610d89a2 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModelType.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol RoomInfoListViewModelViewDelegate: class { +protocol RoomInfoListViewModelViewDelegate: AnyObject { func roomInfoListViewModel(_ viewModel: RoomInfoListViewModelType, didUpdateViewState viewSate: RoomInfoListViewState) } -protocol RoomInfoListViewModelCoordinatorDelegate: class { +protocol RoomInfoListViewModelCoordinatorDelegate: AnyObject { func roomInfoListViewModelDidCancel(_ viewModel: RoomInfoListViewModelType) func roomInfoListViewModel(_ viewModel: RoomInfoListViewModelType, wantsToNavigateTo target: RoomInfoListTarget) } diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index fb4b7db8f..fbd8a25f0 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -6056,7 +6056,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView]; if (roomInputToolbarView) { - [roomInputToolbarView sendSelectedVideo:url isPhotoLibraryAsset:NO]; + AVURLAsset *selectedVideo = [AVURLAsset assetWithURL:url]; + [roomInputToolbarView sendSelectedVideoAsset:selectedVideo isPhotoLibraryAsset:NO]; } } @@ -6080,7 +6081,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } } -- (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePresenter *)coordinatorBridgePresenter didSelectVideoAt:(NSURL *)url +- (void)mediaPickerCoordinatorBridgePresenter:(MediaPickerCoordinatorBridgePresenter *)coordinatorBridgePresenter didSelectVideo:(AVAsset *)videoAsset { [coordinatorBridgePresenter dismissWithAnimated:YES completion:nil]; self.mediaPickerPresenter = nil; @@ -6088,7 +6089,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView]; if (roomInputToolbarView) { - [roomInputToolbarView sendSelectedVideo:url isPhotoLibraryAsset:YES]; + [roomInputToolbarView sendSelectedVideoAsset:videoAsset isPhotoLibraryAsset:YES]; } } diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index 634468fe8..08d18f655 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -528,7 +528,10 @@ NSString *const kRoomSettingsAdvancedE2eEnabledCellViewIdentifier = @"kRoomSetti { [sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_DIRECT_CHAT]; } - [sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_MUTE_NOTIFICATIONS]; + if (!BuildSettings.roomSettingsScreenShowNotificationsV2) + { + [sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_MUTE_NOTIFICATIONS]; + } [sectionMain addRowWithTag:ROOM_SETTINGS_MAIN_SECTION_ROW_LEAVE]; [tmpSections addObject:sectionMain]; diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h index a97402465..31d5ccaa9 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h @@ -31,7 +31,7 @@ extern NSString *const kRoomEncryptedDataBubbleCellTapOnEncryptionIcon; /** Return the icon displayed in front of an event in an encrypted room if needed. - @param event the bubble component. + @param bubbleComponent the bubble component. */ + (UIImage*)encryptionIconForBubbleComponent:(MXKRoomBubbleComponent *)bubbleComponent; diff --git a/Riot/Modules/Room/Views/RemoveJitsiWidget/RemoveJitsiWidgetViewDelegate.swift b/Riot/Modules/Room/Views/RemoveJitsiWidget/RemoveJitsiWidgetViewDelegate.swift index f48af79a1..6e97db18c 100644 --- a/Riot/Modules/Room/Views/RemoveJitsiWidget/RemoveJitsiWidgetViewDelegate.swift +++ b/Riot/Modules/Room/Views/RemoveJitsiWidget/RemoveJitsiWidgetViewDelegate.swift @@ -17,7 +17,7 @@ import Foundation @objc -protocol RemoveJitsiWidgetViewDelegate: class { +protocol RemoveJitsiWidgetViewDelegate: AnyObject { /// Tells the delegate that the user complete sliding on the view /// - Parameter view: The view instance diff --git a/Riot/Modules/Rooms/RoomsDirectoryCoordinatorType.swift b/Riot/Modules/Rooms/RoomsDirectoryCoordinatorType.swift index a33788a44..40e38c6d4 100644 --- a/Riot/Modules/Rooms/RoomsDirectoryCoordinatorType.swift +++ b/Riot/Modules/Rooms/RoomsDirectoryCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol RoomsDirectoryCoordinatorDelegate: class { +protocol RoomsDirectoryCoordinatorDelegate: AnyObject { func roomsDirectoryCoordinator(_ coordinator: RoomsDirectoryCoordinatorType, didSelectRoom room: MXPublicRoom) func roomsDirectoryCoordinatorDidTapCreateNewRoom(_ coordinator: RoomsDirectoryCoordinatorType) func roomsDirectoryCoordinatorDidComplete(_ coordinator: RoomsDirectoryCoordinatorType) diff --git a/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift b/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift index e072ff350..d6b67472b 100644 --- a/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift +++ b/Riot/Modules/Rooms/ShowDirectory/Cells/Room/DirectoryRoomTableViewCell.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -protocol DirectoryRoomTableViewCellDelegate: class { +protocol DirectoryRoomTableViewCellDelegate: AnyObject { func directoryRoomTableViewCellDidTapJoin(_ cell: DirectoryRoomTableViewCell) } diff --git a/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryCoordinatorType.swift b/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryCoordinatorType.swift index 2290edf48..b46b3ca4f 100644 --- a/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryCoordinatorType.swift +++ b/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol ShowDirectoryCoordinatorDelegate: class { +protocol ShowDirectoryCoordinatorDelegate: AnyObject { func showDirectoryCoordinator(_ coordinator: ShowDirectoryCoordinatorType, didSelectRoom room: MXPublicRoom) func showDirectoryCoordinatorDidTapCreateNewRoom(_ coordinator: ShowDirectoryCoordinatorType) func showDirectoryCoordinatorDidCancel(_ coordinator: ShowDirectoryCoordinatorType) diff --git a/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryViewModelType.swift b/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryViewModelType.swift index 643cf4029..4c4291f99 100644 --- a/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryViewModelType.swift +++ b/Riot/Modules/Rooms/ShowDirectory/ShowDirectoryViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol ShowDirectoryViewModelViewDelegate: class { +protocol ShowDirectoryViewModelViewDelegate: AnyObject { func showDirectoryViewModel(_ viewModel: ShowDirectoryViewModelType, didUpdateViewState viewSate: ShowDirectoryViewState) } -protocol ShowDirectoryViewModelCoordinatorDelegate: class { +protocol ShowDirectoryViewModelCoordinatorDelegate: AnyObject { func showDirectoryViewModelDidSelect(_ viewModel: ShowDirectoryViewModelType, room: MXPublicRoom) func showDirectoryViewModel(_ viewModel: ShowDirectoryViewModelType, didSelectRoomWithIdOrAlias roomIdOrAlias: String) func showDirectoryViewModelDidTapCreateNewRoom(_ viewModel: ShowDirectoryViewModelType) diff --git a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinatorType.swift b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinatorType.swift index f0a593f99..74b1b41a2 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinatorType.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol SecretsRecoveryWithKeyCoordinatorDelegate: class { +protocol SecretsRecoveryWithKeyCoordinatorDelegate: AnyObject { func secretsRecoveryWithKeyCoordinatorDidRecover(_ coordinator: SecretsRecoveryWithKeyCoordinatorType) func secretsRecoveryWithKeyCoordinatorDidCancel(_ coordinator: SecretsRecoveryWithKeyCoordinatorType) func secretsRecoveryWithKeyCoordinatorWantsToResetSecrets(_ viewModel: SecretsRecoveryWithKeyCoordinatorType) diff --git a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift index a0cc96d35..911f08302 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewController.swift @@ -123,6 +123,8 @@ final class SecretsRecoveryWithKeyViewController: UIViewController { self.updateRecoverButton() self.resetSecretsButton.vc_enableMultiLinesTitle() + + self.resetSecretsButton.isHidden = !RiotSettings.shared.secretsRecoveryAllowReset } private func update(theme: Theme) { diff --git a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModelType.swift b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModelType.swift index c747d67ba..b71ffac5d 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModelType.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithKey/SecretsRecoveryWithKeyViewModelType.swift @@ -16,11 +16,11 @@ import Foundation -protocol SecretsRecoveryWithKeyViewModelViewDelegate: class { +protocol SecretsRecoveryWithKeyViewModelViewDelegate: AnyObject { func secretsRecoveryWithKeyViewModel(_ viewModel: SecretsRecoveryWithKeyViewModelType, didUpdateViewState viewSate: SecretsRecoveryWithKeyViewState) } -protocol SecretsRecoveryWithKeyViewModelCoordinatorDelegate: class { +protocol SecretsRecoveryWithKeyViewModelCoordinatorDelegate: AnyObject { func secretsRecoveryWithKeyViewModelDidRecover(_ viewModel: SecretsRecoveryWithKeyViewModelType) func secretsRecoveryWithKeyViewModelDidCancel(_ viewModel: SecretsRecoveryWithKeyViewModelType) func secretsRecoveryWithKeyViewModelWantsToResetSecrets(_ viewModel: SecretsRecoveryWithKeyViewModelType) diff --git a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinatorType.swift b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinatorType.swift index f09c2eb98..3d6d17e4e 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinatorType.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol SecretsRecoveryWithPassphraseCoordinatorDelegate: class { +protocol SecretsRecoveryWithPassphraseCoordinatorDelegate: AnyObject { func secretsRecoveryWithPassphraseCoordinatorDidRecover(_ coordinator: SecretsRecoveryWithPassphraseCoordinatorType) func secretsRecoveryWithPassphraseCoordinatorDoNotKnowPassphrase(_ coordinator: SecretsRecoveryWithPassphraseCoordinatorType) func secretsRecoveryWithPassphraseCoordinatorDidCancel(_ coordinator: SecretsRecoveryWithPassphraseCoordinatorType) diff --git a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift index c1fcaaec4..5c64fd51b 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewController.swift @@ -125,6 +125,8 @@ final class SecretsRecoveryWithPassphraseViewController: UIViewController { self.updateRecoverButton() self.resetSecretsButton.vc_enableMultiLinesTitle() + + self.resetSecretsButton.isHidden = !RiotSettings.shared.secretsRecoveryAllowReset } private func update(theme: Theme) { diff --git a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModelType.swift b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModelType.swift index d54ae59f2..d1f1860a9 100644 --- a/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModelType.swift +++ b/Riot/Modules/Secrets/Recover/RecoverWithPassphrase/SecretsRecoveryWithPassphraseViewModelType.swift @@ -16,11 +16,11 @@ import Foundation -protocol SecretsRecoveryWithPassphraseViewModelViewDelegate: class { +protocol SecretsRecoveryWithPassphraseViewModelViewDelegate: AnyObject { func secretsRecoveryWithPassphraseViewModel(_ viewModel: SecretsRecoveryWithPassphraseViewModelType, didUpdateViewState viewSate: SecretsRecoveryWithPassphraseViewState) } -protocol SecretsRecoveryWithPassphraseViewModelCoordinatorDelegate: class { +protocol SecretsRecoveryWithPassphraseViewModelCoordinatorDelegate: AnyObject { func secretsRecoveryWithPassphraseViewModelDidRecover(_ viewModel: SecretsRecoveryWithPassphraseViewModelType) func secretsRecoveryWithPassphraseViewModelDidCancel(_ viewModel: SecretsRecoveryWithPassphraseViewModelType) func secretsRecoveryWithPassphraseViewModelWantsToRecoverByKey(_ viewModel: SecretsRecoveryWithPassphraseViewModelType) diff --git a/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinatorType.swift b/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinatorType.swift index 64b35f203..f7aea9dba 100644 --- a/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinatorType.swift +++ b/Riot/Modules/Secrets/Recover/SecretsRecoveryCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol SecretsRecoveryCoordinatorDelegate: class { +protocol SecretsRecoveryCoordinatorDelegate: AnyObject { func secretsRecoveryCoordinatorDidRecover(_ coordinator: SecretsRecoveryCoordinatorType) func secretsRecoveryCoordinatorDidCancel(_ coordinator: SecretsRecoveryCoordinatorType) } diff --git a/Riot/Modules/Secrets/Reset/SecretsResetCoordinatorType.swift b/Riot/Modules/Secrets/Reset/SecretsResetCoordinatorType.swift index 6b28912ce..cd33b058a 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetCoordinatorType.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SecretsResetCoordinatorDelegate: class { +protocol SecretsResetCoordinatorDelegate: AnyObject { func secretsResetCoordinatorDidResetSecrets(_ coordinator: SecretsResetCoordinatorType) func secretsResetCoordinatorDidCancel(_ coordinator: SecretsResetCoordinatorType) } diff --git a/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift b/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift index ce64f4c31..5a5c88077 100644 --- a/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift +++ b/Riot/Modules/Secrets/Reset/SecretsResetViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol SecretsResetViewModelViewDelegate: class { +protocol SecretsResetViewModelViewDelegate: AnyObject { func secretsResetViewModel(_ viewModel: SecretsResetViewModelType, didUpdateViewState viewState: SecretsResetViewState) } -protocol SecretsResetViewModelCoordinatorDelegate: class { +protocol SecretsResetViewModelCoordinatorDelegate: AnyObject { func secretsResetViewModel(_ viewModel: SecretsResetViewModelType, needsToAuthenticateWith request: AuthenticatedEndpointRequest) func secretsResetViewModelDidResetSecrets(_ viewModel: SecretsResetViewModelType) func secretsResetViewModelDidCancel(_ viewModel: SecretsResetViewModelType) diff --git a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinatorType.swift b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinatorType.swift index 0c2002813..87c885fcd 100644 --- a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinatorType.swift +++ b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SecretsSetupRecoveryKeyCoordinatorDelegate: class { +protocol SecretsSetupRecoveryKeyCoordinatorDelegate: AnyObject { func secretsSetupRecoveryKeyCoordinatorDidComplete(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType) func secretsSetupRecoveryKeyCoordinatorDidFailed(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType) func secretsSetupRecoveryKeyCoordinatorDidCancel(_ coordinator: SecretsSetupRecoveryKeyCoordinatorType) diff --git a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModelType.swift b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModelType.swift index 3cf3843d2..0922c9347 100644 --- a/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModelType.swift +++ b/Riot/Modules/Secrets/Setup/RecoveryKey/SecretsSetupRecoveryKeyViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol SecretsSetupRecoveryKeyViewModelViewDelegate: class { +protocol SecretsSetupRecoveryKeyViewModelViewDelegate: AnyObject { func secretsSetupRecoveryKeyViewModel(_ viewModel: SecretsSetupRecoveryKeyViewModelType, didUpdateViewState viewSate: SecretsSetupRecoveryKeyViewState) } -protocol SecretsSetupRecoveryKeyViewModelCoordinatorDelegate: class { +protocol SecretsSetupRecoveryKeyViewModelCoordinatorDelegate: AnyObject { func secretsSetupRecoveryKeyViewModelDidComplete(_ viewModel: SecretsSetupRecoveryKeyViewModelType) func secretsSetupRecoveryKeyViewModelDidFailed(_ viewModel: SecretsSetupRecoveryKeyViewModelType) func secretsSetupRecoveryKeyViewModelDidCancel(_ viewModel: SecretsSetupRecoveryKeyViewModelType) diff --git a/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseCoordinatorType.swift b/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseCoordinatorType.swift index 4318c4414..a3e3140d0 100644 --- a/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseCoordinatorType.swift +++ b/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SecretsSetupRecoveryPassphraseCoordinatorDelegate: class { +protocol SecretsSetupRecoveryPassphraseCoordinatorDelegate: AnyObject { func secretsSetupRecoveryPassphraseCoordinator(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType, didEnterNewPassphrase passphrase: String) func secretsSetupRecoveryPassphraseCoordinator(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType, didConfirmPassphrase passphrase: String) func secretsSetupRecoveryPassphraseCoordinatorDidCancel(_ coordinator: SecretsSetupRecoveryPassphraseCoordinatorType) diff --git a/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseViewModelType.swift b/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseViewModelType.swift index a7f27ad22..91a3eb50b 100644 --- a/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseViewModelType.swift +++ b/Riot/Modules/Secrets/Setup/RecoveryPassphrase/SecretsSetupRecoveryPassphraseViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol SecretsSetupRecoveryPassphraseViewModelViewDelegate: class { +protocol SecretsSetupRecoveryPassphraseViewModelViewDelegate: AnyObject { func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didUpdateViewState viewSate: SecretsSetupRecoveryPassphraseViewState) } -protocol SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate: class { +protocol SecretsSetupRecoveryPassphraseViewModelCoordinatorDelegate: AnyObject { func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didEnterNewPassphrase passphrase: String) func secretsSetupRecoveryPassphraseViewModel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType, didConfirmPassphrase passphrase: String) func secretsSetupRecoveryPassphraseViewModelDidCancel(_ viewModel: SecretsSetupRecoveryPassphraseViewModelType) diff --git a/Riot/Modules/SecureBackup/Banners/SecureBackupBannerCell.swift b/Riot/Modules/SecureBackup/Banners/SecureBackupBannerCell.swift index a1ff99449..780689396 100644 --- a/Riot/Modules/SecureBackup/Banners/SecureBackupBannerCell.swift +++ b/Riot/Modules/SecureBackup/Banners/SecureBackupBannerCell.swift @@ -16,7 +16,7 @@ import UIKit -@objc protocol SecureBackupBannerCellDelegate: class { +@objc protocol SecureBackupBannerCellDelegate: AnyObject { func secureBackupBannerCellDidTapCloseAction(_ cell: SecureBackupBannerCell) } diff --git a/Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewController.swift b/Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewController.swift index 0bdd5123c..b95bf6a24 100644 --- a/Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewController.swift +++ b/Riot/Modules/SecureBackup/Setup/Intro/SecureBackupSetupIntroViewController.swift @@ -16,7 +16,7 @@ import UIKit -protocol SecureBackupSetupIntroViewControllerDelegate: class { +protocol SecureBackupSetupIntroViewControllerDelegate: AnyObject { func secureBackupSetupIntroViewControllerDidTapUseKey(_ secureBackupSetupIntroViewController: SecureBackupSetupIntroViewController) func secureBackupSetupIntroViewControllerDidTapUsePassphrase(_ secureBackupSetupIntroViewController: SecureBackupSetupIntroViewController) func secureBackupSetupIntroViewControllerDidCancel(_ secureBackupSetupIntroViewController: SecureBackupSetupIntroViewController, showSkipAlert: Bool) diff --git a/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinatorType.swift b/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinatorType.swift index b4392672f..0ab664999 100644 --- a/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinatorType.swift +++ b/Riot/Modules/SecureBackup/Setup/SecureBackupSetupCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SecureBackupSetupCoordinatorDelegate: class { +protocol SecureBackupSetupCoordinatorDelegate: AnyObject { func secureBackupSetupCoordinatorDidComplete(_ coordinator: SecureBackupSetupCoordinatorType) func secureBackupSetupCoordinatorDidCancel(_ coordinator: SecureBackupSetupCoordinatorType) } diff --git a/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenCoordinatorType.swift b/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenCoordinatorType.swift index ebf6adc6e..909a0b33f 100644 --- a/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenCoordinatorType.swift +++ b/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol ServiceTermsModalScreenCoordinatorDelegate: class { +protocol ServiceTermsModalScreenCoordinatorDelegate: AnyObject { func serviceTermsModalScreenCoordinatorDidAccept(_ coordinator: ServiceTermsModalScreenCoordinatorType) func serviceTermsModalScreenCoordinator(_ coordinator: ServiceTermsModalScreenCoordinatorType, displayPolicy policy: MXLoginPolicyData) func serviceTermsModalScreenCoordinatorDidDecline(_ coordinator: ServiceTermsModalScreenCoordinatorType) diff --git a/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenViewModelType.swift b/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenViewModelType.swift index 76fff52d3..4dd4b6317 100644 --- a/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenViewModelType.swift +++ b/Riot/Modules/ServiceTerms/Modal/Modal/ServiceTermsModalScreenViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol ServiceTermsModalScreenViewModelViewDelegate: class { +protocol ServiceTermsModalScreenViewModelViewDelegate: AnyObject { func serviceTermsModalScreenViewModel(_ viewModel: ServiceTermsModalScreenViewModelType, didUpdateViewState viewSate: ServiceTermsModalScreenViewState) } -protocol ServiceTermsModalScreenViewModelCoordinatorDelegate: class { +protocol ServiceTermsModalScreenViewModelCoordinatorDelegate: AnyObject { func serviceTermsModalScreenViewModel(_ coordinator: ServiceTermsModalScreenViewModelType, displayPolicy policy: MXLoginPolicyData) func serviceTermsModalScreenViewModelDidAccept(_ viewModel: ServiceTermsModalScreenViewModelType) func serviceTermsModalScreenViewModelDidDecline(_ viewModel: ServiceTermsModalScreenViewModelType) diff --git a/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorType.swift b/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorType.swift index 84f3386b9..34c09cb18 100644 --- a/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorType.swift +++ b/Riot/Modules/ServiceTerms/Modal/ServiceTermsModalCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol ServiceTermsModalCoordinatorDelegate: class { +protocol ServiceTermsModalCoordinatorDelegate: AnyObject { func serviceTermsModalCoordinatorDidAccept(_ coordinator: ServiceTermsModalCoordinatorType) func serviceTermsModalCoordinatorDidDecline(_ coordinator: ServiceTermsModalCoordinatorType) func serviceTermsModalCoordinatorDidCancel(_ coordinator: ServiceTermsModalCoordinatorType) diff --git a/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeCoordinatorType.swift b/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeCoordinatorType.swift index 873a365bf..fb2a705bc 100644 --- a/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeCoordinatorType.swift +++ b/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol EnterPinCodeCoordinatorDelegate: class { +protocol EnterPinCodeCoordinatorDelegate: AnyObject { func enterPinCodeCoordinatorDidComplete(_ coordinator: EnterPinCodeCoordinatorType) func enterPinCodeCoordinatorDidCompleteWithReset(_ coordinator: EnterPinCodeCoordinatorType, dueToTooManyErrors: Bool) func enterPinCodeCoordinator(_ coordinator: EnterPinCodeCoordinatorType, didCompleteWithPin pin: String) diff --git a/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeViewModelType.swift b/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeViewModelType.swift index eb66cdc8c..89d1bf8f1 100644 --- a/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeViewModelType.swift +++ b/Riot/Modules/SetPinCode/EnterPinCode/EnterPinCodeViewModelType.swift @@ -18,13 +18,13 @@ import Foundation -protocol EnterPinCodeViewModelViewDelegate: class { +protocol EnterPinCodeViewModelViewDelegate: AnyObject { func enterPinCodeViewModel(_ viewModel: EnterPinCodeViewModelType, didUpdateViewState viewSate: EnterPinCodeViewState) func enterPinCodeViewModel(_ viewModel: EnterPinCodeViewModelType, didUpdatePlaceholdersCount count: Int) func enterPinCodeViewModel(_ viewModel: EnterPinCodeViewModelType, didUpdateCancelButtonHidden isHidden: Bool) } -protocol EnterPinCodeViewModelCoordinatorDelegate: class { +protocol EnterPinCodeViewModelCoordinatorDelegate: AnyObject { func enterPinCodeViewModelDidComplete(_ viewModel: EnterPinCodeViewModelType) func enterPinCodeViewModelDidCompleteWithReset(_ viewModel: EnterPinCodeViewModelType, dueToTooManyErrors: Bool) func enterPinCodeViewModel(_ viewModel: EnterPinCodeViewModelType, didCompleteWithPin pin: String) diff --git a/Riot/Modules/SetPinCode/SetPinCoordinatorType.swift b/Riot/Modules/SetPinCode/SetPinCoordinatorType.swift index 3649250b1..ae439b9ee 100644 --- a/Riot/Modules/SetPinCode/SetPinCoordinatorType.swift +++ b/Riot/Modules/SetPinCode/SetPinCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SetPinCoordinatorDelegate: class { +protocol SetPinCoordinatorDelegate: AnyObject { func setPinCoordinatorDidComplete(_ coordinator: SetPinCoordinatorType) func setPinCoordinatorDidCompleteWithReset(_ coordinator: SetPinCoordinatorType, dueToTooManyErrors: Bool) func setPinCoordinatorDidCancel(_ coordinator: SetPinCoordinatorType) diff --git a/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsCoordinatorType.swift b/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsCoordinatorType.swift index 2cd9e9f83..f43d7759a 100644 --- a/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsCoordinatorType.swift +++ b/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SetupBiometricsCoordinatorDelegate: class { +protocol SetupBiometricsCoordinatorDelegate: AnyObject { func setupBiometricsCoordinatorDidComplete(_ coordinator: SetupBiometricsCoordinatorType) func setupBiometricsCoordinatorDidCompleteWithReset(_ coordinator: SetupBiometricsCoordinatorType, dueToTooManyErrors: Bool) func setupBiometricsCoordinatorDidCancel(_ coordinator: SetupBiometricsCoordinatorType) diff --git a/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsViewModelType.swift b/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsViewModelType.swift index 2b2708e1d..bd7f3124f 100644 --- a/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsViewModelType.swift +++ b/Riot/Modules/SetPinCode/SetupBiometrics/SetupBiometricsViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol SetupBiometricsViewModelViewDelegate: class { +protocol SetupBiometricsViewModelViewDelegate: AnyObject { func setupBiometricsViewModel(_ viewModel: SetupBiometricsViewModelType, didUpdateViewState viewSate: SetupBiometricsViewState) } -protocol SetupBiometricsViewModelCoordinatorDelegate: class { +protocol SetupBiometricsViewModelCoordinatorDelegate: AnyObject { func setupBiometricsViewModelDidComplete(_ viewModel: SetupBiometricsViewModelType) func setupBiometricsViewModelDidCompleteWithReset(_ viewModel: SetupBiometricsViewModelType, dueToTooManyErrors: Bool) func setupBiometricsViewModelDidCancel(_ viewModel: SetupBiometricsViewModelType) diff --git a/Riot/Modules/Settings/Discovery/SettingsDiscoveryTableViewSection.swift b/Riot/Modules/Settings/Discovery/SettingsDiscoveryTableViewSection.swift index 0c9116928..6bee0aebe 100644 --- a/Riot/Modules/Settings/Discovery/SettingsDiscoveryTableViewSection.swift +++ b/Riot/Modules/Settings/Discovery/SettingsDiscoveryTableViewSection.swift @@ -16,7 +16,7 @@ import Foundation -@objc protocol SettingsDiscoveryTableViewSectionDelegate: class { +@objc protocol SettingsDiscoveryTableViewSectionDelegate: AnyObject { func settingsDiscoveryTableViewSection(_ settingsDiscoveryTableViewSection: SettingsDiscoveryTableViewSection, tableViewCellClass: MXKTableViewCell.Type, forRow: Int) -> MXKTableViewCell func settingsDiscoveryTableViewSectionDidUpdate(_ settingsDiscoveryTableViewSection: SettingsDiscoveryTableViewSection) diff --git a/Riot/Modules/Settings/Discovery/SettingsDiscoveryViewModelType.swift b/Riot/Modules/Settings/Discovery/SettingsDiscoveryViewModelType.swift index c3ebf4dab..0435a5eb5 100644 --- a/Riot/Modules/Settings/Discovery/SettingsDiscoveryViewModelType.swift +++ b/Riot/Modules/Settings/Discovery/SettingsDiscoveryViewModelType.swift @@ -16,11 +16,11 @@ import Foundation -protocol SettingsDiscoveryViewModelViewDelegate: class { +protocol SettingsDiscoveryViewModelViewDelegate: AnyObject { func settingsDiscoveryViewModel(_ viewModel: SettingsDiscoveryViewModelType, didUpdateViewState viewState: SettingsDiscoveryViewState) } -@objc protocol SettingsDiscoveryViewModelCoordinatorDelegate: class { +@objc protocol SettingsDiscoveryViewModelCoordinatorDelegate: AnyObject { func settingsDiscoveryViewModel(_ viewModel: SettingsDiscoveryViewModel, didSelectThreePidWith medium: String, and address: String) func settingsDiscoveryViewModelDidTapUserSettingsLink(_ viewModel: SettingsDiscoveryViewModel) } diff --git a/Riot/Modules/Settings/Discovery/ThreePidDetails/SettingsDiscoveryThreePidDetailsViewModelType.swift b/Riot/Modules/Settings/Discovery/ThreePidDetails/SettingsDiscoveryThreePidDetailsViewModelType.swift index ce00918fd..df8ccf6f2 100644 --- a/Riot/Modules/Settings/Discovery/ThreePidDetails/SettingsDiscoveryThreePidDetailsViewModelType.swift +++ b/Riot/Modules/Settings/Discovery/ThreePidDetails/SettingsDiscoveryThreePidDetailsViewModelType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SettingsDiscoveryThreePidDetailsViewModelViewDelegate: class { +protocol SettingsDiscoveryThreePidDetailsViewModelViewDelegate: AnyObject { func settingsDiscoveryThreePidDetailsViewModel(_ viewModel: SettingsDiscoveryThreePidDetailsViewModelType, didUpdateViewState viewSate: SettingsDiscoveryThreePidDetailsViewState) } diff --git a/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModel.swift b/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModel.swift index 0c80415fb..205d7c174 100644 --- a/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModel.swift +++ b/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModel.swift @@ -155,8 +155,7 @@ final class SettingsIdentityServerViewModel: SettingsIdentityServerViewModelType let viewStateUpdate: (SettingsIdentityServerViewState) -> Void = { (viewState) in - // Convert states for .addActionAlert and .disconnectActionAlert to - //.changeActionAlert + // Convert states for .addActionAlert and .disconnectActionAlert to .changeActionAlert var changeViewState = viewState switch viewState { case .alert(let alert, let onContinue): diff --git a/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModelType.swift b/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModelType.swift index 5d8447750..210fcbaef 100644 --- a/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModelType.swift +++ b/Riot/Modules/Settings/IdentityServer/SettingsIdentityServerViewModelType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SettingsIdentityServerViewModelViewDelegate: class { +protocol SettingsIdentityServerViewModelViewDelegate: AnyObject { func settingsIdentityServerViewModel(_ viewModel: SettingsIdentityServerViewModelType, didUpdateViewState viewSate: SettingsIdentityServerViewState) } diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift index d63ce69be..69b64d44f 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupTableViewSection.swift @@ -16,7 +16,7 @@ import UIKit -@objc protocol SettingsKeyBackupTableViewSectionDelegate: class { +@objc protocol SettingsKeyBackupTableViewSectionDelegate: AnyObject { func settingsKeyBackupTableViewSectionDidUpdate(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection) func settingsKeyBackupTableViewSection(_ settingsKeyBackupTableViewSection: SettingsKeyBackupTableViewSection, textCellForRow: Int) -> MXKTableViewCellWithTextView diff --git a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift index 662462145..191f1b802 100644 --- a/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift +++ b/Riot/Modules/Settings/KeyBackup/SettingsKeyBackupViewModelType.swift @@ -16,7 +16,7 @@ import UIKit -protocol SettingsKeyBackupViewModelViewDelegate: class { +protocol SettingsKeyBackupViewModelViewDelegate: AnyObject { func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateViewState viewState: SettingsKeyBackupViewState) func settingsKeyBackupViewModel(_ viewModel: SettingsKeyBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsKeyBackupNetworkRequestViewState) diff --git a/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupTableViewSection.swift b/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupTableViewSection.swift index 6ef387a20..cc23c878c 100644 --- a/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupTableViewSection.swift +++ b/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupTableViewSection.swift @@ -16,7 +16,7 @@ import UIKit -@objc protocol SettingsSecureBackupTableViewSectionDelegate: class { +@objc protocol SettingsSecureBackupTableViewSectionDelegate: AnyObject { // Table view rendering func settingsSecureBackupTableViewSectionDidUpdate(_ settingsSecureBackupTableViewSection: SettingsSecureBackupTableViewSection) diff --git a/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupViewModelType.swift b/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupViewModelType.swift index 4f83b5ccc..4248872dc 100644 --- a/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupViewModelType.swift +++ b/Riot/Modules/Settings/Security/SecureBackup/SettingsSecureBackupViewModelType.swift @@ -16,7 +16,7 @@ import UIKit -protocol SettingsSecureBackupViewModelViewDelegate: class { +protocol SettingsSecureBackupViewModelViewDelegate: AnyObject { func settingsSecureBackupViewModel(_ viewModel: SettingsSecureBackupViewModelType, didUpdateViewState viewState: SettingsSecureBackupViewState) func settingsSecureBackupViewModel(_ viewModel: SettingsSecureBackupViewModelType, didUpdateNetworkRequestViewState networkRequestViewSate: SettingsSecureBackupNetworkRequestViewState) diff --git a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift index faaba6827..0231aef4e 100644 --- a/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift +++ b/Riot/Modules/Settings/SignOut/SignOutAlertPresenter.swift @@ -16,7 +16,7 @@ import UIKit -@objc protocol SignOutAlertPresenterDelegate: class { +@objc protocol SignOutAlertPresenterDelegate: AnyObject { func signOutAlertPresenterDidTapSignOutAction(_ presenter: SignOutAlertPresenter) func signOutAlertPresenterDidTapBackupAction(_ presenter: SignOutAlertPresenter) } diff --git a/Riot/Modules/SideMenu/SideMenuActionView.swift b/Riot/Modules/SideMenu/SideMenuActionView.swift index 72ff6a852..689472fc1 100644 --- a/Riot/Modules/SideMenu/SideMenuActionView.swift +++ b/Riot/Modules/SideMenu/SideMenuActionView.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -protocol SideMenuActionViewDelegate: class { +protocol SideMenuActionViewDelegate: AnyObject { func sideMenuActionView(_ actionView: SideMenuActionView, didTapMenuItem sideMenuItem: SideMenuItem?) } diff --git a/Riot/Modules/SideMenu/SideMenuCoordinatorType.swift b/Riot/Modules/SideMenu/SideMenuCoordinatorType.swift index f193c5a73..9223eca59 100644 --- a/Riot/Modules/SideMenu/SideMenuCoordinatorType.swift +++ b/Riot/Modules/SideMenu/SideMenuCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol SideMenuCoordinatorDelegate: class { +protocol SideMenuCoordinatorDelegate: AnyObject { func sideMenuCoordinator(_ coordinator: SideMenuCoordinatorType, didTapMenuItem menuItem: SideMenuItem, fromSourceView sourceView: UIView) } diff --git a/Riot/Modules/SideMenu/SideMenuViewModelType.swift b/Riot/Modules/SideMenu/SideMenuViewModelType.swift index 1ab51f3cf..92479a5ad 100644 --- a/Riot/Modules/SideMenu/SideMenuViewModelType.swift +++ b/Riot/Modules/SideMenu/SideMenuViewModelType.swift @@ -18,11 +18,11 @@ import Foundation -protocol SideMenuViewModelViewDelegate: class { +protocol SideMenuViewModelViewDelegate: AnyObject { func sideMenuViewModel(_ viewModel: SideMenuViewModelType, didUpdateViewState viewSate: SideMenuViewState) } -protocol SideMenuViewModelCoordinatorDelegate: class { +protocol SideMenuViewModelCoordinatorDelegate: AnyObject { func sideMenuViewModel(_ viewModel: SideMenuViewModelType, didTapMenuItem menuItem: SideMenuItem, fromSourceView sourceView: UIView) } diff --git a/Riot/Modules/SlidingModal/SlidingModalContainerView.swift b/Riot/Modules/SlidingModal/SlidingModalContainerView.swift index a494351f2..5a2c6b8d5 100644 --- a/Riot/Modules/SlidingModal/SlidingModalContainerView.swift +++ b/Riot/Modules/SlidingModal/SlidingModalContainerView.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -protocol SlidingModalContainerViewDelegate: class { +protocol SlidingModalContainerViewDelegate: AnyObject { func slidingModalContainerViewDidTapBackground(_ view: SlidingModalContainerView) } diff --git a/Riot/Modules/Spaces/BetaAnnounceCell.swift b/Riot/Modules/Spaces/BetaAnnounceCell.swift index dac6dca86..9897c9417 100644 --- a/Riot/Modules/Spaces/BetaAnnounceCell.swift +++ b/Riot/Modules/Spaces/BetaAnnounceCell.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -@objc protocol BetaAnnounceCellDelegate: class { +@objc protocol BetaAnnounceCellDelegate: AnyObject { func betaAnnounceCellDidTapCloseButton(_ cell: BetaAnnounceCell) } diff --git a/Riot/Modules/SplitView/SplitViewCoordinatorType.swift b/Riot/Modules/SplitView/SplitViewCoordinatorType.swift index 0162e9808..d87138978 100644 --- a/Riot/Modules/SplitView/SplitViewCoordinatorType.swift +++ b/Riot/Modules/SplitView/SplitViewCoordinatorType.swift @@ -16,7 +16,7 @@ import Foundation -protocol SplitViewCoordinatorDelegate: class { +protocol SplitViewCoordinatorDelegate: AnyObject { // TODO: Remove this method, authentication should not be handled by SplitViewCoordinator func splitViewCoordinatorDidCompleteAuthentication(_ coordinator: SplitViewCoordinatorType) } diff --git a/Riot/Modules/SplitView/SplitViewPresentable.swift b/Riot/Modules/SplitView/SplitViewPresentable.swift index c1bfa2bf7..f09134d3f 100644 --- a/Riot/Modules/SplitView/SplitViewPresentable.swift +++ b/Riot/Modules/SplitView/SplitViewPresentable.swift @@ -16,12 +16,12 @@ import UIKit -protocol SplitViewMasterPresentableDelegate: class { +protocol SplitViewMasterPresentableDelegate: AnyObject { func splitViewMasterPresentable(_ presentable: Presentable, wantsToDisplay detailPresentable: Presentable) } /// Protocol used by the master view presentable of a UISplitViewController -protocol SplitViewMasterPresentable: class, Presentable { +protocol SplitViewMasterPresentable: AnyObject, Presentable { var splitViewMasterPresentableDelegate: SplitViewMasterPresentableDelegate? { get set } diff --git a/Riot/Modules/StartChat/InviteFriendsHeaderView.swift b/Riot/Modules/StartChat/InviteFriendsHeaderView.swift index ceffd0cbb..c1d81ea06 100644 --- a/Riot/Modules/StartChat/InviteFriendsHeaderView.swift +++ b/Riot/Modules/StartChat/InviteFriendsHeaderView.swift @@ -18,7 +18,7 @@ import UIKit import Reusable @objc -protocol InviteFriendsHeaderViewDelegate: class { +protocol InviteFriendsHeaderViewDelegate: AnyObject { func inviteFriendsHeaderView(_ headerView: InviteFriendsHeaderView, didTapButton button: UIButton) } diff --git a/Riot/Modules/TabBar/MasterTabBarController.h b/Riot/Modules/TabBar/MasterTabBarController.h index 6ef661948..1d5f41a12 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.h +++ b/Riot/Modules/TabBar/MasterTabBarController.h @@ -90,7 +90,7 @@ @param roomId the room identifier. @param eventId if not nil, the room will be opened on this event. - @param mxSession the matrix session in which the room should be available. + @param matrixSession the matrix session in which the room should be available. @param completion the block to execute at the end of the operation. */ - (void)selectRoomWithId:(NSString*)roomId andEventId:(NSString*)eventId inMatrixSession:(MXSession*)matrixSession completion:(void (^)(void))completion; @@ -113,7 +113,7 @@ Open a GroupDetailsViewController to display the information of the provided group. @param group - @param mxSession the matrix session in which the group should be available. + @param matrixSession the matrix session in which the group should be available. */ - (void)selectGroup:(MXGroup*)group inMatrixSession:(MXSession*)matrixSession; diff --git a/Riot/Modules/TabBar/TabBarCoordinator.swift b/Riot/Modules/TabBar/TabBarCoordinator.swift index 0efc1c03c..cb28c4427 100644 --- a/Riot/Modules/TabBar/TabBarCoordinator.swift +++ b/Riot/Modules/TabBar/TabBarCoordinator.swift @@ -245,9 +245,9 @@ final class TabBarCoordinator: NSObject, TabBarCoordinatorType { } private func setupSideMenuGestures() { - self.parameters.appNavigator.sideMenu.addScreenEdgePanGesturesToPresent(to: self.masterNavigationController.view) - - self.parameters.appNavigator.sideMenu.addPanGestureToPresent(to: self.masterNavigationController.navigationBar) + if let rootViewController = self.masterNavigationController.viewControllers.first { + self.parameters.appNavigator.sideMenu.addScreenEdgePanGesturesToPresent(to: rootViewController.view) + } } // MARK: Navigation diff --git a/Riot/Modules/TabBar/TabBarCoordinatorType.swift b/Riot/Modules/TabBar/TabBarCoordinatorType.swift index 6cd58a485..50d1cc36e 100644 --- a/Riot/Modules/TabBar/TabBarCoordinatorType.swift +++ b/Riot/Modules/TabBar/TabBarCoordinatorType.swift @@ -18,7 +18,7 @@ import Foundation -protocol TabBarCoordinatorDelegate: class { +protocol TabBarCoordinatorDelegate: AnyObject { // TODO: Remove this method, authentication should not be handled by TabBarCoordinator func tabBarCoordinatorDidCompleteAuthentication(_ coordinator: TabBarCoordinatorType) } diff --git a/Riot/Routers/NavigationRouterType.swift b/Riot/Routers/NavigationRouterType.swift index c32ea4e8e..a04e1f430 100755 --- a/Riot/Routers/NavigationRouterType.swift +++ b/Riot/Routers/NavigationRouterType.swift @@ -18,7 +18,7 @@ import UIKit /// Protocol describing a router that wraps a UINavigationController and add convenient completion handlers. Completions are called when a Presentable is removed. /// Routers are used to be passed between coordinators. They handles only `physical` navigation. -protocol NavigationRouterType: class, Presentable { +protocol NavigationRouterType: AnyObject, Presentable { /// Present modally a view controller on the navigation controller /// diff --git a/Riot/Routers/RootRouterType.swift b/Riot/Routers/RootRouterType.swift index b185b0723..633da610c 100755 --- a/Riot/Routers/RootRouterType.swift +++ b/Riot/Routers/RootRouterType.swift @@ -18,7 +18,7 @@ import UIKit /// Protocol describing a router that wraps the root navigation of the application. /// Routers are used to be passed between coordinators. They handles only `physical` navigation. -protocol RootRouterType: class { +protocol RootRouterType: AnyObject { /// Update the root view controller /// diff --git a/RiotShareExtension/Managers/ShareExtensionManager.m b/RiotShareExtension/Managers/ShareExtensionManager.m index 47dfb03c4..5b69743be 100644 --- a/RiotShareExtension/Managers/ShareExtensionManager.m +++ b/RiotShareExtension/Managers/ShareExtensionManager.m @@ -1165,8 +1165,8 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } // Retrieve the video frame at 1 sec to define the video thumbnail - AVURLAsset *urlAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil]; - AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:urlAsset]; + AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil]; + AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:videoAsset]; assetImageGenerator.appliesPreferredTrackTransform = YES; CMTime time = CMTimeMake(1, 1); CGImageRef imageRef = [assetImageGenerator copyCGImageAtTime:time actualTime:NULL error:nil]; @@ -1174,7 +1174,7 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) UIImage *videoThumbnail = [[UIImage alloc] initWithCGImage:imageRef]; CFRelease(imageRef); - [room sendVideo:videoLocalUrl withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { + [room sendVideoAsset:videoAsset withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { if (successBlock) { successBlock(); diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m index 777249a6e..94acaa453 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.m @@ -129,6 +129,13 @@ } } +- (void)setKeyboardHeight:(CGFloat)keyboardHeight +{ + // Bypass inherited keyboard handling to fix layout when searching. + // There are no sticky headers to worry about updating. + return; +} + #pragma mark - Private - (void)showShareAlertForRoomPath:(NSIndexPath *)indexPath @@ -289,6 +296,12 @@ // Refresh display [self refreshRecentsTable]; } + + // Dismiss the keyboard when scrolling to match the behaviour of the main app. + if (self.recentsSearchBar.isFirstResponder) + { + [self.recentsSearchBar resignFirstResponder]; + } } } } diff --git a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.xib b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.xib index 630d940a3..bc77d3275 100644 --- a/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.xib +++ b/RiotShareExtension/Modules/Share/Listing/RoomsListViewController.xib @@ -1,11 +1,9 @@ - - - - + + - + @@ -39,7 +37,6 @@ - @@ -49,6 +46,7 @@ + diff --git a/RiotTests/RoomNotificationSettingsViewModelTests.swift b/RiotTests/RoomNotificationSettingsViewModelTests.swift new file mode 100644 index 000000000..b10dbd63b --- /dev/null +++ b/RiotTests/RoomNotificationSettingsViewModelTests.swift @@ -0,0 +1,146 @@ +// +// 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 MockRoomNotificationSettingsService: RoomNotificationSettingsServiceType { + + var listener: RoomNotificationStateCallback? + var notificationState: RoomNotificationState + + init(initialState: RoomNotificationState) { + notificationState = initialState + } + + func observeNotificationState(listener: @escaping RoomNotificationStateCallback) { + self.listener = listener + } + + func update(state: RoomNotificationState, completion: @escaping UpdateRoomNotificationStateCompletion) { + self.notificationState = state + completion() + listener?(state) + } +} + +class MockRoomNotificationSettingsView: RoomNotificationSettingsViewModelViewDelegate { + + var viewState: RoomNotificationSettingsViewStateType? + + func roomNotificationSettingsViewModel(_ viewModel: RoomNotificationSettingsViewModelType, didUpdateViewState viewState: RoomNotificationSettingsViewStateType) { + self.viewState = viewState + } +} + +class MockRoomNotificationSettingsCoordinator: RoomNotificationSettingsViewModelCoordinatorDelegate { + + var didComplete = false + var didCancel = false + func roomNotificationSettingsViewModelDidComplete(_ viewModel: RoomNotificationSettingsViewModelType) { + didComplete = true + } + + func roomNotificationSettingsViewModelDidCancel(_ viewModel: RoomNotificationSettingsViewModelType) { + didCancel = true + } +} + +class RoomNotificationSettingsViewModelTests: XCTestCase { + + enum Constants{ + static let roomDisplayName: String = "Test Room Name" + static let roomId: String = "1" + static let avatarUrl: String = "http://test.url.com" + static let avatarData = RoomAvatarViewData(roomId: "1", displayName: roomDisplayName, avatarUrl: avatarUrl, mediaManager: MXMediaManager()) + } + + var coordinator: MockRoomNotificationSettingsCoordinator! + var service: MockRoomNotificationSettingsService! + var view: MockRoomNotificationSettingsView! + var viewModel: RoomNotificationSettingsViewModel! + + override func setUpWithError() throws { + service = MockRoomNotificationSettingsService(initialState: .all) + view = MockRoomNotificationSettingsView() + coordinator = MockRoomNotificationSettingsCoordinator() + } + + func setupViewModel(roomEncrypted: Bool, showAvatar: Bool) { + let avatarData = showAvatar ? Constants.avatarData : nil + let viewModel = RoomNotificationSettingsViewModel(roomNotificationService: service, roomEncrypted: roomEncrypted, avatarViewData: avatarData) + viewModel.viewDelegate = view + viewModel.coordinatorDelegate = coordinator + self.viewModel = viewModel + } + + func testUnloaded() throws { + setupViewModel(roomEncrypted: true, showAvatar: false) + XCTAssertNil(view.viewState) + } + + func testUnencryptedOptions() throws { + setupViewModel(roomEncrypted: false, showAvatar: false) + viewModel.process(viewAction: .load) + XCTAssertNotNil(view.viewState) + XCTAssertTrue(view.viewState!.notificationOptions.count == 3) + } + + func testEncryptedOptions() throws { + setupViewModel(roomEncrypted: true, showAvatar: false) + viewModel.process(viewAction: .load) + XCTAssertNotNil(view.viewState) + XCTAssertTrue(view.viewState!.notificationOptions.count == 2) + } + + func testAvatar() throws { + setupViewModel(roomEncrypted: true, showAvatar: true) + viewModel.process(viewAction: .load) + XCTAssertNotNil(view.viewState?.avatarData) + XCTAssertEqual(view.viewState!.avatarData!.avatarUrl, Constants.avatarUrl) + } + + func testSelectionUpdateAndSave() throws { + setupViewModel(roomEncrypted: false, showAvatar: false) + viewModel.process(viewAction: .load) + XCTAssertNotNil(view.viewState) + XCTAssertTrue(view.viewState!.notificationState == .all) + viewModel.process(viewAction: .selectNotificationState(.mentionsAndKeywordsOnly)) + XCTAssertTrue(view.viewState!.notificationState == .mentionsAndKeywordsOnly) + viewModel.process(viewAction: .save) + XCTAssertTrue(service.notificationState == .mentionsAndKeywordsOnly) + XCTAssertTrue(coordinator.didComplete) + } + + func testCancel() throws { + setupViewModel(roomEncrypted: false, showAvatar: false) + viewModel.process(viewAction: .load) + XCTAssertNotNil(view.viewState) + viewModel.process(viewAction: .cancel) + XCTAssertTrue(coordinator.didCancel) + } + + func testMentionsOnlyNotAvaileOnEncryptedRoom() throws { + service = MockRoomNotificationSettingsService(initialState: .mentionsAndKeywordsOnly) + setupViewModel(roomEncrypted: true, showAvatar: false) + + viewModel.process(viewAction: .load) + XCTAssertNotNil(view.viewState) + XCTAssertTrue(view.viewState!.notificationState == .mute) + } + +} diff --git a/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinator.swift b/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinator.swift index a211ab040..2f51aa2c2 100644 --- a/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinator.swift +++ b/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinator.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorBridgePresenter.swift b/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorBridgePresenter.swift index bb7f824e4..25024f94d 100644 --- a/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorBridgePresenter.swift +++ b/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorBridgePresenter.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorType.swift b/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorType.swift index 4fa5cc5dc..8caa44cf8 100644 --- a/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorType.swift +++ b/Tools/Templates/buildable/FlowCoordinatorTemplate/FlowTemplateCoordinatorType.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. @@ -16,7 +16,7 @@ import Foundation -protocol FlowTemplateCoordinatorDelegate: class { +protocol FlowTemplateCoordinatorDelegate: AnyObject { func flowTemplateCoordinatorDidComplete(_ coordinator: FlowTemplateCoordinatorType) } diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinator.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinator.swift index 78ebc30f8..276fff2a8 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinator.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinator.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinatorType.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinatorType.swift index 745997b9c..191a4198b 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinatorType.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenCoordinatorType.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. @@ -16,7 +16,7 @@ import Foundation -protocol TemplateScreenCoordinatorDelegate: class { +protocol TemplateScreenCoordinatorDelegate: AnyObject { func templateScreenCoordinator(_ coordinator: TemplateScreenCoordinatorType, didCompleteWithUserDisplayName userDisplayName: String?) func templateScreenCoordinatorDidCancel(_ coordinator: TemplateScreenCoordinatorType) } diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewAction.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewAction.swift index 0bfc0f7f2..fc25efd98 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewAction.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewAction.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewController.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewController.swift index f3a30d180..78175a877 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewController.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewController.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModel.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModel.swift index 05c07ba58..4c386a8f7 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModel.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModel.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModelType.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModelType.swift index fd03254da..81900b629 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModelType.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewModelType.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. @@ -16,11 +16,11 @@ import Foundation -protocol TemplateScreenViewModelViewDelegate: class { +protocol TemplateScreenViewModelViewDelegate: AnyObject { func templateScreenViewModel(_ viewModel: TemplateScreenViewModelType, didUpdateViewState viewSate: TemplateScreenViewState) } -protocol TemplateScreenViewModelCoordinatorDelegate: class { +protocol TemplateScreenViewModelCoordinatorDelegate: AnyObject { func templateScreenViewModel(_ viewModel: TemplateScreenViewModelType, didCompleteWithUserDisplayName userDisplayName: String?) func templateScreenViewModelDidCancel(_ viewModel: TemplateScreenViewModelType) } diff --git a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewState.swift b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewState.swift index cc347baaa..4cebae662 100644 --- a/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewState.swift +++ b/Tools/Templates/buildable/ScreenTemplate/TemplateScreenViewState.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. diff --git a/Tools/Templates/buildable/SimpleScreenTemplate/SimpleScreenTemplateViewController.swift b/Tools/Templates/buildable/SimpleScreenTemplate/SimpleScreenTemplateViewController.swift index 2955714c9..4513240b0 100644 --- a/Tools/Templates/buildable/SimpleScreenTemplate/SimpleScreenTemplateViewController.swift +++ b/Tools/Templates/buildable/SimpleScreenTemplate/SimpleScreenTemplateViewController.swift @@ -1,5 +1,5 @@ /* - Copyright 2020 New Vector Ltd + 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. @@ -16,7 +16,7 @@ import UIKit -protocol SimpleScreenTemplateViewControllerDelegate: class { +protocol SimpleScreenTemplateViewControllerDelegate: AnyObject { func simpleScreenTemplateViewControllerDidTapSetupAction(_ viewController: SimpleScreenTemplateViewController) func simpleScreenTemplateViewControllerDidCancel(_ viewController: SimpleScreenTemplateViewController) }