diff --git a/CHANGES.md b/CHANGES.md index 29c234d02..a501125c3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,27 @@ +## Changes in 0.16.2 (2021-09-24) + +✨ Features + +- Added device de/rehydration supporting flows. ([#4255](https://github.com/vector-im/element-ios/issues/4255)) +- Support for space link. ([#4498](https://github.com/vector-im/element-ios/issues/4498)) +- Add suggested rooms and support for suggested room selection to the list of recent cell data ([#4501](https://github.com/vector-im/element-ios/issues/4501)) +- moved space filtering to MatrixKit. ([#4509](https://github.com/vector-im/element-ios/issues/4509)) +- Tweaked `MXKRoomMemberDetailsViewController` so we can hide leave option ([#4682](https://github.com/vector-im/element-ios/issues/4682)) + +🙌 Improvements + +- Upgrade MatrixSDK version ([v0.20.2](https://github.com/matrix-org/matrix-ios-sdk/releases/tag/v0.20.2)). + +🐛 Bugfixes + +- MXKAppSettings: Return matrix.to when firstURLDetectionIgnoredHosts is nil, and store an empty array when setting nil. ([#4826](https://github.com/vector-im/element-ios/issues/4826)) + +⚠️ API Changes + +- Dropped support for iOS versions 11 and lower. ([#4693](https://github.com/vector-im/element-ios/issues/4693)) +- Exposed more room joining result types in the completion handler. ([#4830](https://github.com/vector-im/element-ios/issues/4830)) + + ## Changes in 0.16.1 (2021-09-16) 🙌 Improvements diff --git a/MatrixKit.podspec b/MatrixKit.podspec index fb235c84b..0a1145d2b 100644 --- a/MatrixKit.podspec +++ b/MatrixKit.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "MatrixKit" - s.version = "0.16.1" + s.version = "0.16.2" s.summary = "The Matrix reusable UI library for iOS based on MatrixSDK." s.description = <<-DESC @@ -15,7 +15,7 @@ Pod::Spec.new do |s| s.author = { "matrix.org" => "support@matrix.org" } s.social_media_url = "http://twitter.com/matrixdotorg" - s.platform = :ios, "9.0" + s.platform = :ios, "12.1" s.source = { :git => "https://github.com/matrix-org/matrix-ios-kit.git", :tag => "v#{s.version}" } @@ -23,7 +23,7 @@ Pod::Spec.new do |s| s.swift_version = '5.0' - s.dependency 'MatrixSDK', "= 0.20.1" + s.dependency 'MatrixSDK', "= 0.20.2" s.dependency 'HPGrowingTextView', '~> 1.1' s.dependency 'libPhoneNumber-iOS', '~> 0.9.13' s.dependency 'DTCoreText', '~> 1.6.25' diff --git a/MatrixKit.xcodeproj/project.pbxproj b/MatrixKit.xcodeproj/project.pbxproj index 71c2ed5aa..b158991c5 100644 --- a/MatrixKit.xcodeproj/project.pbxproj +++ b/MatrixKit.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 32FBDAF81E4484C40033C519 /* MXKEncryptionKeysImportView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FBDAF71E4484C40033C519 /* MXKEncryptionKeysImportView.m */; }; 32FBDAFB1E44B0FC0033C519 /* MXKEncryptionKeysExportView.m in Sources */ = {isa = PBXBuildFile; fileRef = 32FBDAFA1E44B0FC0033C519 /* MXKEncryptionKeysExportView.m */; }; 3A1293A825801D9400F3474B /* MXKPreviewViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3A1293A625801D9400F3474B /* MXKPreviewViewController.m */; }; + 3AF85F9726FCD75700A9E67B /* MXKActivityHandlingViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AF85F9626FCC35D00A9E67B /* MXKActivityHandlingViewController.m */; }; 4F236C27EC459185548BEF4F /* Pods_MatrixKitSamplePods_MatrixKitTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B455B95A7B9ECAD75BA21E12 /* Pods_MatrixKitSamplePods_MatrixKitTests.framework */; }; 550A36BD1DE484DB005C1647 /* EncryptedAttachmentsTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 550A36BC1DE484DB005C1647 /* EncryptedAttachmentsTest.m */; }; 71352D551C0ED240001D50B0 /* MXKRoomSettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 71352D531C0ED240001D50B0 /* MXKRoomSettingsViewController.m */; }; @@ -194,7 +195,6 @@ F09A66671FD812CA004B13B5 /* MXKGroupCellData.m in Sources */ = {isa = PBXBuildFile; fileRef = F09A66661FD812CA004B13B5 /* MXKGroupCellData.m */; }; F09E288E1AC1FEDA00C51E44 /* MXKImageView.m in Sources */ = {isa = PBXBuildFile; fileRef = F09E288B1AC1FEDA00C51E44 /* MXKImageView.m */; }; F09E288F1AC1FEDA00C51E44 /* MXKPieChartView.m in Sources */ = {isa = PBXBuildFile; fileRef = F09E288D1AC1FEDA00C51E44 /* MXKPieChartView.m */; }; - F0A8955E1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.m in Sources */ = {isa = PBXBuildFile; fileRef = F0A8955D1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.m */; }; F0AD3CC21B288C05002E0899 /* MXKInterleavedRecentsDataSource.m in Sources */ = {isa = PBXBuildFile; fileRef = F0AD3CBF1B288C05002E0899 /* MXKInterleavedRecentsDataSource.m */; }; F0AD3CC71B289441002E0899 /* MXKInterleavedRecentTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = F0AD3CC51B289441002E0899 /* MXKInterleavedRecentTableViewCell.m */; }; F0AD3CC81B289441002E0899 /* MXKInterleavedRecentTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = F0AD3CC61B289441002E0899 /* MXKInterleavedRecentTableViewCell.xib */; }; @@ -352,6 +352,9 @@ 392A579537BBF28A9436C420 /* Pods-MatrixKitSample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MatrixKitSample.release.xcconfig"; path = "Pods/Target Support Files/Pods-MatrixKitSample/Pods-MatrixKitSample.release.xcconfig"; sourceTree = ""; }; 3A1293A625801D9400F3474B /* MXKPreviewViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXKPreviewViewController.m; sourceTree = ""; }; 3A1293A725801D9400F3474B /* MXKPreviewViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXKPreviewViewController.h; sourceTree = ""; }; + 3AF85F9426FCC0B100A9E67B /* MXKViewControllerActivityHandling.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXKViewControllerActivityHandling.h; sourceTree = ""; }; + 3AF85F9526FCC35D00A9E67B /* MXKActivityHandlingViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MXKActivityHandlingViewController.h; sourceTree = ""; }; + 3AF85F9626FCC35D00A9E67B /* MXKActivityHandlingViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = MXKActivityHandlingViewController.m; sourceTree = ""; }; 550A36BC1DE484DB005C1647 /* EncryptedAttachmentsTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EncryptedAttachmentsTest.m; sourceTree = ""; }; 5537B7A941FDD5CF92368345 /* Pods-MatrixKitSamplePods-MatrixKitTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-MatrixKitSamplePods-MatrixKitTests.debug.xcconfig"; path = "Pods/Target Support Files/Pods-MatrixKitSamplePods-MatrixKitTests/Pods-MatrixKitSamplePods-MatrixKitTests.debug.xcconfig"; sourceTree = ""; }; 5891CE7965783A3890D40ED9 /* Pods_MatrixKitSamplePods_MatrixKitSample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_MatrixKitSamplePods_MatrixKitSample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -605,8 +608,6 @@ F09E288B1AC1FEDA00C51E44 /* MXKImageView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXKImageView.m; sourceTree = ""; }; F09E288C1AC1FEDA00C51E44 /* MXKPieChartView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXKPieChartView.h; sourceTree = ""; }; F09E288D1AC1FEDA00C51E44 /* MXKPieChartView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXKPieChartView.m; sourceTree = ""; }; - F0A8955C1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIScrollView+MatrixKit.h"; sourceTree = ""; }; - F0A8955D1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIScrollView+MatrixKit.m"; sourceTree = ""; }; F0AD3CBE1B288C05002E0899 /* MXKInterleavedRecentsDataSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXKInterleavedRecentsDataSource.h; sourceTree = ""; }; F0AD3CBF1B288C05002E0899 /* MXKInterleavedRecentsDataSource.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MXKInterleavedRecentsDataSource.m; sourceTree = ""; }; F0AD3CC41B289441002E0899 /* MXKInterleavedRecentTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MXKInterleavedRecentTableViewCell.h; sourceTree = ""; }; @@ -863,6 +864,9 @@ F0026B651C91EED1001D2C04 /* MXKWebViewViewController.m */, 3A1293A725801D9400F3474B /* MXKPreviewViewController.h */, 3A1293A625801D9400F3474B /* MXKPreviewViewController.m */, + 3AF85F9426FCC0B100A9E67B /* MXKViewControllerActivityHandling.h */, + 3AF85F9526FCC35D00A9E67B /* MXKActivityHandlingViewController.h */, + 3AF85F9626FCC35D00A9E67B /* MXKActivityHandlingViewController.m */, ); path = Controllers; sourceTree = ""; @@ -1314,8 +1318,6 @@ F07E18111ABC563900DE3766 /* Categories */ = { isa = PBXGroup; children = ( - F0A8955C1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.h */, - F0A8955D1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.m */, F04F78331F17A1B60039485E /* UIAlertController+MatrixKit.h */, F04F78341F17A1B60039485E /* UIAlertController+MatrixKit.m */, 32D9F4E021D54A08008007F2 /* UIViewController+MatrixKit.h */, @@ -1880,6 +1882,7 @@ F06E76811AF0FEB100980E5A /* MXKAuthenticationViewController.m in Sources */, F0F148C61AB31240005F5D4A /* MXKTools.m in Sources */, 3230A3721ACA835400CC57F5 /* MXKSampleJSQMessageMediaData.m in Sources */, + 3AF85F9726FCD75700A9E67B /* MXKActivityHandlingViewController.m in Sources */, F0868E0D1B18FC01004CBE80 /* MXKRoomCreationView.m in Sources */, CE14CA671E80122600E329A3 /* MXKAttachmentInteractionController.m in Sources */, B125D10C22D7414400570CA4 /* MXKVideoThumbnailGenerator.swift in Sources */, @@ -1966,7 +1969,6 @@ F0B0ECC41B14B16C005EB20D /* MXKRoomTitleView.m in Sources */, F09A66641FD8061D004B13B5 /* MXKSessionGroupsDataSource.m in Sources */, B12C56F22396D75500FAC6DE /* UITextView+MatrixKit.m in Sources */, - F0A8955E1F7A55DF00BD6C2A /* UIScrollView+MatrixKit.m in Sources */, F095E50F1B25899F009606CE /* MXKContactManager.m in Sources */, F09617C31DE881D800093E9D /* MXKEncryptionInfoView.m in Sources */, F0CE56EB1AA8BB5E003BE77A /* MXKSampleMainTableViewController.m in Sources */, @@ -2072,7 +2074,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 5537B7A941FDD5CF92368345 /* Pods-MatrixKitSamplePods-MatrixKitTests.debug.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = YES; @@ -2082,7 +2083,6 @@ ENABLE_TESTABILITY = YES; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = MatrixKitTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2097,7 +2097,6 @@ isa = XCBuildConfiguration; baseConfigurationReference = 1099FE41E4156DB223718DB2 /* Pods-MatrixKitSamplePods-MatrixKitTests.release.xcconfig */; buildSettings = { - ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; BUNDLE_LOADER = "$(TEST_HOST)"; CLANG_ANALYZER_NONNULL = YES; CLANG_ENABLE_MODULES = YES; @@ -2107,7 +2106,6 @@ DEVELOPMENT_TEAM = 7J4U792NQT; GCC_NO_COMMON_BLOCKS = YES; INFOPLIST_FILE = MatrixKitTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = org.matrix.MatrixKitTests; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -2164,7 +2162,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -2212,7 +2210,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -2230,7 +2228,6 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEVELOPMENT_TEAM = 7J4U792NQT; INFOPLIST_FILE = "$(SRCROOT)/Samples/MatrixKitSample/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.matrix.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_MODULE_NAME = MatrixKit; @@ -2251,7 +2248,6 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; DEVELOPMENT_TEAM = 7J4U792NQT; INFOPLIST_FILE = "$(SRCROOT)/Samples/MatrixKitSample/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 9.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "org.matrix.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_MODULE_NAME = MatrixKit; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/de.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/de.lproj/MatrixKit.strings index a49bd2a78..de55f3c6f 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/de.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/de.lproj/MatrixKit.strings @@ -225,10 +225,10 @@ "room_member_power_level_prompt" = "Du kannst diese Änderung nicht rückgangig machen, weil du dem Benutzer die gleiche Berechtigungsstufe gibst, die du selbst hast.\nBist du sicher?"; // Attachment "attachment_size_prompt" = "Möchtest du senden als:"; -"attachment_original" = "Originalgröße: %@"; -"attachment_small" = "Klein: %@"; -"attachment_medium" = "Mittel: %@"; -"attachment_large" = "Groß: %@"; +"attachment_original" = "Originalgröße (%@)"; +"attachment_small" = "Klein (~%@)"; +"attachment_medium" = "Mittel (~%@)"; +"attachment_large" = "Groß (~%@)"; "attachment_cancel_download" = "Herunterladen abbrechen?"; "attachment_cancel_upload" = "Hochladen abbrechen?"; "attachment_multiselection_size_prompt" = "Bilder senden als:"; @@ -492,3 +492,8 @@ "call_consulting_with_user" = "Bei %@ anfragen"; "microphone_access_not_granted_for_voice_message" = "%@ fehlt die Berechtigung, für Sprachnachrichten auf das Mikrofon zuzugreifen"; "message_reply_to_sender_sent_a_voice_message" = "hat eine Sprachnachricht gesendet."; +"attachment_size_prompt_title" = "Größe zum Senden"; +"attachment_large_with_resolution" = "Groß %@ (~%@)"; +"attachment_medium_with_resolution" = "Mittel %@ (~%@)"; +"attachment_small_with_resolution" = "Klein %@ (~%@)"; +"attachment_size_prompt_message" = "Du kannst dies in den Einstellungen ausschalten."; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings index da10707a0..5258f9cbb 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings @@ -240,7 +240,7 @@ // Room "room_please_select" = "Please select a room"; "room_error_join_failed_title" = "Failed to join room"; -"room_error_join_failed_empty_room" = "It is not currently possible to re-join an empty room."; +"room_error_join_failed_empty_room" = "It is not currently possible to join an empty room."; "room_error_name_edition_not_authorized" = "You are not authorized to edit this room name"; "room_error_topic_edition_not_authorized" = "You are not authorized to edit this room topic"; "room_error_cannot_load_timeline" = "Failed to load timeline"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/et.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/et.lproj/MatrixKit.strings index 6915e6118..cd40f35e6 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/et.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/et.lproj/MatrixKit.strings @@ -37,10 +37,10 @@ "room_member_power_level_prompt" = "Sa ei saa seda muudatust hiljem tagasi pöörata, sest annad teisele kasutajale samad õigused, mis sinul on.\nKas sa oled ikka kindel?"; // Attachment "attachment_size_prompt" = "Kas sa soovid faili saata:"; -"attachment_original" = "Tegelikus suuruses: %@"; -"attachment_small" = "Väiksena: %@"; -"attachment_medium" = "Keskmisena: %@"; -"attachment_large" = "Suurena: %@"; +"attachment_original" = "Tegelikus suuruses (%@)"; +"attachment_small" = "Väiksena (%@)"; +"attachment_medium" = "Keskmisena (%@)"; +"attachment_large" = "Suurena (%@)"; "attachment_cancel_download" = "Kas katkestame allalaadimise?"; "attachment_cancel_upload" = "Kas katkestame üleslaadimise?"; "attachment_multiselection_size_prompt" = "Kas sa soovid pilte saata:"; @@ -464,3 +464,8 @@ "e2e_passphrase_too_short" = "Salafraas on liiga lühike (pikkus peaks olema vähemalt %d tähemärki)"; "microphone_access_not_granted_for_voice_message" = "Häälsõnumite salvestamiseks on vajalik ligipääs mikrofonile, kuid %@'l pole selleks õigusi"; "message_reply_to_sender_sent_a_voice_message" = "saatis häälsõnumi."; +"attachment_large_with_resolution" = "Suurena %@ (~%@)"; +"attachment_medium_with_resolution" = "Keskmisena %@ (~%@)"; +"attachment_small_with_resolution" = "Väiksena %@ (~%@)"; +"attachment_size_prompt_message" = "Seadistustest saad määrata, et see funktsionaalsus pole kasutusel."; +"attachment_size_prompt_title" = "Saatmiseks kinnita meedia suurus"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/hu.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/hu.lproj/MatrixKit.strings index 4b294ec29..bf88aefdb 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/hu.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/hu.lproj/MatrixKit.strings @@ -197,10 +197,10 @@ "room_member_power_level_prompt" = "Valószínűleg nem fogod tudni visszavonni ezt a műveletet, mivel ugyanarra a szintre emeled a felhasználót mint amin te magad vagy.\nBiztos vagy benne?"; // Attachment "attachment_size_prompt" = "Hogy szeretnéd elküldeni:"; -"attachment_original" = "Jelenlegi méret: %@"; -"attachment_small" = "Kicsi: %@"; -"attachment_medium" = "Közepes: %@"; -"attachment_large" = "Nagy: %@"; +"attachment_original" = "Jelenlegi méret (%@)"; +"attachment_small" = "Kicsi (~%@)"; +"attachment_medium" = "Közepes (~%@)"; +"attachment_large" = "Nagy (~%@)"; "attachment_cancel_download" = "Megszakítod a letöltést?"; "attachment_cancel_upload" = "Megszakítod a feltöltést?"; "attachment_multiselection_size_prompt" = "Hogy szeretnéd elküldeni a képet:"; @@ -465,3 +465,8 @@ "e2e_passphrase_too_short" = "A jelmondat túl rövid (legalább %d karakter hosszúnak kell lennie)"; "microphone_access_not_granted_for_voice_message" = "Ha hangüzenetekhez a mikrofonhoz szükséges a hozzáférés, de %@ nem rendelkezik a használatához szükséges engedéllyel"; "message_reply_to_sender_sent_a_voice_message" = "hang üzenet elküldve."; +"attachment_large_with_resolution" = "Nagy %@ (~%@)"; +"attachment_medium_with_resolution" = "Közepes %@ (~%@)"; +"attachment_small_with_resolution" = "Kicsi %@ (~%@)"; +"attachment_size_prompt_message" = "Ezt a beállításokban kikapcsolhatod."; +"attachment_size_prompt_title" = "Méret megerősítése küldéshez"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/it.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/it.lproj/MatrixKit.strings index 891772dd0..4ce1a097b 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/it.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/it.lproj/MatrixKit.strings @@ -208,10 +208,10 @@ "room_member_power_level_prompt" = "Non potrai annullare questa modifica perché stai innalzando i permessi dell'utente al tuo stesso livello di accesso.\nSei sicuro?"; // Attachment "attachment_size_prompt" = "Vuoi inviare come:"; -"attachment_original" = "Originale: %@"; -"attachment_small" = "Piccolo: %@"; -"attachment_medium" = "Medio: %@"; -"attachment_large" = "Grande: %@"; +"attachment_original" = "Dim. effettiva (%@)"; +"attachment_small" = "Piccolo (~%@)"; +"attachment_medium" = "Medio (~%@)"; +"attachment_large" = "Grande (~%@)"; "attachment_cancel_download" = "Interrompi scaricamento?"; "attachment_cancel_upload" = "Interrompi caricamento?"; "attachment_multiselection_size_prompt" = "Vuoi inviare le immagini come:"; @@ -465,3 +465,8 @@ "e2e_passphrase_too_short" = "Password troppo corta (deve avere almeno %d caratteri)"; "microphone_access_not_granted_for_voice_message" = "I messaggi vocali hanno bisogno dell'accesso al microfono, ma %@ non ha il permesso di usarlo"; "message_reply_to_sender_sent_a_voice_message" = "inviato un messaggio vocale."; +"attachment_large_with_resolution" = "Grande %@ (~%@)"; +"attachment_medium_with_resolution" = "Medio %@ (~%@)"; +"attachment_small_with_resolution" = "Piccolo %@ (~%@)"; +"attachment_size_prompt_message" = "Puoi disattivarlo nelle impostazioni."; +"attachment_size_prompt_title" = "Conferma dimensione da inviare"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/nl.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/nl.lproj/MatrixKit.strings index 968672ab1..caea3f98c 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/nl.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/nl.lproj/MatrixKit.strings @@ -207,10 +207,10 @@ "room_member_power_level_prompt" = "U kunt deze veranderingen niet ongedaan maken aangezien u de gebruiker tot hetzelfde niveau als uzelf promoveert.\nWeet u het zeker?"; // Attachment "attachment_size_prompt" = "Wilt u het versturen als:"; -"attachment_original" = "Werkelijke grootte: %@"; -"attachment_small" = "Klein: %@"; -"attachment_medium" = "Medium: %@"; -"attachment_large" = "Groot: %@"; +"attachment_original" = "Werkelijke grootte (%@)"; +"attachment_small" = "Klein (~%@)"; +"attachment_medium" = "Middel (~%@)"; +"attachment_large" = "Groot (~%@)"; "attachment_cancel_download" = "Download annuleren?"; "attachment_cancel_upload" = "Upload annuleren?"; "attachment_multiselection_size_prompt" = "Wilt u afbeeldingen versturen als:"; @@ -247,7 +247,7 @@ "not_supported_yet" = "Nog niet ondersteund"; "default" = "standaard"; "private" = "Privé"; -"public" = "Openbaar"; +"public" = "Publiek"; "power_level" = "Machtsniveau"; "network_error_not_reachable" = "Controleer uw netwerkverbinding"; "user_id_placeholder" = "bv: @jan:thuisserver"; @@ -495,10 +495,10 @@ "notice_room_history_visible_to_members_from_invited_point_for_dm" = "%@ heeft toekomstige berichten voor iedereen zichtbaar gemaakt vanaf het moment dat zij zijn uitgenodigd."; "notice_room_history_visible_to_members_for_dm" = "%@ heeft toekomstige berichten voor alle gespreksleden zichtbaar gemaakt."; "notice_room_aliases_for_dm" = "De bijnamen zijn: %@"; -"notice_room_join_rule_public_by_you_for_dm" = "U maakte dit openbaar."; -"notice_room_join_rule_public_by_you" = "U heeft het gesprek openbaar gemaakt."; -"notice_room_join_rule_public_for_dm" = "%@ maakte dit openbaar."; -"notice_room_join_rule_public" = "%@ heeft het gesprek openbaar gemaakt."; +"notice_room_join_rule_public_by_you_for_dm" = "U maakte dit publiekelijk."; +"notice_room_join_rule_public_by_you" = "U heeft de kamer publiekelijk gemaakt."; +"notice_room_join_rule_public_for_dm" = "%@ maakte dit publiekelijk."; +"notice_room_join_rule_public" = "%@ heeft de kamer publiekelijk gemaakt."; "notice_room_created_for_dm" = "%@ is toegetreden."; "notice_room_power_level_intro_for_dm" = "Het machtsniveau van de gespreksleden is:"; "notice_room_join_rule_invite_by_you_for_dm" = "U maakte dit gesprek alleen op uitnodiging."; @@ -526,3 +526,8 @@ "e2e_passphrase_too_short" = "Wachtwoord is te kort (hij moet minimaal %d tekens lang zijn)"; "microphone_access_not_granted_for_voice_message" = "Spraakberichten vereisen toegang tot de Microfoon maar %@ heeft geen toestemming om het te gebruiken"; "message_reply_to_sender_sent_a_voice_message" = "heeft een spraakbericht gestuurd."; +"attachment_large_with_resolution" = "Groot %@ (~%@)"; +"attachment_medium_with_resolution" = "Middel %@ (~%@)"; +"attachment_small_with_resolution" = "Klein %@ (~%@)"; +"attachment_size_prompt_message" = "U kunt dit uitzetten in uw instellingen."; +"attachment_size_prompt_title" = "Bevestig de afmeting om te versturen"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/pl.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/pl.lproj/MatrixKit.strings index 560ea4192..87bb251de 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/pl.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/pl.lproj/MatrixKit.strings @@ -414,10 +414,10 @@ // Contacts "contact_mx_users" = "Użytkownicy Matrix"; "attachment_e2e_keys_file_prompt" = "Ten plik zawiera klucze szyfrowania wyeksportowane z klienta Matrix.\nChcesz przejrzeć zawartość pliku czy zaimportować zawarte w nim klucze?"; -"attachment_large" = "Duży: %@"; -"attachment_medium" = "Średni: %@"; -"attachment_small" = "Mały: %@"; -"attachment_original" = "Rzeczywisty rozmiar: %@"; +"attachment_large" = "Duży (%@)"; +"attachment_medium" = "Średni (%@)"; +"attachment_small" = "Mały (%@)"; +"attachment_original" = "Rzeczywisty rozmiar (%@)"; // Attachment "attachment_size_prompt" = "Czy chcesz wysłać jako:"; @@ -491,3 +491,8 @@ "e2e_passphrase_too_short" = "Hasło jest zbyt krótkie (Hasło musi składać się z co najmniej %d znaków)"; "microphone_access_not_granted_for_voice_message" = "Wiadomości głosowe wymagają dostępu do mikrofonu ale %@ nie posiada uprawnień do użycia go"; "message_reply_to_sender_sent_a_voice_message" = "wysłał(-a) wiadomość głosową."; +"attachment_large_with_resolution" = "Duży %@ (~%@)"; +"attachment_medium_with_resolution" = "Średni %@ (~%@)"; +"attachment_small_with_resolution" = "Mały %@ (~%@)"; +"attachment_size_prompt_message" = "Możesz to wyłączyć w ustawieniach."; +"attachment_size_prompt_title" = "Potwierdź rozmiar, który chcesz wysłać"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/pt_BR.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/pt_BR.lproj/MatrixKit.strings index 7595f19f4..71fca6689 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/pt_BR.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/pt_BR.lproj/MatrixKit.strings @@ -210,10 +210,10 @@ "room_member_power_level_prompt" = "Você não vai ser capaz de desfazer esta mudança como você está promovendo a/o usuária(o) para ter o mesmo nível de poder que você mesma(o).\nVocê tem certeza?"; // Attachment "attachment_size_prompt" = "Você quer enviar como:"; -"attachment_original" = "Tamanho de Verdade: %@"; -"attachment_small" = "Pequeno: %@"; -"attachment_medium" = "Médio: %@"; -"attachment_large" = "Grande: %@"; +"attachment_original" = "Tamanho de Verdade (%@)"; +"attachment_small" = "Pequeno (~%@)"; +"attachment_medium" = "Médio (~%@)"; +"attachment_large" = "Grande (~%@)"; "attachment_cancel_download" = "Cancelar o download?"; "attachment_cancel_upload" = "Cancelar o upload?"; "attachment_multiselection_size_prompt" = "Você quer enviar imagens como:"; @@ -465,3 +465,8 @@ "e2e_passphrase_too_short" = "Frasepasse curta demais (Ela deve ser a um mínimo %d caracteres em comprimento)"; "microphone_access_not_granted_for_voice_message" = "Mensagens de voz requerem acesso ao Microfone mas %@ não tem permissão para usá-lo"; "message_reply_to_sender_sent_a_voice_message" = "enviou uma mensagem de voz."; +"attachment_large_with_resolution" = "Grande %@ (~%@)"; +"attachment_medium_with_resolution" = "Médio %@ (~%@)"; +"attachment_small_with_resolution" = "Pequeno %@ (~%@)"; +"attachment_size_prompt_message" = "Você pode desligar isto em configurações."; +"attachment_size_prompt_title" = "Confirmar tamanho para enviar"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/ru.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/ru.lproj/MatrixKit.strings index 61323dc0c..784f2f60d 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/ru.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/ru.lproj/MatrixKit.strings @@ -237,10 +237,10 @@ "room_no_conference_call_in_encrypted_rooms" = "Групповые вызовы не поддерживаются в зашифрованных комнатах"; // Attachment "attachment_size_prompt" = "Вы хотите отправить как:"; -"attachment_original" = "Фактический размер: %@"; -"attachment_small" = "Маленький: %@"; -"attachment_medium" = "Средний: %@"; -"attachment_large" = "Большой: %@"; +"attachment_original" = "Фактический размер (%@)"; +"attachment_small" = "Маленький (%@)"; +"attachment_medium" = "Средний (%@)"; +"attachment_large" = "Большой (%@)"; "attachment_cancel_download" = "Отменить загрузку?"; "attachment_cancel_upload" = "Отменить отправку?"; "attachment_multiselection_size_prompt" = "Вы хотите отправить изображения как:"; @@ -365,10 +365,10 @@ "notice_in_reply_to" = "В ответ на"; "error_common_message" = "Произошла ошибка. Пожалуйста, повторите попытку позже."; // Reply to message -"message_reply_to_sender_sent_an_image" = "отправил изображение."; -"message_reply_to_sender_sent_a_video" = "отправил видео."; -"message_reply_to_sender_sent_an_audio_file" = "отправил аудиофайл."; -"message_reply_to_sender_sent_a_file" = "отправил файл."; +"message_reply_to_sender_sent_an_image" = "отправил(а) изображение."; +"message_reply_to_sender_sent_a_video" = "отправил(а) видео."; +"message_reply_to_sender_sent_an_audio_file" = "отправил(а) аудиофайл."; +"message_reply_to_sender_sent_a_file" = "отправил(а) файл."; "message_reply_to_message_to_reply_to_prefix" = "В ответ на"; "login_error_resource_limit_exceeded_title" = "Превышен лимит ресурса"; "login_error_resource_limit_exceeded_contact_button" = "Связаться с администратором"; @@ -464,4 +464,9 @@ "call_ringing" = "Звонок…"; "microphone_access_not_granted_for_voice_message" = "Голосовые сообщения требуют доступа к микрофону, но у %@ нет разрешения на его использование"; "e2e_passphrase_too_short" = "Слишком короткая парольная фраза (Длина парольной фразы должна быть не менее %d символов)"; -"message_reply_to_sender_sent_a_voice_message" = "отправил голосовое сообщение."; +"message_reply_to_sender_sent_a_voice_message" = "отправил(а) голосовое сообщение."; +"attachment_large_with_resolution" = "Большой %@ (~%@)"; +"attachment_medium_with_resolution" = "Средний %@ (~%@)"; +"attachment_small_with_resolution" = "Маленький %@ (~%@)"; +"attachment_size_prompt_message" = "Это можно отключить в настройках."; +"attachment_size_prompt_title" = "Подтвердите размер для отправки"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/sq.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/sq.lproj/MatrixKit.strings index 34eda559c..feb7b03f0 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/sq.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/sq.lproj/MatrixKit.strings @@ -465,3 +465,8 @@ "e2e_passphrase_too_short" = "Frazëkalim shumë i shkurtër (Duhet të jetë e pakta %d shenja i gjatë)"; "microphone_access_not_granted_for_voice_message" = "Mesazhet zanorë lypin përdorim të Mikrofonit, por %@ s’ka leje përdorimi të tij"; "message_reply_to_sender_sent_a_voice_message" = "dërgoi një mesazh zanor."; +"attachment_large_with_resolution" = "E madhe %@ (~%@)"; +"attachment_medium_with_resolution" = "Mesatare %@ (~%@)"; +"attachment_small_with_resolution" = "E vogël %@ (~%@)"; +"attachment_size_prompt_message" = "Këtë mund ta çaktivizoni te rregullimet."; +"attachment_size_prompt_title" = "Ripohoni madhësi për dërgim"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings index 3f95365e4..1aa1a8ee2 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/sv.lproj/MatrixKit.strings @@ -207,10 +207,10 @@ "room_member_power_level_prompt" = "Du kommer inte att kunna ångra denna ändring eftersom du befordrar användaren till samma behörighetsnivå som dig själv.\nÄr du säker?"; // Attachment "attachment_size_prompt" = "Vill du skicka som:"; -"attachment_original" = "Faktisk storlek: %@"; -"attachment_small" = "Liten: %@"; -"attachment_medium" = "Mellan: %@"; -"attachment_large" = "Stor: %@"; +"attachment_original" = "Faktisk storlek (%@)"; +"attachment_small" = "Liten (%@)"; +"attachment_medium" = "Mellan (%@)"; +"attachment_large" = "Stor (%@)"; "attachment_cancel_download" = "Avbryt nedladdningen?"; "attachment_cancel_upload" = "Avbryt uppladdningen?"; "attachment_multiselection_size_prompt" = "Vill du skicka bilder som:"; @@ -464,3 +464,8 @@ "e2e_passphrase_too_short" = "Lösenfras för kort (den måste vara minst %d tecken långt)"; "microphone_access_not_granted_for_voice_message" = "Röstmeddelanden kräver åtkomst till mikrofonen, men %@ har inte behörighet att använda den"; "message_reply_to_sender_sent_a_voice_message" = "skickade ett röstmeddelande."; +"attachment_large_with_resolution" = "Stor %@ (~%@)"; +"attachment_medium_with_resolution" = "Mellan %@ (~%@)"; +"attachment_small_with_resolution" = "Liten %@ (~%@)"; +"attachment_size_prompt_message" = "Du kan stänga av detta i inställningarna."; +"attachment_size_prompt_title" = "Bekräfta storlek att skicka"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/uk.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/uk.lproj/MatrixKit.strings index a7a9720e0..4edae8d1e 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/uk.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/uk.lproj/MatrixKit.strings @@ -58,8 +58,8 @@ "start_chat" = "Почати бесіду"; "set_admin" = "Призначити адміністратора"; "set_moderator" = "Призначити модератора"; -"set_default_power_level" = "Скинути рівень прав"; -"set_power_level" = "Визначити рівень прав"; +"set_default_power_level" = "Скинути рівень повноважень"; +"set_power_level" = "Визначити рівень повноважень"; "submit_code" = "Надіслати код"; "dismiss" = "Відхилити"; "abort" = "Перервати"; @@ -98,8 +98,8 @@ "login_identity_server_title" = "URL-адреса сервера ідентифікації:"; "login_home_server_info" = "Ваш домашній сервер зберігає всі ваші розмови та дані облікового запису"; "login_home_server_title" = "URL-адреса домашнього сервера:"; -"notice_room_power_level_intro_for_dm" = "Рівні доступу учасників:"; -"notice_room_power_level_intro" = "Рівні доступу учасників кімнати:"; +"notice_room_power_level_intro_for_dm" = "Рівні повноважень учасників:"; +"notice_room_power_level_intro" = "Рівні повноважень учасників кімнати:"; "notice_room_join_rule_public_by_you_for_dm" = "Ви дозволяєте доступ всім."; "notice_room_join_rule_public_by_you" = "Ви дозволяєте доступ до кімнати всім."; "notice_room_join_rule_public_for_dm" = "%@ дозволяє доступ всім."; @@ -200,7 +200,7 @@ "ssl_homeserver_url" = "URL-адреса домашнього сервера: %@"; "user_id_placeholder" = "наприклад: @bob:homeserver"; "network_error_not_reachable" = "Перевірте під'єднання до мережі"; -"power_level" = "Рівень доступу"; +"power_level" = "Рівень повноважень"; "public" = "Загальнодоступний"; "private" = "Приватний"; "default" = "типово"; @@ -280,10 +280,10 @@ "attachment_multiselection_size_prompt" = "Хочете надіслати зображення як:"; "attachment_cancel_upload" = "Скасувати вивантаження?"; "attachment_cancel_download" = "Скасувати завантаження?"; -"attachment_large" = "Великий: %@"; -"attachment_medium" = "Середній: %@"; -"attachment_small" = "Маленький: %@"; -"attachment_original" = "Справжній розмір: %@"; +"attachment_large" = "Великий (~%@)"; +"attachment_medium" = "Середній (~%@)"; +"attachment_small" = "Маленький (~%@)"; +"attachment_original" = "Справжній розмір (%@)"; // Attachment "attachment_size_prompt" = "Бажаєте надіслати:"; @@ -341,3 +341,14 @@ "notice_error_unexpected_event" = "Неочікувана подія"; "notice_error_unsupported_event" = "Непідтримувана подія"; "notice_invalid_attachment" = "неприпустиме вкладення"; +"notice_room_history_visible_to_members_from_joined_point_for_dm" = "%@ робить майбутню історію повідомлень видимою всім від часу їхнього приєднання."; +"notice_room_history_visible_to_members_from_joined_point" = "%@ робить майбутню історію кімнати видимою всім учасникам кімнати від часу їхнього приєднання."; +"notice_room_history_visible_to_members_from_invited_point_for_dm" = "%@ робить майбутню історію повідомлень видимою всім від часу їхнього запрошення."; +"notice_room_history_visible_to_members_from_invited_point" = "%@ робить майбутню історію кімнати видимою усім учасникам кімнати від часу їхнього запрошення."; +"notice_room_history_visible_to_members_for_dm" = "%@ робить майбутню історію повідомлень видимою усім учасникам кімнати."; +"notice_room_history_visible_to_members" = "%@ робить майбутню історію кімнати видимою усім учасникам кімнати."; +"notice_room_history_visible_to_anyone" = "%@ робить майбутню історію кімнати видимою усім."; +"notice_redaction" = "%@ редагує подію (id: %@)"; +"notice_feedback" = "Подія відгуку (id: %@): %@"; +"notice_room_related_groups" = "Групи пов'язані з цією кімнатою: %@"; +"notice_room_power_level_acting_requirement" = "Мінімальний рівень повноважень користувача для виконання дії:"; diff --git a/MatrixKit/Assets/MatrixKitAssets.bundle/zh_Hans.lproj/MatrixKit.strings b/MatrixKit/Assets/MatrixKitAssets.bundle/zh_Hans.lproj/MatrixKit.strings index c96109922..4c2676c22 100644 --- a/MatrixKit/Assets/MatrixKitAssets.bundle/zh_Hans.lproj/MatrixKit.strings +++ b/MatrixKit/Assets/MatrixKitAssets.bundle/zh_Hans.lproj/MatrixKit.strings @@ -160,9 +160,9 @@ "room_error_cannot_load_timeline" = "时间线加载失败"; "room_error_timeline_event_not_found_title" = "时间线位置加载失败"; "room_left" = "你离开了聊天室"; -"attachment_small" = "小:%@"; -"attachment_medium" = "中:%@"; -"attachment_large" = "大:%@"; +"attachment_small" = "小 (~%@)"; +"attachment_medium" = "中 (~%@)"; +"attachment_large" = "大 (~%@)"; "attachment_cancel_download" = "是否取消下载?"; "attachment_cancel_upload" = "是否取消上传?"; "attachment_e2e_keys_import" = "导入…"; @@ -338,7 +338,7 @@ "room_member_power_level_prompt" = "该用户将被提升至与您一样的权限级别,所以此操作将无法撤销。\n您确定吗?"; // Attachment "attachment_size_prompt" = "发送为:"; -"attachment_original" = "实际大小:%@"; +"attachment_original" = "实际大小 (%@)"; "attachment_multiselection_size_prompt" = "发送图片为:"; "attachment_multiselection_original" = "实际大小"; "attachment_e2e_keys_file_prompt" = "此文件含有 Matrix 客户端导出的密钥。\n您想要查看文件内容还是导入密钥?"; @@ -466,3 +466,8 @@ "e2e_passphrase_too_short" = "密码口令太短 (长度至少为 %d 个字符)"; "microphone_access_not_granted_for_voice_message" = "语音消息需要访问麦克风,但 %@ 无权使用它"; "message_reply_to_sender_sent_a_voice_message" = "发送了一条语音消息。"; +"attachment_large_with_resolution" = "大 %@ (~%@)"; +"attachment_medium_with_resolution" = "中等 %@ (~%@)"; +"attachment_small_with_resolution" = "小 %@ (~%@)"; +"attachment_size_prompt_message" = "你可以在设置中关闭这个。"; +"attachment_size_prompt_title" = "确认要发送的大小"; diff --git a/MatrixKit/Categories/UIScrollView+MatrixKit.h b/MatrixKit/Categories/UIScrollView+MatrixKit.h deleted file mode 100644 index 75dad1f54..000000000 --- a/MatrixKit/Categories/UIScrollView+MatrixKit.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - Copyright 2017 Vector Creations Ltd - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import - -/** - Define a `UIScrollView` category at MatrixKit level to handle the adjusted content inset which is not defined before iOS 11. - */ -@interface UIScrollView (MatrixKit) - -/** - Get the total adjustment in a scroll view. - The insets derived from the content insets and the safe area of the scroll view. - */ -@property(nonatomic, readonly) UIEdgeInsets mxk_adjustedContentInset; - -@end diff --git a/MatrixKit/Categories/UIScrollView+MatrixKit.m b/MatrixKit/Categories/UIScrollView+MatrixKit.m deleted file mode 100644 index 59d0ca8a8..000000000 --- a/MatrixKit/Categories/UIScrollView+MatrixKit.m +++ /dev/null @@ -1,33 +0,0 @@ -/* - Copyright 2017 Vector Creations Ltd - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - */ - -#import "UIScrollView+MatrixKit.h" - -@implementation UIScrollView (MatrixKit) - -- (UIEdgeInsets)mxk_adjustedContentInset -{ - if (@available(iOS 11.0, *)) - { - return self.adjustedContentInset; - } - else - { - return self.contentInset; - } -} - -@end diff --git a/MatrixKit/Controllers/MXKActivityHandlingViewController.h b/MatrixKit/Controllers/MXKActivityHandlingViewController.h new file mode 100644 index 000000000..400b9cc3b --- /dev/null +++ b/MatrixKit/Controllers/MXKActivityHandlingViewController.h @@ -0,0 +1,26 @@ +// +// Copyright 2020 The Matrix.org Foundation C.I.C +// +// 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 +#import "MXKViewControllerActivityHandling.h" + +NS_ASSUME_NONNULL_BEGIN + +@interface MXKActivityHandlingViewController : UIViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/MatrixKit/Controllers/MXKActivityHandlingViewController.m b/MatrixKit/Controllers/MXKActivityHandlingViewController.m new file mode 100644 index 000000000..5628c7396 --- /dev/null +++ b/MatrixKit/Controllers/MXKActivityHandlingViewController.m @@ -0,0 +1,83 @@ +// +// Copyright 2020 The Matrix.org Foundation C.I.C +// +// 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 "MXKActivityHandlingViewController.h" + +@interface MXKActivityHandlingViewController () + +@end + +@implementation MXKActivityHandlingViewController +@synthesize activityIndicator; + +#pragma mark - + +- (void)viewDidLoad +{ + [super viewDidLoad]; + + // Add default activity indicator + activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; + activityIndicator.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0]; + activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; + activityIndicator.hidesWhenStopped = YES; + + CGRect frame = activityIndicator.frame; + frame.size.width += 30; + frame.size.height += 30; + activityIndicator.bounds = frame; + [activityIndicator.layer setCornerRadius:5]; + + activityIndicator.center = self.view.center; + [self.view addSubview:activityIndicator]; +} + +- (void)dealloc +{ + if (activityIndicator) + { + [activityIndicator removeFromSuperview]; + activityIndicator = nil; + } +} + +#pragma mark - Activity indicator + +- (void)startActivityIndicator +{ + if (activityIndicator) + { + [self.view bringSubviewToFront:activityIndicator]; + [activityIndicator startAnimating]; + + // Show the loading wheel after a delay so that if the caller calls stopActivityIndicator + // in a short future, the loading wheel will not be displayed to the end user. + activityIndicator.alpha = 0; + [UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ + self->activityIndicator.alpha = 1; + } completion:^(BOOL finished) + { + }]; + } +} + +- (void)stopActivityIndicator +{ + [activityIndicator stopAnimating]; +} + + +@end diff --git a/MatrixKit/Controllers/MXKAuthenticationViewController.h b/MatrixKit/Controllers/MXKAuthenticationViewController.h index b15356955..49a0edd93 100644 --- a/MatrixKit/Controllers/MXKAuthenticationViewController.h +++ b/MatrixKit/Controllers/MXKAuthenticationViewController.h @@ -286,6 +286,10 @@ /// @param parameters Login parameters - (void)loginWithParameters:(NSDictionary*)parameters; +/// Create an account with the given credentials +/// @param credentials Account credentials +- (void)createAccountWithCredentials:(MXCredentials *)credentials; + #pragma mark - Authentication Fallback /** @@ -293,5 +297,15 @@ */ - (void)showAuthenticationFallBackView; +#pragma mark - Device rehydration + +/** + Call this method at an appropriate time to attempt rehydrating from an existing dehydrated device + @param keyData Secret key data + @param credentials Account credentials + */ + +- (void)attemptDeviceRehydrationWithKeyData:(NSData *)keyData credentials:(MXCredentials *)credentials; + @end diff --git a/MatrixKit/Controllers/MXKAuthenticationViewController.m b/MatrixKit/Controllers/MXKAuthenticationViewController.m index 825ce648f..c6a76e327 100644 --- a/MatrixKit/Controllers/MXKAuthenticationViewController.m +++ b/MatrixKit/Controllers/MXKAuthenticationViewController.m @@ -26,6 +26,7 @@ #import "NSBundle+MatrixKit.h" #import +#import "MXKAppSettings.h" @interface MXKAuthenticationViewController () { @@ -1423,15 +1424,8 @@ - (void)onSuccessfulLogin:(MXCredentials*)credentials { credentials.identityServer = _identityServerTextField.text; } - MXKAccount *account = [[MXKAccount alloc] initWithCredentials:credentials]; - account.identityServerURL = credentials.identityServer; - [[MXKAccountManager sharedManager] addAccount:account andOpenSession:YES]; - - if (_delegate) - { - [_delegate authenticationViewController:self didLogWithUserId:credentials.userId]; - } + [self createAccountWithCredentials:credentials]; } } @@ -1442,6 +1436,82 @@ - (MXHTTPOperation *)currentHttpOperation #pragma mark - Privates +// Hook point for triggering device rehydration in subclasses +// Avoid cycles by using a separate private method do to the actual work +- (void)createAccountWithCredentials:(MXCredentials *)credentials +{ + [self _createAccountWithCredentials:credentials]; +} + +- (void)attemptDeviceRehydrationWithKeyData:(NSData *)keyData + credentials:(MXCredentials *)credentials +{ + [self attemptDeviceRehydrationWithKeyData:keyData + credentials:credentials + retry:YES]; +} + +- (void)attemptDeviceRehydrationWithKeyData:(NSData *)keyData + credentials:(MXCredentials *)credentials + retry:(BOOL)retry +{ + MXLogDebug(@"[MXKAuthenticationViewController] attemptDeviceRehydration: starting device rehydration"); + + if (keyData == nil) + { + MXLogError(@"[MXKAuthenticationViewController] attemptDeviceRehydration: no key provided for device rehydration"); + [self _createAccountWithCredentials:credentials]; + return; + } + + MXRestClient *mxRestClient = [[MXRestClient alloc] initWithCredentials:credentials andOnUnrecognizedCertificateBlock:^BOOL(NSData *certificate) { + return NO; + }]; + + MXWeakify(self); + [[MXKAccountManager sharedManager].dehydrationService rehydrateDeviceWithMatrixRestClient:mxRestClient dehydrationKey:keyData success:^(NSString * deviceId) { + MXStrongifyAndReturnIfNil(self); + + if (deviceId) + { + MXLogDebug(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device %@ rehydrated successfully.", deviceId); + credentials.deviceId = deviceId; + } + else + { + MXLogDebug(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device rehydration has been canceled."); + } + + [self _createAccountWithCredentials:credentials]; + } failure:^(NSError *error) { + MXStrongifyAndReturnIfNil(self); + + if (retry) + { + MXLogError(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device rehydration failed due to error: %@. Retrying", error); + [self attemptDeviceRehydrationWithKeyData:keyData credentials:credentials retry:NO]; + return; + } + + MXLogError(@"[MXKAuthenticationViewController] attemptDeviceRehydration: device rehydration failed due to error: %@", error); + + [self _createAccountWithCredentials:credentials]; + }]; +} + +- (void)_createAccountWithCredentials:(MXCredentials *)credentials +{ + MXKAccount *account = [[MXKAccount alloc] initWithCredentials:credentials]; + account.identityServerURL = credentials.identityServer; + + [[MXKAccountManager sharedManager] addAccount:account andOpenSession:YES]; + + if (_delegate) + { + [_delegate authenticationViewController:self didLogWithUserId:credentials.userId]; + } +} + - (NSString *)deviceDisplayName { if (_deviceDisplayName) diff --git a/MatrixKit/Controllers/MXKContactListViewController.m b/MatrixKit/Controllers/MXKContactListViewController.m index ed246df8b..712b9a8a1 100644 --- a/MatrixKit/Controllers/MXKContactListViewController.m +++ b/MatrixKit/Controllers/MXKContactListViewController.m @@ -19,7 +19,6 @@ #import "MXKSectionedContacts.h" #import "NSBundle+MatrixKit.h" -#import "UIScrollView+MatrixKit.h" @interface MXKContactListViewController () { @@ -150,7 +149,7 @@ - (void)scrollToTop // stop any scrolling effect [UIView setAnimationsEnabled:NO]; // before scrolling to the tableview top - self.tableView.contentOffset = CGPointMake(-self.tableView.mxk_adjustedContentInset.left, -self.tableView.mxk_adjustedContentInset.top); + self.tableView.contentOffset = CGPointMake(-self.tableView.adjustedContentInset.left, -self.tableView.adjustedContentInset.top); [UIView setAnimationsEnabled:YES]; } diff --git a/MatrixKit/Controllers/MXKCountryPickerViewController.m b/MatrixKit/Controllers/MXKCountryPickerViewController.m index f1b0e9bff..d52da9570 100644 --- a/MatrixKit/Controllers/MXKCountryPickerViewController.m +++ b/MatrixKit/Controllers/MXKCountryPickerViewController.m @@ -117,9 +117,7 @@ - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - if (@available(iOS 11.0, *)) { - self.navigationItem.hidesSearchBarWhenScrolling = YES; - } + self.navigationItem.hidesSearchBarWhenScrolling = YES; } #pragma mark - @@ -156,12 +154,10 @@ - (void)setupSearchController searchController.dimsBackgroundDuringPresentation = NO; searchController.hidesNavigationBarDuringPresentation = NO; searchController.searchResultsUpdater = self; - - if (@available(iOS 11.0, *)) { - self.navigationItem.searchController = searchController; - // Make the search bar visible on first view appearance - self.navigationItem.hidesSearchBarWhenScrolling = NO; - } + + self.navigationItem.searchController = searchController; + // Make the search bar visible on first view appearance + self.navigationItem.hidesSearchBarWhenScrolling = NO; self.definesPresentationContext = YES; diff --git a/MatrixKit/Controllers/MXKGroupListViewController.m b/MatrixKit/Controllers/MXKGroupListViewController.m index 1f32a78ba..1d1e533d1 100644 --- a/MatrixKit/Controllers/MXKGroupListViewController.m +++ b/MatrixKit/Controllers/MXKGroupListViewController.m @@ -19,8 +19,6 @@ #import "MXKGroupTableViewCell.h" #import "MXKTableViewHeaderFooterWithLabel.h" -#import "UIScrollView+MatrixKit.h" - @interface MXKGroupListViewController () { /** @@ -468,7 +466,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == _groupsTableView) { - if (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top == 0) + if (scrollView.contentOffset.y + scrollView.adjustedContentInset.top == 0) { [self managePullToKick:scrollView]; } @@ -566,7 +564,7 @@ - (void)detectPullToKick:(UIScrollView *)scrollView if (!reconnectingView) { // detect if the user scrolls over the tableview top - restartConnection = (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top < -128); + restartConnection = (scrollView.contentOffset.y + scrollView.adjustedContentInset.top < -128); if (restartConnection) { diff --git a/MatrixKit/Controllers/MXKLanguagePickerViewController.m b/MatrixKit/Controllers/MXKLanguagePickerViewController.m index ec2d294a3..0b070bf8b 100644 --- a/MatrixKit/Controllers/MXKLanguagePickerViewController.m +++ b/MatrixKit/Controllers/MXKLanguagePickerViewController.m @@ -150,9 +150,7 @@ - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - if (@available(iOS 11.0, *)) { - self.navigationItem.hidesSearchBarWhenScrolling = YES; - } + self.navigationItem.hidesSearchBarWhenScrolling = YES; } #pragma mark - Private @@ -164,14 +162,12 @@ - (void)setupSearchController searchController.dimsBackgroundDuringPresentation = NO; searchController.hidesNavigationBarDuringPresentation = NO; searchController.searchResultsUpdater = self; - - if (@available(iOS 11.0, *)) { - // Search bar is hidden for the moment, uncomment following line to enable it. - // TODO: Enable it once we have enough translations to fill pages and pages -// self.navigationItem.searchController = searchController; - // Make the search bar visible on first view appearance - self.navigationItem.hidesSearchBarWhenScrolling = NO; - } + + // Search bar is hidden for the moment, uncomment following line to enable it. + // TODO: Enable it once we have enough translations to fill pages and pages + // self.navigationItem.searchController = searchController; + // Make the search bar visible on first view appearance + self.navigationItem.hidesSearchBarWhenScrolling = NO; self.definesPresentationContext = YES; diff --git a/MatrixKit/Controllers/MXKRecentListViewController.h b/MatrixKit/Controllers/MXKRecentListViewController.h index 348973dda..39ff5de4c 100644 --- a/MatrixKit/Controllers/MXKRecentListViewController.h +++ b/MatrixKit/Controllers/MXKRecentListViewController.h @@ -36,6 +36,14 @@ limitations under the License. */ - (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectRoom:(NSString*)roomId inMatrixSession:(MXSession*)mxSession; +/** + Tells the delegate that the user selected a suggested room. + + @param recentListViewController the `MXKRecentListViewController` instance. + @param childInfo the `MXSpaceChildInfo` instance that describes the selected room. + */ +-(void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo; + @end diff --git a/MatrixKit/Controllers/MXKRecentListViewController.m b/MatrixKit/Controllers/MXKRecentListViewController.m index f51a11b16..6406c1b78 100644 --- a/MatrixKit/Controllers/MXKRecentListViewController.m +++ b/MatrixKit/Controllers/MXKRecentListViewController.m @@ -21,8 +21,7 @@ #import "MXKInterleavedRecentsDataSource.h" #import "MXKInterleavedRecentTableViewCell.h" - -#import "UIScrollView+MatrixKit.h" +#import @interface MXKRecentListViewController () { @@ -469,7 +468,14 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath if ([cellData conformsToProtocol:@protocol(MXKRecentCellDataStoring)]) { id recentCellData = (id)cellData; - [_delegate recentListViewController:self didSelectRoom:recentCellData.roomSummary.roomId inMatrixSession:recentCellData.roomSummary.room.mxSession]; + if (recentCellData.isSuggestedRoom) + { + [_delegate recentListViewController:self didSelectSuggestedRoom:recentCellData.spaceChildInfo]; + } + else + { + [_delegate recentListViewController:self didSelectRoom:recentCellData.roomSummary.roomId inMatrixSession:recentCellData.roomSummary.mxSession]; + } } } } @@ -511,7 +517,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (scrollView == _recentsTableView) { - if (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top == 0) + if (scrollView.contentOffset.y + scrollView.adjustedContentInset.top == 0) { [self managePullToKick:scrollView]; } @@ -605,7 +611,7 @@ - (void)detectPullToKick:(UIScrollView *)scrollView if (!reconnectingView) { // detect if the user scrolls over the tableview top - restartConnection = (scrollView.contentOffset.y + scrollView.mxk_adjustedContentInset.top < -128); + restartConnection = (scrollView.contentOffset.y + scrollView.adjustedContentInset.top < -128); if (restartConnection) { diff --git a/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h b/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h index c2976f897..9d74a2ce0 100644 --- a/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h +++ b/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.h @@ -129,6 +129,11 @@ typedef enum : NSUInteger */ @property (nonatomic) BOOL enableVoipCall; +/** + Enable leave this room. YES by default + */ +@property (nonatomic) BOOL enableLeave; + /** Tell whether an action is already in progress. */ diff --git a/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.m b/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.m index 1a962d56b..b4ed69bfa 100644 --- a/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.m +++ b/MatrixKit/Controllers/MXKRoomMemberDetailsViewController.m @@ -67,6 +67,7 @@ - (void)finalizeInit [super finalizeInit]; actionsArray = [[NSMutableArray alloc] init]; + _enableLeave = YES; } - (void)viewDidLoad @@ -181,6 +182,16 @@ - (void)setEnableVoipCall:(BOOL)enableVoipCall } } +- (void)setEnableLeave:(BOOL)enableLeave +{ + if (_enableLeave != enableLeave) + { + _enableLeave = enableLeave; + + [self updateMemberInfo]; + } +} + - (IBAction)onActionButtonPressed:(id)sender { if ([sender isKindOfClass:[UIButton class]]) @@ -644,7 +655,10 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger // Consider the case of the user himself if ([_mxRoomMember.userId isEqualToString:self.mainSession.myUser.userId]) { - [actionsArray addObject:@(MXKRoomMemberDetailsActionLeave)]; + if (_enableLeave) + { + [actionsArray addObject:@(MXKRoomMemberDetailsActionLeave)]; + } if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomPowerLevels]) { diff --git a/MatrixKit/Controllers/MXKRoomMemberListViewController.m b/MatrixKit/Controllers/MXKRoomMemberListViewController.m index 62385b7ad..2c33a9be7 100644 --- a/MatrixKit/Controllers/MXKRoomMemberListViewController.m +++ b/MatrixKit/Controllers/MXKRoomMemberListViewController.m @@ -23,7 +23,6 @@ #import "MXKConstants.h" #import "NSBundle+MatrixKit.h" -#import "UIScrollView+MatrixKit.h" @interface MXKRoomMemberListViewController () { @@ -379,7 +378,7 @@ - (void)displayList:(MXKRoomMemberListDataSource *)listDataSource - (void)scrollToTop:(BOOL)animated { - [self.membersTableView setContentOffset:CGPointMake(-self.membersTableView.mxk_adjustedContentInset.left, -self.membersTableView.mxk_adjustedContentInset.top) animated:animated]; + [self.membersTableView setContentOffset:CGPointMake(-self.membersTableView.adjustedContentInset.left, -self.membersTableView.adjustedContentInset.top) animated:animated]; } #pragma mark - MXKDataSourceDelegate diff --git a/MatrixKit/Controllers/MXKRoomViewController.h b/MatrixKit/Controllers/MXKRoomViewController.h index cc1fb60b6..718542260 100644 --- a/MatrixKit/Controllers/MXKRoomViewController.h +++ b/MatrixKit/Controllers/MXKRoomViewController.h @@ -27,6 +27,13 @@ #import "MXKAttachmentsViewController.h" #import "MXKAttachmentAnimator.h" +typedef NS_ENUM(NSUInteger, MXKRoomViewControllerJoinRoomResult) { + MXKRoomViewControllerJoinRoomResultSuccess, + MXKRoomViewControllerJoinRoomResultFailureRoomEmpty, + MXKRoomViewControllerJoinRoomResultFailureJoinInProgress, + MXKRoomViewControllerJoinRoomResultFailureGeneric +}; + /** This view controller displays messages of a room. Only one matrix session is handled by this view controller. */ @@ -280,7 +287,7 @@ @param completion the block to execute at the end of the operation. You may specify nil for this parameter. */ -- (void)joinRoom:(void(^)(BOOL succeed))completion; +- (void)joinRoom:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion; /** Join a room with a room id or an alias. @@ -296,7 +303,10 @@ @param completion the block to execute at the end of the operation. You may specify nil for this parameter. */ -- (void)joinRoomWithRoomIdOrAlias:(NSString*)roomIdOrAlias viaServers:(NSArray*)viaServers andSignUrl:(NSString*)signUrl completion:(void(^)(BOOL succeed))completion; +- (void)joinRoomWithRoomIdOrAlias:(NSString*)roomIdOrAlias + viaServers:(NSArray*)viaServers + andSignUrl:(NSString*)signUrl + completion:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion; /** Update view controller appearance when the user is about to leave the displayed room. diff --git a/MatrixKit/Controllers/MXKRoomViewController.m b/MatrixKit/Controllers/MXKRoomViewController.m index 9d76b538a..2db94fdae 100644 --- a/MatrixKit/Controllers/MXKRoomViewController.m +++ b/MatrixKit/Controllers/MXKRoomViewController.m @@ -49,7 +49,6 @@ #import "MXKEncryptionKeysImportView.h" #import "NSBundle+MatrixKit.h" -#import "UIScrollView+MatrixKit.h" #import "MXKSlashCommands.h" #import "MXKSwiftHeader.h" @@ -366,12 +365,9 @@ - (void)viewWillAppear:(BOOL)animated - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; - - if (@available(iOS 11.0, *)) - { - // Remove the rounded bottom unsafe area of the iPhone X - _bubblesTableViewBottomConstraint.constant += self.view.safeAreaInsets.bottom; - } + + // Remove the rounded bottom unsafe area of the iPhone X + _bubblesTableViewBottomConstraint.constant += self.view.safeAreaInsets.bottom; if (_saveProgressTextInput && roomDataSource) { @@ -533,18 +529,15 @@ - (void)setKeyboardHeight:(CGFloat)keyboardHeight // Update constraints _roomInputToolbarContainerBottomConstraint.constant = inputToolbarViewBottomConst; _bubblesTableViewBottomConstraint.constant = inputToolbarViewBottomConst + _roomInputToolbarContainerHeightConstraint.constant + _roomActivitiesContainerHeightConstraint.constant; - - if (@available(iOS 11.0, *)) - { - // Remove the rounded bottom unsafe area of the iPhone X - _bubblesTableViewBottomConstraint.constant += self.view.safeAreaInsets.bottom; - } + + // Remove the rounded bottom unsafe area of the iPhone X + _bubblesTableViewBottomConstraint.constant += self.view.safeAreaInsets.bottom; // Invalidate the current layout to take into account the new constraints in the next update cycle. [self.view setNeedsLayout]; // Compute the visible area (tableview + toolbar) at the end of animation - CGFloat visibleArea = self.view.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.top - keyboardHeight; + CGFloat visibleArea = self.view.frame.size.height - _bubblesTableView.adjustedContentInset.top - keyboardHeight; // Deduce max height of the message text input by considering the minimum height of the table view. inputToolbarView.maxHeight = visibleArea - MXKROOMVIEWCONTROLLER_MESSAGES_TABLE_MINIMUM_HEIGHT; @@ -675,7 +668,7 @@ - (void)updateMessageTextViewFrame if (!self.keyboardView) { // Compute the visible area (tableview + toolbar) - CGFloat visibleArea = self.view.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.top; + CGFloat visibleArea = self.view.frame.size.height - _bubblesTableView.adjustedContentInset.top; // Deduce max height of the message text input by considering the minimum height of the table view. inputToolbarView.maxHeight = visibleArea - MXKROOMVIEWCONTROLLER_MESSAGES_TABLE_MINIMUM_HEIGHT; } @@ -685,13 +678,8 @@ - (CGFloat)tableViewSafeAreaWidth { CGFloat safeAreaInsetsWidth; - if (@available(iOS 11.0, *)) - { - // Take safe area into account - safeAreaInsetsWidth = self.bubblesTableView.safeAreaInsets.left + self.bubblesTableView.safeAreaInsets.right; - } else { - safeAreaInsetsWidth = 0; - } + // Take safe area into account + safeAreaInsetsWidth = self.bubblesTableView.safeAreaInsets.left + self.bubblesTableView.safeAreaInsets.right; return self.bubblesTableView.frame.size.width - safeAreaInsetsWidth; } @@ -886,147 +874,125 @@ - (void)onTimelineError:(NSNotification *)notif } } -- (void)joinRoom:(void(^)(BOOL succeed))completion +- (void)joinRoom:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion { - // Check whether a join request is not already running - if (!joinRoomRequest) + if (joinRoomRequest != nil) { - [self startActivityIndicator]; + if (completion) + { + completion(MXKRoomViewControllerJoinRoomResultFailureJoinInProgress); + } + return; + } + + [self startActivityIndicator]; + + joinRoomRequest = [roomDataSource.room join:^{ - joinRoomRequest = [roomDataSource.room join:^{ - - self->joinRoomRequest = nil; - [self stopActivityIndicator]; - - [self triggerInitialBackPagination]; - - if (completion) - { - completion(YES); - } - - } failure:^(NSError *error) { - - MXLogDebug(@"[MXKRoomVC] Failed to join room (%@)", self->roomDataSource.room.summary.displayname); - - self->joinRoomRequest = nil; - [self stopActivityIndicator]; - - // Show the error to the end user - MXWeakify(self); - NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey]; - if ([msg isEqualToString:@"No known servers"]) - { - // minging kludge until https://matrix.org/jira/browse/SYN-678 is fixed - // 'Error when trying to join an empty room should be more explicit' - msg = [NSBundle mxk_localizedStringForKey:@"room_error_join_failed_empty_room"]; - } - - [self->currentAlert dismissViewControllerAnimated:NO completion:nil]; - - self->currentAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"room_error_join_failed_title"] message:msg preferredStyle:UIAlertControllerStyleAlert]; - - [self->currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - MXStrongifyAndReturnIfNil(self); - self->currentAlert = nil; - - }]]; - - [self presentViewController:self->currentAlert animated:YES completion:nil]; + self->joinRoomRequest = nil; + [self stopActivityIndicator]; + + [self triggerInitialBackPagination]; + + if (completion) + { + completion(MXKRoomViewControllerJoinRoomResultSuccess); + } + + } failure:^(NSError *error) { + MXLogDebug(@"[MXKRoomVC] Failed to join room (%@)", self->roomDataSource.room.summary.displayname); + [self processRoomJoinFailureWithError:error completion:completion]; + }]; +} + +- (void)joinRoomWithRoomIdOrAlias:(NSString*)roomIdOrAlias + viaServers:(NSArray*)viaServers + andSignUrl:(NSString*)signUrl + completion:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion +{ + if (joinRoomRequest != nil) + { + if (completion) + { + completion(MXKRoomViewControllerJoinRoomResultFailureJoinInProgress); + } + + return; + } + + [self startActivityIndicator]; + + void (^success)(MXRoom *room) = ^(MXRoom *room) { + + self->joinRoomRequest = nil; + [self stopActivityIndicator]; + + // The room is now part of the user's room + MXKRoomDataSourceManager *roomDataSourceManager = [MXKRoomDataSourceManager sharedManagerForMatrixSession:self.mainSession]; + + [roomDataSourceManager roomDataSourceForRoom:room.roomId create:YES onComplete:^(MXKRoomDataSource *newRoomDataSource) { + // And can be displayed + [self displayRoom:newRoomDataSource]; if (completion) { - completion(NO); + completion(MXKRoomViewControllerJoinRoomResultSuccess); } - }]; + }; + + void (^failure)(NSError *error) = ^(NSError *error) { + MXLogDebug(@"[MXKRoomVC] Failed to join room (%@)", roomIdOrAlias); + [self processRoomJoinFailureWithError:error completion:completion]; + }; + + // Does the join need to be validated before? + if (signUrl) + { + joinRoomRequest = [self.mainSession joinRoom:roomIdOrAlias viaServers:viaServers withSignUrl:signUrl success:success failure:failure]; } - else if (completion) + else { - completion (NO); + joinRoomRequest = [self.mainSession joinRoom:roomIdOrAlias viaServers:viaServers success:success failure:failure]; } } -- (void)joinRoomWithRoomIdOrAlias:(NSString*)roomIdOrAlias viaServers:(NSArray*)viaServers andSignUrl:(NSString*)signUrl completion:(void(^)(BOOL succeed))completion +- (void)processRoomJoinFailureWithError:(NSError *)error completion:(void(^)(MXKRoomViewControllerJoinRoomResult result))completion { - // Check whether a join request is not already running - if (!joinRoomRequest) + self->joinRoomRequest = nil; + [self stopActivityIndicator]; + + // Show the error to the end user + NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey]; + + // FIXME: We should hide this inside the SDK and expose it as a domain specific error + BOOL isRoomEmpty = [msg isEqualToString:@"No known servers"]; + if (isRoomEmpty) { - [self startActivityIndicator]; - - void (^success)(MXRoom *room) = ^(MXRoom *room) { - - self->joinRoomRequest = nil; - [self stopActivityIndicator]; - - // The room is now part of the user's room - MXKRoomDataSourceManager *roomDataSourceManager = [MXKRoomDataSourceManager sharedManagerForMatrixSession:self.mainSession]; - - [roomDataSourceManager roomDataSourceForRoom:room.roomId create:YES onComplete:^(MXKRoomDataSource *newRoomDataSource) { - // And can be displayed - [self displayRoom:newRoomDataSource]; - - if (completion) - { - completion(YES); - } - }]; - }; - - void (^failure)(NSError *error) = ^(NSError *error) { - - MXLogDebug(@"[MXKRoomVC] Failed to join room (%@)", roomIdOrAlias); - - self->joinRoomRequest = nil; - [self stopActivityIndicator]; - - // Show the error to the end user - NSString *msg = [error.userInfo valueForKey:NSLocalizedDescriptionKey]; - if ([msg isEqualToString:@"No known servers"]) - { - // minging kludge until https://matrix.org/jira/browse/SYN-678 is fixed - // 'Error when trying to join an empty room should be more explicit' - msg = [NSBundle mxk_localizedStringForKey:@"room_error_join_failed_empty_room"]; - } - MXWeakify(self); - [self->currentAlert dismissViewControllerAnimated:NO completion:nil]; - - self->currentAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"room_error_join_failed_title"] message:msg preferredStyle:UIAlertControllerStyleAlert]; - - [self->currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - - MXStrongifyAndReturnIfNil(self); - self->currentAlert = nil; - - }]]; - - [self presentViewController:self->currentAlert animated:YES completion:nil]; - - if (completion) - { - completion(NO); - } - }; - - // Does the join need to be validated before? - if (signUrl) - { - joinRoomRequest = [self.mainSession joinRoom:roomIdOrAlias viaServers:viaServers withSignUrl:signUrl success:success failure:failure]; - } - else + // minging kludge until https://matrix.org/jira/browse/SYN-678 is fixed + // 'Error when trying to join an empty room should be more explicit' + msg = [NSBundle mxk_localizedStringForKey:@"room_error_join_failed_empty_room"]; + } + + MXWeakify(self); + [self->currentAlert dismissViewControllerAnimated:NO completion:nil]; + + self->currentAlert = [UIAlertController alertControllerWithTitle:[NSBundle mxk_localizedStringForKey:@"room_error_join_failed_title"] message:msg preferredStyle:UIAlertControllerStyleAlert]; + + [self->currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"ok"] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { + + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + if (completion) { - joinRoomRequest = [self.mainSession joinRoom:roomIdOrAlias viaServers:viaServers success:success failure:failure]; + completion((isRoomEmpty ? MXKRoomViewControllerJoinRoomResultFailureRoomEmpty : MXKRoomViewControllerJoinRoomResultFailureGeneric)); } - } - else if (completion) - { - completion (NO); - } + }]]; + + [self presentViewController:self->currentAlert animated:YES completion:nil]; } - (void)leaveRoomOnEvent:(MXEvent*)event @@ -1110,54 +1076,8 @@ - (void)setRoomTitleViewClass:(Class)roomTitleViewClass titleView.delegate = self; - if (@available(iOS 11.0, *)) - { - // Define directly the navigation titleView with the custom title view instance. Do not use anymore a container. - self.navigationItem.titleView = titleView; - } - else - { - if (!_roomTitleViewContainer) - { - _roomTitleViewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 600, 40)]; - self.navigationItem.titleView = _roomTitleViewContainer; - } - - // Add the title view and define edge constraints - titleView.translatesAutoresizingMaskIntoConstraints = NO; - [_roomTitleViewContainer addSubview:titleView]; - NSLayoutConstraint *bottomConstraint = [NSLayoutConstraint constraintWithItem:_roomTitleViewContainer - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:titleView - attribute:NSLayoutAttributeBottom - multiplier:1.0f - constant:0.0f]; - NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:_roomTitleViewContainer - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:titleView - attribute:NSLayoutAttributeTop - multiplier:1.0f - constant:0.0f]; - NSLayoutConstraint *leadingConstraint = [NSLayoutConstraint constraintWithItem:_roomTitleViewContainer - attribute:NSLayoutAttributeLeading - relatedBy:NSLayoutRelationEqual - toItem:titleView - attribute:NSLayoutAttributeLeading - multiplier:1.0f - constant:0.0f]; - NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:_roomTitleViewContainer - attribute:NSLayoutAttributeTrailing - relatedBy:NSLayoutRelationEqual - toItem:titleView - attribute:NSLayoutAttributeTrailing - multiplier:1.0f - constant:0.0f]; - - [NSLayoutConstraint activateConstraints:@[topConstraint, bottomConstraint, leadingConstraint, trailingConstraint]]; - [_roomTitleViewContainer setNeedsUpdateConstraints]; - } + // Define directly the navigation titleView with the custom title view instance. Do not use anymore a container. + self.navigationItem.titleView = titleView; [self updateViewControllerAppearanceOnRoomDataSourceState]; } @@ -1774,7 +1694,7 @@ - (BOOL)isBubblesTableScrollViewAtTheBottom { // Check whether the most recent message is visible. // Compute the max vertical position visible according to contentOffset - CGFloat maxPositionY = _bubblesTableView.contentOffset.y + (_bubblesTableView.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.bottom); + CGFloat maxPositionY = _bubblesTableView.contentOffset.y + (_bubblesTableView.frame.size.height - _bubblesTableView.adjustedContentInset.bottom); // Be a bit less retrictive, consider the table view at the bottom even if the most recent message is partially hidden maxPositionY += 44; BOOL isScrolledToBottom = (maxPositionY >= _bubblesTableView.contentSize.height); @@ -1793,10 +1713,10 @@ - (void)scrollBubblesTableViewToBottomAnimated:(BOOL)animated { if (_bubblesTableView.contentSize.height) { - CGFloat visibleHeight = _bubblesTableView.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.top - _bubblesTableView.mxk_adjustedContentInset.bottom; + CGFloat visibleHeight = _bubblesTableView.frame.size.height - _bubblesTableView.adjustedContentInset.top - _bubblesTableView.adjustedContentInset.bottom; if (visibleHeight < _bubblesTableView.contentSize.height) { - CGFloat wantedOffsetY = _bubblesTableView.contentSize.height - visibleHeight - _bubblesTableView.mxk_adjustedContentInset.top; + CGFloat wantedOffsetY = _bubblesTableView.contentSize.height - visibleHeight - _bubblesTableView.adjustedContentInset.top; CGFloat currentOffsetY = _bubblesTableView.contentOffset.y; if (wantedOffsetY != currentOffsetY) { @@ -1814,7 +1734,7 @@ - (void)scrollBubblesTableViewToBottomAnimated:(BOOL)animated } else { - [self setBubbleTableViewContentOffset:CGPointMake(0, -_bubblesTableView.mxk_adjustedContentInset.top) animated:animated]; + [self setBubbleTableViewContentOffset:CGPointMake(0, -_bubblesTableView.adjustedContentInset.top) animated:animated]; } shouldScrollToBottomOnTableRefresh = NO; @@ -1948,8 +1868,8 @@ - (void)triggerInitialBackPagination UITableViewCell *cell = [self->_bubblesTableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0]]; CGPoint contentOffset = self->_bubblesTableView.contentOffset; - CGFloat firstVisibleContentRowOffset = self->_bubblesTableView.contentOffset.y + self->_bubblesTableView.mxk_adjustedContentInset.top; - CGFloat lastVisibleContentRowOffset = self->_bubblesTableView.frame.size.height - self->_bubblesTableView.mxk_adjustedContentInset.bottom; + CGFloat firstVisibleContentRowOffset = self->_bubblesTableView.contentOffset.y + self->_bubblesTableView.adjustedContentInset.top; + CGFloat lastVisibleContentRowOffset = self->_bubblesTableView.frame.size.height - self->_bubblesTableView.adjustedContentInset.bottom; CGFloat localPositionOfEvent = 0.0; @@ -2405,7 +2325,7 @@ - (BOOL)reloadBubblesTable:(BOOL)useBottomAnchor invalidateBubblesCellDataCache: } // Compute the offset of the content displayed at the bottom. - CGFloat contentBottomOffsetY = _bubblesTableView.contentOffset.y + (_bubblesTableView.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.bottom); + CGFloat contentBottomOffsetY = _bubblesTableView.contentOffset.y + (_bubblesTableView.frame.size.height - _bubblesTableView.adjustedContentInset.bottom); if (contentBottomOffsetY > _bubblesTableView.contentSize.height) { contentBottomOffsetY = _bubblesTableView.contentSize.height; @@ -2415,13 +2335,13 @@ - (BOOL)reloadBubblesTable:(BOOL)useBottomAnchor invalidateBubblesCellDataCache: if ((contentBottomOffsetY <= eventTopPosition ) || (eventBottomPosition < contentBottomOffsetY)) { // Compute the top content offset to display again this event at the table bottom - CGFloat contentOffsetY = eventBottomPosition - (_bubblesTableView.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.bottom); + CGFloat contentOffsetY = eventBottomPosition - (_bubblesTableView.frame.size.height - _bubblesTableView.adjustedContentInset.bottom); // Check if there are enought data to fill the top - if (contentOffsetY < -_bubblesTableView.mxk_adjustedContentInset.top) + if (contentOffsetY < -_bubblesTableView.adjustedContentInset.top) { // Scroll to the top - contentOffsetY = -_bubblesTableView.mxk_adjustedContentInset.top; + contentOffsetY = -_bubblesTableView.adjustedContentInset.top; } CGPoint contentOffset = _bubblesTableView.contentOffset; @@ -2457,7 +2377,7 @@ - (void)updateCurrentEventIdAtTableBottom:(BOOL)acknowledge if (!isSizeTransitionInProgress && !self.isBubbleTableViewDisplayInTransition) { // Compute the content offset corresponding to the line displayed at the table bottom (just above the toolbar). - CGFloat contentBottomOffsetY = _bubblesTableView.contentOffset.y + (_bubblesTableView.frame.size.height - _bubblesTableView.mxk_adjustedContentInset.bottom); + CGFloat contentBottomOffsetY = _bubblesTableView.contentOffset.y + (_bubblesTableView.frame.size.height - _bubblesTableView.adjustedContentInset.bottom); if (contentBottomOffsetY > _bubblesTableView.contentSize.height) { contentBottomOffsetY = _bubblesTableView.contentSize.height; @@ -3298,7 +3218,7 @@ - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoi if (scrollView == _bubblesTableView) { // Detect top bounce - if (scrollView.contentOffset.y < -scrollView.mxk_adjustedContentInset.top) + if (scrollView.contentOffset.y < -scrollView.adjustedContentInset.top) { // Shall we add back pagination spinner? if (isPaginationInProgress && !backPaginationActivityView) @@ -3380,7 +3300,7 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView // when the content size if smaller that the frame // scrollViewDidEndDecelerating is not called // so test it when the content offset goes back to the screen top. - if ((scrollView.contentSize.height < scrollView.frame.size.height) && (-scrollView.contentOffset.y == scrollView.mxk_adjustedContentInset.top)) + if ((scrollView.contentSize.height < scrollView.frame.size.height) && (-scrollView.contentOffset.y == scrollView.adjustedContentInset.top)) { [self managePullToKick:scrollView]; } @@ -3727,7 +3647,7 @@ - (void)showAttachmentInCell:(UITableViewCell*)cell // "Initializing" closedAttachmentEventId so it is equal to openedAttachmentEventId at the beginning self.closedAttachmentEventId = self.openedAttachmentEventId; - + if (@available(iOS 13.0, *)) { attachmentsViewer.modalPresentationStyle = UIModalPresentationFullScreen; diff --git a/MatrixKit/Controllers/MXKSearchViewController.m b/MatrixKit/Controllers/MXKSearchViewController.m index 9a600c879..5f8dd30b3 100644 --- a/MatrixKit/Controllers/MXKSearchViewController.m +++ b/MatrixKit/Controllers/MXKSearchViewController.m @@ -19,7 +19,6 @@ #import "MXKSearchTableViewCell.h" #import "NSBundle+MatrixKit.h" -#import "UIScrollView+MatrixKit.h" @interface MXKSearchViewController () { @@ -418,10 +417,10 @@ - (void)scrollToBottomAnimated:(BOOL)animated { if (_searchTableView.contentSize.height) { - CGFloat visibleHeight = _searchTableView.frame.size.height - _searchTableView.mxk_adjustedContentInset.top - _searchTableView.mxk_adjustedContentInset.bottom; + CGFloat visibleHeight = _searchTableView.frame.size.height - _searchTableView.adjustedContentInset.top - _searchTableView.adjustedContentInset.bottom; if (visibleHeight < _searchTableView.contentSize.height) { - CGFloat wantedOffsetY = _searchTableView.contentSize.height - visibleHeight - _searchTableView.mxk_adjustedContentInset.top; + CGFloat wantedOffsetY = _searchTableView.contentSize.height - visibleHeight - _searchTableView.adjustedContentInset.top; CGFloat currentOffsetY = _searchTableView.contentOffset.y; if (wantedOffsetY != currentOffsetY) { @@ -430,7 +429,7 @@ - (void)scrollToBottomAnimated:(BOOL)animated } else { - _searchTableView.contentOffset = CGPointMake(0, - _searchTableView.mxk_adjustedContentInset.top); + _searchTableView.contentOffset = CGPointMake(0, - _searchTableView.adjustedContentInset.top); } } } diff --git a/MatrixKit/Controllers/MXKTableViewController.m b/MatrixKit/Controllers/MXKTableViewController.m index be5fad602..383672543 100644 --- a/MatrixKit/Controllers/MXKTableViewController.m +++ b/MatrixKit/Controllers/MXKTableViewController.m @@ -18,7 +18,6 @@ #import "MXKTableViewController.h" #import "UIViewController+MatrixKit.h" -#import "UIScrollView+MatrixKit.h" #import "MXSession+MatrixKit.h" @interface MXKTableViewController () @@ -509,7 +508,7 @@ - (void)startActivityIndicator { // Keep centering the loading wheel CGPoint center = self.view.center; - center.y += self.tableView.contentOffset.y - self.tableView.mxk_adjustedContentInset.top; + center.y += self.tableView.contentOffset.y - self.tableView.adjustedContentInset.top; activityIndicator.center = center; [self.view bringSubviewToFront:activityIndicator]; diff --git a/MatrixKit/Controllers/MXKViewController.h b/MatrixKit/Controllers/MXKViewController.h index d43b858aa..e75d42e11 100644 --- a/MatrixKit/Controllers/MXKViewController.h +++ b/MatrixKit/Controllers/MXKViewController.h @@ -15,6 +15,7 @@ */ #import "MXKViewControllerHandling.h" +#import "MXKActivityHandlingViewController.h" /** MXKViewController extends UIViewController to handle requirements for @@ -23,7 +24,7 @@ This class provides some methods to ease keyboard handling. */ -@interface MXKViewController : UIViewController +@interface MXKViewController : MXKActivityHandlingViewController #pragma mark - Keyboard handling diff --git a/MatrixKit/Controllers/MXKViewController.m b/MatrixKit/Controllers/MXKViewController.m index e1ba6571f..a4e559b4c 100644 --- a/MatrixKit/Controllers/MXKViewController.m +++ b/MatrixKit/Controllers/MXKViewController.m @@ -40,7 +40,7 @@ @implementation MXKViewController @synthesize defaultBarTintColor, enableBarTintColorStatusChange; @synthesize barTitleColor; @synthesize mainSession; -@synthesize activityIndicator, rageShakeManager; +@synthesize rageShakeManager; @synthesize childViewControllers; #pragma mark - @@ -81,35 +81,6 @@ - (void)finalizeInit #pragma mark - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - // Add default activity indicator - activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite]; - activityIndicator.backgroundColor = [UIColor colorWithRed:0.8 green:0.8 blue:0.8 alpha:1.0]; - activityIndicator.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin | UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; - activityIndicator.hidesWhenStopped = YES; - - CGRect frame = activityIndicator.frame; - frame.size.width += 30; - frame.size.height += 30; - activityIndicator.bounds = frame; - [activityIndicator.layer setCornerRadius:5]; - - activityIndicator.center = self.view.center; - [self.view addSubview:activityIndicator]; -} - -- (void)dealloc -{ - if (activityIndicator) - { - [activityIndicator removeFromSuperview]; - activityIndicator = nil; - } -} - - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; @@ -139,7 +110,7 @@ - (void)viewWillDisappear:(BOOL)animated [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXSessionStateDidChangeNotification object:nil]; - [activityIndicator stopAnimating]; + [self.activityIndicator stopAnimating]; if (self.rageShakeManager) { @@ -258,10 +229,10 @@ - (void)setView:(UIView *)view [super setView:view]; // Keep the activity indicator (if any) - if (activityIndicator) + if (self.activityIndicator) { - activityIndicator.center = self.view.center; - [self.view addSubview:activityIndicator]; + self.activityIndicator.center = self.view.center; + [self.view addSubview:self.activityIndicator]; } } @@ -521,24 +492,6 @@ - (void)onMatrixSessionChange #pragma mark - Activity indicator -- (void)startActivityIndicator -{ - if (activityIndicator) - { - [self.view bringSubviewToFront:activityIndicator]; - [activityIndicator startAnimating]; - - // Show the loading wheel after a delay so that if the caller calls stopActivityIndicator - // in a short future, the loading wheel will not be displayed to the end user. - activityIndicator.alpha = 0; - [UIView animateWithDuration:0.3 delay:0.3 options:UIViewAnimationOptionBeginFromCurrentState animations:^{ - self->activityIndicator.alpha = 1; - } completion:^(BOOL finished) - { - }]; - } -} - - (void)stopActivityIndicator { // Check whether all conditions are satisfied before stopping loading wheel @@ -552,7 +505,7 @@ - (void)stopActivityIndicator } if (!isActivityInProgress) { - [activityIndicator stopAnimating]; + [super stopActivityIndicator]; } } diff --git a/MatrixKit/Controllers/MXKViewControllerActivityHandling.h b/MatrixKit/Controllers/MXKViewControllerActivityHandling.h new file mode 100644 index 000000000..299071230 --- /dev/null +++ b/MatrixKit/Controllers/MXKViewControllerActivityHandling.h @@ -0,0 +1,50 @@ +// +// Copyright 2021 The Matrix.org Foundation C.I.C +// +// 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. +// + +#ifndef MXKViewControllerActivityHandling_h +#define MXKViewControllerActivityHandling_h + +/** + `MXKViewControllerActivityHandling` defines a protocol to handle requirements for + all matrixKit view controllers and table view controllers. + + It manages the following points: + - stop/start activity indicator according to the state of the associated matrix sessions. + */ +@protocol MXKViewControllerActivityHandling + +/** + Activity indicator view. + By default this activity indicator is centered inside the view controller view. It automatically + starts if `shouldShowActivityIndicator `returns true for the session. + It is stopped on other states. + Set nil to disable activity indicator animation. + */ +@property (nonatomic) UIActivityIndicatorView *activityIndicator; + +/** + Bring the activity indicator to the front and start it. + */ +- (void)startActivityIndicator; + +/** + Stop the activity indicator if all conditions are satisfied. + */ +- (void)stopActivityIndicator; + +@end + +#endif /* MXKViewControllerActivityHandling_h */ diff --git a/MatrixKit/Controllers/MXKViewControllerHandling.h b/MatrixKit/Controllers/MXKViewControllerHandling.h index f71d2d9c0..ee9143508 100644 --- a/MatrixKit/Controllers/MXKViewControllerHandling.h +++ b/MatrixKit/Controllers/MXKViewControllerHandling.h @@ -19,6 +19,7 @@ #import #import "MXKResponderRageShaking.h" +#import "MXKViewControllerActivityHandling.h" /** `MXKViewControllerHandling` defines a protocol to handle requirements for @@ -30,7 +31,7 @@ - update view appearance on matrix session state change. - support rage shake mechanism (depend on `rageShakeManager` property). */ -@protocol MXKViewControllerHandling +@protocol MXKViewControllerHandling /** The default navigation bar tint color (nil by default). @@ -73,15 +74,6 @@ */ @property (nonatomic) id rageShakeManager; -/** - Activity indicator view. - By default this activity indicator is centered inside the view controller view. It automatically - starts if `shouldShowActivityIndicator `returns true for the session. - It is stopped on other states. - Set nil to disable activity indicator animation. - */ -@property (nonatomic) UIActivityIndicatorView *activityIndicator; - /** Called during UIViewController initialization to set the default properties values (see [initWithNibName:bundle:] and [initWithCoder:]). @@ -152,15 +144,5 @@ */ - (void)destroy; -/** - Bring the activity indicator to the front and start it. - */ -- (void)startActivityIndicator; - -/** - Stop the activity indicator if all conditions are satisfied. - */ -- (void)stopActivityIndicator; - @end diff --git a/MatrixKit/MatrixKit.h b/MatrixKit/MatrixKit.h index be9cb0442..a121072bd 100644 --- a/MatrixKit/MatrixKit.h +++ b/MatrixKit/MatrixKit.h @@ -29,7 +29,6 @@ #import "NSBundle+MatrixKit.h" #import "NSBundle+MXKLanguage.h" #import "UIAlertController+MatrixKit.h" -#import "UIScrollView+MatrixKit.h" #import "UIViewController+MatrixKit.h" #import "MXKEventFormatter.h" diff --git a/MatrixKit/MatrixKitVersion.m b/MatrixKit/MatrixKitVersion.m index 42123f28f..e8ac192e2 100644 --- a/MatrixKit/MatrixKitVersion.m +++ b/MatrixKit/MatrixKitVersion.m @@ -16,4 +16,4 @@ #import -NSString *const MatrixKitVersion = @"0.16.1"; +NSString *const MatrixKitVersion = @"0.16.2"; diff --git a/MatrixKit/Models/Account/MXKAccount.h b/MatrixKit/Models/Account/MXKAccount.h index 019e3c595..1357dd39e 100644 --- a/MatrixKit/Models/Account/MXKAccount.h +++ b/MatrixKit/Models/Account/MXKAccount.h @@ -431,4 +431,11 @@ typedef BOOL (^MXKAccountOnCertificateChange)(MXKAccount *mxAccount, NSData *cer */ - (void)supportLazyLoadOfRoomMembers:(void (^)(BOOL supportLazyLoadOfRoomMembers))completion; +/** + Call this method at an appropriate time to attempt dehydrating to a new backup device + */ +- (void)attemptDeviceDehydrationWithKeyData:(NSData *)keyData + success:(void (^)(void))success + failure:(void (^)(NSError *error))failure; + @end diff --git a/MatrixKit/Models/Account/MXKAccount.m b/MatrixKit/Models/Account/MXKAccount.m index 72e5174f3..47aa14381 100644 --- a/MatrixKit/Models/Account/MXKAccount.m +++ b/MatrixKit/Models/Account/MXKAccount.m @@ -1629,7 +1629,7 @@ - (void)launchInitialServerSync if (isClientTimeout || isServerTimeout) { - // do not propogate this error to the client + // do not propagate this error to the client // the request will be retried or postponed according to the reachability status MXLogDebug(@"[MXKAccount] Initial sync failure did not propagated"); } @@ -1675,6 +1675,56 @@ - (void)launchInitialServerSync }]; } +- (void)attemptDeviceDehydrationWithKeyData:(NSData *)keyData + success:(void (^)(void))success + failure:(void (^)(NSError *error))failure +{ + [self attemptDeviceDehydrationWithKeyData:keyData retry:YES success:success failure:failure]; +} + +- (void)attemptDeviceDehydrationWithKeyData:(NSData *)keyData + retry:(BOOL)retry + success:(void (^)(void))success + failure:(void (^)(NSError *error))failure +{ + if (keyData == nil) + { + MXLogWarning(@"[MXKAccount] attemptDeviceDehydrationWithRetry: no key provided for device dehydration"); + + if (failure) + { + failure(nil); + } + + return; + } + + MXLogDebug(@"[MXKAccount] attemptDeviceDehydrationWithRetry: starting device dehydration"); + [[MXKAccountManager sharedManager].dehydrationService dehydrateDeviceWithMatrixRestClient:mxRestClient crypto:mxSession.crypto dehydrationKey:keyData success:^(NSString *deviceId) { + MXLogDebug(@"[MXKAccount] attemptDeviceDehydrationWithRetry: device successfully dehydrated"); + + if (success) + { + success(); + } + } failure:^(NSError *error) { + if (retry) + { + [self attemptDeviceDehydrationWithKeyData:keyData retry:NO success:success failure:failure]; + MXLogError(@"[MXKAccount] attemptDeviceDehydrationWithRetry: device dehydration failed due to error: %@. Retrying.", error); + } + else + { + MXLogError(@"[MXKAccount] attemptDeviceDehydrationWithRetry: device dehydration failed due to error: %@", error); + + if (failure) + { + failure(error); + } + } + }]; +} + - (void)onMatrixSessionStateChange { if (mxSession.state == MXSessionStateRunning) diff --git a/MatrixKit/Models/Account/MXKAccountManager.h b/MatrixKit/Models/Account/MXKAccountManager.h index f86d9bce2..70c4857c9 100644 --- a/MatrixKit/Models/Account/MXKAccountManager.h +++ b/MatrixKit/Models/Account/MXKAccountManager.h @@ -101,6 +101,8 @@ extern NSString *const MXKAccountManagerDataType; */ @property (nonatomic) BOOL isPushAvailable; +@property (nonatomic, readonly) MXDehydrationService *dehydrationService; + /** Retrieve the MXKAccounts manager. diff --git a/MatrixKit/Models/Account/MXKAccountManager.m b/MatrixKit/Models/Account/MXKAccountManager.m index 35df98b07..0763dab53 100644 --- a/MatrixKit/Models/Account/MXKAccountManager.m +++ b/MatrixKit/Models/Account/MXKAccountManager.m @@ -59,6 +59,7 @@ - (instancetype)init if (self) { _storeClass = [MXFileStore class]; + _dehydrationService = [MXDehydrationService new]; // Migrate old account file to new format [self migrateAccounts]; @@ -122,8 +123,7 @@ - (void)addAccount:(MXKAccount *)account andOpenSession:(BOOL)openSession if (openSession && !account.disabled) { // Open a new matrix session by default - MXLogDebug(@"[MXKAccountManager] openSession for %@ account", account.mxCredentials.userId); - + MXLogDebug(@"[MXKAccountManager] openSession for %@ account (device %@)", account.mxCredentials.userId, account.mxCredentials.deviceId); id store = [[_storeClass alloc] init]; [account openSessionWithStore:store]; } diff --git a/MatrixKit/Models/MXKAppSettings.h b/MatrixKit/Models/MXKAppSettings.h index 188aa8abe..346ded093 100644 --- a/MatrixKit/Models/MXKAppSettings.h +++ b/MatrixKit/Models/MXKAppSettings.h @@ -116,7 +116,7 @@ typedef NS_ENUM(NSUInteger, MXKKeyPreSharingStrategy) Customising this value modifies the behaviour of link detection in `MXKRoomBubbleComponent`. This boolean value is defined in shared settings object with the key: `firstURLDetectionIgnoredHosts`. - Return NO if no value is defined. + The default value of this property only contains the matrix.to host. */ @property (nonatomic) NSArray *firstURLDetectionIgnoredHosts; diff --git a/MatrixKit/Models/MXKAppSettings.m b/MatrixKit/Models/MXKAppSettings.m index ce8f0c563..41bac1f42 100644 --- a/MatrixKit/Models/MXKAppSettings.m +++ b/MatrixKit/Models/MXKAppSettings.m @@ -497,7 +497,7 @@ - (void)setEnableBubbleComponentLinkDetection:(BOOL)storeLinksInBubbleComponents { if (self == [MXKAppSettings standardAppSettings]) { - return [NSUserDefaults.standardUserDefaults objectForKey:@"firstURLDetectionIgnoredHosts"]; + return [NSUserDefaults.standardUserDefaults objectForKey:@"firstURLDetectionIgnoredHosts"] ?: @[[NSURL URLWithString:kMXMatrixDotToUrl].host]; } else { @@ -509,6 +509,11 @@ - (void)setFirstURLDetectionIgnoredHosts:(NSArray *)ignoredHosts { if (self == [MXKAppSettings standardAppSettings]) { + if (ignoredHosts == nil) + { + ignoredHosts = @[]; + } + [NSUserDefaults.standardUserDefaults setObject:ignoredHosts forKey:@"firstURLDetectionIgnoredHosts"]; } else diff --git a/MatrixKit/Models/RoomList/MXKRecentCellData.m b/MatrixKit/Models/RoomList/MXKRecentCellData.m index 42e9662e0..d7fa7dd8f 100644 --- a/MatrixKit/Models/RoomList/MXKRecentCellData.m +++ b/MatrixKit/Models/RoomList/MXKRecentCellData.m @@ -19,9 +19,10 @@ #import "MXKSessionRecentsDataSource.h" #import "MXEvent+MatrixKit.h" +#import @implementation MXKRecentCellData -@synthesize roomSummary, recentsDataSource, roomDisplayname, lastEventTextMessage, lastEventAttributedTextMessage, lastEventDate; +@synthesize roomSummary, spaceChildInfo, recentsDataSource, roomDisplayname, lastEventTextMessage, lastEventAttributedTextMessage, lastEventDate; - (instancetype)initWithRoomSummary:(MXRoomSummary*)theRoomSummary andRecentListDataSource:(MXKSessionRecentsDataSource*)recentListDataSource { @@ -38,19 +39,36 @@ - (instancetype)initWithRoomSummary:(MXRoomSummary*)theRoomSummary andRecentList return self; } +- (instancetype)initWithSpaceChildInfo:(MXSpaceChildInfo*)theSpaceChildInfo andRecentListDataSource:(MXKSessionRecentsDataSource*)recentListDataSource +{ + self = [self init]; + if (self) + { + spaceChildInfo = theSpaceChildInfo; + recentsDataSource = recentListDataSource; + + [self update]; + } + return self; +} + - (void)update { // Keep ref on displayed last event - roomDisplayname = roomSummary.displayname; + roomDisplayname = spaceChildInfo ? spaceChildInfo.name : roomSummary.displayname; - lastEventTextMessage = roomSummary.lastMessage.text; - lastEventAttributedTextMessage = roomSummary.lastMessage.attributedText; + lastEventTextMessage = spaceChildInfo ? spaceChildInfo.topic : roomSummary.lastMessage.text; + lastEventAttributedTextMessage = spaceChildInfo ? nil : roomSummary.lastMessage.attributedText; } - (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXRoomSummaryDidChangeNotification object:roomSummary]; + if (roomSummary) + { + [[NSNotificationCenter defaultCenter] removeObserver:self name:kMXRoomSummaryDidChangeNotification object:roomSummary]; + } roomSummary = nil; + spaceChildInfo = nil; lastEventTextMessage = nil; lastEventAttributedTextMessage = nil; @@ -91,4 +109,10 @@ - (NSString*)description return [NSString stringWithFormat:@"%@ %@: %@ - %@", super.description, self.roomSummary.roomId, self.roomDisplayname, self.lastEventTextMessage]; } +- (BOOL)isSuggestedRoom +{ + // As off now, we only store MXSpaceChildInfo in case of suggested rooms + return self.spaceChildInfo != nil; +} + @end diff --git a/MatrixKit/Models/RoomList/MXKRecentCellDataStoring.h b/MatrixKit/Models/RoomList/MXKRecentCellDataStoring.h index 380736fd3..7143282a7 100644 --- a/MatrixKit/Models/RoomList/MXKRecentCellDataStoring.h +++ b/MatrixKit/Models/RoomList/MXKRecentCellDataStoring.h @@ -21,6 +21,7 @@ #import "MXKCellData.h" @class MXKSessionRecentsDataSource; +@class MXSpaceChildInfo; /** `MXKRecentCellDataStoring` defines a protocol a class must conform in order to store recent cell data @@ -39,6 +40,10 @@ The `MXRoomSummary` instance of the room for the recent displayed by the cell. */ @property (nonatomic, readonly) MXRoomSummary *roomSummary; +/** + In case of suggested rooms we store the `MXSpaceChildInfo` instance of the room + */ +@property (nonatomic, readonly) MXSpaceChildInfo *spaceChildInfo; @property (nonatomic, readonly) NSString *roomDisplayname; @property (nonatomic, readonly) NSString *lastEventTextMessage; @@ -48,6 +53,7 @@ @property (nonatomic, readonly) NSUInteger notificationCount; @property (nonatomic, readonly) NSUInteger highlightCount; @property (nonatomic, readonly) NSString *notificationCountStringValue; +@property (nonatomic, readonly) BOOL isSuggestedRoom; #pragma mark - Public methods /** @@ -59,6 +65,15 @@ */ - (instancetype)initWithRoomSummary:(MXRoomSummary*)roomSummary andRecentListDataSource:(MXKSessionRecentsDataSource*)recentListDataSource; +/** + Create a new `MXKCellData` object for a new recent cell. + + @param spaceChildInfo the `MXSpaceChildInfo` object that has data about the room. + @param recentListDataSource the `MXKSessionRecentsDataSource` object that will use this instance. + @return the newly created instance. + */ +- (instancetype)initWithSpaceChildInfo:(MXSpaceChildInfo*)spaceChildInfo andRecentListDataSource:(MXKSessionRecentsDataSource*)recentListDataSource; + /** The `MXKSessionRecentsDataSource` object calls this method when it detects a change in the room. */ diff --git a/MatrixKit/Models/RoomList/MXKRecentsDataSource.h b/MatrixKit/Models/RoomList/MXKRecentsDataSource.h index 5c3625689..150aac2a4 100644 --- a/MatrixKit/Models/RoomList/MXKRecentsDataSource.h +++ b/MatrixKit/Models/RoomList/MXKRecentsDataSource.h @@ -57,6 +57,8 @@ */ @property (nonatomic, readonly) NSArray* searchPatternsList; +@property (nonatomic, strong) MXSpace *currentSpace; + #pragma mark - Configuration /** diff --git a/MatrixKit/Models/RoomList/MXKRecentsDataSource.m b/MatrixKit/Models/RoomList/MXKRecentsDataSource.m index 006c9d30d..ab4bb7488 100644 --- a/MatrixKit/Models/RoomList/MXKRecentsDataSource.m +++ b/MatrixKit/Models/RoomList/MXKRecentsDataSource.m @@ -126,6 +126,15 @@ - (void)removeMatrixSession:(MXSession*)matrixSession } } +- (void)setCurrentSpace:(MXSpace *)currentSpace +{ + _currentSpace = currentSpace; + + for (MXKSessionRecentsDataSource *recentsDataSource in recentsDataSourceArray) { + recentsDataSource.currentSpace = currentSpace; + } +} + #pragma mark - MXKDataSource overridden - (MXSession*)mxSession diff --git a/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h b/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h index 51a6cca53..e4a8a4c03 100644 --- a/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h +++ b/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.h @@ -21,6 +21,8 @@ #import "MXKDataSource.h" #import "MXKRecentCellData.h" +@class MXSpace; + /** Identifier to use for cells that display a room in the recents list. */ @@ -54,6 +56,8 @@ extern NSString *const kMXKRecentCellIdentifier; */ @property (nonatomic, readonly) BOOL hasUnread; +@property (nonatomic, strong, nullable) MXSpace *currentSpace; + #pragma mark - Life cycle diff --git a/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.m b/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.m index 52a6da523..525d5261f 100644 --- a/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.m +++ b/MatrixKit/Models/RoomList/MXKSessionRecentsDataSource.m @@ -18,6 +18,7 @@ #import "MXKSessionRecentsDataSource.h" #import "MXKRoomDataSourceManager.h" +#import #pragma mark - Constant definitions NSString *const kMXKRecentCellIdentifier = @"kMXKRecentCellIdentifier"; @@ -44,8 +45,20 @@ @interface MXKSessionRecentsDataSource () Do not react on every summary change */ MXThrottler *roomSummaryChangeThrottler; + + /** + Last received suggested rooms per space ID + */ + NSMutableDictionary *> *lastSuggestedRooms; + + id spaceEventsListener; } +/** + Additional suggestedRooms related to the current selected Space + */ +@property (nonatomic, strong) NSArray *suggestedRooms; + @end @implementation MXKSessionRecentsDataSource @@ -60,6 +73,8 @@ - (instancetype)initWithMatrixSession:(MXSession *)matrixSession internalCellDataArray = [NSMutableArray array]; filteredCellDataArray = nil; + lastSuggestedRooms = [NSMutableDictionary new]; + // Set default data and view classes [self registerCellDataClass:MXKRecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier]; @@ -82,6 +97,7 @@ - (void)destroy cellDataArray = nil; internalCellDataArray = nil; filteredCellDataArray = nil; + lastSuggestedRooms = nil; searchPatternsList = nil; @@ -105,6 +121,55 @@ - (void)didMXSessionStateChange } } +- (void)setCurrentSpace:(MXSpace *)currentSpace +{ + if (_currentSpace == currentSpace) + { + return; + } + + if (_currentSpace && spaceEventsListener) + { + [_currentSpace.room removeListener:spaceEventsListener]; + } + + _currentSpace = currentSpace; + + self.suggestedRooms = _currentSpace ? lastSuggestedRooms[_currentSpace.spaceId] : nil; + [self updateSuggestedRooms]; + + MXWeakify(self); + spaceEventsListener = [self.currentSpace.room listenToEvents:^(MXEvent *event, MXTimelineDirection direction, MXRoomState *roomState) { + MXStrongifyAndReturnIfNil(self); + [self updateSuggestedRooms]; + }]; +} + +-(void)setSuggestedRooms:(NSArray *)suggestedRooms +{ + _suggestedRooms = suggestedRooms; + [self loadData]; +} + +-(void)updateSuggestedRooms +{ + if (self.currentSpace) + { + NSString *currentSpaceId = self.currentSpace.spaceId; + MXWeakify(self); + [self.mxSession.spaceService getSpaceChildrenForSpaceWithId:currentSpaceId suggestedOnly:YES limit:5 success:^(MXSpaceChildrenSummary * _Nonnull childrenSummary) { + MXLogDebug(@"[MXKSessionRecentsDataSource] getSpaceChildrenForSpaceWithId %@: %ld found", self.currentSpace.spaceId, childrenSummary.childInfos.count); + MXStrongifyAndReturnIfNil(self); + self->lastSuggestedRooms[currentSpaceId] = childrenSummary.childInfos; + if ([self.currentSpace.spaceId isEqual:currentSpaceId]) { + self.suggestedRooms = childrenSummary.childInfos; + } + } failure:^(NSError * _Nonnull error) { + MXLogError(@"[MXKSessionRecentsDataSource] getSpaceChildrenForSpaceWithId failed with error: %@", error); + }]; + } +} + #pragma mark - - (NSInteger)numberOfCells @@ -235,10 +300,22 @@ - (void)loadData id cellData = [[class alloc] initWithRoomSummary:roomSummary andRecentListDataSource:self]; if (cellData) { - [internalCellDataArray addObject:cellData]; + if (self.currentSpace == nil || [self.mxSession.spaceService isRoomWithId:roomSummary.roomId descendantOf:self.currentSpace.spaceId]) + { + [internalCellDataArray addObject:cellData]; + } } } } + + for (MXSpaceChildInfo *childInfo in _suggestedRooms) + { + id cellData = [[class alloc] initWithSpaceChildInfo:childInfo andRecentListDataSource:self]; + if (cellData) + { + [internalCellDataArray addObject:cellData]; + } + } MXLogDebug(@"[MXKSessionRecentsDataSource] Loaded %tu recents in %.3fms", self.mxSession.rooms.count, [[NSDate date] timeIntervalSinceDate:startDate] * 1000); diff --git a/MatrixKit/Views/MXKImageView.m b/MatrixKit/Views/MXKImageView.m index bfe51ac67..92060afc6 100644 --- a/MatrixKit/Views/MXKImageView.m +++ b/MatrixKit/Views/MXKImageView.m @@ -376,10 +376,8 @@ - (void)layoutSubviews UIApplication *sharedApplication = [UIApplication performSelector:@selector(sharedApplication)]; if (sharedApplication) { - if (@available(iOS 11.0, *)) - { - safeAreaInsets = [sharedApplication keyWindow].safeAreaInsets; - } + safeAreaInsets = [sharedApplication keyWindow].safeAreaInsets; + UIViewController *rootViewController = [sharedApplication keyWindow].rootViewController; tabBarController = rootViewController.tabBarController; if (!tabBarController && [rootViewController isKindOfClass:[UITabBarController class]]) diff --git a/MatrixKit/Views/RoomBubbleList/MXKRoomBubbleTableViewCell.m b/MatrixKit/Views/RoomBubbleList/MXKRoomBubbleTableViewCell.m index 2b1fe5894..96a7ad640 100644 --- a/MatrixKit/Views/RoomBubbleList/MXKRoomBubbleTableViewCell.m +++ b/MatrixKit/Views/RoomBubbleList/MXKRoomBubbleTableViewCell.m @@ -1070,7 +1070,7 @@ - (void)didEndDisplay } - (BOOL)shouldInteractWithURL:(NSURL *)URL urlItemInteraction:(UITextItemInteraction)urlItemInteraction associatedEvent:(MXEvent*)associatedEvent -API_AVAILABLE(ios(10.0)) { +{ return [self shouldInteractWithURL:URL urlItemInteractionValue:@(urlItemInteraction) associatedEvent:associatedEvent]; } @@ -1340,16 +1340,7 @@ - (IBAction)onMessageTap:(UITapGestureRecognizer*)sender // If a link has been touched warn delegate immediately. if (tappedUrl) { - // Send default URL interaction `UITextItemInteractionInvokeDefaultAction` for a quick tap as received by UITextViewDelegate method `- (BOOL)textView:shouldInteractWithURL:inRange:interaction:` for a tap. - if (@available(iOS 10.0, *)) - { - [self shouldInteractWithURL:tappedUrl urlItemInteraction:UITextItemInteractionInvokeDefaultAction associatedEvent:tappedEvent]; - } - else - { - // Use UITextItemInteractionInvokeDefaultAction raw value for iOS 9 - [self shouldInteractWithURL:tappedUrl urlItemInteractionValue:@(0) associatedEvent:tappedEvent]; - } + [self shouldInteractWithURL:tappedUrl urlItemInteraction:UITextItemInteractionInvokeDefaultAction associatedEvent:tappedEvent]; } else { @@ -1490,7 +1481,7 @@ - (IBAction)onLongPressGesture:(UILongPressGestureRecognizer*)longPressGestureRe #pragma mark - UITextView delegate -- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction API_AVAILABLE(ios(10.0)) +- (BOOL)textView:(UITextView *)textView shouldInteractWithURL:(NSURL *)URL inRange:(NSRange)characterRange interaction:(UITextItemInteraction)interaction { BOOL shouldInteractWithURL = YES; diff --git a/Podfile b/Podfile index 22d941ee2..3db4f6364 100644 --- a/Podfile +++ b/Podfile @@ -1,5 +1,5 @@ # Uncomment this line to define a global platform for your project -platform :ios, '9.0' +platform :ios, '12.1' # Use frameforks to allow usage of pod written in Swift (like PiwikTracker) use_frameworks! @@ -8,7 +8,7 @@ abstract_target 'MatrixKitSamplePods' do # Different flavours of pods to Matrix SDK # The tagged version on which this version of MatrixKit has been built - pod 'MatrixSDK', '= 0.20.1' + pod 'MatrixSDK', '= 0.20.2' # The lastest release available on the CocoaPods repository #pod 'MatrixSDK' diff --git a/Podfile.lock b/Podfile.lock index 2c83a5653..0fdbd079e 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -15,22 +15,22 @@ PODS: - AFNetworking/UIKit (4.0.1): - AFNetworking/NSURLSession - Down (0.11.0) - - DTCoreText (1.6.25): - - DTCoreText/Core (= 1.6.25) + - DTCoreText (1.6.26): + - DTCoreText/Core (= 1.6.26) - DTFoundation/Core (~> 1.7.5) - DTFoundation/DTAnimatedGIF (~> 1.7.5) - DTFoundation/DTHTMLParser (~> 1.7.5) - DTFoundation/UIKit (~> 1.7.5) - - DTCoreText/Core (1.6.25): + - DTCoreText/Core (1.6.26): - DTFoundation/Core (~> 1.7.5) - DTFoundation/DTAnimatedGIF (~> 1.7.5) - DTFoundation/DTHTMLParser (~> 1.7.5) - DTFoundation/UIKit (~> 1.7.5) - - DTFoundation/Core (1.7.16) - - DTFoundation/DTAnimatedGIF (1.7.16) - - DTFoundation/DTHTMLParser (1.7.16): + - DTFoundation/Core (1.7.18) + - DTFoundation/DTAnimatedGIF (1.7.18) + - DTFoundation/DTHTMLParser (1.7.18): - DTFoundation/Core - - DTFoundation/UIKit (1.7.16): + - DTFoundation/UIKit (1.7.18): - DTFoundation/Core - GZIP (1.3.0) - HPGrowingTextView (1.1) @@ -39,13 +39,13 @@ PODS: - JSQSystemSoundPlayer (2.0.1) - libbase58 (0.1.4) - libPhoneNumber-iOS (0.9.15) - - MatrixSDK (0.20.1): - - MatrixSDK/Core (= 0.20.1) - - MatrixSDK/Core (0.20.1): + - MatrixSDK (0.20.2): + - MatrixSDK/Core (= 0.20.2) + - MatrixSDK/Core (0.20.2): - AFNetworking (~> 4.0.0) - GZIP (~> 1.3.0) - libbase58 (~> 0.1.4) - - OLMKit (~> 3.2.4) + - OLMKit (~> 3.2.5) - Realm (= 10.7.6) - SwiftyBeaver (= 1.9.5) - OLMKit (3.2.5): @@ -64,7 +64,7 @@ DEPENDENCIES: - HPGrowingTextView (~> 1.1) - JSQMessagesViewController (~> 7.3.5) - libPhoneNumber-iOS (~> 0.9.13) - - MatrixSDK (= 0.20.1) + - MatrixSDK (= 0.20.2) SPEC REPOS: trunk: @@ -86,19 +86,19 @@ SPEC REPOS: SPEC CHECKSUMS: AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce Down: b6ba1bc985c9d2f4e15e3b293d2207766fa12612 - DTCoreText: e92f4cf6b36d9d71ce4436d12cf089d74ab0596b - DTFoundation: e7781d9fd2f202bfd451fbbf8cab71ce83b46498 + DTCoreText: ec749e013f2e1f76de5e7c7634642e600a7467ce + DTFoundation: a53f8cda2489208cbc71c648be177f902ee17536 GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3 HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19 JSQMessagesViewController: 6587f56aedbcb150a8ba1d968e1ef58b1bc758b7 JSQSystemSoundPlayer: c5850e77a4363ffd374cd851154b9af93264ed8d libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75 - MatrixSDK: 37fbb6a650095387e908937b7411c4370599c90b + MatrixSDK: bf3ebecbe643273c4439367175ccd4e5307831c8 OLMKit: 9fb4799c4a044dd2c06bda31ec31a12191ad30b5 Realm: ed860452717c8db8f4bf832b6807f7f2ce708839 SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 -PODFILE CHECKSUM: 86fda57346abf3e42c36ceb4e7232f6fe85209bd +PODFILE CHECKSUM: 79ff8ad84a5bd5e3d7695273a889c5008a769709 COCOAPODS: 1.10.1