Merge branch 'develop' into doug/4896_url_previews_string_whitespace

This commit is contained in:
Doug 2021-09-27 14:44:17 +01:00
commit b35838e268
207 changed files with 8822 additions and 363 deletions

View file

@ -1,3 +1,57 @@
## Changes in 1.6.0 (2021-09-24)
✨ Features
- Spaces chooser ([#4052](https://github.com/vector-im/element-ios/issues/4052))
- SDK: Support Spaces summary ([#4068](https://github.com/vector-im/element-ios/issues/4068))
- Space home view inherits title from previously viewed tab ([#4493](https://github.com/vector-im/element-ios/issues/4493))
- Added Space menu ([#4494](https://github.com/vector-im/element-ios/issues/4494))
- Filter rooms for a given space ([#4495](https://github.com/vector-im/element-ios/issues/4495))
- Space invite ([#4496](https://github.com/vector-im/element-ios/issues/4496))
- Space preview bottom sheet ([#4497](https://github.com/vector-im/element-ios/issues/4497))
- Handle space link ([#4498](https://github.com/vector-im/element-ios/issues/4498))
- Support suggested rooms ([#4500](https://github.com/vector-im/element-ios/issues/4500))
- Show suggested in room lists ([#4501](https://github.com/vector-im/element-ios/issues/4501))
- Show space name in navigation bar title view for each root tab bar navigation controllers ([#4502](https://github.com/vector-im/element-ios/issues/4502))
- Space switching ([#4503](https://github.com/vector-im/element-ios/issues/4503))
- Added Show spaces in left panel ([#4509](https://github.com/vector-im/element-ios/issues/4509))
- Explore rooms ([#4571](https://github.com/vector-im/element-ios/issues/4571))
- Browsing users in a space ([#4682](https://github.com/vector-im/element-ios/issues/4682), [#4982](https://github.com/vector-im/element-ios/issues/4982))
🙌 Improvements
- Upgrade MatrixKit version ([v0.16.2](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.16.2)).
- URL Previews: Enable by default and remove from labs. ([#4828](https://github.com/vector-im/element-ios/issues/4828))
- Automatically dismissing invites for empty rooms after failing to join. ([#4830](https://github.com/vector-im/element-ios/issues/4830))
- Using the bundle display name as the app name in localizable .strings files. Exposing generated .strings and info.plist members to Objective-C. ([#4881](https://github.com/vector-im/element-ios/issues/4881))
- Voice Messages: Pause playback when changing rooms while retaining the playback position when re-entering. ([#47773](https://github.com/vector-im/element-ios/issues/47773))
🐛 Bugfixes
- Cannot disable Face ID after disabling pin. ([#4415](https://github.com/vector-im/element-ios/issues/4415))
- Fixes "PIN & (NULL)" security section header when device biometrics are not available or not enrolled into. ([#4461](https://github.com/vector-im/element-ios/issues/4461))
- SSO: Fix redirection issue when logging in with single sign on. Contributed by Chelsea Finnie. ([#4785](https://github.com/vector-im/element-ios/issues/4785))
- Fix incorrect theme being shown in the notification settings screens. ([#4816](https://github.com/vector-im/element-ios/issues/4816))
- Fix incorrect theme being shown in the notification settings screens after launch. ([#4835](https://github.com/vector-im/element-ios/issues/4835))
- No notification for space invitation ([#4840](https://github.com/vector-im/element-ios/issues/4840))
- Prevent home screen horizontal scroll views from capturing side menu swipe gestures. ([#4843](https://github.com/vector-im/element-ios/issues/4843))
- Odd error message in Space member list ([#4845](https://github.com/vector-im/element-ios/issues/4845))
- Space view has communities tab at the bottom of the screen ([#4846](https://github.com/vector-im/element-ios/issues/4846))
- Take user to space overview after joining space ([#4848](https://github.com/vector-im/element-ios/issues/4848))
- Refresh suggested room list in the home view when room is (un)marked as suggested ([#4849](https://github.com/vector-im/element-ios/issues/4849))
- Bring leaving space experience in line with Web ([#4850](https://github.com/vector-im/element-ios/issues/4850))
- Space home view inherits title from previously viewed tab ([#4851](https://github.com/vector-im/element-ios/issues/4851))
- Remove search filter when switching space ([#4852](https://github.com/vector-im/element-ios/issues/4852))
- URL Previews: Fix layout on 4" devices. ([#4855](https://github.com/vector-im/element-ios/issues/4855))
- RecentsViewController: Fix a crash when scrolling to a room in the room list. ([#4874](https://github.com/vector-im/element-ios/issues/4874))
- Explore rooms list in space has odd ordering ([#4890](https://github.com/vector-im/element-ios/issues/4890))
- Fixed suggested spaces appear as suggested rooms ([#4903](https://github.com/vector-im/element-ios/issues/4903))
🧱 Build
- Bumped the minimum deployment target to iOS 12.1 ([#4693](https://github.com/vector-im/element-ios/issues/4693))
## Changes in 1.5.4 (2021-09-16)
🙌 Improvements

View file

@ -15,5 +15,5 @@
//
// Version
MARKETING_VERSION = 1.5.5
CURRENT_PROJECT_VERSION = 1.5.5
MARKETING_VERSION = 1.6.1
CURRENT_PROJECT_VERSION = 1.6.1

View file

@ -13,7 +13,7 @@ use_frameworks!
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI
#
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
$matrixKitVersion = '= 0.16.1'
$matrixKitVersion = '= 0.16.2'
# $matrixKitVersion = :local
# $matrixKitVersion = {'develop' => 'develop'}

View file

@ -58,29 +58,29 @@ PODS:
- MatomoTracker (7.4.1):
- MatomoTracker/Core (= 7.4.1)
- MatomoTracker/Core (7.4.1)
- MatrixKit (0.16.1):
- MatrixKit (0.16.2):
- Down (~> 0.11.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.16.1)
- MatrixSDK (= 0.20.1)
- MatrixKit/Core (0.16.1):
- MatrixKit/Core (= 0.16.2)
- MatrixSDK (= 0.20.2)
- MatrixKit/Core (0.16.2):
- Down (~> 0.11.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.20.1)
- MatrixSDK (0.20.1):
- MatrixSDK/Core (= 0.20.1)
- MatrixSDK/Core (0.20.1):
- MatrixSDK (= 0.20.2)
- 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)
- MatrixSDK/JingleCallStack (0.20.1):
- MatrixSDK/JingleCallStack (0.20.2):
- JitsiMeetSDK (= 3.5.0)
- MatrixSDK/Core
- OLMKit (3.2.5):
@ -124,7 +124,7 @@ DEPENDENCIES:
- KeychainAccess (~> 4.2.2)
- KTCenterFlowLayout (~> 1.3.1)
- MatomoTracker (~> 7.4.1)
- MatrixKit (= 0.16.1)
- MatrixKit (= 0.16.2)
- MatrixSDK
- MatrixSDK/JingleCallStack
- OLMKit
@ -204,8 +204,8 @@ SPEC CHECKSUMS:
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
Logging: beeb016c9c80cf77042d62e83495816847ef108b
MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb
MatrixKit: 7033539085bc94b6b8755fdab68ba6f7e6e79d56
MatrixSDK: 37fbb6a650095387e908937b7411c4370599c90b
MatrixKit: 0cc184292f2dcf5b6ad831cc008184a89111503f
MatrixSDK: bf3ebecbe643273c4439367175ccd4e5307831c8
OLMKit: 9fb4799c4a044dd2c06bda31ec31a12191ad30b5
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
Realm: ed860452717c8db8f4bf832b6807f7f2ce708839
@ -219,6 +219,6 @@ SPEC CHECKSUMS:
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: 9478742d5244cae5112451119f9e004eae089967
PODFILE CHECKSUM: c03148cb3f07b073a3340d45f6120290461fb32f
COCOAPODS: 1.10.1

View file

@ -4,8 +4,7 @@
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES"
runPostActionsOnFailure = "NO">
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "side_menu_notif_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "side_menu_notif_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "side_menu_notif_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

View file

@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "space_home_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_home_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_home_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 328 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 541 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 703 B

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_menu_close.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_menu_close@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_menu_close@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 261 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 393 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 548 B

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_menu_leave.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_menu_leave@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_menu_leave@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 287 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 397 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 544 B

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_menu_members.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_menu_members@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_menu_members@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_menu_rooms.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_menu_rooms@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_menu_rooms@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_room_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_room_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_room_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 447 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 B

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_type_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_type_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_type_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 459 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "space_user_icon.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "space_user_icon@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "space_user_icon@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 567 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View file

@ -0,0 +1,26 @@
{
"images" : [
{
"filename" : "spaces_more.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "spaces_more@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "spaces_more@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 304 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 408 B

View file

@ -78,7 +78,7 @@
"room_creation_make_private" = "Mache privat";
"room_creation_wait_for_creation" = "Es wird gerade schon ein Raum erstellt. Bitte warten.";
// Room recents
"room_recents_directory_section" = "RAUM VERZEICHNIS";
"room_recents_directory_section" = "RAUMVERZEICHNIS";
"room_recents_favourites_section" = "FAVORITEN";
"room_recents_people_section" = "PERSONEN";
"room_recents_conversations_section" = "RÄUME";
@ -509,7 +509,7 @@
"room_action_send_photo_or_video" = "Foto oder Video senden";
"room_action_send_sticker" = "Aufkleber senden";
"settings_deactivate_account" = "DEAKTIVIERTES KONTO";
"settings_deactivate_my_account" = "Deaktivere meinen Konto";
"settings_deactivate_my_account" = "Benutzerkonto deaktiveren";
"widget_sticker_picker_no_stickerpacks_alert" = "Du hast aktuell keine Aufkleberpakete aktiviert.";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Welche hinzufügen?";
// GDPR
@ -518,7 +518,7 @@
"deactivate_account_title" = "Deaktiviere Konto";
"deactivate_account_informations_part1" = "Dies wird deinen Konto permanent unbenutzbar machen. Du wirst dich nicht erneut anmelden können und keiner wird in der Lage sein, dieselbe Nutzer-ID erneut zu registrieren. Alle Räume, in denen dein Konto ist, werden verlassen und deine Kontodaten werden vom Identitätsserver gelöscht. ";
"deactivate_account_informations_part2_emphasize" = "Diese Aktion ist irreversibel.";
"deactivate_account_informations_part3" = "\n\nDeinen Konto deaktivieren ";
"deactivate_account_informations_part3" = "\n\nDein Konto deaktivieren ";
"deactivate_account_informations_part4_emphasize" = "wird standardmäßig nicht dafür sorgen, dass wir alle Nachrichten löschen, die du gesendet hast. ";
"deactivate_account_informations_part5" = "Wenn du möchtest, dass wir deine Nachrichten löschen, wähle das Auswahlfeld unten aus.\n\nDie Sichtbarkeit der Nachrichten in Matrix ist wie bei E-Mails: Wenn wir deine Nachrichten löschen, werden sie nicht mehr mit neuen oder nicht registrierten Benutzer geteilt. Bereits registrierte Nutzer behalten den Zugriff auf ihre Kopie deiner Nachrichten.";
"deactivate_account_forget_messages_information_part1" = "Bitte alle Nachrichten vergessen, die ich gesendet habe, wenn mein Konto deaktiviert wird (";
@ -1414,3 +1414,40 @@
"event_formatter_call_missed_video" = "Verpasster Videoanruf";
"event_formatter_call_active_voice" = "Aktiver Sprachanruf";
"event_formatter_call_active_video" = "Aktiver Videoanruf";
"version_check_modal_action_title_deprecated" = "Zeige mir, wie es geht";
"version_check_modal_action_title_supported" = "Verstanden";
"version_check_banner_title_deprecated" = "iOS %@ wird nicht mehr unterstützt";
"version_check_banner_subtitle_supported" = "Wir hören bald auf, iOS %@ zu unterstützen. Um Element weiterhin vollumfänglich zu nutzen, empfehlen wir dir die Aktualisierung deiner iOS-Version.";
// Mark: - Version check
"version_check_banner_title_supported" = "iOS %@ wird nicht mehr unterstützt";
"settings_new_keyword" = "Schlüsselwort hinzufügen";
"settings_your_keywords" = "Deine Schlüsselwörter";
"settings_room_upgrades" = "Raumupgrades";
"settings_messages_by_a_bot" = "Nachrichten von Bots";
"settings_call_invitations" = "Anrufeinladungen";
"settings_room_invitations" = "Einladungen";
"settings_messages_containing_keywords" = "Schlüsselwörter";
"settings_messages_containing_at_room" = "@room";
"settings_messages_containing_user_name" = "Meinem Benutzernamen";
"settings_messages_containing_display_name" = "Meinem Anzeigenamen";
"settings_encrypted_group_messages" = "Verschlüsselten Gruppenchats";
"settings_group_messages" = "Gruppenchats";
"settings_encrypted_direct_messages" = "Verschlüsselten Direktnachrichten";
"settings_direct_messages" = "Direktnachrichten";
"settings_notify_me_for" = "Benachrichtige mich bei";
"settings_mentions_and_keywords" = "Erwähnungen und Schlüsselwörter";
"settings_confirm_media_size_description" = "Wenn dies aktiviert ist, wirst du beim Senden von Bildern und Videos gefragt, wie groß sie gesendet werden sollen.";
"settings_confirm_media_size" = "Größe beim Senden bestätigen";
"settings_notifications" = "BENACHRICHTIGUNGEN";
"settings_mentions_and_keywords_encryption_notice" = "Auf deinem Mobilgerät wirst du keine Benachrichtigungen für Erwähnungen und Schlüsselwörter in verschlüsselten Räumen erhalten.";
"version_check_modal_subtitle_supported" = "Wir haben daran gearbeitet Element zu verbessern um ein schnelleres und bereinigteres Erlebnis zu schaffen. Leider ist deine aktuelle iOS-Version mit einigen dieser Verbesserungen nicht kompatibel und wird daher nicht mehr unterstützt werden.\nWir empfehlen dir die Aktualisierung deines Betriebssystems um Element weiterhin vollumfänglich zu nutzen.";
"version_check_modal_subtitle_deprecated" = "Wir haben daran gearbeitet Element zu verbessern um ein schnelleres und bereinigteres Erlebnis zu schaffen. Leider ist deine aktuelle iOS-Version mit einigen dieser Verbesserungen nicht kompatibel und wird daher nicht mehr unterstützt.\nWir empfehlen dir die Aktualisierung deines Betriebssystems um Element weiterhin vollumfänglich zu nutzen.";
"version_check_modal_title_deprecated" = "Wir unterstützen iOS %@ nicht mehr";
"settings_show_url_previews_description" = "Link-Vorschauen werden nur in unverschlüsselten Räumen angezeigt.";
"settings_show_url_previews" = "Link-Vorschau anzeigen";
"settings_sending_media" = "FOTOS UND VIDEOS VERSENDEN";
"version_check_modal_title_supported" = "Wir stellen die Unterstützung für iOS %@ ein";
"version_check_banner_subtitle_deprecated" = "Element wird für iOS %@ nicht weiter unterstützt. Um Element weiterhin vollumfänglich zu nutzen, empfehlen wir dir die Aktualisierung deiner iOS-Version.";
"settings_default" = "Standardbenachrichtigungen";

View file

@ -63,6 +63,7 @@
"switch" = "Switch";
"more" = "More";
"less" = "Less";
"open" = "Open";
"done" = "Done";
// Call Bar
@ -190,6 +191,7 @@
"room_recents_low_priority_section" = "LOW PRIORITY";
"room_recents_server_notice_section" = "SYSTEM ALERTS";
"room_recents_invites_section" = "INVITES";
"room_recents_suggested_rooms_section" = "SUGGESTED ROOMS";
"room_recents_start_chat_with" = "Start chat";
"room_recents_create_empty_room" = "Create room";
"room_recents_join_room" = "Join room";
@ -1695,6 +1697,36 @@ Tap the + to start adding people.";
"space_beta_announce_subtitle" = "The new version of communities";
"space_beta_announce_information" = "Spaces are a new way to group rooms and people. Theyre not on iOS yet, but you can use them now on Web and Desktop.";
"spaces_home_space_title" = "Home";
"spaces_left_panel_title" = "Spaces";
"leave_space_title" = "Leave %@";
"leave_space_message" = "Are you sure you want to leave %@? Do you also want to leave all rooms and spaces of this space?";
"leave_space_message_admin_warning" = "You are admin of this space, ensure that you have transferred admin right to another member before leaving.";
"leave_space_only_action" = "Don't leave any rooms";
"leave_space_and_all_rooms_action" = "Leave all rooms and spaces";
"spaces_explore_rooms" = "Explore rooms";
"spaces_suggested_room" = "Suggested";
"space_tag" = "space";
"spaces_empty_space_title" = "This space has no rooms (yet)";
"spaces_empty_space_detail" = "Some rooms may be hidden because theyre private and you need an invite.";
"spaces_no_result_found_title" = "No results found";
"spaces_no_room_found_detail" = "Some results may be hidden because theyre private and you need an invite to join them.";
"spaces_no_member_found_detail" = "Looking for someone not in %@? For now, you can invite them on web or desktop.";
"spaces_coming_soon_title" = "Coming soon";
"spaces_add_rooms_coming_soon_title" = "Adding rooms coming soon";
"spaces_invites_coming_soon_title" = "Invites coming soon";
"spaces_coming_soon_detail" = "This feature hasnt been implemented here, but its on the way. For now, you can do that with Element on your computer.";
"space_participants_action_remove" = "Remove from this space";
"space_participants_action_ban" = "Ban from this space";
"space_private_join_rule" = "Private space";
"space_public_join_rule" = "Public space";
// Mark: Avatar
"space_avatar_view_accessibility_label" = "avatar";
"space_avatar_view_accessibility_hint" = "Change space avatar";
// Mark: - User avatar view
"user_avatar_view_accessibility_label" = "avatar";

View file

@ -1406,3 +1406,8 @@
"settings_mentions_and_keywords" = "Mainimised ja märksõnad";
"settings_default" = "Vaikimisi teavitused";
"settings_notifications" = "TEAVITUSED";
"settings_confirm_media_size_description" = "Kui see valik on kasutusel, siis palume sul kinnitada saadetavate piltide ja videote suurused.";
"settings_show_url_previews_description" = "Eelvaateid saame kuvada vaid krüptimata jututubades.";
"settings_show_url_previews" = "Näita sisus urlide eelvaateid";
"settings_confirm_media_size" = "Enne saatmist kinnita meedia mõõdud";
"settings_sending_media" = "SAADAN PILTE JA VIDEOSID";

View file

@ -1469,3 +1469,8 @@
"settings_mentions_and_keywords" = "Megemlítések és kulcsszavak";
"settings_default" = "Alapértelmezett értesítések";
"settings_notifications" = "ÉRTESÍTÉSEK";
"settings_show_url_previews_description" = "Csak titkosítatlan szobákban jelenik meg az előnézet.";
"settings_show_url_previews" = "URL előnézetek megjelenítése";
"settings_confirm_media_size_description" = "Ha ez be van kapcsolva, akkor küldésnél ki tudod választani a kép és videó méretét.";
"settings_confirm_media_size" = "Méret megerősítése küldésnél";
"settings_sending_media" = "KÉP ÉS VIDEÓ KÜLDÉSE";

View file

@ -198,7 +198,7 @@
"room_participants_action_start_new_chat" = "Inizia nuova chat";
"room_participants_action_start_voice_call" = "Nuova telefonata";
"room_participants_action_start_video_call" = "Nuova videochiamata";
"room_participants_action_mention" = "Citazione";
"room_participants_action_mention" = "Menziona";
// Chat
"room_jump_to_first_unread" = "Vai ai non letti";
"room_new_message_notification" = "%d nuovo messaggio";
@ -1440,3 +1440,8 @@
"settings_mentions_and_keywords" = "Menzioni e parole chiave";
"settings_default" = "Notifiche predefinite";
"settings_notifications" = "NOTIFICHE";
"settings_show_url_previews_description" = "Le anteprime verranno mostrate solo in stanze non cifrate.";
"settings_show_url_previews" = "Mostra anteprime degli URL";
"settings_confirm_media_size_description" = "Quando attivo, ti verrà chiesto di confermare con che dimensione verranno inviati immagini e video.";
"settings_confirm_media_size" = "Conferma dimensione durante l'invio";
"settings_sending_media" = "INVIO DI IMMAGINI E VIDEO";

View file

@ -1024,3 +1024,17 @@
"room_event_action_reaction_show_all" = "すべてを見る";
"room_event_action_edit" = "編集";
"room_event_action_reply" = "返信";
"device_verification_security_advice_emoji" = "絵文字の順番はもう一方のログインと一致しますか?";
"key_verification_verify_sas_validate_action" = "一致します";
"key_verification_verify_sas_cancel_action" = "一致しません";
// MARK: Verify
"key_verification_verify_sas_title_emoji" = "絵文字の比較";
"device_verification_self_verify_alert_validate_action" = "検証";
"device_verification_self_verify_alert_message" = "ログインを検証してください: %@";
// MARK: Self verification start
// New login
"device_verification_self_verify_alert_title" = "ログインしましたか?";

View file

@ -564,7 +564,7 @@
"room_message_reply_to_short_placeholder" = "Stuur een antwoord…";
// String for App Store
"store_short_description" = "Veilig en gedecentraliseerd chatten en bellen";
"store_full_description" = "Element is een nieuw type messenger en samenwerkings app die:\n\n1. U de controle geeft om uw privacy te behouden\n2. U laat communiceren met iedereen in het Matrix-netwerk, en zelfs daarbuiten door integratie met apps zoals Slack\n3. Beschermt u tegen reclame, datamining, achterdeurtjes en ommuurde netwerken\n4. Beveiligt u door eind-tot-eind versleuteling, met kruislings ondertekenen om anderen te verifiëren\n\nElement is compleet anders dan andere messengers en samenwerkings-apps, omdat het gedecentraliseerd en open source is.\n\nMet Element kunt u zelf hosten - of een host kiezen - zodat u privacy, eigendom en controle heeft over uw gegevens en gesprekken. Het geeft u toegang tot een open netwerk; u zit dus niet vast aan het praten met alleen andere Element-gebruikers. En het is zeer veilig.\n\nElement is hiertoe in staat omdat het werkt op basis van Matrix - de standaard voor open, gedecentraliseerde communicatie. \n\nElement geeft u de controle door u te laten kiezen wie uw gesprekken host. Vanuit de Element app kunt u kiezen om op verschillende manieren te hosten:\n\n1. Neem een gratis account op de publieke server matrix.org\n2. Host het zelf, uw account door draait op uw eigen server\n3. Laat ons het hosten, meld u aan voor een account op een aangepaste server bij het Element Matrix Services hosting platform\n\nWaarom kiest u voor Element?\n\nEIGENAAR VAN UW GEGEVENS: U bepaalt waar uw gegevens en berichten worden bewaard. U bent de eigenaar en heeft de controle, niet een of andere MEGACORP die uw gegevens mijnt of toegang geeft aan derden.\n\nOPEN MESSAGING EN SAMENWERKING: U kunt met iedereen in het Matrix-netwerk chatten, of ze nu Element of een andere Matrix-app gebruiken, en zelfs als ze een ander messaging-systeem gebruiken zoals Slack, IRC of XMPP.\n\nSUPER-VEILIG: Echte eind-tot-eind versleuteling (alleen degenen in de conversatie kunnen berichten ontsleutelen), en kruislings ondertekenen om de apparaten van gespreksdeelnemers te verifiëren.\n\nCOMPLETE COMMUNICATIE: Berichten, spraak- en videogesprekken, bestandsdeling, schermdeling en een heleboel integraties, bots en widgets. Bouw kamers, spaces, blijf in contact en krijg het gedaan.\n\nOVERAL WAAR U BENT: Blijf in contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten en op het web op https://element.io/app.";
"store_full_description" = "Element is een nieuw type messenger en samenwerkings app die:\n\n1. U de controle geeft om uw privacy te behouden\n2. U laat communiceren met iedereen in het Matrix-netwerk, en zelfs daarbuiten door integratie met apps zoals Slack\n3. Beschermt u tegen reclame, datamining, achterdeurtjes en ommuurde netwerken\n4. Beveiligt u door eind-tot-eind versleuteling, met kruislings ondertekenen om anderen te verifiëren\n\nElement is compleet anders dan andere messengers en samenwerkings-apps, omdat het gedecentraliseerd en open source is.\n\nMet Element kunt u zelf hosten - of een host kiezen - zodat u privacy, eigendom en controle heeft over uw gegevens en gesprekken. Het geeft u toegang tot een open netwerk; u zit dus niet vast aan het praten met alleen andere Element-gebruikers. En het is zeer veilig.\n\nElement is hiertoe in staat omdat het werkt op basis van Matrix - de standaard voor open, gedecentraliseerde communicatie. \n\nElement geeft u de controle door u te laten kiezen wie uw gesprekken host. Vanuit de Element app kunt u kiezen om op verschillende manieren te hosten:\n\n1. Neem een gratis account op de publieke server matrix.org\n2. Host het zelf, uw account door draait op uw eigen server\n3. Laat ons het hosten, meld u aan voor een account op een aangepaste server bij het Element Matrix Services hosting platform\n\nWaarom kiest u voor Element?\n\nEIGENAAR VAN UW GEGEVENS: U bepaalt waar uw gegevens en berichten worden bewaard. U bent de eigenaar en heeft de controle, niet een of andere MEGACORP die uw gegevens mijnt of toegang geeft aan derden.\n\nOPEN MESSAGING EN SAMENWERKING: U kunt met iedereen in het Matrix-netwerk chatten, of ze nu Element of een andere Matrix-app gebruiken, en zelfs als ze een ander messaging-systeem gebruiken zoals Slack, IRC of XMPP.\n\nSUPER-VEILIG: Echte eind-tot-eind versleuteling (alleen degenen in de conversatie kunnen berichten ontsleutelen), en kruislings ondertekenen om de apparaten van gespreksdeelnemers te verifiëren.\n\nCOMPLETE COMMUNICATIE: Berichten, spraak- en videogesprekken, bestandsdeling, schermdeling en een heleboel integraties, bots en widgets. Bouw kamers, ruimtes, blijf in contact en krijg het gedaan.\n\nOVERAL WAAR U BENT: Blijf in contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten en op het web op https://element.io/app.";
"auth_login_single_sign_on" = "Aanmelden met enkele aanmelding";
"auth_accept_policies" = "Gelieve het beleid van deze server te lezen en aanvaarden:";
"auth_autodiscover_invalid_response" = "Ongeldig server-ontdekkings-antwoord";
@ -1469,16 +1469,16 @@
// Chat
"room_slide_to_end_group_call" = "Schuif om voor iedereen de oproep te beëindigen";
"space_beta_announce_information" = "Spaces zijn de nieuwe manier om kamers en personen te groeperen. Dit is nog niet beschikbaar op iOS, maar u kunt ze nu al gebruiken op Web en Desktop.";
"space_feature_unavailable_information" = "Spaces zijn de nieuwe manier om kamers en personen te groeperen. \n\nHet is binnenkort beschikbaar. U kan aan spaces deelnemen via andere platformen en die kamer worden dan hier beschikbaar.";
"space_beta_announce_information" = "Ruimtes zijn de nieuwe manier om kamers en personen te groeperen. Dit is nog niet beschikbaar op iOS, maar u kunt ze nu al gebruiken op Web en Desktop.";
"space_feature_unavailable_information" = "Ruimtes zijn de nieuwe manier om kamers en personen te groeperen. \n\nHet is binnenkort beschikbaar. U kan aan ruimtes deelnemen via andere platformen en die kamers worden dan hier beschikbaar.";
"space_beta_announce_subtitle" = "De nieuwe versie van gemeenschappen";
"space_beta_announce_title" = "Spaces komen binnenkort";
"space_beta_announce_title" = "Ruimtes komen binnenkort";
"space_beta_announce_badge" = "BETA";
"space_feature_unavailable_subtitle" = "Spaces is nog niet beschikbaar op iOS, maar u kunt het nu al testen op Web en Desktop";
"space_feature_unavailable_subtitle" = "Ruimtes zijn nog niet beschikbaar op iOS, maar u kunt het nu al testen op Web en Desktop";
// Mark: - Spaces
"space_feature_unavailable_title" = "Spaces is nog niet klaar";
"space_feature_unavailable_title" = "Ruimtes zijn nog niet klaar";
"side_menu_app_version" = "Versie %@";
"side_menu_action_feedback" = "Feedback";
"side_menu_action_help" = "Help";
@ -1569,3 +1569,8 @@
"version_check_banner_title_supported" = "We stoppen de ondersteuning voor iOS %@";
"settings_mentions_and_keywords_encryption_notice" = "U krijgt geen meldingen voor vermeldingen en trefwoorden in versleutelde kamers op mobiele telefoons.";
"settings_show_url_previews_description" = "Voorvertoningen worden alleen getoond in niet versleutelde kamers.";
"settings_show_url_previews" = "URL-voorvertoningen tonen";
"settings_confirm_media_size_description" = "Wanneer dit aan staat wordt u elke keer gevraagd welk formaat afbeeldingen en video's u wilt versturen.";
"settings_confirm_media_size" = "Bevestig afmeting bij versturen";
"settings_sending_media" = "AFBEELDINGEN EN VIDEO'S VERSTUREN";

View file

@ -805,7 +805,7 @@
"user_verification_session_details_untrusted_title" = "Niezaufany";
"user_verification_session_details_information_trusted_current_user" = "Ta sesja jest zaufana dla bezpiecznego przesyłania wiadomości, ponieważ ją zweryfikowałeś:";
"skip" = "Pomiń";
"joined" = "Dołączył";
"joined" = "Obecny(-a)";
"switch" = "Przełącz";
"more" = "Więcej";
// Accessibility
@ -877,7 +877,7 @@
"room_intro_cell_information_multiple_dm_sentence2" = "Tylko Ty bierzesz udział w tej rozmowie, dopóki kogoś nie zaprosisz.";
"room_intro_cell_information_dm_sentence2" = "Tylko wy dwoje uczestniczycie w tej rozmowie, nikt inny nie może się przyłączyć.";
"room_intro_cell_information_dm_sentence1_part3" = ". ";
"room_intro_cell_information_dm_sentence1_part1" = "Rozpocząłeś rozmowę bezpośrednią z ";
"room_intro_cell_information_dm_sentence1_part1" = "Rozpocząłeś(-aś) rozmowę bezpośrednią z ";
"room_intro_cell_information_room_without_topic_sentence2_part2" = " aby ludzie wiedzieli na jaki temat rozmawiać w tym pokoju.";
"room_intro_cell_information_room_without_topic_sentence2_part1" = "Dodaj temat";
"room_intro_cell_information_room_with_topic_sentence2" = "Temat: %@";
@ -981,10 +981,10 @@
"pin_protection_reset_alert_title" = "Zresetuj PIN";
"pin_protection_forgot_pin" = "Zapomniałem(-am) PIN";
"pin_protection_enter_pin" = "Wprowadź swój PIN";
"pin_protection_confirm_pin_to_change" = "Potwierdź PIN, aby zmień PIN";
"pin_protection_confirm_pin_to_change" = "Potwierdź PIN, aby go zmienić";
"pin_protection_confirm_pin_to_disable" = "Potwierdź PIN, aby wyłączyć PIN";
"pin_protection_confirm_pin" = "Potwierdź swój PIN";
"pin_protection_choose_pin" = "Dla poprawy bezpieczeństwa - utwórz PIN";
"pin_protection_choose_pin" = "Ustaw kod PIN";
"pin_protection_choose_pin_welcome_after_register" = "Witaj.";
// MARK: - PIN Protection
@ -1378,8 +1378,8 @@
"room_unsent_messages_cancel_title" = "Usuń niewysłane wiadomości";
"room_message_replying_to" = "Odpisuję do %@";
"room_message_editing" = "Edytuję";
"room_participants_security_information_room_encrypted_for_dm" = "Wiadomości w tym pokoju są szyfrowane end-to-end.\n\nTwoje wiadomości są zabezpieczone \"zamkami\" i tylko Ty i odbiorca macie unikalne klucze do ich \"otworzenia\".";
"room_participants_security_information_room_encrypted" = "Wiadomości w tym pokoju są szyfrowane end-to-end.\n\nTwoje wiadomości są zabezpieczone \"zamkami\" i tylko Ty i odbiorca macie unikalne klucze do ich \"otworzenia\".";
"room_participants_security_information_room_encrypted_for_dm" = "Wiadomości w tym pokoju są szyfrowane end-to-end.\n\nTwoje wiadomości są zabezpieczone \"kłódkami\" i tylko Ty i odbiorca macie unikalne klucze do ich \"otworzenia\".";
"room_participants_security_information_room_encrypted" = "Wiadomości w tym pokoju są szyfrowane end-to-end.\n\nTwoje wiadomości są zabezpieczone \"kłódkami\" i tylko Ty i odbiorca macie unikalne klucze do ich \"otworzenia\".";
"room_participants_security_information_room_not_encrypted_for_dm" = "Wiadomości w tym pokoju nie są szyfrowane end-to-end.";
"room_participants_filter_room_members_for_dm" = "Filtruj uczestników pokoju";
"room_participants_leave_prompt_msg_for_dm" = "Czy napewno chcesz opuścić pokój?";
@ -1534,3 +1534,8 @@
"settings_mentions_and_keywords" = "Oznaczenia i słowa kluczowe";
"settings_default" = "Powiadomienia dotyczące wiadomości";
"settings_notifications" = "POWIADOMIENIA";
"settings_show_url_previews_description" = "Podgląd URL będzie wyświetlany tylko w niezaszyfrowanych pokojach.";
"settings_show_url_previews" = "Pokaż podgląd adresów URL";
"settings_confirm_media_size_description" = "Gdy ta opcja jest włączona, zostaniesz poproszony o potwierdzenie, w jakim rozmiarze obrazy i filmy będą wysyłane.";
"settings_confirm_media_size" = "Potwierdź rozmiar podczas wysyłania";
"settings_sending_media" = "WYSYŁANIE ZDJĘĆ I WIDEO";

View file

@ -1437,3 +1437,8 @@
"settings_mentions_and_keywords" = "Menções e Palavrachaves";
"settings_default" = "Notificações Default";
"settings_notifications" = "NOTIFICAÇÕES";
"settings_show_url_previews_description" = "Previsualizações vão somente ser mostradas em salas não-encriptadas.";
"settings_show_url_previews" = "Mostrar previsualizações de URL emlinha";
"settings_confirm_media_size_description" = "Quanto isto está ligado, você vai ser pedido para confirmar que tamanho imagens e vídeos vão ser enviados como.";
"settings_confirm_media_size" = "Confirmar tamanho quando enviando";
"settings_sending_media" = "ENVIANDO IMAGENS E VÍDEOS";

View file

@ -68,3 +68,51 @@
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Начался групповой вызов";
/* A user's membership has updated in an unknown way */
"USER_MEMBERSHIP_UPDATED" = "%@ обновил(а) свой профиль";
/* A user has change their avatar */
"USER_UPDATED_AVATAR" = "%@ изменил(а) свой аватар";
/* A user has change their name to a new name which we don't know */
"GENERIC_USER_UPDATED_DISPLAYNAME" = "%@ изменил(а) свое имя";
/** Membership Updates **/
/* A user has change their name to a new name */
"USER_UPDATED_DISPLAYNAME" = "%@ изменил(а) свое имя на %@";
/* A user has reacted to a message, but the reaction content is unknown */
"GENERIC_REACTION_FROM_USER" = "%@ отправил(а) реакцию";
/** Reactions **/
/* A user has reacted to a message, including the reaction e.g. "Alice reacted 👍". */
"REACTION_FROM_USER" = "%@ отреагировал(а) %@";
/* New file message from a specific person, not referencing a room. */
"FILE_FROM_USER" = "%@ отправил(а) файл %@";
/* New voice message from a specific person, not referencing a room. */
"VOICE_MESSAGE_FROM_USER" = "%@ отправил(а) голосовое сообщение";
/* New audio message from a specific person, not referencing a room. */
"AUDIO_FROM_USER" = "%@ отправил(а) аудиофайл %@";
/* New video message from a specific person, not referencing a room. */
"VIDEO_FROM_USER" = "%@ отправил(а) видео";
/** Media Messages **/
/* New image message from a specific person, not referencing a room. */
"PICTURE_FROM_USER" = "%@ отправил(а) фото";
/* New message reply from a specific person in a named room. */
"REPLY_FROM_USER_IN_ROOM_TITLE" = "%@ ответил(а) в %@";
/* New message reply from a specific person, not referencing a room. */
"REPLY_FROM_USER_TITLE" = "%@ ответил(а)";
/** General **/
"NOTIFICATION" = "Уведомление";

View file

@ -1419,3 +1419,39 @@
"voice_message_lock_screen_placeholder" = "Голосовое сообщение";
"event_formatter_call_has_ended_with_time" = "Вызов закончен • %@";
"settings_notifications" = "УВЕДОМЛЕНИЯ";
"version_check_modal_action_title_deprecated" = "Узнайте, как";
"version_check_modal_subtitle_deprecated" = "Мы работали над улучшением Element для более быстрой и совершенной работы. К сожалению, ваша текущая версия iOS не совместима с некоторыми из этих исправлений и больше не будет поддерживаться.\nМы советуем вам обновить свою операционную систему, чтобы использовать Element в полной мере.";
"version_check_modal_title_deprecated" = "Мы больше не поддерживаем iOS %@";
"version_check_modal_action_title_supported" = "Понятно";
"version_check_modal_subtitle_supported" = "Мы работали над улучшением Element для более быстрой и совершенной работы. К сожалению, ваша текущая версия iOS не совместима с некоторыми из этих исправлений и больше не будет поддерживаться.\nМы советуем вам обновить свою операционную систему, чтобы использовать Element в полной мере.";
"version_check_modal_title_supported" = "Мы прекращаем поддержку iOS %@";
"version_check_banner_subtitle_deprecated" = "Мы больше не поддерживаем Element на iOS %@. Чтобы продолжать использовать Element в полной мере, мы советуем вам обновить версию iOS.";
"version_check_banner_title_deprecated" = "Мы больше не поддерживаем iOS %@";
"version_check_banner_subtitle_supported" = "В ближайшее время мы прекращаем поддержку Element на iOS %@. Чтобы продолжать использовать Element в полной мере, мы советуем вам обновить вашу версию iOS.";
// Mark: - Version check
"version_check_banner_title_supported" = "Мы прекращаем поддержку iOS %@";
"settings_show_url_previews_description" = "Предварительный просмотр будет осуществляться только в незашифрованных комнатах.";
"settings_show_url_previews" = "Показывать встроенные предварительные просмотры URL-адресов";
"settings_mentions_and_keywords_encryption_notice" = "Вы не будете получать уведомления об упоминаниях и ключевых словах в зашифрованных комнатах на мобильных устройствах.";
"settings_new_keyword" = "Добавить новое ключевое слово";
"settings_your_keywords" = "Ваши ключевые слова";
"settings_room_upgrades" = "Обновлениях комнаты";
"settings_messages_by_a_bot" = "Сообщениях от бота";
"settings_call_invitations" = "Вызовы";
"settings_room_invitations" = "Приглашения в комнату";
"settings_messages_containing_keywords" = "Ключевые слова";
"settings_messages_containing_at_room" = "@room";
"settings_messages_containing_user_name" = "Мое имя пользователя";
"settings_messages_containing_display_name" = "Мое отображаемое имя";
"settings_encrypted_group_messages" = "Зашифрованных групповых сообщениях";
"settings_group_messages" = "Групповых сообщениях";
"settings_encrypted_direct_messages" = "Зашифрованных диалогах";
"settings_direct_messages" = "Диалогах";
"settings_notify_me_for" = "Уведомлять меня о";
"settings_mentions_and_keywords" = "Упоминания и ключевые слова";
"settings_default" = "Уведомления по умолчанию";
"settings_confirm_media_size" = "Подтверждать размер при отправке";
"settings_confirm_media_size_description" = "Когда эта функция включена, вам будет предложено подтвердить, в каком размере будут отправляться изображения и видео.";
"settings_sending_media" = "ОТПРАВКА ИЗОБРАЖЕНИЙ И ВИДЕО";

View file

@ -1457,3 +1457,8 @@
"settings_mentions_and_keywords" = "Përmendje dhe Fjalëkyçe";
"settings_default" = "Njoftime Parazgjedhje";
"settings_notifications" = "NJOFTIME";
"settings_show_url_previews_description" = "Paraparjet do të shfaqen vetëm në dhoma të pafshehtëzuara.";
"settings_show_url_previews" = "Shfaq paraparje URL-sh brendazi";
"settings_confirm_media_size_description" = "Kur kjo është aktive, do tju kërkohet të ripohoni se në çmadhësi të dërgohen figurat dhe videot.";
"settings_confirm_media_size" = "Ripoho madhësi, kur dërgohet";
"settings_sending_media" = "DËRGIM FIGURASH DHE VIDEOSH";

View file

@ -1405,3 +1405,8 @@
"settings_mentions_and_keywords" = "Omnämnanden och nyckelord";
"settings_default" = "Förvalda aviseringar";
"settings_notifications" = "AVISERINGAR";
"settings_show_url_previews_description" = "Förhandsgranskningar kommer bara att visas i okrypterade rum.";
"settings_show_url_previews" = "Visa inbäddade URL-förhandsgranskningar";
"settings_confirm_media_size_description" = "När detta är på så kommer du få bekräfta vilken storlek bilder och videor kommer att skickas som.";
"settings_confirm_media_size" = "Bekräfta storlek vid sparning";
"settings_sending_media" = "SÄNDNING AV BILDER OCH VIDEO";

View file

@ -575,3 +575,114 @@
"secure_backup_setup_banner_title" = "Безпечне резервне копіювання";
"room_details_direct_chat" = "Особиста бесіда";
"room_participants_action_section_direct_chats" = "Особисті бесіди";
"version_check_modal_action_title_deprecated" = "Дізнайтеся як";
"version_check_modal_title_deprecated" = "Ми більше не підтримуємо iOS %@";
"version_check_modal_action_title_supported" = "Зрозуміло";
"voice_message_lock_screen_placeholder" = "Голосове повідомлення";
"voice_message_remaining_recording_time" = "Залишилося %@s";
"side_menu_action_invite_friends" = "Запросити друзів";
// Mark: - Side menu
"side_menu_reveal_action_accessibility_label" = "Ліва панель";
"user_avatar_view_accessibility_hint" = "Змінити аватар користувача";
// Mark: - User avatar view
"user_avatar_view_accessibility_label" = "аватар";
"room_intro_cell_information_dm_sentence1_part3" = ". ";
"room_intro_cell_information_room_without_topic_sentence2_part1" = "Додати тему";
"room_intro_cell_information_room_with_topic_sentence2" = "Тема: %@";
"room_intro_cell_information_room_sentence1_part3" = ". ";
"room_intro_cell_information_room_sentence1_part1" = "Це початок ";
// Mark: - Room creation introduction cell
"room_intro_cell_add_participants_action" = "Додати людей";
"room_avatar_view_accessibility_hint" = "Змінити аватар кімнати";
// Mark: - Room avatar view
"room_avatar_view_accessibility_label" = "аватар";
// MARK: - Home
"home_empty_view_title" = "Вітаємо у %@,\n%@";
"call_transfer_users" = "Користувачі";
"create_room_placeholder_address" = "#testroom:matrix.org";
"create_room_section_header_address" = "Адреса кімнати";
"create_room_type_public" = "Загальнодоступна кімната";
"create_room_type_private" = "Приватна кімната";
"create_room_section_header_type" = "Тип кімнати";
"create_room_section_footer_encryption" = "Шифрування не може бути вимкнено.";
"create_room_enable_encryption" = "Увімкнути шифрування";
"create_room_section_header_encryption" = "Шифрування кімнати";
"biometrics_desetup_disable_button_title_x" = "Вимкнути %@";
"biometrics_desetup_title_x" = "Вимкнути %@";
"biometrics_setup_subtitle" = "Заощадьте час";
"biometrics_setup_enable_button_title_x" = "Увімкнути %@";
"biometrics_setup_title_x" = "Увімкнути %@";
"biometrics_settings_enable_x" = "Увімкнути %@";
"biometrics_mode_face_id" = "Face ID";
// MARK: - Biometrics Protection
"biometrics_mode_touch_id" = "Touch ID";
"pin_protection_settings_change_pin" = "Змінити PIN-код";
"pin_protection_settings_enable_pin" = "Увімкнути PIN-код";
"pin_protection_settings_enabled_forced" = "PIN-код увімкнено";
"pin_protection_settings_section_header_x" = "PIN-код і %@";
"pin_protection_mismatch_error_message" = "Повторіть спробу";
"pin_protection_mismatch_error_title" = "PIN-коди відрізняються";
"pin_protection_reset_alert_action_reset" = "Скинути";
"pin_protection_reset_alert_title" = "Скинути PIN-код";
"pin_protection_forgot_pin" = "Забули PIN-код";
"pin_protection_enter_pin" = "Введіть свій PIN-код";
"pin_protection_confirm_pin_to_change" = "Підтвердьте PIN-код, щоб змінити його";
"pin_protection_confirm_pin_to_disable" = "Підтвердьте PIN-код, щоб вимкнути його";
"pin_protection_confirm_pin" = "Підтвердьте PIN-код";
"pin_protection_choose_pin" = "Створіть PIN-код для безпеки";
"pin_protection_choose_pin_welcome_after_register" = "Вітаємо.";
// MARK: - PIN Protection
"pin_protection_choose_pin_welcome_after_login" = "З поверненням.";
"major_update_done_action" = "Зрозуміло";
"secrets_setup_recovery_passphrase_validate_action" = "Готово";
"secrets_setup_recovery_key_done_action" = "Готово";
"secrets_setup_recovery_key_loading" = "Завантаження…";
"user_verification_session_details_untrusted_title" = "Не довірені";
// Session details
"user_verification_session_details_trusted_title" = "Довірені";
"user_verification_sessions_list_session_untrusted" = "Не довірені";
"user_verification_sessions_list_session_trusted" = "Довірені";
"user_verification_sessions_list_table_title" = "Сеанси";
"user_verification_sessions_list_user_trust_level_unknown_title" = "Невідомо";
"user_verification_sessions_list_user_trust_level_warning_title" = "Попередження";
// MARK: QR code
"key_verification_verify_qr_code_title" = "Підтвердити скануванням";
// Incoming key verification request
"key_verification_incoming_request_incoming_alert_message" = "%@ просить підтвердження";
"key_verification_tile_conclusion_warning_title" = "Не довірений вхід";
"key_verification_tile_conclusion_done_title" = "Підтверджений";
"key_verification_tile_request_incoming_approval_accept" = "Прийняти";
"key_verification_tile_request_status_accepted" = "Ви прийняли";
"key_verification_tile_request_status_cancelled" = "%@ скасовує";
"key_verification_tile_request_status_cancelled_by_me" = "Ви скасували";
"key_verification_tile_request_status_waiting" = "Очікування…";
"key_verification_tile_request_status_data_loading" = "Завантаження даних…";
"key_verification_tile_request_outgoing_title" = "Підтвердження надіслано";
// Tiles
"key_verification_tile_request_incoming_title" = "Запит підтвердження";
"space_beta_announce_badge" = "БЕТА";
"space_beta_announce_title" = "Простори скоро з'являться";
"space_beta_announce_subtitle" = "Нова версія спільнот";
"space_beta_announce_information" = "Простори — це новий спосіб об'єднати кімнати та людей. Їх ще не додано на iOS, але ви вже можете користуватися ними у вебпереглядачі та на комп'ютері.";

View file

@ -458,3 +458,4 @@
// Share extension
"share_extension_auth_prompt" = "Đăng nhập vào ứng dụng chính để chia sẻ nội dung";
"share_extension_failed_to_encrypt" = "Gửi thất bại. Kiểm tra cài đặt bảo mật phòng trong ứng dụng chính";
"title_groups" = "Cộng đồng";

View file

@ -1484,3 +1484,8 @@
"settings_mentions_and_keywords" = "提及和关键词";
"settings_default" = "默认通知";
"settings_notifications" = "通知";
"settings_show_url_previews_description" = "预览只会在未加密的房间里显示。";
"settings_show_url_previews" = "显示内联 URL 预览";
"settings_confirm_media_size_description" = "当打开此选项时,你会被要求确认将被发送的图片和视频的大小。";
"settings_confirm_media_size" = "发送时确认大小";
"settings_sending_media" = "发送图片和视频";

View file

@ -0,0 +1,32 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
extension MXKImageView {
@objc func vc_setRoomAvatarImage(with url: String?, displayName: String, mediaManager: MXMediaManager) {
// Use the display name to prepare the default avatar image.
let avatarImage = AvatarGenerator.generateAvatar(forText: displayName)
if let avatarUrl = url {
self.enableInMemoryCache = true
self.setImageURI(avatarUrl, withType: nil, andImageOrientation: .up, toFitViewSize: self.frame.size, with: MXThumbnailingMethodCrop, previewImage: avatarImage, mediaManager: mediaManager)
} else {
self.image = avatarImage
}
self.contentMode = .scaleAspectFill
}
}

View file

@ -32,6 +32,8 @@ typedef NS_ENUM(NSUInteger, RoomEncryptionTrustLevel) {
*/
@interface MXRoomSummary (Riot)
@property(nonatomic, readonly) BOOL isJoined;
/**
Set the room avatar in the dedicated MXKImageView.
The riot style implies to use in order :

View file

@ -77,4 +77,9 @@
return roomEncryptionTrustLevel;
}
- (BOOL)isJoined
{
return self.membership == MXMembershipJoin || self.membershipTransitionState == MXMembershipTransitionStateJoined;
}
@end

View file

@ -32,6 +32,16 @@ extension UIView {
}
}
/// Add a subview matching the safe area of the parent view using autolayout
@objc func vc_addSubViewMatchingParentSafeArea(_ subView: UIView) {
self.addSubview(subView)
subView.translatesAutoresizingMaskIntoConstraints = false
subView.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor).isActive = true
subView.topAnchor.constraint(equalTo: self.safeAreaLayoutGuide.topAnchor).isActive = true
subView.trailingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.trailingAnchor).isActive = true
subView.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor).isActive = true
}
@objc func vc_removeAllSubviews() {
for subView in self.subviews {
subView.removeFromSuperview()

View file

@ -184,8 +184,18 @@ internal enum Asset {
internal static let sideMenuActionIconSettings = ImageAsset(name: "side_menu_action_icon_settings")
internal static let sideMenuActionIconShare = ImageAsset(name: "side_menu_action_icon_share")
internal static let sideMenuIcon = ImageAsset(name: "side_menu_icon")
internal static let sideMenuNotifIcon = ImageAsset(name: "side_menu_notif_icon")
internal static let featureUnavaibleArtwork = ImageAsset(name: "feature_unavaible_artwork")
internal static let featureUnavaibleArtworkDark = ImageAsset(name: "feature_unavaible_artwork_dark")
internal static let spaceHomeIcon = ImageAsset(name: "space_home_icon")
internal static let spaceMenuClose = ImageAsset(name: "space_menu_close")
internal static let spaceMenuLeave = ImageAsset(name: "space_menu_leave")
internal static let spaceMenuMembers = ImageAsset(name: "space_menu_members")
internal static let spaceMenuRooms = ImageAsset(name: "space_menu_rooms")
internal static let spaceRoomIcon = ImageAsset(name: "space_room_icon")
internal static let spaceTypeIcon = ImageAsset(name: "space_type_icon")
internal static let spaceUserIcon = ImageAsset(name: "space_user_icon")
internal static let spacesMore = ImageAsset(name: "spaces_more")
internal static let tabFavourites = ImageAsset(name: "tab_favourites")
internal static let tabGroups = ImageAsset(name: "tab_groups")
internal static let tabHome = ImageAsset(name: "tab_home")

View file

@ -244,11 +244,36 @@ internal enum StoryboardScene {
internal static let initialScene = InitialSceneType<Riot.SimpleScreenTemplateViewController>(storyboard: SimpleScreenTemplateViewController.self)
}
internal enum SpaceChildRoomDetailViewController: StoryboardType {
internal static let storyboardName = "SpaceChildRoomDetailViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceChildRoomDetailViewController>(storyboard: SpaceChildRoomDetailViewController.self)
}
internal enum SpaceDetailViewController: StoryboardType {
internal static let storyboardName = "SpaceDetailViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceDetailViewController>(storyboard: SpaceDetailViewController.self)
}
internal enum SpaceExploreRoomViewController: StoryboardType {
internal static let storyboardName = "SpaceExploreRoomViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceExploreRoomViewController>(storyboard: SpaceExploreRoomViewController.self)
}
internal enum SpaceFeatureUnaivableViewController: StoryboardType {
internal static let storyboardName = "SpaceFeatureUnaivableViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceFeatureUnaivableViewController>(storyboard: SpaceFeatureUnaivableViewController.self)
}
internal enum SpaceListViewController: StoryboardType {
internal static let storyboardName = "SpaceListViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceListViewController>(storyboard: SpaceListViewController.self)
}
internal enum SpaceMenuViewController: StoryboardType {
internal static let storyboardName = "SpaceMenuViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceMenuViewController>(storyboard: SpaceMenuViewController.self)
}
internal enum TemplateScreenViewController: StoryboardType {
internal static let storyboardName = "TemplateScreenViewController"

View file

@ -2083,6 +2083,26 @@ public class VectorL10n: NSObject {
public static var leave: String {
return VectorL10n.tr("Vector", "leave")
}
/// Leave all rooms and spaces
public static var leaveSpaceAndAllRoomsAction: String {
return VectorL10n.tr("Vector", "leave_space_and_all_rooms_action")
}
/// Are you sure you want to leave %@? Do you also want to leave all rooms and spaces of this space?
public static func leaveSpaceMessage(_ p1: String) -> String {
return VectorL10n.tr("Vector", "leave_space_message", p1)
}
/// You are admin of this space, ensure that you have transferred admin right to another member before leaving.
public static var leaveSpaceMessageAdminWarning: String {
return VectorL10n.tr("Vector", "leave_space_message_admin_warning")
}
/// Don't leave any rooms
public static var leaveSpaceOnlyAction: String {
return VectorL10n.tr("Vector", "leave_space_only_action")
}
/// Leave %@
public static func leaveSpaceTitle(_ p1: String) -> String {
return VectorL10n.tr("Vector", "leave_space_title", p1)
}
/// Less
public static var less: String {
return VectorL10n.tr("Vector", "less")
@ -2191,6 +2211,10 @@ public class VectorL10n: NSObject {
public static var on: String {
return VectorL10n.tr("Vector", "on")
}
/// Open
public static var `open`: String {
return VectorL10n.tr("Vector", "open")
}
/// or
public static var or: String {
return VectorL10n.tr("Vector", "or")
@ -3419,6 +3443,10 @@ public class VectorL10n: NSObject {
public static var roomRecentsStartChatWith: String {
return VectorL10n.tr("Vector", "room_recents_start_chat_with")
}
/// SUGGESTED ROOMS
public static var roomRecentsSuggestedRoomsSection: String {
return VectorL10n.tr("Vector", "room_recents_suggested_rooms_section")
}
/// Can't find this room. Make sure it exists
public static var roomRecentsUnknownRoomErrorMessage: String {
return VectorL10n.tr("Vector", "room_recents_unknown_room_error_message")
@ -4791,6 +4819,14 @@ public class VectorL10n: NSObject {
public static var socialLoginListTitleSignUp: String {
return VectorL10n.tr("Vector", "social_login_list_title_sign_up")
}
/// Change space avatar
public static var spaceAvatarViewAccessibilityHint: String {
return VectorL10n.tr("Vector", "space_avatar_view_accessibility_hint")
}
/// avatar
public static var spaceAvatarViewAccessibilityLabel: String {
return VectorL10n.tr("Vector", "space_avatar_view_accessibility_label")
}
/// BETA
public static var spaceBetaAnnounceBadge: String {
return VectorL10n.tr("Vector", "space_beta_announce_badge")
@ -4819,6 +4855,78 @@ public class VectorL10n: NSObject {
public static var spaceFeatureUnavailableTitle: String {
return VectorL10n.tr("Vector", "space_feature_unavailable_title")
}
/// Ban from this space
public static var spaceParticipantsActionBan: String {
return VectorL10n.tr("Vector", "space_participants_action_ban")
}
/// Remove from this space
public static var spaceParticipantsActionRemove: String {
return VectorL10n.tr("Vector", "space_participants_action_remove")
}
/// Private space
public static var spacePrivateJoinRule: String {
return VectorL10n.tr("Vector", "space_private_join_rule")
}
/// Public space
public static var spacePublicJoinRule: String {
return VectorL10n.tr("Vector", "space_public_join_rule")
}
/// space
public static var spaceTag: String {
return VectorL10n.tr("Vector", "space_tag")
}
/// Adding rooms coming soon
public static var spacesAddRoomsComingSoonTitle: String {
return VectorL10n.tr("Vector", "spaces_add_rooms_coming_soon_title")
}
/// This feature hasnt been implemented here, but its on the way. For now, you can do that with Element on your computer.
public static var spacesComingSoonDetail: String {
return VectorL10n.tr("Vector", "spaces_coming_soon_detail")
}
/// Coming soon
public static var spacesComingSoonTitle: String {
return VectorL10n.tr("Vector", "spaces_coming_soon_title")
}
/// Some rooms may be hidden because theyre private and you need an invite.
public static var spacesEmptySpaceDetail: String {
return VectorL10n.tr("Vector", "spaces_empty_space_detail")
}
/// This space has no rooms (yet)
public static var spacesEmptySpaceTitle: String {
return VectorL10n.tr("Vector", "spaces_empty_space_title")
}
/// Explore rooms
public static var spacesExploreRooms: String {
return VectorL10n.tr("Vector", "spaces_explore_rooms")
}
/// Home
public static var spacesHomeSpaceTitle: String {
return VectorL10n.tr("Vector", "spaces_home_space_title")
}
/// Invites coming soon
public static var spacesInvitesComingSoonTitle: String {
return VectorL10n.tr("Vector", "spaces_invites_coming_soon_title")
}
/// Spaces
public static var spacesLeftPanelTitle: String {
return VectorL10n.tr("Vector", "spaces_left_panel_title")
}
/// Looking for someone not in %@? For now, you can invite them on web or desktop.
public static func spacesNoMemberFoundDetail(_ p1: String) -> String {
return VectorL10n.tr("Vector", "spaces_no_member_found_detail", p1)
}
/// No results found
public static var spacesNoResultFoundTitle: String {
return VectorL10n.tr("Vector", "spaces_no_result_found_title")
}
/// Some results may be hidden because theyre private and you need an invite to join them.
public static var spacesNoRoomFoundDetail: String {
return VectorL10n.tr("Vector", "spaces_no_room_found_detail")
}
/// Suggested
public static var spacesSuggestedRoom: String {
return VectorL10n.tr("Vector", "spaces_suggested_room")
}
/// Start
public static var start: String {
return VectorL10n.tr("Vector", "start")

View file

@ -34,6 +34,10 @@ extension UserSessionsService {
@objcMembers
class UserSessionsService: NSObject {
// MARK: - Singleton
static public let shared: UserSessionsService = UserSessionsService()
// MARK: - Properties
// MARK: Private

View file

@ -97,6 +97,14 @@
*/
- (instancetype)initWithPublicRoom:(MXPublicRoom*)publicRoom andSession:(MXSession*)mxSession;
/**
Contructors.
@param childInfo MXSpaceChildInfo instance that describes the child.
@param mxSession the session to open the room preview with.
*/
- (instancetype)initWithSpaceChildInfo:(MXSpaceChildInfo*)childInfo andSession:(MXSession*)mxSession;
/**
Attempt to peek into the room to get room data (state, messages history, etc).

View file

@ -16,6 +16,7 @@
*/
#import "RoomPreviewData.h"
#import <MatrixSDK-Swift.h>
@implementation RoomPreviewData
@ -79,6 +80,21 @@
return self;
}
- (instancetype)initWithSpaceChildInfo:(MXSpaceChildInfo*)childInfo andSession:(MXSession*)mxSession
{
self = [self init];
if (self)
{
_roomId = childInfo.childRoomId;
_roomName = childInfo.name;
_roomAvatarUrl = childInfo.avatarUrl;
_roomTopic = childInfo.topic;
_numJoinedMembers = childInfo.activeMemberCount;
_mxSession = mxSession;
}
return self;
}
- (void)dealloc
{
if (_roomDataSource)

View file

@ -56,6 +56,8 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
return self.userSessionsService.mainUserSession?.matrixSession
}
private var currentSpaceId: String?
// MARK: Public
var childCoordinators: [Coordinator] = []
@ -65,7 +67,7 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
init(router: RootRouterType, window: UIWindow) {
self.rootRouter = router
self.customSchemeURLParser = CustomSchemeURLParser()
self.userSessionsService = UserSessionsService()
self.userSessionsService = UserSessionsService.shared
super.init()
@ -148,7 +150,7 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
private func addSideMenu() {
let appInfo = AppInfo.current
let coordinatorParameters = SideMenuCoordinatorParameters(userSessionsService: self.userSessionsService, appInfo: appInfo)
let coordinatorParameters = SideMenuCoordinatorParameters(appNavigator: self.appNavigator, userSessionsService: self.userSessionsService, appInfo: appInfo)
let coordinator = SideMenuCoordinator(parameters: coordinatorParameters)
coordinator.delegate = self
@ -187,6 +189,29 @@ final class AppCoordinator: NSObject, AppCoordinatorType {
FLEXManager.shared.showExplorer()
#endif
}
fileprivate func navigate(to destination: AppNavigatorDestination) {
switch destination {
case .homeSpace:
MXLog.verbose("Switch to home space")
self.navigateToSpace(with: nil)
case .space(let spaceId):
MXLog.verbose("Switch to space with id: \(spaceId)")
self.navigateToSpace(with: spaceId)
}
}
private func navigateToSpace(with spaceId: String?) {
guard spaceId != self.currentSpaceId else {
MXLog.verbose("Space with id: \(String(describing: spaceId)) is already selected")
return
}
self.currentSpaceId = spaceId
// Reload split view with selected space id
self.splitViewCoordinator?.start(with: spaceId)
}
}
// MARK: - LegacyAppDelegateDelegate
@ -218,6 +243,10 @@ extension AppCoordinator: LegacyAppDelegateDelegate {
func legacyAppDelegate(_ legacyAppDelegate: LegacyAppDelegate!, didRemove account: MXKAccount!) {
self.userSessionsService.removeUserSession(relatedToAccount: account)
}
func legacyAppDelegate(_ legacyAppDelegate: LegacyAppDelegate!, didNavigateToSpaceWithId spaceId: String!) {
self.sideMenuCoordinator?.select(spaceWithId: spaceId)
}
}
// MARK: - SplitViewCoordinatorDelegate
@ -239,6 +268,8 @@ extension AppCoordinator: SideMenuCoordinatorDelegate {
fileprivate class AppNavigator: AppNavigatorProtocol {
// swiftlint:enable private_over_fileprivate
// MARK: - Properties
private unowned let appCoordinator: AppCoordinator
let alert: AlertPresentable
@ -251,8 +282,16 @@ fileprivate class AppNavigator: AppNavigatorProtocol {
return SideMenuPresenter(sideMenuCoordinator: sideMenuCoordinator)
}()
// MARK: - Setup
init(appCoordinator: AppCoordinator) {
self.appCoordinator = appCoordinator
self.alert = AppAlertPresenter(legacyAppDelegate: appCoordinator.legacyAppDelegate)
}
// MARK: - Public
func navigate(to destination: AppNavigatorDestination) {
self.appCoordinator.navigate(to: destination)
}
}

View file

@ -18,9 +18,13 @@ import Foundation
/// AppNavigatorProtocol abstract a navigator at app level.
/// It enables to perform the navigation within the global app scope (open the side menu, open a room and so on)
/// Note: Use a destination enum like presented here https://www.swiftbysundell.com/articles/navigation-in-swift/#where-to-navigator or use simple methods like Element Android Navigator
/// Note: Presentation of the pattern here https://www.swiftbysundell.com/articles/navigation-in-swift/#where-to-navigator
protocol AppNavigatorProtocol {
var sideMenu: SideMenuPresentable { get }
var alert: AlertPresentable { get }
/// Navigate to a destination screen or a state
/// Do not use protocol with associatedtype for the moment like presented here https://www.swiftbysundell.com/articles/navigation-in-swift/#where-to-navigator use a separate enum
func navigate(to destination: AppNavigatorDestination)
}

View file

@ -0,0 +1,27 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
/// Supported destinations used by AppNavigator to navigate in screen hierarchy
enum AppNavigatorDestination {
/// Show home space
case homeSpace
/// Show a space with specific id
case space(_ spaceId: String)
}

View file

@ -241,6 +241,29 @@ UINavigationControllerDelegate
*/
- (BOOL)handleUniversalLinkURL:(NSURL*)universalLinkURL;
/**
Extract params from the URL fragment part (after '#') of a vector.im Universal link:
The fragment can contain a '?'. So there are two kinds of parameters: path params and query params.
It is in the form of /[pathParam1]/[pathParam2]?[queryParam1Key]=[queryParam1Value]&[queryParam2Key]=[queryParam2Value]
@note this method should be private but is used by RoomViewController. This should be moved to a univresal link parser class
@param fragment the fragment to parse.
@param outPathParams the decoded path params.
@param outQueryParams the decoded query params. If there is no query params, it will be nil.
*/
- (void)parseUniversalLinkFragment:(NSString*)fragment outPathParams:(NSArray<NSString*> **)outPathParams outQueryParams:(NSMutableDictionary **)outQueryParams;
/**
Open the dedicated space with the given ID.
This method will open only joined or invited spaces.
@note this method is temporary and should be moved to a dedicated coordinator
@param spaceId ID of the space.
*/
- (void)openSpaceWithId:(NSString*)spaceId;
#pragma mark - App version management
/**
@ -271,4 +294,6 @@ UINavigationControllerDelegate
- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didRemoveAccount:(MXKAccount*)account;
- (void)legacyAppDelegate:(LegacyAppDelegate*)legacyAppDelegate didNavigateToSpaceWithId:(NSString*)spaceId;
@end

View file

@ -87,7 +87,7 @@ NSString *const AppDelegateDidValidateEmailNotificationClientSecretKey = @"AppDe
NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUniversalLinkDidChangeNotification";
@interface LegacyAppDelegate () <GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate, PushNotificationServiceDelegate, SetPinCoordinatorBridgePresenterDelegate, CallPresenterDelegate>
@interface LegacyAppDelegate () <GDPRConsentViewControllerDelegate, KeyVerificationCoordinatorBridgePresenterDelegate, ServiceTermsModalCoordinatorBridgePresenterDelegate, PushNotificationServiceDelegate, SetPinCoordinatorBridgePresenterDelegate, CallPresenterDelegate, SpaceDetailPresenterDelegate>
{
/**
Reachability observer
@ -204,6 +204,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
@property (nonatomic, strong) ServiceTermsModalCoordinatorBridgePresenter *serviceTermsModalCoordinatorBridgePresenter;
@property (nonatomic, strong) SlidingModalPresenter *slidingModalPresenter;
@property (nonatomic, strong) SetPinCoordinatorBridgePresenter *setPinCoordinatorBridgePresenter;
@property (nonatomic, strong) SpaceDetailPresenter *spaceDetailPresenter;
/**
Used to manage on boarding steps, like create DM with riot bot
@ -1344,8 +1345,11 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if (room.summary.roomType == MXRoomTypeSpace)
{
// Indicates that spaces are not supported
[self.spaceFeatureUnavailablePresenter presentUnavailableFeatureFrom:self.presentedViewController animated:YES];
[self restoreInitialDisplay:^{
self.spaceDetailPresenter = [SpaceDetailPresenter new];
self.spaceDetailPresenter.delegate = self;
[self.spaceDetailPresenter presentForSpaceWithId:room.roomId from:self.masterNavigationController sourceView:nil session:account.mxSession animated:YES];
}];
}
else
{
@ -1361,9 +1365,9 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
// So, come back to the home VC and show its loading wheel while processing
[self restoreInitialDisplay:^{
if ([_masterTabBarController.selectedViewController isKindOfClass:MXKViewController.class])
if ([_masterTabBarController.selectedViewController isKindOfClass:MXKActivityHandlingViewController.class])
{
MXKViewController *homeViewController = (MXKViewController*)_masterTabBarController.selectedViewController;
MXKActivityHandlingViewController *homeViewController = (MXKActivityHandlingViewController*)_masterTabBarController.selectedViewController;
[homeViewController startActivityIndicator];
@ -1458,24 +1462,21 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
roomPreviewData.viaServers = queryParams[@"via"];
}
// Is it a link to an event of a room?
// If yes, the event will be displayed once the room is joined
roomPreviewData.eventId = (pathParams.count >= 3) ? pathParams[2] : nil;
// Try to get more information about the room before opening its preview
[roomPreviewData peekInRoom:^(BOOL succeeded) {
// Note: the activity indicator will not disappear if the session is not ready
[homeViewController stopActivityIndicator];
// If no data is available for this room, we name it with the known room alias (if any).
if (!succeeded && universalLinkFragmentPendingRoomAlias[roomIdOrAlias])
[account.mxSession.matrixRestClient roomSummaryWith:roomIdOrAlias via:roomPreviewData.viaServers success:^(MXPublicRoom *room) {
if ([room.roomTypeString isEqualToString:MXRoomTypeStringSpace])
{
roomPreviewData.roomName = universalLinkFragmentPendingRoomAlias[roomIdOrAlias];
}
universalLinkFragmentPendingRoomAlias = nil;
[homeViewController stopActivityIndicator];
[self showRoomPreview:roomPreviewData];
self.spaceDetailPresenter = [SpaceDetailPresenter new];
self.spaceDetailPresenter.delegate = self;
[self.spaceDetailPresenter presentForSpaceWithPublicRoom:room from:self.masterNavigationController sourceView:nil session:account.mxSession animated:YES];
}
else
{
[self peekInRoomWithId:roomIdOrAlias forPreviewData:roomPreviewData params:pathParams];
}
} failure:^(NSError *error) {
[self peekInRoomWithId:roomIdOrAlias forPreviewData:roomPreviewData params:pathParams];
}];
}
@ -1607,6 +1608,33 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
}
}
- (void)peekInRoomWithId:(NSString*)roomIdOrAlias forPreviewData:(RoomPreviewData *)roomPreviewData params:(NSArray<NSString*> *)pathParams
{
// Is it a link to an event of a room?
// If yes, the event will be displayed once the room is joined
roomPreviewData.eventId = (pathParams.count >= 3) ? pathParams[2] : nil;
MXWeakify(self);
// Try to get more information about the room before opening its preview
[roomPreviewData peekInRoom:^(BOOL succeeded) {
MXStrongifyAndReturnIfNil(self);
MXKViewController *homeViewController = (MXKViewController*)self.masterTabBarController.selectedViewController;
// Note: the activity indicator will not disappear if the session is not ready
[homeViewController stopActivityIndicator];
// If no data is available for this room, we name it with the known room alias (if any).
if (!succeeded && self->universalLinkFragmentPendingRoomAlias[roomIdOrAlias])
{
roomPreviewData.roomName = self->universalLinkFragmentPendingRoomAlias[roomIdOrAlias];
}
self->universalLinkFragmentPendingRoomAlias = nil;
[self showRoomPreview:roomPreviewData];
}];
}
/**
Extract params from the URL fragment part (after '#') of a vector.im Universal link:
@ -4382,4 +4410,50 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
[URLPreviewService.shared clearStore];
}
#pragma mark - Spaces
-(void)openSpaceWithId:(NSString *)spaceId
{
MXSession *session = mxSessionArray.firstObject;
if ([session.spaceService getSpaceWithId:spaceId]) {
[self restoreInitialDisplay:^{
[self.delegate legacyAppDelegate:self didNavigateToSpaceWithId:spaceId];
}];
}
else
{
MXWeakify(self);
__block __weak id observer = [[NSNotificationCenter defaultCenter] addObserverForName:MXSpaceService.didBuildSpaceGraph object:nil queue:nil usingBlock:^(NSNotification * _Nonnull note) {
MXStrongifyAndReturnIfNil(self);
[[NSNotificationCenter defaultCenter] removeObserver:observer];
if ([session.spaceService getSpaceWithId:spaceId]) {
[self restoreInitialDisplay:^{
[self.delegate legacyAppDelegate:self didNavigateToSpaceWithId:spaceId];
}];
}
}];
}
}
#pragma mark - SpaceDetailPresenterDelegate
- (void)spaceDetailPresenterDidComplete:(SpaceDetailPresenter *)presenter
{
self.spaceDetailPresenter = nil;
}
- (void)spaceDetailPresenter:(SpaceDetailPresenter *)presenter didOpenSpaceWithId:(NSString *)spaceId
{
self.spaceDetailPresenter = nil;
[self openSpaceWithId:spaceId];
}
- (void)spaceDetailPresenter:(SpaceDetailPresenter *)presenter didJoinSpaceWithId:(NSString *)spaceId
{
self.spaceDetailPresenter = nil;
[self openSpaceWithId:spaceId];
}
@end

View file

@ -32,7 +32,7 @@ class AvatarView: UIView, Themable {
// MARK: Private
private var theme: Theme?
private(set) var theme: Theme?
// MARK: Public
@ -106,7 +106,18 @@ class AvatarView: UIView, Themable {
return
}
let defaultavatarImage = AvatarGenerator.generateAvatar(forMatrixItem: viewData.matrixItemId, withDisplayName: viewData.displayName)
let defaultAvatarImage: UIImage?
var defaultAvatarImageContentMode: UIView.ContentMode = .scaleAspectFill
switch viewData.fallbackImage {
case .matrixItem(let matrixItemId, let matrixItemDisplayName):
defaultAvatarImage = AvatarGenerator.generateAvatar(forMatrixItem: matrixItemId, withDisplayName: matrixItemDisplayName)
case .image(let image, let contentMode):
defaultAvatarImage = image
defaultAvatarImageContentMode = contentMode ?? .scaleAspectFill
case .none:
defaultAvatarImage = nil
}
if let avatarUrl = viewData.avatarUrl {
avatarImageView.setImageURI(avatarUrl,
@ -114,13 +125,13 @@ class AvatarView: UIView, Themable {
andImageOrientation: .up,
toFitViewSize: avatarImageView.frame.size,
with: MXThumbnailingMethodScale,
previewImage: defaultavatarImage,
previewImage: defaultAvatarImage,
mediaManager: viewData.mediaManager)
avatarImageView.contentMode = .scaleAspectFill
} else {
avatarImageView.image = defaultavatarImage
avatarImageView.image = defaultAvatarImage
avatarImageView.contentMode = defaultAvatarImageContentMode
}
avatarImageView.contentMode = .scaleAspectFill
}
func updateView() {

View file

@ -0,0 +1,34 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
struct AvatarViewData: AvatarViewDataProtocol {
/// Matrix item identifier (user id or room id)
var matrixItemId: String
/// Matrix item display name (user or room display name)
var displayName: String?
/// Matrix item avatar URL (user or room avatar url)
var avatarUrl: String?
/// Matrix media handler
var mediaManager: MXMediaManager
/// Fallback image used when avatarUrl is nil
var fallbackImage: AvatarFallbackImage?
}

View file

@ -14,7 +14,18 @@
// limitations under the License.
//
import Foundation
import UIKit
enum AvatarFallbackImage {
/// matrixItem represent a Matrix item like a room, space, user
/// matrixItemId: Matrix item identifier (user id or room id)
/// displayName: Matrix item display name (user or room display name)
case matrixItem(_ matrixItemId: String, _ displayName: String?)
/// Normal image with optional content mode
case image(_ image: UIImage, _ contentMode: UIView.ContentMode? = nil)
}
/// AvatarViewDataProtocol describe a view data that should be given to an AvatarView sublcass
protocol AvatarViewDataProtocol: AvatarProtocol {
@ -29,4 +40,7 @@ protocol AvatarViewDataProtocol: AvatarProtocol {
/// Matrix media handler
var mediaManager: MXMediaManager { get }
/// Fallback image used when avatarUrl is nil
var fallbackImage: AvatarFallbackImage? { get }
}

View file

@ -18,6 +18,7 @@
#import "RecentCellData.h"
#import "MXRoom+Riot.h"
#import "MatrixSDK-Swift.h"
@implementation RecentCellData
// trick to hide the mother class property as it is readonly one.
@ -57,7 +58,7 @@
- (void)update
{
[super update];
roomDisplayname = self.roomSummary.displayname;
roomDisplayname = self.spaceChildInfo ? self.spaceChildInfo.name: self.roomSummary.displayname;
if (!roomDisplayname.length)
{
roomDisplayname = [NSBundle mxk_localizedStringForKey:@"room_displayname_empty_room"];

View file

@ -19,6 +19,8 @@
#import "PublicRoomsDirectoryDataSource.h"
@class MXSpace;
/**
List the different modes used to prepare the recents data source.
Each mode corresponds to an application tab: Home, Favourites, People and Rooms.
@ -72,6 +74,7 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
@property (nonatomic) NSInteger conversationSection;
@property (nonatomic) NSInteger lowPrioritySection;
@property (nonatomic) NSInteger serverNoticeSection;
@property (nonatomic) NSInteger suggestedRoomsSection;
@property (nonatomic, readonly) NSArray* invitesCellDataArray;
@property (nonatomic, readonly) NSArray* favoriteCellDataArray;
@ -79,6 +82,7 @@ extern NSString *const kRecentsDataSourceTapOnDirectoryServerChange;
@property (nonatomic, readonly) NSArray* conversationCellDataArray;
@property (nonatomic, readonly) NSArray* lowPriorityCellDataArray;
@property (nonatomic, readonly) NSArray* serverNoticeCellDataArray;
@property (nonatomic, readonly) NSArray* suggestedRoomCellDataArray;
@property (nonatomic, readonly) SecureBackupBannerDisplay secureBackupBannerDisplay;
@property (nonatomic, readonly) CrossSigningBannerDisplay crossSigningBannerDisplay;

View file

@ -34,6 +34,7 @@
#define RECENTSDATASOURCE_SECTION_LOWPRIORITY 0x10
#define RECENTSDATASOURCE_SECTION_SERVERNOTICE 0x20
#define RECENTSDATASOURCE_SECTION_PEOPLE 0x40
#define RECENTSDATASOURCE_SECTION_SUGGESTED 0x80
#define RECENTSDATASOURCE_DEFAULT_SECTION_HEADER_HEIGHT 30.0
@ -60,7 +61,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
@end
@implementation RecentsDataSource
@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, secureBackupBannerSection, crossSigningBannerSection;
@synthesize directorySection, invitesSection, favoritesSection, peopleSection, conversationSection, lowPrioritySection, serverNoticeSection, suggestedRoomsSection, secureBackupBannerSection, crossSigningBannerSection;
@synthesize hiddenCellIndexPath, droppingCellIndexPath, droppingCellBackGroundView;
- (instancetype)init
@ -84,10 +85,17 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
// Set default data and view classes
[self registerCellDataClass:RecentCellData.class forCellIdentifier:kMXKRecentCellIdentifier];
[self registerSpaceServiceDidBuildGraphNotification];
}
return self;
}
- (void)dealloc
{
[self unregisterSpaceServiceDidBuildGraphNotification];
}
- (void)resetSectionIndexes
{
crossSigningBannerSection = -1;
@ -99,9 +107,9 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
conversationSection = -1;
lowPrioritySection = -1;
serverNoticeSection = -1;
suggestedRoomsSection = -1;
}
#pragma mark - Properties
- (NSArray *)invitesCellDataArray
@ -128,6 +136,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
return state.serverNoticeCellDataArray;
}
- (NSArray *)suggestedRoomCellDataArray
{
return state.suggestedRoomCellDataArray;
}
- (NSUInteger)missedFavouriteDiscussionsCount
{
@ -165,7 +177,6 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
return state.unsentMessagesGroupDiscussionsCount;
}
#pragma mark -
- (void)setDelegate:(id<MXKDataSourceDelegate>)delegate andRecentsDataSourceMode:(RecentsDataSourceMode)recentsDataSourceMode
@ -212,6 +223,23 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
return stickyHeader;
}
#pragma mark - Space Service notifications
- (void)registerSpaceServiceDidBuildGraphNotification
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(spaceServiceDidBuildGraphNotification:) name:MXSpaceService.didBuildSpaceGraph object:nil];
}
- (void)spaceServiceDidBuildGraphNotification:(NSNotification*)notification
{
[self forceRefresh];
}
- (void)unregisterSpaceServiceDidBuildGraphNotification
{
[[NSNotificationCenter defaultCenter] removeObserver:self name:MXSpaceService.didBuildSpaceGraph object:nil];
}
#pragma mark - Key backup setup banner
- (void)registerKeyBackupStateDidChangeNotification
@ -491,6 +519,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
serverNoticeSection = sectionsCount++;
}
if (self.suggestedRoomCellDataArray.count > 0)
{
suggestedRoomsSection = sectionsCount++;
}
}
return sectionsCount;
@ -543,6 +576,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
count = self.invitesCellDataArray.count;
}
else if (section == suggestedRoomsSection && !(shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_SUGGESTED))
{
count = self.suggestedRoomCellDataArray.count;
}
// Adjust this count according to the potential dragged cell.
if ([self isMovingCellSection:section])
@ -624,6 +661,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
title = NSLocalizedStringFromTable(@"room_recents_invites_section", @"Vector", nil);
}
}
else if (section == suggestedRoomsSection)
{
count = self.suggestedRoomCellDataArray.count;
title = NSLocalizedStringFromTable(@"room_recents_suggested_rooms_section", @"Vector", nil);
}
if (count)
{
@ -675,6 +717,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
sectionArray = self.serverNoticeCellDataArray;
}
else if (section == suggestedRoomsSection)
{
sectionArray = self.suggestedRoomCellDataArray;
}
BOOL highlight = NO;
for (id<MXKRecentCellDataStoring> cellData in sectionArray)
@ -760,6 +806,10 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
sectionBitwise = RECENTSDATASOURCE_SECTION_INVITES;
}
else if (section == suggestedRoomsSection)
{
sectionBitwise = RECENTSDATASOURCE_SECTION_SUGGESTED;
}
}
if (sectionBitwise)
@ -957,6 +1007,13 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
cellData = self.invitesCellDataArray[cellDataIndex];
}
}
else if (tableSection == suggestedRoomsSection)
{
if (cellDataIndex < self.suggestedRoomCellDataArray.count)
{
cellData = self.suggestedRoomCellDataArray[cellDataIndex];
}
}
return cellData;
}
@ -1013,9 +1070,19 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
id<MXKRecentCellDataStoring> cellDataStoring = cellDataArray[index];
if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession))
if (cellDataStoring.roomSummary)
{
return index;
if ([roomId isEqualToString:cellDataStoring.roomSummary.roomId] && (matrixSession == cellDataStoring.roomSummary.room.mxSession))
{
return index;
}
}
else if (cellDataStoring.spaceChildInfo)
{
if ([roomId isEqualToString:cellDataStoring.spaceChildInfo.name])
{
return index;
}
}
}
}
@ -1118,6 +1185,21 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
}
if (!indexPath && (suggestedRoomsSection >= 0))
{
index = [self cellIndexPosWithRoomId:roomId andMatrixSession:matrixSession within:self.serverNoticeCellDataArray];
if (index != NSNotFound)
{
// Check whether the low priority rooms are shrinked
if (shrinkedSectionsBitMask & RECENTSDATASOURCE_SECTION_SUGGESTED)
{
return nil;
}
indexPath = [NSIndexPath indexPathForRow:index inSection:serverNoticeSection];
}
}
return indexPath;
}
@ -1179,6 +1261,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
NSMutableArray<id<MXKRecentCellDataStoring>> *conversationCellDataArray = [NSMutableArray new];
NSMutableArray<id<MXKRecentCellDataStoring>> *lowPriorityCellDataArray = [NSMutableArray new];
NSMutableArray<id<MXKRecentCellDataStoring>> *serverNoticeCellDataArray = [NSMutableArray new];
NSMutableArray<id<MXKRecentCellDataStoring>> *suggestedRoomCellDataArray = [NSMutableArray new];
MissedDiscussionsCount *favouriteMissedDiscussionsCount = [MissedDiscussionsCount new];
MissedDiscussionsCount *directMissedDiscussionsCount = [MissedDiscussionsCount new];
@ -1206,7 +1289,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
else if (room.summary.membership == MXMembershipInvite)
{
if (!MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
if (room.summary.roomType != MXRoomTypeSpace && !MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
{
[invitesCellDataArray addObject:recentCellDataStoring];
}
@ -1215,6 +1298,14 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
{
[peopleCellDataArray addObject:recentCellDataStoring];
}
else if (recentCellDataStoring.isSuggestedRoom && recentCellDataStoring.spaceChildInfo.roomType != MXRoomTypeSpace)
{
MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId];
if (!roomSummary.isJoined)
{
[suggestedRoomCellDataArray addObject:recentCellDataStoring];
}
}
else
{
// Hide spaces from home (keep space invites)
@ -1253,13 +1344,22 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
else if (recentsDataSourceMode == RecentsDataSourceModeRooms)
{
if (recentCellDataStoring.isSuggestedRoom && recentCellDataStoring.spaceChildInfo.roomType != MXRoomTypeSpace)
{
MXRoomSummary *roomSummary = [mxSession roomSummaryWithRoomId:recentCellDataStoring.spaceChildInfo.childRoomId];
BOOL isJoined = roomSummary.membership == MXMembershipJoin || roomSummary.membershipTransitionState == MXMembershipTransitionStateJoined;
if (!isJoined)
{
[suggestedRoomCellDataArray addObject:recentCellDataStoring];
}
}
// Consider only non direct rooms.
if (!room.isDirect)
else if (!room.isDirect)
{
// Keep only the invites, the favourites and the rooms without tag and room type different from space
if (room.summary.membership == MXMembershipInvite)
{
if (!MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
if (room.summary.roomType != MXRoomTypeSpace && !MXSDKOptions.sharedInstance.autoAcceptRoomInvites)
{
[invitesCellDataArray addObject:recentCellDataStoring];
}
@ -1348,6 +1448,15 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
// Sort each rooms collection by considering first the rooms with some missed notifs, the rooms with unread, then the others.
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
if (recentCellData1.spaceChildInfo && !recentCellData2.spaceChildInfo)
{
return NSOrderedDescending;
}
if (recentCellData2.spaceChildInfo && !recentCellData1.spaceChildInfo)
{
return NSOrderedAscending;
}
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
{
@ -1417,6 +1526,15 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
// Sort each rooms collection by considering first the rooms with some unread messages then the others.
comparator = ^NSComparisonResult(id<MXKRecentCellDataStoring> recentCellData1, id<MXKRecentCellDataStoring> recentCellData2) {
if (recentCellData1.spaceChildInfo && !recentCellData2.spaceChildInfo)
{
return NSOrderedDescending;
}
if (recentCellData2.spaceChildInfo && !recentCellData1.spaceChildInfo)
{
return NSOrderedAscending;
}
if (recentCellData1.roomSummary.room.sentStatus != RoomSentStatusOk
&& recentCellData2.roomSummary.room.sentStatus == RoomSentStatusOk)
{
@ -1489,6 +1607,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
MXLogDebug(@"[RecentsDataSource] refreshRoomsSections: Done in %.0fms", [[NSDate date] timeIntervalSinceDate:startDate] * 1000);
MXLogDebug(@"[Spaces] refreshRoomsSections with %ld suggested room", suggestedRoomCellDataArray.count);
return [[RecentsDataSourceState alloc]
initWithInvitesCellDataArray:invitesCellDataArray
@ -1497,6 +1616,7 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
conversationCellDataArray:conversationCellDataArray
lowPriorityCellDataArray:lowPriorityCellDataArray
serverNoticeCellDataArray:serverNoticeCellDataArray
suggestedRoomCellDataArray:suggestedRoomCellDataArray
favouriteMissedDiscussionsCount:favouriteMissedDiscussionsCount
directMissedDiscussionsCount:directMissedDiscussionsCount
groupMissedDiscussionsCount:groupMissedDiscussionsCount

View file

@ -29,6 +29,7 @@ class RecentsDataSourceState: NSObject {
let conversationCellDataArray: [MXKRecentCellDataStoring]
let lowPriorityCellDataArray: [MXKRecentCellDataStoring]
let serverNoticeCellDataArray: [MXKRecentCellDataStoring]
let suggestedRoomCellDataArray: [MXKRecentCellDataStoring]
// MARK: Notifications counts
let favouriteMissedDiscussionsCount: MissedDiscussionsCount
@ -47,6 +48,7 @@ class RecentsDataSourceState: NSObject {
conversationCellDataArray: [MXKRecentCellDataStoring],
lowPriorityCellDataArray: [MXKRecentCellDataStoring],
serverNoticeCellDataArray: [MXKRecentCellDataStoring],
suggestedRoomCellDataArray: [MXKRecentCellDataStoring],
favouriteMissedDiscussionsCount: MissedDiscussionsCount,
directMissedDiscussionsCount: MissedDiscussionsCount,
groupMissedDiscussionsCount: MissedDiscussionsCount,
@ -58,6 +60,7 @@ class RecentsDataSourceState: NSObject {
self.conversationCellDataArray = conversationCellDataArray
self.lowPriorityCellDataArray = lowPriorityCellDataArray
self.serverNoticeCellDataArray = serverNoticeCellDataArray
self.suggestedRoomCellDataArray = suggestedRoomCellDataArray
self.favouriteMissedDiscussionsCount = favouriteMissedDiscussionsCount
self.directMissedDiscussionsCount = directMissedDiscussionsCount
self.groupMissedDiscussionsCount = groupMissedDiscussionsCount

View file

@ -72,6 +72,8 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
@property (nonatomic, strong) RoomsDirectoryCoordinatorBridgePresenter *roomsDirectoryCoordinatorBridgePresenter;
@property (nonatomic, strong) ExploreRoomCoordinatorBridgePresenter *exploreRoomsCoordinatorBridgePresenter;
@property (nonatomic, strong) SpaceFeatureUnavailablePresenter *spaceFeatureUnavailablePresenter;
@property (nonatomic, strong) CustomSizedPresentationController *customSizedPresentationController;
@ -1950,7 +1952,13 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
return;
}
if (RiotSettings.shared.roomsAllowToJoinPublicRooms)
if (self.dataSource.currentSpace)
{
self.exploreRoomsCoordinatorBridgePresenter = [[ExploreRoomCoordinatorBridgePresenter alloc] initWithSession:self.mainSession spaceId:self.dataSource.currentSpace.spaceId];
self.exploreRoomsCoordinatorBridgePresenter.delegate = self;
[self.exploreRoomsCoordinatorBridgePresenter presentFrom:self animated:YES];
}
else if (RiotSettings.shared.roomsAllowToJoinPublicRooms)
{
self.roomsDirectoryCoordinatorBridgePresenter = [[RoomsDirectoryCoordinatorBridgePresenter alloc] initWithSession:self.mainSession dataSource:[self.recentsDataSource.publicRoomsDirectoryDataSource copy]];
self.roomsDirectoryCoordinatorBridgePresenter.delegate = self;
@ -2064,6 +2072,18 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
[self dispayRoomWithRoomId:roomId inMatrixSession:matrixSession];
}
- (void)recentListViewController:(MXKRecentListViewController *)recentListViewController didSelectSuggestedRoom:(MXSpaceChildInfo *)childInfo
{
RoomPreviewData *previewData = [[RoomPreviewData alloc] initWithSpaceChildInfo:childInfo andSession:self.mainSession];
[self startActivityIndicator];
MXWeakify(self);
[previewData peekInRoom:^(BOOL succeeded) {
MXStrongifyAndReturnIfNil(self);
[self stopActivityIndicator];
[[AppDelegate theDelegate].masterTabBarController showRoomPreview:previewData];
}];
}
#pragma mark - UISearchBarDelegate
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
@ -2270,6 +2290,16 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
}
}
#pragma mark - ExploreRoomCoordinatorBridgePresenterDelegate
- (void)exploreRoomCoordinatorBridgePresenterDelegateDidComplete:(ExploreRoomCoordinatorBridgePresenter *)coordinatorBridgePresenter {
MXWeakify(self);
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
MXStrongifyAndReturnIfNil(self);
self.exploreRoomsCoordinatorBridgePresenter = nil;
}];
}
#pragma mark - RoomNotificationSettingsCoordinatorBridgePresenterDelegate
-(void)roomNotificationSettingsCoordinatorBridgePresenterDelegateDidComplete:(RoomNotificationSettingsCoordinatorBridgePresenter *)coordinatorBridgePresenter
{

View file

@ -76,7 +76,7 @@
self.lastEventDate.text = roomCellData.lastEventDate;
// Manage lastEventAttributedTextMessage optional property
if ([roomCellData respondsToSelector:@selector(lastEventAttributedTextMessage)])
if (!roomCellData.spaceChildInfo && [roomCellData respondsToSelector:@selector(lastEventAttributedTextMessage)])
{
// Force the default text color for the last message (cancel highlighted message color)
NSMutableAttributedString *lastEventDescription = [[NSMutableAttributedString alloc] initWithAttributedString:roomCellData.lastEventAttributedTextMessage];
@ -124,7 +124,14 @@
self.roomTitle.font = [UIFont systemFontOfSize:17 weight:UIFontWeightMedium];
}
[roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar];
if (roomCellData.spaceChildInfo)
{
[self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.spaceChildInfo.avatarUrl displayName:roomCellData.spaceChildInfo.displayName mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager];
}
else
{
[self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.roomSummary.avatar displayName:roomCellData.roomSummary.displayname mediaManager:roomCellData.roomSummary.mxSession.mediaManager];
}
}
else
{

View file

@ -86,16 +86,7 @@
{
_showCustomAccessoryView = show;
if (show)
{
self.customAccessViewWidthConstraint.constant = 25;
self.customAccessoryViewLeadingConstraint.constant = 13;
}
else
{
self.customAccessViewWidthConstraint.constant = 0;
self.customAccessoryViewLeadingConstraint.constant = 0;
}
self.customAccessViewWidthConstraint.constant = show ? 25 : 0;
}
- (void)setShowMatrixIdInDisplayName:(BOOL)showMatrixIdInDisplayName

View file

@ -26,7 +26,7 @@
#import "MXRoom+Riot.h"
@interface HomeViewController () <SecureBackupSetupCoordinatorBridgePresenterDelegate>
@interface HomeViewController () <SecureBackupSetupCoordinatorBridgePresenterDelegate, SpaceMembersCoordinatorBridgePresenterDelegate>
{
RecentsDataSource *recentsDataSource;
@ -48,6 +48,8 @@
@property (nonatomic, assign, readwrite) BOOL roomListDataReady;
@property(nonatomic) SpaceMembersCoordinatorBridgePresenter *spaceMembersCoordinatorBridgePresenter;
@end
@implementation HomeViewController
@ -254,7 +256,72 @@
[self cancelEditionMode:YES];
}
[super onPlusButtonPressed];
if (recentsDataSource.currentSpace != nil)
{
[self showPlusMenuForSpace];
}
else
{
[super onPlusButtonPressed];
}
}
- (void)showPlusMenuForSpace
{
__weak typeof(self) weakSelf = self;
[currentAlert dismissViewControllerAnimated:NO completion:nil];
currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet];
[currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"spaces_explore_rooms", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
[self showRoomDirectory];
}
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:NSLocalizedStringFromTable(@"room_details_people", @"Vector", nil)
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
self.spaceMembersCoordinatorBridgePresenter = [[SpaceMembersCoordinatorBridgePresenter alloc] initWithUserSessionsService:[UserSessionsService shared] session:self.mainSession spaceId:self.dataSource.currentSpace.spaceId];
self.spaceMembersCoordinatorBridgePresenter.delegate = self;
[self.spaceMembersCoordinatorBridgePresenter presentFrom:self animated:YES];
}
}]];
[currentAlert addAction:[UIAlertAction actionWithTitle:[NSBundle mxk_localizedStringForKey:@"cancel"]
style:UIAlertActionStyleCancel
handler:^(UIAlertAction * action) {
if (weakSelf)
{
typeof(self) self = weakSelf;
self->currentAlert = nil;
}
}]];
[currentAlert popoverPresentationController].sourceView = plusButtonImageView;
[currentAlert popoverPresentationController].sourceRect = plusButtonImageView.bounds;
[currentAlert mxk_setAccessibilityIdentifier:@"RecentsVCCreateRoomAlert"];
[self presentViewController:currentAlert animated:YES completion:nil];
}
- (void)cancelEditionMode:(BOOL)forceRefresh
@ -562,7 +629,14 @@
id<MXKRecentCellDataStoring> renderedCellData = (id<MXKRecentCellDataStoring>)roomCollectionViewCell.renderedCellData;
[self.delegate recentListViewController:self didSelectRoom:renderedCellData.roomSummary.roomId inMatrixSession:renderedCellData.roomSummary.room.mxSession];
if (renderedCellData.isSuggestedRoom)
{
[self.delegate recentListViewController:self didSelectSuggestedRoom:renderedCellData.spaceChildInfo];
}
else
{
[self.delegate recentListViewController:self didSelectRoom:renderedCellData.roomSummary.roomId inMatrixSession:renderedCellData.roomSummary.room.mxSession];
}
}
// Hide the keyboard when user select a room
@ -861,7 +935,17 @@
+ recentsDataSource.peopleCellDataArray.count
+ recentsDataSource.conversationCellDataArray.count
+ recentsDataSource.lowPriorityCellDataArray.count
+ recentsDataSource.serverNoticeCellDataArray.count;
+ recentsDataSource.serverNoticeCellDataArray.count
+ recentsDataSource.suggestedRoomCellDataArray.count;
}
#pragma mark - SpaceMembersCoordinatorBridgePresenterDelegate
- (void)spaceMembersCoordinatorBridgePresenterDelegateDidComplete:(SpaceMembersCoordinatorBridgePresenter *)coordinatorBridgePresenter
{
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
self.spaceMembersCoordinatorBridgePresenter = nil;
}];
}
@end

View file

@ -16,7 +16,7 @@
import Foundation
class HomeViewControllerWithBannerWrapperViewController: UIViewController, BannerPresentationProtocol {
class HomeViewControllerWithBannerWrapperViewController: MXKActivityHandlingViewController, BannerPresentationProtocol {
@objc let homeViewController: HomeViewController
private var bannerContainerView: UIView!
@ -41,6 +41,8 @@ class HomeViewControllerWithBannerWrapperViewController: UIViewController, Banne
override func viewDidLoad() {
super.viewDidLoad()
homeViewController.willMove(toParent: self)
view.backgroundColor = .clear
stackView = UIStackView()

View file

@ -130,7 +130,14 @@
}
[roomCellData.roomSummary setRoomAvatarImageIn:self.roomAvatar];
if (roomCellData.roomSummary)
{
[self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.roomSummary.avatar displayName:roomCellData.roomSummary.displayname mediaManager:roomCellData.roomSummary.mxSession.mediaManager];
}
else
{
[self.roomAvatar vc_setRoomAvatarImageWith:roomCellData.spaceChildInfo.avatarUrl displayName:roomCellData.spaceChildInfo.displayName mediaManager:roomCellData.recentsDataSource.mxSession.mediaManager];
}
}
}
@ -171,7 +178,7 @@
{
if (roomCellData)
{
return roomCellData.roomSummary.roomId;
return roomCellData.spaceChildInfo ? roomCellData.spaceChildInfo.childRoomId : roomCellData.roomSummary.roomId;
}
return nil;
}

View file

@ -26,12 +26,14 @@
#import "Riot-Swift.h"
@interface PeopleViewController ()
@interface PeopleViewController () <SpaceMembersCoordinatorBridgePresenterDelegate>
{
NSInteger directRoomsSectionNumber;
RecentsDataSource *recentsDataSource;
}
@property(nonatomic) SpaceMembersCoordinatorBridgePresenter *spaceMembersCoordinatorBridgePresenter;
@end
@implementation PeopleViewController
@ -119,7 +121,16 @@
- (void)onPlusButtonPressed
{
[self performSegueWithIdentifier:@"presentStartChat" sender:self];
if (self.dataSource.currentSpace != nil)
{
self.spaceMembersCoordinatorBridgePresenter = [[SpaceMembersCoordinatorBridgePresenter alloc] initWithUserSessionsService:[UserSessionsService shared] session:self.mainSession spaceId:self.dataSource.currentSpace.spaceId];
self.spaceMembersCoordinatorBridgePresenter.delegate = self;
[self.spaceMembersCoordinatorBridgePresenter presentFrom:self animated:YES];
}
else
{
[self performSegueWithIdentifier:@"presentStartChat" sender:self];
}
}
#pragma mark -
@ -172,4 +183,13 @@
+ recentsDataSource.conversationCellDataArray.count;
}
#pragma mark - SpaceMembersCoordinatorBridgePresenterDelegate
- (void)spaceMembersCoordinatorBridgePresenterDelegateDidComplete:(SpaceMembersCoordinatorBridgePresenter *)coordinatorBridgePresenter
{
[coordinatorBridgePresenter dismissWithAnimated:YES completion:^{
self.spaceMembersCoordinatorBridgePresenter = nil;
}];
}
@end

View file

@ -465,6 +465,11 @@
[[AppDelegate theDelegate] presentCompleteSecurityForSession:self.mainSession];
}
- (void)showRoomWithId:(NSString*)roomId
{
[[AppDelegate theDelegate] showRoom:roomId andEventId:nil withMatrixSession:self.mainSession];
}
#pragma mark - Hide/Show navigation bar border
- (void)hideNavigationBarBorder:(BOOL)isHidden
@ -518,7 +523,10 @@
{
isOneself = YES;
[otherActionsArray addObject:@(MXKRoomMemberDetailsActionLeave)];
if (self.enableLeave)
{
[otherActionsArray addObject:@(MXKRoomMemberDetailsActionLeave)];
}
if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomPowerLevels])
{
@ -754,10 +762,24 @@
title = NSLocalizedStringFromTable(@"room_participants_action_leave", @"Vector", nil);
break;
case MXKRoomMemberDetailsActionKick:
title = NSLocalizedStringFromTable(@"room_participants_action_remove", @"Vector", nil);
if (self.mxRoom.summary.roomType == MXRoomTypeSpace)
{
title = NSLocalizedStringFromTable(@"space_participants_action_remove", @"Vector", nil);
}
else
{
title = NSLocalizedStringFromTable(@"room_participants_action_remove", @"Vector", nil);
}
break;
case MXKRoomMemberDetailsActionBan:
title = NSLocalizedStringFromTable(@"room_participants_action_ban", @"Vector", nil);
if (self.mxRoom.summary.roomType == MXRoomTypeSpace)
{
title = NSLocalizedStringFromTable(@"space_participants_action_ban", @"Vector", nil);
}
else
{
title = NSLocalizedStringFromTable(@"room_participants_action_ban", @"Vector", nil);
}
break;
case MXKRoomMemberDetailsActionUnban:
title = NSLocalizedStringFromTable(@"room_participants_action_unban", @"Vector", nil);
@ -1047,7 +1069,7 @@
if (indexPath.row < directChatsArray.count)
{
// Open this room
[[AppDelegate theDelegate] showRoom:directChatsArray[indexPath.row] andEventId:nil withMatrixSession:self.mainSession];
[self showRoomWithId:directChatsArray[indexPath.row]];
}
else
{

View file

@ -85,6 +85,7 @@
@property (nonatomic) BOOL enableMention;
@property (nonatomic) BOOL showCancelBarButtonItem;
@property (nonatomic) BOOL showParticipantCustomAccessoryView;
/**
The delegate for the view controller.

View file

@ -84,6 +84,7 @@
// Setup `MXKViewControllerHandling` properties
self.enableBarTintColorStatusChange = NO;
self.rageShakeManager = [RageShakeManager sharedManager];
self.showParticipantCustomAccessoryView = YES;
}
- (void)viewDidLoad
@ -113,7 +114,11 @@
self.navigationItem.title = NSLocalizedStringFromTable(@"room_participants_title", @"Vector", nil);
if (self.mxRoom.isDirect)
if (self.mxRoom.summary.roomType == MXRoomTypeSpace)
{
_searchBarView.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
}
else if (self.mxRoom.isDirect)
{
_searchBarView.placeholder = NSLocalizedStringFromTable(@"room_participants_filter_room_members_for_dm", @"Vector", nil);
}
@ -340,7 +345,11 @@
{
self.searchBarHeader.hidden = NO;
if (self.mxRoom.isDirect)
if (self.mxRoom.summary.roomType == MXRoomTypeSpace)
{
self.searchBarView.placeholder = NSLocalizedStringFromTable(@"search_default_placeholder", @"Vector", nil);
}
else if (self.mxRoom.isDirect)
{
self.searchBarView.placeholder = NSLocalizedStringFromTable(@"room_participants_filter_room_members_for_dm", @"Vector", nil);
}
@ -870,6 +879,19 @@
}
}
- (void)showDetailFor:(MXRoomMember* _Nonnull)member from:(UIView* _Nullable)sourceView {
memberDetailsViewController = [RoomMemberDetailsViewController roomMemberDetailsViewController];
// Set delegate to handle action on member (start chat, mention)
memberDetailsViewController.delegate = self;
memberDetailsViewController.enableMention = _enableMention;
memberDetailsViewController.enableVoipCall = NO;
[memberDetailsViewController displayRoomMember:member withMatrixRoom:self.mxRoom];
[self pushViewController:memberDetailsViewController];
}
#pragma mark - UITableView data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
@ -948,6 +970,7 @@
{
ContactTableViewCell* participantCell = [tableView dequeueReusableCellWithIdentifier:@"ParticipantTableViewCellId" forIndexPath:indexPath];
participantCell.selectionStyle = UITableViewCellSelectionStyleNone;
participantCell.showCustomAccessoryView = self.showParticipantCustomAccessoryView;
participantCell.mxRoom = self.mxRoom;
@ -1185,16 +1208,8 @@
if (contact.mxMember)
{
memberDetailsViewController = [RoomMemberDetailsViewController roomMemberDetailsViewController];
// Set delegate to handle action on member (start chat, mention)
memberDetailsViewController.delegate = self;
memberDetailsViewController.enableMention = _enableMention;
memberDetailsViewController.enableVoipCall = NO;
[memberDetailsViewController displayRoomMember:contact.mxMember withMatrixRoom:self.mxRoom];
[self pushViewController:memberDetailsViewController];
UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
[self showDetailFor:contact.mxMember from:selectedCell];
}
[tableView deselectRowAtIndexPath:indexPath animated:YES];

View file

@ -19,26 +19,18 @@ import Reusable
class RoomNotificationSettingsAvatarView: UIView {
@IBOutlet weak var avatarView: MXKImageView!
@IBOutlet weak var avatarView: RoomAvatarView!
@IBOutlet weak var nameLabel: UILabel!
func configure(viewData: AvatarViewDataProtocol) {
let avatarImage = AvatarGenerator.generateAvatar(forMatrixItem: viewData.matrixItemId, withDisplayName: viewData.displayName)
avatarView.fill(with: viewData)
if let avatarUrl = viewData.avatarUrl {
avatarView.enableInMemoryCache = true
avatarView.setImageURI(avatarUrl,
withType: nil,
andImageOrientation: .up,
toFitViewSize: avatarView.frame.size,
with: MXThumbnailingMethodCrop,
previewImage: avatarImage,
mediaManager: viewData.mediaManager)
} else {
avatarView.image = avatarImage
switch viewData.fallbackImage {
case .matrixItem(_, let matrixItemDisplayName):
nameLabel.text = matrixItemDisplayName
default:
nameLabel.text = nil
}
nameLabel.text = viewData.displayName
}
}

View file

@ -14,7 +14,7 @@
<rect key="frame" x="0.0" y="0.0" width="414" height="192"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
<subviews>
<view autoresizesSubviews="NO" clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q3Z-S1-Py9" customClass="MXKImageView">
<view autoresizesSubviews="NO" clipsSubviews="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="q3Z-S1-Py9" customClass="RoomAvatarView" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="167" y="20" width="80" height="80"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>

View file

@ -0,0 +1,127 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import Foundation
/// this extension is temprorary and implements navigation to the Space bootom sheet. This should be moved to an universal link flow coordinator
extension RoomViewController {
@objc func handleSpaceUniversalLink(with url: URL) {
let url = Tools.fixURL(withSeveralHashKeys: url)
var pathParamsObjc: NSArray?
var queryParamsObjc: NSMutableDictionary?
AppDelegate.theDelegate().parseUniversalLinkFragment(url?.fragment, outPathParams: &pathParamsObjc, outQueryParams: &queryParamsObjc)
// Sanity check
guard let pathParams = pathParamsObjc as? [String], pathParams.count > 0 else {
MXLog.error("[RoomViewController] Universal link: Error: No path parameters")
return
}
var roomIdOrAliasParam: String?
var eventIdParam: String?
var userIdParam: String?
var groupIdParam: String?
// Check permalink to room or event
if pathParams[0] == "room" && pathParams.count >= 2 {
// The link is the form of "/room/[roomIdOrAlias]" or "/room/[roomIdOrAlias]/[eventId]"
roomIdOrAliasParam = pathParams[1]
// Is it a link to an event of a room?
eventIdParam = pathParams.count >= 3 ? pathParams[2] : nil
} else if pathParams[0] == "group" && pathParams.count >= 2 {
// The link is the form of "/group/[groupId]"
groupIdParam = pathParams[1]
} else if (pathParams[0].hasPrefix("#") || pathParams[0].hasPrefix("!")) && pathParams.count >= 1 {
// The link is the form of "/#/[roomIdOrAlias]" or "/#/[roomIdOrAlias]/[eventId]"
// Such links come from matrix.to permalinks
roomIdOrAliasParam = pathParams[0]
eventIdParam = pathParams.count >= 2 ? pathParams[1] : nil
} else if pathParams[0] == "user" && pathParams.count == 2 { // Check permalink to a user
// The link is the form of "/user/userId"
userIdParam = pathParams[1]
} else if pathParams[0].hasPrefix("@") && pathParams.count == 1 {
// The link is the form of "/#/[userId]"
// Such links come from matrix.to permalinks
userIdParam = pathParams[0]
}
guard let roomIdOrAlias = roomIdOrAliasParam else {
AppDelegate.theDelegate().handleUniversalLinkURL(url)
return
}
self.startActivityIndicator()
var viaServers: [String] = []
if let queryParams = queryParamsObjc as? [String: Any], let via = queryParams["via"] as? [String] {
viaServers = via
}
if roomIdOrAlias.hasPrefix("#") {
self.mainSession.matrixRestClient.roomId(forRoomAlias: roomIdOrAlias) { [weak self] response in
guard let self = self else {
return
}
guard let roomId = response.value else {
self.stopActivityIndicator()
if response.error != nil {
let errorMessage = VectorL10n.roomDoesNotExist(roomIdOrAlias)
AppDelegate.theDelegate().showAlert(withTitle: nil, message: errorMessage)
}
return
}
self.requestSummaryAndShowSpaceDetail(forRoomWithId: roomId, via: viaServers, from: url)
}
} else {
self.requestSummaryAndShowSpaceDetail(forRoomWithId: roomIdOrAlias, via: viaServers, from: url)
}
}
private func requestSummaryAndShowSpaceDetail(forRoomWithId roomId: String, via: [String], from url: URL?) {
if self.mainSession.spaceService.getSpace(withId: roomId) != nil {
self.stopActivityIndicator()
self.showSpaceDetail(withId: roomId)
return
}
self.mainSession.matrixRestClient.roomSummary(with: roomId, via: via) { [weak self] response in
guard let self = self else {
return
}
self.stopActivityIndicator()
guard let publicRoom = response.value, publicRoom.roomTypeString == MXRoomTypeString.space.rawValue else {
AppDelegate.theDelegate().handleUniversalLinkURL(url)
return
}
self.showSpaceDetail(with: publicRoom)
}
}
}

View file

@ -86,6 +86,10 @@ extern NSNotificationName const RoomGroupCallTileTappedNotification;
*/
- (void)displayRoomPreview:(RoomPreviewData*)roomPreviewData;
- (void)showSpaceDetailWithPublicRoom:(MXPublicRoom *)publicRoom;
- (void)showSpaceDetailWithId:(NSString *)spaceId;
/**
Action used to handle some buttons.
*/

View file

@ -137,7 +137,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, UIScrollViewAccessibilityDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate,
ReactionsMenuViewModelCoordinatorDelegate, EditHistoryCoordinatorBridgePresenterDelegate, MXKDocumentPickerPresenterDelegate, EmojiPickerCoordinatorBridgePresenterDelegate,
ReactionHistoryCoordinatorBridgePresenterDelegate, CameraPresenterDelegate, MediaPickerCoordinatorBridgePresenterDelegate,
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate, VoiceMessageControllerDelegate>
RoomDataSourceDelegate, RoomCreationModalCoordinatorBridgePresenterDelegate, RoomInfoCoordinatorBridgePresenterDelegate, DialpadViewControllerDelegate, RemoveJitsiWidgetViewDelegate, VoiceMessageControllerDelegate, SpaceDetailPresenterDelegate>
{
// The preview header
@ -244,8 +244,10 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
@property (nonatomic, strong) CustomSizedPresentationController *customSizedPresentationController;
@property (nonatomic, getter=isActivitiesViewExpanded) BOOL activitiesViewExpanded;
@property (nonatomic, getter=isScrollToBottomHidden) BOOL scrollToBottomHidden;
@property (nonatomic, getter=isMissedDiscussionsBadgeHidden) BOOL missedDiscussionsBadgeHidden;
@property (nonatomic, strong) VoiceMessageController *voiceMessageController;
@property (nonatomic, strong) SpaceDetailPresenter *spaceDetailPresenter;
@end
@ -1013,6 +1015,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
[self refreshRoomInputToolbar];
[VoiceMessageMediaServiceProvider.sharedProvider setCurrentRoomSummary:dataSource.room.summary];
_voiceMessageController.roomId = dataSource.roomId;
}
- (void)onRoomDataSourceReady
@ -1422,12 +1425,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
}
- (void)setShowMissedDiscussionsBadge:(BOOL)showMissedDiscussionsBadge
{
missedDiscussionsBadgeLabel.hidden = !showMissedDiscussionsBadge;
missedDiscussionsDotView.hidden = !showMissedDiscussionsBadge;
}
- (void)setScrollToBottomHidden:(BOOL)scrollToBottomHidden
{
if (_scrollToBottomHidden != scrollToBottomHidden)
@ -1451,6 +1448,13 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}];
}
- (void)setMissedDiscussionsBadgeHidden:(BOOL)missedDiscussionsBadgeHidden{
_missedDiscussionsBadgeHidden = missedDiscussionsBadgeHidden;
missedDiscussionsBadgeLabel.hidden = missedDiscussionsBadgeHidden;
missedDiscussionsDotView.hidden = missedDiscussionsBadgeHidden;
}
#pragma mark - Internals
- (UIBarButtonItem *)videoCallBarButtonItem
@ -2189,7 +2193,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}
else
{
return [[AppDelegate theDelegate] handleUniversalLinkURL:universalLinkURL];
[self handleSpaceUniversalLinkWith:universalLinkURL];
return YES;
}
}
@ -4960,15 +4965,15 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
- (void)refreshMissedDiscussionsCount:(BOOL)force
{
// Ignore this action when no room is displayed
if (!self.roomDataSource || !missedDiscussionsBadgeLabel
if (!self.showMissedDiscussionsBadge || !self.roomDataSource || !missedDiscussionsBadgeLabel
|| [UIDevice currentDevice].userInterfaceIdiom != UIUserInterfaceIdiomPhone
|| ([[UIScreen mainScreen] nativeBounds].size.height > 2532 && UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)))
{
self.showMissedDiscussionsBadge = NO;
self.missedDiscussionsBadgeHidden = YES;
return;
}
self.showMissedDiscussionsBadge = YES;
self.missedDiscussionsBadgeHidden = NO;
NSUInteger highlightCount = 0;
NSUInteger missedCount = [[AppDelegate theDelegate].masterTabBarController missedDiscussionsCount];
@ -6477,4 +6482,37 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
}];
}
- (void)showSpaceDetailWithPublicRoom:(MXPublicRoom *)publicRoom
{
self.spaceDetailPresenter = [SpaceDetailPresenter new];
self.spaceDetailPresenter.delegate = self;
[self.spaceDetailPresenter presentForSpaceWithPublicRoom:publicRoom from:self sourceView:nil session:self.mainSession animated:YES];
}
- (void)showSpaceDetailWithId:(NSString *)spaceId
{
self.spaceDetailPresenter = [SpaceDetailPresenter new];
self.spaceDetailPresenter.delegate = self;
[self.spaceDetailPresenter presentForSpaceWithId:spaceId from:self sourceView:nil session:self.mainSession animated:YES];
}
#pragma mark - SpaceDetailPresenterDelegate
- (void)spaceDetailPresenterDidComplete:(SpaceDetailPresenter *)presenter
{
self.spaceDetailPresenter = nil;
}
- (void)spaceDetailPresenter:(SpaceDetailPresenter *)presenter didOpenSpaceWithId:(NSString *)spaceId
{
self.spaceDetailPresenter = nil;
[[LegacyAppDelegate theDelegate] openSpaceWithId:spaceId];
}
- (void)spaceDetailPresenter:(SpaceDetailPresenter *)presenter didJoinSpaceWithId:(NSString *)spaceId
{
self.spaceDetailPresenter = nil;
[[LegacyAppDelegate theDelegate] openSpaceWithId:spaceId];
}
@end

View file

@ -25,7 +25,11 @@ final class RoomAvatarView: AvatarView, NibOwnerLoadable {
@IBOutlet private weak var cameraBadgeContainerView: UIView!
// MARK: Setup
// MARK: Public
var showCameraBadgeOnFallbackImage: Bool = false
// MARK: - Setup
private func commonInit() {
}
@ -74,6 +78,14 @@ final class RoomAvatarView: AvatarView, NibOwnerLoadable {
override func updateAvatarImageView(with viewData: AvatarViewDataProtocol) {
super.updateAvatarImageView(with: viewData)
self.cameraBadgeContainerView.isHidden = viewData.avatarUrl != nil
let hideCameraBadge: Bool
if self.showCameraBadgeOnFallbackImage {
hideCameraBadge = viewData.avatarUrl != nil
} else {
hideCameraBadge = true
}
self.cameraBadgeContainerView.isHidden = hideCameraBadge
}
}

View file

@ -25,4 +25,8 @@ struct RoomAvatarViewData: AvatarViewDataProtocol {
var matrixItemId: String {
return roomId
}
var fallbackImage: AvatarFallbackImage? {
return .matrixItem(matrixItemId, displayName)
}
}

Some files were not shown because too many files have changed in this diff Show more