mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-16 06:28:27 +02:00
chore: Update to FOSS 1.11.31 (MESSENGER-7610)
Merge commit '822cbc5076da248fa7b997a5e3e906b03c4a09f7' into feature/7610_FOSS_Merge_1_11_31 # Conflicts: # Config/AppVersion.xcconfig # Podfile # Podfile.lock # README.md # Riot/Modules/Common/Recents/RecentsViewController.m # Riot/Modules/ContextMenu/Services/RoomContextActionService.swift # Riot/Modules/Room/Members/RoomParticipantsViewController.m # Riot/Modules/Room/RoomInfo/RoomInfoList/RoomInfoListViewController.swift # fastlane/Fastfile
This commit is contained in:
3
.github/workflows/ci-tests.yml
vendored
3
.github/workflows/ci-tests.yml
vendored
@@ -56,6 +56,9 @@ jobs:
|
||||
run: |
|
||||
bundle config path vendor/bundle
|
||||
bundle install --jobs 4 --retry 3
|
||||
|
||||
- name: Xcodegen
|
||||
run: mint run yonaskolb/XcodeGen@2.39.0
|
||||
|
||||
# Main step
|
||||
- name: Unit tests
|
||||
|
||||
3
.github/workflows/ci-ui-tests.yml
vendored
3
.github/workflows/ci-ui-tests.yml
vendored
@@ -51,6 +51,9 @@ jobs:
|
||||
run: |
|
||||
bundle config path vendor/bundle
|
||||
bundle install --jobs 4 --retry 3
|
||||
|
||||
- name: Xcodegen
|
||||
run: mint run yonaskolb/XcodeGen@2.39.0
|
||||
|
||||
# Main step
|
||||
- name: UI tests
|
||||
|
||||
33
CHANGES.md
33
CHANGES.md
@@ -1,3 +1,36 @@
|
||||
## Changes in 1.11.31 (2025-07-28)
|
||||
|
||||
✨ Features
|
||||
|
||||
- Support for MSC 4289. ([#7950](https://github.com/element-hq/element-ios/pull/7950))
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- PL 150 users will be displayed as Owners. ([#7951](https://github.com/element-hq/element-ios/issues/7951))
|
||||
- Owners can't leave the room if they are the last owners while also not being the last member. ([#7952](https://github.com/element-hq/element-ios/issues/7952))
|
||||
|
||||
🐛 Bugfixes
|
||||
|
||||
- Room continuity fix for room version 12. ([#7953](https://github.com/element-hq/element-ios/pull/7953))
|
||||
|
||||
|
||||
## Changes in 1.11.30 (2025-06-10)
|
||||
|
||||
No significant changes.
|
||||
|
||||
|
||||
## Changes in 1.11.29 (2025-05-29)
|
||||
|
||||
No significant changes.
|
||||
|
||||
|
||||
## Changes in 1.11.28 (2025-05-28)
|
||||
|
||||
🙌 Improvements
|
||||
|
||||
- Support for experimental MSC4286 during event rendering. ([#7927](https://github.com/element-hq/element-ios/pull/7927))
|
||||
|
||||
|
||||
## Changes in 1.11.27 (2025-03-28)
|
||||
|
||||
No significant changes.
|
||||
|
||||
@@ -16,6 +16,6 @@
|
||||
//
|
||||
|
||||
// Version
|
||||
MARKETING_VERSION = 2.25.0
|
||||
CURRENT_PROJECT_VERSION = 20220714163152
|
||||
|
||||
MARKETING_VERSION = 2.25.1
|
||||
CURRENT_PROJECT_VERSION = 20220714163152
|
||||
|
||||
31
Gemfile.lock
31
Gemfile.lock
@@ -26,17 +26,18 @@ GEM
|
||||
artifactory (3.0.17)
|
||||
atomos (0.1.3)
|
||||
aws-eventstream (1.3.2)
|
||||
aws-partitions (1.1063.0)
|
||||
aws-sdk-core (3.220.1)
|
||||
aws-partitions (1.1107.0)
|
||||
aws-sdk-core (3.224.0)
|
||||
aws-eventstream (~> 1, >= 1.3.0)
|
||||
aws-partitions (~> 1, >= 1.992.0)
|
||||
aws-sigv4 (~> 1.9)
|
||||
base64
|
||||
jmespath (~> 1, >= 1.6.1)
|
||||
aws-sdk-kms (1.99.0)
|
||||
logger
|
||||
aws-sdk-kms (1.101.0)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sigv4 (~> 1.5)
|
||||
aws-sdk-s3 (1.182.0)
|
||||
aws-sdk-s3 (1.186.1)
|
||||
aws-sdk-core (~> 3, >= 3.216.0)
|
||||
aws-sdk-kms (~> 1)
|
||||
aws-sigv4 (~> 1.5)
|
||||
@@ -90,13 +91,13 @@ GEM
|
||||
commander (4.6.0)
|
||||
highline (~> 2.0.0)
|
||||
concurrent-ruby (1.3.5)
|
||||
connection_pool (2.5.0)
|
||||
connection_pool (2.5.3)
|
||||
declarative (0.0.20)
|
||||
digest-crc (0.7.0)
|
||||
rake (>= 12.0.0, < 14.0.0)
|
||||
domain_name (0.6.20240107)
|
||||
dotenv (2.8.1)
|
||||
drb (2.2.1)
|
||||
drb (2.2.3)
|
||||
emoji_regex (3.2.3)
|
||||
escape (0.0.4)
|
||||
ethon (0.16.0)
|
||||
@@ -131,7 +132,7 @@ GEM
|
||||
faraday_middleware (1.2.1)
|
||||
faraday (~> 1.0)
|
||||
fastimage (2.4.0)
|
||||
fastlane (2.226.0)
|
||||
fastlane (2.227.2)
|
||||
CFPropertyList (>= 2.3, < 4.0.0)
|
||||
addressable (>= 2.8, < 3.0.0)
|
||||
artifactory (~> 3.0)
|
||||
@@ -171,17 +172,17 @@ GEM
|
||||
tty-spinner (>= 0.8.0, < 1.0.0)
|
||||
word_wrap (~> 1.0.0)
|
||||
xcodeproj (>= 1.13.0, < 2.0.0)
|
||||
xcpretty (~> 0.4.0)
|
||||
xcpretty (~> 0.4.1)
|
||||
xcpretty-travis-formatter (>= 0.0.3, < 2.0.0)
|
||||
fastlane-plugin-brew (0.1.1)
|
||||
fastlane-plugin-sentry (1.28.0)
|
||||
fastlane-plugin-sentry (1.29.0)
|
||||
os (~> 1.1, >= 1.1.4)
|
||||
fastlane-plugin-versioning (0.7.1)
|
||||
fastlane-plugin-xcodegen (1.1.0)
|
||||
fastlane-plugin-brew (~> 0.1.1)
|
||||
fastlane-sirp (1.0.0)
|
||||
sysrandom (~> 1.0)
|
||||
ffi (1.17.1)
|
||||
ffi (1.17.2)
|
||||
fourflusher (2.3.1)
|
||||
fuzzy_match (2.0.4)
|
||||
gh_inspector (1.1.3)
|
||||
@@ -229,14 +230,14 @@ GEM
|
||||
i18n (1.14.7)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jmespath (1.6.2)
|
||||
json (2.10.1)
|
||||
json (2.12.2)
|
||||
jwt (2.10.1)
|
||||
base64
|
||||
logger (1.6.6)
|
||||
logger (1.7.0)
|
||||
mini_magick (4.13.2)
|
||||
mini_mime (1.1.5)
|
||||
mini_portile2 (2.8.8)
|
||||
minitest (5.25.4)
|
||||
mini_portile2 (2.8.9)
|
||||
minitest (5.25.5)
|
||||
molinillo (0.8.0)
|
||||
multi_json (1.15.0)
|
||||
multipart-post (2.4.1)
|
||||
@@ -307,7 +308,7 @@ GEM
|
||||
colored2 (~> 3.1)
|
||||
nanaimo (~> 0.4.0)
|
||||
rexml (>= 3.3.6, < 4.0)
|
||||
xcpretty (0.4.0)
|
||||
xcpretty (0.4.1)
|
||||
rouge (~> 3.28.0)
|
||||
xcpretty-travis-formatter (1.0.1)
|
||||
xcpretty (~> 0.2, >= 0.0.7)
|
||||
|
||||
1
Podfile
1
Podfile
@@ -69,7 +69,6 @@ abstract_target 'RiotPods' do
|
||||
# Piwik for analytics
|
||||
pod 'MatomoTracker', '~> 7.5.2'
|
||||
|
||||
|
||||
pod 'zxcvbn-ios'
|
||||
|
||||
# Tools
|
||||
|
||||
111
Podfile.lock
111
Podfile.lock
@@ -14,49 +14,43 @@ PODS:
|
||||
- AFNetworking/Serialization (4.0.1)
|
||||
- AFNetworking/UIKit (4.0.1):
|
||||
- AFNetworking/NSURLSession
|
||||
- BlueCryptor (1.0.32)
|
||||
- BlueECC (1.2.5)
|
||||
- BlueRSA (1.0.200)
|
||||
- Down (0.11.0)
|
||||
- DSWaveformImage (6.1.1)
|
||||
- DTCoreText (1.6.26):
|
||||
- DTCoreText/Core (= 1.6.26)
|
||||
- DTFoundation/Core (~> 1.7.5)
|
||||
- DTFoundation/DTAnimatedGIF (~> 1.7.5)
|
||||
- DTFoundation/DTHTMLParser (~> 1.7.5)
|
||||
- DTFoundation/UIKit (~> 1.7.5)
|
||||
- DTCoreText/Core (1.6.26):
|
||||
- DTFoundation/Core (~> 1.7.5)
|
||||
- DTFoundation/DTAnimatedGIF (~> 1.7.5)
|
||||
- DTFoundation/DTHTMLParser (~> 1.7.5)
|
||||
- DTFoundation/UIKit (~> 1.7.5)
|
||||
- DTFoundation/Core (1.7.19)
|
||||
- DTFoundation/DTAnimatedGIF (1.7.19)
|
||||
- DTFoundation/DTHTMLParser (1.7.19):
|
||||
- DTFoundation/Core
|
||||
- DTFoundation/UIKit (1.7.19):
|
||||
- DTFoundation/Core
|
||||
- DTTJailbreakDetection (0.4.0)
|
||||
- FLEX (5.22.10)
|
||||
- FlowCommoniOS (1.12.2)
|
||||
- GBDeviceInfo (7.1.0):
|
||||
- GBDeviceInfo/Core (= 7.1.0)
|
||||
- GBDeviceInfo/Core (7.1.0)
|
||||
- GZIP (1.3.2)
|
||||
- Introspect (0.12.0)
|
||||
- JitsiMeetSDKLite (8.1.2-lite):
|
||||
- JitsiWebRTC (~> 111.0)
|
||||
- JitsiWebRTC (111.0.2)
|
||||
- KeychainAccess (4.2.2)
|
||||
- KituraContracts (1.2.1):
|
||||
- LoggerAPI (~> 1.7)
|
||||
- KTCenterFlowLayout (1.3.1)
|
||||
- libbase58 (0.1.4)
|
||||
- libPhoneNumber-iOS (0.9.15)
|
||||
- MatomoTracker (7.5.2):
|
||||
- MatomoTracker/Core (= 7.5.2)
|
||||
- MatomoTracker/Core (7.5.2)
|
||||
- LoggerAPI (1.9.200):
|
||||
- Logging (~> 1.1)
|
||||
- Logging (1.4.0)
|
||||
- MatrixSDK (0.27.17):
|
||||
- MatrixSDK/Core (= 0.27.17)
|
||||
- MatrixSDK/Core (0.27.17):
|
||||
- AFNetworking (~> 4.0.0)
|
||||
- GZIP (~> 1.3.0)
|
||||
- libbase58 (~> 0.1.4)
|
||||
- MatrixSDKCrypto (= 0.4.3)
|
||||
- MatrixSDKCrypto (= 0.11.1)
|
||||
- Realm (= 10.27.0)
|
||||
- SwiftyBeaver (= 1.9.5)
|
||||
- MatrixSDKCrypto (0.4.3)
|
||||
- MatrixSDK/JingleCallStack (0.27.17):
|
||||
- JitsiMeetSDKLite (= 8.1.2-lite)
|
||||
- MatrixSDK/Core
|
||||
- MatrixSDKCrypto (0.11.1)
|
||||
- ReadMoreTextView (3.0.1)
|
||||
- Realm (10.27.0):
|
||||
- Realm/Headers (= 10.27.0)
|
||||
@@ -66,9 +60,19 @@ PODS:
|
||||
- Reusable/View (= 4.1.2)
|
||||
- Reusable/Storyboard (4.1.2)
|
||||
- Reusable/View (4.1.2)
|
||||
- Sentry (8.46.0):
|
||||
- Sentry/Core (= 8.46.0)
|
||||
- Sentry/Core (8.46.0)
|
||||
- SideMenu (6.5.0)
|
||||
- SwiftBase32 (0.9.0)
|
||||
- SwiftFormat/CLI (0.54.5)
|
||||
- SwiftGen (6.6.3)
|
||||
- SwiftJWT (3.6.200):
|
||||
- BlueCryptor (~> 1.0)
|
||||
- BlueECC (~> 1.1)
|
||||
- BlueRSA (~> 1.0)
|
||||
- KituraContracts (~> 1.2)
|
||||
- LoggerAPI (~> 1.7)
|
||||
- SwiftLint (0.57.0)
|
||||
- SwiftyBeaver (1.9.5)
|
||||
- UICollectionViewLeftAlignedLayout (1.0.2)
|
||||
@@ -82,21 +86,23 @@ PODS:
|
||||
DEPENDENCIES:
|
||||
- Down (~> 0.11.0)
|
||||
- DSWaveformImage (~> 6.1.1)
|
||||
- DTCoreText (= 1.6.26)
|
||||
- DTTJailbreakDetection (~> 0.4.0)
|
||||
- FLEX (~> 5.22.10)
|
||||
- FlowCommoniOS (~> 1.12.0)
|
||||
- GBDeviceInfo (~> 7.1.0)
|
||||
- Introspect (~> 0.1)
|
||||
- KeychainAccess (~> 4.2.2)
|
||||
- KTCenterFlowLayout (~> 1.3.1)
|
||||
- libPhoneNumber-iOS (~> 0.9.13)
|
||||
- MatomoTracker (~> 7.5.2)
|
||||
- MatrixSDK (from `https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk`, tag `v2.25.0-RC01`)
|
||||
- MatrixSDK (from `matrix-ios-sdk/MatrixSDK.podspec`)
|
||||
- MatrixSDK/JingleCallStack (from `matrix-ios-sdk/MatrixSDK.podspec`)
|
||||
- ReadMoreTextView (~> 3.0.1)
|
||||
- Reusable (~> 4.1)
|
||||
- Sentry (~> 8.46.0)
|
||||
- SideMenu (~> 6.5)
|
||||
- SwiftBase32 (~> 0.9.0)
|
||||
- SwiftFormat/CLI
|
||||
- SwiftGen
|
||||
- SwiftJWT (~> 3.6.200)
|
||||
- SwiftLint
|
||||
- UICollectionViewLeftAlignedLayout (~> 1.0.2)
|
||||
- UICollectionViewRightAlignedLayout (~> 0.0.3)
|
||||
@@ -106,28 +112,37 @@ DEPENDENCIES:
|
||||
|
||||
SPEC REPOS:
|
||||
https://github.com/CocoaPods/Specs.git:
|
||||
- MatrixSDKCrypto
|
||||
- Sentry
|
||||
trunk:
|
||||
- AFNetworking
|
||||
- BlueCryptor
|
||||
- BlueECC
|
||||
- BlueRSA
|
||||
- Down
|
||||
- DSWaveformImage
|
||||
- DTCoreText
|
||||
- DTFoundation
|
||||
- DTTJailbreakDetection
|
||||
- FLEX
|
||||
- FlowCommoniOS
|
||||
- GBDeviceInfo
|
||||
- GZIP
|
||||
- Introspect
|
||||
- JitsiMeetSDKLite
|
||||
- JitsiWebRTC
|
||||
- KeychainAccess
|
||||
- KituraContracts
|
||||
- KTCenterFlowLayout
|
||||
- libbase58
|
||||
- libPhoneNumber-iOS
|
||||
- MatomoTracker
|
||||
- MatrixSDKCrypto
|
||||
- LoggerAPI
|
||||
- Logging
|
||||
- ReadMoreTextView
|
||||
- Realm
|
||||
- Reusable
|
||||
- SideMenu
|
||||
- SwiftBase32
|
||||
- SwiftFormat
|
||||
- SwiftGen
|
||||
- SwiftJWT
|
||||
- SwiftLint
|
||||
- SwiftyBeaver
|
||||
- UICollectionViewLeftAlignedLayout
|
||||
@@ -138,38 +153,40 @@ SPEC REPOS:
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
MatrixSDK:
|
||||
:git: https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk
|
||||
:tag: v2.25.0-RC01
|
||||
|
||||
CHECKOUT OPTIONS:
|
||||
MatrixSDK:
|
||||
:git: https://dl-gitlab.example.com/bwmessenger/bundesmessenger/bundesmessenger-ios-sdk
|
||||
:tag: v2.25.0-RC01
|
||||
:path: matrix-ios-sdk/MatrixSDK.podspec
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
AFNetworking: 3bd23d814e976cd148d7d44c3ab78017b744cd58
|
||||
BlueCryptor: b0aee3d9b8f367b49b30de11cda90e1735571c24
|
||||
BlueECC: 0d18e93347d3ec6d41416de21c1ffa4d4cd3c2cc
|
||||
BlueRSA: dfeef51db96bcc4edec654956c1581adbda4e6a3
|
||||
Down: b6ba1bc985c9d2f4e15e3b293d2207766fa12612
|
||||
DSWaveformImage: 3c718a0cf99291887ee70d1d0c18d80101d3d9ce
|
||||
DTCoreText: ec749e013f2e1f76de5e7c7634642e600a7467ce
|
||||
DTFoundation: 76b624967cf5bcaae6bb057d622c536c36ef36d0
|
||||
DTTJailbreakDetection: 5e356c5badc17995f65a83ed9483f787a0057b71
|
||||
FLEX: f21ee4f498eed3f8a1eded66b21939fd3b7a22ce
|
||||
FlowCommoniOS: ca92071ab526dc89905495a37844fd7e78d1a7f2
|
||||
GBDeviceInfo: 5d62fa85bdcce3ed288d83c28789adf1173e4376
|
||||
GZIP: 3c0abf794bfce8c7cb34ea05a1837752416c8868
|
||||
Introspect: b66b675de8a85d9ef832f3a710d8e3c7db186884
|
||||
JitsiMeetSDKLite: 895213158cf62342069a10634a41d2f1c00057f7
|
||||
JitsiWebRTC: 80f62908fcf2a1160e0d14b584323fb6e6be630b
|
||||
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
|
||||
KituraContracts: e845e60dc8627ad0a76fa55ef20a45451d8f830b
|
||||
KTCenterFlowLayout: 6e02b50ab2bd865025ae82fe266ed13b6d9eaf97
|
||||
libbase58: 8abc2a53ac38cd37720c0acbc53ef3660e9016c2
|
||||
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
|
||||
libPhoneNumber-iOS: 0a32a9525cf8744fe02c5206eb30d571e38f7d75
|
||||
MatomoTracker: 1d98ddc58322fd9d65e1a6886b8e41363047bd13
|
||||
MatrixSDK: 33d348122df228efa234d7b353c33620fc420a59
|
||||
MatrixSDKCrypto: 27bee960e0e8b3a3039f3f3e93dd2ec88299c77e
|
||||
LoggerAPI: ad9c4a6f1e32f518fdb43a1347ac14d765ab5e3d
|
||||
Logging: beeb016c9c80cf77042d62e83495816847ef108b
|
||||
MatrixSDK: 45f9f97e7424e5d8731bf6b207c728a71caa8eb1
|
||||
MatrixSDKCrypto: e44608012cae9befc52f13cd8e56c6f51ac83702
|
||||
ReadMoreTextView: 19147adf93abce6d7271e14031a00303fe28720d
|
||||
Realm: 9ca328bd7e700cc19703799785e37f77d1a130f2
|
||||
Reusable: 6bae6a5e8aa793c9c441db0213c863a64bce9136
|
||||
Sentry: da60d980b197a46db0b35ea12cb8f39af48d8854
|
||||
SideMenu: f583187d21c5b1dd04c72002be544b555a2627a2
|
||||
SwiftBase32: 9399c25a80666dc66b51e10076bf591e3bbb8f17
|
||||
SwiftFormat: 543a7b1ab4a6ce2d88bd5616a17903446ca3dc5c
|
||||
SwiftGen: 4993cbf71cbc4886f775e26f8d5c3a1188ec9f99
|
||||
SwiftJWT: 88c412708f58c169d431d344c87bc79a87c830ae
|
||||
SwiftLint: eb47480d47c982481592c195c221d11013a679cc
|
||||
SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82
|
||||
UICollectionViewLeftAlignedLayout: 830bf6fa5bab9f9b464f62e3384f9d2e00b3c0f6
|
||||
@@ -178,6 +195,6 @@ SPEC CHECKSUMS:
|
||||
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
|
||||
ZXingObjC: 8898711ab495761b2dbbdec76d90164a6d7e14c5
|
||||
|
||||
PODFILE CHECKSUM: b5e41c832b239f0b12152d3c9e66baf098d3d57d
|
||||
PODFILE CHECKSUM: 60f4fe3695f2304b9bba734acf38d59c79678ac1
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -167,3 +167,5 @@
|
||||
/** General **/
|
||||
|
||||
"Notification" = "إشعار";
|
||||
"VOICE_BROADCAST_FROM_USER" = "%@ بدأ بثًا صوتيًا";
|
||||
"UNSUPPORTED_CALL" = "مكالمة غير مدعومة";
|
||||
|
||||
@@ -2080,3 +2080,556 @@
|
||||
"poll_timeline_not_closed_subtitle" = "الرجاء المحاولة مرة أخرى";
|
||||
"poll_edit_form_post_failure_title" = "فشل في نشر الاستطلاع";
|
||||
"location_sharing_title" = "موقع";
|
||||
"room_details_fail_to_update_history_visibility" = "فشل في تحديث رؤية التاريخ";
|
||||
"room_details_copy_room_address" = "عنوان غرفة النسخ";
|
||||
"room_details_copy_room_url" = "نسخ عنوان URL للغرفة";
|
||||
"widget_integration_missing_room_id" = "room_id مفقود في الطلب.";
|
||||
"room_access_settings_screen_message" = "قرر من يمكنه العثور على %@ والانضمام إليه.";
|
||||
"room_access_settings_screen_upgrade_alert_message_no_param" = "سيتمكن أي شخص في مساحة الوالدين من العثور على هذه الغرفة والانضمام إليها - دون الحاجة إلى دعوة الجميع يدويًا. يمكنك تغيير ذلك في إعدادات الغرفة في أي وقت.";
|
||||
"room_access_settings_screen_upgrade_alert_note" = "يرجى ملاحظة أن الترقية ستؤدي إلى إنشاء نسخة جديدة من الغرفة. ستبقى جميع الرسائل الحالية في هذه الغرفة المؤرشفة.";
|
||||
"room_access_settings_screen_upgrade_alert_auto_invite_switch" = "دعوة الأعضاء تلقائيًا إلى غرفة جديدة";
|
||||
"room_notifs_settings_notify_me_for" = "أعلمني بذلك";
|
||||
"e2e_room_key_request_message" = "تطلب جلستك غير الموثقة '%@' مفاتيح التشفير.";
|
||||
"secure_key_backup_setup_intro_use_security_key_title" = "استخدم مفتاح الأمان";
|
||||
"secure_key_backup_setup_existing_backup_error_info" = "قم بإلغاء قفله لإعادة استخدامه في النسخ الاحتياطي الآمن أو احذفه لإنشاء نسخة احتياطية جديدة للرسائل في النسخ الاحتياطي الآمن.";
|
||||
"room_details_fail_to_add_room_aliases" = "فشل في إضافة عناوين الغرف الجديدة";
|
||||
"room_details_fail_to_update_room_direct" = "فشل في تحديث العلم المباشر لهذه الغرفة";
|
||||
"room_access_settings_screen_restricted_message" = "اسمح لأي شخص في مساحة بالبحث والانضمام.\nسيُطلب منك تأكيد المساحات.";
|
||||
"room_suggestion_settings_screen_title" = "إنشاء غرفة مقترحة في مساحة";
|
||||
"group_details_title" = "تفاصيل المجتمع";
|
||||
"group_invitation_format" = "لقد دعاك %@ للانضمام إلى هذا المجتمع";
|
||||
"directory_server_type_homeserver" = "اكتب خادمًا رئيسيًا لإدراج الغرف العامة منه";
|
||||
"bug_report_send_logs" = "إرسال تسجيلات الدخول";
|
||||
"e2e_room_key_request_start_verification" = "بدء التحقق…";
|
||||
"key_backup_setup_intro_manual_export_info" = "(متقدم)";
|
||||
"room_access_settings_screen_upgrade_alert_upgrading" = "ترقية الغرفة";
|
||||
"room_notifs_settings_done_action" = "منتهي";
|
||||
"e2e_room_key_request_share_without_verifying" = "شارك دون التحقق";
|
||||
"gdpr_consent_not_given_alert_review_now_action" = "قم بالمراجعة الآن";
|
||||
"service_terms_modal_description_integration_manager" = "سيسمح لك هذا باستخدام الروبوتات والجسور والأدوات وحزم الملصقات.";
|
||||
"key_backup_setup_title" = "النسخ الاحتياطي للمفتاح";
|
||||
"group_details_home" = "الصفحة الرئيسية";
|
||||
"room_details_set_main_address" = "تعيين كعنوان رئيسي";
|
||||
"room_notifs_settings_manage_notifications" = "يمكنك إدارة الإشعارات في %@";
|
||||
"room_notifs_settings_encrypted_room_notice" = "يرجى ملاحظة أن الإشارات وإشعارات الكلمات الرئيسية غير متوفرة في الغرف المشفرة على الهاتف المحمول.";
|
||||
"group_details_rooms" = "الغرف";
|
||||
"widget_integration_room_not_visible" = "الغرفة %@ غير مرئية.";
|
||||
"room_widget_permission_room_id_permission" = "معرف الغرفة";
|
||||
"service_terms_modal_information_title_integration_manager" = "مدير التكامل";
|
||||
"service_terms_modal_information_description_integration_manager" = "يتيح لك مدير التكامل إضافة ميزات من جهات خارجية.";
|
||||
"secure_key_backup_setup_intro_use_security_key_info" = "إنشاء مفتاح أمان لتخزينه في مكان آمن مثل مدير كلمات المرور أو الخزنة.";
|
||||
"secure_key_backup_setup_cancel_alert_message" = "إذا ألغيت الاشتراك الآن، فقد تفقد رسائلك وبياناتك المشفرة إذا فقدت الوصول إلى بيانات تسجيل الدخول الخاصة بك.\n\nيمكنك أيضًا إعداد النسخ الاحتياطي الآمن وإدارة مفاتيحك في الإعدادات.";
|
||||
"key_backup_setup_skip_alert_message" = "قد تفقد الرسائل الآمنة إذا قمت بتسجيل الخروج أو فقدت جهازك.";
|
||||
"widget_integration_missing_user_id" = "معرف المستخدم مفقود في الطلب.";
|
||||
"widget_picker_manage_integrations" = "إدارة التكاملات…";
|
||||
"room_widget_permission_creator_info_title" = "تمت إضافة هذه الودجت بواسطة:";
|
||||
"share_extension_auth_prompt" = "قم بتسجيل الدخول إلى التطبيق الرئيسي لمشاركة المحتوى";
|
||||
"e2e_room_key_request_message_new_device" = "لقد قمت بإضافة جلسة جديدة '%@'، والتي تطلب مفاتيح التشفير.";
|
||||
"room_access_settings_screen_setting_room_access" = "الوصول إلى غرفة الإعداد";
|
||||
"group_home_multi_rooms_format" = "%tu غرف";
|
||||
"group_participants_add_participant" = "إضافة مشارك";
|
||||
"group_participants_leave_prompt_msg" = "هل أنت متأكد أنك تريد مغادرة المجموعة؟";
|
||||
"room_widget_permission_widget_id_permission" = "معرف الودجت";
|
||||
"share_extension_low_quality_video_title" = "سيتم إرسال الفيديو بجودة منخفضة";
|
||||
"share_extension_low_quality_video_message" = "أرسل %@ للحصول على جودة أفضل، أو أرسل بجودة منخفضة أدناه.";
|
||||
"e2e_room_key_request_title" = "طلب مفتاح التشفير";
|
||||
"service_terms_modal_decline_button" = "رفض";
|
||||
"service_terms_modal_description_identity_server" = "سيسمح هذا لأي شخص بالعثور عليك إذا كان لديه رقم هاتفك أو بريدك الإلكتروني محفوظًا في جهات اتصال هاتفه.";
|
||||
"room_access_space_chooser_other_spaces_section_info" = "من المحتمل أن تكون هذه أشياء يشارك فيها مسؤولون آخرون في %@.";
|
||||
"room_access_settings_screen_nav_title" = "الوصول إلى الغرفة";
|
||||
"service_terms_modal_table_header_integration_manager" = "شروط مدير التكامل";
|
||||
"room_access_settings_screen_public_message" = "يمكن لأي شخص العثور والانضمام.";
|
||||
"room_notifs_settings_none" = "لا أحد";
|
||||
"room_details_fail_to_enable_encryption" = "فشل في تمكين التشفير في هذه الغرفة";
|
||||
"room_details_copy_room_id" = "معرف غرفة النسخ";
|
||||
"room_access_settings_screen_upgrade_alert_upgrade_button" = "ترقية";
|
||||
"room_suggestion_settings_screen_message" = "يتم الترويج للغرف المقترحة لأعضاء الفضاء باعتبارها غرفًا جيدة للانضمام إليها.";
|
||||
"room_notifs_settings_account_settings" = "إعدادات الحساب";
|
||||
"group_participants_remove_prompt_title" = "تأكيد";
|
||||
"service_terms_modal_footer" = "يمكن تعطيل هذه الميزة في أي وقت من خلال الإعدادات.";
|
||||
"deactivate_account_forget_messages_information_part1" = "يرجى نسيان جميع الرسائل التي أرسلتها عندما تم إلغاء تنشيط حسابي (";
|
||||
"secure_key_backup_setup_intro_info" = "قم بحماية نفسك من فقدان الوصول إلى الرسائل والبيانات المشفرة عن طريق عمل نسخة احتياطية لمفاتيح التشفير على الخادم الخاص بك.";
|
||||
"key_backup_setup_intro_manual_export_action" = "تصدير المفاتيح يدويًا";
|
||||
"room_widget_permission_avatar_url_permission" = "عنوان URL للصورة الرمزية الخاصة بك";
|
||||
"share_extension_failed_to_encrypt" = "فشل الإرسال. تحقق من إعدادات التشفير لهذه الغرفة في التطبيق الرئيسي";
|
||||
"secure_key_backup_setup_intro_use_security_passphrase_info" = "أدخل عبارة سرية تعرفها أنت فقط، ثم قم بإنشاء مفتاح للنسخ الاحتياطي.";
|
||||
"room_details_fail_to_remove_room_aliases" = "فشل في إزالة عناوين الغرف";
|
||||
"room_access_settings_screen_private_message" = "يمكن فقط للأشخاص المدعوين العثور على الصفحة والانضمام إليها.";
|
||||
"room_access_settings_screen_edit_spaces" = "تحرير المساحات";
|
||||
"group_details_people" = "الناس";
|
||||
"widget_integration_must_be_in_room" = "أنت لست في هذه الغرفة.";
|
||||
"widget_integration_no_permission_in_room" = "ليس لديك الإذن للقيام بذلك في هذه الغرفة.";
|
||||
"deactivate_account_informations_part2_emphasize" = "هذا الإجراء لا رجعة فيه.";
|
||||
"deactivate_account_validate_action" = "إلغاء تنشيط الحساب";
|
||||
"deactivate_account_password_alert_message" = "للمتابعة، الرجاء إدخال كلمة مرور حساب Matrix الخاص بك";
|
||||
"secure_key_backup_setup_existing_backup_error_unlock_it" = "افتحه";
|
||||
"room_notifs_settings_cancel_action" = "إلغاء";
|
||||
"share_extension_send_now" = "أرسل الآن";
|
||||
"service_terms_modal_title_message" = "للمتابعة، قم بقبول الشروط والأحكام أدناه";
|
||||
"room_details_promote_room_suggest_title" = "اقترح على أعضاء المساحة";
|
||||
"room_details_fail_to_update_room_canonical_alias" = "فشل في تحديث العنوان الرئيسي";
|
||||
"room_details_unset_main_address" = "غير مُعيَّن كعنوان رئيسي";
|
||||
"e2e_room_key_request_ignore_request" = "تجاهل الطلب";
|
||||
"deactivate_account_forget_messages_information_part3" = ": سيؤدي هذا إلى جعل المستخدمين في المستقبل يرون عرضًا غير كامل للمحادثات)";
|
||||
"rerequest_keys_alert_title" = "تم إرسال الطلب";
|
||||
"room_details_fail_to_update_room_communities" = "فشل في تحديث المجتمعات ذات الصلة";
|
||||
"group_home_one_room_format" = "غرفة واحدة";
|
||||
"widget_creation_failure" = "فشل إنشاء الودجت";
|
||||
"service_terms_modal_information_title_identity_server" = "خادم الهوية";
|
||||
"deactivate_account_forget_messages_information_part2_emphasize" = "تحذير";
|
||||
"key_backup_setup_skip_alert_title" = "هل أنت متأكد؟";
|
||||
"key_backup_setup_intro_title" = "لا تفقد الرسائل المشفرة أبدًا";
|
||||
"widget_picker_title" = "التكاملات";
|
||||
"service_terms_modal_accept_button" = "قبول";
|
||||
"key_backup_setup_intro_info" = "الرسائل في الغرف المشفرة مؤمنة بتشفير شامل. أنت والمستلم فقط لديهما مفاتيح قراءة هذه الرسائل.\n\nاحتفظ بنسخة احتياطية آمنة من مفاتيحك لتجنب فقدانها.";
|
||||
"room_access_settings_screen_upgrade_alert_title" = "ترقية الغرفة";
|
||||
"room_notifs_settings_all_messages" = "كل الرسائل";
|
||||
"deactivate_account_title" = "إلغاء تنشيط الحساب";
|
||||
"deactivate_account_informations_part4_emphasize" = "لا يؤدي افتراضيًا إلى نسيان الرسائل التي أرسلتها. ";
|
||||
"secure_key_backup_setup_intro_use_security_passphrase_title" = "استخدم عبارة أمنية";
|
||||
"key_backup_setup_passphrase_title" = "تأمين النسخة الاحتياطية الخاصة بك باستخدام عبارة أمان";
|
||||
"bug_report_progress_zipping" = "جمع تسجيلات الدخول";
|
||||
"room_details_save_changes_prompt" = "هل تريد حفظ التغييرات؟";
|
||||
"room_access_settings_screen_title" = "من يمكنه الوصول إلى هذه الغرفة؟";
|
||||
"room_access_settings_screen_upgrade_required" = "الترقية مطلوبة";
|
||||
"room_access_settings_screen_upgrade_alert_message" = "سيتمكن أي شخص في %@ من العثور على هذه الغرفة والانضمام إليها - دون الحاجة إلى دعوة الجميع يدويًا. يمكنك تغيير ذلك في أي وقت من إعدادات الغرفة.";
|
||||
"room_access_space_chooser_known_spaces_section" = "المساحات التي تعرف أنها تحتوي على %@";
|
||||
"room_access_space_chooser_other_spaces_section" = "مساحات أو غرف أخرى";
|
||||
"room_suggestion_settings_screen_nav_title" = "اقتراح غرفة";
|
||||
"room_notifs_settings_mentions_and_keywords" = "الإشارات والكلمات الرئيسية فقط";
|
||||
"group_home_one_member_format" = "عضو واحد";
|
||||
"group_home_multi_members_format" = "%tu أعضاء";
|
||||
"group_participants_leave_prompt_title" = "مغادرة المجموعة";
|
||||
"event_formatter_widget_removed" = "تمت إزالة الودجت %@ بواسطة %@";
|
||||
"widget_integration_room_not_recognised" = "لم يتم التعرف على هذه الغرفة.";
|
||||
"widget_integration_positive_power_level" = "يجب أن يكون مستوى الطاقة عددًا صحيحًا موجبًا.";
|
||||
"widget_integration_manager_disabled" = "يجب عليك تمكين مدير التكامل في الإعدادات";
|
||||
"room_widget_permission_webview_information_title" = "قد يؤدي استخدامه إلى تعيين ملفات تعريف الارتباط ومشاركة البيانات مع %@:\n";
|
||||
"room_widget_permission_display_name_permission" = "اسم العرض الخاص بك";
|
||||
"room_widget_permission_user_id_permission" = "معرف المستخدم الخاص بك";
|
||||
"gdpr_consent_not_given_alert_message" = "لمواصلة استخدام %@ homeserver، يجب عليك مراجعة الشروط والأحكام والموافقة عليها.";
|
||||
"service_terms_modal_table_header_identity_server" = "شروط خادم الهوية";
|
||||
"deactivate_account_informations_part1" = "سيؤدي هذا إلى تعطيل حسابك نهائيًا. لن تتمكن من تسجيل الدخول، ولن يتمكن أي شخص من إعادة تسجيل اسم المستخدم نفسه. سيؤدي هذا إلى مغادرة حسابك جميع الغرف التي يشارك فيها، وإزالة تفاصيل حسابك من خادم الهوية الخاص بك. ";
|
||||
"deactivate_account_informations_part5" = "إذا كنت ترغب في حذف رسائلك، يُرجى وضع علامة في المربع أدناه.\n\nتشبه ميزة رؤية الرسائل في Matrix ميزة البريد الإلكتروني. تعني ميزة \"حذف رسائلك\" أن الرسائل التي أرسلتها لن تُشارك مع أي مستخدمين جدد أو غير مسجلين، بينما سيظل بإمكان المستخدمين المسجلين الذين لديهم حق الوصول إلى هذه الرسائل الوصول إلى نسخهم.";
|
||||
"deactivate_account_password_alert_title" = "إلغاء تنشيط الحساب";
|
||||
"secure_key_backup_setup_intro_title" = "النسخ الاحتياطي الآمن";
|
||||
"secure_key_backup_setup_existing_backup_error_title" = "توجد نسخة احتياطية للرسائل بالفعل";
|
||||
"secure_key_backup_setup_existing_backup_error_delete_it" = "احذفه";
|
||||
"secure_key_backup_setup_cancel_alert_title" = "هل انت متأكد؟";
|
||||
"secure_backup_setup_banner_title" = "النسخ الاحتياطي الآمن";
|
||||
"secure_backup_setup_banner_subtitle" = "الحماية من فقدان الوصول إلى الرسائل والبيانات المشفرة";
|
||||
"key_backup_setup_skip_alert_skip_action" = "تخطي";
|
||||
"key_backup_setup_intro_setup_action_without_existing_backup" = "ابدأ باستخدام النسخ الاحتياطي للمفتاح";
|
||||
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "قم بتوصيل هذا الجهاز بـ Key Backup";
|
||||
"room_widget_permission_title" = "ودجت تحميل";
|
||||
"room_widget_permission_information_title" = "قد يؤدي استخدامه إلى مشاركة البيانات مع %@:\n";
|
||||
"service_terms_modal_information_description_identity_server" = "يساعدك خادم الهوية في العثور على جهات الاتصال الخاصة بك، من خلال البحث عن رقم الهاتف أو عنوان البريد الإلكتروني، لمعرفة ما إذا كان لديهم حساب بالفعل.";
|
||||
"rerequest_keys_alert_message" = "يرجى تشغيل %@ على جهاز آخر يمكنه فك تشفير الرسالة حتى يتمكن من إرسال المفاتيح إلى هذه الجلسة.";
|
||||
"key_backup_setup_passphrase_info" = "سنخزن نسخة مشفرة من مفاتيحك على خادمنا. احمِ نسختك الاحتياطية بعبارة للحفاظ عليها آمنة.\n\nلأقصى درجات الأمان، يجب أن تكون كلمة المرور مختلفة عن كلمة مرور حساب Matrix الخاص بك.";
|
||||
"device_verification_emoji_trophy" = "غنيمة";
|
||||
"key_backup_recover_invalid_passphrase_title" = "عبارة أمنية غير صحيحة";
|
||||
"key_backup_recover_invalid_recovery_key_title" = "عدم تطابق مفتاح الأمان";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_info" = "أو قم بتأمين النسخة الاحتياطية الخاصة بك باستخدام مفتاح أمان، وحفظها في مكان آمن.";
|
||||
"key_backup_recover_title" = "رسائل آمنة";
|
||||
"key_backup_recover_from_private_key_info" = "جاري استعادة النسخة الاحتياطية…";
|
||||
"device_verification_emoji_cloud" = "سحاب";
|
||||
"device_verification_emoji_clock" = "ساعة";
|
||||
"device_verification_emoji_pencil" = "قلم رصاص";
|
||||
"key_backup_setup_passphrase_passphrase_invalid" = "حاول إضافة كلمة";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_invalid" = "العبارة لا تتطابق";
|
||||
"key_backup_setup_success_from_recovery_key_info" = "يتم الآن نسخ مفاتيحك احتياطيًا.\n\nانسخ مفتاح الأمان هذا واحتفظ به في مكان آمن.";
|
||||
"device_verification_emoji_panda" = "باندا";
|
||||
"device_verification_emoji_telephone" = "الهاتف";
|
||||
"device_verification_emoji_pig" = "خنزير";
|
||||
"device_verification_emoji_paperclip" = "مشبك";
|
||||
"device_verification_emoji_ball" = "كرة";
|
||||
"device_verification_emoji_guitar" = "غيتار";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "تأكيد العبارة";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = ".";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "أدخل مفتاح الأمان";
|
||||
"device_verification_emoji_glasses" = "نظارات";
|
||||
"device_verification_emoji_unicorn" = "وحيد القرن";
|
||||
"device_verification_emoji_flower" = "ورد";
|
||||
"device_verification_emoji_tree" = "شجرة";
|
||||
"device_verification_emoji_cactus" = "صبار";
|
||||
"device_verification_emoji_smiley" = "ابتسامة";
|
||||
"device_verification_emoji_scissors" = "مقص";
|
||||
"device_verification_emoji_hammer" = "مطرقة";
|
||||
"device_verification_emoji_banana" = "موز";
|
||||
"device_verification_emoji_turtle" = "سلحفاة";
|
||||
"key_backup_setup_passphrase_passphrase_valid" = "عظيم!";
|
||||
"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "حفظ مفتاح الأمان";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "لا تعرف عبارة الأمان الخاصة بك؟ يمكنك ";
|
||||
"device_verification_emoji_octopus" = "الأخطبوط";
|
||||
"device_verification_emoji_strawberry" = "الفراولة";
|
||||
"device_verification_emoji_heart" = "قلب";
|
||||
"device_verification_emoji_hourglass" = "الساعة الرملية";
|
||||
"device_verification_emoji_key" = "مفتاح";
|
||||
"device_verification_emoji_flag" = "علَم";
|
||||
"device_verification_emoji_bicycle" = "دراجة";
|
||||
"device_verification_emoji_rocket" = "صاروخ";
|
||||
"device_verification_emoji_aeroplane" = "طائرة";
|
||||
"device_verification_emoji_horse" = "حصان";
|
||||
"device_verification_emoji_elephant" = "فيل";
|
||||
"device_verification_emoji_rabbit" = "أرنب";
|
||||
"key_backup_setup_success_from_recovery_key_recovery_key_title" = "مفتاح الأمان";
|
||||
"device_verification_emoji_rooster" = "ديك";
|
||||
"device_verification_emoji_light bulb" = "مصباح كهربائي";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_valid" = "عظيم!";
|
||||
"key_backup_setup_success_title" = "نجاح!";
|
||||
"key_backup_recover_from_passphrase_info" = "استخدم عبارة الأمان الخاصة بك لفتح سجل رسائلك الآمنة";
|
||||
"device_verification_emoji_penguin" = "البطريق";
|
||||
"device_verification_emoji_apple" = "تفاحة";
|
||||
"device_verification_emoji_book" = "كتاب";
|
||||
"key_backup_setup_success_from_recovery_key_make_copy_action" = "اصنع نسخة";
|
||||
"key_backup_setup_passphrase_setup_recovery_key_action" = "(متقدم) الإعداد باستخدام مفتاح الأمان";
|
||||
"device_verification_emoji_fish" = "سمكة";
|
||||
"device_verification_emoji_corn" = "حبوب ذرة";
|
||||
"device_verification_emoji_robot" = "روبوت";
|
||||
"key_backup_setup_passphrase_passphrase_title" = "دخول";
|
||||
"device_verification_emoji_umbrella" = "مظلة";
|
||||
"device_verification_emoji_cake" = "كعكة";
|
||||
"device_verification_emoji_lock" = "قفل";
|
||||
"security_settings_crosssigning_bootstrap" = "إعداد";
|
||||
"event_formatter_call_decline" = "رفض";
|
||||
"key_backup_setup_passphrase_passphrase_placeholder" = "أدخل العبارة";
|
||||
"key_backup_setup_passphrase_confirm_passphrase_title" = "تأكيد";
|
||||
"key_backup_setup_success_from_passphrase_info" = "يتم نسخ مفاتيحك احتياطيًا.\n\nمفتاح الأمان الخاص بك هو بمثابة شبكة أمان، يمكنك استخدامه لاستعادة الوصول إلى رسائلك المشفرة في حال نسيت كلمة المرور.\n\nاحتفظ بمفتاح الأمان الخاص بك في مكان آمن للغاية، مثل مدير كلمات المرور (أو خزنة).";
|
||||
"key_backup_setup_success_from_passphrase_done_action" = "منتهي";
|
||||
"key_backup_setup_success_from_recovery_key_made_copy_action" = "لقد قمت بعمل نسخة";
|
||||
"key_backup_setup_success_from_secure_backup_info" = "يتم إجراء نسخة احتياطية لمفاتيحك.";
|
||||
"key_backup_recover_invalid_passphrase" = "لم يتم فك تشفير النسخ الاحتياطي باستخدام هذه العبارة: يرجى التأكد من إدخال عبارة الأمان الصحيحة.";
|
||||
"key_backup_recover_invalid_recovery_key" = "لم يتمكن من فك تشفير النسخة الاحتياطية باستخدام هذا المفتاح: يرجى التأكد من إدخال مفتاح الأمان الصحيح.";
|
||||
"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "استخدم مفتاح الأمان الخاص بك";
|
||||
"key_backup_recover_from_recovery_key_info" = "استخدم مفتاح الأمان الخاص بك لفتح سجل رسائلك الآمنة";
|
||||
"device_verification_emoji_lion" = "الأسد";
|
||||
"device_verification_emoji_butterfly" = "فراشة";
|
||||
"device_verification_emoji_globe" = "الكرة الأرضية";
|
||||
"device_verification_emoji_fire" = "نار";
|
||||
"device_verification_emoji_pizza" = "بيتزا";
|
||||
"device_verification_emoji_spanner" = "مفتاح البراغي";
|
||||
"device_verification_emoji_gift" = "هدية";
|
||||
"key_backup_recover_from_passphrase_recover_action" = "فتح التاريخ";
|
||||
"device_verification_emoji_mushroom" = "فطر";
|
||||
"device_verification_emoji_moon" = "القمر";
|
||||
"key_backup_recover_from_passphrase_passphrase_placeholder" = "أدخل العبارة";
|
||||
"deactivate_account_informations_part3" = "\n\nإلغاء تنشيط حسابك ";
|
||||
"user_verification_sessions_list_user_trust_level_unknown_title" = "غير معروف";
|
||||
"spaces_coming_soon_detail" = "لم تُطبّق هذه الميزة هنا، ولكنها في طريقها. حاليًا، يمكنك القيام بذلك باستخدام %@ على جهاز الكمبيوتر.";
|
||||
"space_feature_unavailable_subtitle" = "لم يتم إطلاق Spaces على نظام التشغيل iOS بعد، ولكن يمكنك استخدامها الآن على الويب وسطح المكتب";
|
||||
"space_feature_unavailable_information" = "المساحات وسيلة جديدة لتجميع الغرف والأشخاص.\n\nستتوفر قريبًا. حاليًا، إذا انضممت إلى واحدة عبر منصة أخرى، ستتمكن من الوصول إلى أي غرف تنضم إليها هنا.";
|
||||
"space_tag" = "مساحة";
|
||||
"spaces_empty_space_detail" = "قد تكون بعض الغرف مخفية لأنها خاصة وتحتاج إلى دعوة.";
|
||||
"spaces_no_member_found_detail" = "هل تبحث عن شخص ليس في %@؟ حاليًا، يمكنك دعوته عبر الويب أو سطح المكتب.";
|
||||
"spaces_no_room_found_detail" = "قد تكون بعض النتائج مخفية لأنها خاصة وتحتاج إلى دعوة للانضمام إليها.";
|
||||
"space_settings_update_failed_message" = "فشل تحديث إعدادات المساحة. هل تريد إعادة المحاولة؟";
|
||||
"space_private_join_rule" = "مساحة خاصة";
|
||||
"major_update_learn_more_action" = "معرفة المزيد";
|
||||
"emoji_picker_title" = "ردود الفعل";
|
||||
"emoji_picker_symbols_category" = "الرموز";
|
||||
"user_verification_start_information_part1" = "لمزيد من الأمان، قم بالتحقق ";
|
||||
"user_verification_sessions_list_user_trust_level_trusted_title" = "موثوق به";
|
||||
"user_verification_session_details_information_trusted_current_user" = "تمت الوثوق بهذه الجلسة للمراسلة الآمنة لأنك قمت بالتحقق منها:";
|
||||
"user_verification_session_details_information_trusted_other_user_part1" = "هذه الجلسة موثوقة للمراسلة الآمنة لأنها ";
|
||||
"user_verification_session_details_information_trusted_other_user_part2" = " تم التحقق من ذلك:";
|
||||
"home_context_menu_mute" = "كتم";
|
||||
"room_intro_cell_information_dm_sentence1_part1" = "هذه هي بداية رسالتك المباشرة مع ";
|
||||
"room_intro_cell_information_dm_sentence2" = "أنتما الاثنان فقط في هذه المحادثة، ولا يمكن لأي شخص آخر الانضمام.";
|
||||
"room_invite_not_enough_permission" = "ليس لديك إذن لدعوة الأشخاص إلى هذه الغرفة";
|
||||
"leave_space_message" = "هل أنت متأكد أنك تريد مغادرة %@؟ هل تريد أيضًا مغادرة جميع الغرف والمساحات في هذه المساحة؟";
|
||||
"spaces_suggested_room" = "مقترح";
|
||||
"spaces_empty_space_title" = "لا يوجد غرف في هذه المساحة (حتى الآن)";
|
||||
"spaces_add_rooms_coming_soon_title" = "سيتم إضافة الغرف قريبًا";
|
||||
"space_participants_action_remove" = "إزالة من هذه المساحة";
|
||||
"space_participants_action_ban" = "حظر من هذه المساحة";
|
||||
"space_home_show_all_rooms" = "عرض جميع الغرف";
|
||||
"space_private_join_rule_detail" = "للدعوة فقط، الأفضل لك أو لفريقك";
|
||||
"spaces_invite_people" = "دعوة الناس";
|
||||
"spaces_add_space" = "إضافة مساحة";
|
||||
"spaces_feature_not_available" = "هذه الميزة غير متوفرة هنا. حاليًا، يمكنك القيام بذلك باستخدام %@ على جهاز الكمبيوتر الخاص بك.";
|
||||
"spaces_creation_footer" = "يمكنك تغيير هذا لاحقًا";
|
||||
"device_verification_emoji_headphones" = "سماعات الرأس";
|
||||
"user_verification_session_details_information_untrusted_other_user" = " تم تسجيل الدخول باستخدام جلسة جديدة:";
|
||||
"user_verification_session_details_additional_information_untrusted_other_user" = "حتى يثق هذا المستخدم بهذه الجلسة، تُعلَّم الرسائل المرسلة إليها ومنها بتحذيرات. يمكنك أيضًا التحقق منها يدويًا.";
|
||||
"secrets_recovery_with_passphrase_passphrase_placeholder" = "أدخل عبارة الأمان";
|
||||
"create_room_section_footer_type_restricted" = "يمكن لأي شخص في اسم المساحة البحث والانضمام.";
|
||||
"space_beta_announce_information" = "المساحات هي طريقة جديدة لتجميع الغرف والأشخاص. لم تتوفر بعد على نظام iOS، ولكن يمكنك استخدامها الآن على الويب وسطح المكتب.";
|
||||
"leave_space_message_admin_warning" = "أنت مسؤول عن هذه المساحة، تأكد من أنك قمت بنقل حقوق المسؤول إلى عضو آخر قبل المغادرة.";
|
||||
"spaces_creation_settings_message" = "أضف بعض التفاصيل لإبرازها. يمكنك تغييرها في أي وقت.";
|
||||
"device_verification_emoji_anchor" = "مِرسَاة";
|
||||
"error_not_supported_on_mobile" = "لا يمكنك القيام بذلك من %@الجوال.";
|
||||
"user_verification_sessions_list_user_trust_level_warning_title" = "تحذير";
|
||||
"user_verification_session_details_verify_action_current_user" = "التحقق بشكل تفاعلي";
|
||||
"create_room_placeholder_topic" = "ما هي هذه الغرفة؟";
|
||||
"room_intro_cell_information_room_without_topic_sentence2_part1" = "أضف موضوعًا";
|
||||
"space_invite_not_enough_permission" = "ليس لديك إذن لدعوة الأشخاص إلى هذه المساحة";
|
||||
"space_public_join_rule_detail" = "مفتوح للجميع، الأفضل للمجتمعات";
|
||||
"spaces_creation_visibility_message" = "للانضمام إلى مساحة موجودة، تحتاج إلى دعوة.";
|
||||
"space_topic" = "وصف";
|
||||
"reaction_history_title" = "ردود الفعل";
|
||||
"home_context_menu_leave" = "يغادر";
|
||||
"spaces_add_space_title" = "إنشاء مساحة";
|
||||
"spaces_explore_rooms" = "استكشاف الغرف";
|
||||
"device_verification_emoji_bell" = "جرس";
|
||||
"device_verification_emoji_pin" = "دبوس";
|
||||
"space_feature_unavailable_title" = "المساحات ليست هنا بعد";
|
||||
"key_verification_bootstrap_not_setup_message" = "يجب عليك أولاً تمهيد التوقيع المتبادل.";
|
||||
"user_verification_session_details_verify_action_other_user" = "التحقق يدويًا";
|
||||
"secrets_recovery_with_passphrase_information_verify_device" = "استخدم عبارة الأمان الخاصة بك للتحقق من هذا الجهاز.";
|
||||
"key_verification_alert_title" = "لديك جلسات غير موثقة";
|
||||
"device_verification_emoji_folder" = "مجلد";
|
||||
"file_upload_error_unsupported_file_type_message" = "نوع الملف غير مدعوم.";
|
||||
"emoji_picker_places_category" = "السفر والأماكن";
|
||||
"error_invite_3pid_with_no_identity_server" = "أضف خادم هوية في إعداداتك لدعوتك عبر البريد الإلكتروني.";
|
||||
"user_verification_start_waiting_partner" = "في انتظار %@…";
|
||||
"user_verification_session_details_trusted_title" = "موثوق به";
|
||||
"user_verification_session_details_untrusted_title" = "غير موثوق به";
|
||||
"secrets_recovery_reset_action_part_2" = "إعادة تعيين كل شيء";
|
||||
"secrets_recovery_with_passphrase_title" = "عبارة أمنية";
|
||||
"room_invite_to_space_option_detail" = "بإمكانهم استكشاف %@، ولكنهم لن يكونوا أعضاءً في %@.";
|
||||
"spaces_home_space_title" = "الصفحة الرئيسية";
|
||||
"spaces_left_panel_title" = "المساحات";
|
||||
"leave_space_and_all_rooms_action" = "اترك جميع الغرف والمساحات";
|
||||
"spaces_no_result_found_title" = "لم يتم العثور على نتائج";
|
||||
"spaces_invites_coming_soon_title" = "الدعوات قادمة قريبا";
|
||||
"spaces_add_room" = "إضافة غرفة";
|
||||
"spaces_subspace_creation_visibility_message" = "سيتم إضافة المساحة التي تم إنشاؤها إلى %@.";
|
||||
"space_public_join_rule" = "مساحة عامة";
|
||||
"secrets_recovery_with_passphrase_information_default" = "قم بالوصول إلى سجل رسائلك الآمنة وهوية التوقيع المتبادل الخاصة بك للتحقق من الجلسات الأخرى عن طريق إدخال عبارة الأمان الخاصة بك.";
|
||||
"emoji_picker_foods_category" = "الطعام والشراب";
|
||||
"emoji_picker_activity_category" = "أنشطة";
|
||||
"user_verification_sessions_list_table_title" = "الجلسات";
|
||||
"create_room_type_restricted" = "أعضاء المساحة";
|
||||
"room_invite_to_room_option_detail" = "لن يكونوا جزءًا من %@.";
|
||||
"spaces_add_subspace_title" = "إنشاء مساحة داخل %@";
|
||||
"space_settings_current_address_message" = "مساحتك متاحة للعرض على\n%@";
|
||||
"leave_space_only_action" = "لا تغادر أي غرف";
|
||||
"spaces_explore_rooms_room_number" = "%@ غرف";
|
||||
"user_verification_sessions_list_session_trusted" = "موثوق به";
|
||||
"create_room_show_in_directory_footer" = "سيساعد هذا الأشخاص في العثور على أعضاء جدد والانضمام إليهم.";
|
||||
"room_intro_cell_information_room_without_topic_sentence2_part2" = " لإعلام الناس بما تحتويه هذه الغرفة.";
|
||||
"spaces_create_space_title" = "إنشاء مساحة";
|
||||
"spaces_create_subspace_title" = "إنشاء مساحة فرعية";
|
||||
"file_upload_error_title" = "تحميل الملف";
|
||||
"emoji_picker_people_category" = "الوجوه الضاحكة والأشخاص";
|
||||
"emoji_picker_nature_category" = "الحيوانات والطبيعة";
|
||||
"emoji_picker_objects_category" = "أشياء";
|
||||
"emoji_picker_flags_category" = "الأعلام";
|
||||
"key_verification_bootstrap_not_setup_title" = "خطأ";
|
||||
"key_verification_tile_request_incoming_title" = "طلب التحقق";
|
||||
"key_verification_tile_request_outgoing_title" = "تم إرسال التحقق";
|
||||
"user_verification_start_verify_action" = "بدء التحقق";
|
||||
"user_verification_start_information_part2" = " عن طريق التحقق من رمز لمرة واحدة على كلا الجهازين.";
|
||||
"user_verification_start_additional_information" = "لضمان الأمان، قم بذلك شخصيًا أو استخدم طريقة أخرى للتواصل.";
|
||||
"user_verification_sessions_list_information" = "الرسائل التي يتبادلها هذا المستخدم في هذه الغرفة تكون مشفرة من البداية إلى النهاية ولا يمكن لأطراف ثالثة قراءتها.";
|
||||
"user_verification_session_details_information_untrusted_current_user" = "قم بالتحقق من هذه الجلسة لوضع علامة عليها كموثوقة ومنحها حق الوصول إلى الرسائل المشفرة:";
|
||||
"user_verification_session_details_additional_information_untrusted_current_user" = "إذا لم تقم بتسجيل الدخول إلى هذه الجلسة، فقد يكون حسابك معرضًا للخطر.";
|
||||
"user_verification_session_details_verify_action_current_user_manually" = "التحقق يدويًا عن طريق النص";
|
||||
"secrets_recovery_reset_action_part_1" = "هل نسيت أو فقدت كافة خيارات الاسترداد؟ ";
|
||||
"secrets_recovery_with_passphrase_passphrase_title" = "دخول";
|
||||
"room_intro_cell_information_dm_sentence1_part3" = ". ";
|
||||
"room_intro_cell_information_multiple_dm_sentence2" = "أنت وحدك من يشارك في هذه المحادثة، ما لم يقم أي منكم بدعوة شخص ما للانضمام.";
|
||||
"room_invite_to_room_option_title" = "إلى هذه الغرفة فقط";
|
||||
"spaces_explore_rooms_one_room" = "غرفة واحدة";
|
||||
"space_settings_access_section" = "من يمكنه الوصول إلى هذه المساحة؟";
|
||||
"spaces_creation_hint" = "المساحات هي طريقة جديدة لتجميع الغرف والأشخاص.";
|
||||
"spaces_creation_visibility_title" = "ما نوع المساحة التي تريد إنشاءها؟";
|
||||
"spaces_subspace_creation_visibility_title" = "ما نوع المساحة الفرعية التي تريد إنشاءها؟";
|
||||
"spaces_creation_address" = "عنوان";
|
||||
"space_beta_announce_title" = "المساحات قادمة قريبا";
|
||||
"user_verification_sessions_list_session_untrusted" = "غير موثوق به";
|
||||
"secrets_recovery_with_passphrase_recover_action" = "استخدم العبارة";
|
||||
"biometrics_cant_unlocked_alert_title" = "لا يمكن فتح التطبيق";
|
||||
"create_room_section_footer_type_public" = "يمكن فقط للأشخاص المدعوين العثور على المساحة والانضمام إليها، وليس فقط الأشخاص الموجودين في اسم المساحة.";
|
||||
"space_beta_announce_subtitle" = "النسخة الجديدة من المجتمعات";
|
||||
"user_session_verification_unknown" = "حالة التحقق غير معروفة";
|
||||
"user_session_overview_session_title" = "جلسة";
|
||||
"wysiwyg_composer_start_action_location" = "موقع";
|
||||
"user_session_details_last_activity" = "آخر نشاط";
|
||||
"spaces_creation_sharing_type_me_and_teammates_detail" = "مساحة خاصة لك ولزملائك في الفريق";
|
||||
"user_session_details_device_os" = "نظام التشغيل";
|
||||
"spaces_creation_private_space_title" = "مساحتك الخاصة";
|
||||
"wysiwyg_composer_start_action_polls" = "استطلاعات الرأي";
|
||||
"wysiwyg_composer_format_action_unordered_list" = "تبديل القائمة النقطية";
|
||||
"wysiwyg_composer_format_action_indent" = "زيادة المسافة البادئة";
|
||||
"wysiwyg_composer_format_action_un_indent" = "تقليل المسافة البادئة";
|
||||
"spaces_creation_address_default_message" = "ستكون مساحتك متاحة للعرض في\n%@";
|
||||
"spaces_creation_new_rooms_general" = "عام";
|
||||
"notice_display_name_changed_to" = "%@ غيّر اسم العرض الخاص به إلى %@";
|
||||
"network_offline_prompt" = "يبدو أنه غير متصل بالانترنت.";
|
||||
"side_menu_action_invite_friends" = "دعوة الأصدقاء";
|
||||
"spaces_creation_post_process_creating_space" = "إنشاء مساحة";
|
||||
"user_session_unverified_additional_info" = "قم بالتحقق من جلستك الحالية للحصول على مراسلة آمنة معززة.";
|
||||
"user_session_unverified_session_description" = "الجلسات غير المُتحققة هي الجلسات التي تم تسجيل الدخول إليها باستخدام بيانات اعتمادك ولكن لم يتم التحقق منها.\n\nيجب عليك التأكد بشكل خاص من التعرف على هذه الجلسات، فقد تُمثل استخدامًا غير مُصرّح به لحسابك.";
|
||||
"user_other_session_menu_select_sessions" = "اختيار الجلسات";
|
||||
"poll_timeline_total_votes_not_voted" = "تم الإدلاء بـ %lu من الأصوات. صوّت لرؤية النتائج";
|
||||
"user_session_permanently_unverified_session_description" = "هذه الجلسة لا تدعم التشفير، لذا لا يمكن التحقق منها.\n\nلن تتمكن من المشاركة في الغرف التي يُفعّل فيها التشفير عند استخدام هذه الجلسة.\n\nلأعلى مستوى من الأمان والخصوصية، يُنصح باستخدام عملاء Matrix الذين يدعمون التشفير.";
|
||||
"user_session_verified_session_description" = "الجلسات المُتحققة موجودة في أي مكان تستخدم فيه Element بعد إدخال كلمة المرور أو تأكيد هويتك بجلسة مُتحققة أخرى.\n\nهذا يعني أن لديك جميع المفاتيح اللازمة لفتح رسائلك المُشفرة وتأكيد ثقتك بهذه الجلسة للمستخدمين الآخرين.";
|
||||
"device_name_desktop" = "%@ سطح المكتب";
|
||||
"user_sessions_overview_current_session_section_title" = "الجلسة الحالية";
|
||||
"user_sessions_view_all_action" = "عرض الكل (%d)";
|
||||
"user_session_verify_action" = "التحقق من الجلسة";
|
||||
"user_session_view_details" = "عرض التفاصيل";
|
||||
"user_session_details_title" = "تفاصيل الجلسة";
|
||||
"user_session_inactive_session_title" = "الجلسات غير النشطة";
|
||||
"device_type_name_web" = "الويب";
|
||||
"wysiwyg_composer_start_action_camera" = "كاميرا";
|
||||
"wysiwyg_composer_start_action_voice_broadcast" = "البث الصوتي";
|
||||
"wysiwyg_composer_format_action_code_block" = "مكون كود التبديل";
|
||||
"user_other_session_no_verified_sessions" = "لم يتم العثور على جلسات تم التحقق منها.";
|
||||
"user_inactive_session_item" = "غير نشط لمدة 90 يومًا أو أكثر";
|
||||
"wysiwyg_composer_format_action_quote" = "اقتباس التبديل";
|
||||
"wysiwyg_composer_link_action_edit_title" = "تعديل الرابط";
|
||||
"key_backup_setup_passphrase_set_passphrase_action" = "تعيين عبارة";
|
||||
"user_session_unverified_session_title" = "جلسة غير مُتحققة";
|
||||
"device_name_web" = "%@ ويب";
|
||||
"user_session_verification_unknown_short" = "غير معروف";
|
||||
"message_reply_to_sender_sent_their_live_location" = "الموقع المباشر";
|
||||
"spaces_creation_add_rooms_message" = "بما أن هذه المساحة مخصصة لك فقط، فلن يتم إعلام أحد. يمكنك إضافة المزيد لاحقًا.";
|
||||
"spaces_creation_post_process_creating_space_task" = "إنشاء %@";
|
||||
"spaces_creation_post_process_uploading_avatar" = "تحميل الصورة الرمزية";
|
||||
"spaces_creation_in_spacename_plus_many" = "في مساحات %@ + %@";
|
||||
"voice_message_stop_locked_mode_recording" = "اضغط على التسجيل الخاص بك لإيقافه أو الاستماع إليه";
|
||||
"poll_edit_form_option_number" = "الخيار %lu";
|
||||
"poll_timeline_total_votes" = "%lu الأصوات المدلى بها";
|
||||
"location_sharing_live_timer_incoming" = "مباشر حتى %@";
|
||||
"user_sessions_overview_link_device" = "ربط جهاز";
|
||||
"user_other_session_permanently_unverified_additional_info" = "هذه الجلسة لا تدعم التشفير وبالتالي لا يمكن التحقق منها.";
|
||||
"user_other_session_verified_additional_info" = "هذه الجلسة جاهزة للمراسلة الآمنة.";
|
||||
"user_session_push_notifications_message" = "عند تشغيلها، ستتلقى هذه الجلسة إشعارات فورية.";
|
||||
"user_session_details_device_browser" = "المتصفح";
|
||||
"user_session_details_application_url" = "عنوان URL";
|
||||
"wysiwyg_composer_action_maximise_action" = "توسيع الملحن";
|
||||
"wysiwyg_composer_format_action_bold" = "تطبيق تنسيق غامق";
|
||||
"wysiwyg_composer_format_action_italic" = "تطبيق التنسيق المائل";
|
||||
"wysiwyg_composer_format_action_link" = "تطبيق تنسيق الرابط";
|
||||
"wysiwyg_composer_link_action_link" = "وصلة";
|
||||
"device_type_name_unknown" = "غير معروف";
|
||||
"user_other_session_verified_sessions_header_subtitle" = "للحصول على أفضل مستوى من الأمان، قم بتسجيل الخروج من أي جلسة لا تعرفها أو لا تستخدمها بعد الآن.";
|
||||
"device_type_name_desktop" = "سطح المكتب";
|
||||
"wysiwyg_composer_link_action_create_title" = "إنشاء رابط";
|
||||
"deselect_all" = "إلغاء تحديد الكل";
|
||||
"ignore_user" = "تجاهل المستخدم";
|
||||
"device_verification_emoji_train" = "يدرب";
|
||||
"spaces_creation_address_invalid_characters" = "%@\nيحتوي على أحرف غير صالحة";
|
||||
"spaces_creation_new_rooms_message" = "سننشئ غرفة لكل واحد منهم.";
|
||||
"spaces_creation_new_rooms_random" = "عشوائي";
|
||||
"spaces_add_room_missing_permission_message" = "ليس لديك الأذونات اللازمة لإضافة غرف إلى هذه المساحة.";
|
||||
"side_menu_reveal_action_accessibility_label" = "اللوحة اليسرى";
|
||||
"voice_message_release_to_send" = "اضغط باستمرار للتسجيل، ثم حرر للإرسال";
|
||||
"leave_space_and_more_rooms" = "اترك مساحة و %@غرف";
|
||||
"user_session_learn_more" = "معرفة المزيد";
|
||||
"wysiwyg_composer_action_minimise_action" = "ملحن الانكماش";
|
||||
"user_session_rename_session_description" = "يستطيع المستخدمون الآخرون في الرسائل المباشرة والغرف التي تنضم إليها عرض قائمة كاملة بجلساتك.\n\nهذا يمنحهم الثقة بأنهم يتحدثون إليك حقًا، ويعني أيضًا أنهم يستطيعون رؤية اسم الجلسة التي تُدخلها هنا.";
|
||||
"user_other_session_filter_menu_verified" = "تم التحقق";
|
||||
"user_other_session_no_inactive_sessions" = "لم يتم العثور على جلسات غير نشطة.";
|
||||
"device_verification_emoji_hat" = "قبعة";
|
||||
"space_beta_announce_badge" = "بيتا (تجريبي)";
|
||||
"spaces_creation_new_rooms_title" = "ما هي بعض المناقشات التي ستجريها؟";
|
||||
"spaces_creation_invite_by_username_title" = "ادعُ فريقك";
|
||||
"spaces_creation_post_process_inviting_users" = "دعوة %@ المستخدمين";
|
||||
"leave_space_action" = "غادر المساحة";
|
||||
"leave_space_selection_all_rooms" = "حدد جميع الغرف";
|
||||
"space_avatar_view_accessibility_hint" = "تغيير الصورة الرمزية للمساحة";
|
||||
"leave_space_selection_title" = "تحديد الغرف";
|
||||
"side_menu_action_settings" = "إعدادات";
|
||||
"side_menu_coach_message" = "مرر لليمين أو انقر لرؤية جميع الغرف";
|
||||
"voice_message_broadcast_in_progress_title" = "لا يمكن بدء الرسالة الصوتية";
|
||||
"voice_message_broadcast_in_progress_message" = "لا يمكنك بدء رسالة صوتية لأنك تُسجِّل بثًا مباشرًا. يُرجى إنهاء البث المباشر لبدء تسجيل رسالة صوتية";
|
||||
"voice_broadcast_unauthorized_title" = "لا يمكن بدء بث صوتي جديد";
|
||||
"user_session_inactive_session_description" = "الجلسات غير النشطة هي جلسات لم تستخدمها منذ فترة، ولكنها تستمر في تلقي مفاتيح التشفير.\n\nيؤدي حذف الجلسات غير النشطة إلى تحسين الأمان والأداء، ويسهّل عليك تحديد ما إذا كانت الجلسة الجديدة مشبوهة.";
|
||||
"user_other_session_unverified_sessions_header_subtitle" = "قم بالتحقق من جلساتك للحصول على رسائل آمنة معززة أو قم بتسجيل الخروج من الجلسات التي لا تعرفها أو لا تستخدمها بعد الآن.";
|
||||
"user_session_name" = "%@: %@";
|
||||
"user_other_session_filter_menu_unverified" = "غير مُتحقق";
|
||||
"user_session_details_session_section_footer" = "انسخ أي بيانات عن طريق النقر عليها مع الاستمرار في الضغط عليها.";
|
||||
"user_session_details_device_ip_location" = "موقع IP";
|
||||
"user_inactive_session_item_with_date" = "غير نشط لمدة 90 يومًا أو أكثر (%@)";
|
||||
"user_session_overview_session_details_button_title" = "تفاصيل الجلسة";
|
||||
"wysiwyg_composer_start_action_media_picker" = "مكتبة الصور";
|
||||
"user_session_unverified_short" = "غير مُتحقق";
|
||||
"wysiwyg_composer_format_action_underline" = "تطبيق تنسيق التسطير";
|
||||
"spaces_creation_empty_room_name_error" = "الاسم مطلوب";
|
||||
"room_event_encryption_info_key_authenticity_not_guaranteed" = "لا يمكن ضمان صحة هذه الرسالة المشفرة على هذا الجهاز.";
|
||||
"spaces_creation_sharing_type_me_and_teammates_title" = "أنا وزملائي في الفريق";
|
||||
"spaces_creation_invite_by_username" = "دعوة عن طريق اسم المستخدم";
|
||||
"spaces_creation_in_spacename_plus_one" = "في %@ + 1 مساحة";
|
||||
"side_menu_action_help" = "مساعدة";
|
||||
"user_session_push_notifications" = "إشعارات الدفع";
|
||||
"user_other_session_filter_menu_all" = "جميع الجلسات";
|
||||
"user_other_session_filter_menu_inactive" = "غير نشط";
|
||||
"user_session_details_application_section_header" = "تطبيق";
|
||||
"user_session_details_session_id" = "معرف الجلسة";
|
||||
"wysiwyg_composer_start_action_attachments" = "المرفقات";
|
||||
"wysiwyg_composer_format_action_ordered_list" = "تبديل القائمة المرقمة";
|
||||
"device_verification_emoji_trumpet" = "بوق";
|
||||
"key_verification_tile_request_incoming_approval_decline" = "رفض";
|
||||
"spaces_creation_address_already_exists" = "%@\nموجود بالفعل";
|
||||
"spaces_creation_email_invites_email_title" = "بريد إلكتروني";
|
||||
"spaces_creation_sharing_type_just_me_title" = "أنا فقط";
|
||||
"spaces_creation_sharing_type_just_me_detail" = "مساحة خاصة لتنظيم غرفك";
|
||||
"spaces_creation_in_many_spaces" = "في %@ مساحات";
|
||||
"key_backup_recover_from_recovery_key_recovery_key_title" = "دخول";
|
||||
"device_verification_emoji_thumbs up" = "ممتاز";
|
||||
"spaces_creation_cancel_title" = "توقف عن إنشاء مساحة؟";
|
||||
"spaces_creation_cancel_message" = "سيتم فقدان تقدمك.";
|
||||
"spaces_creation_new_rooms_support" = "دعم";
|
||||
"spaces_creation_email_invites_title" = "ادعُ فريقك";
|
||||
"leave_space_selection_no_rooms" = "عدم تحديد الغرف";
|
||||
"space_avatar_view_accessibility_label" = "الصورة الرمزية";
|
||||
"user_session_verified" = "جلسة تم التحقق منها";
|
||||
"wysiwyg_composer_start_action_text_formatting" = "تنسيق النص";
|
||||
"wysiwyg_composer_format_action_inline_code" = "تطبيق تنسيق الكود المضمن";
|
||||
"wysiwyg_composer_link_action_text" = "نص";
|
||||
"service_terms_modal_policy_checkbox_accessibility_hint" = "حدد لقبول %@";
|
||||
"user_avatar_view_accessibility_label" = "الصورة الرمزية";
|
||||
"spaces_creation_public_space_title" = "مساحتك العامة";
|
||||
"spaces_creation_email_invites_message" = "ويمكنك دعوتهم لاحقًا أيضًا.";
|
||||
"poll_timeline_reply_ended_poll" = "انتهى الاستطلاع";
|
||||
"user_session_verified_additional_info" = "جلستك الحالية جاهزة للمراسلة الآمنة.";
|
||||
"user_session_verification_unknown_additional_info" = "قم بالتحقق من جلستك الحالية للكشف عن حالة التحقق الخاصة بهذه الجلسة.";
|
||||
"user_session_rename_session_title" = "إعادة تسمية الجلسات";
|
||||
"user_session_item_details" = "%1$@ · %2$@";
|
||||
"user_session_details_session_name" = "اسم الجلسة";
|
||||
"user_session_details_application_name" = "اسم";
|
||||
"user_other_session_selected_count" = "%@ تم اختياره";
|
||||
"wysiwyg_composer_format_action_strikethrough" = "تطبيق تنسيق الشطب";
|
||||
"spaces_creation_invite_by_username_message" = "ويمكنك دعوتهم لاحقًا أيضًا.";
|
||||
"voice_message_remaining_recording_time" = "%@s متبقية";
|
||||
"spaces_creation_sharing_type_title" = "مع من تعمل؟";
|
||||
"side_menu_action_feedback" = "تعليق";
|
||||
"user_session_unverified" = "جلسة غير مُتحققة";
|
||||
"user_other_session_security_recommendation_title" = "جلسات أخرى";
|
||||
"user_session_details_application_version" = "إصدار";
|
||||
"key_backup_recover_from_passphrase_passphrase_title" = "دخول";
|
||||
"device_verification_emoji_santa" = "سانتا";
|
||||
"major_update_title" = "الشغب الآن %@";
|
||||
"home_context_menu_unmute" = "إزالة الكتم";
|
||||
"spaces_creation_new_rooms_room_name_title" = "اسم الغرفة";
|
||||
"spaces_creation_sharing_type_message" = "تأكد من أن الأشخاص المناسبين لديهم حق الوصول %@. يمكنك تغيير هذا لاحقًا.";
|
||||
"spaces_creation_add_rooms_title" = "ماذا تريد أن تضيف؟";
|
||||
"spaces_creation_post_process_creating_room" = "إنشاء %@";
|
||||
"spaces_creation_post_process_adding_rooms" = "إضافة %@ غرف";
|
||||
"spaces_creation_in_one_space" = "في مساحة واحدة";
|
||||
"voice_message_lock_screen_placeholder" = "رسالة صوتية";
|
||||
"user_session_verified_short" = "تم التحقق";
|
||||
"user_other_session_unverified_additional_info" = "قم بالتحقق من هذه الجلسة أو تسجيل الخروج منها للحصول على أفضل مستوى من الأمان والموثوقية.";
|
||||
"user_other_session_current_session_details" = "جلستك الحالية";
|
||||
"user_other_session_filter" = "عامل التصفية";
|
||||
"user_other_session_no_unverified_sessions" = "لم يتم العثور على جلسات غير موثقة.";
|
||||
"user_other_session_clear_filter" = "مسح عامل التصفية";
|
||||
"user_other_session_menu_sign_out_sessions" = "تسجيل الخروج من جلسات %@";
|
||||
"user_session_item_details_last_activity" = "آخر نشاط %@";
|
||||
"user_session_details_device_section_header" = "جهاز";
|
||||
"user_session_details_device_ip_address" = "عنوان IP";
|
||||
"spaces_coming_soon_title" = "قادم قريباً";
|
||||
"leave_space_and_one_room" = "اترك مساحة وغرفة واحدة";
|
||||
"room_widget_permission_theme_permission" = "موضوعك";
|
||||
"user_avatar_view_accessibility_hint" = "تغيير صورة المستخدم الرمزية";
|
||||
"user_session_details_session_section_header" = "جلسة";
|
||||
"user_session_overview_current_session_title" = "الجلسة الحالية";
|
||||
"wysiwyg_composer_start_action_stickers" = "ملصقات";
|
||||
"user_session_got_it" = "فهمتها";
|
||||
"user_session_verified_session_title" = "الجلسات التي تم التحقق منها";
|
||||
"user_session_details_device_model" = "نموذج";
|
||||
"device_name_unknown" = "عميل غير معروف";
|
||||
"device_type_name_mobile" = "جوال";
|
||||
|
||||
@@ -479,6 +479,7 @@ Tap the + to start adding people.";
|
||||
"room_participants_invite_malformed_id" = "Malformed ID. Should be an email address or a Matrix ID like '@localpart:domain'";
|
||||
"room_participants_invited_section" = "INVITED";
|
||||
"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "No identity server is configured so you cannot start a chat with a contact using an email.";
|
||||
"room_participants_leave_not_allowed_for_last_owner_msg" = "You can't leave the room since you're the only owner of it.";
|
||||
|
||||
"room_participants_online" = "Online";
|
||||
"room_participants_offline" = "Offline";
|
||||
@@ -519,10 +520,12 @@ Tap the + to start adding people.";
|
||||
"room_participants_security_information_room_encrypted" = "Messages in this room are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them.";
|
||||
"room_participants_security_information_room_encrypted_for_dm" = "Messages here are end-to-end encrypted.\n\nYour messages are secured with locks and only you and the recipient have the unique keys to unlock them.";
|
||||
|
||||
"room_member_power_level_owner_in" = "Owner in %@";
|
||||
"room_member_power_level_admin_in" = "Admin in %@";
|
||||
"room_member_power_level_moderator_in" = "Moderator in %@";
|
||||
"room_member_power_level_custom_in" = "Custom (%@) in %@";
|
||||
|
||||
"room_member_power_level_short_owner" = "Owner";
|
||||
"room_member_power_level_short_admin" = "Admin";
|
||||
"room_member_power_level_short_moderator" = "Mod";
|
||||
"room_member_power_level_short_custom" = "Custom";
|
||||
|
||||
@@ -2735,3 +2735,5 @@
|
||||
|
||||
// MARK: Sunset
|
||||
"sunset_delegated_oidc_registration_not_supported_title" = "Selle rakendusega enam ei saa luua kasutajakontot teenuses %1$@";
|
||||
"room_member_power_level_owner_in" = "„%@“ jututoa omanik";
|
||||
"room_member_power_level_short_owner" = "Omanik";
|
||||
|
||||
@@ -2990,3 +2990,5 @@
|
||||
// MARK: Sunset
|
||||
"sunset_delegated_oidc_registration_not_supported_title" = "Anda sudah tidak bisa lagi membuat akun dengan %1$@ menggunakan aplikasi ini";
|
||||
"sunset_delegated_oidc_registration_not_supported_generic_error" = "Anda sudah tidak bisa lagi membuat akun dengan homeserver yang ditentukan menggunakan aplikasi ini";
|
||||
"room_member_power_level_owner_in" = "Pemilik dalam %@";
|
||||
"room_member_power_level_short_owner" = "Pemilik";
|
||||
|
||||
@@ -121,3 +121,4 @@
|
||||
|
||||
/* New voice broadcast from a specific person, not referencing a room. */
|
||||
"VOICE_BROADCAST_FROM_USER" = "%@ ha iniziato una trasmissione vocale";
|
||||
"UNSUPPORTED_CALL" = "Chiamata non supportata";
|
||||
|
||||
@@ -2754,3 +2754,10 @@
|
||||
"wysiwyg_composer_action_maximise_action" = "Espandi il compositore";
|
||||
"room_action_report" = "Segnala stanza";
|
||||
"room_action_report_prompt_reason" = "Motivo della segnalazione della stanza";
|
||||
"call_unsupported_matrix_rtc_call" = "Chiamata non supportata. Per unirsi a questa chiamata è necessaria la nuova app Element X.";
|
||||
"sunset_delegated_oidc_registration_not_supported_title" = "Non puoi più creare un account con %1$@ usando quest'app";
|
||||
"sunset_delegated_oidc_registration_not_supported_message" = "Scarica %1$@ per utilizzare %2$@ per il tuo account o scegli un homeserver differente.";
|
||||
"sunset_download_banner_title" = "Scarica %1$@";
|
||||
"sunset_download_banner_message" = "Più veloce, più sicura, e piena di potenti strumenti di collaborazione.";
|
||||
"sunset_download_banner_learn_more" = "Per saperne di più";
|
||||
"sunset_delegated_oidc_registration_not_supported_generic_error" = "Non puoi più creare un account con l'homeserver indicato usando quest'app";
|
||||
|
||||
@@ -3,3 +3,4 @@
|
||||
"NSPhotoLibraryUsageDescription" = "Foto bibliotēka tiek izmantota, lai nosūtītu fotoattēlus un video.";
|
||||
"NSMicrophoneUsageDescription" = "Mikrofons tiek izmantots, lai uzņemtu video un veiktu zvanus.";
|
||||
"NSContactsUsageDescription" = "Kontaktu grāmata tiek izmantota, lai meklētu lietotājus pēc epasta adreses vai telefona numura Riot aplikācijā.";
|
||||
"NSFaceIDUsageDescription" = "Face ID tiek izmantots, lai piekļūtu lietotnei.";
|
||||
|
||||
@@ -118,3 +118,5 @@
|
||||
|
||||
/* New file message from a specific person, not referencing a room. */
|
||||
"LOCATION_FROM_USER" = "%@ compartilhou a localização dela(e)";
|
||||
"VOICE_BROADCAST_FROM_USER" = "%@ iniciou uma transmissão de voz";
|
||||
"UNSUPPORTED_CALL" = "Chamada não suportada";
|
||||
|
||||
@@ -2556,8 +2556,8 @@
|
||||
"authentication_qr_login_start_subtitle" = "Use a câmera neste dispositivo para scannar o QR code mostrado em seu outro dispositivo:";
|
||||
"authentication_qr_login_start_title" = "Scannar QR code";
|
||||
"authentication_login_with_qr" = "Fazer signin com QR code";
|
||||
"wysiwyg_composer_format_action_underline" = "Aplicar formato sublinhar";
|
||||
"wysiwyg_composer_format_action_strikethrough" = "Aplicar formato tachar";
|
||||
"wysiwyg_composer_format_action_underline" = "Aplicar formato de sublinhado";
|
||||
"wysiwyg_composer_format_action_strikethrough" = "Aplicar formato tachado";
|
||||
"wysiwyg_composer_format_action_italic" = "Aplicar formato itálico";
|
||||
|
||||
// Formatting Actions
|
||||
@@ -2671,3 +2671,77 @@
|
||||
"room_command_join_room_description" = "Entra na sala com o endereço fornecido";
|
||||
"room_command_invite_user_description" = "Convida o usuário com o ID fornecido para a sala atual";
|
||||
"authentication_qr_login_failure_device_not_supported" = "Vincular com este dispositivo não é suportado.";
|
||||
"key_verification_scan_qr_code_information_other_device" = "Aponte sua câmera para o código QR exibido em seu outro dispositivo para verificar esta sessão";
|
||||
"wysiwyg_composer_action_minimise_action" = "Compositor psiquiatra";
|
||||
"pill_message" = "Mensagem";
|
||||
"sunset_delegated_oidc_registration_not_supported_title" = "Você não pode mais criar uma conta com %1$@ usando este aplicativo";
|
||||
"sunset_delegated_oidc_registration_not_supported_message" = "Baixe %1$@ para usar %2$@ na sua conta ou escolha um servidor doméstico diferente.";
|
||||
"sunset_delegated_oidc_registration_not_supported_generic_error" = "Você não pode mais criar uma conta com o servidor doméstico inserido usando este aplicativo";
|
||||
"sunset_download_banner_title" = "Baixar %1$@";
|
||||
"sunset_download_banner_message" = "Mais rápido, mais seguro e repleto de poderosas ferramentas de colaboração.";
|
||||
"sunset_download_banner_learn_more" = "Saber mais";
|
||||
"call_unsupported_matrix_rtc_call" = "Chamada não suportada. O novo aplicativo Element X é necessário para participar desta chamada.";
|
||||
"voice_broadcast_voip_cannot_start_description" = "Você não pode iniciar uma chamada porque está gravando uma transmissão ao vivo. Encerre a transmissão ao vivo para iniciar a chamada.";
|
||||
"poll_timeline_decryption_error" = "Devido a erros de descriptografia, alguns votos podem não ser contados";
|
||||
"wysiwyg_composer_action_maximise_action" = "Expandir compositor";
|
||||
"room_command_change_room_topic_description" = "Define o tema da sala";
|
||||
"room_action_report" = "Sala de relatórios";
|
||||
"room_action_report_prompt_reason" = "Motivo da denúncia desta sala";
|
||||
"room_command_discard_session_description" = "Força o descarte da sessão de grupo de saída atual em uma sala criptografada";
|
||||
"room_command_error_unknown_command" = "Comando inválido ou não tratado";
|
||||
"pill_room_fallback_display_name" = "Espaço/Sala";
|
||||
"device_verification_self_verify_wait_recover_secrets_additional_help" = "Não consegue acessar uma sessão %@ existente?";
|
||||
"room_waiting_other_participants_title" = "Aguardando a adesão dos usuários %@";
|
||||
"voice_broadcast_playback_lock_screen_placeholder" = "Transmissão de voz";
|
||||
"device_verification_self_verify_open_on_other_device_title" = "Abra %@ no seu outro dispositivo";
|
||||
"key_verification_scan_qr_code_information_other_session" = "Aponte sua câmera para o código QR exibido em seu outro dispositivo para verificar sua sessão";
|
||||
"voice_message_broadcast_in_progress_title" = "Não é possível iniciar a mensagem de voz";
|
||||
"voice_message_broadcast_in_progress_message" = "Você não pode iniciar uma mensagem de voz, pois está gravando uma transmissão ao vivo. Encerre a transmissão ao vivo para iniciar a gravação da mensagem de voz.";
|
||||
"notice_display_name_changed_to" = "%@ mudou seu nome de exibição para %@";
|
||||
"pill_message_from" = "Mensagem de %@";
|
||||
"poll_timeline_loading" = "Carregando...";
|
||||
"wysiwyg_composer_format_action_un_indent" = "Diminuir recuo";
|
||||
"wysiwyg_composer_format_action_indent" = "Aumentar o recuo";
|
||||
"room_details_polls" = "Histórico de pesquisas";
|
||||
"poll_history_no_active_poll_text" = "Não há enquetes ativas nesta sala";
|
||||
"poll_history_fetching_error" = "Erro ao buscar enquetes.";
|
||||
"wysiwyg_composer_format_action_code_block" = "Alternar bloco de código";
|
||||
"poll_history_detail_view_in_timeline" = "Ver enquete na linha do tempo";
|
||||
"settings_acceptable_use" = "Política de Uso Aceitável";
|
||||
"launch_loading_generic" = "Sincronizando suas conversas";
|
||||
"launch_loading_delay_warning" = "Isso pode demorar um pouco mais.\nObrigado pela sua paciência.";
|
||||
"poll_history_no_past_poll_text" = "Não há pesquisas anteriores nesta sala";
|
||||
"poll_timeline_ended_text" = "Terminou a enquete";
|
||||
"home_context_menu_mark_as_unread" = "Marcar como não lido";
|
||||
"poll_history_title" = "Histórico de pesquisas";
|
||||
"poll_history_active_segment_title" = "Pesquisas ativas";
|
||||
"wysiwyg_composer_format_action_unordered_list" = "Alternar lista com marcadores";
|
||||
"voice_broadcast_recorder_connection_error" = "Erro de conexão - Gravação pausada";
|
||||
"wysiwyg_composer_format_action_quote" = "Alternar citação";
|
||||
"manage_session_redirect" = "Você será redirecionado ao provedor de autenticação do seu servidor para concluir o logout.";
|
||||
"manage_session_redirect_error" = "Funcionalidade indisponível no momento. Entre em contato com o administrador do seu servidor doméstico.";
|
||||
"room_command_reset_user_power_level_description" = "Usuário Deops com ID fornecido";
|
||||
"settings_push_rules_error" = "Ocorreu um erro ao atualizar suas preferências de notificação. Tente alternar sua opção novamente.";
|
||||
"key_verification_scan_qr_code_title" = "Escaneie o código QR";
|
||||
"key_verification_scan_qr_code_information_other_user" = "Aponte sua câmera para o código QR exibido no dispositivo para verificar a sessão";
|
||||
"key_verification_scan_qr_code_information_new_session" = "Aponte sua câmera para o código QR exibido em seu outro dispositivo para verificar sua nova sessão";
|
||||
"voice_broadcast_connection_error_title" = "Erro de conexão";
|
||||
"voice_broadcast_connection_error_message" = "Infelizmente, não podemos iniciar a gravação no momento. Tente novamente mais tarde.";
|
||||
"voice_broadcast_playback_unable_to_decrypt" = "Não é possível decifrar esta transmissão de voz.";
|
||||
"poll_history_past_segment_title" = "Pesquisas anteriores";
|
||||
"poll_history_load_more" = "Carregar mais enquetes";
|
||||
"poll_timeline_reply_ended_poll" = "Enquete encerrada";
|
||||
"wysiwyg_composer_format_action_ordered_list" = "Alternar lista numerada";
|
||||
"key_backup_recover_from_private_key_progress" = "%@%% Concluído";
|
||||
"pill_message_in" = "Mensagem em %@";
|
||||
"poll_history_loading_text" = "Exibindo enquetes";
|
||||
"poll_history_no_active_poll_period_text" = "Não há enquetes ativas nos últimos %@ dias. Carregue mais enquetes para ver as enquetes dos meses anteriores.";
|
||||
"poll_history_no_past_poll_period_text" = "Não há enquetes anteriores nos últimos %@ dias. Carregue mais enquetes para ver as enquetes dos meses anteriores.";
|
||||
"settings_manage_account_title" = "Conta";
|
||||
"settings_manage_account_action" = "Gerenciar conta";
|
||||
"settings_manage_account_description" = "Gerencie sua conta em %@";
|
||||
"key_verification_self_verify_security_upgrade_alert_title" = "Aplicativo atualizado";
|
||||
"key_verification_self_verify_security_upgrade_alert_message" = "A segurança das mensagens foi aprimorada com a atualização mais recente. Verifique novamente o seu dispositivo.";
|
||||
"device_verification_self_verify_open_on_other_device_information" = "Você precisa verificar esta sessão para ler seu histórico de mensagens seguras.\n\nAbra o Element em um dos seus outros dispositivos e siga as instruções.";
|
||||
"voice_broadcast_voip_cannot_start_title" = "Não é possível iniciar uma chamada";
|
||||
"room_waiting_other_participants_message" = "Depois que os usuários convidados se juntarem a %@, você poderá bater papo e a sala será criptografada de ponta a ponta";
|
||||
|
||||
@@ -2124,7 +2124,7 @@
|
||||
"onboarding_use_case_existing_server_message" = "Хотите присоединиться к существующему серверу?";
|
||||
"onboarding_use_case_skip_button" = "Пропустить вопрос";
|
||||
/* The placeholder string contains onboarding_use_case_skip_button as a tappable action */
|
||||
"onboarding_use_case_not_sure_yet" = "Ещё не уверенны? %@";
|
||||
"onboarding_use_case_not_sure_yet" = "Ещё не уверены? %@";
|
||||
"onboarding_use_case_community_messaging" = "Сообщества";
|
||||
"onboarding_use_case_work_messaging" = "Команды";
|
||||
"onboarding_use_case_personal_messaging" = "Друзья и семья";
|
||||
|
||||
1
Riot/Assets/uz.lproj/Localizable.strings
Normal file
1
Riot/Assets/uz.lproj/Localizable.strings
Normal file
@@ -0,0 +1 @@
|
||||
|
||||
1
Riot/Assets/uz.lproj/Vector.strings
Normal file
1
Riot/Assets/uz.lproj/Vector.strings
Normal file
@@ -0,0 +1 @@
|
||||
"store_short_description" = "Xavfsiz markazlashmagan chat/VoIP";
|
||||
@@ -1,5 +1,5 @@
|
||||
// Permissions usage explanations
|
||||
"NSCameraUsageDescription" = "Máy ảnh được sử dụng để chụp ảnh và quay phim, thực hiện các cuộc gọi video.";
|
||||
"NSCameraUsageDescription" = "Máy ảnh được dùng để gọi truyền hình hoặc quay phim, chụp ảnh.";
|
||||
"NSPhotoLibraryUsageDescription" = "Thư viện ảnh được dùng để gửi hình ảnh và videos.";
|
||||
"NSMicrophoneUsageDescription" = "Element cần quyền truy cập vào mi-crô của bạn để nhận và thực hiện cuộc gọi, quay video, và ghi âm các tin nhắn thoại.";
|
||||
"NSContactsUsageDescription" = "Element sẽ hiển thị danh bạ của bạn để bạn có thể mời họ trò chuyện.";
|
||||
|
||||
@@ -38,17 +38,17 @@
|
||||
/* Incoming one-to-one video call */
|
||||
"VIDEO_CALL_FROM_USER" = "Gọi video từ %@";
|
||||
/* Incoming unnamed voice conference invite from a specific person */
|
||||
"VOICE_CONF_FROM_USER" = "Gọi nhóm từ %@";
|
||||
"VOICE_CONF_FROM_USER" = "Cuộc gọi nhóm từ %@";
|
||||
/* Incoming unnamed video conference invite from a specific person */
|
||||
"VIDEO_CONF_FROM_USER" = "Gọi video nhóm từ %@";
|
||||
"VIDEO_CONF_FROM_USER" = "Cuộc gọi truyền hình nhóm từ %@";
|
||||
/* Incoming named voice conference invite from a specific person */
|
||||
"VOICE_CONF_NAMED_FROM_USER" = "Gọi nhóm từ %@: '%@'";
|
||||
"VOICE_CONF_NAMED_FROM_USER" = "Cuộc gọi nhóm từ %@: '%@'";
|
||||
/* Incoming named video conference invite from a specific person */
|
||||
"VIDEO_CONF_NAMED_FROM_USER" = "Gọi video nhóm từ %@: '%@'";
|
||||
"VIDEO_CONF_NAMED_FROM_USER" = "Cuộc gọi video nhóm từ %@: '%@'";
|
||||
|
||||
/** Key verification **/
|
||||
|
||||
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ muốn xác minh";
|
||||
"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ muốn xác thực";
|
||||
|
||||
/* Group call from user, CallKit caller name */
|
||||
"GROUP_CALL_FROM_USER" = "%@ (cuộc gọi nhóm)";
|
||||
@@ -60,7 +60,7 @@
|
||||
"USER_MEMBERSHIP_UPDATED" = "%@ đã cập nhật hồ sơ";
|
||||
|
||||
/* A user has change their avatar */
|
||||
"USER_UPDATED_AVATAR" = "%@ đã đổi avatar";
|
||||
"USER_UPDATED_AVATAR" = "%@ đã đổi ảnh đại diện";
|
||||
|
||||
/* A user has change their name to a new name which we don't know */
|
||||
"GENERIC_USER_UPDATED_DISPLAYNAME" = "%@ đã đổi tên";
|
||||
@@ -71,7 +71,7 @@
|
||||
"USER_UPDATED_DISPLAYNAME" = "%@ đã đổi tên sang %@";
|
||||
|
||||
/* A user has reacted to a message, but the reaction content is unknown */
|
||||
"GENERIC_REACTION_FROM_USER" = "%@ đã gửi một tương tác";
|
||||
"GENERIC_REACTION_FROM_USER" = "%@ đã bày tỏ cảm xúc";
|
||||
|
||||
/** Reactions **/
|
||||
|
||||
@@ -96,10 +96,10 @@
|
||||
"STICKER_FROM_USER" = "%@ đã gửi một sticker";
|
||||
|
||||
/* A single unread message */
|
||||
"SINGLE_UNREAD" = "Bạn đã nhận một tin nhắn";
|
||||
"SINGLE_UNREAD" = "Bạn nhận được một tin nhắn";
|
||||
|
||||
/* A single unread message in a room */
|
||||
"SINGLE_UNREAD_IN_ROOM" = "Bạn đã nhận một tin nhắn trong %@";
|
||||
"SINGLE_UNREAD_IN_ROOM" = "Bạn nhận được một tin nhắn trong %@";
|
||||
|
||||
/* New file message from a specific person, not referencing a room. */
|
||||
"FILE_FROM_USER" = "%@ đã gửi một tệp %@";
|
||||
@@ -131,3 +131,6 @@
|
||||
/** General **/
|
||||
|
||||
"Notification" = "Thông báo";
|
||||
"VOICE_BROADCAST_FROM_USER" = "%@ bắt đầu phát thanh";
|
||||
"UNSUPPORTED_CALL" = "Cuộc gọi không được hỗ trợ";
|
||||
"LOCATION_FROM_USER" = "%@ đã chia sẻ vị trí của họ";
|
||||
|
||||
@@ -37,14 +37,14 @@
|
||||
"auth_register" = "Đăng kí";
|
||||
"auth_submit" = "Gửi đi";
|
||||
"auth_skip" = "Bỏ qua";
|
||||
"auth_send_reset_email" = "Gửi email đặt lại";
|
||||
"auth_send_reset_email" = "Gửi thư đặt lại";
|
||||
"auth_return_to_login" = "Trở về trang đăng kí";
|
||||
"auth_user_id_placeholder" = "Email hoặc tên đăng nhập";
|
||||
"auth_user_id_placeholder" = "Địa chỉ thư điện tử hoặc tên đăng nhập";
|
||||
"auth_password_placeholder" = "Mật khẩu";
|
||||
"auth_new_password_placeholder" = "Mật khẩu mới";
|
||||
"auth_user_name_placeholder" = "Tên đăng nhập";
|
||||
"auth_optional_email_placeholder" = "Địa chỉ email (không bắt buộc)";
|
||||
"auth_email_placeholder" = "Địa chỉ email";
|
||||
"auth_optional_email_placeholder" = "Địa chỉ thư điện tử (không bắt buộc)";
|
||||
"auth_email_placeholder" = "Địa chỉ thư điện tử";
|
||||
"auth_optional_phone_placeholder" = "Số điện thoại (không bắt buộc)";
|
||||
"auth_phone_placeholder" = "Số điện thoại";
|
||||
"auth_repeat_password_placeholder" = "Nhật lại mật khẩu";
|
||||
@@ -55,38 +55,38 @@
|
||||
"warning" = "Cảnh báo";
|
||||
"auth_invalid_user_name" = "Tên đăng nhập chỉ được chứa các chữ cái, dấu chấm, dấu gạch ngang và dấu gạch dưới";
|
||||
"auth_invalid_password" = "Mật khẩu quá ngắn (tối thiểu 6 kí tự)";
|
||||
"auth_invalid_email" = "Địa chỉ Email không hợp lệ";
|
||||
"auth_invalid_email" = "Địa chỉ Địa thư điện tử không hợp lệ";
|
||||
"auth_invalid_phone" = "Số điện thoại không hợp lệ";
|
||||
"auth_missing_password" = "Thiếu mật khẩu";
|
||||
"auth_add_email_message" = "Thêm địa chỉ email vào tài khoản để người dùng khác có thể tìm thấy bạn và giúp bạn thay đổi mật khẩu về sau.";
|
||||
"auth_add_phone_message" = "Thêm số điện thoại vào tài khoản của bạn để giúp người dùng khác có thể tìm thấy bạn.";
|
||||
"auth_add_email_phone_message" = "Thêm địa chỉ email hoặc số điện thoại vào tài khoản để người dùng khác có thể tìm thấy bạn. Địa chỉ email cũng sẽ giúp bạn thay đổi mật khẩu về sau.";
|
||||
"auth_add_email_and_phone_message" = "Thêm địa chỉ email hoặc số điện thoại vào tài khoản để người dùng khác có thể tìm thấy bạn. Địa chỉ email cũng sẽ giúp bạn thay đổi mật khẩu về sau.";
|
||||
"auth_missing_email" = "Thiếu địa chỉ email";
|
||||
"auth_missing_email" = "Thiếu địa chỉ thư điện tử";
|
||||
"auth_missing_phone" = "Thiếu số điện thoại";
|
||||
"auth_missing_email_or_phone" = "Thiếu địa chỉ email hoặc số điện thoại";
|
||||
"auth_email_in_use" = "Địa chỉ email này đã được sử dụng";
|
||||
"auth_missing_email_or_phone" = "Thiếu địa chỉ thư điện tử hoặc số điện thoại";
|
||||
"auth_email_in_use" = "Địa chỉ thư điện tử này đã được sử dụng";
|
||||
"auth_phone_in_use" = "Số điện thoại này đã được sử dụng";
|
||||
"auth_untrusted_id_server" = "Máy chủ xác thực không được tin cậy";
|
||||
"auth_password_dont_match" = "Mật khẩu không trùng khớp";
|
||||
"auth_username_in_use" = "Tên đăng nhập đang được sử dụng";
|
||||
"auth_forgot_password" = "Quên mật khẩu danh khoản Matrix?";
|
||||
"auth_email_not_found" = "Gửi email thất bại: Địa chỉ email này không thể tìm thấy";
|
||||
"auth_email_not_found" = "Gửi thư thất bại: Địa chỉ thư điện tử này không thể tìm thấy";
|
||||
"auth_use_server_options" = "Sử dụng tùy chọn máy chủ tuỳ chỉnh (nâng cao)";
|
||||
"auth_email_validation_message" = "Vui lòng kiểm tra email của bẹn để tiếp tục đăng kí";
|
||||
"auth_email_validation_message" = "Vui lòng kiểm tra hòm thư của bẹn để tiếp tục đăng ký";
|
||||
"auth_msisdn_validation_title" = "Xác minh đang chờ xử lí";
|
||||
"auth_msisdn_validation_message" = "Chúng tôi đã gửi mã kích hoạt qua SMS. Vui lòng nhập mã kích hoạt bên dưới.";
|
||||
"auth_msisdn_validation_error" = "Không thể xác thực số điện thoại.";
|
||||
"auth_recaptcha_message" = "Home Server này muốn đảm bảo rằng bạn không phải là Robot";
|
||||
"auth_reset_password_message" = "Để thay đổi mật khẩu, nhập địa chỉ email được kết nối với tài khoản của bạn:";
|
||||
"auth_reset_password_missing_email" = "Bạn phải nhập địa chỉ email đã được kết nối với tài khoản của bạn.";
|
||||
"auth_reset_password_message" = "Để thay đổi mật khẩu, nhập địa chỉ thư điện tử được kết nối với tài khoản của bạn:";
|
||||
"auth_reset_password_missing_email" = "Bạn phải nhập địa chỉ thư điện tử đã được kết nối với tài khoản của bạn.";
|
||||
"auth_reset_password_missing_password" = "Bạn phải nhập mật khẩu mới.";
|
||||
"auth_reset_password_email_validation_message" = "Email đã được gửi tới %@. Khi bạn đã theo liên kết trong đó, bấm vào dưới đây.";
|
||||
"auth_reset_password_next_step_button" = "Tôi đã xác thực địa chỉ email của tôi";
|
||||
"auth_reset_password_error_unauthorized" = "Xác thực địa chỉ email thất bại: hãy đảm bảo rằng bạn đã bấm vào địa chỉ đính kèm trong email";
|
||||
"auth_reset_password_error_not_found" = "Địa chỉ email có vẻ chưa được liên kết với Matrix ID trên homeserver này.";
|
||||
"auth_reset_password_email_validation_message" = "Thư đã được gửi tới %@. Khi bạn đã theo liên kết trong đó, bấm vào dưới đây.";
|
||||
"auth_reset_password_next_step_button" = "Tôi đã xác thực địa chỉ thư điện tử của tôi";
|
||||
"auth_reset_password_error_unauthorized" = "Xác thực địa chỉ thư điện tử thất bại: hãy đảm bảo rằng bạn đã bấm vào địa chỉ đính kèm trong thư";
|
||||
"auth_reset_password_error_not_found" = "Địa chỉ thư điện tử của bạn không có tài khoản trên máy chủ nhà này.";
|
||||
"auth_reset_password_success_message" = "Mật khẩu của bạn đã được thiết lập lại.\n\nBạn đã được đăng xuất khỏi tất cả các thiết bị và sẽ không còn nhận được thông báo. Để bật lại thông báo, đăng nhập lại trên mỗi thiết bị.";
|
||||
"auth_add_email_and_phone_warning" = "Đăng kí với mật khẩu và số điện thoại cùng lúc chưa được hỗ trợ cho tới khi api được thiết lập. Duy nhất số điện thoại sẽ được liên kết với với tài khoản. Bạn sẽ phải thêm email vào hồ sơ trong mục cài đặt.";
|
||||
"auth_add_email_and_phone_warning" = "Đăng ký bằng cả địa chỉ thư điện tử và số điện thoại chưa được hỗ trợ vì chưa có API. Chỉ có số điện thoại được thêm vào tài khoản của bạn. Bạn có thể thêm địa chỉ thư điện tử trong phần cài đặt hồ sơ.";
|
||||
// Chat creation
|
||||
"room_creation_title" = "Cuộc trò chuyện mới";
|
||||
"room_creation_account" = "Tài khoản";
|
||||
@@ -1594,10 +1594,10 @@
|
||||
"auth_reset_password_error_is_required" = "Không có máy chủ xác thực nào được cấu hình: thêm một trong các tùy chọn máy chủ để đặt lại mật khẩu của bạn.";
|
||||
"auth_forgot_password_error_no_configured_identity_server" = "Không có máy chủ xác thực nào được cấu hình: thêm một để đặt lại mật khẩu của bạn.";
|
||||
"auth_phone_is_required" = "Không có máy chủ xác thực nào được cấu hình để bạn không thể thêm số điện thoại để đặt lại mật khẩu của mình trong tương lai.";
|
||||
"auth_email_is_required" = "Không có máy chủ xác thực nào được cấu hình để bạn không thể thêm địa chỉ email để đặt lại mật khẩu của mình trong tương lai.";
|
||||
"auth_add_email_phone_message_2" = "Đặt email để khôi phục tài khoản. Sử dụng email hoặc điện thoại sau này để được tùy chọn phát hiện bởi những người biết bạn.";
|
||||
"auth_email_is_required" = "Không có máy chủ xác thực nào được cấu hình nên bạn không thể thêm địa chỉ thư điện tử để đặt lại mật khẩu của mình trong tương lai.";
|
||||
"auth_add_email_phone_message_2" = "Đặt địa chỉ thư điện tử để khôi phục tài khoản. Sử dụng địa chỉ thư điện tử hoặc điện thoại sau này để được tùy chọn phát hiện bởi những người biết bạn.";
|
||||
"auth_add_phone_message_2" = "Đặt điện thoại và sau đó có thể tùy chọn được tìm kiếm bởi những người biết bạn.";
|
||||
"auth_add_email_message_2" = "Đặt email để khôi phục tài khoản và sau đó có thể tùy chọn được tìm kiếm bởi những người biết bạn.";
|
||||
"auth_add_email_message_2" = "Đặt địa chỉ thư điện tử để khôi phục tài khoản và sau đó có thể tùy chọn được tìm kiếm bởi những người biết bạn.";
|
||||
"auth_login_single_sign_on" = "Đăng nhập";
|
||||
|
||||
// Accessibility
|
||||
@@ -1994,3 +1994,16 @@
|
||||
"onboarding_splash_register_button_title" = "Tạo danh khoản";
|
||||
"accessibility_button_label" = "nút";
|
||||
"enable" = "Bật";
|
||||
"authentication_choose_password_not_verified_title" = "Địa chỉ thư điện tử chưa được xác nhận";
|
||||
"authentication_verify_email_text_field_placeholder" = "Địa chỉ thư điện tử";
|
||||
"authentication_verify_email_waiting_title" = "Xác nhận địa chỉ thư điện tử của bạn.";
|
||||
"authentication_forgot_password_input_title" = "Nhập địa chỉ thư điện tử";
|
||||
"authentication_forgot_password_text_field_placeholder" = "Địa chỉ thư điện tử";
|
||||
"authentication_forgot_password_waiting_button" = "Gửi lại";
|
||||
"authentication_login_username" = "Tên đăng nhập / Địa chỉ thư điện tử / Số điện thoại";
|
||||
"authentication_verify_email_input_title" = "Nhập địa chỉ thư điện tử";
|
||||
"authentication_verify_email_waiting_hint" = "Không nhận được thư?";
|
||||
"authentication_verify_email_waiting_button" = "Gửi lại";
|
||||
"authentication_verify_email_input_message" = "%@ cần xác thực tài khoản của bạn";
|
||||
"authentication_verify_email_waiting_message" = "Làm theo chỉ dẫn được gửi đến %@";
|
||||
"authentication_forgot_password_waiting_title" = "Kiểm tra hòm thư của bạn.";
|
||||
|
||||
@@ -1598,7 +1598,7 @@
|
||||
"accessibility_button_label" = "按钮";
|
||||
"enable" = "启用";
|
||||
"onboarding_splash_page_1_message" = "独立安全的通信,为您提供与家中面谈相同的私密性。";
|
||||
"onboarding_splash_page_1_title" = "掌控你的对话。";
|
||||
"onboarding_splash_page_1_title" = "掌控您的对话。";
|
||||
|
||||
// Onboarding
|
||||
"onboarding_splash_register_button_title" = "注册";
|
||||
@@ -2086,7 +2086,7 @@
|
||||
"room_many_users_are_typing" = "%@、%@和其他人正在输入……";
|
||||
/* The placeholder %1$tu will be replaced with a number and %2$@ with the user's search terms. */
|
||||
"directory_search_results" = "为%2$@找到%1$tu个结果";
|
||||
"onboarding_splash_page_2_title" = "一切都在你的掌控中。";
|
||||
"onboarding_splash_page_2_title" = "一切都在您的掌控中。";
|
||||
"onboarding_congratulations_personalize_button" = "个性化用户资料";
|
||||
/* The placeholder string contains the user's matrix ID */
|
||||
"onboarding_congratulations_message" = "你的账户%@已创建";
|
||||
@@ -2101,7 +2101,7 @@
|
||||
"onboarding_use_case_title" = "你会和谁聊得最多?";
|
||||
"onboarding_splash_page_4_message" = "Element也很适合工作场所。受世界最安全的组织的信任。";
|
||||
"onboarding_splash_page_3_message" = "端到端加密且不要求电话号码。无广告或数据挖掘。";
|
||||
"onboarding_splash_page_2_message" = "选择在哪里保存你的对话,给你控制和独立。通过Matrix连接。";
|
||||
"onboarding_splash_page_2_message" = "选择在哪里保存您的对话,给您控制和独立。通过Matrix连接。";
|
||||
|
||||
// MARK: Reactions
|
||||
|
||||
@@ -2433,5 +2433,10 @@
|
||||
"room_command_discard_session_description" = "强制当前已在加密房间中的外部群组会话失效";
|
||||
"call_jitsi_unable_to_start" = "无法开始会议通话";
|
||||
"room_suggestion_settings_screen_title" = "将房间设置为该空间中的建议房间";
|
||||
"room_suggestion_settings_screen_message" = "向空间成员推荐建议房间";
|
||||
"room_suggestion_settings_screen_message" = "向空间成员推荐建议房间。";
|
||||
"key_backup_recover_from_private_key_progress" = "完成 %@%%";
|
||||
"sunset_download_banner_learn_more" = "了解更多";
|
||||
"sunset_delegated_oidc_registration_not_supported_message" = "下载 %1$@ 后才能在您的账户中使用 %2$@,或选择另一个家服务器。";
|
||||
"sunset_delegated_oidc_registration_not_supported_generic_error" = "您已无法用该家服务器在本应用中创建账户";
|
||||
"sunset_download_banner_title" = "下载 %1$@";
|
||||
"sunset_delegated_oidc_registration_not_supported_title" = "您已无法再用 %1$@ 在本应用中创建账户";
|
||||
|
||||
36
Riot/Categories/MXRoom.swift
Normal file
36
Riot/Categories/MXRoom.swift
Normal file
@@ -0,0 +1,36 @@
|
||||
//
|
||||
// Copyright 2025 New Vector Ltd
|
||||
//
|
||||
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
|
||||
// Please see LICENSE files in the repository root for full details.
|
||||
//
|
||||
|
||||
@objc
|
||||
extension MXRoom {
|
||||
/// Returns true if the user is the last owner of the room, but not the last member.
|
||||
func isLastOwner() async throws -> Bool {
|
||||
let userID = mxSession.myUserId
|
||||
let state = try await state()
|
||||
|
||||
let requiredPowerLevel: RoomPowerLevel = state.isMSC4289Supported() ? .owner : .admin
|
||||
|
||||
guard state.powerLevelOfUser(withUserID: userID) >= requiredPowerLevel.rawValue else {
|
||||
return false
|
||||
}
|
||||
|
||||
guard let joinedMembers = try await members()?.members(with: .join) else {
|
||||
return false
|
||||
}
|
||||
|
||||
var areOtherMembers = false
|
||||
for member in joinedMembers where member.userId != userID {
|
||||
// User is not the last member in the whole room.
|
||||
areOtherMembers = true
|
||||
// If there are other owners/admins the user can leave
|
||||
if state.powerLevelOfUser(withUserID: member.userId) >= requiredPowerLevel.rawValue {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return areOtherMembers
|
||||
}
|
||||
}
|
||||
@@ -6155,6 +6155,10 @@ public class VectorL10n: NSObject {
|
||||
public static func roomMemberPowerLevelModeratorIn(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "room_member_power_level_moderator_in", p1)
|
||||
}
|
||||
/// Owner in %@
|
||||
public static func roomMemberPowerLevelOwnerIn(_ p1: String) -> String {
|
||||
return VectorL10n.tr("Vector", "room_member_power_level_owner_in", p1)
|
||||
}
|
||||
/// You will not be able to undo this change as you are promoting the user to have the same power level as yourself.\nAre you sure?
|
||||
public static var roomMemberPowerLevelPrompt: String {
|
||||
return VectorL10n.tr("Vector", "room_member_power_level_prompt")
|
||||
@@ -6171,6 +6175,10 @@ public class VectorL10n: NSObject {
|
||||
public static var roomMemberPowerLevelShortModerator: String {
|
||||
return VectorL10n.tr("Vector", "room_member_power_level_short_moderator")
|
||||
}
|
||||
/// Owner
|
||||
public static var roomMemberPowerLevelShortOwner: String {
|
||||
return VectorL10n.tr("Vector", "room_member_power_level_short_owner")
|
||||
}
|
||||
/// Editing
|
||||
public static var roomMessageEditing: String {
|
||||
return VectorL10n.tr("Vector", "room_message_editing")
|
||||
@@ -6439,6 +6447,10 @@ public class VectorL10n: NSObject {
|
||||
public static var roomParticipantsInvitedSection: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_invited_section")
|
||||
}
|
||||
/// You can't leave the room since you're the only owner of it.
|
||||
public static var roomParticipantsLeaveNotAllowedForLastOwnerMsg: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_leave_not_allowed_for_last_owner_msg")
|
||||
}
|
||||
/// Leaving
|
||||
public static var roomParticipantsLeaveProcessing: String {
|
||||
return VectorL10n.tr("Vector", "room_participants_leave_processing")
|
||||
|
||||
@@ -348,7 +348,7 @@ NSString *const WidgetManagerErrorDomain = @"WidgetManagerErrorDomain";
|
||||
|
||||
// Check user's power in the room
|
||||
MXRoomPowerLevels *powerLevels = roomState.powerLevels;
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:room.mxSession.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [roomState powerLevelOfUserWithUserID:room.mxSession.myUser.userId];
|
||||
|
||||
// The user must be able to send state events to manage widgets
|
||||
if (oneSelfPowerLevel < powerLevels.stateDefault)
|
||||
|
||||
@@ -10,13 +10,16 @@ import Foundation
|
||||
/// Riot Standard Room Member Power Level
|
||||
@objc
|
||||
public enum RoomPowerLevel: Int {
|
||||
case owner = 150
|
||||
case admin = 100
|
||||
case moderator = 50
|
||||
case user = 0
|
||||
|
||||
public init?(rawValue: Int) {
|
||||
switch rawValue {
|
||||
case 100...:
|
||||
case 150...:
|
||||
self = .owner
|
||||
case 100...149:
|
||||
self = .admin
|
||||
case 50...99:
|
||||
self = .moderator
|
||||
|
||||
@@ -125,7 +125,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
[tableSearchBar setImage:AssetImages.filterOff.image
|
||||
forSearchBarIcon:UISearchBarIconSearch
|
||||
state:UIControlStateNormal];
|
||||
|
||||
|
||||
tableSearchBar.delegate = self;
|
||||
|
||||
displayedSectionHeaders = [NSMutableArray array];
|
||||
@@ -133,7 +133,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
_contextMenuProvider = [RecentCellContextMenuProvider new];
|
||||
self.contextMenuProvider.serviceDelegate = self;
|
||||
self.contextMenuProvider.menuProviderDelegate = self;
|
||||
|
||||
|
||||
// Set itself as delegate by default.
|
||||
self.delegate = self;
|
||||
}
|
||||
@@ -151,10 +151,10 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
|
||||
// Register key backup banner cells
|
||||
[self.recentsTableView registerNib:SecureBackupBannerCell.nib forCellReuseIdentifier:SecureBackupBannerCell.defaultReuseIdentifier];
|
||||
|
||||
|
||||
// Register key verification banner cells
|
||||
[self.recentsTableView registerNib:CrossSigningSetupBannerCell.nib forCellReuseIdentifier:CrossSigningSetupBannerCell.defaultReuseIdentifier];
|
||||
|
||||
|
||||
[self.recentsTableView registerClass:SectionHeaderView.class
|
||||
forHeaderFooterViewReuseIdentifier:SectionHeaderView.defaultReuseIdentifier];
|
||||
|
||||
@@ -181,7 +181,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
[self.recentsSearchBar setImage:AssetImages.filterOff.image
|
||||
forSearchBarIcon:UISearchBarIconSearch
|
||||
state:UIControlStateNormal];
|
||||
|
||||
|
||||
// Observe user interface theme change.
|
||||
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
|
||||
|
||||
@@ -196,7 +196,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
- (void)userInterfaceThemeDidChange
|
||||
{
|
||||
[ThemeService.shared.theme applyStyleOnNavigationBar:self.navigationController.navigationBar];
|
||||
|
||||
|
||||
self.activityIndicator.backgroundColor = ThemeService.shared.theme.overlayBackgroundColor;
|
||||
|
||||
// Use the primary bg color for the recents table view in plain style.
|
||||
@@ -204,15 +204,15 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
self.recentsTableView.separatorColor = ThemeService.shared.theme.lineBreakColor;
|
||||
topview.backgroundColor = ThemeService.shared.theme.headerBackgroundColor;
|
||||
self.view.backgroundColor = ThemeService.shared.theme.backgroundColor;
|
||||
|
||||
|
||||
[ThemeService.shared.theme applyStyleOnSearchBar:tableSearchBar];
|
||||
[ThemeService.shared.theme applyStyleOnSearchBar:self.recentsSearchBar];
|
||||
|
||||
|
||||
// Force table refresh
|
||||
[self.recentsTableView reloadData];
|
||||
|
||||
[self.emptyView updateWithTheme:ThemeService.shared.theme];
|
||||
|
||||
|
||||
[self setNeedsStatusBarAppearanceUpdate];
|
||||
}
|
||||
|
||||
@@ -270,7 +270,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
[super viewWillAppear:animated];
|
||||
isViewVisible = YES;
|
||||
[self.screenTracker trackScreen];
|
||||
|
||||
|
||||
// Reset back user interactions
|
||||
self.userInteractionEnabled = YES;
|
||||
|
||||
@@ -341,7 +341,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
// the selected room (if any) is highlighted.
|
||||
[self refreshCurrentSelectedCell:YES];
|
||||
}
|
||||
|
||||
|
||||
if (self.recentsDataSource)
|
||||
{
|
||||
[self refreshRecentsTable];
|
||||
@@ -913,10 +913,10 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
{
|
||||
Analytics.shared.joinedRoomTrigger = AnalyticsJoinedRoomTriggerInvite;
|
||||
}
|
||||
|
||||
|
||||
// Avoid multiple openings of rooms
|
||||
self.userInteractionEnabled = NO;
|
||||
|
||||
|
||||
// Do not stack views when showing room
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:NO stackAboveVisibleViews:NO];
|
||||
|
||||
@@ -935,7 +935,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
- (void)showRoomPreviewWithData:(RoomPreviewData*)roomPreviewData
|
||||
{
|
||||
Analytics.shared.joinedRoomTrigger = AnalyticsJoinedRoomTriggerRoomDirectory;
|
||||
|
||||
|
||||
// Do not stack views when showing room
|
||||
ScreenPresentationParameters *presentationParameters = [[ScreenPresentationParameters alloc] initWithRestoreInitialDisplay:NO stackAboveVisibleViews:NO sender:nil sourceView:nil];
|
||||
|
||||
@@ -1008,7 +1008,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
{
|
||||
// Retrieve the invited room
|
||||
MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey];
|
||||
|
||||
|
||||
if (invitedRoom.summary.roomType == MXRoomTypeSpace)
|
||||
{
|
||||
// Indicates that spaces are not supported
|
||||
@@ -1023,7 +1023,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
{
|
||||
// Retrieve the invited room
|
||||
MXRoom *invitedRoom = userInfo[kInviteRecentTableViewCellRoomKey];
|
||||
|
||||
|
||||
if (invitedRoom.summary.roomType == MXRoomTypeSpace)
|
||||
{
|
||||
// Indicates that spaces are not supported
|
||||
@@ -1062,7 +1062,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
[super dataSource:dataSource didCellChange:changes];
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if ([changes isKindOfClass:NSIndexPath.class])
|
||||
{
|
||||
NSIndexPath *indexPath = (NSIndexPath *)changes;
|
||||
@@ -1073,7 +1073,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
|
||||
TableViewCellWithCollectionView *collectionViewCell = (TableViewCellWithCollectionView *)cell;
|
||||
[collectionViewCell.collectionView reloadData];
|
||||
|
||||
|
||||
CGRect headerFrame = [self.recentsTableView rectForHeaderInSection:indexPath.section];
|
||||
UIView *headerView = [self.recentsTableView headerViewForSection:indexPath.section];
|
||||
UIView *updatedHeaderView = [self.dataSource viewForHeaderInSection:indexPath.section withFrame:headerFrame inTableView:self.recentsTableView];
|
||||
@@ -1111,7 +1111,7 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
}
|
||||
|
||||
[self showEmptyViewIfNeeded];
|
||||
|
||||
|
||||
if (dataSource.state == MXKDataSourceStateReady)
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:RecentsViewControllerDataReadyNotification
|
||||
@@ -1120,109 +1120,120 @@ NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewContro
|
||||
}
|
||||
|
||||
#pragma mark - Swipe actions
|
||||
|
||||
- (void)leaveEditedRoom
|
||||
{
|
||||
if (editedRoomId)
|
||||
{
|
||||
NSString *currentRoomId = editedRoomId;
|
||||
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
NSString *title, *message;
|
||||
if ([self.mainSession roomWithRoomId:currentRoomId].isDirect)
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitleForDm];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsgForDm];
|
||||
}
|
||||
else
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitle];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsg];
|
||||
}
|
||||
|
||||
// confirm leave
|
||||
UIAlertController *leavePrompt = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[leavePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[leavePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
|
||||
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
self->currentAlert = nil;
|
||||
|
||||
// Check whether the user didn't leave the room yet
|
||||
// TODO: Handle multi-account
|
||||
MXRoom *room = [self.mainSession roomWithRoomId:currentRoomId];
|
||||
if (room)
|
||||
{
|
||||
[self startActivityIndicatorWithLabel:[VectorL10n roomParticipantsLeaveProcessing]];
|
||||
// cancel pending uploads/downloads
|
||||
// they are useless by now
|
||||
[MXMediaManager cancelDownloadsInCacheFolder:room.roomId];
|
||||
|
||||
// TODO GFO cancel pending uploads related to this room
|
||||
|
||||
MXLogDebug(@"[RecentsViewController] Leave room (%@)", room.roomId);
|
||||
|
||||
[room leave:^{
|
||||
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
[self stopActivityIndicator];
|
||||
[self.userIndicatorStore presentSuccessWithLabel:[VectorL10n roomParticipantsLeaveSuccess]];
|
||||
// Force table refresh
|
||||
[self cancelEditionMode:YES];
|
||||
}
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXLogDebug(@"[RecentsViewController] Failed to leave room");
|
||||
if (weakSelf)
|
||||
{
|
||||
typeof(self) self = weakSelf;
|
||||
// Notify the end user
|
||||
NSString *userId = room.mxSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification
|
||||
object:error
|
||||
userInfo:userId ? @{kMXKErrorUserIdKey: userId} : nil];
|
||||
|
||||
[self stopActivityIndicator];
|
||||
|
||||
// Leave editing mode
|
||||
[self cancelEditionMode:self->isRefreshPending];
|
||||
}
|
||||
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Leave editing mode
|
||||
[self cancelEditionMode:self->isRefreshPending];
|
||||
}
|
||||
}
|
||||
|
||||
}]];
|
||||
|
||||
[leavePrompt mxk_setAccessibilityIdentifier:@"LeaveEditedRoomAlert"];
|
||||
[self presentViewController:leavePrompt animated:YES completion:nil];
|
||||
currentAlert = leavePrompt;
|
||||
MXWeakify(self);
|
||||
MXRoom *room = [self.mainSession roomWithRoomId:currentRoomId];
|
||||
__weak typeof(room) weakRoom = room;
|
||||
[room isLastOwnerWithCompletionHandler:^(BOOL isLastOwner, NSError* error){
|
||||
if (isLastOwner)
|
||||
{
|
||||
UIAlertController *isLastOwnerPrompt = [UIAlertController alertControllerWithTitle:[VectorL10n error]
|
||||
message:[VectorL10n roomParticipantsLeaveNotAllowedForLastOwnerMsg]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[isLastOwnerPrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n ok]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
}]];
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self presentViewController:isLastOwnerPrompt animated:YES completion:nil];
|
||||
self->currentAlert = isLastOwnerPrompt;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
NSString *title, *message;
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
if ([self.mainSession roomWithRoomId:currentRoomId].isDirect)
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitleForDm];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsgForDm];
|
||||
}
|
||||
else
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitle];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsg];
|
||||
}
|
||||
|
||||
// confirm leave
|
||||
UIAlertController *leavePrompt = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
MXWeakify(self);
|
||||
[leavePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
}]];
|
||||
|
||||
[leavePrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
|
||||
style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
// Check whether the user didn't leave the room yet
|
||||
// TODO: Handle multi-account
|
||||
if (weakRoom)
|
||||
{
|
||||
[self startActivityIndicatorWithLabel:[VectorL10n roomParticipantsLeaveProcessing]];
|
||||
// cancel pending uploads/downloads
|
||||
// they are useless by now
|
||||
[MXMediaManager cancelDownloadsInCacheFolder:weakRoom.roomId];
|
||||
|
||||
// TODO GFO cancel pending uploads related to this room
|
||||
|
||||
MXLogDebug(@"[RecentsViewController] Leave room (%@)", weakRoom.roomId);
|
||||
|
||||
MXWeakify(self);
|
||||
[weakRoom leave:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self stopActivityIndicator];
|
||||
[self.userIndicatorStore presentSuccessWithLabel:[VectorL10n roomParticipantsLeaveSuccess]];
|
||||
// Force table refresh
|
||||
[self cancelEditionMode:YES];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXLogDebug(@"[RecentsViewController] Failed to leave room");
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
// Notify the end user
|
||||
NSString *userId = room.mxSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification
|
||||
object:error
|
||||
userInfo:userId ? @{kMXKErrorUserIdKey: userId} : nil];
|
||||
|
||||
[self stopActivityIndicator];
|
||||
|
||||
// Leave editing mode
|
||||
[self cancelEditionMode:self->isRefreshPending];
|
||||
|
||||
}];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Leave editing mode
|
||||
[self cancelEditionMode:self->isRefreshPending];
|
||||
}
|
||||
|
||||
}]];
|
||||
[leavePrompt mxk_setAccessibilityIdentifier:@"LeaveEditedRoomAlert"];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self presentViewController:leavePrompt animated:YES completion:nil];
|
||||
self->currentAlert = leavePrompt;
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -134,10 +134,12 @@ class AllChatsEditActionProvider {
|
||||
spaceRoom.state { [weak self] roomState in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let powerLevels = roomState?.powerLevels, let userId = session.myUserId else {
|
||||
guard let roomState,
|
||||
let powerLevels = roomState.powerLevels,
|
||||
let userId = session.myUserId else {
|
||||
return
|
||||
}
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
||||
let userPowerLevel = roomState.powerLevelOfUser(withUserID: userId)
|
||||
|
||||
self.isInviteAvailable = userPowerLevel >= powerLevels.invite
|
||||
self.isAddRoomAvailable = userPowerLevel >= parentSpace.minimumPowerLevelForAddingRoom(with: powerLevels)
|
||||
|
||||
@@ -77,10 +77,12 @@ class AllChatsSpaceActionProvider {
|
||||
spaceRoom.state { [weak self] roomState in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let powerLevels = roomState?.powerLevels, let userId = session.myUserId else {
|
||||
guard let roomState,
|
||||
let powerLevels = roomState.powerLevels,
|
||||
let userId = session.myUserId else {
|
||||
return
|
||||
}
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
||||
let userPowerLevel = roomState.powerLevelOfUser(withUserID: userId)
|
||||
|
||||
self.isInviteAvailable = userPowerLevel >= powerLevels.invite
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ class RoomContextActionService: NSObject, RoomContextActionServiceProtocol {
|
||||
|
||||
func leaveRoom(promptUser: Bool) {
|
||||
guard promptUser else {
|
||||
// Only used for declining an invite
|
||||
self.leaveRoom()
|
||||
return
|
||||
}
|
||||
@@ -141,6 +142,26 @@ class RoomContextActionService: NSObject, RoomContextActionServiceProtocol {
|
||||
self.delegate?.roomContextActionService(self, presentAlert: self.getLeaveAlertController())
|
||||
} else {
|
||||
self.delegate?.roomContextActionService(self, presentAlert: self.leaveAlertController)
|
||||
|
||||
Task {
|
||||
if try await room.isLastOwner() {
|
||||
await MainActor.run {
|
||||
let alertController = UIAlertController(title: VectorL10n.error, message: VectorL10n.roomParticipantsLeaveNotAllowedForLastOwnerMsg, preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: VectorL10n.ok, style: .cancel, handler: nil))
|
||||
self.delegate?.roomContextActionService(self, presentAlert: alertController)
|
||||
}
|
||||
} else {
|
||||
let title = room.isDirect ? VectorL10n.roomParticipantsLeavePromptTitleForDm : VectorL10n.roomParticipantsLeavePromptTitle
|
||||
let message = room.isDirect ? VectorL10n.roomParticipantsLeavePromptMsgForDm : VectorL10n.roomParticipantsLeavePromptMsg
|
||||
await MainActor.run {
|
||||
let alertController = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: VectorL10n.cancel, style: .cancel, handler: nil))
|
||||
alertController.addAction(UIAlertAction(title: VectorL10n.leave, style: .default, handler: { [weak self] action in
|
||||
self?.leaveRoom()
|
||||
}))
|
||||
self.delegate?.roomContextActionService(self, presentAlert: alertController)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -489,7 +489,7 @@ NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ";
|
||||
MXJSONModelSetBoolean(isState, requestData[@"is_state"]);
|
||||
|
||||
MXRoomPowerLevels *powerLevels = roomState.powerLevels;
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:self->mxSession.myUser.userId];
|
||||
NSInteger userPowerLevel = [roomState powerLevelOfUserWithUserID:self->mxSession.myUser.userId];
|
||||
|
||||
BOOL canSend = NO;
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse
|
||||
{
|
||||
// Check user's power in the room
|
||||
MXRoomPowerLevels *powerLevels = roomState.powerLevels;
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:session.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [roomState powerLevelOfUserWithUserID:session.myUser.userId];
|
||||
|
||||
// The user must be able to send state events to manage widgets
|
||||
if (oneSelfPowerLevel >= powerLevels.stateDefault)
|
||||
|
||||
@@ -23,6 +23,16 @@ public extension DTHTMLElement {
|
||||
// Remove any attachments to fix rendering.
|
||||
textAttachment = nil
|
||||
|
||||
// Handle special case for span with data-mx-external-payment-details
|
||||
// This could be based on Storefront.current.countryCode to show the link
|
||||
// content in unrestricted countries. e.g. currently USA
|
||||
if name == "span",
|
||||
let attributes = attributes as? [String: String],
|
||||
attributes["data-msc4286-external-payment-details"] != nil {
|
||||
parent.removeChildNode(self)
|
||||
return
|
||||
}
|
||||
|
||||
// If the element has plain text content show that,
|
||||
// otherwise prevent the tag from displaying.
|
||||
if let stringContent = attributedString()?.string,
|
||||
|
||||
@@ -220,20 +220,47 @@ Please see LICENSE in the repository root for full details.
|
||||
}
|
||||
case MXKRoomMemberDetailsActionLeave:
|
||||
{
|
||||
[self addPendingActionMask];
|
||||
[self.mxRoom leave:^{
|
||||
|
||||
[self removePendingActionMask];
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
[self removePendingActionMask];
|
||||
MXLogDebug(@"[MXKRoomMemberDetailsVC] Leave room %@ failed", self->mxRoom.roomId);
|
||||
// Notify MatrixKit user
|
||||
NSString *myUserId = self.mainSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
|
||||
|
||||
MXWeakify(self);
|
||||
[self.mxRoom isLastOwnerWithCompletionHandler:^(BOOL isLastOwner, NSError* error){
|
||||
if (isLastOwner)
|
||||
{
|
||||
UIAlertController *isLastOwnerPrompt = [UIAlertController alertControllerWithTitle:[VectorL10n error]
|
||||
message:[VectorL10n roomParticipantsLeaveNotAllowedForLastOwnerMsg]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[isLastOwnerPrompt addAction:[UIAlertAction actionWithTitle:[VectorL10n ok]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
}]];
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self presentViewController:isLastOwnerPrompt animated:YES completion:nil];
|
||||
self->currentAlert = isLastOwnerPrompt;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self addPendingActionMask];
|
||||
MXWeakify(self);
|
||||
[self.mxRoom leave:^{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
MXLogDebug(@"[MXKRoomMemberDetailsVC] Leave room %@ failed", self->mxRoom.roomId);
|
||||
// Notify MatrixKit user
|
||||
NSString *myUserId = self.mainSession.myUser.userId;
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:kMXKErrorNotification object:error userInfo:myUserId ? @{kMXKErrorUserIdKey: myUserId} : nil];
|
||||
|
||||
}];
|
||||
}
|
||||
}];
|
||||
break;
|
||||
}
|
||||
@@ -639,9 +666,10 @@ Please see LICENSE in the repository root for full details.
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
// Check user's power level before allowing an action (kick, ban, ...)
|
||||
MXRoomState *roomState = self.mxRoomLiveTimeline.state;
|
||||
MXRoomPowerLevels *powerLevels = [self.mxRoomLiveTimeline.state powerLevels];
|
||||
NSInteger memberPowerLevel = [powerLevels powerLevelOfUserWithUserID:_mxRoomMember.userId];
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger memberPowerLevel = [roomState powerLevelOfUserWithUserID:_mxRoomMember.userId];
|
||||
NSInteger oneSelfPowerLevel = [roomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
[actionsArray removeAllObjects];
|
||||
|
||||
@@ -894,14 +922,14 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
- (void)setPowerLevel:(NSInteger)value promptUser:(BOOL)promptUser
|
||||
{
|
||||
NSInteger currentPowerLevel = [self.mxRoomLiveTimeline.state.powerLevels powerLevelOfUserWithUserID:_mxRoomMember.userId];
|
||||
NSInteger currentPowerLevel = [self.mxRoomLiveTimeline.state powerLevelOfUserWithUserID:_mxRoomMember.userId];
|
||||
|
||||
// check if the power level has not yet been set to 0
|
||||
if (value != currentPowerLevel)
|
||||
{
|
||||
__weak typeof(self) weakSelf = self;
|
||||
|
||||
if (promptUser && value == [self.mxRoomLiveTimeline.state.powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId])
|
||||
if (promptUser && value == [self.mxRoomLiveTimeline.state powerLevelOfUserWithUserID:self.mainSession.myUser.userId])
|
||||
{
|
||||
// If the user is setting the same power level as his to another user, ask him for a confirmation
|
||||
if (currentAlert)
|
||||
@@ -999,7 +1027,7 @@ Please see LICENSE in the repository root for full details.
|
||||
typeof(self) self = weakSelf;
|
||||
|
||||
textField.secureTextEntry = NO;
|
||||
textField.text = [NSString stringWithFormat:@"%ld", (long)[self.mxRoomLiveTimeline.state.powerLevels powerLevelOfUserWithUserID:self.mxRoomMember.userId]];
|
||||
textField.text = [NSString stringWithFormat:@"%ld", (long)[self.mxRoomLiveTimeline.state powerLevelOfUserWithUserID:self.mxRoomMember.userId]];
|
||||
textField.placeholder = nil;
|
||||
textField.keyboardType = UIKeyboardTypeDecimalPad;
|
||||
}];
|
||||
|
||||
@@ -307,7 +307,7 @@ Please see LICENSE in the repository root for full details.
|
||||
if (showInvitationOption && self->dataSource)
|
||||
{
|
||||
// Check conditions to be able to invite someone
|
||||
NSInteger oneSelfPowerLevel = [roomState.powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [roomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
if (oneSelfPowerLevel < [roomState.powerLevels invite])
|
||||
{
|
||||
showInvitationOption = NO;
|
||||
|
||||
@@ -690,7 +690,7 @@ Please see LICENSE in the repository root for full details.
|
||||
- (BOOL)canInvitePeople
|
||||
{
|
||||
NSInteger requiredLevel = roomDataSource.roomState.powerLevels.invite;
|
||||
NSInteger myLevel = [roomDataSource.roomState.powerLevels powerLevelOfUserWithUserID:roomDataSource.mxSession.myUserId];
|
||||
NSInteger myLevel = [roomDataSource.roomState powerLevelOfUserWithUserID:roomDataSource.mxSession.myUserId];
|
||||
return myLevel >= requiredLevel;
|
||||
}
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ Please see LICENSE in the repository root for full details.
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
MXRoomPowerLevels *powerLevels = [roomState powerLevels];
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:self->mxSession.myUser.userId];
|
||||
NSInteger userPowerLevel = [roomState powerLevelOfUserWithUserID:self->mxSession.myUser.userId];
|
||||
if (powerLevels.redact)
|
||||
{
|
||||
if (userPowerLevel >= powerLevels.redact)
|
||||
|
||||
@@ -176,7 +176,7 @@ Please see LICENSE in the repository root for full details.
|
||||
// Check whether the user has enough power to rename the room
|
||||
MXRoomPowerLevels *powerLevels = _mxRoom.dangerousSyncState.powerLevels;
|
||||
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:_mxRoom.mxSession.myUser.userId];
|
||||
NSInteger userPowerLevel = [_mxRoom.dangerousSyncState powerLevelOfUserWithUserID:_mxRoom.mxSession.myUser.userId];
|
||||
if (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomName])
|
||||
{
|
||||
// Only the room name is edited here, update the text field with the room name
|
||||
|
||||
@@ -354,7 +354,7 @@ Please see LICENSE in the repository root for full details.
|
||||
{
|
||||
// Check whether the user has enough power to rename the room
|
||||
MXRoomPowerLevels *powerLevels = self.mxRoom.dangerousSyncState.powerLevels;
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxRoom.mxSession.myUser.userId];
|
||||
NSInteger userPowerLevel = [self.mxRoom.dangerousSyncState powerLevelOfUserWithUserID:self.mxRoom.mxSession.myUser.userId];
|
||||
if (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomName])
|
||||
{
|
||||
// Only the room name is edited here, update the text field with the room name
|
||||
@@ -384,7 +384,7 @@ Please see LICENSE in the repository root for full details.
|
||||
{
|
||||
// Check whether the user has enough power to edit room topic
|
||||
MXRoomPowerLevels *powerLevels = self.mxRoom.dangerousSyncState.powerLevels;
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxRoom.mxSession.myUser.userId];
|
||||
NSInteger userPowerLevel = [self.mxRoom.dangerousSyncState powerLevelOfUserWithUserID:self.mxRoom.mxSession.myUser.userId];
|
||||
if (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomTopic])
|
||||
{
|
||||
textField.backgroundColor = [UIColor whiteColor];
|
||||
|
||||
@@ -420,11 +420,15 @@ Please see LICENSE in the repository root for full details.
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
|
||||
MXRoomPowerLevels *powerLevels = [roomState powerLevels];
|
||||
NSInteger powerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxRoomMember.userId];
|
||||
NSInteger powerLevel = [roomState powerLevelOfUserWithUserID:self.mxRoomMember.userId];
|
||||
|
||||
RoomPowerLevel roomPowerLevel = [RoomPowerLevelHelper roomPowerLevelFrom:powerLevel];
|
||||
|
||||
switch (roomPowerLevel) {
|
||||
case RoomPowerLevelOwner:
|
||||
self.roomMemberPowerLevelLabel.text = [VectorL10n roomMemberPowerLevelOwnerIn:self.mxRoom.summary.displayName];
|
||||
self.roomMemberPowerLevelContainerView.hidden = NO;
|
||||
break;
|
||||
case RoomPowerLevelAdmin:
|
||||
self.roomMemberPowerLevelLabel.text = [BWIL10n roomMemberPowerLevelAdminIn:self.mxRoom.summary.displayName];
|
||||
self.roomMemberPowerLevelContainerView.hidden = NO;
|
||||
@@ -594,8 +598,8 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
// Check user's power level before allowing an action (kick, ban, ...)
|
||||
MXRoomPowerLevels *powerLevels = [self.mxRoom.dangerousSyncState powerLevels];
|
||||
NSInteger memberPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mxRoomMember.userId];
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger memberPowerLevel = [self.mxRoom.dangerousSyncState powerLevelOfUserWithUserID:self.mxRoomMember.userId];
|
||||
NSInteger oneSelfPowerLevel = [self.mxRoom.dangerousSyncState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
[adminActionsArray removeAllObjects];
|
||||
[otherActionsArray removeAllObjects];
|
||||
|
||||
@@ -796,8 +796,8 @@ Please see LICENSE in the repository root for full details.
|
||||
{
|
||||
// Order first by power levels (admins then moderators then others)
|
||||
MXRoomPowerLevels *powerLevels = [roomState powerLevels];
|
||||
NSInteger powerLevelA = [powerLevels powerLevelOfUserWithUserID:contactA.mxMember.userId];
|
||||
NSInteger powerLevelB = [powerLevels powerLevelOfUserWithUserID:contactB.mxMember.userId];
|
||||
NSInteger powerLevelA = [roomState powerLevelOfUserWithUserID:contactA.mxMember.userId];
|
||||
NSInteger powerLevelB = [roomState powerLevelOfUserWithUserID:contactB.mxMember.userId];
|
||||
|
||||
if (powerLevelA == powerLevelB)
|
||||
{
|
||||
@@ -1099,6 +1099,9 @@ Please see LICENSE in the repository root for full details.
|
||||
NSString *powerLevelText;
|
||||
|
||||
switch (roomPowerLevel) {
|
||||
case RoomPowerLevelOwner:
|
||||
powerLevelText = [VectorL10n roomMemberPowerLevelShortOwner];
|
||||
break;
|
||||
case RoomPowerLevelAdmin:
|
||||
powerLevelText = [VectorL10n roomMemberPowerLevelShortAdmin];
|
||||
break;
|
||||
@@ -1309,62 +1312,7 @@ Please see LICENSE in the repository root for full details.
|
||||
|
||||
if (section == participantsSection && userParticipant && (0 == row) && !currentSearchText.length)
|
||||
{
|
||||
// Leave ?
|
||||
MXWeakify(self);
|
||||
|
||||
NSString *title, *message;
|
||||
if (self.mxRoom.isDirect)
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitleForDm];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsgForDm];
|
||||
}
|
||||
else
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitle];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsg];
|
||||
}
|
||||
|
||||
currentAlert = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
}]];
|
||||
|
||||
[currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self addPendingActionMask];
|
||||
MXWeakify(self);
|
||||
[self.mxRoom leave:^{
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
MXLogDebug(@"[RoomParticipantsVC] Leave room %@ failed", self.mxRoom.roomId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
}]];
|
||||
|
||||
[currentAlert mxk_setAccessibilityIdentifier:@"RoomParticipantsVCLeaveAlert"];
|
||||
[self presentViewController:currentAlert animated:YES completion:nil];
|
||||
[self leaveRoom];
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1511,6 +1459,90 @@ Please see LICENSE in the repository root for full details.
|
||||
}
|
||||
}
|
||||
|
||||
- (void)leaveRoom {
|
||||
MXWeakify(self);
|
||||
|
||||
[self.mxRoom isLastOwnerWithCompletionHandler:^(BOOL isLastOwner, NSError* error) {
|
||||
if (isLastOwner)
|
||||
{
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n error]
|
||||
message:[VectorL10n roomParticipantsLeaveNotAllowedForLastOwnerMsg]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
}]];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self presentViewController:self->currentAlert animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// Leave ?
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
NSString *title, *message;
|
||||
if (self.mxRoom.isDirect)
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitleForDm];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsgForDm];
|
||||
}
|
||||
else
|
||||
{
|
||||
title = [VectorL10n roomParticipantsLeavePromptTitle];
|
||||
message = [VectorL10n roomParticipantsLeavePromptMsg];
|
||||
}
|
||||
|
||||
self->currentAlert = [UIAlertController alertControllerWithTitle:title
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
|
||||
MXWeakify(self);
|
||||
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel]
|
||||
style:UIAlertActionStyleCancel
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
}]];
|
||||
|
||||
[self->currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n leave]
|
||||
style:UIAlertActionStyleDefault
|
||||
handler:^(UIAlertAction * action) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
self->currentAlert = nil;
|
||||
|
||||
[self addPendingActionMask];
|
||||
MXWeakify(self);
|
||||
[self.mxRoom leave:^{
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
MXStrongifyAndReturnIfNil(self);
|
||||
[self removePendingActionMask];
|
||||
MXLogDebug(@"[RoomParticipantsVC] Leave room %@ failed", self.mxRoom.roomId);
|
||||
// Alert user
|
||||
[[AppDelegate theDelegate] showErrorAsAlert:error];
|
||||
|
||||
}];
|
||||
|
||||
}]];
|
||||
|
||||
[self->currentAlert mxk_setAccessibilityIdentifier:@"RoomParticipantsVCLeaveAlert"];
|
||||
[self presentViewController:self->currentAlert animated:YES completion:nil];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)onCancel:(id)sender
|
||||
{
|
||||
[self withdrawViewControllerAnimated:YES completion:nil];
|
||||
|
||||
@@ -163,12 +163,13 @@ final class RoomParticipantsInviteCoordinatorBridgePresenter: NSObject {
|
||||
}
|
||||
|
||||
room.state { roomState in
|
||||
guard let powerLevels = roomState?.powerLevels else {
|
||||
guard let roomState,
|
||||
let powerLevels = roomState.powerLevels else {
|
||||
MXLog.error("[RoomParticipantsInviteCoordinatorBridgePresenter] canInvite: room powerLevels not found")
|
||||
completion(false)
|
||||
return
|
||||
}
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
||||
let userPowerLevel = roomState.powerLevelOfUser(withUserID: userId)
|
||||
|
||||
completion(userPowerLevel >= powerLevels.invite)
|
||||
}
|
||||
|
||||
@@ -102,6 +102,18 @@ final class RoomInfoListViewController: UIViewController {
|
||||
return self.doNotLeaveUIAlertController()
|
||||
}
|
||||
}
|
||||
|
||||
private lazy var isLastOwnerAlertController: UIAlertController = {
|
||||
let title = VectorL10n.error
|
||||
let message = VectorL10n.roomParticipantsLeaveNotAllowedForLastOwnerMsg
|
||||
let controller = UIAlertController(title: title, message: message, preferredStyle: .alert)
|
||||
|
||||
controller.addAction(UIAlertAction(title: VectorL10n.ok, style: .default, handler: nil))
|
||||
controller.mxk_setAccessibilityIdentifier("RoomSettingsVCLastOwnerAlert")
|
||||
|
||||
return controller
|
||||
}()
|
||||
|
||||
|
||||
private enum RowType {
|
||||
case `default`
|
||||
@@ -267,8 +279,11 @@ final class RoomInfoListViewController: UIViewController {
|
||||
VectorL10n.roomParticipantsLeavePromptTitleForDm :
|
||||
VectorL10n.roomParticipantsLeavePromptTitle
|
||||
let rowLeave = Row(type: .destructive, icon: Asset.Images.roomActionLeave.image, text: leaveTitle, accessoryType: .none) {
|
||||
|
||||
if BWIBuildSettings.shared.lastAdminIsNotAllowedToLeaveRoom {
|
||||
self.present(self.getLeaveAlertController(), animated: true, completion: nil)
|
||||
} else if viewData.isLastOwner {
|
||||
self.present(self.isLastOwnerAlertController, animated: true, completion: nil)
|
||||
} else {
|
||||
self.present(self.leaveAlertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@@ -24,4 +24,5 @@ struct RoomInfoListViewData {
|
||||
let isEncrypted: Bool
|
||||
let isDirect: Bool
|
||||
let basicInfoViewData: RoomInfoBasicViewData
|
||||
let isLastOwner: Bool
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ final class RoomInfoListViewModel: NSObject, RoomInfoListViewModelType {
|
||||
|
||||
private let session: MXSession
|
||||
private let room: MXRoom
|
||||
private var isLastOwner = false
|
||||
|
||||
// MARK: Public
|
||||
|
||||
@@ -70,7 +71,8 @@ final class RoomInfoListViewModel: NSObject, RoomInfoListViewModelType {
|
||||
return RoomInfoListViewData(numberOfMembers: Int(room.summary.membersCount.joined),
|
||||
isEncrypted: room.summary.isEncrypted,
|
||||
isDirect: room.isDirect,
|
||||
basicInfoViewData: basicInfoViewData)
|
||||
basicInfoViewData: basicInfoViewData,
|
||||
isLastOwner: isLastOwner)
|
||||
}
|
||||
|
||||
// bwi: 5216 - federation
|
||||
@@ -163,6 +165,9 @@ final class RoomInfoListViewModel: NSObject, RoomInfoListViewModelType {
|
||||
@objc private func roomSummaryUpdated(_ notification: Notification) {
|
||||
// force update view
|
||||
self.update(viewState: .loaded(viewData: viewData))
|
||||
Task {
|
||||
isLastOwner = (try? await room.isLastOwner()) == true
|
||||
}
|
||||
}
|
||||
|
||||
private func loadData() {
|
||||
|
||||
@@ -1235,7 +1235,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
if (self.roomDataSource.roomState)
|
||||
{
|
||||
MXRoomPowerLevels *powerLevels = self.roomDataSource.roomState.powerLevels;
|
||||
NSInteger userPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger userPowerLevel = [self.roomDataSource.roomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
BOOL canSend = (userPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsMessage:kMXEventTypeStringRoomMessage]);
|
||||
BOOL isRoomObsolete = self.roomDataSource.roomState.isObsolete;
|
||||
@@ -1906,7 +1906,7 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
{
|
||||
MXRoomPowerLevels *powerLevels = [self.roomDataSource.roomState powerLevels];
|
||||
NSInteger requiredPower = [powerLevels minimumPowerLevelForSendingEventAsStateEvent:eventTypeString];
|
||||
NSInteger myPower = [powerLevels powerLevelOfUserWithUserID:self.roomDataSource.mxSession.myUserId];
|
||||
NSInteger myPower = [self.roomDataSource.roomState powerLevelOfUserWithUserID:self.roomDataSource.mxSession.myUserId];
|
||||
return myPower >= requiredPower;
|
||||
}
|
||||
|
||||
@@ -2724,23 +2724,6 @@ static CGSize kThreadListBarButtonItemImageSize;
|
||||
}
|
||||
}
|
||||
|
||||
- (void)leaveRoom
|
||||
{
|
||||
[self startActivityIndicator];
|
||||
|
||||
[self.roomDataSource.room leave:^{
|
||||
|
||||
[self stopActivityIndicator];
|
||||
[self notifyDelegateOnLeaveRoomIfNecessary];
|
||||
|
||||
} failure:^(NSError *error) {
|
||||
|
||||
[self stopActivityIndicator];
|
||||
MXLogDebug(@"[RoomVC] Failed to reject an invited room (%@) failed", self.roomDataSource.room.roomId);
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)notifyDelegateOnLeaveRoomIfNecessary {
|
||||
if (isRoomLeft) {
|
||||
return;
|
||||
|
||||
@@ -678,7 +678,7 @@ BOOL reloadToggleCell = false;
|
||||
{
|
||||
// Check user's power level to know whether the user is allowed to turn on the encryption mode
|
||||
MXRoomPowerLevels *powerLevels = [mxRoomState powerLevels];
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [mxRoomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomEncryption])
|
||||
{
|
||||
@@ -721,7 +721,7 @@ BOOL reloadToggleCell = false;
|
||||
return;
|
||||
|
||||
MXRoomPowerLevels *powerLevels = [mxRoomState powerLevels];
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [mxRoomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
if (oneSelfPowerLevel < [powerLevels minimumPowerLevelForSendingEventAsStateEvent:eventTypeForSelectedField])
|
||||
return;
|
||||
@@ -2249,7 +2249,7 @@ BOOL reloadToggleCell = false;
|
||||
|
||||
// Check user's power level to know which settings are editable.
|
||||
MXRoomPowerLevels *powerLevels = [mxRoomState powerLevels];
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [mxRoomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
// general settings
|
||||
if (section == SECTION_TAG_MAIN)
|
||||
@@ -3398,7 +3398,7 @@ BOOL reloadToggleCell = false;
|
||||
{
|
||||
// Check user's power level to know whether the user is allowed to set the main address
|
||||
MXRoomPowerLevels *powerLevels = [mxRoomState powerLevels];
|
||||
NSInteger oneSelfPowerLevel = [powerLevels powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
NSInteger oneSelfPowerLevel = [mxRoomState powerLevelOfUserWithUserID:self.mainSession.myUser.userId];
|
||||
|
||||
if (oneSelfPowerLevel >= [powerLevels minimumPowerLevelForSendingEventAsStateEvent:kMXEventTypeStringRoomAliases])
|
||||
{
|
||||
|
||||
@@ -329,11 +329,12 @@ final class SideMenuCoordinator: NSObject, SideMenuCoordinatorType {
|
||||
spaceRoom.state { [weak self] roomState in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let powerLevels = roomState?.powerLevels, let userId = session.myUserId else {
|
||||
guard let roomState,
|
||||
let powerLevels = roomState.powerLevels, let userId = session.myUserId else {
|
||||
MXLog.error("[SpaceMembersCoordinator] spaceMemberListCoordinatorShowInvite: failed to find powerLevels for room")
|
||||
return
|
||||
}
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
||||
let userPowerLevel = roomState.powerLevelOfUser(withUserID: userId)
|
||||
|
||||
guard userPowerLevel >= powerLevels.invite else {
|
||||
let alert = UIAlertController(title: VectorL10n.spacesInvitePeople, message: VectorL10n.spaceInviteNotEnoughPermission, preferredStyle: .alert)
|
||||
|
||||
@@ -165,11 +165,12 @@ extension SpaceMembersCoordinator: SpaceMemberListCoordinatorDelegate {
|
||||
spaceRoom.state { [weak self] roomState in
|
||||
guard let self = self else { return }
|
||||
|
||||
guard let powerLevels = roomState?.powerLevels, let userId = self.parameters.session.myUserId else {
|
||||
guard let roomState,
|
||||
let powerLevels = roomState.powerLevels, let userId = self.parameters.session.myUserId else {
|
||||
MXLog.error("[SpaceMembersCoordinator] spaceMemberListCoordinatorShowInvite: failed to find powerLevels for room")
|
||||
return
|
||||
}
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: userId)
|
||||
let userPowerLevel = roomState.powerLevelOfUser(withUserID: userId)
|
||||
|
||||
guard userPowerLevel >= powerLevels.invite else {
|
||||
let alert = UIAlertController(title: VectorL10n.spacesInvitePeople, message: VectorL10n.spaceInviteNotEnoughPermission, preferredStyle: .alert)
|
||||
|
||||
@@ -166,7 +166,7 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType {
|
||||
if let spaceRoom = self.spaceRoom {
|
||||
spaceRoom.state { roomState in
|
||||
self.powerLevels = roomState?.powerLevels
|
||||
self.powerLevelOfCurrentUser = self.powerLevels?.powerLevelOfUser(withUserID: self.session.myUserId)
|
||||
self.powerLevelOfCurrentUser = roomState?.powerLevelOfUser(withUserID: self.session.myUserId)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,8 +159,9 @@ final class LocationSharingCoordinator: Coordinator, Presentable {
|
||||
// Check if user can send beacon info state event
|
||||
private func canShareLiveLocation() -> Bool {
|
||||
guard let myUserId = parameters.roomDataSource.mxSession.myUserId,
|
||||
let roomPowerLevels = parameters.roomDataSource.roomState.powerLevels,
|
||||
let userPowerLevel = RoomPowerLevel(rawValue: roomPowerLevels.powerLevelOfUser(withUserID: myUserId)) else {
|
||||
let roomState = parameters.roomDataSource.roomState,
|
||||
let roomPowerLevels = roomState.powerLevels,
|
||||
let userPowerLevel = RoomPowerLevel(rawValue: roomState.powerLevelOfUser(withUserID: myUserId)) else {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -162,8 +162,10 @@ private class CompletionSuggestionCoordinatorRoomMemberProvider: RoomMembersProv
|
||||
/// Gets the power levels for the room to update suggestions accordingly.
|
||||
func updateWithPowerLevels() {
|
||||
room.state { [weak self] state in
|
||||
guard let self, let powerLevels = state?.powerLevels else { return }
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: self.userID)
|
||||
guard let self,
|
||||
let state,
|
||||
let powerLevels = state.powerLevels else { return }
|
||||
let userPowerLevel = state.powerLevelOfUser(withUserID: self.userID)
|
||||
let mentionRoomPowerLevel = powerLevels.minimumPowerLevel(forNotifications: kMXRoomPowerLevelNotificationsRoomKey,
|
||||
defaultPower: kMXRoomPowerLevelNotificationsRoomDefault)
|
||||
self.canMentionRoom = userPowerLevel >= mentionRoomPowerLevel
|
||||
@@ -208,9 +210,11 @@ private class CompletionSuggestionCoordinatorCommandProvider: CommandsProviderPr
|
||||
|
||||
func updateWithPowerLevels() {
|
||||
room.state { [weak self] state in
|
||||
guard let self, let powerLevels = state?.powerLevels else { return }
|
||||
guard let self,
|
||||
let state,
|
||||
let powerLevels = state.powerLevels else { return }
|
||||
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: self.userID)
|
||||
let userPowerLevel = state.powerLevelOfUser(withUserID: self.userID)
|
||||
self.isRoomAdmin = RoomPowerLevel(rawValue: userPowerLevel) == .admin
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,12 +150,12 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
return allowedParentIds
|
||||
}
|
||||
|
||||
private func isField(ofType notification: String, editableWith powerLevels: MXRoomPowerLevels?) -> Bool {
|
||||
guard let powerLevels = powerLevels else {
|
||||
private func isField(ofType notification: String, editableWith roomState: MXRoomState) -> Bool {
|
||||
guard let powerLevels = roomState.powerLevels else {
|
||||
return false
|
||||
}
|
||||
|
||||
let userPowerLevel = powerLevels.powerLevelOfUser(withUserID: session.myUserId)
|
||||
let userPowerLevel = roomState.powerLevelOfUser(withUserID: session.myUserId)
|
||||
return userPowerLevel >= powerLevels.minimumPowerLevel(forNotifications: notification, defaultPower: powerLevels.stateDefault)
|
||||
}
|
||||
|
||||
@@ -226,11 +226,11 @@ class SpaceSettingsService: SpaceSettingsServiceProtocol {
|
||||
avatarUrl: roomState.avatar,
|
||||
visibility: visibility(with: roomState),
|
||||
allowedParentIds: allowedParentIds(with: roomState),
|
||||
isAvatarEditable: isField(ofType: kMXEventTypeStringRoomAvatar, editableWith: roomState.powerLevels),
|
||||
isNameEditable: isField(ofType: kMXEventTypeStringRoomName, editableWith: roomState.powerLevels),
|
||||
isTopicEditable: isField(ofType: kMXEventTypeStringRoomTopic, editableWith: roomState.powerLevels),
|
||||
isAddressEditable: isField(ofType: kMXEventTypeStringRoomAliases, editableWith: roomState.powerLevels),
|
||||
isAccessEditable: isField(ofType: kMXEventTypeStringRoomJoinRules, editableWith: roomState.powerLevels)
|
||||
isAvatarEditable: isField(ofType: kMXEventTypeStringRoomAvatar, editableWith: roomState),
|
||||
isNameEditable: isField(ofType: kMXEventTypeStringRoomName, editableWith: roomState),
|
||||
isTopicEditable: isField(ofType: kMXEventTypeStringRoomTopic, editableWith: roomState),
|
||||
isAddressEditable: isField(ofType: kMXEventTypeStringRoomAliases, editableWith: roomState),
|
||||
isAccessEditable: isField(ofType: kMXEventTypeStringRoomJoinRules, editableWith: roomState)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -49,7 +49,6 @@ targets:
|
||||
PRODUCT_BUNDLE_IDENTIFIER: org.matrix.$(PRODUCT_NAME:rfc1034identifier)
|
||||
PRODUCT_NAME: RiotSwiftUnitTests
|
||||
configs:
|
||||
Debug:
|
||||
Release:
|
||||
PROVISIONING_PROFILE: $(RIOT_PROVISIONING_PROFILE)
|
||||
PROVISIONING_PROFILE_SPECIFIER: $(RIOT_PROVISIONING_PROFILE_SPECIFIER)
|
||||
|
||||
@@ -239,6 +239,24 @@ Please see LICENSE in the repository root for full details.
|
||||
XCTAssertFalse(hasAttachment, @"iFrame attachments should be removed as they're not included in the allowedHTMLTags array.");
|
||||
}
|
||||
|
||||
- (void)testMxExternalPaymentDetailsRemoved
|
||||
{
|
||||
// Given an HTML string containing a <span> with data-mx-external-payment-details.
|
||||
NSString *html = @"This is visible<span data-msc4286-external-payment-details>. But text is hidden <a href=\"https://matrix.org\">and this link too</a></span>";
|
||||
|
||||
// When rendering this string as an attributed string.
|
||||
NSAttributedString *attributedString = [eventFormatter renderHTMLString:html
|
||||
forEvent:anEvent
|
||||
withRoomState:nil
|
||||
andLatestRoomState:nil];
|
||||
|
||||
// Then the attributed string should have the <span> stripped and not include any attachments.
|
||||
XCTAssertEqualObjects(attributedString.string, @"This is visible", @"The <span data-msc4286-external-payment-details> tag content should be removed.");
|
||||
|
||||
BOOL hasAttachment = [attributedString containsAttachmentsInRange:NSMakeRange(0, attributedString.length)];
|
||||
XCTAssertFalse(hasAttachment, @"span attachments should be removed as they're not included in the allowedHTMLTags array.");
|
||||
}
|
||||
|
||||
- (void)testRenderHTMLStringWithMXReply
|
||||
{
|
||||
// Given an HTML string representing a matrix reply.
|
||||
|
||||
@@ -25,7 +25,8 @@ class EncryptionTrustLevelTests: XCTestCase {
|
||||
identity: .other(
|
||||
userId: "Bob",
|
||||
masterKey: "MSK",
|
||||
selfSigningKey: "SSK"
|
||||
selfSigningKey: "SSK",
|
||||
hasVerificationViolation: false
|
||||
),
|
||||
isVerified: isVerified
|
||||
)
|
||||
|
||||
@@ -52,7 +52,6 @@ targets:
|
||||
SWIFT_OBJC_BRIDGING_HEADER: RiotTests/RiotTests-Bridging-Header.h
|
||||
TEST_HOST: $(BUILT_PRODUCTS_DIR)/Element.app/Element
|
||||
configs:
|
||||
Debug:
|
||||
Release:
|
||||
PROVISIONING_PROFILE: $(RIOT_PROVISIONING_PROFILE)
|
||||
PROVISIONING_PROFILE_SPECIFIER: $(RIOT_PROVISIONING_PROFILE_SPECIFIER)
|
||||
|
||||
Submodule matrix-ios-sdk updated: 6a49ee70a5...b0f967c9c8
Reference in New Issue
Block a user