Merge branch 'release/1.3.7/master'

This commit is contained in:
SBiOSoftWhare
2021-05-12 17:41:45 +02:00
63 changed files with 1247 additions and 149 deletions
+32
View File
@@ -1,3 +1,32 @@
Changes in 1.3.7 (2021-05-12)
=================================================
✨ Features
*
🙌 Improvements
* NSE: Add logs for notification delay.
* Templates: Update bridge presenter template to auto-implement iOS 13 pull-down gesture.
🐛 Bugfix
* NSE: Fixes to avoid PushKit crashes (#4269).
* Handle pull-down gesture for reactions history view (#4293).
⚠️ API Changes
*
🗣 Translations
*
🧱 Build
*
Others
*
Improvements:
* Upgrade MatrixKit version ([v0.14.12](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.14.12)).
Changes in 1.3.6 (2021-05-07)
=================================================
@@ -14,6 +43,9 @@ Changes in 1.3.6 (2021-05-07)
* Add Jitsi widget remove banner for privileged users.
* Update "Jump to unread" banner to a pill style button.
* CallVC: Add transfer button.
* Spaces: Hide spaces from room list and home but keep space invites (#4252).
* Spaces: Show space invites and advertise that they are not available (#4277).
* Advertise that spaces are not available when tapping on a space link or a space invite (#4279).
🐛 Bugfix
* RoomVC: Avoid navigation to integration management using integration popup with settings set to integration disabled (#4261).
+2 -2
View File
@@ -22,8 +22,8 @@ APPLICATION_GROUP_IDENTIFIER = group.im.vector
APPLICATION_SCHEME = element
// Version
MARKETING_VERSION = 1.3.6
CURRENT_PROJECT_VERSION = 1.3.6
MARKETING_VERSION = 1.3.7
CURRENT_PROJECT_VERSION = 1.3.7
// Team
+1 -1
View File
@@ -11,7 +11,7 @@ use_frameworks!
# - `{ {kit spec hash} => {sdk spec hash}` to depend on specific pod options (:git => …, :podspec => …) for each repo. Used by Fastfile during CI
#
# Warning: our internal tooling depends on the name of this variable name, so be sure not to change it
$matrixKitVersion = '= 0.14.11'
$matrixKitVersion = '= 0.14.12'
# $matrixKitVersion = :local
# $matrixKitVersion = {'develop' => 'develop'}
+14 -14
View File
@@ -55,28 +55,28 @@ PODS:
- MatomoTracker (7.4.1):
- MatomoTracker/Core (= 7.4.1)
- MatomoTracker/Core (7.4.1)
- MatrixKit (0.14.11):
- MatrixKit (0.14.12):
- Down (~> 0.10.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixKit/Core (= 0.14.11)
- MatrixSDK (= 0.18.11)
- MatrixKit/Core (0.14.11):
- MatrixKit/Core (= 0.14.12)
- MatrixSDK (= 0.18.12)
- MatrixKit/Core (0.14.12):
- Down (~> 0.10.0)
- DTCoreText (~> 1.6.25)
- HPGrowingTextView (~> 1.1)
- libPhoneNumber-iOS (~> 0.9.13)
- MatrixSDK (= 0.18.11)
- MatrixSDK (0.18.11):
- MatrixSDK/Core (= 0.18.11)
- MatrixSDK/Core (0.18.11):
- MatrixSDK (= 0.18.12)
- MatrixSDK (0.18.12):
- MatrixSDK/Core (= 0.18.12)
- MatrixSDK/Core (0.18.12):
- AFNetworking (~> 4.0.0)
- GZIP (~> 1.3.0)
- libbase58 (~> 0.1.4)
- OLMKit (~> 3.2.2)
- Realm (= 10.7.2)
- MatrixSDK/JingleCallStack (0.18.11):
- MatrixSDK/JingleCallStack (0.18.12):
- JitsiMeetSDK (= 3.2.0)
- MatrixSDK/Core
- OLMKit (3.2.2):
@@ -115,7 +115,7 @@ DEPENDENCIES:
- KeychainAccess (~> 4.2.2)
- KTCenterFlowLayout (~> 1.3.1)
- MatomoTracker (~> 7.4.1)
- MatrixKit (= 0.14.11)
- MatrixKit (= 0.14.12)
- MatrixSDK
- MatrixSDK/JingleCallStack
- OLMKit
@@ -186,8 +186,8 @@ SPEC CHECKSUMS:
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
Logging: beeb016c9c80cf77042d62e83495816847ef108b
MatomoTracker: 24a846c9d3aa76933183fe9d47fd62c9efa863fb
MatrixKit: b4427e22aed3ae4a3ef5175bb017fc2b9786269c
MatrixSDK: f3cecb8e8ca7624dc52940dfae95ae8b81ebee1a
MatrixKit: 7e372f21d63bbc489d64f493e47544193cd5635c
MatrixSDK: f72f413738e0f03892d9127c6b0b96cd8642abe1
OLMKit: 20d1c564033a1ae7148f8f599378d4c798363905
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
Realm: e523da9ade306c5ae87e85dc09fdef148d3e1cc1
@@ -199,6 +199,6 @@ SPEC CHECKSUMS:
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb
PODFILE CHECKSUM: eafd5b002866b4fb5d6814a0b07f1c3d99c5744a
PODFILE CHECKSUM: 150af66ac75238a58b5665592850c990348adf31
COCOAPODS: 1.10.1
COCOAPODS: 1.10.0
@@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}
@@ -0,0 +1,23 @@
{
"images" : [
{
"filename" : "feature_unavaible_artwork.png",
"idiom" : "universal",
"scale" : "1x"
},
{
"filename" : "feature_unavaible_artwork@2x.png",
"idiom" : "universal",
"scale" : "2x"
},
{
"filename" : "feature_unavaible_artwork@3x.png",
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

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

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

+6
View File
@@ -111,3 +111,9 @@
/* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "لَقَد أرسَلَ %@ رِسالة";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (مُكالَمَةٌ جَماعِيَّة)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "بَدَأت مُكالَمَةٌ جَماعِيَّة";
+7
View File
@@ -137,3 +137,10 @@
"auth_reset_password_success_message" = "لَقَد تمَّ إعادَةُ ضَبطِ كَلِمَةِ المُرُور الخَّاصَّةِ بِك.\n\nلَقَد تمَّ تَسجِيلُ خُرُوجِك مِن جَميعِ الجَلَسات وَلَن تَستَلِمَ بَعد الآن دَفعَ الإِشعَارات. لِإعادَةِ تَفعِيل الإِشعَارات، أعِد تَسجِيلَ الدُّخول عَلَى كُلِّ جِهاز.";
"auth_reset_password_error_not_found" = "لَا يَبدو أنَّ عُنوان البَريد الإلِكتُرونيّ الخَّاصِّ بِك مُقتَرِنٌ بِمُعَرِّف Matrix عَلَى الخادِمِ الرَّئيس هَذَا.";
"auth_reset_password_error_unauthorized" = "فَشَلَ التَّحَقُق مِن عُنوان البَريد الإلِكتُرونيّ: تَأكَّد مِن نَقرِكَ عَلَى الرَّابِط الَّذي فِي البَريد الإلِكتُرونيّ";
"callbar_only_single_active_group" = "اُنقُر لِلاِنضِمَامِ إلَى المُكالَمَةِ الجَماعِيَّة (%@)";
"auth_softlogout_clear_data_sign_out_title" = "هل أنت واثق؟";
"auth_softlogout_clear_data_button" = "مَحوُ كَافَّةِ البَيَانَات";
"auth_softlogout_clear_data_message_2" = "اِمحِيهَا إذَا اِنتَهَيتَ مِن اِستِخدَامِ هَذَا الجِّهاز، أو إذَا أردتَ تَسجيلَ الدُّخُولِ إلَى حِسَابٍ آخَر.";
"auth_softlogout_clear_data_message_1" = "تَحذير: بَيَانَاتُكَ الشَّخصِيَّة (بِمَا فِي ذَلِكَ مَفاتيحُ التَّعمِيَة) لَا تَزَالُ مُخَزَنَةً عَلَى هَذَا الجِّهاز.";
"auth_softlogout_clear_data" = "مَحوُ البَيَانَاتِ الشَّخصِيَّة";
"auth_softlogout_recover_encryption_keys" = "سَجَّل الدُّخُول لِاِستِعادَة مَفاتيح التَّعمِيَة المُخَزَّنَة حَصرِيًّا عَلَى هَذَا الجِّهاز. أنتَ بِحاجةٍ لَهُم لِقِراءةِ جَمِيعِ رَسائِلكَ الآمِنَة عَلَى أيِّ جِهاز.";
+11
View File
@@ -1632,3 +1632,14 @@ Tap the + to start adding people.";
"room_intro_cell_information_dm_sentence2" = "Only the two of you are in this conversation, no one else can join.";
"room_intro_cell_information_multiple_dm_sentence2" = "Only you are in this conversation, unless any of you invites someone to join.";
// Mark: - Spaces
"space_feature_unavailable_title" = "Spaces arent here yet";
"space_feature_unavailable_subtitle" = "Spaces aren't on iOS yet, but you can use them now on Web and Desktop";
"space_feature_unavailable_information" = "Spaces are a new way to group rooms and people.\n\nTheyll be here soon. For now, if you join one on another platform, you will be able to access any rooms you join here.";
"space_beta_announce_badge" = "BETA";
"space_beta_announce_title" = "Spaces are coming soon";
"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.";
+6
View File
@@ -62,3 +62,9 @@
/* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Video rühmakõne kasutajalt %@: „%@“";
"MESSAGE_PROTECTED" = "Uus sõnum";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (rühmakõne)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Rühmakõne algas";
+23 -4
View File
@@ -115,7 +115,7 @@
"room_participants_security_information_room_not_encrypted" = "See jututuba ei ole läbivalt krüptitud.";
"room_participants_security_information_room_encrypted" = "Sõnumid siin jututoas kasutavad läbivat krüptimist.\n\nSinu sõnumid on turvatud ning ainult sinul ja saaja(te)l on unikaalsed võtmed selliste sõnumite lugemiseks.";
// Chat
"room_jump_to_first_unread" = "Mine esimese lugemata sõnumi juurde";
"room_jump_to_first_unread" = "Mine lugemata sõnumite juurde";
// Room Details
"room_details_title" = "Jututoa üksikasjad";
"room_details_advanced_enable_e2e_encryption" = "Võta krüptimine kasutusele (hoiatus: seda ei saa hiljem enam välja lülitada!)";
@@ -1269,8 +1269,8 @@
"call_actions_unhold" = "Jätka";
"event_formatter_call_back" = "Helista tagasi";
"event_formatter_call_you_declined" = "Sina keeldusid sellest kõnest";
"event_formatter_call_you_currently_in" = "Sul on parasjagu see kõne pooleli";
"event_formatter_call_has_ended" = "See kõne on lõppenud";
"event_formatter_call_you_currently_in" = "Kõne on käsil";
"event_formatter_call_has_ended" = "%@ kõne on lõppenud";
"event_formatter_call_video" = "Videokõne";
"event_formatter_call_voice" = "Häälkõne";
"room_open_dialpad" = "Numbriklahvistik";
@@ -1286,10 +1286,29 @@
"callbar_active_and_single_paused" = "Käsil on üks kõne (%@) · üks kõne on ootel";
// Call Bar
"callbar_only_single_active" = "Kõne on käsil (%@)";
"callbar_only_single_active" = "Kõne juurde tagasipöördumiseks puuduta (%@)";
"room_details_integrations" = "Lõiminguid";
"room_details_search" = "Otsi jututoast";
"room_multiple_typing_notification" = "%@ ja muud kasutajad";
"room_accessibility_video_call" = "Videokõne";
"room_message_replying_to" = "Vastan sõnumile %@";
"room_message_editing" = "Muudan sõnumit";
"room_no_privileges_to_create_group_call" = "Kõne alustamiseks peaksid sa olema haldaja või moderaatori õigustes.";
"event_formatter_group_call_incoming" = "%@ kõnes %@";
"event_formatter_group_call_leave" = "Lahku";
"event_formatter_group_call_join" = "Liitu";
"event_formatter_group_call" = "Rühmakõne";
"event_formatter_call_end_call" = "Lõpeta kõne";
"event_formatter_call_retry" = "Proovi uuesti";
"event_formatter_call_answer" = "Vasta";
"event_formatter_call_decline" = "Keeldu";
"event_formatter_call_connection_failed" = "Ühendus ebaõnnestus";
"event_formatter_call_you_missed" = "Sa ei märganud seda kõnet";
"event_formatter_call_ringing" = "Helistan…";
"event_formatter_call_connecting" = "Kõne on ühendamisel…";
"settings_labs_enable_ringing_for_group_calls" = "Rühmakõnede helin";
"room_join_group_call" = "Liitu";
// Chat
"room_slide_to_end_group_call" = "Viipa kõne lõpetamiseks kõigi jaoks";
"callbar_only_single_active_group" = "Rühmakõnega liitumiseks puuduta (%@)";
+6
View File
@@ -62,3 +62,9 @@
/* New message indicator on a room */
"MESSAGE_IN_X" = "Message dans %@";
"MESSAGE_PROTECTED" = "Nouveau message";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (appel de groupe)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Lappel de groupe a démarré";
+22 -3
View File
@@ -1301,7 +1301,7 @@
"secrets_reset_title" = "Tout réinitialiser";
"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Contrôle des autres fonctionnalités de vérification…";
"event_formatter_call_you_currently_in" = "Vous êtes actuellement dans cet appel";
"event_formatter_call_you_currently_in" = "Appel en cours";
"rooms_empty_view_information" = "Les salons sont utiles pour toute conversation de groupe, privée ou publique. Appuyez sur « + » pour trouver des salons existants, ou en créer de nouveaux.";
"rooms_empty_view_title" = "Salons";
"people_empty_view_information" = "Communiquez de manière sécurisée avec nimporte qui. Appuyez sur « + » pour commencer à ajouter des personnes.";
@@ -1318,7 +1318,7 @@
"call_actions_unhold" = "Reprendre";
"event_formatter_call_back" = "Rappeler";
"event_formatter_call_you_declined" = "Vous avez refusé cet appel";
"event_formatter_call_has_ended" = "Lappel est terminé";
"event_formatter_call_has_ended" = "Appel %@ terminé";
"event_formatter_call_video" = "Appel vidéo";
"event_formatter_call_voice" = "Appel audio";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Le chiffrement nest pas activé ici.";
@@ -1358,7 +1358,7 @@
"callbar_active_and_single_paused" = "1 appel en cours (%@) · 1 appel en attente";
// Call Bar
"callbar_only_single_active" = "Appel en cours (%@)";
"callbar_only_single_active" = "Appuyez pour revenir à lappel (%@)";
"less" = "Moins";
"more" = "Plus";
"switch" = "Basculer";
@@ -1370,3 +1370,22 @@
"room_accessibility_video_call" = "Appel vidéo";
"room_message_replying_to" = "Réponse à %@";
"room_message_editing" = "Modification";
"event_formatter_group_call_incoming" = "%@ dans %@";
"event_formatter_group_call_leave" = "Partir";
"event_formatter_group_call_join" = "Rejoindre";
"event_formatter_group_call" = "Appel de groupe";
"event_formatter_call_end_call" = "Raccrocher";
"event_formatter_call_retry" = "Réessayer";
"event_formatter_call_answer" = "Décrocher";
"event_formatter_call_decline" = "Refuser";
"event_formatter_call_connection_failed" = "Échec de connexion";
"event_formatter_call_you_missed" = "Vous avez manqué cet appel";
"event_formatter_call_ringing" = "Sonnerie…";
"event_formatter_call_connecting" = "Connexion…";
"settings_labs_enable_ringing_for_group_calls" = "Sonnerie pour les appels de groupe";
"room_no_privileges_to_create_group_call" = "Vous devez être administrateur ou modérateur pour démarrer un appel.";
"room_join_group_call" = "Rejoindre";
// Chat
"room_slide_to_end_group_call" = "Faites glisser pour mettre fin à lappel pour tout le monde";
"callbar_only_single_active_group" = "Appuyez pour rejoindre lappel de groupe (%@)";
+6
View File
@@ -62,3 +62,9 @@
/* New message indicator on a room */
"MESSAGE_IN_X" = "Üzenet itt: %@";
"MESSAGE_PROTECTED" = "Új üzenet";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (Csoportos hívás)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Csoportos hívás elkezdődött";
+22 -3
View File
@@ -1332,8 +1332,8 @@
"call_actions_unhold" = "Folytatás";
"event_formatter_call_back" = "Visszahívás";
"event_formatter_call_you_declined" = "Elutasította ezt a hívást";
"event_formatter_call_you_currently_in" = "Jelenleg ebben a hívásban van";
"event_formatter_call_has_ended" = "Hívás befejeződött";
"event_formatter_call_you_currently_in" = "Aktív hívás";
"event_formatter_call_has_ended" = "Befejeződött: %@";
"event_formatter_call_video" = "Videóhívás";
"event_formatter_call_voice" = "Hang hívás";
"room_open_dialpad" = "Tárcsázó számlap";
@@ -1349,10 +1349,29 @@
"callbar_active_and_single_paused" = "1 aktív hívás (%@) · 1 hívás tartásban";
// Call Bar
"callbar_only_single_active" = "Aktív hívás (%@)";
"callbar_only_single_active" = "Koppints a hívásba való visszatéréshez (%@)";
"room_details_integrations" = "Integrációk";
"room_details_search" = "Szoba keresése";
"room_multiple_typing_notification" = "%@ és mások";
"room_accessibility_video_call" = "Videohívás";
"room_message_replying_to" = "Válasz erre: %@";
"room_message_editing" = "Szerkesztés";
"event_formatter_group_call_incoming" = "%@ itt: %@";
"event_formatter_group_call_leave" = "Elhagy";
"event_formatter_group_call_join" = "Csatlakozás";
"event_formatter_group_call" = "Csoportos hívás";
"event_formatter_call_end_call" = "Hívás befejezése";
"event_formatter_call_retry" = "Újra";
"event_formatter_call_answer" = "Válaszol";
"event_formatter_call_decline" = "Elutasít";
"event_formatter_call_connection_failed" = "Kapcsolódás sikertelen";
"event_formatter_call_you_missed" = "Elmulasztottad ezt a hívást";
"event_formatter_call_ringing" = "Hívás…";
"event_formatter_call_connecting" = "Kapcsolás…";
"settings_labs_enable_ringing_for_group_calls" = "Csengetés csoportos hívásokhoz";
"room_no_privileges_to_create_group_call" = "Adminisztrátornak vagy moderátornak kell lenned a hívás indításához.";
"room_join_group_call" = "Csatlakozás";
// Chat
"room_slide_to_end_group_call" = "Húzd el a hívás befejezéséhez mindenki számára";
"callbar_only_single_active_group" = "Koppints a csoporthívásba való belépéshez (%@)";
+6
View File
@@ -62,3 +62,9 @@
/* New message indicator on a room */
"MESSAGE_IN_X" = "Messaggio in %@";
"MESSAGE_PROTECTED" = "Nuovo messaggio";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (chiamata di gruppo)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Chiamata di gruppo iniziata";
+23 -4
View File
@@ -201,7 +201,7 @@
"room_participants_action_start_video_call" = "Nuova videochiamata";
"room_participants_action_mention" = "Citazione";
// Chat
"room_jump_to_first_unread" = "Vai al primo messaggio non letto";
"room_jump_to_first_unread" = "Vai ai non letti";
"room_new_message_notification" = "%d nuovo messaggio";
"room_new_messages_notification" = "%d nuovi messaggi";
"room_one_user_is_typing" = "%@ sta scrivendo…";
@@ -1302,8 +1302,8 @@
"call_actions_unhold" = "Riprendi";
"event_formatter_call_back" = "Richiama";
"event_formatter_call_you_declined" = "Hai rifiutato questa chiamata";
"event_formatter_call_you_currently_in" = "Sei attualmente in questa chiamata";
"event_formatter_call_has_ended" = "Questa chiamata è terminata";
"event_formatter_call_you_currently_in" = "Chiamata attiva";
"event_formatter_call_has_ended" = "Terminato %@";
"event_formatter_call_video" = "Videochiamata";
"event_formatter_call_voice" = "Telefonata";
"settings_show_NSFW_public_rooms" = "Mostra stanze pubbliche per adulti";
@@ -1320,10 +1320,29 @@
"callbar_active_and_single_paused" = "1 chiamata attiva (%@) · 1 chiamata in pausa";
// Call Bar
"callbar_only_single_active" = "Chiamata attiva (%@)";
"callbar_only_single_active" = "Tocca per tornare alla chiamata (%@)";
"room_details_integrations" = "Integrazioni";
"room_details_search" = "Cerca stanza";
"room_multiple_typing_notification" = "%@ e altri";
"room_accessibility_video_call" = "Videochiamata";
"room_message_editing" = "Modifica";
"room_message_replying_to" = "Risposta a %@";
"event_formatter_group_call_incoming" = "%@ in %@";
"event_formatter_group_call_leave" = "Esci";
"event_formatter_group_call_join" = "Entra";
"event_formatter_group_call" = "Chiamata di gruppo";
"event_formatter_call_end_call" = "Termina chiamata";
"event_formatter_call_retry" = "Riprova";
"event_formatter_call_answer" = "Rispondi";
"event_formatter_call_decline" = "Rifiuta";
"event_formatter_call_connection_failed" = "Connessione fallita";
"event_formatter_call_you_missed" = "Hai perso questa chiamata";
"event_formatter_call_ringing" = "Sta squillando…";
"event_formatter_call_connecting" = "In connessione…";
"settings_labs_enable_ringing_for_group_calls" = "Squilla per chiamate di gruppo";
"room_no_privileges_to_create_group_call" = "Devi essere un amministratore o un moderatore per iniziare una chiamata.";
"room_join_group_call" = "Entra";
// Chat
"room_slide_to_end_group_call" = "Scorri per terminare la chiamata per tutti";
"callbar_only_single_active_group" = "Tocca per unirti alla chiamata di gruppo (%@)";
+13
View File
@@ -860,3 +860,16 @@
"settings_flair" = "Vis brukervalg hvor tillat";
"settings_on_denied_notification" = "Varsler er ikke tillat for %@, vennligst tillat dem i enhetens innstillinger";
"settings_pin_rooms_with_missed_notif" = "Fest rom med tapte varsler";
"room_info_list_several_members" = "% @ medlemmer";
"pin_protection_not_allowed_pin" = "Av sikkerhetsgrunner er denne PIN-koden ikke tilgjengelig. Prøv en annen PIN-kode";
"secrets_setup_recovery_passphrase_information" = "Skriv inn et sikkerhetsfrase bare du kjenner, brukt til å sikre hemmeligheter på serveren din.";
"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "bruk gjenopprettingsnøkkelen din";
"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "bruk gjenopprettingsnøkkelen";
"room_details_access_section_for_dm" = "Hvem har til gang til dette?";
"identity_server_settings_place_holder" = "Skriv inn en identitetsserver";
"identity_server_settings_description" = "Du bruker for øyeblikket %@ for å finne å bli funnet av dine eksisterende kontakter.";
"security_settings_crosssigning_info_exists" = "Din konto har en kryss-signeringsidentitet, men den er ikke klarert av den økten. Fullfør klarering for denne økten.";
"security_settings_crypto_sessions_loading" = "Laster sesjoner…";
"settings_discovery_no_identity_server" = "Du bruker ikke for øyeblikket en identitetsserver. Legg til en for at dine eksisterende kontakter skal kunne finne deg.";
"settings_unignore_user" = "Vi alle meldinger fra %@?";
"device_verification_cancelled" = "Den andre parten avbrøt verifiseringen";
+6
View File
@@ -95,3 +95,9 @@
/* New message indicator on unknown room */
"MESSAGE" = "Bericht";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Groepsgesprek gestart";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (groepsgesprek)";
+23 -4
View File
@@ -194,7 +194,7 @@
"room_participants_action_start_video_call" = "Video-oproep beginnen";
"room_participants_action_mention" = "Vermelden";
// Chat
"room_jump_to_first_unread" = "Spring naar het eerste ongelezen bericht";
"room_jump_to_first_unread" = "Spring naar ongelezen";
"room_new_message_notification" = "%d nieuw bericht";
"room_new_messages_notification" = "%d nieuwe berichten";
"room_one_user_is_typing" = "%@ is aan het typen…";
@@ -1285,8 +1285,8 @@
"event_formatter_widget_added_by_you" = "U heeft deze widget toegevoegd: %@";
"event_formatter_call_back" = "Terugbellen";
"event_formatter_call_you_declined" = "U heeft de oproep afgewezen";
"event_formatter_call_you_currently_in" = "U bent momenteel in deze oproep";
"event_formatter_call_has_ended" = "Deze oproep is beëindigd";
"event_formatter_call_you_currently_in" = "Actieve oproep";
"event_formatter_call_has_ended" = "Beëindigd %@";
"event_formatter_call_video" = "Video-oproep";
"event_formatter_call_voice" = "Audio-oproep";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Versleuteling is hier niet ingeschakeld.";
@@ -1444,7 +1444,7 @@
"callbar_active_and_single_paused" = "1 oproep actief (%@) · 1 oproep in de wacht";
// Call Bar
"callbar_only_single_active" = "Oproep actief (%@)";
"callbar_only_single_active" = "Ga terug naar de oproep (%@)";
"less" = "Minder";
"more" = "Meer";
"switch" = "Wissel";
@@ -1456,3 +1456,22 @@
"room_accessibility_video_call" = "Video-oproep";
"room_message_replying_to" = "Antwoord aan %@";
"room_message_editing" = "Bewerken";
"callbar_only_single_active_group" = "Klik om deel te nemen aan groepsgesprek (%@)";
"event_formatter_group_call_incoming" = "%@ in %@";
"event_formatter_group_call_leave" = "Verlaten";
"event_formatter_group_call_join" = "Deelnemen";
"event_formatter_group_call" = "Groepsgesprek";
"event_formatter_call_end_call" = "Oproep beëindigen";
"event_formatter_call_retry" = "Opnieuw";
"event_formatter_call_answer" = "Opnemen";
"event_formatter_call_decline" = "Weigeren";
"event_formatter_call_connection_failed" = "Verbinding mislukt";
"event_formatter_call_you_missed" = "U heeft deze oproep gemist";
"event_formatter_call_ringing" = "Bellen…";
"event_formatter_call_connecting" = "Verbinden…";
"settings_labs_enable_ringing_for_group_calls" = "Audiomelding voor groepsgesprek";
"room_no_privileges_to_create_group_call" = "U moet een beheerder of moderator zijn om een gesprek te starten.";
"room_join_group_call" = "Deelnemen";
// Chat
"room_slide_to_end_group_call" = "Schuif om voor iedereen de oproep te beëindigen";
+6
View File
@@ -62,3 +62,9 @@
/* New message indicator on a room */
"MESSAGE_IN_X" = "Wiadomość w %@";
"MESSAGE_PROTECTED" = "Nowa Wiadomość";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (Połączenie grupowe)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Rozpoczęto połączenie grupowe";
+24 -5
View File
@@ -6,7 +6,7 @@
"title_groups" = "Społeczności";
"warning" = "Ostrzeżenie";
// Actions
"view" = "Wyświetl";
"view" = "Podgląd";
"back" = "Powrót";
"continue" = "Kontynuuj";
"create" = "Utwórz";
@@ -373,7 +373,7 @@
"room_participants_unknown" = "Status nieznany";
"room_participants_action_section_other" = "Opcje";
// Chat
"room_jump_to_first_unread" = "Przeskocz do pierwszej nieprzeczytanej wiadomości";
"room_jump_to_first_unread" = "Przeskocz do nieprzeczytanych wiadomości";
"room_new_message_notification" = "%d nowa wiadomość";
"room_new_messages_notification" = "%d nowych wiadomości";
"room_one_user_is_typing" = "%@ pisze…";
@@ -1290,8 +1290,8 @@
"event_formatter_jitsi_widget_added_by_you" = "Dodałeś(-aś) konferencję VoIP";
"event_formatter_call_back" = "Oddzwoń";
"event_formatter_call_you_declined" = "Odrzuciłeś to połączenie";
"event_formatter_call_you_currently_in" = "Bierzesz obecnie udział w tej rozmowie";
"event_formatter_call_has_ended" = "Rozmowa zakończona";
"event_formatter_call_you_currently_in" = "Aktywne połączenie";
"event_formatter_call_has_ended" = "Zakończono %@";
"event_formatter_call_video" = "Połączenie Wideo";
"event_formatter_call_voice" = "Połączenie głosowe";
"room_details_advanced_e2e_encryption_disabled_for_dm" = "Szyfrowanie nie jest włączone w tym pokoju.";
@@ -1416,8 +1416,27 @@
"callbar_active_and_single_paused" = "1 aktywne połączenie (%@) · 1 wstrzymane połączenie";
// Call Bar
"callbar_only_single_active" = "Aktywne połączenie (%@)";
"callbar_only_single_active" = "Dotknij, aby powrócić do rozmowy (%@)";
"auth_email_is_required" = "Brak skonfigurowanego serwera tożsamości, nie możesz dodać adresu e-mail na wypadek konieczności zresetowania hasła.";
"auth_add_email_phone_message_2" = "Ustaw adres e-mail na wypadek konieczności przywracania dostępu do konta, dodatkowo adres ten lub numer telefonu może być wykorzystany przez Twoich znajomych do znalezienia Twojego profilu.";
"auth_add_phone_message_2" = "Ustaw numer telefonu, numer ten może być wykorzystany przez Twoich znajomych do znalezienia Twojego profilu.";
"auth_add_email_message_2" = "Ustaw adres e-mail na wypadek konieczności przywracania dostępu do konta, dodatkowo adres ten może być wykorzystany przez Twoich znajomych do znalezienia Twojego profilu.";
"event_formatter_group_call_incoming" = "%@ w %@";
"event_formatter_group_call_leave" = "Opuść";
"event_formatter_group_call_join" = "Dołącz";
"event_formatter_group_call" = "Połączenie grupowe";
"event_formatter_call_end_call" = "Zakończ połączenie";
"event_formatter_call_retry" = "Ponów";
"event_formatter_call_decline" = "Odrzuć";
"event_formatter_call_answer" = "Odbierz";
"event_formatter_call_connection_failed" = "Połączenie nieudane";
"event_formatter_call_you_missed" = "Przegapiłeś(-aś) to połączenie";
"event_formatter_call_ringing" = "Dzwonie…";
"event_formatter_call_connecting" = "Łączenie…";
"settings_labs_enable_ringing_for_group_calls" = "Dźwięk połączeń grupowych";
"room_no_privileges_to_create_group_call" = "Aby rozpocząć połączenie, musisz być administratorem lub moderatorem.";
"room_join_group_call" = "Dołącz";
// Chat
"room_slide_to_end_group_call" = "Przesuń, aby zakończyć połączenie dla wszystkich";
"callbar_only_single_active_group" = "Dotknij, aby powrócić do rozmowy grupowej (%@)";
+6
View File
@@ -62,3 +62,9 @@
/* New message indicator on a room */
"MESSAGE_IN_X" = "Mesazh te %@";
"MESSAGE_PROTECTED" = "Mesazh i Ri";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (Thirrje në grup)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Nisi thirrje në grup";
+24 -5
View File
@@ -162,7 +162,7 @@
"room_participants_action_start_video_call" = "Nis thirrje video";
"room_participants_action_mention" = "Përmendje";
// Chat
"room_jump_to_first_unread" = "Hidhu te mesazhi i parë i palexuar";
"room_jump_to_first_unread" = "Hidhu te palexuar";
"room_new_message_notification" = "%d mesazh i ri";
"room_new_messages_notification" = "%d mesazhe të rinj";
"room_one_user_is_typing" = "%@ po shtyp…";
@@ -170,7 +170,7 @@
"room_many_users_are_typing" = "%@, %@ & të tjerë po shtypin…";
"room_message_placeholder" = "Dërgoni një mesazh (të pafshehtëzuar)…";
"room_do_not_have_permission_to_post" = "Skeni leje të postoni në këtë dhomë";
"encrypted_room_message_placeholder" = "Dërgoni një mesazhi të fshehtëzuar…";
"encrypted_room_message_placeholder" = "Dërgoni një mesazh të fshehtëzuar…";
"room_message_short_placeholder" = "Dërgoni një mesazh…";
"room_offline_notification" = "Humbi lidhja me shërbyesin.";
"room_unsent_messages_notification" = "Mesazhet su dërguan.";
@@ -1309,8 +1309,8 @@
"call_actions_unhold" = "Rimerre";
"event_formatter_call_back" = "Ktheji thirrjen";
"event_formatter_call_you_declined" = "Hodhët poshtë këtë thirrje";
"event_formatter_call_you_currently_in" = "Gjendeni në këtë thirrje";
"event_formatter_call_has_ended" = "Kjo thirrje ka përfunduar";
"event_formatter_call_you_currently_in" = "Thirrje aktive";
"event_formatter_call_has_ended" = "Përfundoi %@";
"event_formatter_call_video" = "Thirrje video";
"event_formatter_call_voice" = "Thirrje audio";
"security_settings_crosssigning_reset" = "Rikthe te parazgjedhjet <em>cross-signing</em>";
@@ -1338,10 +1338,29 @@
"callbar_active_and_single_paused" = "1 thirrje aktive (%@) · 1 thirrje e ndalur";
// Call Bar
"callbar_only_single_active" = "Thirrje aktive (%@)";
"callbar_only_single_active" = "Prekeni që të riktheheni te thirrja (%@)";
"room_details_integrations" = "Integrime";
"room_multiple_typing_notification" = "%@ dhe të tjerë";
"room_accessibility_video_call" = "Thirrje Video";
"room_message_replying_to" = "Në përgjigje të %@";
"room_message_editing" = "Përpunim";
"room_details_search" = "Kërkoni për dhomë";
"settings_labs_enable_ringing_for_group_calls" = "Bjeri ziles për thirrje në grup";
"event_formatter_group_call_incoming" = "%@ në %@";
"event_formatter_group_call_leave" = "Dilni";
"event_formatter_group_call_join" = "Hyni";
"event_formatter_group_call" = "Thirrje në grup";
"event_formatter_call_end_call" = "Përfundoje thirrjen";
"event_formatter_call_retry" = "Riprovo";
"event_formatter_call_answer" = "Përgjigjuni";
"event_formatter_call_decline" = "Hidhe poshtë";
"event_formatter_call_connection_failed" = "Lidhja dështoi";
"event_formatter_call_you_missed" = "E humbët këtë thirrje";
"event_formatter_call_ringing" = "Po i bihet ziles…";
"event_formatter_call_connecting" = "Po lidhet…";
"room_no_privileges_to_create_group_call" = "Që të nisni një thirrje, duhet të jeni një përgjegjës ose një moderator.";
"room_join_group_call" = "Hyni";
// Chat
"room_slide_to_end_group_call" = "Rrëshqiteni, që të përfundohet thirrja për këdo";
"callbar_only_single_active_group" = "Prekeni, që të Hyni në thirrjen e grupit (%@)";
+6
View File
@@ -62,3 +62,9 @@
"VIDEO_CONF_NAMED_FROM_USER" = "Videogruppsamtal från %@: '%@'";
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ vill verifiera";
"MESSAGE_PROTECTED" = "Nytt meddelande";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (Gruppsamtal)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Gruppsamtal startat";
+23 -4
View File
@@ -185,7 +185,7 @@
"room_member_power_level_short_moderator" = "Mod";
"room_member_power_level_short_custom" = "Anpassad";
// Chat
"room_jump_to_first_unread" = "Hoppa till första olästa meddelandet";
"room_jump_to_first_unread" = "Hoppa till oläst";
"room_new_message_notification" = "%d nytt meddelande";
"room_new_messages_notification" = "%u nya meddelanden";
"room_one_user_is_typing" = "%@ skriver…";
@@ -1267,8 +1267,8 @@
"call_actions_unhold" = "Återuppta";
"event_formatter_call_back" = "Ring tillbaka";
"event_formatter_call_you_declined" = "Du avslog det här samtalet";
"event_formatter_call_you_currently_in" = "Du är för närvarande i det här samtalet";
"event_formatter_call_has_ended" = "Det här samtalet har avslutats";
"event_formatter_call_you_currently_in" = "Aktivt samtal";
"event_formatter_call_has_ended" = "Avslutade %@";
"event_formatter_call_video" = "Videosamtal";
"event_formatter_call_voice" = "Röstsamtal";
"settings_show_NSFW_public_rooms" = "Visa NSFW offentliga rum";
@@ -1285,10 +1285,29 @@
"callbar_active_and_single_paused" = "1 aktivt samtal (%@) · 1 pausat samtal";
// Call Bar
"callbar_only_single_active" = "Aktivt samtal (%@)";
"callbar_only_single_active" = "Tryck för att återgå till samtalet (%@)";
"room_accessibility_video_call" = "Videosamtal";
"room_message_editing" = "Redigerar";
"room_message_replying_to" = "Svarar på %@";
"room_multiple_typing_notification" = "%@ och andra";
"room_details_search" = "Sök i rum";
"room_details_integrations" = "Integrationer";
"event_formatter_group_call_incoming" = "%@ i %@";
"event_formatter_group_call_leave" = "Lämna";
"event_formatter_group_call_join" = "Gå med";
"event_formatter_group_call" = "Gruppsamtal";
"event_formatter_call_end_call" = "Avsluta samtal";
"event_formatter_call_retry" = "Försök igen";
"event_formatter_call_answer" = "Svara";
"event_formatter_call_decline" = "Neka";
"event_formatter_call_connection_failed" = "Anslutning misslyckades";
"event_formatter_call_you_missed" = "Du missade det här samtalet";
"event_formatter_call_ringing" = "Ringer…";
"event_formatter_call_connecting" = "Ansluter…";
"settings_labs_enable_ringing_for_group_calls" = "Ring för gruppsamtal";
"room_no_privileges_to_create_group_call" = "Du måste vara en administratör eller moderator för att starta ett samtal.";
"room_join_group_call" = "Gå med";
// Chat
"room_slide_to_end_group_call" = "Glid för att avsluta samtalet för alla";
"callbar_only_single_active_group" = "Tryck för att gå med i gruppsamtalet (%@)";
+6
View File
@@ -62,3 +62,9 @@
/* New message indicator on a room */
"MESSAGE_IN_X" = "Повідомлення у %@";
"MESSAGE_PROTECTED" = "Нове повідомлення";
/* Group call from user, CallKit caller name */
"GROUP_CALL_FROM_USER" = "%@ (Груповий виклик)";
/* A user added a Jitsi call to a room */
"GROUP_CALL_STARTED" = "Груповий виклик розпочато";
+1 -1
View File
@@ -296,7 +296,7 @@
"callbar_active_and_single_paused" = "1 активний виклик (%@) · 1 виклик в очікуванні";
// Call Bar
"callbar_only_single_active" = "Активний виклик (%@)";
"callbar_only_single_active" = "Торкніться, щоб повернутися до виклику (%@)";
"switch" = "Перемкнути";
"room_event_action_resend" = "Повторно надіслати";
"room_event_action_redact" = "Вилучити";
+5
View File
@@ -33,6 +33,11 @@ extension UITableViewCell {
return result
}
// Hide separator for one cell, otherwise use `tableView.separatorStyle = .none`
@objc func vc_hideSeparator() {
self.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: .greatestFiniteMagnitude)
}
@objc func vc_setAccessoryDisclosureIndicator(withTintColor tintColor: UIColor) {
let disclosureImage = Asset.Images.disclosureIcon.image.withRenderingMode(.alwaysTemplate)
let disclosureImageView = UIImageView(image: disclosureImage)
+2
View File
@@ -158,6 +158,8 @@ internal enum Asset {
internal static let secretsResetWarning = ImageAsset(name: "secrets_reset_warning")
internal static let removeIconPink = ImageAsset(name: "remove_icon_pink")
internal static let settingsIcon = ImageAsset(name: "settings_icon")
internal static let featureUnavaibleArtwork = ImageAsset(name: "feature_unavaible_artwork")
internal static let featureUnavaibleArtworkDark = ImageAsset(name: "feature_unavaible_artwork_dark")
internal static let tabFavourites = ImageAsset(name: "tab_favourites")
internal static let tabGroups = ImageAsset(name: "tab_groups")
internal static let tabHome = ImageAsset(name: "tab_home")
+5
View File
@@ -229,6 +229,11 @@ internal enum StoryboardScene {
internal static let initialScene = InitialSceneType<Riot.SimpleScreenTemplateViewController>(storyboard: SimpleScreenTemplateViewController.self)
}
internal enum SpaceFeatureUnaivableViewController: StoryboardType {
internal static let storyboardName = "SpaceFeatureUnaivableViewController"
internal static let initialScene = InitialSceneType<Riot.SpaceFeatureUnaivableViewController>(storyboard: SpaceFeatureUnaivableViewController.self)
}
internal enum TemplateScreenViewController: StoryboardType {
internal static let storyboardName = "TemplateScreenViewController"
+28
View File
@@ -4562,6 +4562,34 @@ internal enum VectorL10n {
internal static var socialLoginListTitleSignUp: String {
return VectorL10n.tr("Vector", "social_login_list_title_sign_up")
}
/// BETA
internal static var spaceBetaAnnounceBadge: String {
return VectorL10n.tr("Vector", "space_beta_announce_badge")
}
/// 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.
internal static var spaceBetaAnnounceInformation: String {
return VectorL10n.tr("Vector", "space_beta_announce_information")
}
/// The new version of communities
internal static var spaceBetaAnnounceSubtitle: String {
return VectorL10n.tr("Vector", "space_beta_announce_subtitle")
}
/// Spaces are coming soon
internal static var spaceBetaAnnounceTitle: String {
return VectorL10n.tr("Vector", "space_beta_announce_title")
}
/// Spaces are a new way to group rooms and people.\n\nTheyll be here soon. For now, if you join one on another platform, you will be able to access any rooms you join here.
internal static var spaceFeatureUnavailableInformation: String {
return VectorL10n.tr("Vector", "space_feature_unavailable_information")
}
/// Spaces aren't on iOS yet, but you can use them now on Web and Desktop
internal static var spaceFeatureUnavailableSubtitle: String {
return VectorL10n.tr("Vector", "space_feature_unavailable_subtitle")
}
/// Spaces arent here yet
internal static var spaceFeatureUnavailableTitle: String {
return VectorL10n.tr("Vector", "space_feature_unavailable_title")
}
/// Start
internal static var start: String {
return VectorL10n.tr("Vector", "start")
@@ -38,4 +38,5 @@ protocol KeyValueStore {
// remove
func removeObject(forKey key: KeyValueStoreKey) throws
func removeAll() throws
}
@@ -114,4 +114,8 @@ extension KeychainStore: KeyValueStore {
try keychain.remove(key)
}
func removeAll() throws {
try keychain.removeAll()
}
}
@@ -92,4 +92,8 @@ extension MemoryStore: KeyValueStore {
map.removeValue(forKey: key)
}
func removeAll() throws {
map.removeAll()
}
}
@@ -299,25 +299,15 @@ Matrix session observer used to detect new opened sessions.
NSArray *mxAccounts = [MXKAccountManager sharedManager].activeAccounts;
for (MXKAccount *account in mxAccounts)
{
// Check the current session state
if (account.mxSession.state == MXSessionStatePaused)
{
NSLog(@"[PushNotificationService] launchBackgroundSync");
MXWeakify(self);
NSLog(@"[PushNotificationService] launchBackgroundSync");
[account backgroundSync:20000 success:^{
// Sanity check
MXStrongifyAndReturnIfNil(self);
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
[[UNUserNotificationCenter currentNotificationCenter] removeCallNotificationsFor:nil];
NSLog(@"[PushNotificationService] launchBackgroundSync: the background sync succeeds");
} failure:^(NSError *error) {
NSLog(@"[PushNotificationService] launchBackgroundSync: the background sync failed. Error: %@ (%@).", error.domain, @(error.code));
}];
}
[account backgroundSync:20000 success:^{
[[UNUserNotificationCenter currentNotificationCenter] removeUnwantedNotifications];
[[UNUserNotificationCenter currentNotificationCenter] removeCallNotificationsFor:nil];
NSLog(@"[PushNotificationService] launchBackgroundSync: the background sync succeeds");
} failure:^(NSError *error) {
NSLog(@"[PushNotificationService] launchBackgroundSync: the background sync failed. Error: %@ (%@).", error.domain, @(error.code));
}];
}
}
@@ -564,16 +554,16 @@ Matrix session observer used to detect new opened sessions.
if (@available(iOS 13.0, *))
{
// for iOS 13, we'll just report the incoming call in the same runloop. It means we cannot call an async API here.
MXEvent *lastCallInvite = _pushNotificationStore.lastCallInvite;
MXEvent *callInvite = [_pushNotificationStore callInviteForEventId:eventId];
// remove event
_pushNotificationStore.lastCallInvite = nil;
[_pushNotificationStore removeCallInviteWithEventId:eventId];
MXSession *session = [AppDelegate theDelegate].mxSessions.firstObject;
// when we have a VoIP push while the application is killed, session.callManager will not be ready yet. Configure it.
[[AppDelegate theDelegate] configureCallManagerIfRequiredForSession:session];
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: lastCallInvite: %@", lastCallInvite);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: callInvite: %@", callInvite);
if ([lastCallInvite.eventId isEqualToString:eventId])
if (callInvite)
{
// We're using this dispatch_group to continue event stream after cache fully processed.
dispatch_group_t dispatchGroup = dispatch_group_create();
@@ -585,18 +575,12 @@ Matrix session observer used to detect new opened sessions.
dispatch_group_leave(dispatchGroup);
}];
if (lastCallInvite.isEncrypted && ![session decryptEvent:lastCallInvite inTimeline:nil])
{
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Failed to decrypt the call invite event: %@", eventId);
completion();
return;
}
if (lastCallInvite.eventType == MXEventTypeCallInvite)
if (callInvite.eventType == MXEventTypeCallInvite)
{
// process the call invite synchronously
[session.callManager handleCallEvent:lastCallInvite];
MXCall *call = [session.callManager callWithCallId:lastCallInvite.content[@"call_id"]];
[session.callManager handleCallEvent:callInvite];
MXCallInviteEventContent *content = [MXCallInviteEventContent modelFromJSON:callInvite.content];
MXCall *call = [session.callManager callWithCallId:content.callId];
if (call)
{
[session.callManager.callKitAdapter reportIncomingCall:call];
@@ -613,10 +597,10 @@ Matrix session observer used to detect new opened sessions.
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: Error on call object on room %@ for the event: %@", roomId, eventId);
}
}
else if ([lastCallInvite.type isEqualToString:kWidgetMatrixEventTypeString] ||
[lastCallInvite.type isEqualToString:kWidgetModularEventTypeString])
else if ([callInvite.type isEqualToString:kWidgetMatrixEventTypeString] ||
[callInvite.type isEqualToString:kWidgetModularEventTypeString])
{
[[AppDelegate theDelegate].callPresenter processWidgetEvent:lastCallInvite
[[AppDelegate theDelegate].callPresenter processWidgetEvent:callInvite
inSession:session];
}
else
@@ -628,7 +612,7 @@ Matrix session observer used to detect new opened sessions.
else
{
// It's a serious error. There is nothing to avoid iOS to kill us here.
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: iOS 13 and in bg, but we don't have the last callInvite event for the event %@. There is something wrong.", eventId);
NSLog(@"[PushNotificationService] didReceiveIncomingPushWithPayload: iOS 13 and in bg, but we don't have the callInvite event for the eventId: %@. There is something wrong.", eventId);
}
}
else
@@ -29,7 +29,6 @@ final class PushNotificationStore: NSObject {
private struct StoreKeys {
static let pushToken: String = "pushtoken"
static let lastCallInvite: String = "lastCallInvite"
}
/// Store. Defaults to `KeychainStore`
@@ -59,32 +58,23 @@ final class PushNotificationStore: NSObject {
}
}
var lastCallInvite: MXEvent? {
get {
do {
guard let data = try store.data(forKey: StoreKeys.lastCallInvite) else {
return nil
}
return NSKeyedUnarchiver.unarchiveObject(with: data) as? MXEvent
} catch let error {
NSLog("[PinCodePreferences] Error when reading push token from store: \(error)")
return nil
}
} set {
do {
guard let newValue = newValue else {
return try store.removeObject(forKey: StoreKeys.lastCallInvite)
}
let data = NSKeyedArchiver.archivedData(withRootObject: newValue)
try store.set(data, forKey: StoreKeys.lastCallInvite)
} catch let error {
NSLog("[PinCodePreferences] Error when storing push token to the store: \(error)")
}
func callInvite(forEventId eventId: String) -> MXEvent? {
guard let data = try? store.data(forKey: eventId) else {
return nil
}
return NSKeyedUnarchiver.unarchiveObject(with: data) as? MXEvent
}
func storeCallInvite(_ event: MXEvent) {
let data = NSKeyedArchiver.archivedData(withRootObject: event)
try? store.set(data, forKey: event.eventId)
}
func removeCallInvite(withEventId eventId: String) {
try? store.removeObject(forKey: eventId)
}
func reset() {
pushKitToken = nil
lastCallInvite = nil
try? store.removeAll()
}
}
+10
View File
@@ -79,6 +79,7 @@ final class RiotSettings: NSObject {
static let roomInfoScreenShowIntegrations = "roomInfoScreenShowIntegrations"
static let roomMemberScreenShowIgnore = "roomMemberScreenShowIgnore"
static let unifiedSearchScreenShowPublicDirectory = "unifiedSearchScreenShowPublicDirectory"
static let hideSpaceBetaAnnounce = "hideSpaceBetaAnnounce"
}
static let shared = RiotSettings()
@@ -707,4 +708,13 @@ final class RiotSettings: NSObject {
}
}
// MARK: - Beta
var hideSpaceBetaAnnounce: Bool {
get {
return defaults.bool(forKey: UserDefaultsKeys.hideSpaceBetaAnnounce)
} set {
defaults.set(newValue, forKey: UserDefaultsKeys.hideSpaceBetaAnnounce)
}
}
}
@@ -224,6 +224,38 @@ UINavigationControllerDelegate
*/
- (BOOL)handleUniversalLinkFragment:(NSString*)fragment;
/**
Process the fragment part of a vector.im link.
@param fragment the fragment part of the universal link.
@param universalLinkURL the unprocessed the universal link URL (optional).
@return YES in case of processing success.
*/
- (BOOL)handleUniversalLinkFragment:(NSString*)fragment fromURL:(NSURL*)universalLinkURL;
/**
Process the URL of a vector.im link.
@param universalLinkURL the universal link URL.
@return YES in case of processing success.
*/
- (BOOL)handleUniversalLinkURL:(NSURL*)universalLinkURL;
#pragma mark - Jitsi call
/**
Open the Jitsi view controller from a widget.
@param jitsiWidget the jitsi widget.
@param video to indicate voice or video call.
*/
- (void)displayJitsiViewControllerWithWidget:(Widget*)jitsiWidget andVideo:(BOOL)video;
/**
The current Jitsi view controller being displayed.
*/
@property (nonatomic, readonly) JitsiViewController *jitsiViewController;
#pragma mark - Call status handling
/**
+64 -9
View File
@@ -228,6 +228,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
@property (nonatomic, strong) MajorUpdateManager *majorUpdateManager;
@property (nonatomic, strong) SpaceFeatureUnavailablePresenter *spaceFeatureUnavailablePresenter;
@end
@implementation LegacyAppDelegate
@@ -389,6 +391,12 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
NSLog(@"[AppDelegate] didFinishLaunchingWithOptions: isProtectedDataAvailable: %@", @([application isProtectedDataAvailable]));
if (![application isProtectedDataAvailable])
{
NSLog(@"[AppDelegate] didFinishLaunchingWithOptions: Terminating the app because protected data not available");
exit(0);
}
_configuration = [AppConfiguration new];
// Log app information
@@ -461,6 +469,8 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
self.pushNotificationStore = [PushNotificationStore new];
self.pushNotificationService = [[PushNotificationService alloc] initWithPushNotificationStore:self.pushNotificationStore];
self.pushNotificationService.delegate = self;
self.spaceFeatureUnavailablePresenter = [SpaceFeatureUnavailablePresenter new];
// Add matrix observers, and initialize matrix sessions if the app is not launched in background.
[self initMatrixSessions];
@@ -1212,7 +1222,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
// Continue the registration with the passed nextLink
NSLog(@"[AppDelegate] handleUniversalLink. Complete registration with nextLink");
NSURL *nextLink = [NSURL URLWithString:queryParams[@"nextLink"]];
[self handleUniversalLinkFragment:nextLink.fragment];
[self handleUniversalLinkFragment:nextLink.fragment fromURL:nextLink];
}
else
{
@@ -1238,10 +1248,15 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
return YES;
}
return [self handleUniversalLinkFragment:webURL.fragment];
return [self handleUniversalLinkFragment:webURL.fragment fromURL:webURL];
}
- (BOOL)handleUniversalLinkFragment:(NSString*)fragment
{
return [self handleUniversalLinkFragment:fragment fromURL:nil];
}
- (BOOL)handleUniversalLinkFragment:(NSString*)fragment fromURL:(NSURL*)universalLinkURL
{
BOOL continueUserActivity = NO;
MXKAccountManager *accountManager = [MXKAccountManager sharedManager];
@@ -1325,19 +1340,32 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if (account)
{
NSString *roomId = roomIdOrAlias;
MXRoom *room;
// Translate the alias into the room id
if ([roomIdOrAlias hasPrefix:@"#"])
{
MXRoom *room = [account.mxSession roomWithAlias:roomIdOrAlias];
room = [account.mxSession roomWithAlias:roomIdOrAlias];
if (room)
{
roomId = room.roomId;
}
}
else
{
room = [account.mxSession roomWithRoomId:roomId];
}
// Open the room page
[self showRoom:roomId andEventId:eventId withMatrixSession:account.mxSession];
if (room.summary.roomType == MXRoomTypeSpace)
{
// Indicates that spaces are not supported
[self.spaceFeatureUnavailablePresenter presentUnavailableFeatureFrom:self.presentedViewController animated:YES];
}
else
{
// Open the room page
[self showRoom:roomId andEventId:eventId withMatrixSession:account.mxSession];
}
continueUserActivity = YES;
}
@@ -1387,7 +1415,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
{
universalLinkFragmentPendingRoomAlias = @{roomId: roomIdOrAlias};
[self handleUniversalLinkFragment:newUniversalLinkFragment];
[self handleUniversalLinkFragment:newUniversalLinkFragment fromURL:universalLinkURL];
}
else
{
@@ -1425,7 +1453,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if (notif.object == account.mxSession && account.mxSession.state == MXSessionStateRunning)
{
NSLog(@"[AppDelegate] Universal link: The session is running. Retry the link");
[self handleUniversalLinkFragment:fragment];
[self handleUniversalLinkFragment:fragment fromURL:universalLinkURL];
}
}
}];
@@ -1486,7 +1514,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if ([universalLinkFragmentPending isEqualToString:fragment])
{
NSLog(@"[AppDelegate] Universal link: The user is now logged in. Retry the link");
[self handleUniversalLinkFragment:fragment];
[self handleUniversalLinkFragment:fragment fromURL:universalLinkURL];
}
}];
}
@@ -1551,7 +1579,7 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
if ([universalLinkFragmentPending isEqualToString:fragment])
{
NSLog(@"[AppDelegate] Universal link: The user is now logged in. Retry the link");
[self handleUniversalLinkFragment:fragment];
[self handleUniversalLinkFragment:fragment fromURL:universalLinkURL];
}
}];
}
@@ -1575,6 +1603,14 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
return continueUserActivity;
}
- (BOOL)handleUniversalLinkURL:(NSURL*)universalLinkURL
{
// iOS Patch: fix vector.im urls before using it
NSURL *fixedURL = [Tools fixURLWithSeveralHashKeys:universalLinkURL];
return [self handleUniversalLinkFragment:fixedURL.fragment fromURL:universalLinkURL];
}
- (void)resetPendingUniversalLink
{
universalLinkFragmentPending = nil;
@@ -2740,6 +2776,25 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni
- (void)showRoom:(NSString*)roomId andEventId:(NSString*)eventId withMatrixSession:(MXSession*)mxSession restoreInitialDisplay:(BOOL)restoreInitialDisplay completion:(void (^)(void))completion
{
if (roomId && mxSession)
{
MXRoom *room = [mxSession roomWithRoomId:roomId];
// Indicates that spaces are not supported
if (room.summary.roomType == MXRoomTypeSpace)
{
[self.spaceFeatureUnavailablePresenter presentUnavailableFeatureFrom:self.presentedViewController animated:YES];
if (completion)
{
completion();
}
return;
}
}
void (^selectRoom)(void) = ^() {
// Select room to display its details (dispatch this action in order to let TabBarController end its refresh)
[self.masterTabBarController selectRoomWithId:roomId andEventId:eventId inMatrixSession:mxSession completion:^{
@@ -21,9 +21,9 @@ final class CloseButton: UIButton, Themable {
// MARK: - Constants
private enum CircleBackgroundConstants {
static let height: CGFloat = 30.0
static let height: CGFloat = 26.0
static let highlightedAlha: CGFloat = 0.5
static let normalAlha: CGFloat = 1.0
static let normalAlha: CGFloat = 0.8
}
// MARK: - Properties
@@ -109,6 +109,6 @@ final class CloseButton: UIButton, Themable {
func update(theme: Theme) {
self.theme = theme
self.circleBackgroundView.backgroundColor = theme.headerTextSecondaryColor
self.circleBackgroundView.backgroundColor = theme.secondaryCircleButtonBackgroundColor
}
}
@@ -1188,7 +1188,11 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
}
else
{
[conversationCellDataArray addObject:recentCellDataStoring];
// Hide spaces from home (keep space invites)
if (room.summary.roomType != MXRoomTypeSpace)
{
[conversationCellDataArray addObject:recentCellDataStoring];
}
}
}
else if (_recentsDataSourceMode == RecentsDataSourceModeFavourites)
@@ -1219,12 +1223,12 @@ NSString *const kRecentsDataSourceTapOnDirectoryServerChange = @"kRecentsDataSou
// Consider only non direct rooms.
if (!room.isDirect)
{
// Keep only the invites, the favourites and the rooms without tag
// Keep only the invites, the favourites and the rooms without tag and room type different from space
if (room.summary.membership == MXMembershipInvite)
{
[invitesCellDataArray addObject:recentCellDataStoring];
}
else if (!room.accountData.tags.count || room.accountData.tags[kMXRoomTagFavourite])
else if ((!room.accountData.tags.count || room.accountData.tags[kMXRoomTagFavourite]) && room.summary.roomType != MXRoomTypeSpace)
{
[conversationCellDataArray addObject:recentCellDataStoring];
}
@@ -70,6 +70,8 @@
@property (nonatomic, strong) RoomsDirectoryCoordinatorBridgePresenter *roomsDirectoryCoordinatorBridgePresenter;
@property (nonatomic, strong) SpaceFeatureUnavailablePresenter *spaceFeatureUnavailablePresenter;
@end
@implementation RecentsViewController
@@ -870,6 +872,16 @@
return recentsDataSource;
}
- (void)showSpaceInviteNotAvailable
{
if (!self.spaceFeatureUnavailablePresenter)
{
self.spaceFeatureUnavailablePresenter = [SpaceFeatureUnavailablePresenter new];
}
[self.spaceFeatureUnavailablePresenter presentUnavailableFeatureFrom:self animated:YES];
}
#pragma mark - MXKDataSourceDelegate
- (Class<MXKCellRendering>)cellViewClassForCellData:(MXKCellData*)cellData
@@ -905,6 +917,13 @@
{
// Retrieve the invited room
MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey];
if (invitedRoom.summary.roomType == MXRoomTypeSpace)
{
// Indicates that spaces are not supported
[self showSpaceInviteNotAvailable];
return;
}
// Display the room preview
[self dispayRoomWithRoomId:invitedRoom.roomId inMatrixSession:invitedRoom.mxSession];
@@ -913,6 +932,13 @@
{
// Retrieve the invited room
MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey];
if (invitedRoom.summary.roomType == MXRoomTypeSpace)
{
// Indicates that spaces are not supported
[self showSpaceInviteNotAvailable];
return;
}
// Accept invitation
[self joinRoom:invitedRoom completion:nil];
@@ -921,7 +947,7 @@
{
// Retrieve the invited room
MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey];
[self cancelEditionMode:isRefreshPending];
// Decline the invitation
@@ -1372,8 +1398,13 @@
// Retrieve the invited room
MXRoom* invitedRoom = cellData.roomSummary.room;
if (invitedRoom.summary.roomType == MXRoomTypeSpace)
{
// Indicates that spaces are not supported
[self showSpaceInviteNotAvailable];
}
// Check if can show preview for the invited room
if ([self canShowRoomPreviewFor:invitedRoom])
else if ([self canShowRoomPreviewFor:invitedRoom])
{
// Display the room preview
[self dispayRoomWithRoomId:invitedRoom.roomId inMatrixSession:invitedRoom.mxSession];
@@ -15,9 +15,79 @@
*/
#import "GroupsDataSource.h"
#import "Riot-Swift.h"
@interface GroupsDataSource() <BetaAnnounceCellDelegate>
@property (nonatomic) NSInteger betaAnnounceSection;
@property (nonatomic) BOOL showBetaAnnounce;
@end
@implementation GroupsDataSource
- (instancetype)initWithMatrixSession:(MXSession *)matrixSession
{
self = [super initWithMatrixSession:matrixSession];
if (self)
{
// TODO: Hide the banner for the moment. Wait for iterations on it.
// _showBetaAnnounce = !RiotSettings.shared.hideSpaceBetaAnnounce;
_showBetaAnnounce = NO;
}
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSInteger count = 0;
self.betaAnnounceSection = self.groupInvitesSection = self.joinedGroupsSection = -1;
// Check whether all data sources are ready before rendering groups.
if (self.state == MXKDataSourceStateReady)
{
if (self.showBetaAnnounce)
{
self.betaAnnounceSection = count++;
}
if (groupsInviteCellDataArray.count)
{
self.groupInvitesSection = count++;
}
if (groupsCellDataArray.count)
{
self.joinedGroupsSection = count++;
}
}
return count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == self.betaAnnounceSection)
{
BetaAnnounceCell *cell = [tableView dequeueReusableCellWithIdentifier:BetaAnnounceCell.reuseIdentifier forIndexPath:indexPath];
[cell vc_hideSeparator];
[cell updateWithTheme:ThemeService.shared.theme];
cell.delegate = self;
return cell;
}
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == self.betaAnnounceSection)
{
return 1;
}
return [super tableView:tableView numberOfRowsInSection:section];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString* sectionTitle = nil;
@@ -44,4 +114,13 @@
return (indexPath.section == self.joinedGroupsSection);
}
#pragma mark - BetaAnnounceCellDelegate
- (void)betaAnnounceCellDidTapCloseButton:(BetaAnnounceCell *)cell
{
self.showBetaAnnounce = NO;
RiotSettings.shared.hideSpaceBetaAnnounce = YES;
[self.delegate dataSource:self didCellChange:nil];
}
@end
@@ -79,6 +79,7 @@
//Register here the customized cell view class used to render groups
[self.groupsTableView registerNib:GroupTableViewCell.nib forCellReuseIdentifier:GroupTableViewCell.defaultReuseIdentifier];
[self.groupsTableView registerNib:GroupInviteTableViewCell.nib forCellReuseIdentifier:GroupInviteTableViewCell.defaultReuseIdentifier];
[self.groupsTableView registerNib:BetaAnnounceCell.nib forCellReuseIdentifier:BetaAnnounceCell.reuseIdentifier];
// Hide line separators of empty cells
self.groupsTableView.tableFooterView = [[UIView alloc] init];
@@ -786,11 +786,8 @@
if ([Tools isUniversalLink:URL])
{
shouldInteractWithURL = NO;
// iOS Patch: fix vector.im urls before using it
NSURL *fixedURL = [Tools fixURLWithSeveralHashKeys:URL];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fixedURL.fragment];
[[AppDelegate theDelegate] handleUniversalLinkURL:URL];
}
// Open a detail screen about the clicked user
else if ([MXTools isMatrixUserIdentifier:absoluteURLString])
@@ -60,6 +60,7 @@ final class ReactionHistoryCoordinatorBridgePresenter: NSObject {
let coordinatorPresentable = reactionHistoryCoordinator.toPresentable()
coordinatorPresentable.modalPresentationStyle = .formSheet
coordinatorPresentable.presentationController?.delegate = self
viewController.present(coordinatorPresentable, animated: animated, completion: nil)
reactionHistoryCoordinator.start()
@@ -87,3 +88,13 @@ extension ReactionHistoryCoordinatorBridgePresenter: ReactionHistoryCoordinatorD
self.delegate?.reactionHistoryCoordinatorBridgePresenterDelegateDidClose(self)
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension ReactionHistoryCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate {
func presentationControllerDidDismiss(_ presentationController: UIPresentationController) {
self.delegate?.reactionHistoryCoordinatorBridgePresenterDelegateDidClose(self)
}
}
+3 -6
View File
@@ -3410,10 +3410,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
{
shouldDoAction = NO;
// iOS Patch: fix vector.im urls before using it
NSURL *fixedURL = [Tools fixURLWithSeveralHashKeys:url];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fixedURL.fragment];
[[AppDelegate theDelegate] handleUniversalLinkURL:url];
}
// Open a detail screen about the clicked user
else if ([MXTools isMatrixUserIdentifier:absoluteURLString])
@@ -3452,7 +3449,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Open the room or preview it
NSString *fragment = [NSString stringWithFormat:@"/room/%@", [MXTools encodeURIComponent:roomIdOrAlias]];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fragment];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fragment fromURL:url];
}
// Preview the clicked group
else if ([MXTools isMatrixGroupIdentifier:absoluteURLString])
@@ -3461,7 +3458,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05;
// Open the group or preview it
NSString *fragment = [NSString stringWithFormat:@"/group/%@", [MXTools encodeURIComponent:absoluteURLString]];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fragment];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fragment fromURL:url];
}
else if ([absoluteURLString hasPrefix:EventFormatterOnReRequestKeysLinkAction])
{
@@ -0,0 +1,94 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import UIKit
import Reusable
@objc protocol BetaAnnounceCellDelegate: class {
func betaAnnounceCellDidTapCloseButton(_ cell: BetaAnnounceCell)
}
/// BetaAnnounceCell enables to show coming beta feature
final class BetaAnnounceCell: UITableViewCell, Themable {
// MARK: - Constants
private enum Constants {
static let cardBackgroundViewCornersRadius: CGFloat = 8.0
}
// MARK: - Properties
@IBOutlet private weak var cardBackgroundView: UIView!
@IBOutlet private weak var closeButton: CloseButton!
@IBOutlet private weak var badgeView: UIView!
@IBOutlet private weak var badgeLabel: UILabel!
@IBOutlet private weak var titleLabel: UILabel!
@IBOutlet private weak var subtitleLabel: UILabel!
@IBOutlet private weak var informationLabel: UILabel!
@objc weak var delegate: BetaAnnounceCellDelegate?
// MARK: - Life cycle
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.badgeLabel.text = VectorL10n.spaceBetaAnnounceBadge
self.titleLabel.text = VectorL10n.spaceBetaAnnounceTitle
self.subtitleLabel.text = VectorL10n.spaceBetaAnnounceSubtitle
self.informationLabel.text = VectorL10n.spaceBetaAnnounceInformation
self.badgeView.layer.masksToBounds = true
self.cardBackgroundView.layer.masksToBounds = true
}
override func layoutSubviews() {
super.layoutSubviews()
self.cardBackgroundView.layer.cornerRadius = Constants.cardBackgroundViewCornersRadius
self.badgeView.layer.cornerRadius = self.badgeView.frame.height/2
}
// MARK: - Public
func update(theme: Theme) {
self.closeButton.update(theme: theme)
self.titleLabel.textColor = theme.textPrimaryColor
self.subtitleLabel.textColor = theme.textPrimaryColor
self.informationLabel.textColor = theme.textSecondaryColor
self.cardBackgroundView.backgroundColor = theme.baseColor
self.contentView.backgroundColor = theme.backgroundColor
}
// MARK: - Actions
@IBAction private func closeButtonAction(_ sender: Any) {
self.delegate?.betaAnnounceCellDidTapCloseButton(self)
}
}
// Copy past from NibReusable in order to expose these methods to ObjC
extension BetaAnnounceCell {
@objc static var reuseIdentifier: String {
return String(describing: self)
}
@objc static var nib: UINib {
return UINib(nibName: String(describing: self), bundle: Bundle(for: self))
}
}
+124
View File
@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="327" id="KGk-i7-Jjw" customClass="BetaAnnounceCell" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="331" height="327"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
<rect key="frame" x="0.0" y="0.0" width="331" height="327"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="vuH-Jo-iN1">
<rect key="frame" x="20" y="20" width="291" height="287"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="aTW-9I-M53">
<rect key="frame" x="15" y="15" width="46" height="19"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="BETA" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Szn-LE-OSt">
<rect key="frame" x="8" y="2" width="30" height="15"/>
<fontDescription key="fontDescription" type="system" pointSize="12"/>
<color key="textColor" systemColor="secondarySystemBackgroundColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemBlueColor"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="Szn-LE-OSt" secondAttribute="bottom" constant="2" id="Dz7-J1-Fd9"/>
<constraint firstAttribute="trailing" secondItem="Szn-LE-OSt" secondAttribute="trailing" constant="8" id="KQR-Wz-FzB"/>
<constraint firstItem="Szn-LE-OSt" firstAttribute="leading" secondItem="aTW-9I-M53" secondAttribute="leading" constant="8" id="Kwa-X4-z2j"/>
<constraint firstItem="Szn-LE-OSt" firstAttribute="top" secondItem="aTW-9I-M53" secondAttribute="top" constant="2" id="TwD-zu-wYb"/>
</constraints>
</view>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="kel-VV-C0f" customClass="CloseButton" customModule="Riot" customModuleProvider="target">
<rect key="frame" x="237" y="6" width="44" height="44"/>
<constraints>
<constraint firstAttribute="width" constant="44" id="BOd-JJ-paV"/>
<constraint firstAttribute="height" constant="44" id="tdl-KN-AnH"/>
</constraints>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<state key="normal" image="close_button"/>
<connections>
<action selector="closeButtonAction:" destination="KGk-i7-Jjw" eventType="touchUpInside" id="yXe-P8-tRC"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Meet Spaces" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="aSK-Uf-CjE">
<rect key="frame" x="15" y="49" width="261" height="24"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="20"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="246" verticalCompressionResistancePriority="749" text="The new version of communities" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="vu4-y4-3xv">
<rect key="frame" x="15" y="83" width="261" height="87.5"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Spaces are new ways to group rooms and people. You can try them out now on Android, or on your computer." textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="npW-wC-Sab">
<rect key="frame" x="15" y="185.5" width="261" height="81.5"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" systemColor="systemGray5Color"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="aSK-Uf-CjE" secondAttribute="trailing" constant="15" id="1T1-zJ-fup"/>
<constraint firstAttribute="bottom" secondItem="npW-wC-Sab" secondAttribute="bottom" constant="20" id="2lh-cu-mmZ"/>
<constraint firstAttribute="trailing" secondItem="kel-VV-C0f" secondAttribute="trailing" constant="10" id="CH2-5q-a51"/>
<constraint firstItem="npW-wC-Sab" firstAttribute="trailing" secondItem="vu4-y4-3xv" secondAttribute="trailing" id="D0P-in-hDZ"/>
<constraint firstItem="aTW-9I-M53" firstAttribute="leading" secondItem="vuH-Jo-iN1" secondAttribute="leading" constant="15" id="EiU-im-VWT"/>
<constraint firstItem="npW-wC-Sab" firstAttribute="leading" secondItem="vu4-y4-3xv" secondAttribute="leading" id="MD1-a4-T1w"/>
<constraint firstItem="aSK-Uf-CjE" firstAttribute="top" secondItem="aTW-9I-M53" secondAttribute="bottom" constant="15" id="ey5-aY-n3y"/>
<constraint firstItem="aSK-Uf-CjE" firstAttribute="leading" secondItem="aTW-9I-M53" secondAttribute="leading" id="ihA-R5-fpd"/>
<constraint firstItem="kel-VV-C0f" firstAttribute="top" secondItem="vuH-Jo-iN1" secondAttribute="top" constant="6" id="ilP-Uo-PLu"/>
<constraint firstItem="npW-wC-Sab" firstAttribute="top" secondItem="vu4-y4-3xv" secondAttribute="bottom" constant="15" id="nbH-gK-EU6"/>
<constraint firstItem="vu4-y4-3xv" firstAttribute="trailing" secondItem="aSK-Uf-CjE" secondAttribute="trailing" id="ox3-Gb-PVP"/>
<constraint firstItem="vu4-y4-3xv" firstAttribute="leading" secondItem="aSK-Uf-CjE" secondAttribute="leading" id="pCR-Vy-sbf"/>
<constraint firstItem="aTW-9I-M53" firstAttribute="top" secondItem="vuH-Jo-iN1" secondAttribute="top" constant="15" id="pkY-VS-aCB"/>
<constraint firstItem="vu4-y4-3xv" firstAttribute="top" secondItem="aSK-Uf-CjE" secondAttribute="bottom" constant="10" id="rg4-3n-uSE"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="vuH-Jo-iN1" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" constant="20" id="Gt7-qL-q6P"/>
<constraint firstAttribute="trailing" secondItem="vuH-Jo-iN1" secondAttribute="trailing" constant="20" id="RJH-X8-eno"/>
<constraint firstItem="vuH-Jo-iN1" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" constant="20" id="exf-6Z-LN6"/>
<constraint firstAttribute="bottom" secondItem="vuH-Jo-iN1" secondAttribute="bottom" constant="20" id="tAe-8X-9LN"/>
</constraints>
</tableViewCellContentView>
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
<connections>
<outlet property="badgeLabel" destination="Szn-LE-OSt" id="Ts2-O8-9Hm"/>
<outlet property="badgeView" destination="aTW-9I-M53" id="6iH-DI-CN1"/>
<outlet property="cardBackgroundView" destination="vuH-Jo-iN1" id="bJL-Ib-scJ"/>
<outlet property="closeButton" destination="kel-VV-C0f" id="h6d-is-LyE"/>
<outlet property="informationLabel" destination="npW-wC-Sab" id="caK-gm-MRm"/>
<outlet property="subtitleLabel" destination="vu4-y4-3xv" id="uRJ-2B-3nP"/>
<outlet property="titleLabel" destination="aSK-Uf-CjE" id="S09-2y-xWL"/>
</connections>
<point key="canvasLocation" x="-25.362318840579711" y="53.90625"/>
</tableViewCell>
</objects>
<resources>
<image name="close_button" width="16" height="16"/>
<systemColor name="secondarySystemBackgroundColor">
<color red="0.94901960784313721" green="0.94901960784313721" blue="0.96862745098039216" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemBlueColor">
<color red="0.0" green="0.47843137254901963" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
<systemColor name="systemGray5Color">
<color red="0.89803921568627454" green="0.89803921568627454" blue="0.91764705882352937" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</systemColor>
</resources>
</document>
@@ -0,0 +1,101 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="lF3-B1-QSM">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Space Feature Unaivable View Controller-->
<scene sceneID="GxM-11-zLQ">
<objects>
<viewController extendedLayoutIncludesOpaqueBars="YES" automaticallyAdjustsScrollViewInsets="NO" id="lF3-B1-QSM" customClass="SpaceFeatureUnaivableViewController" customModule="Riot" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="xml-pK-Qwj">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="1B8-AI-sNF">
<rect key="frame" x="0.0" y="44" width="414" height="852"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="nR7-UU-l9H">
<rect key="frame" x="0.0" y="0.0" width="414" height="398"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="27X-Of-wNa">
<rect key="frame" x="0.0" y="0.0" width="414" height="398"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="50" translatesAutoresizingMaskIntoConstraints="NO" id="ylT-1L-OLp">
<rect key="frame" x="25" y="50" width="364" height="328"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="feature_unavaible_artwork" translatesAutoresizingMaskIntoConstraints="NO" id="sGd-vk-QZn">
<rect key="frame" x="0.0" y="0.0" width="364" height="106"/>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Youre trying to open a link to a Space. Spaces are currently only available in beta on web, or Android" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="0bq-od-FQz">
<rect key="frame" x="0.0" y="156" width="364" height="61"/>
<fontDescription key="fontDescription" type="system" weight="medium" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Use your computer to open the link. If you do, well let you know when the feature comes to iOS." textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="9ZF-ov-Mf3">
<rect key="frame" x="0.0" y="267" width="364" height="61"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</stackView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="ylT-1L-OLp" secondAttribute="bottom" constant="20" id="34J-bP-IoO"/>
<constraint firstAttribute="trailing" secondItem="ylT-1L-OLp" secondAttribute="trailing" constant="25" id="5Jt-g6-D8E"/>
<constraint firstItem="ylT-1L-OLp" firstAttribute="leading" secondItem="27X-Of-wNa" secondAttribute="leading" constant="25" id="pi6-0g-zBY"/>
<constraint firstItem="ylT-1L-OLp" firstAttribute="top" secondItem="27X-Of-wNa" secondAttribute="top" constant="50" id="q2s-te-4sL"/>
<constraint firstAttribute="width" priority="750" constant="500" id="ypd-Rv-SnZ"/>
</constraints>
</view>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="bottom" secondItem="27X-Of-wNa" secondAttribute="bottom" id="8IE-H1-hHy"/>
<constraint firstAttribute="trailing" relation="greaterThanOrEqual" secondItem="27X-Of-wNa" secondAttribute="trailing" id="9ES-BJ-i6i"/>
<constraint firstItem="27X-Of-wNa" firstAttribute="centerX" secondItem="nR7-UU-l9H" secondAttribute="centerX" id="Qaa-FG-9KG"/>
<constraint firstItem="27X-Of-wNa" firstAttribute="top" secondItem="nR7-UU-l9H" secondAttribute="top" id="lYG-Wh-gO8"/>
<constraint firstItem="27X-Of-wNa" firstAttribute="leading" relation="greaterThanOrEqual" secondItem="nR7-UU-l9H" secondAttribute="leading" id="vN8-ue-jSD"/>
</constraints>
</view>
</subviews>
<constraints>
<constraint firstItem="nR7-UU-l9H" firstAttribute="width" secondItem="1B8-AI-sNF" secondAttribute="width" id="DDt-dv-KuK"/>
<constraint firstAttribute="bottom" secondItem="nR7-UU-l9H" secondAttribute="bottom" id="NEU-Tu-bEO"/>
<constraint firstItem="nR7-UU-l9H" firstAttribute="top" secondItem="1B8-AI-sNF" secondAttribute="top" id="RUb-FJ-n39"/>
<constraint firstAttribute="trailing" secondItem="nR7-UU-l9H" secondAttribute="trailing" id="baF-fE-9RM"/>
<constraint firstItem="nR7-UU-l9H" firstAttribute="leading" secondItem="1B8-AI-sNF" secondAttribute="leading" id="m9t-z5-09A"/>
</constraints>
</scrollView>
</subviews>
<viewLayoutGuide key="safeArea" id="EKA-x2-Dp6"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="EKA-x2-Dp6" firstAttribute="top" secondItem="1B8-AI-sNF" secondAttribute="top" id="4JH-b0-GAR"/>
<constraint firstItem="1B8-AI-sNF" firstAttribute="leading" secondItem="EKA-x2-Dp6" secondAttribute="leading" id="FyW-NO-hPT"/>
<constraint firstAttribute="bottom" secondItem="1B8-AI-sNF" secondAttribute="bottom" id="amp-xt-t4Z"/>
<constraint firstItem="EKA-x2-Dp6" firstAttribute="trailing" secondItem="1B8-AI-sNF" secondAttribute="trailing" id="fBG-DS-i4e"/>
</constraints>
</view>
<connections>
<outlet property="artworkImageView" destination="sGd-vk-QZn" id="823-PG-zoL"/>
<outlet property="informationLabel" destination="9ZF-ov-Mf3" id="9Oc-Zg-QZE"/>
<outlet property="subtitleLabel" destination="0bq-od-FQz" id="fLM-1x-mjU"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="aGN-2E-nEI" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-3198" y="-647"/>
</scene>
</scenes>
<resources>
<image name="feature_unavaible_artwork" width="160" height="106"/>
</resources>
</document>
@@ -0,0 +1,97 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import UIKit
final class SpaceFeatureUnaivableViewController: UIViewController {
// MARK: - Properties
// MARK: Outlets
@IBOutlet private weak var artworkImageView: UIImageView!
@IBOutlet private weak var subtitleLabel: UILabel!
@IBOutlet private weak var informationLabel: UILabel!
// MARK: Private
private var theme: Theme!
// MARK: - Setup
class func instantiate() -> SpaceFeatureUnaivableViewController {
let viewController = StoryboardScene.SpaceFeatureUnaivableViewController.initialScene.instantiate()
viewController.theme = ThemeService.shared().theme
return viewController
}
// MARK: - Life cycle
override func viewDidLoad() {
super.viewDidLoad()
self.setupViews()
self.registerThemeServiceDidChangeThemeNotification()
self.update(theme: self.theme)
}
override var preferredStatusBarStyle: UIStatusBarStyle {
return self.theme.statusBarStyle
}
// MARK: - Private
private func registerThemeServiceDidChangeThemeNotification() {
NotificationCenter.default.addObserver(self, selector: #selector(themeDidChange), name: .themeServiceDidChangeTheme, object: nil)
}
@objc private func themeDidChange() {
self.update(theme: ThemeService.shared().theme)
}
private func setupViews() {
self.title = VectorL10n.spaceFeatureUnavailableTitle
self.subtitleLabel.text = VectorL10n.spaceFeatureUnavailableSubtitle
self.informationLabel.text = VectorL10n.spaceFeatureUnavailableInformation
}
// MARK: - Public
func update(theme: Theme) {
self.theme = theme
self.view.backgroundColor = theme.backgroundColor
if let navigationBar = self.navigationController?.navigationBar {
theme.applyStyle(onNavigationBar: navigationBar)
}
self.subtitleLabel.textColor = theme.textPrimaryColor
self.informationLabel.textColor = theme.textSecondaryColor
// Artwork image view
let artworkImage = ThemeService.shared().isCurrentThemeDark() ? Asset.Images.featureUnavaibleArtworkDark.image : Asset.Images.featureUnavaibleArtwork.image
self.artworkImageView.image = artworkImage
}
func fill(informationText: String, shareLink: URL) {
self.subtitleLabel.text = informationText
}
}
@@ -0,0 +1,47 @@
//
// Copyright 2021 New Vector Ltd
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
import UIKit
/// SpaceFeatureUnavailablePresenter enables to present modals for unavailable space features
@objcMembers
final class SpaceFeatureUnavailablePresenter: NSObject {
// MARK: - Constants
// MARK: - Properties
// MARK: Private
private weak var presentingViewController: UIViewController?
// MARK: - Public
func presentUnavailableFeature(from presentingViewController: UIViewController,
animated: Bool) {
let spaceFeatureUnavailableVC = SpaceFeatureUnaivableViewController.instantiate()
let navigationVC = RiotNavigationController(rootViewController: spaceFeatureUnavailableVC)
spaceFeatureUnavailableVC.navigationItem.rightBarButtonItem = MXKBarButtonItem(title: Bundle.mxk_localizedString(forKey: "ok"), style: .plain, action: { [weak navigationVC] in
navigationVC?.dismiss(animated: true)
})
navigationVC.modalPresentationStyle = .formSheet
presentingViewController.present(navigationVC, animated: animated, completion: nil)
}
}
+5
View File
@@ -365,6 +365,11 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
self.encryptedMessagesTextFont = [UIFont italicSystemFontOfSize:15];
self.emojiOnlyTextFont = [UIFont systemFontOfSize:48];
self.editionMentionTextFont = [UIFont systemFontOfSize:12];
// Handle space room type, enables to show space in room list
defaultRoomSummaryUpdater.showRoomTypeStrings = @[
MXRoomTypeStringSpace
];
}
return self;
}
+61 -10
View File
@@ -18,10 +18,23 @@ import UserNotifications
import MatrixKit
import MatrixSDK
/// The number of milliseconds in one second.
private let MSEC_PER_SEC: TimeInterval = 1000
class NotificationService: UNNotificationServiceExtension {
private struct NSE {
enum Constants {
static let voipPushRequestTimeout: TimeInterval = 15
static let timeNeededToSendVoIPPushes: TimeInterval = 20
}
}
// MARK: - Properties
/// Receiving dates for notifications. Keys are eventId's
private var receiveDates: [String: Date] = [:]
/// Content handlers. Keys are eventId's
private var contentHandlers: [String: ((UNNotificationContent) -> Void)] = [:]
@@ -88,6 +101,9 @@ class NotificationService: UNNotificationServiceExtension {
return
}
// store receive date
receiveDates[eventId] = Date()
// read badge from "unread_count"
// no need to check before, if it's nil, the badge will remain unchanged
content.badge = userInfo["unread_count"] as? NSNumber
@@ -190,6 +206,10 @@ class NotificationService: UNNotificationServiceExtension {
}
private func processEvent(_ event: MXEvent) {
if let receiveDate = receiveDates[event.eventId] {
NSLog("[NotificationService] processEvent: notification receive delay: \(receiveDate.timeIntervalSince1970*MSEC_PER_SEC - TimeInterval(event.originServerTs)) ms")
}
guard let content = bestAttemptContents[event.eventId], let userAccount = userAccount else {
self.fallbackToBestAttemptContent(forEventId: event.eventId)
return
@@ -246,6 +266,7 @@ class NotificationService: UNNotificationServiceExtension {
// clear maps
contentHandlers.removeValue(forKey: eventId)
bestAttemptContents.removeValue(forKey: eventId)
receiveDates.removeValue(forKey: eventId)
// We are done for this push
NSLog("--------------------------------------------------------------------------------")
@@ -290,7 +311,14 @@ class NotificationService: UNNotificationServiceExtension {
// call notifications should stand out from normal messages, so we don't stack them
threadIdentifier = nil
self.sendVoipPush(forEvent: event)
if let callInviteContent = MXCallInviteEventContent(fromJSON: event.content),
callInviteContent.lifetime > event.age,
(callInviteContent.lifetime - event.age) > UInt(NSE.Constants.timeNeededToSendVoIPPushes * MSEC_PER_SEC) {
self.sendVoipPush(forEvent: event)
} else {
NSLog("[NotificationService] notificationContent: Do not attempt to send a VoIP push, there is not enough time to process it.")
}
case .roomMessage, .roomEncrypted:
if isRoomMentionsOnly {
// A local notification will be displayed only for highlighted notification.
@@ -559,20 +587,43 @@ class NotificationService: UNNotificationServiceExtension {
return
}
pushNotificationStore.lastCallInvite = event
if #available(iOS 13.0, *) {
if event.isEncrypted {
guard let clearEvent = event.clear else {
NSLog("[NotificationService] sendVoipPush: Do not send a VoIP push for undecrypted event, it'll cause a crash.")
return
}
// Add some original data on the clear event
clearEvent.eventId = event.eventId
clearEvent.originServerTs = event.originServerTs
clearEvent.sender = event.sender
clearEvent.roomId = event.roomId
pushNotificationStore.storeCallInvite(clearEvent)
} else {
pushNotificationStore.storeCallInvite(event)
}
}
ongoingVoIPPushRequests[event.eventId] = true
let appId = BuildSettings.pushKitAppId
pushGatewayRestClient.notifyApp(withId: appId, pushToken: token, eventId: event.eventId, roomId: event.roomId, eventType: nil, sender: event.sender, success: { [weak self] (rejected) in
NSLog("[NotificationService] sendVoipPush succeeded, rejected tokens: \(rejected)")
guard let self = self else { return }
self.ongoingVoIPPushRequests.removeValue(forKey: event.eventId)
self.fallbackToBestAttemptContent(forEventId: event.eventId)
}) { [weak self] (error) in
pushGatewayRestClient.notifyApp(withId: appId,
pushToken: token,
eventId: event.eventId,
roomId: event.roomId,
eventType: nil,
sender: event.sender,
timeout: NSE.Constants.voipPushRequestTimeout,
success: { [weak self] (rejected) in
NSLog("[NotificationService] sendVoipPush succeeded, rejected tokens: \(rejected)")
guard let self = self else { return }
self.ongoingVoIPPushRequests.removeValue(forKey: event.eventId)
self.fallbackToBestAttemptContent(forEventId: event.eventId)
}) { [weak self] (error) in
NSLog("[NotificationService] sendVoipPush failed with error: \(error)")
guard let self = self else { return }
@@ -54,7 +54,9 @@ final class FlowTemplateCoordinatorBridgePresenter: NSObject {
func present(from viewController: UIViewController, animated: Bool) {
let flowTemplateCoordinator = FlowTemplateCoordinator(session: self.session)
flowTemplateCoordinator.delegate = self
viewController.present(flowTemplateCoordinator.toPresentable(), animated: animated, completion: nil)
let presentable = flowTemplateCoordinator.toPresentable()
presentable.presentationController?.delegate = self
viewController.present(presentable, animated: animated, completion: nil)
flowTemplateCoordinator.start()
self.coordinator = flowTemplateCoordinator
@@ -80,3 +82,13 @@ extension FlowTemplateCoordinatorBridgePresenter: FlowTemplateCoordinatorDelegat
self.delegate?.flowTemplateCoordinatorBridgePresenterDelegateDidComplete(self)
}
}
// MARK: - UIAdaptivePresentationControllerDelegate
extension FlowTemplateCoordinatorBridgePresenter: UIAdaptivePresentationControllerDelegate {
func flowTemplateCoordinatorDidComplete(_ presentationController: UIPresentationController) {
self.delegate?.flowTemplateCoordinatorBridgePresenterDelegateDidComplete(self)
}
}