Merge branch 'develop' into create_button_size

This commit is contained in:
manuroe 2019-06-19 15:42:40 +02:00 committed by GitHub
commit f155f99374
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
55 changed files with 1614 additions and 511 deletions

View file

@ -10,9 +10,11 @@ Improvements:
* Context menu polish (#2466). * Context menu polish (#2466).
Bug fix: Bug fix:
* Registration with an email is broken (#2417).
* Device Verification: Fix user display name and device id colors in dark theme * Device Verification: Fix user display name and device id colors in dark theme
* Adjust size of the insert button in the People tab * Registration with an email is broken (#2417).
* Reactions: Bad position (#2462).
* Reactions: It lets you react to join/leave events (#2476).
* Adjust size of the insert button in the People tab, thanks to @dcordero (PR #2473).
Changes in 0.8.6 (2019-05-06) Changes in 0.8.6 (2019-05-06)
=============================================== ===============================================
@ -51,7 +53,7 @@ Changes in 0.8.4 (2019-03-21)
Improvements: Improvements:
* Upgrade MatrixKit version ([v0.9.8](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.8)). * Upgrade MatrixKit version ([v0.9.8](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.8)).
* Share extension: Remove image large size resizing choice if output dimension is too high to prevent memory limit exception (PR #2342). * Share extension: Remove image large size resizing choice if output dimension is too high to prevent memory limit exception (PR #2342).
Bug fix: Bug fix:
* Unable to open a file attachment of a room message (#2338). * Unable to open a file attachment of a room message (#2338).
@ -60,7 +62,7 @@ Changes in 0.8.3 (2019-03-13)
Improvements: Improvements:
* Upgrade MatrixKit version ([v0.9.7](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.7)). * Upgrade MatrixKit version ([v0.9.7](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.7)).
Bug fix: Bug fix:
* Widgets: Attempt to re-register for a scalar token if ours is invalid (#2326). * Widgets: Attempt to re-register for a scalar token if ours is invalid (#2326).
* Widgets: Pass scalar_token only when required. * Widgets: Pass scalar_token only when required.
@ -122,7 +124,7 @@ Improvements:
* Key backup: Update key backup setup UI and UX (PR #2243). * Key backup: Update key backup setup UI and UX (PR #2243).
* Key backup: Logout warning (#2245). * Key backup: Logout warning (#2245).
* Key backup: new recover method detected (#2230). * Key backup: new recover method detected (#2230).
Bug fix: Bug fix:
* Use white scroll bar on dark themes (#2158). * Use white scroll bar on dark themes (#2158).
* Registration: fix tap gesture on checkboxes in the terms screen. * Registration: fix tap gesture on checkboxes in the terms screen.

12
Podfile
View file

@ -63,16 +63,14 @@ abstract_target 'RiotPods' do
pod 'Reusable', '~> 4.0' pod 'Reusable', '~> 4.0'
# Piwik for analytics # Piwik for analytics
# While https://github.com/matomo-org/matomo-sdk-ios/pull/223 is not released, use the PR branch pod 'MatomoTracker', '~> 6.0.1'
pod 'PiwikTracker', :git => 'https://github.com/manuroe/matomo-sdk-ios.git', :branch => 'feature/CustomVariables'
#pod 'PiwikTracker', '~> 4.4.2'
# Remove warnings from "bad" pods # Remove warnings from "bad" pods
pod 'OLMKit', :inhibit_warnings => true pod 'OLMKit', :inhibit_warnings => true
pod 'cmark', :inhibit_warnings => true pod 'cmark', :inhibit_warnings => true
pod 'DTCoreText', :inhibit_warnings => true pod 'DTCoreText', :inhibit_warnings => true
pod 'zxcvbn-ios' pod 'zxcvbn-ios'
# Tools # Tools
pod 'SwiftGen', '~> 6.1' pod 'SwiftGen', '~> 6.1'
pod 'SwiftLint', '~> 0.30.1' pod 'SwiftLint', '~> 0.30.1'
@ -101,13 +99,7 @@ post_install do |installer|
# Plus the app does not enable it # Plus the app does not enable it
target.build_configurations.each do |config| target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO' config.build_settings['ENABLE_BITCODE'] = 'NO'
# Required for PiwikTracker as `swift_version` is not defined in podspec. Should be removed
if target.name.include? 'PiwikTracker'
config.build_settings['SWIFT_VERSION'] = '4.0'
end
end end
end end
end end

View file

@ -15,6 +15,7 @@ PODS:
- AFNetworking/UIKit (3.2.1): - AFNetworking/UIKit (3.2.1):
- AFNetworking/NSURLSession - AFNetworking/NSURLSession
- cmark (0.24.1) - cmark (0.24.1)
- DGCollectionViewLeftAlignFlowLayout (1.0.4)
- DTCoreText (1.6.21): - DTCoreText (1.6.21):
- DTCoreText/Core (= 1.6.21) - DTCoreText/Core (= 1.6.21)
- DTFoundation/Core (~> 1.7.5) - DTFoundation/Core (~> 1.7.5)
@ -45,6 +46,9 @@ PODS:
- JitsiMeetSDK (2.1.0) - JitsiMeetSDK (2.1.0)
- libbase58 (0.1.4) - libbase58 (0.1.4)
- libPhoneNumber-iOS (0.9.13) - libPhoneNumber-iOS (0.9.13)
- MatomoTracker (6.0.1):
- MatomoTracker/Core (= 6.0.1)
- MatomoTracker/Core (6.0.1)
- MatrixKit (0.9.9): - MatrixKit (0.9.9):
- cmark (~> 0.24.1) - cmark (~> 0.24.1)
- DTCoreText (~> 1.6.21) - DTCoreText (~> 1.6.21)
@ -83,9 +87,6 @@ PODS:
- OLMKit/olmcpp (= 3.1.0) - OLMKit/olmcpp (= 3.1.0)
- OLMKit/olmc (3.1.0) - OLMKit/olmc (3.1.0)
- OLMKit/olmcpp (3.1.0) - OLMKit/olmcpp (3.1.0)
- PiwikTracker (4.4.2):
- PiwikTracker/Core (= 4.4.2)
- PiwikTracker/Core (4.4.2)
- Realm (3.13.1): - Realm (3.13.1):
- Realm/Headers (= 3.13.1) - Realm/Headers (= 3.13.1)
- Realm/Headers (3.13.1) - Realm/Headers (3.13.1)
@ -100,14 +101,15 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- cmark - cmark
- DGCollectionViewLeftAlignFlowLayout (~> 1.0.4)
- DTCoreText - DTCoreText
- GBDeviceInfo (~> 5.2.0) - GBDeviceInfo (~> 5.2.0)
- MatomoTracker (~> 6.0.1)
- MatrixKit (= 0.9.9) - MatrixKit (= 0.9.9)
- MatrixKit/AppExtension (= 0.9.9) - MatrixKit/AppExtension (= 0.9.9)
- MatrixSDK/JingleCallStack - MatrixSDK/JingleCallStack
- MatrixSDK/SwiftSupport - MatrixSDK/SwiftSupport
- OLMKit - OLMKit
- PiwikTracker (from `https://github.com/manuroe/matomo-sdk-ios.git`, branch `feature/CustomVariables`)
- Reusable (~> 4.0) - Reusable (~> 4.0)
- SwiftGen (~> 6.1) - SwiftGen (~> 6.1)
- SwiftLint (~> 0.30.1) - SwiftLint (~> 0.30.1)
@ -117,6 +119,7 @@ SPEC REPOS:
https://github.com/cocoapods/specs.git: https://github.com/cocoapods/specs.git:
- AFNetworking - AFNetworking
- cmark - cmark
- DGCollectionViewLeftAlignFlowLayout
- DTCoreText - DTCoreText
- DTFoundation - DTFoundation
- GBDeviceInfo - GBDeviceInfo
@ -125,6 +128,7 @@ SPEC REPOS:
- JitsiMeetSDK - JitsiMeetSDK
- libbase58 - libbase58
- libPhoneNumber-iOS - libPhoneNumber-iOS
- MatomoTracker
- MatrixKit - MatrixKit
- MatrixSDK - MatrixSDK
- OLMKit - OLMKit
@ -134,19 +138,10 @@ SPEC REPOS:
- SwiftLint - SwiftLint
- zxcvbn-ios - zxcvbn-ios
EXTERNAL SOURCES:
PiwikTracker:
:branch: feature/CustomVariables
:git: https://github.com/manuroe/matomo-sdk-ios.git
CHECKOUT OPTIONS:
PiwikTracker:
:commit: dfb048f25f4eefbe13ff7515c3c1c2cad5d94491
:git: https://github.com/manuroe/matomo-sdk-ios.git
SPEC CHECKSUMS: SPEC CHECKSUMS:
AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057 AFNetworking: b6f891fdfaed196b46c7a83cf209e09697b94057
cmark: ec0275215b504780287b6fca360224e384368af8 cmark: ec0275215b504780287b6fca360224e384368af8
DGCollectionViewLeftAlignFlowLayout: a0fa58797373ded039cafba8133e79373d048399
DTCoreText: e5d688cffc9f6a61eddd1a4f94e2046851230de3 DTCoreText: e5d688cffc9f6a61eddd1a4f94e2046851230de3
DTFoundation: f03be9fd786f11e505bb8fc44e2a3732bf0917df DTFoundation: f03be9fd786f11e505bb8fc44e2a3732bf0917df
GBDeviceInfo: 2c65ceb9404f9079264d4c238f5b81916fdfc5e2 GBDeviceInfo: 2c65ceb9404f9079264d4c238f5b81916fdfc5e2
@ -155,16 +150,16 @@ SPEC CHECKSUMS:
JitsiMeetSDK: 3e66564af7f38a19142338955dd7f581801852b3 JitsiMeetSDK: 3e66564af7f38a19142338955dd7f581801852b3
libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd libbase58: 7c040313537b8c44b6e2d15586af8e21f7354efd
libPhoneNumber-iOS: e444379ac18bbfbdefad571da735b2cd7e096caa libPhoneNumber-iOS: e444379ac18bbfbdefad571da735b2cd7e096caa
MatomoTracker: 3ae4f65a1f5ace8043bda7244888fee28a734de5
MatrixKit: 6f553797e1ad42794b5336afb5cecb975ec69daa MatrixKit: 6f553797e1ad42794b5336afb5cecb975ec69daa
MatrixSDK: ed0d0cee4877955052f19730bb3ee727e01ec948 MatrixSDK: ed0d0cee4877955052f19730bb3ee727e01ec948
OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639 OLMKit: 4ee0159d63feeb86d836fdcfefe418e163511639
PiwikTracker: 42862c7b13028065c3dfd36b4dc38db8a5765acf
Realm: 50071da38fe079e0735e47c9f2eae738c68c5996 Realm: 50071da38fe079e0735e47c9f2eae738c68c5996
Reusable: 188be1a54ac0691bc66e5bb24ec6eb91971b315b Reusable: 188be1a54ac0691bc66e5bb24ec6eb91971b315b
SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0 SwiftGen: f872ca75cbd17bf7103c17f13dcfa0d9a15667b0
SwiftLint: a54bf1fe12b55c68560eb2a7689dfc81458508f7 SwiftLint: a54bf1fe12b55c68560eb2a7689dfc81458508f7
zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c
PODFILE CHECKSUM: cfb6be050dfbb227d58b14434629e447ea54554b PODFILE CHECKSUM: 16b6518b09d4e3af0af46ed9c1338e9df8674aff
COCOAPODS: 1.6.1 COCOAPODS: 1.6.1

View file

@ -205,6 +205,7 @@
B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */; }; B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */; };
B19EFA3B21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */; }; B19EFA3B21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */; };
B1A5B33E227ADF2A004CBA85 /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1A5B33D227ADF2A004CBA85 /* UIImage.swift */; }; B1A5B33E227ADF2A004CBA85 /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1A5B33D227ADF2A004CBA85 /* UIImage.swift */; };
B1A68593229E807A00D6C09A /* RoomBubbleCellLayout.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1A68592229E807800D6C09A /* RoomBubbleCellLayout.swift */; };
B1B12B2922942315002CB419 /* UITouch.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B12B2822942315002CB419 /* UITouch.swift */; }; B1B12B2922942315002CB419 /* UITouch.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B12B2822942315002CB419 /* UITouch.swift */; };
B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */; }; B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */; };
B1B5571920EE6C4D00210D55 /* LanguagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567C20EE6C4C00210D55 /* LanguagePickerViewController.m */; }; B1B5571920EE6C4D00210D55 /* LanguagePickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567C20EE6C4C00210D55 /* LanguagePickerViewController.m */; };
@ -804,6 +805,7 @@
B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinatorType.swift; sourceTree = "<group>"; }; B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinatorType.swift; sourceTree = "<group>"; };
B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinator.swift; sourceTree = "<group>"; }; B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyBackupRecoverCoordinator.swift; sourceTree = "<group>"; };
B1A5B33D227ADF2A004CBA85 /* UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = "<group>"; }; B1A5B33D227ADF2A004CBA85 /* UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = "<group>"; };
B1A68592229E807800D6C09A /* RoomBubbleCellLayout.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoomBubbleCellLayout.swift; sourceTree = "<group>"; };
B1B12B2822942315002CB419 /* UITouch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITouch.swift; sourceTree = "<group>"; }; B1B12B2822942315002CB419 /* UITouch.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UITouch.swift; sourceTree = "<group>"; };
B1B5567920EE6C4C00210D55 /* CountryPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryPickerViewController.h; sourceTree = "<group>"; }; B1B5567920EE6C4C00210D55 /* CountryPickerViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CountryPickerViewController.h; sourceTree = "<group>"; };
B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryPickerViewController.m; sourceTree = "<group>"; }; B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CountryPickerViewController.m; sourceTree = "<group>"; };
@ -2885,6 +2887,7 @@
B1B5584220EF768E00210D55 /* Encryption */ = { B1B5584220EF768E00210D55 /* Encryption */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
B1A68592229E807800D6C09A /* RoomBubbleCellLayout.swift */,
B1B5584320EF768E00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h */, B1B5584320EF768E00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h */,
B1B5584420EF768E00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h */, B1B5584420EF768E00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h */,
B1B5584520EF768E00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.h */, B1B5584520EF768E00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.h */,
@ -3688,10 +3691,10 @@
"${BUILT_PRODUCTS_DIR}/HPGrowingTextView/HPGrowingTextView.framework", "${BUILT_PRODUCTS_DIR}/HPGrowingTextView/HPGrowingTextView.framework",
"${PODS_ROOT}/JitsiMeetSDK/Frameworks/JitsiMeet.framework", "${PODS_ROOT}/JitsiMeetSDK/Frameworks/JitsiMeet.framework",
"${PODS_ROOT}/JitsiMeetSDK/Frameworks/WebRTC.framework", "${PODS_ROOT}/JitsiMeetSDK/Frameworks/WebRTC.framework",
"${BUILT_PRODUCTS_DIR}/MatomoTracker/MatomoTracker.framework",
"${BUILT_PRODUCTS_DIR}/MatrixKit/MatrixKit.framework", "${BUILT_PRODUCTS_DIR}/MatrixKit/MatrixKit.framework",
"${BUILT_PRODUCTS_DIR}/MatrixSDK.common-JingleCallStack/MatrixSDK.framework", "${BUILT_PRODUCTS_DIR}/MatrixSDK.common-JingleCallStack/MatrixSDK.framework",
"${BUILT_PRODUCTS_DIR}/OLMKit/OLMKit.framework", "${BUILT_PRODUCTS_DIR}/OLMKit/OLMKit.framework",
"${BUILT_PRODUCTS_DIR}/PiwikTracker/PiwikTracker.framework",
"${BUILT_PRODUCTS_DIR}/Realm/Realm.framework", "${BUILT_PRODUCTS_DIR}/Realm/Realm.framework",
"${BUILT_PRODUCTS_DIR}/Reusable/Reusable.framework", "${BUILT_PRODUCTS_DIR}/Reusable/Reusable.framework",
"${BUILT_PRODUCTS_DIR}/cmark/cmark.framework", "${BUILT_PRODUCTS_DIR}/cmark/cmark.framework",
@ -3714,10 +3717,10 @@
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HPGrowingTextView.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/HPGrowingTextView.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JitsiMeet.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/JitsiMeet.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/WebRTC.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MatomoTracker.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MatrixKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MatrixKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MatrixSDK.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MatrixSDK.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OLMKit.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/OLMKit.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/PiwikTracker.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Realm.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reusable.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Reusable.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cmark.framework", "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cmark.framework",
@ -3920,6 +3923,7 @@
B1B558E820EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */, B1B558E820EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */,
B1B558F320EF768F00210D55 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */, B1B558F320EF768F00210D55 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
B1B557BD20EF5B4500210D55 /* KeyboardGrowingTextView.m in Sources */, B1B557BD20EF5B4500210D55 /* KeyboardGrowingTextView.m in Sources */,
B1A68593229E807A00D6C09A /* RoomBubbleCellLayout.swift in Sources */,
B1B558F420EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */, B1B558F420EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
B1B5572320EE6C4D00210D55 /* AttachmentsViewController.m in Sources */, B1B5572320EE6C4D00210D55 /* AttachmentsViewController.m in Sources */,
F083BDEE1E7009ED00A9B29C /* MXRoom+Riot.m in Sources */, F083BDEE1E7009ED00A9B29C /* MXRoom+Riot.m in Sources */,

View file

@ -3,3 +3,4 @@
"NSPhotoLibraryUsageDescription" = "Галерията се използва, за да се изпращат снимки и видеа."; "NSPhotoLibraryUsageDescription" = "Галерията се използва, за да се изпращат снимки и видеа.";
"NSMicrophoneUsageDescription" = "Микрофонът се използва, за да се правят видеа и да се водят разговори."; "NSMicrophoneUsageDescription" = "Микрофонът се използва, за да се правят видеа и да се водят разговори.";
"NSContactsUsageDescription" = "За да покажем кои от контактите Ви използват Riot или Matrix, можем да изпратим имейл адресите и телефонните номера от телефонния указател към Matrix сървъра за самоличност. Компания New Vector не складира тези данни и не ги използва за никаква друга цел. За повече информация, вижте политиката за поверителност в настройките."; "NSContactsUsageDescription" = "За да покажем кои от контактите Ви използват Riot или Matrix, можем да изпратим имейл адресите и телефонните номера от телефонния указател към Matrix сървъра за самоличност. Компания New Vector не складира тези данни и не ги използва за никаква друга цел. За повече информация, вижте политиката за поверителност в настройките.";
"NSCalendarsUsageDescription" = "Вижте насрочените срещи в приложението.";

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Съобщение от %@"; "MSG_FROM_USER" = "%@ изпрати съобщение";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ публикува в %@"; "MSG_FROM_USER_IN_ROOM" = "%@ публикува в %@";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ Ви изпрати снимка %@"; "IMAGE_FROM_USER" = "%@ изпрати снимка %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ публикува снимка %@ в %@"; "IMAGE_FROM_USER_IN_ROOM" = "%@ публикува снимка %@ в %@";
/* A single unread message in a room */ /* A single unread message in a room */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Групово повикване от %@: '%@'"; "VOICE_CONF_NAMED_FROM_USER" = "Групово повикване от %@: '%@'";
/* Incoming named video conference invite from a specific person */ /* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Групово видео повикване от %@: '%@'"; "VIDEO_CONF_NAMED_FROM_USER" = "Групово видео повикване от %@: '%@'";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ в %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ изпрати стикер";

View file

@ -76,14 +76,14 @@
"auth_msisdn_validation_title" = "Очакване на потвърждение"; "auth_msisdn_validation_title" = "Очакване на потвърждение";
"auth_msisdn_validation_message" = "Изпратихме Ви SMS с код за активиране. Моля, въведете този код по-долу."; "auth_msisdn_validation_message" = "Изпратихме Ви SMS с код за активиране. Моля, въведете този код по-долу.";
"auth_msisdn_validation_error" = "Неуспешно потвърждение на телефонен номер."; "auth_msisdn_validation_error" = "Неуспешно потвърждение на телефонен номер.";
"auth_recaptcha_message" = "Този Home сървър би искал да се увери, че не сте робот"; "auth_recaptcha_message" = "Този сървър би искал да се увери, че не сте робот";
"auth_reset_password_message" = "За да възстановите Вашата парола, въведете имейл адреса, свързан с профила Ви:"; "auth_reset_password_message" = "За да възстановите Вашата парола, въведете имейл адреса, свързан с профила Ви:";
"auth_reset_password_missing_email" = "Имейл адресът, свързан с профила Ви, трябва да бъде въведен."; "auth_reset_password_missing_email" = "Имейл адресът, свързан с профила Ви, трябва да бъде въведен.";
"auth_reset_password_missing_password" = "Трябва да бъде въведена нова парола."; "auth_reset_password_missing_password" = "Трябва да бъде въведена нова парола.";
"auth_reset_password_email_validation_message" = "Имейл беше изпратен на %@. След като проследите връзката, която съдържа, натиснете по-долу."; "auth_reset_password_email_validation_message" = "Имейл беше изпратен на %@. След като проследите връзката, която съдържа, натиснете по-долу.";
"auth_reset_password_next_step_button" = "Потвърдих имейл адреса си"; "auth_reset_password_next_step_button" = "Потвърдих имейл адреса си";
"auth_reset_password_error_unauthorized" = "Неуспешно потвърждаване на имейл адреса: уверете се, че сте кликнали върху връзката в имейла"; "auth_reset_password_error_unauthorized" = "Неуспешно потвърждаване на имейл адреса: уверете се, че сте кликнали върху връзката в имейла";
"auth_reset_password_error_not_found" = "Изглежда вашият имейл адрес не може да се асоциира с Matrix ID на този Home сървър."; "auth_reset_password_error_not_found" = "Изглежда имейл адресът Ви не принадлежи на Matrix потребител от този сървър.";
"auth_reset_password_success_message" = "Вашата парола беше възстановена.\n\nВие сте излязли от профила си от всички устройства и вече няма да получавате известия. За да включите известията отново, влезте в профила си от всички устройства."; "auth_reset_password_success_message" = "Вашата парола беше възстановена.\n\nВие сте излязли от профила си от всички устройства и вече няма да получавате известия. За да включите известията отново, влезте в профила си от всички устройства.";
"auth_add_email_and_phone_warning" = "Регистрация с имейл и телефонен номер наведнъж не се поддържа в момента. Само телефонен номер се взима под внимание. Можете да добавите имейл към профила си в настройките."; "auth_add_email_and_phone_warning" = "Регистрация с имейл и телефонен номер наведнъж не се поддържа в момента. Само телефонен номер се взима под внимание. Можете да добавите имейл към профила си в настройките.";
// Chat creation // Chat creation
@ -562,7 +562,7 @@
"settings_key_backup_info_version" = "Версия на резервното копие на ключовете: %@"; "settings_key_backup_info_version" = "Версия на резервното копие на ключовете: %@";
"settings_key_backup_info_algorithm" = "Алгоритъм: %@"; "settings_key_backup_info_algorithm" = "Алгоритъм: %@";
"settings_key_backup_info_valid" = "Това устройство прави резервно копие на ключовете Ви."; "settings_key_backup_info_valid" = "Това устройство прави резервно копие на ключовете Ви.";
"settings_key_backup_info_not_valid" = "Това устройство не прави резервно копие на ключовете Ви."; "settings_key_backup_info_not_valid" = "Това устройство не прави резервно копие на ключовете Ви, но имате съществуващо резервно копие, от което да възстановявате или допълвате в бъдеще.";
"settings_key_backup_info_progress" = "Правене на резервно копие на %@ ключа..."; "settings_key_backup_info_progress" = "Правене на резервно копие на %@ ключа...";
"settings_key_backup_info_progress_done" = "Има резервно копие на всички ключове"; "settings_key_backup_info_progress_done" = "Има резервно копие на всички ключове";
"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "За да използвате Възстановяване на Защитени Съобщения на това устройство, потвърдете %@ сега."; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "За да използвате Възстановяване на Защитени Съобщения на това устройство, потвърдете %@ сега.";
@ -624,7 +624,7 @@
"key_backup_recover_banner_title_part1" = "Стартирайте Възстановяване на Защитени Съобщения"; "key_backup_recover_banner_title_part1" = "Стартирайте Възстановяване на Защитени Съобщения";
"key_backup_recover_banner_title_part2" = " за да четете шифрованата история на съобщенията на това устройство"; "key_backup_recover_banner_title_part2" = " за да четете шифрованата история на съобщенията на това устройство";
"settings_key_backup_info" = "Шифрованите съобщения са защитени с шифроване от край до край. Само Вие и получателят (получателите) имате ключове за прочитането им."; "settings_key_backup_info" = "Шифрованите съобщения са защитени с шифроване от край до край. Само Вие и получателят (получателите) имате ключове за прочитането им.";
"settings_key_backup_info_signout_warning" = "Направете копие на ключовете преди да излезете от профила, за да не ги загубите."; "settings_key_backup_info_signout_warning" = "Свържете това устройство с резервно копие за ключове преди да излезете от профила, за да не изгубите ключовете намиращи се само на устройството.";
"settings_key_backup_button_use" = "Използвай резервно копие на ключовете"; "settings_key_backup_button_use" = "Използвай резервно копие на ключовете";
// Key backup wrong version // Key backup wrong version
"e2e_key_backup_wrong_version_title" = "Ново резервно копие на ключовете"; "e2e_key_backup_wrong_version_title" = "Ново резервно копие на ключовете";
@ -673,3 +673,106 @@
"store_full_description" = "Комуникирай по свой начин.\n\nЧат приложение, което е изцяло гъвкаво и под Ваш контрол. Riot позволява да комуникирате по начина, по който искате. Направено за [matrix] - стандарт за отворена и децентрализирана комуникация.\n\nИзползвайте безплатен matrix.org акаунт, собствен сървър от https://modular.im или друг Matrix сървър.\n\nЗащо да изберете Riot.im?\n\n• ПЪЛНА КОМУНИКАЦИЯ: Създавайте каквито пожелаете чат стаи - свързани с работни екипи, приятели или друг вид общности! Чатете, споделяйте файлове, добавяйте приспособления и водете аудио и видео разговори - всичко това, изцяло безплатно.\n\n• МОЩНИ ИНТЕГРАЦИИ: Използвайте Riot.im с досега-познатите Ви инструменти. Посредством Riot.im дори можете да чатите с потребители и групи използващи други чат приложения.\n\n• ЛИЧНО И ЗАЩИТЕНО: Пазете комуникацията си в тайна. Съвременна технология за шифроване от край до край гарантира, че Вашата комуникацията наистина остава Ваша.\n\n• ОТВОРЕНО, А НЕ ЗАТВОРЕНО: Приложение с отворен код, изградено върху Matrix. Дръжте данните си под Ваш контрол, като използвате Ваш собствен сървър или като изберете сървър, на който вярвате.\n\n• КЪДЕТО И ДА СТЕ: Поддържайте връзка където и да сте, с напълно синхронизирана чат история на всички Ваши устройства или онлайн на https://riot.im."; "store_full_description" = "Комуникирай по свой начин.\n\nЧат приложение, което е изцяло гъвкаво и под Ваш контрол. Riot позволява да комуникирате по начина, по който искате. Направено за [matrix] - стандарт за отворена и децентрализирана комуникация.\n\nИзползвайте безплатен matrix.org акаунт, собствен сървър от https://modular.im или друг Matrix сървър.\n\nЗащо да изберете Riot.im?\n\n• ПЪЛНА КОМУНИКАЦИЯ: Създавайте каквито пожелаете чат стаи - свързани с работни екипи, приятели или друг вид общности! Чатете, споделяйте файлове, добавяйте приспособления и водете аудио и видео разговори - всичко това, изцяло безплатно.\n\n• МОЩНИ ИНТЕГРАЦИИ: Използвайте Riot.im с досега-познатите Ви инструменти. Посредством Riot.im дори можете да чатите с потребители и групи използващи други чат приложения.\n\n• ЛИЧНО И ЗАЩИТЕНО: Пазете комуникацията си в тайна. Съвременна технология за шифроване от край до край гарантира, че Вашата комуникацията наистина остава Ваша.\n\n• ОТВОРЕНО, А НЕ ЗАТВОРЕНО: Приложение с отворен код, изградено върху Matrix. Дръжте данните си под Ваш контрол, като използвате Ваш собствен сървър или като изберете сървър, на който вярвате.\n\n• КЪДЕТО И ДА СТЕ: Поддържайте връзка където и да сте, с напълно синхронизирана чат история на всички Ваши устройства или онлайн на https://riot.im.";
"auth_autodiscover_invalid_response" = "Невалиден отговор при опит за откриване на адреса на сървъра"; "auth_autodiscover_invalid_response" = "Невалиден отговор при опит за откриване на адреса на сървъра";
"room_message_unable_open_link_error_message" = "Неуспешно отваряне на връзката."; "room_message_unable_open_link_error_message" = "Неуспешно отваряне на връзката.";
"room_event_action_reply" = "Отговори";
"room_event_action_edit" = "Редактирай";
"auth_login_single_sign_on" = "Влез със SSO";
"room_event_action_reaction_agree" = "Съгласи се с %@";
"room_event_action_reaction_disagree" = "Противоречи на %@";
"room_event_action_reaction_like" = "Харесай %@";
"room_event_action_reaction_dislike" = "Не харесай %@";
"room_action_reply" = "Отговори";
"settings_labs_message_reaction" = "Реагирай на съобщения с емоджи";
"settings_key_backup_button_connect" = "Свържи устройството към резервно копие на ключове";
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Свържи устройството към резервно копие на ключове";
"key_backup_recover_connent_banner_subtitle" = "Свържи устройството към резервно копие на ключове";
// MARK: - Device Verification
"device_verification_title" = "Потвърждение на устройство";
"device_verification_security_advice" = "За максимална сигурност, препоръчваме да правите това на живо или използвайки друг защитен начин за комуникация";
"device_verification_cancelled" = "Отсрещната страна отказа потвърждението.";
"device_verification_cancelled_by_me" = "Потвърждението беше отказано. Причина: %@";
"device_verification_error_cannot_load_device" = "Неуспешно зареждане на информация за устройството.";
// Mark: Incoming
"device_verification_incoming_title" = "Входяща заявка за потвърждение";
"device_verification_incoming_description_1" = "Потвърдете това устройство за да го маркирате като доверено. Доверяването на устройства на партньори Ви дава допълнително спокойствие когато използвате шифроване от-край-до-край.";
"device_verification_incoming_description_2" = "Потвърждаването на устройството ще го маркира като доверено и ще маркира Вашето като доверено при партньора.";
// MARK: Start
"device_verification_start_title" = "Потвърждение чрез сравняване на кратък текст";
"device_verification_start_wait_partner" = "Изчакване на партньора да приеме...";
"device_verification_start_use_legacy" = "Не се показва нищо? Засега не всички клиенти поддържат интерактивно потвърждение. Използвайте стария метод за потвърждение.";
"device_verification_start_verify_button" = "Започни потвърждение";
"device_verification_start_use_legacy_action" = "Потвърди по стария метод";
// MARK: Verify
"device_verification_verify_title_emoji" = "Потвърдете това устройство като се уверите че следните емоджита се повяват на екрана на партньора";
"device_verification_verify_title_number" = "Потвърдете това устройство като се уверите че следните числа се повяват на екрана на партньора";
"device_verification_verify_wait_partner" = "Изчакване на потвърждение от партньора...";
// MARK: Verified
"device_verification_verified_title" = "Потвърдено!";
"device_verification_verified_description_1" = "Успешно потвърдихте това устройство.";
"device_verification_verified_description_2" = "Защитените съобщения с този потребител са шифровани от край до край и не могат да бъдат прочетени от трети лица.";
"device_verification_verified_got_it_button" = "Разбрах";
// MARK: Emoji
"device_verification_emoji_dog" = "Куче";
"device_verification_emoji_cat" = "Котка";
"device_verification_emoji_lion" = "Лъв";
"device_verification_emoji_horse" = "Кон";
"device_verification_emoji_unicorn" = "Еднорог";
"device_verification_emoji_pig" = "Прасее";
"device_verification_emoji_elephant" = "Слон";
"device_verification_emoji_rabbit" = "Заек";
"device_verification_emoji_panda" = "Панда";
"device_verification_emoji_rooster" = "Петел";
"device_verification_emoji_penguin" = "Пингвин";
"device_verification_emoji_turtle" = "Костенурка";
"device_verification_emoji_fish" = "Риба";
"device_verification_emoji_octopus" = "Октопод";
"device_verification_emoji_butterfly" = "Пеперуда";
"device_verification_emoji_flower" = "Цвете";
"device_verification_emoji_tree" = "Дърво";
"device_verification_emoji_cactus" = "Кактус";
"device_verification_emoji_mushroom" = "Гъба";
"device_verification_emoji_globe" = "Глобус";
"device_verification_emoji_moon" = "Луна";
"device_verification_emoji_cloud" = "Облак";
"device_verification_emoji_fire" = "Огън";
"device_verification_emoji_banana" = "Банан";
"device_verification_emoji_apple" = "Ябълка";
"device_verification_emoji_strawberry" = "Ягода";
"device_verification_emoji_corn" = "Царевица";
"device_verification_emoji_pizza" = "Пица";
"device_verification_emoji_cake" = "Торта";
"device_verification_emoji_heart" = "Сърце";
"device_verification_emoji_smiley" = "Усмивка";
"device_verification_emoji_robot" = "Робот";
"device_verification_emoji_hat" = "Шапка";
"device_verification_emoji_glasses" = "Очила";
"device_verification_emoji_spanner" = "Гаечен ключ";
"device_verification_emoji_santa" = "Дядо Коледа";
"device_verification_emoji_thumbs up" = "Палец нагоре";
"device_verification_emoji_umbrella" = "Чадър";
"device_verification_emoji_hourglass" = "Пясъчен часовник";
"device_verification_emoji_clock" = "Часовник";
"device_verification_emoji_gift" = "Подарък";
"device_verification_emoji_light bulb" = "Лампа";
"device_verification_emoji_book" = "Книга";
"device_verification_emoji_pencil" = "Молив";
"device_verification_emoji_paperclip" = "Кламер";
"device_verification_emoji_scissors" = "Ножици";
"device_verification_emoji_padlock" = "Катинар";
"device_verification_emoji_key" = "Ключ";
"device_verification_emoji_hammer" = "Чук";
"device_verification_emoji_telephone" = "Телефон";
"device_verification_emoji_flag" = "Знаме";
"device_verification_emoji_train" = "Влак";
"device_verification_emoji_bicycle" = "Колело";
"device_verification_emoji_aeroplane" = "Самолет";
"device_verification_emoji_rocket" = "Ракета";
"device_verification_emoji_trophy" = "Трофей";
"device_verification_emoji_ball" = "Топка";
"device_verification_emoji_guitar" = "Китара";
"device_verification_emoji_trumpet" = "Тромпет";
"device_verification_emoji_bell" = "Звънец";
"device_verification_emoji_anchor" = "Котва";
"device_verification_emoji_headphones" = "Слушалки";
"device_verification_emoji_folder" = "Папка";
"device_verification_emoji_pin" = "Карфица";
"event_formatter_message_edited_mention" = "(Редактирано)";

View file

@ -3,3 +3,4 @@
"NSPhotoLibraryUsageDescription" = "Die Foto-Bibliothek wird verwendet um Fotos und Videos zu senden."; "NSPhotoLibraryUsageDescription" = "Die Foto-Bibliothek wird verwendet um Fotos und Videos zu senden.";
"NSMicrophoneUsageDescription" = "Das Mikrofon wird verwendet um Videos aufzunehmen sowie Gespräche zu führen."; "NSMicrophoneUsageDescription" = "Das Mikrofon wird verwendet um Videos aufzunehmen sowie Gespräche zu führen.";
"NSContactsUsageDescription" = "Um dir zu zeigen, welche deiner Kontakte bereits Riot oder Matrix benutzen, können wir die E-Mail-Adressen und Telefonnummern deines Adressbuches an deinen Matrix-Identitätsserver senden. New Vector speichert diese Daten nicht und nutzt sie auch für keine anderen Zwecke. Für mehr Informationen sieh dir bitte die Datenschutz-Seite in den App-Einstellungen an."; "NSContactsUsageDescription" = "Um dir zu zeigen, welche deiner Kontakte bereits Riot oder Matrix benutzen, können wir die E-Mail-Adressen und Telefonnummern deines Adressbuches an deinen Matrix-Identitätsserver senden. New Vector speichert diese Daten nicht und nutzt sie auch für keine anderen Zwecke. Für mehr Informationen sieh dir bitte die Datenschutz-Seite in den App-Einstellungen an.";
"NSCalendarsUsageDescription" = "Sieh dir deine geplanten Meetings in der App an.";

View file

@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ sendet dir ein Bild %@"; "IMAGE_FROM_USER" = "%@ hat ein Bild gesendet %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ sendet ein Bild %@ in %@"; "IMAGE_FROM_USER_IN_ROOM" = "%@ sendet ein Bild %@ in %@";
/* Multiple unread messages in a room */ /* Multiple unread messages in a room */
@ -50,3 +50,7 @@
"SINGLE_UNREAD_IN_ROOM" = "Du hast eine Nachricht in %@ bekommen"; "SINGLE_UNREAD_IN_ROOM" = "Du hast eine Nachricht in %@ bekommen";
/* A single unread message */ /* A single unread message */
"SINGLE_UNREAD" = "Du hast eine Nachricht bekommen"; "SINGLE_UNREAD" = "Du hast eine Nachricht bekommen";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ in %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ hat einen Sticker gesendet";

View file

@ -276,7 +276,7 @@
"title_home" = "Start"; "title_home" = "Start";
"next" = "Weiter"; "next" = "Weiter";
"auth_invalid_login_param" = "Falscher Benutzername oder Passwort"; "auth_invalid_login_param" = "Falscher Benutzername oder Passwort";
"auth_add_email_message" = "Füge eine E-Mail-Adresse hinzu, damit dich andere Benutzer finden können, oder um das Passwort zurücksetzen zu können."; "auth_add_email_message" = "Füge eine E-Mail-Adresse hinzu, damit dich andere Benutzer finden können und um dein Passwort zurückzusetzen.";
"auth_add_phone_message" = "Füge eine Telefonnummer hinzu, damit dich andere Benutzer finden können."; "auth_add_phone_message" = "Füge eine Telefonnummer hinzu, damit dich andere Benutzer finden können.";
"auth_add_email_phone_message" = "Füge eine E-Mail-Adresse und/oder Telefonnummer hinzu, damit dich andere Benutzer finden können. Über die E-Mail-Adresse kannst du das Passwort zurücksetzen."; "auth_add_email_phone_message" = "Füge eine E-Mail-Adresse und/oder Telefonnummer hinzu, damit dich andere Benutzer finden können. Über die E-Mail-Adresse kannst du das Passwort zurücksetzen.";
"auth_add_email_and_phone_message" = "Füge eine E-Mail-Adresse und eine Telefonnummer hinzu, damit dich andere Benutzer finden können. Über die E-Mail-Adresse kannst du das Passwort zurücksetzen."; "auth_add_email_and_phone_message" = "Füge eine E-Mail-Adresse und eine Telefonnummer hinzu, damit dich andere Benutzer finden können. Über die E-Mail-Adresse kannst du das Passwort zurücksetzen.";
@ -656,7 +656,14 @@
"key_backup_setup_intro_manual_export_action" = "Manueller Schlüssel Export"; "key_backup_setup_intro_manual_export_action" = "Manueller Schlüssel Export";
// String for App Store // String for App Store
"store_short_description" = "Sicherer, dezentralisierter Chat/VoIP"; "store_short_description" = "Sicherer, dezentralisierter Chat/VoIP";
"store_full_description" = "Kommuniziere - auf deine Art.\n\nEine Chat-App - unter deiner Kontrolle und komplett flexibel. Riot lässt dich so kommunizieren wie du willst. Gebaut für [matrix] - dem Standard für offene, dezentrale Kommunikation.\n\nHol dir ein kostenloses Konto auf matrix.org, hol deinen eigenen Server auf https://modular.im oder nutze einen anderen Matrix-Server.\n\nWarum Riot.im wählen?\n\nKOMPLETTE KOMMUNIKATION: Baue Räume um deine Teams, deine Freunde, deine Community - wie auch immer du es willst! Chatte, teile Dateien, füge Widgets hinzu, führe Sprach- und Videogespräche - alles kostenlos.\n\nMÄCHTIGE INTEGRATIONEN: Nutze Riot.im mit den Werkzeugen die du kennst und liebst. Mit Riot.im kannst du auch mit Nutzern und Gruppen anderer Chat-Apps in Kontakt bleiben.\n\nPRIVAT UND SICHER: Halte deine Gespräche geheim. Modernste Verschlüsselung sogt dafür, dass deine private Kommunikation auch privat bleibt.\n\nOFFEN, NICHT VERSCHLOSSEN: Open Source - basierend auf [matrix]. Behalte deine Daten indem du deinen eigenen Server betreibst - oder einen wählst, dem du vertraust.\n\nWOIMMER DU AUCH BIST: Halte den Kontakt wo auch immer du bist mit einem Nachrichtenverlauf der auf allen deinen Geräten voll synchronisiert wird - in einer App oder im Browser z.B. auf https://riot.im"; "store_full_description" = "Kommuniziere - auf deine Art.\n\nEine Chat-App - unter deiner Kontrolle und komplett flexibel. Riot lässt dich so kommunizieren wie du willst. Gebaut für [matrix] - dem Standard für offene, dezentrale Kommunikation.\n\nHol dir ein kostenloses Konto auf matrix.org, deinen eigenen Server auf https://modular.im oder nutze einen anderen Matrix-Server.\n\nWarum Riot.im nutzen?\n\nLÜCKENLOSE KOMMUNIKATION: Baue Räume um deine Teams, deine Freunde, deine Community - ganz nach deinen Vorstellungen! Chatte, teile Dateien, füge Widgets hinzu und führe Sprach- sowie Videogespräche - alles kostenlos.\n\nMÄCHTIGE INTEGRATIONEN: Nutze Riot.im mit den Werkzeugen die du kennst und liebst. Mit Riot.im kannst du sogar mit Nutzern und Gruppen anderer Chat-Apps in Kontakt bleiben.\n\nPRIVAT UND SICHER: Halte deine Gespräche geheim. Modernste Verschlüsselung sogt dafür, dass private Kommunikation auch privat bleibt.\n\nOFFEN, NICHT VERSCHLOSSEN: Open Source - basierend auf [matrix]. Behalte die Hoheit über deine Daten indem du deinen eigenen Server betreibst - oder einen wählst, dem du vertraust.\n\nWO AUCH IMMER DU BIST: Halte den Kontakt - mit einem Nachrichtenverlauf der vollständig synchronisiert wird - auf all deinen Geräten oder Online unter https://riot.im";
"auth_login_single_sign_on" = "Anmelden mit Single Sign-On"; "auth_login_single_sign_on" = "Anmelden mit Single Sign-On";
"auth_autodiscover_invalid_response" = "Ungültige Antwort beim Entdecken des Heimservers"; "auth_autodiscover_invalid_response" = "Ungültige Antwort beim Entdecken des Heimservers";
"room_message_unable_open_link_error_message" = "Konnte Link nicht öffnen."; "room_message_unable_open_link_error_message" = "Konnte Link nicht öffnen.";
"room_event_action_reply" = "Antworten";
"room_event_action_edit" = "Bearbeiten";
"room_event_action_reaction_agree" = "%@ zustimmen";
"room_event_action_reaction_disagree" = "%@ nicht zustimmen";
"room_event_action_reaction_like" = "%@ zustimmen";
"room_event_action_reaction_dislike" = "%@ nicht zustimmen";
"room_action_reply" = "Antworten";

View file

@ -579,6 +579,7 @@
"event_formatter_jitsi_widget_removed" = "VoIP conference removed by %@"; "event_formatter_jitsi_widget_removed" = "VoIP conference removed by %@";
"event_formatter_rerequest_keys_part1_link" = "Re-request encryption keys"; "event_formatter_rerequest_keys_part1_link" = "Re-request encryption keys";
"event_formatter_rerequest_keys_part2" = " from your other devices."; "event_formatter_rerequest_keys_part2" = " from your other devices.";
"event_formatter_message_edited_mention" = "(Edited)";
// Others // Others
"or" = "or"; "or" = "or";

View file

@ -15,3 +15,5 @@
"room_jump_to_first_unread" = "Salti al unua nelegita mesaĝo"; "room_jump_to_first_unread" = "Salti al unua nelegita mesaĝo";
"group_details_people" = "Homoj"; "group_details_people" = "Homoj";
"group_details_rooms" = "Babilejoj"; "group_details_rooms" = "Babilejoj";
// MARK: - Device Verification
"device_verification_title" = "Kontroli aparaton";

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Mensaje de %@"; "MSG_FROM_USER" = "%@ envió un mensaje";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ publicó en %@"; "MSG_FROM_USER_IN_ROOM" = "%@ publicó en %@";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Llamada en grupo de %@: '%@'"; "VOICE_CONF_NAMED_FROM_USER" = "Llamada en grupo de %@: '%@'";
/* Incoming named video conference invite from a specific person */ /* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Llamada de vídeo en grupo de %@: '%@'"; "VIDEO_CONF_NAMED_FROM_USER" = "Llamada de vídeo en grupo de %@: '%@'";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ en %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ envió una pegatina";

View file

@ -551,3 +551,5 @@
"deactivate_account_informations_part5" = "Si quieres que olvidemos tus mensajes, por favor marca la casilla a continuación\n\nLa visibilidad de mensajes en Matrix es similar a la del correo electrónico. Que olvidemos tus mensajes implica que los mensajes que hayas enviado no se compartirán con ningún usuario nuevo o no registrado, pero aquellos usuarios registrados que ya tengan acceso a estos mensajes seguirán teniendo acceso a su copia."; "deactivate_account_informations_part5" = "Si quieres que olvidemos tus mensajes, por favor marca la casilla a continuación\n\nLa visibilidad de mensajes en Matrix es similar a la del correo electrónico. Que olvidemos tus mensajes implica que los mensajes que hayas enviado no se compartirán con ningún usuario nuevo o no registrado, pero aquellos usuarios registrados que ya tengan acceso a estos mensajes seguirán teniendo acceso a su copia.";
"deactivate_account_forget_messages_information_part1" = "Por favor, olvida todos los mensajes enviados al desactivar mi cuenta ("; "deactivate_account_forget_messages_information_part1" = "Por favor, olvida todos los mensajes enviados al desactivar mi cuenta (";
"deactivate_account_forget_messages_information_part3" = ": esto provocará que los usuarios futuros vean conversaciones incompletas)"; "deactivate_account_forget_messages_information_part3" = ": esto provocará que los usuarios futuros vean conversaciones incompletas)";
// String for App Store
"store_short_description" = "Chat/VoIP descentralizado y seguro";

View file

@ -3,3 +3,4 @@
"NSPhotoLibraryUsageDescription" = "Argazkien liburutegia argazkiak eta bideoak bidaltzeko erabiltzen da."; "NSPhotoLibraryUsageDescription" = "Argazkien liburutegia argazkiak eta bideoak bidaltzeko erabiltzen da.";
"NSMicrophoneUsageDescription" = "Mikrofonoa bideoak atera eta deiak egiteko erabiltzen da."; "NSMicrophoneUsageDescription" = "Mikrofonoa bideoak atera eta deiak egiteko erabiltzen da.";
"NSContactsUsageDescription" = "Zure kontaktuetatik Riot edo Matrix jada darabiltenak erakusteko, zure kontaktu liburuko e-mail helbideak eta telefono zenbakiak bidali ditzakegu identitate zerbitzarira. New Vector enpresak ez ditu datu hauek gordetzen edo beste ezertarako erabiltzen. Informazio gehiagorako ikusi pribatutasun politikari buruzko orria aplikazioaren ezarpenetan."; "NSContactsUsageDescription" = "Zure kontaktuetatik Riot edo Matrix jada darabiltenak erakusteko, zure kontaktu liburuko e-mail helbideak eta telefono zenbakiak bidali ditzakegu identitate zerbitzarira. New Vector enpresak ez ditu datu hauek gordetzen edo beste ezertarako erabiltzen. Informazio gehiagorako ikusi pribatutasun politikari buruzko orria aplikazioaren ezarpenetan.";
"NSCalendarsUsageDescription" = "Ikusi zure programatutako batzarrak aplikazioan.";

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "%@ erabiltzailearen mezua"; "MSG_FROM_USER" = "%@ erabiltzaileak mezu bat bidali du";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@erabiltzaileak %@ gelan idatzi du"; "MSG_FROM_USER_IN_ROOM" = "%@erabiltzaileak %@ gelan idatzi du";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ erabiltzaileak irudi bat %@ bidali dizu"; "IMAGE_FROM_USER" = "%@ erabiltzaileak irudi bat bidali du %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ erabiltzaileak irudi bat %@ bidali du %@ gelara"; "IMAGE_FROM_USER_IN_ROOM" = "%@ erabiltzaileak irudi bat %@ bidali du %@ gelara";
/* Multiple unread messages in a room */ /* Multiple unread messages in a room */
@ -50,3 +50,7 @@
"SINGLE_UNREAD_IN_ROOM" = "Mezu bat jaso duzu %@ gelan"; "SINGLE_UNREAD_IN_ROOM" = "Mezu bat jaso duzu %@ gelan";
/* A single unread message */ /* A single unread message */
"SINGLE_UNREAD" = "Mezu bat jaso duzu"; "SINGLE_UNREAD" = "Mezu bat jaso duzu";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ erabiltzailea %@ gelan";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ erabiltzaileak eranskailu bat bidali du";

View file

@ -52,7 +52,7 @@
"auth_password_placeholder" = "Pasahitza"; "auth_password_placeholder" = "Pasahitza";
"auth_new_password_placeholder" = "Pasahitz berria"; "auth_new_password_placeholder" = "Pasahitz berria";
"auth_user_name_placeholder" = "Erabiltzaile-izena"; "auth_user_name_placeholder" = "Erabiltzaile-izena";
"auth_add_email_message" = "Gehitu e-mail helbide bat zure kontura erabiltzaileek zu aurkitzea baimentzeko, eta zuk pasahitza berrezarri ahal izateko."; "auth_add_email_message" = "Gehitu e-mail helbide bat zure kontura erabiltzaileek zu aurkitzea baimentzeko, eta zure pasahitza berrezartzeko.";
"auth_add_phone_message" = "Gehitu telefono zenbaki bat zure kontura beste erabiltzaileek zu aurkitzea ahalbidetzeko."; "auth_add_phone_message" = "Gehitu telefono zenbaki bat zure kontura beste erabiltzaileek zu aurkitzea ahalbidetzeko.";
"auth_optional_email_placeholder" = "E-mail helbidea (aukerakoa)"; "auth_optional_email_placeholder" = "E-mail helbidea (aukerakoa)";
"auth_optional_phone_placeholder" = "Telefono zenbakia (aukerakoa)"; "auth_optional_phone_placeholder" = "Telefono zenbakia (aukerakoa)";
@ -71,7 +71,7 @@
"auth_forgot_password" = "Pasahitza ahaztu duzu?"; "auth_forgot_password" = "Pasahitza ahaztu duzu?";
"auth_use_server_options" = "Erabili zerbitzari pertsonalizatuaren ezarpenak (aurreratua)"; "auth_use_server_options" = "Erabili zerbitzari pertsonalizatuaren ezarpenak (aurreratua)";
"auth_email_validation_message" = "Egiaztatu zure e-mail helbidea erregistroarekin jarraitzeko"; "auth_email_validation_message" = "Egiaztatu zure e-mail helbidea erregistroarekin jarraitzeko";
"auth_recaptcha_message" = "Hasiera zerbitzari honek robot bat ez zarela egiaztatu nahi du"; "auth_recaptcha_message" = "Hasiera-zerbitzari honek robot bat ez zarela egiaztatu nahi du";
"auth_username_in_use" = "Erabilitako erabiltzaile-izena"; "auth_username_in_use" = "Erabilitako erabiltzaile-izena";
"auth_reset_password_next_step_button" = "Nire e-mail helbidea baieztatu dut"; "auth_reset_password_next_step_button" = "Nire e-mail helbidea baieztatu dut";
"auth_reset_password_message" = "Zure pasahitza berrezartzeko, idatzi zure kontura gehitutako e-mail helbidea:"; "auth_reset_password_message" = "Zure pasahitza berrezartzeko, idatzi zure kontura gehitutako e-mail helbidea:";
@ -110,8 +110,8 @@
"room_participants_action_set_default_power_level" = "Berrezarri erabiltzaile arrunt gisa"; "room_participants_action_set_default_power_level" = "Berrezarri erabiltzaile arrunt gisa";
"room_participants_action_set_moderator" = "Bihurtu moderatzaile"; "room_participants_action_set_moderator" = "Bihurtu moderatzaile";
"room_participants_action_set_admin" = "Bihurtu kudeatzaile"; "room_participants_action_set_admin" = "Bihurtu kudeatzaile";
"room_participants_action_ignore" = "Ezkutatu kide honen mezu guztiak"; "room_participants_action_ignore" = "Ezkutatu erabiltzaile honen mezu guztiak";
"room_participants_action_unignore" = "Erakutsi kide honen mezu guztiak"; "room_participants_action_unignore" = "Erakutsi erabiltzaile honen mezu guztiak";
"room_participants_action_mention" = "Aipamena"; "room_participants_action_mention" = "Aipamena";
"contacts_address_book_matrix_users_toggle" = "Matrix erabiltzaileak besterik ez"; "contacts_address_book_matrix_users_toggle" = "Matrix erabiltzaileak besterik ez";
"encrypted_room_message_placeholder" = "Bidali zifratutako mezua…"; "encrypted_room_message_placeholder" = "Bidali zifratutako mezua…";
@ -222,7 +222,7 @@
"auth_untrusted_id_server" = "Identitate zerbitzaria ez da fidagarria"; "auth_untrusted_id_server" = "Identitate zerbitzaria ez da fidagarria";
"auth_msisdn_validation_error" = "Ezin izan da telefono zenbakia egiaztatu."; "auth_msisdn_validation_error" = "Ezin izan da telefono zenbakia egiaztatu.";
"auth_reset_password_email_validation_message" = "E-mail bat bidali da %@ helbidera. Honek dakarren esteka jarraitu eta gero egin klik azpian."; "auth_reset_password_email_validation_message" = "E-mail bat bidali da %@ helbidera. Honek dakarren esteka jarraitu eta gero egin klik azpian.";
"auth_reset_password_error_not_found" = "Zure e-mail helbidea ez dago antza hasiera zerbitzari honetako Matrix ID batekin lotuta."; "auth_reset_password_error_not_found" = "Zure e-mail helbidea ez dago antza hasiera-zerbitzari honetako Matrix ID batekin lotuta.";
"room_creation_account" = "Kontua"; "room_creation_account" = "Kontua";
"room_creation_appearance" = "Itxura"; "room_creation_appearance" = "Itxura";
"room_creation_appearance_picture" = "Txateko irudia (aukerakoa)"; "room_creation_appearance_picture" = "Txateko irudia (aukerakoa)";
@ -312,7 +312,7 @@
"settings_config_no_build_info" = "Konpilazio daturik ez"; "settings_config_no_build_info" = "Konpilazio daturik ez";
"settings_mark_all_as_read" = "Markatu mezu guztiak irakurrita gisa"; "settings_mark_all_as_read" = "Markatu mezu guztiak irakurrita gisa";
"settings_report_bug" = "Arazte-txostena"; "settings_report_bug" = "Arazte-txostena";
"settings_config_home_server" = "Hasiera zerbitzaria %@ da"; "settings_config_home_server" = "Hasiera-zerbitzaria %@ da";
"settings_config_identity_server" = "Identitate zerbitzaria %@ da"; "settings_config_identity_server" = "Identitate zerbitzaria %@ da";
"settings_config_user_id" = "%@ gisa hasi duzu saioa"; "settings_config_user_id" = "%@ gisa hasi duzu saioa";
"settings_user_settings" = "ERABILTZAILE EZARPENAK"; "settings_user_settings" = "ERABILTZAILE EZARPENAK";
@ -571,7 +571,7 @@
"settings_key_backup_info_progress" = "%@ gakoen babes-kopia egiten..."; "settings_key_backup_info_progress" = "%@ gakoen babes-kopia egiten...";
"settings_key_backup_info_progress_done" = "Gako guztien babes-kopia egin da"; "settings_key_backup_info_progress_done" = "Gako guztien babes-kopia egin da";
"settings_key_backup_info_valid" = "Gailu honek zure gakoen babes-kopia egiten du."; "settings_key_backup_info_valid" = "Gailu honek zure gakoen babes-kopia egiten du.";
"settings_key_backup_info_not_valid" = "Gailu honek ez du zure gakoen babes kopia egiten."; "settings_key_backup_info_not_valid" = "Gailu honek ez du zure gakoen babes kopia egiten, baina badago berreskuratu dezakezun babes-kopia bat jarraitu ahal izateko.";
"settings_key_backup_button_create" = "Hasi 'Gakoen babes-kopia' erabiltzen"; "settings_key_backup_button_create" = "Hasi 'Gakoen babes-kopia' erabiltzen";
"settings_key_backup_button_use" = "Erabili gakoen babes-kopia"; "settings_key_backup_button_use" = "Erabili gakoen babes-kopia";
"key_backup_setup_passphrase_title" = "Babestu zure babeskopia pasaesaldi batekin"; "key_backup_setup_passphrase_title" = "Babestu zure babeskopia pasaesaldi batekin";
@ -633,7 +633,7 @@
"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Ez ditut nire zifratutako mezuak behar"; "sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Ez ditut nire zifratutako mezuak behar";
"sign_out_key_backup_in_progress_alert_cancel_action" = "Itxaron egingo dut"; "sign_out_key_backup_in_progress_alert_cancel_action" = "Itxaron egingo dut";
"settings_key_backup_info" = "Zifratutako mezuak muturretik muturrerako zifratzearen bidez babestuak daude. Zuk eta hartzaileak edo hartzaileek irakurri ditzakezue mezu horiek, beste inork ez."; "settings_key_backup_info" = "Zifratutako mezuak muturretik muturrerako zifratzearen bidez babestuak daude. Zuk eta hartzaileak edo hartzaileek irakurri ditzakezue mezu horiek, beste inork ez.";
"settings_key_backup_info_signout_warning" = "Egin zure gakoen babes-kopia saioa amaitu aurretik galdu nahi ez badituzu."; "settings_key_backup_info_signout_warning" = "Konektatu gailu hau gakoen babes-kopiara saioa amaitu aurretik, gailu honetan bakarrik egon daitezkeen gakoak galdu nahi ez badituzu.";
"settings_key_backup_info_trust_signature_unknown" = "Babes-kopiak gailu honen sinadura du, ID: %@"; "settings_key_backup_info_trust_signature_unknown" = "Babes-kopiak gailu honen sinadura du, ID: %@";
"settings_key_backup_info_trust_signature_valid" = "Babes-kopiak gailu honen baliozko sinadura bat du"; "settings_key_backup_info_trust_signature_valid" = "Babes-kopiak gailu honen baliozko sinadura bat du";
"settings_key_backup_info_trust_signature_valid_device_verified" = "Gailuak %@ gailuaren baliozko sinadura bat du"; "settings_key_backup_info_trust_signature_valid_device_verified" = "Gailuak %@ gailuaren baliozko sinadura bat du";
@ -663,3 +663,105 @@
"auth_login_single_sign_on" = "Hasi saioa urrats batean"; "auth_login_single_sign_on" = "Hasi saioa urrats batean";
"auth_autodiscover_invalid_response" = "Erantzun baliogabea hasiera-zerbitzarien bilaketari"; "auth_autodiscover_invalid_response" = "Erantzun baliogabea hasiera-zerbitzarien bilaketari";
"room_message_unable_open_link_error_message" = "Ezin izan da esteka ireki."; "room_message_unable_open_link_error_message" = "Ezin izan da esteka ireki.";
"room_event_action_reply" = "Erantzun";
"room_event_action_edit" = "Editatu";
"room_event_action_reaction_agree" = "Ados %@";
"room_event_action_reaction_disagree" = "Ez ados %@";
"room_event_action_reaction_like" = "Gogokoa %@";
"room_event_action_reaction_dislike" = "Ez gogokoa %@";
"room_action_reply" = "Erantzun";
"settings_key_backup_button_connect" = "Konektatu gailu hau gakoen babes-kopiara";
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Konektatu gailu hau gakoen babes-kopiara";
"key_backup_recover_connent_banner_subtitle" = "Konektatu gailu hau gakoen babes-kopiara";
// MARK: - Device Verification
"device_verification_title" = "Egiaztatu gailua";
"device_verification_error_cannot_load_device" = "Ezin izan da gailuaren informazioa kargatu.";
// Mark: Incoming
"device_verification_incoming_title" = "Jasotako egiaztaketa eskaria";
"device_verification_incoming_description_1" = "Egiaztatu gailu hau fidagarri gisa markatzeko. Gailuak fidagarritzat jotzeak lasaitasuna ematen dizu muturretik muturrera zifratutako mezuak erabiltzean.";
"device_verification_incoming_description_2" = "Gailu hau egiaztatzean fidagarri gisa markatuko da, eta zure gailua fidagarri gisa markatuko zaio ere zure kideari.";
// MARK: Start
"device_verification_start_title" = "Egiaztatu testu kate labur bat alderatuz";
"device_verification_start_wait_partner" = "Kideak onartu bitartean zain...";
"device_verification_start_use_legacy" = "Ez da ezer agertzen? Bezero guztiek ez dute onartzen egiaztaketa interaktiboa oraindik. Erabili egiaztaketa metodo zaharra.";
"device_verification_start_verify_button" = "Hasi egiaztaketa";
"device_verification_start_use_legacy_action" = "Erabili egiaztaketa metodo zaharra";
// MARK: Verify
"device_verification_verify_title_emoji" = "Egiaztatu gailu hau honako emojia kidearen pantailan agertu dela baieztatuz";
"device_verification_verify_title_number" = "Egiaztatu gailu hau honako zenbaki hauek kidearen pantailan agertu direla baieztatuz";
"device_verification_verify_wait_partner" = "Kideak baieztatzearen zain...";
// MARK: Verified
"device_verification_verified_title" = "Egiaztatuta!";
"device_verification_verified_description_1" = "Ongi egiaztatu duzu gailu hau.";
"device_verification_verified_description_2" = "Kide honekin partekatutako mezu seguruak muturretik muturrera zifratuta daude eta ezin ditu beste inork irakurri.";
"device_verification_verified_got_it_button" = "Ulertuta";
// MARK: Emoji
"device_verification_emoji_dog" = "Txakurra";
"device_verification_emoji_cat" = "Katua";
"device_verification_emoji_lion" = "Lehoia";
"device_verification_emoji_horse" = "Zaldia";
"device_verification_emoji_unicorn" = "Unikornioa";
"device_verification_emoji_pig" = "Zerria";
"device_verification_emoji_elephant" = "Elefantea";
"device_verification_emoji_rabbit" = "Untxia";
"device_verification_emoji_panda" = "Panda hartza";
"device_verification_emoji_rooster" = "Oilarra";
"device_verification_emoji_penguin" = "Pinguinoa";
"device_verification_emoji_turtle" = "Dortoka";
"device_verification_emoji_fish" = "Arraina";
"device_verification_emoji_octopus" = "Olagarroa";
"device_verification_emoji_butterfly" = "Tximeleta";
"device_verification_emoji_flower" = "Lorea";
"device_verification_emoji_tree" = "Zuhaitza";
"device_verification_emoji_cactus" = "Kaktusa";
"device_verification_emoji_mushroom" = "Perretxikoa";
"device_verification_emoji_globe" = "Lurra";
"device_verification_emoji_moon" = "Ilargia";
"device_verification_emoji_cloud" = "Hodeia";
"device_verification_emoji_fire" = "Sua";
"device_verification_emoji_banana" = "Banana";
"device_verification_emoji_apple" = "Sagarra";
"device_verification_emoji_strawberry" = "Marrubia";
"device_verification_emoji_corn" = "Artoa";
"device_verification_emoji_pizza" = "Pizza";
"device_verification_emoji_cake" = "Pastela";
"device_verification_emoji_heart" = "Bihotza";
"device_verification_emoji_smiley" = "Irrifartxoa";
"device_verification_emoji_robot" = "Robota";
"device_verification_emoji_hat" = "Txanoa";
"device_verification_emoji_glasses" = "Betaurrekoak";
"device_verification_emoji_spanner" = "Giltza";
"device_verification_emoji_santa" = "Santa";
"device_verification_emoji_thumbs up" = "Ederto";
"device_verification_emoji_umbrella" = "Aterkia";
"settings_labs_message_reaction" = "Erreakzionatu mezuei emojiekin";
"event_formatter_message_edited_mention" = "(Editatua)";
"device_verification_security_advice" = "Segurtasun gehiagorako, hau aurrez aurre edo bestelako komunikazio bide fidagarriak erabiliz egitea aholkatzen dizugu";
"device_verification_cancelled" = "Beste aldeak egiaztaketa ezeztatu du.";
"device_verification_cancelled_by_me" = "Egiaztaketa ezeztatu da. Arrazoia: %@";
"device_verification_emoji_hourglass" = "Harea-erlojua";
"device_verification_emoji_clock" = "Klasea";
"device_verification_emoji_gift" = "Oparia";
"device_verification_emoji_light bulb" = "Bonbilla";
"device_verification_emoji_book" = "Liburua";
"device_verification_emoji_pencil" = "Arkatza";
"device_verification_emoji_paperclip" = "Klipa";
"device_verification_emoji_scissors" = "Artaziak";
"device_verification_emoji_padlock" = "Giltzarrapoa";
"device_verification_emoji_key" = "Giltza";
"device_verification_emoji_hammer" = "Mailua";
"device_verification_emoji_telephone" = "Telefonoa";
"device_verification_emoji_flag" = "Bandera";
"device_verification_emoji_train" = "Trena";
"device_verification_emoji_bicycle" = "Bizikleta";
"device_verification_emoji_aeroplane" = "Hegazkina";
"device_verification_emoji_rocket" = "Kohetea";
"device_verification_emoji_trophy" = "Saria";
"device_verification_emoji_ball" = "Baloia";
"device_verification_emoji_guitar" = "Gitarra";
"device_verification_emoji_trumpet" = "Tronpeta";
"device_verification_emoji_bell" = "Kanpaia";
"device_verification_emoji_anchor" = "Aingura";
"device_verification_emoji_headphones" = "Aurikularrak";
"device_verification_emoji_folder" = "Karpeta";
"device_verification_emoji_pin" = "Txintxeta";

View file

@ -3,3 +3,4 @@
"NSPhotoLibraryUsageDescription" = "La photothèque est utilisée pour envoyer des photos et des vidéos."; "NSPhotoLibraryUsageDescription" = "La photothèque est utilisée pour envoyer des photos et des vidéos.";
"NSMicrophoneUsageDescription" = "Le microphone est utilisé pour prendre des vidéos et passer des appels."; "NSMicrophoneUsageDescription" = "Le microphone est utilisé pour prendre des vidéos et passer des appels.";
"NSContactsUsageDescription" = "Afin dafficher qui parmis vos contacts utilise déjà Riot ou Matrix, nous pouvons envoyer les adresses e-mails et les numéros de téléphone de votre carnet d'adresse à votre Serveur d'Identité Matrix. New Vector ne stocke pas ces données et ne les utilise pas à d'autres fins. Pour plus d'informations, veuillez consulter la page de politique de confidentialité dans les paramètres de l'application."; "NSContactsUsageDescription" = "Afin dafficher qui parmis vos contacts utilise déjà Riot ou Matrix, nous pouvons envoyer les adresses e-mails et les numéros de téléphone de votre carnet d'adresse à votre Serveur d'Identité Matrix. New Vector ne stocke pas ces données et ne les utilise pas à d'autres fins. Pour plus d'informations, veuillez consulter la page de politique de confidentialité dans les paramètres de l'application.";
"NSCalendarsUsageDescription" = "Voir vos rendez-vous prévus dans lapplication.";

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Message de %@"; "MSG_FROM_USER" = "%@ a envoyé un message";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ a posté dans %@"; "MSG_FROM_USER_IN_ROOM" = "%@ a posté dans %@";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@ : * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@ : * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ vous a envoyé une image %@"; "IMAGE_FROM_USER" = "%@ a envoyé une image %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ a posté une image %@ dans %@"; "IMAGE_FROM_USER_IN_ROOM" = "%@ a posté une image %@ dans %@";
/* A single unread message in a room */ /* A single unread message in a room */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Téléconférence vocale de %@ : '%@'"; "VOICE_CONF_NAMED_FROM_USER" = "Téléconférence vocale de %@ : '%@'";
/* Incoming named video conference invite from a specific person */ /* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Téléconférence vidéo de %@ : '%@'"; "VIDEO_CONF_NAMED_FROM_USER" = "Téléconférence vidéo de %@ : '%@'";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ dans %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ a envoyé un sticker";

View file

@ -54,7 +54,7 @@
"auth_invalid_email" = "L'adresse e-mail ne semble pas valide"; "auth_invalid_email" = "L'adresse e-mail ne semble pas valide";
"auth_invalid_phone" = "Le numéro de téléphone ne semble pas valide"; "auth_invalid_phone" = "Le numéro de téléphone ne semble pas valide";
"auth_missing_password" = "Mot de passe manquant"; "auth_missing_password" = "Mot de passe manquant";
"auth_add_email_message" = "Ajouter une adresse e-mail au compte pour que les utilisateurs puissent vous retrouver, et pour pouvoir réinitialiser votre mot de passe."; "auth_add_email_message" = "Ajouter une adresse e-mail au compte pour que les utilisateurs puissent vous retrouver et pour réinitialiser votre mot de passe.";
"auth_add_phone_message" = "Ajouter un numéro de téléphone au compte pour que les utilisateurs puissent vous retrouver."; "auth_add_phone_message" = "Ajouter un numéro de téléphone au compte pour que les utilisateurs puissent vous retrouver.";
"auth_add_email_phone_message" = "Ajouter une adresse e-mail et/ou un numéro de téléphone à votre compte pour que les utilisateurs puissent vous retrouver. L'adresse e-mail vous permettra également de réinitialiser votre mot de passe."; "auth_add_email_phone_message" = "Ajouter une adresse e-mail et/ou un numéro de téléphone à votre compte pour que les utilisateurs puissent vous retrouver. L'adresse e-mail vous permettra également de réinitialiser votre mot de passe.";
"auth_add_email_and_phone_message" = "Ajouter une adresse e-mail et un numéro de téléphone à votre compte pour que les utilisateurs puissent vous retrouver. L'adresse e-mail vous permettra également de réinitialiser votre mot de passe."; "auth_add_email_and_phone_message" = "Ajouter une adresse e-mail et un numéro de téléphone à votre compte pour que les utilisateurs puissent vous retrouver. L'adresse e-mail vous permettra également de réinitialiser votre mot de passe.";
@ -69,14 +69,14 @@
"auth_msisdn_validation_title" = "Vérification en attente"; "auth_msisdn_validation_title" = "Vérification en attente";
"auth_msisdn_validation_message" = "Nous vous avons envoyé un SMS avec un code d'activation. Merci de le recopier ci-dessous."; "auth_msisdn_validation_message" = "Nous vous avons envoyé un SMS avec un code d'activation. Merci de le recopier ci-dessous.";
"auth_msisdn_validation_error" = "Impossible de vérifier votre numéro de téléphone."; "auth_msisdn_validation_error" = "Impossible de vérifier votre numéro de téléphone.";
"auth_recaptcha_message" = "Ce serveur d'accueil voudrait s'assurer que vous n'êtes pas un robot"; "auth_recaptcha_message" = "Ce serveur daccueil voudrait sassurer que vous nêtes pas un robot";
"auth_reset_password_message" = "Pour réinitialiser votre mot de passe, saisissez l'adresse e-mail liée à votre compte :"; "auth_reset_password_message" = "Pour réinitialiser votre mot de passe, saisissez l'adresse e-mail liée à votre compte :";
"auth_reset_password_missing_email" = "Vous devez saisir l'adresse e-mail liée à votre compte."; "auth_reset_password_missing_email" = "Vous devez saisir l'adresse e-mail liée à votre compte.";
"auth_reset_password_missing_password" = "Vous devez spécifier un nouveau mot de passe."; "auth_reset_password_missing_password" = "Vous devez spécifier un nouveau mot de passe.";
"auth_reset_password_email_validation_message" = "Un e-mail a été envoyé à %@. Cliquez d'abord sur le lien dans l'e-mail, puis ci-dessous."; "auth_reset_password_email_validation_message" = "Un e-mail a été envoyé à %@. Cliquez d'abord sur le lien dans l'e-mail, puis ci-dessous.";
"auth_reset_password_next_step_button" = "J'ai vérifié mon adresse e-mail"; "auth_reset_password_next_step_button" = "J'ai vérifié mon adresse e-mail";
"auth_reset_password_error_unauthorized" = "Impossible de vérifier l'adresse e-mail : assurez-vous de cliquer sur le lien dans l'e-mail"; "auth_reset_password_error_unauthorized" = "Impossible de vérifier l'adresse e-mail : assurez-vous de cliquer sur le lien dans l'e-mail";
"auth_reset_password_error_not_found" = "Votre adresse e-mail ne semble pas associée à un identifiant Matrix sur ce serveur d'accueil."; "auth_reset_password_error_not_found" = "Votre adresse e-mail ne semble pas associée à un identifiant Matrix sur ce serveur daccueil.";
"auth_reset_password_success_message" = "Votre mot de passe a été réinitialisé.\n\nVous avez été déconnecté de tous vos appareils et ne recevrez plus les notifications. Pour réactiver les notifications, reconnectez-vous sur chaque appareil."; "auth_reset_password_success_message" = "Votre mot de passe a été réinitialisé.\n\nVous avez été déconnecté de tous vos appareils et ne recevrez plus les notifications. Pour réactiver les notifications, reconnectez-vous sur chaque appareil.";
"auth_add_email_and_phone_warning" = "L'inscription avec un e-mail et un numéro de téléphone à la fois n'est pas supporté tant que l'API n'existe pas. Seul votre numéro de téléphone sera pris en compte. Vous pourrez ajouter l'adresse e-mail dans vos options de profil."; "auth_add_email_and_phone_warning" = "L'inscription avec un e-mail et un numéro de téléphone à la fois n'est pas supporté tant que l'API n'existe pas. Seul votre numéro de téléphone sera pris en compte. Vous pourrez ajouter l'adresse e-mail dans vos options de profil.";
// Chat creation // Chat creation
@ -246,7 +246,7 @@
"settings_config_no_build_info" = "Aucune information sur la version"; "settings_config_no_build_info" = "Aucune information sur la version";
"settings_mark_all_as_read" = "Marquer tous les messages comme lus"; "settings_mark_all_as_read" = "Marquer tous les messages comme lus";
"settings_report_bug" = "Signaler une erreur"; "settings_report_bug" = "Signaler une erreur";
"settings_config_home_server" = "Le serveur d'accueil est %@"; "settings_config_home_server" = "Le serveur daccueil est %@";
"settings_config_identity_server" = "Le serveur d'identité est %@"; "settings_config_identity_server" = "Le serveur d'identité est %@";
"settings_config_user_id" = "Identifié en tant que %@"; "settings_config_user_id" = "Identifié en tant que %@";
"settings_user_settings" = "PRÉFÉRENCES UTILISATEUR"; "settings_user_settings" = "PRÉFÉRENCES UTILISATEUR";
@ -563,7 +563,7 @@
"settings_key_backup_info_version" = "Version de sauvegarde de clé : %@"; "settings_key_backup_info_version" = "Version de sauvegarde de clé : %@";
"settings_key_backup_info_algorithm" = "Algorithme : %@"; "settings_key_backup_info_algorithm" = "Algorithme : %@";
"settings_key_backup_info_valid" = "Cet appareil sauvegarde vos clés."; "settings_key_backup_info_valid" = "Cet appareil sauvegarde vos clés.";
"settings_key_backup_info_not_valid" = "Cet appareil ne sauvegarde pas vos clés."; "settings_key_backup_info_not_valid" = "Cet appareil ne sauvegarde pas vos clés, mais vous avez une sauvegarde que vous pouvez restaurer et joindre.";
"settings_key_backup_info_progress" = "Sauvegarde de %@ clés…"; "settings_key_backup_info_progress" = "Sauvegarde de %@ clés…";
"settings_key_backup_info_progress_done" = "Toutes les clés ont été sauvegardées"; "settings_key_backup_info_progress_done" = "Toutes les clés ont été sauvegardées";
"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Pour utiliser la récupération de messages sécurisée sur cet appareil, vérifiez %@ maintenant."; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Pour utiliser la récupération de messages sécurisée sur cet appareil, vérifiez %@ maintenant.";
@ -625,7 +625,7 @@
"key_backup_recover_banner_title_part1" = "Lancer la récupération de messages sécurisée"; "key_backup_recover_banner_title_part1" = "Lancer la récupération de messages sécurisée";
"key_backup_recover_banner_title_part2" = " pour lire l'historique des messages chiffrés sur cet appareil"; "key_backup_recover_banner_title_part2" = " pour lire l'historique des messages chiffrés sur cet appareil";
"settings_key_backup_info" = "Les messages chiffrés sont sécurisés avec un chiffrement de bout en bout. Seuls vous et le(s) destinataire(s) avez les clés pour lire ces messages."; "settings_key_backup_info" = "Les messages chiffrés sont sécurisés avec un chiffrement de bout en bout. Seuls vous et le(s) destinataire(s) avez les clés pour lire ces messages.";
"settings_key_backup_info_signout_warning" = "Sauvegardez vos clés avant de vous déconnecter pour éviter de les perdre."; "settings_key_backup_info_signout_warning" = "Connectez cet appareil à la sauvegarde de clés avant de vous déconnecter pour éviter de perdre les clés qui ne seraient que sur cet appareil.";
"settings_key_backup_button_use" = "Utiliser la sauvegarde de clés"; "settings_key_backup_button_use" = "Utiliser la sauvegarde de clés";
"key_backup_setup_intro_setup_action_without_existing_backup" = "Commencer à utiliser la sauvegarde de clés"; "key_backup_setup_intro_setup_action_without_existing_backup" = "Commencer à utiliser la sauvegarde de clés";
"key_backup_setup_intro_setup_action_with_existing_backup" = "Utiliser la sauvegarde de clés"; "key_backup_setup_intro_setup_action_with_existing_backup" = "Utiliser la sauvegarde de clés";
@ -675,3 +675,105 @@
"auth_login_single_sign_on" = "Se connecter avec l'authentification unique"; "auth_login_single_sign_on" = "Se connecter avec l'authentification unique";
"room_message_unable_open_link_error_message" = "Impossible douvrir le lien."; "room_message_unable_open_link_error_message" = "Impossible douvrir le lien.";
"auth_autodiscover_invalid_response" = "Réponse de découverte du serveur daccueil non valide"; "auth_autodiscover_invalid_response" = "Réponse de découverte du serveur daccueil non valide";
"room_event_action_reply" = "Répondre";
"room_event_action_edit" = "Éditer";
"room_event_action_reaction_agree" = "Daccord %@";
"room_event_action_reaction_disagree" = "Pas daccord %@";
"room_event_action_reaction_like" = "Jaime %@";
"room_event_action_reaction_dislike" = "Jaime pas %@";
"room_action_reply" = "Répondre";
"settings_labs_message_reaction" = "Réagir aux messages avec des émojis";
"settings_key_backup_button_connect" = "Connecter cet appareil à la sauvegarde de clés";
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Connecter cet appareil à la sauvegarde de clés";
"key_backup_recover_connent_banner_subtitle" = "Connecter cet appareil à la sauvegarde de clés";
// MARK: - Device Verification
"device_verification_title" = "Vérifier lappareil";
"device_verification_security_advice" = "Pour une sécurité maximale, nous vous recommandons de faire cela en personne ou dutiliser un autre moyen sûr de communication";
"device_verification_cancelled" = "Lautre personne a annulé la vérification.";
"device_verification_cancelled_by_me" = "La vérification a été annulée. Motif : %@";
"device_verification_error_cannot_load_device" = "Impossible de charger les informations de lappareil.";
// Mark: Incoming
"device_verification_incoming_title" = "Demande de vérification entrante";
"device_verification_incoming_description_1" = "Vérifier cet appareil pour que ce soit un appareil de confiance. Faire confiance aux appareils de vos partenaires vous apporte une tranquillité desprit quand vous utilisez des messages chiffrés de bout en bout.";
"device_verification_incoming_description_2" = "En vérifiant cet appareil, il sera marqué comme appareil de confiance, et le vôtre sera aussi marqué comme appareil de confiance pour votre partenaire.";
// MARK: Start
"device_verification_start_title" = "Vérifier en comparant une chaîne de caractères courte";
"device_verification_start_wait_partner" = "Nous attendons que le partenaire accepte…";
"device_verification_start_use_legacy" = "Rien n'apparaît ? Certains clients ne prennent pas encore en charge la vérification interactive. Utilisez la vérification traditionnelle.";
"device_verification_start_verify_button" = "Commencer la vérification";
"device_verification_start_use_legacy_action" = "Utiliser la vérification traditionnelle";
// MARK: Verify
"device_verification_verify_title_emoji" = "Vérifier cet appareil en confirmant que les émojis suivant apparaissent sur lécran de votre partenaire";
"device_verification_verify_title_number" = "Vérifier cet utilisateur en confirmant que les chiffres suivant apparaissent sur lécran de votre partenaire";
"device_verification_verify_wait_partner" = "Nous attendons la confirmation de votre partenaire…";
// MARK: Verified
"device_verification_verified_title" = "Vérifié !";
"device_verification_verified_description_1" = "Vous avez bien vérifié cet appareil.";
"device_verification_verified_description_2" = "Les messages sécurisés avec cet utilisateur sont chiffrés de bout en bout et ne peuvent être lus par dautres personnes.";
"device_verification_verified_got_it_button" = "Compris";
// MARK: Emoji
"device_verification_emoji_dog" = "Chien";
"device_verification_emoji_cat" = "Chat";
"device_verification_emoji_lion" = "Lion";
"device_verification_emoji_horse" = "Cheval";
"device_verification_emoji_unicorn" = "Licorne";
"device_verification_emoji_pig" = "Cochon";
"device_verification_emoji_elephant" = "Éléphant";
"device_verification_emoji_rabbit" = "Lapin";
"device_verification_emoji_panda" = "Panda";
"device_verification_emoji_rooster" = "Coq";
"device_verification_emoji_penguin" = "Manchot";
"device_verification_emoji_turtle" = "Tortue";
"device_verification_emoji_fish" = "Poisson";
"device_verification_emoji_octopus" = "Pieuvre";
"device_verification_emoji_butterfly" = "Papillon";
"device_verification_emoji_flower" = "Fleur";
"device_verification_emoji_tree" = "Arbre";
"device_verification_emoji_cactus" = "Cactus";
"device_verification_emoji_mushroom" = "Champignon";
"device_verification_emoji_globe" = "Terre";
"device_verification_emoji_moon" = "Lune";
"device_verification_emoji_cloud" = "Nuage";
"device_verification_emoji_fire" = "Feu";
"device_verification_emoji_banana" = "Banane";
"device_verification_emoji_apple" = "Pomme";
"device_verification_emoji_strawberry" = "Fraise";
"device_verification_emoji_corn" = "Maïs";
"device_verification_emoji_pizza" = "Pizza";
"device_verification_emoji_cake" = "Gâteau";
"device_verification_emoji_heart" = "Cœur";
"device_verification_emoji_smiley" = "Smiley";
"device_verification_emoji_robot" = "Robot";
"device_verification_emoji_hat" = "Chapeau";
"device_verification_emoji_glasses" = "Lunettes";
"device_verification_emoji_spanner" = "Clé plate";
"device_verification_emoji_santa" = "Père Noël";
"device_verification_emoji_thumbs up" = "Pouce levé";
"device_verification_emoji_umbrella" = "Parapluie";
"device_verification_emoji_hourglass" = "Sablier";
"device_verification_emoji_clock" = "Horloge";
"device_verification_emoji_gift" = "Cadeau";
"device_verification_emoji_light bulb" = "Ampoule";
"device_verification_emoji_book" = "Livre";
"device_verification_emoji_pencil" = "Crayon";
"device_verification_emoji_paperclip" = "Trombone";
"device_verification_emoji_scissors" = "Ciseaux";
"device_verification_emoji_padlock" = "Cadenas";
"device_verification_emoji_key" = "Clé";
"device_verification_emoji_hammer" = "Marteau";
"device_verification_emoji_telephone" = "Téléphone";
"device_verification_emoji_flag" = "Drapeau";
"device_verification_emoji_train" = "Train";
"device_verification_emoji_bicycle" = "Vélo";
"device_verification_emoji_aeroplane" = "Avion";
"device_verification_emoji_rocket" = "Fusée";
"device_verification_emoji_trophy" = "Trophée";
"device_verification_emoji_ball" = "Balle";
"device_verification_emoji_guitar" = "Guitare";
"device_verification_emoji_trumpet" = "Trompette";
"device_verification_emoji_bell" = "Cloche";
"device_verification_emoji_anchor" = "Ancre";
"device_verification_emoji_headphones" = "Écouteurs";
"device_verification_emoji_folder" = "Dossier";
"device_verification_emoji_pin" = "Épingle";
"event_formatter_message_edited_mention" = "(Édité)";

View file

@ -3,3 +3,4 @@
"NSPhotoLibraryUsageDescription" = "A fénykép galéria fényképek és videók küldéséhez lesz használva."; "NSPhotoLibraryUsageDescription" = "A fénykép galéria fényképek és videók küldéséhez lesz használva.";
"NSMicrophoneUsageDescription" = "A mikrofon videók készítéséhez és hívásokhoz lesz használva."; "NSMicrophoneUsageDescription" = "A mikrofon videók készítéséhez és hívásokhoz lesz használva.";
"NSContactsUsageDescription" = "Ahhoz, hogy meg tudjuk mutatni melyik ismerősöd használja már a Riot-ot vagy Matrix-ot, el tudjuk küldeni az e-mail címeket és telefonszámokat a címjegyzékedből a Matrix Azonosítási Szerverének. „New Vector” nem tárolja és semmilyen más célra nem használja ezeket az információkat. További információkért olvasd el az adatkezelési oldalt az alkalmazás beállításaiban."; "NSContactsUsageDescription" = "Ahhoz, hogy meg tudjuk mutatni melyik ismerősöd használja már a Riot-ot vagy Matrix-ot, el tudjuk küldeni az e-mail címeket és telefonszámokat a címjegyzékedből a Matrix Azonosítási Szerverének. „New Vector” nem tárolja és semmilyen más célra nem használja ezeket az információkat. További információkért olvasd el az adatkezelési oldalt az alkalmazás beállításaiban.";
"NSCalendarsUsageDescription" = "Nézd meg a találkozóidat az alkalmazásban.";

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Üzenet tőle: %@"; "MSG_FROM_USER" = "%@ üzenet elküldve";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ küldte ebbe a szobába: %@"; "MSG_FROM_USER_IN_ROOM" = "%@ küldte ebbe a szobába: %@";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "%@ csoportos hívása: '%@'"; "VOICE_CONF_NAMED_FROM_USER" = "%@ csoportos hívása: '%@'";
/* Incoming named video conference invite from a specific person */ /* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "%@ csoportos videóhívása: '%@'"; "VIDEO_CONF_NAMED_FROM_USER" = "%@ csoportos videóhívása: '%@'";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ in %@ -ban/ben";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ matricát küldött";

View file

@ -568,7 +568,7 @@
"settings_key_backup_info_version" = "Kulcs mentés verzió: %@"; "settings_key_backup_info_version" = "Kulcs mentés verzió: %@";
"settings_key_backup_info_algorithm" = "Algoritmus: %@"; "settings_key_backup_info_algorithm" = "Algoritmus: %@";
"settings_key_backup_info_valid" = "Ez az eszköz elmenti a kulcsaidat."; "settings_key_backup_info_valid" = "Ez az eszköz elmenti a kulcsaidat.";
"settings_key_backup_info_not_valid" = "Ez az eszköz nem menti el a kulcsaidat."; "settings_key_backup_info_not_valid" = "Ez az eszköz nem menti el a kulcsaidat, de van létező mentésed ahonnan vissza tudsz állni és továbbléphetsz.";
"settings_key_backup_info_progress" = "%@ kulcsok mentése..."; "settings_key_backup_info_progress" = "%@ kulcsok mentése...";
"settings_key_backup_info_progress_done" = "Minden kulcs elmentve"; "settings_key_backup_info_progress_done" = "Minden kulcs elmentve";
"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "A Biztonságos Üzenet Visszaállítás használatához ellenőrizd ezt: %@."; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "A Biztonságos Üzenet Visszaállítás használatához ellenőrizd ezt: %@.";
@ -630,7 +630,7 @@
"key_backup_recover_banner_title_part1" = "Biztonságos Üzenet Visszaállítás futtatása"; "key_backup_recover_banner_title_part1" = "Biztonságos Üzenet Visszaállítás futtatása";
"key_backup_recover_banner_title_part2" = " , hogy elolvashasd a titkosított üzeneteidet ezen az eszközön"; "key_backup_recover_banner_title_part2" = " , hogy elolvashasd a titkosított üzeneteidet ezen az eszközön";
"settings_key_backup_info" = "Titkosított üzenetek végponttól-végpontig vannak titkosítva. Csak te és a címzettek rendelkeznek a visszafejtéshez szükséges kulcsokkal."; "settings_key_backup_info" = "Titkosított üzenetek végponttól-végpontig vannak titkosítva. Csak te és a címzettek rendelkeznek a visszafejtéshez szükséges kulcsokkal.";
"settings_key_backup_info_signout_warning" = "Mentsd el a kulcsaidat a kilépés előtt, hogy ne veszítsd el őket."; "settings_key_backup_info_signout_warning" = "Állítsd be ezen az eszközön a Kulcs Mentést kijelentkezés előtt, hogy ne veszíts el olyan kulcsot ami csak ezen az eszközön van meg.";
"settings_key_backup_button_use" = "Kulcs mentés használata"; "settings_key_backup_button_use" = "Kulcs mentés használata";
"key_backup_setup_intro_setup_action_without_existing_backup" = "Kulcs mentés használata"; "key_backup_setup_intro_setup_action_without_existing_backup" = "Kulcs mentés használata";
"key_backup_setup_intro_setup_action_with_existing_backup" = "Használd a Kulcs mentést"; "key_backup_setup_intro_setup_action_with_existing_backup" = "Használd a Kulcs mentést";
@ -680,3 +680,104 @@
"room_message_unable_open_link_error_message" = "A linket nem lehet megnyitni."; "room_message_unable_open_link_error_message" = "A linket nem lehet megnyitni.";
"store_full_description" = "Beszélgess, ahogy tetszik.\n\nA csevegő alkalmazás ami személyre szabható és az irányításod alatt marad. Riot megteremti a lehetőséget, hogy úgy beszélgess ahogy szeretnél. A [matrix] hálózathoz tervezve - ami egy nyílt és elosztott hálózat.\n\nKészíts egy ingyenes matrix.org fiókot vagy igényelj egy saját szervert a https://modular.im -től, de üzemeltethetsz is saját Matrix szervert.\n\nMiért válaszd a Riot.im-et?\n\nTELJES KOMMUNIKÁCIÓ: Nyiss szobákat a csoportod, barátaid, közösséged vagy bárkiknek akiknek szeretnél! Beszélgess, ossz meg fájlokat, adj hozzá kisalkalmazásokat és indíts hang és videóhívásokat - teljesen ingyen.\n\nERŐS KAPCSOLATOK: Használd a Riot-ot a kedvenc eszközeiddel. A Riottal még másik rendszerekben lévő emberekkel és csoportokkal is képes lehetsz beszélgetni.\n\nSZEMÉLYES ÉS BIZTONSÁGOS: Tartsd a beszélgetéseidet titokban. A végponttól-végpontig titkosítás biztosítja, hogy a személyes beszélgetések személyesek maradnak.\n\nNYÍLT ÉS NEM ZÁRT: Nyílt forrású és a Matrix-hoz készült. Az adataid maradjanak a birtokodban a saját szerver üzemeltetésével vagy válassz olyan szervert amiben megbízol.\n\nMINDENHOL AMERRE JÁRSZ: Maradj kapcsolatban a többiekkel mindenhol az eszközeid közötti teljesen szinkronizált üzenetváltásokkal. Akár a https://riot.im -en."; "store_full_description" = "Beszélgess, ahogy tetszik.\n\nA csevegő alkalmazás ami személyre szabható és az irányításod alatt marad. Riot megteremti a lehetőséget, hogy úgy beszélgess ahogy szeretnél. A [matrix] hálózathoz tervezve - ami egy nyílt és elosztott hálózat.\n\nKészíts egy ingyenes matrix.org fiókot vagy igényelj egy saját szervert a https://modular.im -től, de üzemeltethetsz is saját Matrix szervert.\n\nMiért válaszd a Riot.im-et?\n\nTELJES KOMMUNIKÁCIÓ: Nyiss szobákat a csoportod, barátaid, közösséged vagy bárkiknek akiknek szeretnél! Beszélgess, ossz meg fájlokat, adj hozzá kisalkalmazásokat és indíts hang és videóhívásokat - teljesen ingyen.\n\nERŐS KAPCSOLATOK: Használd a Riot-ot a kedvenc eszközeiddel. A Riottal még másik rendszerekben lévő emberekkel és csoportokkal is képes lehetsz beszélgetni.\n\nSZEMÉLYES ÉS BIZTONSÁGOS: Tartsd a beszélgetéseidet titokban. A végponttól-végpontig titkosítás biztosítja, hogy a személyes beszélgetések személyesek maradnak.\n\nNYÍLT ÉS NEM ZÁRT: Nyílt forrású és a Matrix-hoz készült. Az adataid maradjanak a birtokodban a saját szerver üzemeltetésével vagy válassz olyan szervert amiben megbízol.\n\nMINDENHOL AMERRE JÁRSZ: Maradj kapcsolatban a többiekkel mindenhol az eszközeid közötti teljesen szinkronizált üzenetváltásokkal. Akár a https://riot.im -en.";
"auth_autodiscover_invalid_response" = "Matrix szerver felderítésénél érvénytelen válasz érkezett"; "auth_autodiscover_invalid_response" = "Matrix szerver felderítésénél érvénytelen válasz érkezett";
"room_event_action_reply" = "Válasz";
"room_event_action_edit" = "Szerkeszt";
"room_event_action_reaction_agree" = "Egyetért %@";
"room_event_action_reaction_disagree" = "Ellentmond %@";
"room_event_action_reaction_like" = "Kedveli %@";
"room_event_action_reaction_dislike" = "Nem kedveli %@";
"room_action_reply" = "Válasz";
"settings_labs_message_reaction" = "Emoji reakció az üzenetre";
"settings_key_backup_button_connect" = "Eszköz csatlakoztatása a Kulcs Mentéshez";
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Eszköz csatlakoztatása a Kulcs Mentéshez";
"key_backup_recover_connent_banner_subtitle" = "Eszköz csatlakoztatása a Kulcs Mentéshez";
// MARK: - Device Verification
"device_verification_title" = "Eszköz ellenőrzése";
"device_verification_security_advice" = "A legnagyobb biztonság érdekében javasoljuk, hogy ezt személyesen vagy egy másik biztonságos kommunikációs csatornán tedd meg";
"device_verification_cancelled" = "A másik fél megszakította az ellenőrzést.";
"device_verification_cancelled_by_me" = "Az ellenőrzés megszakadt. Ok: %@";
"device_verification_error_cannot_load_device" = "Az eszköz információk nem tölthetők be.";
// Mark: Incoming
"device_verification_incoming_title" = "Beérkező Ellenőrzési Kérés";
"device_verification_incoming_description_1" = "Eszköz ellenőrzése és beállítás megbízhatónak. A partnerek eszközeiben való megbízás megnyugtató lehet, ha végponttól végpontig titkosítást használsz.";
"device_verification_incoming_description_2" = "Az eszköz ellenőrzése megbízhatónak fogja jelezni az eszközt és a partnernél a te eszközödet szintén megbízhatónak fogja jelezni.";
// MARK: Start
"device_verification_start_title" = "Rövid szöveggel ellenőriz";
"device_verification_start_wait_partner" = "Várakozás a partner általi elfogadásra...";
"device_verification_start_use_legacy" = "Nem jelenik meg semmi? Nem minden kliens támogatja az interaktív ellenőrzést. Használd a hagyományos ellenőrzést.";
"device_verification_start_verify_button" = "Ellenőrzés megkezdése";
"device_verification_start_use_legacy_action" = "Használd a hagyományos ellenőrzést";
// MARK: Verify
"device_verification_verify_title_emoji" = "Eszköz ellenőrzése az alábbi emojik a partner képernyőjén való megjelenésének megerősítésével történik";
"device_verification_verify_title_number" = "Eszköz ellenőrzése az alábbi számok a partner képernyőjén való megjelenésének megerősítésével történik";
"device_verification_verify_wait_partner" = "Várakozás a partner megerősítésére...";
// MARK: Verified
"device_verification_verified_title" = "Ellenőrizve!";
"device_verification_verified_description_1" = "Ezt az eszközt sikeresen ellenőrizted.";
"device_verification_verified_description_2" = "Az biztonságos üzentküldés ezzel a felhasználóval végponttól végpontig titkosított és harmadik fél nem tudja elolvasni.";
"device_verification_verified_got_it_button" = "Értem";
// MARK: Emoji
"device_verification_emoji_dog" = "Kutya";
"device_verification_emoji_cat" = "Macska";
"device_verification_emoji_lion" = "Oroszlán";
"device_verification_emoji_horse" = "Ló";
"device_verification_emoji_unicorn" = "Egyszarvú";
"device_verification_emoji_pig" = "Disznó";
"device_verification_emoji_elephant" = "Elefánt";
"device_verification_emoji_rabbit" = "Nyúl";
"device_verification_emoji_panda" = "Panda";
"device_verification_emoji_rooster" = "Kakas";
"device_verification_emoji_penguin" = "Pingvin";
"device_verification_emoji_turtle" = "Teknős";
"device_verification_emoji_fish" = "Hal";
"device_verification_emoji_octopus" = "Polip";
"device_verification_emoji_butterfly" = "Pillangó";
"device_verification_emoji_flower" = "Virág";
"device_verification_emoji_tree" = "Fa";
"device_verification_emoji_cactus" = "Kaktusz";
"device_verification_emoji_mushroom" = "Gomba";
"device_verification_emoji_globe" = "Földgömb";
"device_verification_emoji_moon" = "Hold";
"device_verification_emoji_cloud" = "Felhő";
"device_verification_emoji_fire" = "Tűz";
"device_verification_emoji_banana" = "Banán";
"device_verification_emoji_apple" = "Alma";
"device_verification_emoji_strawberry" = "Eper";
"device_verification_emoji_corn" = "Kukorica";
"device_verification_emoji_pizza" = "Pizza";
"device_verification_emoji_cake" = "Süti";
"device_verification_emoji_heart" = "Szív";
"device_verification_emoji_smiley" = "Mosoly";
"device_verification_emoji_robot" = "Robot";
"device_verification_emoji_hat" = "Kalap";
"device_verification_emoji_glasses" = "Szemüveg";
"device_verification_emoji_spanner" = "Csavarkulcs";
"device_verification_emoji_santa" = "Télapó";
"device_verification_emoji_thumbs up" = "Hüvelykujj fel";
"device_verification_emoji_umbrella" = "Esernyő";
"device_verification_emoji_hourglass" = "Homokóra";
"device_verification_emoji_clock" = "Osztály";
"device_verification_emoji_gift" = "Ajándék";
"device_verification_emoji_light bulb" = "Égő";
"device_verification_emoji_book" = "Könyv";
"device_verification_emoji_pencil" = "Toll";
"device_verification_emoji_paperclip" = "Gémkapocs";
"device_verification_emoji_scissors" = "Olló";
"device_verification_emoji_padlock" = "Lakat";
"device_verification_emoji_key" = "Kulcs";
"device_verification_emoji_hammer" = "Kalapács";
"device_verification_emoji_telephone" = "Telefon";
"device_verification_emoji_flag" = "Zászló";
"device_verification_emoji_train" = "Vonat";
"device_verification_emoji_bicycle" = "Kerékpár";
"device_verification_emoji_aeroplane" = "Repülő";
"device_verification_emoji_rocket" = "Rakáta";
"device_verification_emoji_trophy" = "Kupa";
"device_verification_emoji_ball" = "Labda";
"device_verification_emoji_guitar" = "Gitár";
"device_verification_emoji_trumpet" = "Trombita";
"device_verification_emoji_bell" = "Harang";
"device_verification_emoji_anchor" = "Vasmacska";
"device_verification_emoji_headphones" = "Fejhallgató";
"device_verification_emoji_folder" = "Mappa";
"device_verification_emoji_pin" = "Rajszeg";

View file

@ -18,7 +18,7 @@
"title_home" = "Thuis"; "title_home" = "Thuis";
"title_favourites" = "Favorieten"; "title_favourites" = "Favorieten";
"title_people" = "Personen"; "title_people" = "Personen";
"title_rooms" = "Kamers"; "title_rooms" = "Gesprekken";
"warning" = "Waarschuwing"; "warning" = "Waarschuwing";
// Actions // Actions
"view" = "Weergeven"; "view" = "Weergeven";
@ -115,23 +115,23 @@
"room_recents_directory_section_network" = "Netwerk"; "room_recents_directory_section_network" = "Netwerk";
"room_recents_favourites_section" = "FAVORIETEN"; "room_recents_favourites_section" = "FAVORIETEN";
"room_recents_people_section" = "PERSONEN"; "room_recents_people_section" = "PERSONEN";
"room_recents_conversations_section" = "KAMERS"; "room_recents_conversations_section" = "GESPREKKEN";
"room_recents_no_conversation" = "Geen kamers"; "room_recents_no_conversation" = "Geen gesprekken";
"room_recents_low_priority_section" = "LAGE PRIORITEIT"; "room_recents_low_priority_section" = "LAGE PRIORITEIT";
"room_recents_invites_section" = "UITNODIGINGEN"; "room_recents_invites_section" = "UITNODIGINGEN";
"room_recents_start_chat_with" = "Gesprek beginnen"; "room_recents_start_chat_with" = "Gesprek beginnen";
"room_recents_create_empty_room" = "Gesprek aanmaken"; "room_recents_create_empty_room" = "Gesprek aanmaken";
"room_recents_join_room" = "Gesprek toetreden"; "room_recents_join_room" = "Gesprek toetreden";
"room_recents_join_room_title" = "Neem aan een gesprek deel"; "room_recents_join_room_title" = "Neem aan een gesprek deel";
"room_recents_join_room_prompt" = "Voer een gespreks-ID of -alias in"; "room_recents_join_room_prompt" = "Voer een gespreks(bij)naam in";
// People tab // People tab
"people_invites_section" = "UITNODIGINGEN"; "people_invites_section" = "UITNODIGINGEN";
"people_conversation_section" = "GESPREKKEN"; "people_conversation_section" = "GESPREKKEN";
"people_no_conversation" = "Geen gesprekken"; "people_no_conversation" = "Geen gesprekken";
// Rooms tab // Rooms tab
"room_directory_no_public_room" = "Geen publieke kamers beschikbaar"; "room_directory_no_public_room" = "Geen publieke gesprekken beschikbaar";
// Search // Search
"search_rooms" = "Kamers"; "search_rooms" = "Gesprekken";
"search_messages" = "Berichten"; "search_messages" = "Berichten";
"search_people" = "Personen"; "search_people" = "Personen";
"search_files" = "Bestanden"; "search_files" = "Bestanden";
@ -140,7 +140,7 @@
"search_no_result" = "Geen resultaten"; "search_no_result" = "Geen resultaten";
// Directory // Directory
"directory_cell_title" = "Bladeren door de catalogus"; "directory_cell_title" = "Bladeren door de catalogus";
"directory_cell_description" = "%tu kamers"; "directory_cell_description" = "%tu gesprekken";
"directory_search_results_title" = "Bladeren door catalogusresultaten"; "directory_search_results_title" = "Bladeren door catalogusresultaten";
"directory_search_results" = "%tu resultaten gevonden voor %@"; "directory_search_results" = "%tu resultaten gevonden voor %@";
"directory_search_results_more_than" = ">%tu resultaten gevonden voor %@"; "directory_search_results_more_than" = ">%tu resultaten gevonden voor %@";
@ -270,7 +270,7 @@
"settings_cryptography" = "CRYPTOGRAFIE"; "settings_cryptography" = "CRYPTOGRAFIE";
"settings_sign_out" = "Afmelden"; "settings_sign_out" = "Afmelden";
"settings_sign_out_confirmation" = "Weet u het zeker?"; "settings_sign_out_confirmation" = "Weet u het zeker?";
"settings_sign_out_e2e_warn" = "U zult uw sleutels voor eind-tot-eind-versleuteling kwijtraken. Dat betekent dat u op dit apparaat geen oude berichten in versleutelde kamers meer zult kunnen lezen."; "settings_sign_out_e2e_warn" = "U zult uw sleutels voor eind-tot-eind-versleuteling kwijtraken. Dat betekent dat u op dit apparaat geen oude berichten in versleutelde gesprekken meer zult kunnen lezen.";
"settings_profile_picture" = "Profielfoto"; "settings_profile_picture" = "Profielfoto";
"settings_display_name" = "Weergavenaam"; "settings_display_name" = "Weergavenaam";
"settings_first_name" = "Voornaam"; "settings_first_name" = "Voornaam";
@ -288,8 +288,8 @@
"settings_fail_to_update_profile" = "Bijwerken van profiel is mislukt"; "settings_fail_to_update_profile" = "Bijwerken van profiel is mislukt";
"settings_enable_push_notif" = "Meldingen op dit apparaat"; "settings_enable_push_notif" = "Meldingen op dit apparaat";
"settings_global_settings_info" = "Globale meldingsinstellingen zijn beschikbaar op uw %@-webcliënt"; "settings_global_settings_info" = "Globale meldingsinstellingen zijn beschikbaar op uw %@-webcliënt";
"settings_pin_rooms_with_missed_notif" = "Kamers met gemiste meldingen vastprikken"; "settings_pin_rooms_with_missed_notif" = "Gesprekken met gemiste meldingen vastprikken";
"settings_pin_rooms_with_unread" = "Kamers met ongelezen berichten vastprikken"; "settings_pin_rooms_with_unread" = "Gesprekken met ongelezen berichten vastprikken";
"settings_on_denied_notification" = "Meldingen worden geweigerd voor %@, sta ze toe in uw apparaatinstellingen"; "settings_on_denied_notification" = "Meldingen worden geweigerd voor %@, sta ze toe in uw apparaatinstellingen";
//"settings_enable_all_notif" = "Alle notificaties aanzetten"; //"settings_enable_all_notif" = "Alle notificaties aanzetten";
//"settings_messages_my_display_name" = "Bericht dat mijn naam bevat"; //"settings_messages_my_display_name" = "Bericht dat mijn naam bevat";
@ -354,8 +354,8 @@
"room_details_no_local_addresses" = "Dit gesprek heeft geen lokale adressen"; "room_details_no_local_addresses" = "Dit gesprek heeft geen lokale adressen";
"room_details_new_address" = "Nieuw adres toevoegen"; "room_details_new_address" = "Nieuw adres toevoegen";
"room_details_new_address_placeholder" = "Nieuw adres toevoegen (bv. #foo%@)"; "room_details_new_address_placeholder" = "Nieuw adres toevoegen (bv. #foo%@)";
"room_details_addresses_invalid_address_prompt_title" = "Ongeldig aliasformaat"; "room_details_addresses_invalid_address_prompt_title" = "Ongeldig bijnaamformaat";
"room_details_addresses_invalid_address_prompt_msg" = "%@ is geen geldig formaat voor een alias"; "room_details_addresses_invalid_address_prompt_msg" = "%@ is geen geldig formaat voor een bijnaam";
"room_details_addresses_disable_main_address_prompt_title" = "Hoofdadreswaarschuwing"; "room_details_addresses_disable_main_address_prompt_title" = "Hoofdadreswaarschuwing";
"room_details_addresses_disable_main_address_prompt_msg" = "U heeft geen hoofdadres opgegeven. Het standaardhoofdadres voor dit gesprek zal willekeurig gekozen worden"; "room_details_addresses_disable_main_address_prompt_msg" = "U heeft geen hoofdadres opgegeven. Het standaardhoofdadres voor dit gesprek zal willekeurig gekozen worden";
"room_details_banned_users_section" = "Verbannen gebruikers"; "room_details_banned_users_section" = "Verbannen gebruikers";
@ -368,7 +368,7 @@
"room_details_advanced_e2e_encryption_prompt_message" = "End-to-endbeveiliging is experimenteel en kan onbetrouwbaar zijn.\n\nHet is beter om het nog niet met gevoelige gegevens te vertrouwen.\n\nApparaten kunnen de geschiedenis van voordat ze de ruimte betraden nog niet ontsleutelen.\n\nZodra de versleuteling aan staat kan het (voorlopig) niet worden uitgezet.\n\nVersleutelde berichten zullen nog niet zichtbaar zijn op programma's die geen versleuteling ondersteunen."; "room_details_advanced_e2e_encryption_prompt_message" = "End-to-endbeveiliging is experimenteel en kan onbetrouwbaar zijn.\n\nHet is beter om het nog niet met gevoelige gegevens te vertrouwen.\n\nApparaten kunnen de geschiedenis van voordat ze de ruimte betraden nog niet ontsleutelen.\n\nZodra de versleuteling aan staat kan het (voorlopig) niet worden uitgezet.\n\nVersleutelde berichten zullen nog niet zichtbaar zijn op programma's die geen versleuteling ondersteunen.";
"room_details_fail_to_update_avatar" = "Bijwerken van gespreksfoto is mislukt"; "room_details_fail_to_update_avatar" = "Bijwerken van gespreksfoto is mislukt";
"room_details_fail_to_update_room_name" = "Bijwerken van gespreksnaam is mislukt"; "room_details_fail_to_update_room_name" = "Bijwerken van gespreksnaam is mislukt";
"room_details_fail_to_update_topic" = "Bijwerken van kameronderwerp is mislukt"; "room_details_fail_to_update_topic" = "Bijwerken van gespreksonderwerp is mislukt";
"room_details_fail_to_update_room_guest_access" = "Bijwerken van gasttoegang tot gesprek is mislukt"; "room_details_fail_to_update_room_guest_access" = "Bijwerken van gasttoegang tot gesprek is mislukt";
"room_details_fail_to_update_room_join_rule" = "Bijwerken van toetredingsregel is mislukt"; "room_details_fail_to_update_room_join_rule" = "Bijwerken van toetredingsregel is mislukt";
"room_details_fail_to_update_room_directory_visibility" = "Bijwerken van zichtbaarheid in de gesprekscatalogus is mislukt"; "room_details_fail_to_update_room_directory_visibility" = "Bijwerken van zichtbaarheid in de gesprekscatalogus is mislukt";
@ -389,9 +389,9 @@
// Directory // Directory
"directory_title" = "Catalogus"; "directory_title" = "Catalogus";
"directory_server_picker_title" = "Selecteer een catalogus"; "directory_server_picker_title" = "Selecteer een catalogus";
"directory_server_all_rooms" = "Alle kamers op server %@"; "directory_server_all_rooms" = "Alle gesprekken op server %@";
"directory_server_all_native_rooms" = "Alle lokale Matrix-kamers"; "directory_server_all_native_rooms" = "Alle lokale Matrix-gesprekken";
"directory_server_type_homeserver" = "Voer een thuisserver in om de publieke kamers ervan weer te geven"; "directory_server_type_homeserver" = "Voer een thuisserver in om de publieke gesprekken ervan weer te geven";
"directory_server_placeholder" = "matrix.org"; "directory_server_placeholder" = "matrix.org";
// Others // Others
"or" = "of"; "or" = "of";
@ -399,7 +399,7 @@
"today" = "Vandaag"; "today" = "Vandaag";
"yesterday" = "Gisteren"; "yesterday" = "Gisteren";
"network_offline_prompt" = "Het ziet er naar uit dat de internetverbinding offline is."; "network_offline_prompt" = "Het ziet er naar uit dat de internetverbinding offline is.";
"public_room_section_title" = "Publieke kamers (op %@):"; "public_room_section_title" = "Publieke gesprekken (op %@):";
"bug_report_prompt" = "De app is de vorige keer gecrasht. Wilt u een crashrapport indienen?"; "bug_report_prompt" = "De app is de vorige keer gecrasht. Wilt u een crashrapport indienen?";
"rage_shake_prompt" = "Het ziet er naar uit dat u de telefoon in frustratie schudt. Wilt u een foutmelding indienen?"; "rage_shake_prompt" = "Het ziet er naar uit dat u de telefoon in frustratie schudt. Wilt u een foutmelding indienen?";
"camera_access_not_granted" = "%@ heeft geen toestemming om de camera te gebruiken, pas de privacy-instellingen aan"; "camera_access_not_granted" = "%@ heeft geen toestemming om de camera te gebruiken, pas de privacy-instellingen aan";
@ -512,12 +512,12 @@
"group_details_title" = "Gemeenschapsdetails"; "group_details_title" = "Gemeenschapsdetails";
"group_details_home" = "Thuis"; "group_details_home" = "Thuis";
"group_details_people" = "Personen"; "group_details_people" = "Personen";
"group_details_rooms" = "Kamers"; "group_details_rooms" = "Gesprekken";
// Group Home // Group Home
"group_home_one_member_format" = "1 lid"; "group_home_one_member_format" = "1 lid";
"group_home_multi_members_format" = "%tu leden"; "group_home_multi_members_format" = "%tu leden";
"group_home_one_room_format" = "1 gesprek"; "group_home_one_room_format" = "1 gesprek";
"group_home_multi_rooms_format" = "%tu kamers"; "group_home_multi_rooms_format" = "%tu gesprekken";
"group_invitation_format" = "%@ heeft u uitgenodigd om tot deze gemeenschap toe te treden"; "group_invitation_format" = "%@ heeft u uitgenodigd om tot deze gemeenschap toe te treden";
// Group participants // Group participants
"group_participants_add_participant" = "Deelnemer toevoegen"; "group_participants_add_participant" = "Deelnemer toevoegen";
@ -533,7 +533,7 @@
"group_participants_invite_malformed_id" = "Misvormde ID. Dit moet een Matrix-ID zijn, zoals @gebruikersnaam:domein"; "group_participants_invite_malformed_id" = "Misvormde ID. Dit moet een Matrix-ID zijn, zoals @gebruikersnaam:domein";
"group_participants_invited_section" = "UITGENODIGD"; "group_participants_invited_section" = "UITGENODIGD";
// Group rooms // Group rooms
"group_rooms_filter_rooms" = "Gemeenschapskamers filteren"; "group_rooms_filter_rooms" = "Gemeenschapsgesprekken filteren";
"e2e_room_key_request_message_new_device" = "U heeft een nieuw apparaat %@ toegevoegd, dat vraagt naar versleutelingssleutels."; "e2e_room_key_request_message_new_device" = "U heeft een nieuw apparaat %@ toegevoegd, dat vraagt naar versleutelingssleutels.";
"room_event_action_kick_prompt_reason" = "Reden voor het verwijderen van deze gebruiker"; "room_event_action_kick_prompt_reason" = "Reden voor het verwijderen van deze gebruiker";
"room_event_action_ban_prompt_reason" = "Reden voor het verbannen van deze gebruiker"; "room_event_action_ban_prompt_reason" = "Reden voor het verbannen van deze gebruiker";
@ -553,7 +553,7 @@
"widget_sticker_picker_no_stickerpacks_alert" = "U heeft momenteel geen stickerpakketten ingeschakeld."; "widget_sticker_picker_no_stickerpacks_alert" = "U heeft momenteel geen stickerpakketten ingeschakeld.";
"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Wilt u er nu een paar toevoegen?"; "widget_sticker_picker_no_stickerpacks_alert_add_now" = "Wilt u er nu een paar toevoegen?";
"deactivate_account_title" = "Account deactiveren"; "deactivate_account_title" = "Account deactiveren";
"deactivate_account_informations_part1" = "Dit zal uw account voorgoed onbruikbaar maken. U zult zich niet meer kunnen aanmelden, en niemand anders zal zich met dezelfde gebruikers-ID kunnen registreren. Dit zal er voor zorgen dat uw account alle kamers verlaat waar deze momenteel lid van is, en het verwijdert uw accountgegevens van de identiteitsserver. "; "deactivate_account_informations_part1" = "Dit zal uw account voorgoed onbruikbaar maken. U zult zich niet meer kunnen aanmelden, en niemand anders zal zich met dezelfde gebruikers-ID kunnen registreren. Dit zal er voor zorgen dat uw account alle gesprekken verlaat waar deze momenteel lid van is, en het verwijdert uw accountgegevens van de identiteitsserver. ";
"deactivate_account_informations_part2_emphasize" = "Deze actie is onomkeerbaar."; "deactivate_account_informations_part2_emphasize" = "Deze actie is onomkeerbaar.";
"deactivate_account_informations_part3" = "\n\nHet deactiveren van uw account "; "deactivate_account_informations_part3" = "\n\nHet deactiveren van uw account ";
"deactivate_account_informations_part4_emphasize" = "zal er niet standaard voor zorgen dat de berichten die u heeft verzonden worden vergeten. "; "deactivate_account_informations_part4_emphasize" = "zal er niet standaard voor zorgen dat de berichten die u heeft verzonden worden vergeten. ";
@ -569,7 +569,7 @@
"room_message_reply_to_short_placeholder" = "Stuur een antwoord…"; "room_message_reply_to_short_placeholder" = "Stuur een antwoord…";
// String for App Store // String for App Store
"store_short_description" = "Veilig en gedecentraliseerd chatten en bellen"; "store_short_description" = "Veilig en gedecentraliseerd chatten en bellen";
"store_full_description" = "Communiceer op uw manier.\n\nEen chat-app, onder uw controle en heel flexibel. Riot laat u communiceren zoals u dat wilt. Gemaakt voor [matrix] - de standaard voor open, gedecentraliseerde communicatie.\n\nMaak een gratis account aan op matrix.org, verkrijg uw eigen server op https://modular.im, of gebruik een andere Matrix-server.\n\nWaarom zou ik voor Riot.im kiezen?\n\n• VOLLEDIGE COMMUNICATIE: maak kamers aan rond uw teams, uw vrienden, uw gemeenschap - hoe u maar wilt! Chat, deel bestanden, voeg widgets toe en maak stem- en video-oproepen - allemaal volledig gratis.\n\n• KRACHTIGE INTEGRATIE: gebruik Riot.im met de hulpmiddelen waarmee u vertrouwd bent. Met Riot.im kunt u zelfs chatten met gebruikers en groepen op andere chat-apps.\n\n• PRIVÉ EN VEILIG: houd uw gesprekken geheim. Eind-tot-eind-versleuteling van de bovenste plank zorgt ervoor dat uw privécommunicatie ook privé blijft.\n\n• OPEN, NIET GESLOTEN: vrije software, gebouwd op Matrix. Wees baas over uw eigen gegevens door uw eigen server te gebruiken, of te kiezen voor een andere server die u vertrouwt.\n\n• WAAR U OOK BENT: houd contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten, en online op https://riot.im."; "store_full_description" = "Communiceer op uw manier.\n\nEen chat-app, onder uw controle en heel flexibel. Riot laat u communiceren zoals u dat wilt. Gemaakt voor [matrix] - de standaard voor open, gedecentraliseerde communicatie.\n\nMaak een gratis account aan op matrix.org, verkrijg uw eigen server op https://modular.im, of gebruik een andere Matrix-server.\n\nWaarom zou ik voor Riot.im kiezen?\n\n• VOLLEDIGE COMMUNICATIE: maak gesprekken aan rond uw teams, uw vrienden, uw gemeenschap - hoe u maar wilt! Chat, deel bestanden, voeg widgets toe en maak stem- en video-oproepen - allemaal volledig gratis.\n\n• KRACHTIGE INTEGRATIE: gebruik Riot.im met de hulpmiddelen waarmee u vertrouwd bent. Met Riot.im kunt u zelfs chatten met gebruikers en groepen op andere chat-apps.\n\n• PRIVÉ EN VEILIG: houd uw gesprekken geheim. Eind-tot-eind-versleuteling van de bovenste plank zorgt ervoor dat uw privécommunicatie ook privé blijft.\n\n• OPEN, NIET GESLOTEN: vrije software, gebouwd op Matrix. Wees baas over uw eigen gegevens door uw eigen server te gebruiken, of te kiezen voor een andere server die u vertrouwt.\n\n• WAAR U OOK BENT: houd contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten, en online op https://riot.im.";
"auth_login_single_sign_on" = "Aanmelden met enkele aanmelding"; "auth_login_single_sign_on" = "Aanmelden met enkele aanmelding";
"auth_accept_policies" = "Gelieve het beleid van deze thuisserver te lezen en aanvaarden:"; "auth_accept_policies" = "Gelieve het beleid van deze thuisserver te lezen en aanvaarden:";
"auth_autodiscover_invalid_response" = "Ongeldig thuisserverontdekkingsantwoord"; "auth_autodiscover_invalid_response" = "Ongeldig thuisserverontdekkingsantwoord";
@ -587,16 +587,16 @@
"room_resource_usage_limit_reached_message_2" = "sommige gebruikers zullen zich niet kunnen aanmelden."; "room_resource_usage_limit_reached_message_2" = "sommige gebruikers zullen zich niet kunnen aanmelden.";
"room_resource_usage_limit_reached_message_contact_3" = " om deze limiet te verhogen."; "room_resource_usage_limit_reached_message_contact_3" = " om deze limiet te verhogen.";
"settings_key_backup" = "SLEUTELBACK-UP"; "settings_key_backup" = "SLEUTELBACK-UP";
"settings_labs_room_members_lazy_loading" = "Kamerleden lui laden"; "settings_labs_room_members_lazy_loading" = "Gespreksleden lui laden";
"settings_labs_room_members_lazy_loading_error_message" = "Uw thuisserver ondersteunt het lui laden van gespreksleden nog niet. Probeer het later opnieuw."; "settings_labs_room_members_lazy_loading_error_message" = "Uw thuisserver ondersteunt het lui laden van gespreksleden nog niet. Probeer het later opnieuw.";
"settings_key_backup_info" = "Versleutelde berichten worden beveiligd met eind-tot-eind-versleuteling. Enkel de ontvanger(s) en u hebben de sleutels om deze berichten te lezen."; "settings_key_backup_info" = "Versleutelde berichten worden beveiligd met eind-tot-eind-versleuteling. Enkel de ontvanger(s) en u hebben de sleutels om deze berichten te lezen.";
"settings_key_backup_info_checking" = "Bezig met controleren…"; "settings_key_backup_info_checking" = "Bezig met controleren…";
"settings_key_backup_info_none" = "Uw sleutels worden niet geback-upt vanaf dit apparaat."; "settings_key_backup_info_none" = "Uw sleutels worden niet geback-upt vanaf dit apparaat.";
"settings_key_backup_info_signout_warning" = "Maak een back-up van uw sleutels vooraleer u zich afmeldt om ze niet te verliezen."; "settings_key_backup_info_signout_warning" = "Verbind dit apparaat met de sleutelback-up vooraleer u zich afmeldt om sleutels die enkel op dit apparaat staat niet te verliezen.";
"settings_key_backup_info_version" = "Sleutelback-upversie: %@"; "settings_key_backup_info_version" = "Sleutelback-upversie: %@";
"settings_key_backup_info_algorithm" = "Algoritme: %@"; "settings_key_backup_info_algorithm" = "Algoritme: %@";
"settings_key_backup_info_valid" = "Dit apparaat maakt een back-up van uw sleutels."; "settings_key_backup_info_valid" = "Dit apparaat maakt een back-up van uw sleutels.";
"settings_key_backup_info_not_valid" = "Dit apparaat maakt geen back-up van uw sleutels."; "settings_key_backup_info_not_valid" = "Dit apparaat maakt geen back-up van uw sleutels, maar u heeft wel een bestaande back-up waarvan u kunt herstellen, en u vanaf dan nieuwe sleutels aan kunt toevoegen.";
"settings_key_backup_info_progress" = "Back-up van %@ sleutels wordt gemaakt…"; "settings_key_backup_info_progress" = "Back-up van %@ sleutels wordt gemaakt…";
"settings_key_backup_info_progress_done" = "Alle sleutels zijn geback-upt"; "settings_key_backup_info_progress_done" = "Alle sleutels zijn geback-upt";
"settings_key_backup_info_trust_signature_unknown" = "De back-up heeft een ondertekening van apparaat met ID: %@"; "settings_key_backup_info_trust_signature_unknown" = "De back-up heeft een ondertekening van apparaat met ID: %@";
@ -622,7 +622,7 @@
"key_backup_setup_skip_alert_message" = "U verliest mogelijk uw versleutelde berichten als u zich afmeldt of uw apparaat verliest."; "key_backup_setup_skip_alert_message" = "U verliest mogelijk uw versleutelde berichten als u zich afmeldt of uw apparaat verliest.";
"key_backup_setup_skip_alert_skip_action" = "Overslaan"; "key_backup_setup_skip_alert_skip_action" = "Overslaan";
"key_backup_setup_intro_title" = "Verlies nooit uw versleutelde berichten"; "key_backup_setup_intro_title" = "Verlies nooit uw versleutelde berichten";
"key_backup_setup_intro_info" = "Berichten in versleutelde kamers worden versleutelde met eind-tot-eind-beveiliging. Enkel de ontvanger(s) en u hebben de sleutels om deze berichten te lezen.\n\nMaak een veilige back-up van uw sleutels om deze niet te verliezen."; "key_backup_setup_intro_info" = "Berichten in versleutelde gesprekken worden versleuteld met eind-tot-eind-beveiliging. Enkel de ontvanger(s) en u hebben de sleutels om deze berichten te lezen.\n\nMaak een veilige back-up van uw sleutels om deze niet te verliezen.";
"key_backup_setup_intro_setup_action_without_existing_backup" = "Begin sleutelback-up te gebruiken"; "key_backup_setup_intro_setup_action_without_existing_backup" = "Begin sleutelback-up te gebruiken";
"key_backup_setup_intro_manual_export_info" = "(Geavanceerd)"; "key_backup_setup_intro_manual_export_info" = "(Geavanceerd)";
"key_backup_setup_intro_manual_export_action" = "Sleutels handmatig exporteren"; "key_backup_setup_intro_manual_export_action" = "Sleutels handmatig exporteren";
@ -683,3 +683,105 @@
"sign_out_key_backup_in_progress_alert_title" = "Sleutelback-up is bezig. Als u zich nu afmeldt zult u de toegang tot uw versleutelde berichten verliezen."; "sign_out_key_backup_in_progress_alert_title" = "Sleutelback-up is bezig. Als u zich nu afmeldt zult u de toegang tot uw versleutelde berichten verliezen.";
"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Ik wil mijn versleutelde berichten niet"; "sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Ik wil mijn versleutelde berichten niet";
"sign_out_key_backup_in_progress_alert_cancel_action" = "Ik wacht wel"; "sign_out_key_backup_in_progress_alert_cancel_action" = "Ik wacht wel";
"room_event_action_reply" = "Beantwoorden";
"room_event_action_edit" = "Bewerken";
"room_event_action_reaction_agree" = "Akkoord met %@";
"room_event_action_reaction_disagree" = "Niet akkoord met %@";
"room_event_action_reaction_like" = "Duim omhoog voor %@";
"room_event_action_reaction_dislike" = "Duim omlaag voor %@";
"room_action_reply" = "Beantwoorden";
"settings_labs_message_reaction" = "Beantwoord berichten met emoticons";
"settings_key_backup_button_connect" = "Dit apparaat verbinden met sleutelback-up";
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Dit apparaat verbinden met sleutelback-up";
"key_backup_recover_connent_banner_subtitle" = "Dit apparaat verbinden met sleutelback-up";
// MARK: - Device Verification
"device_verification_title" = "Apparaat verifiëren";
"device_verification_security_advice" = "Voor een maximale beveiliging raden we aan om dit onder vier ogen te doen, of via een ander vertrouwd communicatiekanaal";
"device_verification_cancelled" = "De andere partij heeft de verificatie geannuleerd.";
"device_verification_cancelled_by_me" = "De verificatie is geannuleerd. Reden: %@";
"device_verification_error_cannot_load_device" = "Kan apparaatsinformatie niet laden.";
// Mark: Incoming
"device_verification_incoming_title" = "Inkomend verificatieverzoek";
"device_verification_incoming_description_1" = "Verifieer dit apparaat om het als vertrouwd te markeren. Door de apparaten van uw partners te vertrouwen hoeft u zich nog minder zorgen te maken over het gebruik van eind-tot-eind-versleutelde berichten.";
"device_verification_incoming_description_2" = "Dit apparaat verifiëren zal het als vertrouwd markeren, en het ook aan uw gesprekspartner als vertrouwd markeren.";
// MARK: Start
"device_verification_start_title" = "Verifieer door een korte tekenreeks te vergelijken";
"device_verification_start_wait_partner" = "Wachten op partner om te aanvaarden…";
"device_verification_start_use_legacy" = "Verschijnt er niets? Nog niet alle cliënten bieden ondersteuning voor interactieve verificatie. Gebruik de traditionele verificatiemethode.";
"device_verification_start_verify_button" = "Verificatie beginnen";
"device_verification_start_use_legacy_action" = "Traditionele verificatie gebruiken";
// MARK: Verify
"device_verification_verify_title_emoji" = "Verifieer dit apparaat door te bevestigen dat de volgende emoticons op het scherm van uw gesprekspartner verschijnen";
"device_verification_verify_title_number" = "Verifieer dit apparaat door te bevestigen dat de volgende cijfers op het scherm van uw gesprekspartner verschijnen";
"device_verification_verify_wait_partner" = "Wachten op partner voor bevestiging…";
// MARK: Verified
"device_verification_verified_title" = "Geverifieerd!";
"device_verification_verified_description_1" = "U heeft dit apparaat geverifieerd.";
"device_verification_verified_description_2" = "Beveiligde berichten met deze gebruiker zijn eind-tot-eind-versleuteld en kunnen niet door derde partijen gelezen worden.";
"device_verification_verified_got_it_button" = "Ik snap het";
// MARK: Emoji
"device_verification_emoji_dog" = "Hond";
"device_verification_emoji_cat" = "Kat";
"device_verification_emoji_lion" = "Leeuw";
"device_verification_emoji_horse" = "Paard";
"device_verification_emoji_unicorn" = "Eenhoorn";
"device_verification_emoji_pig" = "Varken";
"device_verification_emoji_elephant" = "Olifant";
"device_verification_emoji_rabbit" = "Konijn";
"device_verification_emoji_panda" = "Panda";
"device_verification_emoji_rooster" = "Haan";
"device_verification_emoji_penguin" = "Pinguïn";
"device_verification_emoji_turtle" = "Schildpad";
"device_verification_emoji_fish" = "Vis";
"device_verification_emoji_octopus" = "Octopus";
"device_verification_emoji_butterfly" = "Vlinder";
"device_verification_emoji_flower" = "Bloem";
"device_verification_emoji_tree" = "Boom";
"device_verification_emoji_cactus" = "Cactus";
"device_verification_emoji_mushroom" = "Paddenstoel";
"device_verification_emoji_globe" = "Wereldbol";
"device_verification_emoji_moon" = "Maan";
"device_verification_emoji_cloud" = "Wolk";
"device_verification_emoji_fire" = "Vuur";
"device_verification_emoji_banana" = "Banaan";
"device_verification_emoji_apple" = "Appel";
"device_verification_emoji_strawberry" = "Aardbei";
"device_verification_emoji_corn" = "Maïs";
"device_verification_emoji_pizza" = "Pizza";
"device_verification_emoji_cake" = "Taart";
"device_verification_emoji_heart" = "Hart";
"device_verification_emoji_smiley" = "Smiley";
"device_verification_emoji_robot" = "Robot";
"device_verification_emoji_hat" = "Hoed";
"device_verification_emoji_glasses" = "Bril";
"device_verification_emoji_spanner" = "Moersleutel";
"device_verification_emoji_santa" = "Kerstman";
"device_verification_emoji_thumbs up" = "Duim omhoog";
"device_verification_emoji_umbrella" = "Paraplu";
"device_verification_emoji_hourglass" = "Zandloper";
"device_verification_emoji_clock" = "Klok";
"device_verification_emoji_gift" = "Cadeau";
"device_verification_emoji_light bulb" = "Gloeilamp";
"device_verification_emoji_book" = "Boek";
"device_verification_emoji_pencil" = "Potlood";
"device_verification_emoji_paperclip" = "Paperclip";
"device_verification_emoji_scissors" = "Schaar";
"device_verification_emoji_padlock" = "Hangslot";
"device_verification_emoji_key" = "Sleutel";
"device_verification_emoji_hammer" = "Hamer";
"device_verification_emoji_telephone" = "Telefoon";
"device_verification_emoji_flag" = "Vlag";
"device_verification_emoji_train" = "Trein";
"device_verification_emoji_bicycle" = "Fiets";
"device_verification_emoji_aeroplane" = "Vliegtuig";
"device_verification_emoji_rocket" = "Raket";
"device_verification_emoji_trophy" = "Trofee";
"device_verification_emoji_ball" = "Bal";
"device_verification_emoji_guitar" = "Gitaar";
"device_verification_emoji_trumpet" = "Trompet";
"device_verification_emoji_bell" = "Bel";
"device_verification_emoji_anchor" = "Anker";
"device_verification_emoji_headphones" = "Koptelefoon";
"device_verification_emoji_folder" = "Map";
"device_verification_emoji_pin" = "Speld";
"event_formatter_message_edited_mention" = "(Bewerkt)";

View file

@ -207,7 +207,7 @@
// Room Preview // Room Preview
"room_preview_invitation_format" = "Zostałeś(-aś) zaproszony(-a) do tego pokoju przez %@"; "room_preview_invitation_format" = "Zostałeś(-aś) zaproszony(-a) do tego pokoju przez %@";
"room_preview_subtitle" = "To jest podgląd pokoju. Interakcje zostały zablokowane."; "room_preview_subtitle" = "To jest podgląd pokoju. Interakcje zostały zablokowane.";
"room_preview_unlinked_email_warning" = "Zaproszenie zostało wysłane do %@, który nie jest powiązany z zalogowanym kontem. Możesz zalogować się z wykorzystaniem innego konta, albo dodać ten adres e-mail do swoich kontaktów."; "room_preview_unlinked_email_warning" = "Zaproszenie zostało wysłane do %@, który nie jest powiązany z tym kontem. Możesz zalogować się z wykorzystaniem innego konta, albo dodać ten adres email do swojego konta.";
"room_preview_try_join_an_unknown_room_default" = "pokój"; "room_preview_try_join_an_unknown_room_default" = "pokój";
// Settings // Settings
"settings_title" = "Ustawienia"; "settings_title" = "Ustawienia";
@ -314,7 +314,7 @@
"group_participants_remove_prompt_title" = "Potwierdzenie"; "group_participants_remove_prompt_title" = "Potwierdzenie";
"group_participants_invite_prompt_title" = "Potwierdzenie"; "group_participants_invite_prompt_title" = "Potwierdzenie";
"group_participants_filter_members" = "Filtruj członków społeczności"; "group_participants_filter_members" = "Filtruj członków społeczności";
"group_participants_invite_malformed_id" = "Uszkodzony ID. Czy to powinien być Matrix ID podobny do '@localpart:domain'"; "group_participants_invite_malformed_id" = "Uszkodzony ID. Matrix ID powinien być podobny do '@localpart:domain'";
// Group rooms // Group rooms
"group_rooms_filter_rooms" = "Filtruj pokoje społeczności"; "group_rooms_filter_rooms" = "Filtruj pokoje społeczności";
// Read Receipts // Read Receipts
@ -488,3 +488,25 @@
"media_picker_library" = "Biblioteka"; "media_picker_library" = "Biblioteka";
"large_badge_value_k_format" = "%.1fK"; "large_badge_value_k_format" = "%.1fK";
"bug_crash_report_title" = "Raport o awarii"; "bug_crash_report_title" = "Raport o awarii";
// String for App Store
"store_short_description" = "Bezpieczny, zdecentralizowany czat/VoIP";
"store_full_description" = "Komunikuj się, po swojemu.\n\nAplikacja do czatowania, pod Twoją kontrolą i całkowicie elastyczna. Riot pozwala Ci komunikować się tak, jak chcesz. Stworzona dla [matrixa] - otwartego standardu, zdecentralizowanej komunikacji.\n\nZałóż darmowe konto na matrix.org, załatw swój własny serwer na https://modular.im lub skorzystaj z innego serwera Matrix.\n\nDlaczego warto wybrać Riot.im?\n\nPEŁNA KOMUNIKACJA: Zbuduj pokoje wokół swoich zespołów, przyjaciół, społeczności - jak chcesz! Czat, udostępnianie plików, dodawanie widgetów i wykonywanie połączeń głosowych i wideo - wszystko to za darmo.\n\n\nPOTĘŻNA INTEGRACJA: Użyj Riot.im z narzędziami, które znasz i kochasz. Dzięki Riot.im możesz nawet rozmawiać z użytkownikami i grupami z innymi aplikacjami do czatowania.\n\nPRYWATNY I BEZPIECZNY: Trzymaj swoje rozmowy w tajemnicy. Najnowocześniejsze szyfrowanie typu end-to-end zapewnia prywatną komunikację.\n\nOTWARTY, NIE ZAMKNIĘTY: Open source i zbudowany na Matrixie. Miej swoje dane pod kontrolą poprzez hosting własnego serwera lub wybranie serwera, któremu ufasz.\n\nGDZIEKOLWIEK JESTEŚ: Bądź w kontakcie gdziekolwiek jesteś, dzięki w pełni zsynchronizowanej historii wiadomości na wszystkich Twoich urządzeniach i online na https://riot.im.";
"room_creation_make_public_prompt_msg" = "Jesteś pewien, że chcesz zrobić ten czat publiczny? Każdy może czytać Twoje wiadomości i dołączyć do czatu.";
"directory_search_fail" = "Nie udało się pobrać danych";
"contacts_address_book_permission_required" = "Uprawnienie jest wymagane żeby uzyskać dostęp do kontaktów lokalnych";
"room_participants_invite_malformed_id_title" = "Błąd Zaproszenia";
"room_participants_action_ban" = "Zbanuj z tego pokoju";
"room_unsent_messages_unknown_devices_notification" = "Wiadomość nie została wysłana z powodu obecności nieznanych urządzeń. %@ lub %@@ teraz?";
"room_event_action_ban_prompt_reason" = "Powód, dla którego zbanowano tego użytkownika";
"room_event_action_reply" = "Odpowiedz";
"room_event_action_edit" = "Edytuj";
"room_action_reply" = "Odpowiedz";
"room_preview_try_join_an_unknown_room" = "Próbujesz uzyskać dostęp do %@. Czy chciałbyś się przyłączyć, aby wziąć udział w dyskusji?";
"account_logout_all" = "Wyloguj wszystkie konta";
"settings_flair" = "Pokazuj wyznacznik społeczności gdzie jest to zezwolone";
"settings_key_backup" = "KOPIA ZAPASOWA KLUCZY";
"settings_enable_push_notif" = "Powiadomienia na tym urządzeniu";
"settings_global_settings_info" = "Globalne ustawienia powiadomień są dostępne na Twoim kliencie internetowym %@";
"settings_on_denied_notification" = "Powiadomienia są odrzucane w %@, proszę zezwól na nie w ustawieniach urządzenia";
"settings_callkit_info" = "Odbieraj połączenia przychodzące na ekranie blokady. Zobacz swoje połęczenia Riot w historii połączeń w systemie. Jeśli usługa iCloud jest włączona, historia połączeń zostanie udostępniona Apple.";
"settings_ui_theme_picker_message" = "\"Auto\" używa ustawienia \"Odwróć kolory\" urządzenia";

View file

@ -3,3 +3,4 @@
"NSPhotoLibraryUsageDescription" = "Галерея используется для отправки фотографий и видео."; "NSPhotoLibraryUsageDescription" = "Галерея используется для отправки фотографий и видео.";
"NSMicrophoneUsageDescription" = "Микрофон используется при съемке видео и выполнении звонков."; "NSMicrophoneUsageDescription" = "Микрофон используется при съемке видео и выполнении звонков.";
"NSContactsUsageDescription" = "Для отображения контактов, использующих Riot или Matrix, мы можем отправить адреса email и номера телефонов из вашей адресной книги на ваш сервер идентификации Matrix. Новый Vector не хранит эти данные и не использует их для каких-либо других целей. Для получения дополнительной информации, пожалуйста, ознакомьтесь с Политикой конфиденциальности в настройках приложения."; "NSContactsUsageDescription" = "Для отображения контактов, использующих Riot или Matrix, мы можем отправить адреса email и номера телефонов из вашей адресной книги на ваш сервер идентификации Matrix. Новый Vector не хранит эти данные и не использует их для каких-либо других целей. Для получения дополнительной информации, пожалуйста, ознакомьтесь с Политикой конфиденциальности в настройках приложения.";
"NSCalendarsUsageDescription" = "Ознакомьтесь со своими запланированными встречами в приложении.";

View file

@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ отправил(а) вам фото %@"; "IMAGE_FROM_USER" = "%@ отправил(а) фото %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ отправил(а) фото %@ в %@"; "IMAGE_FROM_USER_IN_ROOM" = "%@ отправил(а) фото %@ в %@";
/* Multiple unread messages in a room */ /* Multiple unread messages in a room */
@ -50,3 +50,7 @@
"SINGLE_UNREAD_IN_ROOM" = "Вы получили сообщение в %@"; "SINGLE_UNREAD_IN_ROOM" = "Вы получили сообщение в %@";
/* A single unread message */ /* A single unread message */
"SINGLE_UNREAD" = "Вы получили сообщение"; "SINGLE_UNREAD" = "Вы получили сообщение";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ в %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ отправил(а) стикер";

View file

@ -53,7 +53,7 @@
"auth_invalid_email" = "Это не похоже на допустимый адрес электронной почты"; "auth_invalid_email" = "Это не похоже на допустимый адрес электронной почты";
"auth_invalid_phone" = "Это не похоже на действительный номер телефона"; "auth_invalid_phone" = "Это не похоже на действительный номер телефона";
"auth_missing_password" = "Пароль отсутствует"; "auth_missing_password" = "Пароль отсутствует";
"auth_add_email_message" = "Добавьте адрес электронной почты в свою учетную запись, чтобы другим пользователям было проще вас найти. Также это поможет вам при необходимости восстановить пароль."; "auth_add_email_message" = "Добавьте адрес электронной почты в свою учетную запись, чтобы другим пользователям было проще вас найти. Также это поможет вам при восстановлении паролья.";
"auth_add_phone_message" = "Добавьте номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти."; "auth_add_phone_message" = "Добавьте номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти.";
"auth_add_email_phone_message" = "Добавьте адрес электронной почты и/или номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти. Адрес электронной почты также позволит вам сбросить пароль."; "auth_add_email_phone_message" = "Добавьте адрес электронной почты и/или номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти. Адрес электронной почты также позволит вам сбросить пароль.";
"auth_add_email_and_phone_message" = "Добавьте адрес электронной почты и номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти. Адрес электронной почты также позволит вам сбросить пароль."; "auth_add_email_and_phone_message" = "Добавьте адрес электронной почты и номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти. Адрес электронной почты также позволит вам сбросить пароль.";
@ -675,3 +675,13 @@
"store_full_description" = "Приложение для чата, под вашим контролем и полностью гибкое. Райот позволяет вам общаться так, как вы хотите. Сделано на [matrix] — стандарт для открытого, децентрализованного общения.\n\nПолучите бесплатную учетную запись на matrix.org, собственный сервер по адресу https://modular.im или используйте другой сервер Matrix.\n\nПочему стоит выбрать Riot.im?\n\n• ПОЛНАЯ СВЯЗЬ: создавайте комнаты для команд, друзей, сообщест — как хотите! Общайтесь, обменивайтесь файлами, добавляйте виджеты и совершайте голосовые и видеозвонки — и все это бесплатно.\n\n• МОЩНЫЕ ИНТЕГРАЦИИ: Используйте Riot.im с инструментами, которые знаете и любите. С Riot.im вы можете даже общаться с пользователями и группами других приложений.\n\n• ЧАСТНЫЕ И БЕЗОПАСНЫЕ: держите ваши разговоры в тайне. Современное сквозное шифрование гарантирует, что частное общение остается частным.\n\n• ОТКРЫТО, НЕ ЗАКРЫТО: Исходный код открыт, построено на Matrix. Владейте данными, используя собственный сервер или выбирайте тот, которому доверяете.\n\n• Везде, где вы находитесь: оставайтесь на связи, где бы вы ни находились, с полностью синхронизированной историей сообщений на всех ваших устройствах и в Интернете по адресу https://riot.im."; "store_full_description" = "Приложение для чата, под вашим контролем и полностью гибкое. Райот позволяет вам общаться так, как вы хотите. Сделано на [matrix] — стандарт для открытого, децентрализованного общения.\n\nПолучите бесплатную учетную запись на matrix.org, собственный сервер по адресу https://modular.im или используйте другой сервер Matrix.\n\nПочему стоит выбрать Riot.im?\n\n• ПОЛНАЯ СВЯЗЬ: создавайте комнаты для команд, друзей, сообщест — как хотите! Общайтесь, обменивайтесь файлами, добавляйте виджеты и совершайте голосовые и видеозвонки — и все это бесплатно.\n\n• МОЩНЫЕ ИНТЕГРАЦИИ: Используйте Riot.im с инструментами, которые знаете и любите. С Riot.im вы можете даже общаться с пользователями и группами других приложений.\n\n• ЧАСТНЫЕ И БЕЗОПАСНЫЕ: держите ваши разговоры в тайне. Современное сквозное шифрование гарантирует, что частное общение остается частным.\n\n• ОТКРЫТО, НЕ ЗАКРЫТО: Исходный код открыт, построено на Matrix. Владейте данными, используя собственный сервер или выбирайте тот, которому доверяете.\n\n• Везде, где вы находитесь: оставайтесь на связи, где бы вы ни находились, с полностью синхронизированной историей сообщений на всех ваших устройствах и в Интернете по адресу https://riot.im.";
"auth_login_single_sign_on" = "Вход с SSO"; "auth_login_single_sign_on" = "Вход с SSO";
"room_message_unable_open_link_error_message" = "Невозможно открыть ссылку."; "room_message_unable_open_link_error_message" = "Невозможно открыть ссылку.";
"auth_autodiscover_invalid_response" = "Неверный ответ обнаружения сервера";
"room_event_action_reply" = "Ответ";
"room_event_action_edit" = "Редактировать";
"room_event_action_reaction_agree" = "%@ согласен";
"room_event_action_reaction_disagree" = "%@ несогласен";
"room_event_action_reaction_like" = "%@ согласен";
"room_event_action_reaction_dislike" = "%@ не согласны";
"room_action_reply" = "Ответ";
"settings_labs_message_reaction" = "Реагировать на сообщения с Emoji";
"settings_key_backup_button_connect" = "Подключите это устройство к ключу резервного копирования";

View file

@ -1,5 +1,5 @@
/* New message from a specific person, not referencing a room */ /* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "Mesazh prej %@"; "MSG_FROM_USER" = "%@ dërgoi një mesazh";
/* New message from a specific person in a named room */ /* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ postuar te %@"; "MSG_FROM_USER_IN_ROOM" = "%@ postuar te %@";
/* New message from a specific person, not referencing a room. Content included. */ /* New message from a specific person, not referencing a room. Content included. */
@ -11,7 +11,7 @@
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@"; "ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */ /* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ ju dërgoi një foto %@"; "IMAGE_FROM_USER" = "%@ dërgoi një foto %@";
/* New action message from a specific person in a named room. */ /* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ postoi një foto %@ në %@"; "IMAGE_FROM_USER_IN_ROOM" = "%@ postoi një foto %@ në %@";
/* A single unread message in a room */ /* A single unread message in a room */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Thirrje grupi nga %@: '%@'"; "VOICE_CONF_NAMED_FROM_USER" = "Thirrje grupi nga %@: '%@'";
/* Incoming named video conference invite from a specific person */ /* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Thirrje video në grup nga %@: '%@'"; "VIDEO_CONF_NAMED_FROM_USER" = "Thirrje video në grup nga %@: '%@'";
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ në %@";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ dërgoi një ngjitës";

View file

@ -213,7 +213,7 @@
"settings_config_no_build_info" = "Ska të dhëna montimi"; "settings_config_no_build_info" = "Ska të dhëna montimi";
"settings_mark_all_as_read" = "Vëru shenjë krejt mesazheve si të lexuar"; "settings_mark_all_as_read" = "Vëru shenjë krejt mesazheve si të lexuar";
"settings_report_bug" = "Njoftoni një të metë"; "settings_report_bug" = "Njoftoni një të metë";
"settings_config_home_server" = "Shërbyesi home është %@"; "settings_config_home_server" = "Shërbyesi Home është %@";
"settings_config_identity_server" = "Shërbyes identitetesh është %@"; "settings_config_identity_server" = "Shërbyes identitetesh është %@";
"settings_config_user_id" = "I futur si %@"; "settings_config_user_id" = "I futur si %@";
"settings_user_settings" = "RREGULLIME PËRDORUESI"; "settings_user_settings" = "RREGULLIME PËRDORUESI";
@ -390,7 +390,7 @@
"on" = "On"; "on" = "On";
"auth_add_phone_message" = "Shtoni te llogaria juaj një numër telefoni, për tu dhënë mundësinë përdoruesve tju zbulojnë."; "auth_add_phone_message" = "Shtoni te llogaria juaj një numër telefoni, për tu dhënë mundësinë përdoruesve tju zbulojnë.";
"auth_msisdn_validation_message" = "Kemi dërguar një SMS me një kod aktivizimi. Ju lutemi, jepeni këtë kod më poshtë."; "auth_msisdn_validation_message" = "Kemi dërguar një SMS me një kod aktivizimi. Ju lutemi, jepeni këtë kod më poshtë.";
"auth_recaptcha_message" = "Ky Shërbyes Home do të donte të sigurohej se sjeni robot"; "auth_recaptcha_message" = "Ky shërbyes Home do të donte të sigurohej se sjeni robot";
"auth_reset_password_error_unauthorized" = "Verifikimi i adresës email dështoi: sigurohuni se keni klikuar lidhjen te email-i"; "auth_reset_password_error_unauthorized" = "Verifikimi i adresës email dështoi: sigurohuni se keni klikuar lidhjen te email-i";
"auth_reset_password_error_not_found" = "Adresa juaj email sduket të jetë e përshoqëruar me ID Matrix në këtë shërbyes Home."; "auth_reset_password_error_not_found" = "Adresa juaj email sduket të jetë e përshoqëruar me ID Matrix në këtë shërbyes Home.";
"title_favourites" = "Të parapëlqyer"; "title_favourites" = "Të parapëlqyer";
@ -559,7 +559,7 @@
"settings_key_backup_info_version" = "Version Kopjeruajtjeje Kyçesh: %@"; "settings_key_backup_info_version" = "Version Kopjeruajtjeje Kyçesh: %@";
"settings_key_backup_info_algorithm" = "Algoritëm: %@"; "settings_key_backup_info_algorithm" = "Algoritëm: %@";
"settings_key_backup_info_valid" = "Kjo pajisje po bën kopjeruajtje të kyçeve tuaja."; "settings_key_backup_info_valid" = "Kjo pajisje po bën kopjeruajtje të kyçeve tuaja.";
"settings_key_backup_info_not_valid" = "Kjo pajisje nuk po bën kopjeruajtje të kyçeve tuaja."; "settings_key_backup_info_not_valid" = "Kjo pajisje nuk po bën kopjeruajtje të kyçeve tuaja, por keni një kopjeruajtje ekzistuese që mund ta përdorni për rimarrje dhe ta shtoni më tej.";
"settings_key_backup_info_progress" = "Po kopjeruhen kyçet për %@…"; "settings_key_backup_info_progress" = "Po kopjeruhen kyçet për %@…";
"settings_key_backup_info_progress_done" = "U kopjeruajtën krejt kyçet"; "settings_key_backup_info_progress_done" = "U kopjeruajtën krejt kyçet";
"settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Për të përdorur Rikthim Mesazhesh të Sigurt në këtë pajisje, verifikoni tani %@."; "settings_key_backup_info_not_trusted_from_verifiable_device_fix_action" = "Për të përdorur Rikthim Mesazhesh të Sigurt në këtë pajisje, verifikoni tani %@.";
@ -621,7 +621,7 @@
"key_backup_recover_banner_title_part1" = "Xhironi Rikthim Mesazhesh të Sigurt"; "key_backup_recover_banner_title_part1" = "Xhironi Rikthim Mesazhesh të Sigurt";
"key_backup_recover_banner_title_part2" = " që të lexoni historik mesazhesh të fshehtëzuar në këtë pajisje"; "key_backup_recover_banner_title_part2" = " që të lexoni historik mesazhesh të fshehtëzuar në këtë pajisje";
"settings_key_backup_info" = "Mesazhet e fshehtëzuar sigurohen me fshehtëzim skaj-më-skaj. Vetëm ju dhe marrësi(t) kanë kyçet për të lexuar këto mesazhe."; "settings_key_backup_info" = "Mesazhet e fshehtëzuar sigurohen me fshehtëzim skaj-më-skaj. Vetëm ju dhe marrësi(t) kanë kyçet për të lexuar këto mesazhe.";
"settings_key_backup_info_signout_warning" = "Kopjeruajini kyçet tuaj, përpara se të dilni, që të shmangni humbjen e tyre."; "settings_key_backup_info_signout_warning" = "Lidheni këtë pajisje me kopjeruajtje kyçesh, përpara se të dilni, që të shmangni humbje të çfarëdo kyçi që mund të gjendet vetëm në këtë pajisje.";
"settings_key_backup_button_use" = "Përdor kopjeruajtje kyçesh"; "settings_key_backup_button_use" = "Përdor kopjeruajtje kyçesh";
"key_backup_setup_intro_setup_action_without_existing_backup" = "Fillo të përdorësh Kopjeruajtje Kyçesh"; "key_backup_setup_intro_setup_action_without_existing_backup" = "Fillo të përdorësh Kopjeruajtje Kyçesh";
"key_backup_setup_intro_setup_action_with_existing_backup" = "Përdor Kopjeruajtje Kyçesh"; "key_backup_setup_intro_setup_action_with_existing_backup" = "Përdor Kopjeruajtje Kyçesh";
@ -672,3 +672,102 @@
"room_message_unable_open_link_error_message" = "Sarrihet të hapet lidhja."; "room_message_unable_open_link_error_message" = "Sarrihet të hapet lidhja.";
"auth_autodiscover_invalid_response" = "Përgjigje e pavlefshme pikasjeje shërbyesi Home"; "auth_autodiscover_invalid_response" = "Përgjigje e pavlefshme pikasjeje shërbyesi Home";
"room_details_fail_to_update_room_direct" = "Sarrihet të përditësohet shenja si e drejtpërdrejtë e kësaj dhome"; "room_details_fail_to_update_room_direct" = "Sarrihet të përditësohet shenja si e drejtpërdrejtë e kësaj dhome";
"room_event_action_reply" = "Përgjigjuni";
"room_event_action_edit" = "Përpunoni";
"room_event_action_reaction_agree" = "Pajtohem me %@";
"room_event_action_reaction_disagree" = "Spajtohem me %@";
"room_event_action_reaction_like" = "Pëlqejeni %@";
"room_event_action_reaction_dislike" = "Shpëlqejeni %@";
"room_action_reply" = "Përgjigjuni";
"settings_labs_message_reaction" = "Reagoni ndaj mesazhesh me emoji";
"settings_key_backup_button_connect" = "Lidhe këtë pajisje me Kopjeruajtje Kyçesh";
"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Lidhe këtë pajisje me Kopjeruajtje Kyçesh";
"key_backup_recover_connent_banner_subtitle" = "Lidhe këtë pajisje me Kopjeruajtje Kyçesh";
// MARK: - Device Verification
"device_verification_title" = "Verifikoni pajisje";
"device_verification_security_advice" = "Për siguri maksimale, këshillojmë ta bëni këtë në prani të vetë personit, ose të përdorni një tjetër kanal të besuar komunikimesh";
"device_verification_cancelled" = "Pala tjetër e anuloi verifikimin.";
"device_verification_cancelled_by_me" = "Verifikimi u anulua. Arsye: %@";
"device_verification_error_cannot_load_device" = "Sngarkohen dot të dhëna pajisje.";
// Mark: Incoming
"device_verification_incoming_title" = "Kërkesë Verifikimi e Ardhur";
"device_verification_incoming_description_1" = "Që ti vihet shenjë si e besuar, verifikojeni këtë pajisje. Besimi i pajisjeve të partnerëve ju jep ca qetësi më tepër kur përdoren mesazhe të fshehtëzuar skaj-më-skaj.";
"device_verification_incoming_description_2" = "Verifikimi i kësaj pajisje do ta shënojë atë të besuar, dhe tuajën si të besuar te partneri.";
// MARK: Start
"device_verification_start_title" = "Verifikoje duke krahasuar një varg të shkurtër teksti";
"device_verification_start_wait_partner" = "Po pritet pranimi nga partneri…";
"device_verification_start_use_legacy" = "Sduket gjë? Jo të tërë klientët mbulojnë verifikim ndërveprues ende. Përdorni verifikimin në stil të vjetër.";
"device_verification_start_verify_button" = "Po Verifikohet";
"device_verification_start_use_legacy_action" = "Përdor Verifikim të Dikurshëm";
// MARK: Verify
"device_verification_verify_title_emoji" = "Verifikojeni këtë pajisje duke ripohuar shfaqjen e emoji-t vijues në skenën e partnerit";
"device_verification_verify_title_number" = "Verifikojeni këtë pajisje duke ripohuar se numri vijues shfaqet në ekranin e partnerit";
"device_verification_verify_wait_partner" = "Po pritet ripohimi nga partneri…";
// MARK: Verified
"device_verification_verified_title" = "U verifikua!";
"device_verification_verified_description_1" = "E verifikuat me sukses këtë pajisje.";
"device_verification_verified_description_2" = "Mesazhet e sigurt me këtë përdorues fshehtëzohen skaj-më-skaj dhe janë të palexueshëm nga palë të treta.";
"device_verification_verified_got_it_button" = "E mora vesh";
// MARK: Emoji
"device_verification_emoji_dog" = "Qen";
"device_verification_emoji_cat" = "Mace";
"device_verification_emoji_lion" = "Luan";
"device_verification_emoji_horse" = "Kalë";
"device_verification_emoji_unicorn" = "Njëbrirësh";
"device_verification_emoji_pig" = "Derr";
"device_verification_emoji_elephant" = "Elefant";
"device_verification_emoji_rabbit" = "Lepur";
"device_verification_emoji_panda" = "Panda";
"device_verification_emoji_rooster" = "Këndes";
"device_verification_emoji_penguin" = "Pinguin";
"device_verification_emoji_turtle" = "Breshkë";
"device_verification_emoji_fish" = "Peshk";
"device_verification_emoji_octopus" = "Oktapod";
"device_verification_emoji_butterfly" = "Flutur";
"device_verification_emoji_flower" = "Lule";
"device_verification_emoji_tree" = "Pemë";
"device_verification_emoji_cactus" = "Kaktus";
"device_verification_emoji_mushroom" = "Kërpudhë";
"device_verification_emoji_globe" = "Rruzull";
"device_verification_emoji_moon" = "Hëna";
"device_verification_emoji_cloud" = "Re";
"device_verification_emoji_fire" = "Zjarr";
"device_verification_emoji_banana" = "Banane";
"device_verification_emoji_apple" = "Mollë";
"device_verification_emoji_strawberry" = "Luleshtrydhe";
"device_verification_emoji_corn" = "Misër";
"device_verification_emoji_pizza" = "Picë";
"device_verification_emoji_cake" = "Tortë";
"device_verification_emoji_heart" = "Zemër";
"device_verification_emoji_smiley" = "Emotikon";
"device_verification_emoji_robot" = "Robot";
"device_verification_emoji_hat" = "Kapë";
"device_verification_emoji_glasses" = "Syze";
"device_verification_emoji_santa" = "Babagjyshi i Vitit të Ri";
"device_verification_emoji_umbrella" = "Ombrellë";
"device_verification_emoji_hourglass" = "Klepsidër";
"device_verification_emoji_clock" = "Klasë";
"device_verification_emoji_gift" = "Dhuratë";
"device_verification_emoji_light bulb" = "Llambë";
"device_verification_emoji_book" = "Libër";
"device_verification_emoji_pencil" = "Laps";
"device_verification_emoji_paperclip" = "Kapëse";
"device_verification_emoji_scissors" = "Gërshërë";
"device_verification_emoji_padlock" = "Dry";
"device_verification_emoji_key" = "Kyç";
"device_verification_emoji_hammer" = "Çekiç";
"device_verification_emoji_telephone" = "Telefon";
"device_verification_emoji_flag" = "Flamur";
"device_verification_emoji_train" = "Tren";
"device_verification_emoji_bicycle" = "Biçikletë";
"device_verification_emoji_aeroplane" = "Avion";
"device_verification_emoji_rocket" = "Raketë";
"device_verification_emoji_trophy" = "Trofe";
"device_verification_emoji_ball" = "Top";
"device_verification_emoji_guitar" = "Kitarë";
"device_verification_emoji_trumpet" = "Trombë";
"device_verification_emoji_bell" = "Kambanë";
"device_verification_emoji_anchor" = "Spirancë";
"device_verification_emoji_headphones" = "Kufje";
"device_verification_emoji_folder" = "Dosje";
"event_formatter_message_edited_mention" = "(U përpunua)";

View file

@ -0,0 +1,6 @@
// Permissions usage explanations
"NSCameraUsageDescription" = "De camera wor gebruukt vo fotootjes te trekkn en filmtjes te moakn, en vo videogesprekkn.";
"NSPhotoLibraryUsageDescription" = "De fotogalerie wor gebruukt vo fotootjes en filmtjes te versteurn.";
"NSMicrophoneUsageDescription" = "De microfoon wor gebruukt vo filmtjes te maken, en vo sproakiproepn.";
"NSContactsUsageDescription" = "Vo je te kunn toogn dewelkse van je contactn dat al Riot of Matrix gebruukn, kunn we de-mailadressn en telefongnumeros in jen adresboek noa je Matrix-identiteitsserver steurn. New Vector bewoart deze gegevens nie en gebruukt ze ook nie voor andere doeleindn. Bekykt vo meer informoatie de privacybeleidspagina in dinstelliengn van den app.";
"NSCalendarsUsageDescription" = "Bekykt je geplande afsproakn in den app.";

View file

@ -0,0 +1,56 @@
/* Message title for a specific person in a named room */
"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ in %@";
/* New message from a specific person, not referencing a room */
"MSG_FROM_USER" = "%@ èt e bericht gesteurd";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ geplatst in %@";
/* New message from a specific person, not referencing a room. Content included. */
"MSG_FROM_USER_WITH_CONTENT" = "%@: %@";
/* New message from a specific person in a named room. Content included. */
"MSG_FROM_USER_IN_ROOM_WITH_CONTENT" = "%@ in %@: %@";
/* New action message from a specific person, not referencing a room. */
"ACTION_FROM_USER" = "* %@ %@";
/* New action message from a specific person in a named room. */
"ACTION_FROM_USER_IN_ROOM" = "%@: * %@ %@";
/* New action message from a specific person, not referencing a room. */
"IMAGE_FROM_USER" = "%@ èt e fotootje %@ gesteurd";
/* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ èt e fotootje %@ in %@ geplatst";
/* A single unread message in a room */
"SINGLE_UNREAD_IN_ROOM" = "J' èt e bericht ountvangn in %@";
/* A single unread message */
"SINGLE_UNREAD" = "J' èt e bericht ountvangn";
/* Sticker from a specific person, not referencing a room. */
"STICKER_FROM_USER" = "%@ èt e sticker gesteurd";
/* Multiple unread messages in a room */
"UNREAD_IN_ROOM" = "%@ nieuwe berichten in %@";
/* Multiple unread messages from a specific person, not referencing a room */
"MSGS_FROM_USER" = "%@ nieuwe berichten in %@";
/* Multiple unread messages from two people */
"MSGS_FROM_TWO_USERS" = "%@ nieuwe berichten van %@ en %@";
/* Multiple unread messages from three people */
"MSGS_FROM_THREE_USERS" = "%@ nieuwe berichten van %@, %@ en %@";
/* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */
"MSGS_FROM_TWO_PLUS_USERS" = "%@ nieuwe berichten van %@, %@ en anderen";
/* Multiple messages in two rooms */
"MSGS_IN_TWO_ROOMS" = "%@ nieuwe berichten in %@ en %@";
/* Look, stuff's happened, alright? Just open the app. */
"MSGS_IN_TWO_PLUS_ROOMS" = "%@ nieuwe berichten in %@, %@ en anderen";
/* A user has invited you to a chat */
"USER_INVITE_TO_CHAT" = "%@ èt joun voor e gesprek uutgenodigd";
/* A user has invited you to an (unamed) group chat */
"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ èt joun in e groepsgesprek uutgenodigd";
/* A user has invited you to a named room */
"USER_INVITE_TO_NAMED_ROOM" = "%@ èt joun in %@ uutgenodigd";
/* Incoming one-to-one voice call */
"VOICE_CALL_FROM_USER" = "Iproep van %@";
/* Incoming one-to-one video call */
"VIDEO_CALL_FROM_USER" = "Video-iproep van %@";
/* Incoming unnamed voice conference invite from a specific person */
"VOICE_CONF_FROM_USER" = "Groepsiproep van %@";
/* Incoming unnamed video conference invite from a specific person */
"VIDEO_CONF_FROM_USER" = "Video-groepsiproep van %@";
/* Incoming named voice conference invite from a specific person */
"VOICE_CONF_NAMED_FROM_USER" = "Groepsiproep van %@: %@";
/* Incoming named video conference invite from a specific person */
"VIDEO_CONF_NAMED_FROM_USER" = "Video-groepsiproep van %@: %@";

View file

@ -0,0 +1 @@

View file

@ -86,9 +86,26 @@ extern NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer;
Calculate component frame in table view. Calculate component frame in table view.
@param componentIndex index of the component in bubble message data @param componentIndex index of the component in bubble message data
@return component frame if component exist or CGRectNull. @return component frame in table view if component exist or CGRectNull.
*/ */
- (CGRect)componentFrameForIndex:(NSInteger)componentIndex; - (CGRect)componentFrameInTableViewForIndex:(NSInteger)componentIndex;
/**
Calculate the component frame in the contentView of the tableview cell.
@param componentIndex index of the component in bubble message data
@return component frame in the contentView if the component exists or CGRectNull.
*/
- (CGRect)componentFrameInContentViewForIndex:(NSInteger)componentIndex;
/**
Give the correct cell height for a bubble cell with an attachment view. Handle reactions and read receipts views.
@param cellData The data object to render.
@param maxWidth The maximum available width.
@return The cell height.
*/
+ (CGFloat)attachmentBubbleCellHeightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth;
/** /**
Blur the view by adding a transparent overlay. Default is NO. Blur the view by adding a transparent overlay. Default is NO.

View file

@ -24,8 +24,6 @@
#import <objc/runtime.h> #import <objc/runtime.h>
#define VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH 39
#define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_X 48 #define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_X 48
#define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH 4 #define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH 4
@ -42,7 +40,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
if (componentIndex < bubbleComponents.count) if (componentIndex < bubbleComponents.count)
{ {
component = bubbleComponents[componentIndex]; component = bubbleComponents[componentIndex];
} }
if (component && component.date) if (component && component.date)
@ -60,46 +58,78 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
} }
// Display timestamp on the left for selected component when it cannot overlap other UI elements like user's avatar // Display timestamp on the left for selected component when it cannot overlap other UI elements like user's avatar
BOOL displayLabelOnLeft = roomBubbleCellData.displayTimestampForSelectedComponentOnLeftWhenPossible && !isFirstDisplayedComponent && !isLastMessageMostRecentComponent; BOOL displayLabelOnLeft = roomBubbleCellData.displayTimestampForSelectedComponentOnLeftWhenPossible
&& !isLastMessageMostRecentComponent
&& ( !isFirstDisplayedComponent || roomBubbleCellData.shouldHideSenderInformation);
[self addTimestampLabelForComponent:component [self addTimestampLabelForComponentIndex:componentIndex
isFirstDisplayedComponent:isFirstDisplayedComponent isFirstDisplayedComponent:isFirstDisplayedComponent
viewTag:componentIndex viewTag:componentIndex
displayOnLeft:displayLabelOnLeft]; displayOnLeft:displayLabelOnLeft];
} }
} }
- (void)addTimestampLabelForComponent:(MXKRoomBubbleComponent*)component - (void)addTimestampLabelForComponentIndex:(NSInteger)componentIndex
isFirstDisplayedComponent:(BOOL)isFirstDisplayedComponent isFirstDisplayedComponent:(BOOL)isFirstDisplayedComponent
viewTag:(NSInteger)viewTag viewTag:(NSInteger)viewTag
displayOnLeft:(BOOL)displayOnLeft displayOnLeft:(BOOL)displayOnLeft
{ {
NSArray *bubbleComponents = bubbleData.bubbleComponents;
MXKRoomBubbleComponent *component = bubbleComponents[componentIndex];
self.bubbleInfoContainer.hidden = NO; self.bubbleInfoContainer.hidden = NO;
CGFloat timeLabelPosX; CGFloat timeLabelPosX;
CGFloat timeLabelPosY; CGFloat timeLabelPosY;
CGFloat timeLabelHeight = RoomBubbleCellLayout.timestampLabelHeight;
CGFloat timeLabelWidth; CGFloat timeLabelWidth;
NSTextAlignment timeLabelTextAlignment; NSTextAlignment timeLabelTextAlignment;
CGRect componentFrame = [self componentFrameInContentViewForIndex:componentIndex];
if (displayOnLeft) if (displayOnLeft)
{ {
CGFloat leftMargin = 10.0; CGFloat leftMargin = 10.0;
CGFloat rightMargin = (self.contentView.frame.size.width - (self.bubbleInfoContainer.frame.origin.x + self.bubbleInfoContainer.frame.size.width)); CGFloat rightMargin = (self.contentView.frame.size.width - (self.bubbleInfoContainer.frame.origin.x + self.bubbleInfoContainer.frame.size.width));
timeLabelPosX = 0; timeLabelPosX = 0;
timeLabelPosY = component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant;
if (CGRectEqualToRect(componentFrame, CGRectNull) == false)
{
timeLabelPosY = componentFrame.origin.y - self.bubbleInfoContainerTopConstraint.constant;
}
else
{
timeLabelPosY = component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant;
}
timeLabelWidth = self.contentView.frame.size.width - leftMargin - rightMargin; timeLabelWidth = self.contentView.frame.size.width - leftMargin - rightMargin;
timeLabelTextAlignment = NSTextAlignmentLeft; timeLabelTextAlignment = NSTextAlignmentLeft;
} }
else else
{ {
timeLabelPosX = self.bubbleInfoContainer.frame.size.width - VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH; timeLabelPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth;
timeLabelPosY = isFirstDisplayedComponent ? 0 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant;
timeLabelWidth = VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH; if (isFirstDisplayedComponent)
{
timeLabelPosY = 0;
}
else if (CGRectEqualToRect(componentFrame, CGRectNull) == false)
{
timeLabelPosY = componentFrame.origin.y - self.bubbleInfoContainerTopConstraint.constant - timeLabelHeight;
}
else
{
timeLabelPosY = component.position.y + self.msgTextViewTopConstraint.constant - timeLabelHeight - self.bubbleInfoContainerTopConstraint.constant;
}
timeLabelWidth = RoomBubbleCellLayout.timestampLabelWidth;
timeLabelTextAlignment = NSTextAlignmentRight; timeLabelTextAlignment = NSTextAlignmentRight;
} }
UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(timeLabelPosX, timeLabelPosY, timeLabelWidth , 18)]; timeLabelPosY = MAX(0.0, timeLabelPosY);
UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(timeLabelPosX, timeLabelPosY, timeLabelWidth, timeLabelHeight)];
timeLabel.text = [bubbleData.eventFormatter timeStringFromDate:component.date]; timeLabel.text = [bubbleData.eventFormatter timeStringFromDate:component.date];
timeLabel.textAlignment = timeLabelTextAlignment; timeLabel.textAlignment = timeLabelTextAlignment;
@ -144,32 +174,10 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
toItem:nil toItem:nil
attribute:NSLayoutAttributeNotAnAttribute attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0 multiplier:1.0
constant:18]; constant:timeLabelHeight];
// Available on iOS 8 and later // Available on iOS 8 and later
[NSLayoutConstraint activateConstraints:@[rightConstraint, topConstraint, widthConstraint, heightConstraint]]; [NSLayoutConstraint activateConstraints:@[rightConstraint, topConstraint, widthConstraint, heightConstraint]];
// Check whether a vertical whitespace was applied to display correctly the timestamp.
if (!displayOnLeft && (!isFirstDisplayedComponent || bubbleData.shouldHideSenderInformation || bubbleData.shouldHideSenderName))
{
// Adjust the position of the potential encryption icon in this case.
if (self.encryptionStatusContainerView)
{
NSArray* subviews = self.encryptionStatusContainerView.subviews;
for (UIView *view in subviews)
{
// Note: The encryption icon has been tagged with the component index.
if (view.tag == viewTag)
{
CGRect frame = view.frame;
frame.origin.y += 15;
view.frame = frame;
break;
}
}
}
}
} }
- (void)selectComponent:(NSUInteger)componentIndex - (void)selectComponent:(NSUInteger)componentIndex
@ -307,7 +315,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
NSDate *date = bubbleData.date; NSDate *date = bubbleData.date;
if (date) if (date)
{ {
UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.bubbleInfoContainer.frame.size.width , 18)]; UILabel *timeLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.bubbleInfoContainer.frame.size.width, RoomBubbleCellLayout.timestampLabelHeight)];
timeLabel.text = [bubbleData.eventFormatter dateStringFromDate:date withTime:NO]; timeLabel.text = [bubbleData.eventFormatter dateStringFromDate:date withTime:NO];
timeLabel.textAlignment = NSTextAlignmentRight; timeLabel.textAlignment = NSTextAlignmentRight;
@ -354,7 +362,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
toItem:nil toItem:nil
attribute:NSLayoutAttributeNotAnAttribute attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0 multiplier:1.0
constant:18]; constant:RoomBubbleCellLayout.timestampLabelHeight];
// Available on iOS 8 and later // Available on iOS 8 and later
[NSLayoutConstraint activateConstraints:@[rightConstraint, topConstraint, widthConstraint, heightConstraint]]; [NSLayoutConstraint activateConstraints:@[rightConstraint, topConstraint, widthConstraint, heightConstraint]];
@ -459,7 +467,13 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
} }
} }
- (CGRect)componentFrameForIndex:(NSInteger)componentIndex - (CGRect)componentFrameInTableViewForIndex:(NSInteger)componentIndex
{
CGRect componentFrameInContentView = [self componentFrameInContentViewForIndex:componentIndex];
return [self.contentView convertRect:componentFrameInContentView toView:self.superview];
}
- (CGRect)componentFrameInContentViewForIndex:(NSInteger)componentIndex
{ {
MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = self; MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = self;
MXKRoomBubbleCellData *bubbleCellData = roomBubbleTableViewCell.bubbleData; MXKRoomBubbleCellData *bubbleCellData = roomBubbleTableViewCell.bubbleData;
@ -518,21 +532,62 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
if (roomBubbleTableViewCell.attachmentView || roomBubbleTableViewCell.messageTextView) if (roomBubbleTableViewCell.attachmentView || roomBubbleTableViewCell.messageTextView)
{ {
CGRect roomBubbleTableViewCellFrame = roomBubbleTableViewCell.frame; CGFloat x = 0;
CGFloat x = roomBubbleTableViewCellFrame.origin.x; CGFloat y = selectedComponenContentViewYOffset + selectedComponentPositionY;
CGFloat y = roomBubbleTableViewCellFrame.origin.y + selectedComponenContentViewYOffset + selectedComponentPositionY; CGFloat width = roomBubbleTableViewCell.contentView.frame.size.width;
CGFloat width = roomBubbleTableViewCellFrame.size.width;
componentFrame = CGRectMake(x, y, width, selectedComponentHeight); componentFrame = CGRectMake(x, y, width, selectedComponentHeight);
} }
else else
{ {
componentFrame = roomBubbleTableViewCell.frame; componentFrame = roomBubbleTableViewCell.bounds;
} }
return componentFrame; return componentFrame;
} }
+ (CGFloat)attachmentBubbleCellHeightForCellData:(MXKCellData *)cellData withMaximumWidth:(CGFloat)maxWidth
{
MXKRoomBubbleTableViewCell* cell = [self cellWithOriginalXib];
CGFloat rowHeight = 0;
RoomBubbleCellData *bubbleData;
if ([cellData isKindOfClass:[RoomBubbleCellData class]])
{
bubbleData = (RoomBubbleCellData*)cellData;
}
if (bubbleData && cell.attachmentView && bubbleData.isAttachmentWithThumbnail)
{
// retrieve the suggested image view height
rowHeight = bubbleData.contentSize.height;
// Check here the minimum height defined in cell view for text message
if (cell.attachViewMinHeightConstraint && rowHeight < cell.attachViewMinHeightConstraint.constant)
{
rowHeight = cell.attachViewMinHeightConstraint.constant;
}
// Finalize the row height by adding the vertical constraints.
rowHeight += cell.attachViewTopConstraint.constant;
CGFloat additionalHeight = bubbleData.additionalContentHeight;
if (additionalHeight)
{
rowHeight += additionalHeight;
}
else
{
rowHeight += cell.attachViewBottomConstraint.constant;
}
}
return rowHeight;
}
#pragma mark - User actions #pragma mark - User actions
- (IBAction)onEditButtonPressed:(id)sender - (IBAction)onEditButtonPressed:(id)sender
@ -581,7 +636,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
// Define 'Edit' button frame // Define 'Edit' button frame
UIImage *editIcon = [UIImage imageNamed:@"edit_icon"]; UIImage *editIcon = [UIImage imageNamed:@"edit_icon"];
CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH - 22 - editIcon.size.width / 2; CGFloat editBtnPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth - 22 - editIcon.size.width / 2;
CGFloat editBtnPosY = isFirstDisplayedComponent ? -13 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13; CGFloat editBtnPosY = isFirstDisplayedComponent ? -13 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant - 13;
UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(editBtnPosX, editBtnPosY, 44, 44)]; UIButton *editButton = [[UIButton alloc] initWithFrame:CGRectMake(editBtnPosX, editBtnPosY, 44, 44)];

View file

@ -886,6 +886,10 @@ internal enum VectorL10n {
internal static func eventFormatterMemberUpdates(_ p1: Int) -> String { internal static func eventFormatterMemberUpdates(_ p1: Int) -> String {
return VectorL10n.tr("Vector", "event_formatter_member_updates", p1) return VectorL10n.tr("Vector", "event_formatter_member_updates", p1)
} }
/// (Edited)
internal static var eventFormatterMessageEditedMention: String {
return VectorL10n.tr("Vector", "event_formatter_message_edited_mention")
}
/// Re-request encryption keys /// Re-request encryption keys
internal static var eventFormatterRerequestKeysPart1Link: String { internal static var eventFormatterRerequestKeysPart1Link: String {
return VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part1_link") return VectorL10n.tr("Vector", "event_formatter_rerequest_keys_part1_link")

View file

@ -31,7 +31,30 @@ NSString *const kAnalyticsE2eCategory = @"E2E";
NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure"; NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
@import PiwikTracker; @import MatomoTracker;
@interface MatomoTracker (MatomoTrackerMigration)
+ (MatomoTracker *)shared;
- (void)migrateFromFourPointFourSharedInstance;
@end
@implementation MatomoTracker (MatomoTrackerMigration)
+ (MatomoTracker *)shared
{
NSDictionary *piwikConfig = [[NSUserDefaults standardUserDefaults] objectForKey:@"piwik"];
MatomoTracker *matomoTracker = [[MatomoTracker alloc] initWithSiteId:piwikConfig[@"siteId"] baseURL:[NSURL URLWithString:piwikConfig[@"url"]] userAgent:@"iOSMatomoTracker"];
[matomoTracker migrateFromFourPointFourSharedInstance];
return matomoTracker;
}
- (void)migrateFromFourPointFourSharedInstance
{
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"migratedFromFourPointFourSharedInstance"]) return;
[self copyFromOldSharedInstance];
[[NSUserDefaults standardUserDefaults] setBool:true forKey:@"migratedFromFourPointFourSharedInstance"];
}
@end
@implementation Analytics @implementation Analytics
@ -49,29 +72,24 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
- (void)start - (void)start
{ {
NSDictionary *piwikConfig = [[NSUserDefaults standardUserDefaults] objectForKey:@"piwik"];
[PiwikTracker configureSharedInstanceWithSiteID:piwikConfig[@"siteId"]
baseURL:[NSURL URLWithString:piwikConfig[@"url"]]
userAgent:@"iOSPiwikTracker"];
// Check whether the user has enabled the sending of crash reports. // Check whether the user has enabled the sending of crash reports.
if (RiotSettings.shared.enableCrashReport) if (RiotSettings.shared.enableCrashReport)
{ {
[PiwikTracker shared].isOptedOut = NO; [MatomoTracker shared].isOptedOut = NO;
[[PiwikTracker shared] setCustomVariableWithIndex:1 name:@"App Platform" value:@"iOS Platform"]; [[MatomoTracker shared] setCustomVariableWithIndex:1 name:@"App Platform" value:@"iOS Platform"];
[[PiwikTracker shared] setCustomVariableWithIndex:2 name:@"App Version" value:[AppDelegate theDelegate].appVersion]; [[MatomoTracker shared] setCustomVariableWithIndex:2 name:@"App Version" value:[AppDelegate theDelegate].appVersion];
// The language is either the one selected by the user within the app // The language is either the one selected by the user within the app
// or, else, the one configured by the OS // or, else, the one configured by the OS
NSString *language = [NSBundle mxk_language] ? [NSBundle mxk_language] : [[NSBundle mainBundle] preferredLocalizations][0]; NSString *language = [NSBundle mxk_language] ? [NSBundle mxk_language] : [[NSBundle mainBundle] preferredLocalizations][0];
[[PiwikTracker shared] setCustomVariableWithIndex:4 name:@"Chosen Language" value:language]; [[MatomoTracker shared] setCustomVariableWithIndex:4 name:@"Chosen Language" value:language];
MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject; MXKAccount* account = [MXKAccountManager sharedManager].activeAccounts.firstObject;
if (account) if (account)
{ {
[[PiwikTracker shared] setCustomVariableWithIndex:7 name:@"Homeserver URL" value:account.mxCredentials.homeServer]; [[MatomoTracker shared] setCustomVariableWithIndex:7 name:@"Homeserver URL" value:account.mxCredentials.homeServer];
[[PiwikTracker shared] setCustomVariableWithIndex:8 name:@"Identity Server URL" value:account.identityServerURL]; [[MatomoTracker shared] setCustomVariableWithIndex:8 name:@"Identity Server URL" value:account.identityServerURL];
} }
// TODO: We should also track device and os version // TODO: We should also track device and os version
@ -83,20 +101,20 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
#ifdef DEBUG #ifdef DEBUG
// Disable analytics in debug as it pollutes stats // Disable analytics in debug as it pollutes stats
[PiwikTracker shared].isOptedOut = YES; [MatomoTracker shared].isOptedOut = YES;
#endif #endif
} }
else else
{ {
NSLog(@"[AppDelegate] The user decided to not send analytics"); NSLog(@"[AppDelegate] The user decided to not send analytics");
[PiwikTracker shared].isOptedOut = YES; [MatomoTracker shared].isOptedOut = YES;
[MXLogger logCrashes:NO]; [MXLogger logCrashes:NO];
} }
} }
- (void)stop - (void)stop
{ {
[PiwikTracker shared].isOptedOut = YES; [MatomoTracker shared].isOptedOut = YES;
[MXLogger logCrashes:NO]; [MXLogger logCrashes:NO];
} }
@ -106,20 +124,20 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
NSString *appName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"]; NSString *appName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"];
NSString *appVersion = [AppDelegate theDelegate].appVersion; NSString *appVersion = [AppDelegate theDelegate].appVersion;
[[PiwikTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName] [[MatomoTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName]
url:nil]; url:nil];
} }
- (void)dispatch - (void)dispatch
{ {
[[PiwikTracker shared] dispatch]; [[MatomoTracker shared] dispatch];
} }
- (void)trackLaunchScreenDisplayDuration:(NSTimeInterval)seconds - (void)trackLaunchScreenDisplayDuration:(NSTimeInterval)seconds
{ {
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory]; NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory [[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action action:action
name:kMXAnalyticsStartupLaunchScreen name:kMXAnalyticsStartupLaunchScreen
number:@(seconds * 1000) number:@(seconds * 1000)
@ -132,7 +150,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{ {
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory]; NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory [[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action action:action
name:kMXAnalyticsStartupStorePreload name:kMXAnalyticsStartupStorePreload
number:@(seconds * 1000) number:@(seconds * 1000)
@ -143,7 +161,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{ {
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory]; NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory [[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action action:action
name:kMXAnalyticsStartupMountData name:kMXAnalyticsStartupMountData
number:@(seconds * 1000) number:@(seconds * 1000)
@ -154,7 +172,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{ {
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory]; NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory [[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action action:action
name:isInitial ? kMXAnalyticsStartupInititialSync : kMXAnalyticsStartupIncrementalSync name:isInitial ? kMXAnalyticsStartupInititialSync : kMXAnalyticsStartupIncrementalSync
number:@(seconds * 1000) number:@(seconds * 1000)
@ -165,7 +183,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{ {
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStatsCategory]; NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStatsCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory [[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action action:action
name:kMXAnalyticsStatsRooms name:kMXAnalyticsStatsRooms
number:@(roomCount) number:@(roomCount)
@ -178,7 +196,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{ {
for (NSString *reason in failuresCounts) for (NSString *reason in failuresCounts)
{ {
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory [[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory
action:kAnalyticsE2eDecryptionFailureAction action:kAnalyticsE2eDecryptionFailureAction
name:reason name:reason
number:failuresCounts[reason] number:failuresCounts[reason]

View file

@ -65,4 +65,19 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag)
*/ */
@property(nonatomic, readonly) NSInteger selectedComponentIndex; @property(nonatomic, readonly) NSInteger selectedComponentIndex;
/**
Return additional content height (read receipts, reactions).
*/
@property(nonatomic, readonly) CGFloat additionalContentHeight;
/**
Indicate to update additional content height.
*/
- (void)setNeedsUpdateAdditionalContentHeight;
/**
Update additional content height if needed.
*/
- (void)updateAdditionalContentHeightIfNeeded;
@end @end

View file

@ -25,11 +25,12 @@
#import "Riot-Swift.h" #import "Riot-Swift.h"
static NSAttributedString *timestampVerticalWhitespace = nil; static NSAttributedString *timestampVerticalWhitespace = nil;
static NSAttributedString *readReceiptVerticalWhitespace = nil;
@interface RoomBubbleCellData() @interface RoomBubbleCellData()
@property(nonatomic, readonly) BOOL addVerticalWhitespaceForSelectedComponentTimestamp; @property(nonatomic, readonly) BOOL addVerticalWhitespaceForSelectedComponentTimestamp;
@property(nonatomic, readwrite) CGFloat additionalContentHeight;
@property(nonatomic) BOOL shouldUpdateAdditionalContentHeight;
@end @end
@ -72,10 +73,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Increase maximum number of components // Increase maximum number of components
self.maxComponentCount = 20; self.maxComponentCount = 20;
// Initialize read receipts
self.readReceipts = [NSMutableDictionary dictionary];
self.readReceipts[event.eventId] = [roomDataSource.room getEventReceipts:event.eventId sorted:YES];
// Reset attributedTextMessage to force reset MXKRoomCellData parameters // Reset attributedTextMessage to force reset MXKRoomCellData parameters
self.attributedTextMessage = nil; self.attributedTextMessage = nil;
@ -107,6 +104,8 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
shouldUpdateComponentsPosition = NO; shouldUpdateComponentsPosition = NO;
} }
[self updateAdditionalContentHeightIfNeeded];
} }
- (NSAttributedString*)attributedTextMessage - (NSAttributedString*)attributedTextMessage
@ -274,12 +273,12 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Check whether there is at least one component. // Check whether there is at least one component.
if (bubbleComponents.count) if (bubbleComponents.count)
{ {
BOOL hasReadReceiptsOrReactions = NO;
// Set position of the first component // Set position of the first component
CGFloat positionY = (self.attachment == nil || self.attachment.type == MXKAttachmentTypeFile || self.attachment.type == MXKAttachmentTypeAudio) ? MXKROOMBUBBLECELLDATA_TEXTVIEW_DEFAULT_VERTICAL_INSET : 0; CGFloat positionY = (self.attachment == nil || self.attachment.type == MXKAttachmentTypeFile || self.attachment.type == MXKAttachmentTypeAudio) ? MXKROOMBUBBLECELLDATA_TEXTVIEW_DEFAULT_VERTICAL_INSET : 0;
MXKRoomBubbleComponent *component; MXKRoomBubbleComponent *component;
NSUInteger index = 0; NSUInteger index = 0;
// Use same position for first components without render (redacted)
for (; index < bubbleComponents.count; index++) for (; index < bubbleComponents.count; index++)
{ {
// Compute the vertical position for next component // Compute the vertical position for next component
@ -289,8 +288,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
if (component.attributedTextMessage) if (component.attributedTextMessage)
{ {
hasReadReceiptsOrReactions = (self.reactions[component.event.eventId].reactions.count > 0);
hasReadReceiptsOrReactions |= (self.readReceipts[component.event.eventId].count > 0);
break; break;
} }
} }
@ -298,31 +295,11 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Check whether the position of other components need to be refreshed // Check whether the position of other components need to be refreshed
if (!self.attachment && index < bubbleComponents.count) if (!self.attachment && index < bubbleComponents.count)
{ {
NSMutableAttributedString *attributedString; NSMutableAttributedString *attributedString = [NSMutableAttributedString new];
NSInteger selectedComponentIndex = self.selectedComponentIndex; NSInteger selectedComponentIndex = self.selectedComponentIndex;
NSInteger lastMessageIndex = self.containsLastMessage ? self.mostRecentComponentIndex : NSNotFound; NSInteger lastMessageIndex = self.containsLastMessage ? self.mostRecentComponentIndex : NSNotFound;
// Check whether the timestamp is displayed for this first component, and check whether a vertical whitespace is required for (index = 0; index < bubbleComponents.count; index++)
if (((selectedComponentIndex == index && self.addVerticalWhitespaceForSelectedComponentTimestamp) || lastMessageIndex == index) && (self.shouldHideSenderInformation || self.shouldHideSenderName))
{
attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[RoomBubbleCellData timestampVerticalWhitespace]];
[attributedString appendAttributedString:component.attributedTextMessage];
}
else
{
// Init attributed string with the first text component
attributedString = [[NSMutableAttributedString alloc] initWithAttributedString:component.attributedTextMessage];
}
// Vertical whitespace is added in case of read receipts
if (hasReadReceiptsOrReactions)
{
[self addVerticalWhitespaceToString:attributedString forEvent:component.event.eventId];
}
[attributedString appendAttributedString:[MXKRoomBubbleCellDataWithAppendingMode messageSeparator]];
for (index++; index < bubbleComponents.count; index++)
{ {
// Compute the vertical position for next component // Compute the vertical position for next component
component = bubbleComponents[index]; component = bubbleComponents[index];
@ -330,17 +307,12 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
if (component.attributedTextMessage) if (component.attributedTextMessage)
{ {
// Prepare its attributed string by considering potential vertical margin required to display timestamp. // Prepare its attributed string by considering potential vertical margin required to display timestamp.
NSAttributedString *componentString; NSAttributedString *componentString = component.attributedTextMessage;
// Check whether the timestamp is displayed for this component, and check whether a vertical whitespace is required
if ((selectedComponentIndex == index && self.addVerticalWhitespaceForSelectedComponentTimestamp) || lastMessageIndex == index) if ((selectedComponentIndex == index && self.addVerticalWhitespaceForSelectedComponentTimestamp) || lastMessageIndex == index)
{ {
NSMutableAttributedString *componentAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[RoomBubbleCellData timestampVerticalWhitespace]]; [attributedString appendAttributedString:[RoomBubbleCellData timestampVerticalWhitespace]];
[componentAttributedString appendAttributedString:component.attributedTextMessage];
componentString = componentAttributedString;
}
else
{
componentString = component.attributedTextMessage;
} }
// Append this attributed string. // Append this attributed string.
@ -353,9 +325,10 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
positionY = MXKROOMBUBBLECELLDATA_TEXTVIEW_DEFAULT_VERTICAL_INSET + (cumulatedHeight - [self rawTextHeight:componentString]); positionY = MXKROOMBUBBLECELLDATA_TEXTVIEW_DEFAULT_VERTICAL_INSET + (cumulatedHeight - [self rawTextHeight:componentString]);
component.position = CGPointMake(0, positionY); component.position = CGPointMake(0, positionY);
// Vertical whitespace is added in case of read receipts or reactions
[self addVerticalWhitespaceToString:attributedString forEvent:component.event.eventId]; [self addVerticalWhitespaceToString:attributedString forEvent:component.event.eventId];
[attributedString appendAttributedString:[MXKRoomBubbleCellDataWithAppendingMode messageSeparator]]; [attributedString appendAttributedString:[MXKRoomBubbleCellDataWithAppendingMode messageSeparator]];
} }
else else
@ -377,8 +350,10 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
if (reactionCount) if (reactionCount)
{ {
CGFloat bubbleReactionsViewWidth = self.maxTextViewWidth - 4;
CGSize fittingSize = UILayoutFittingCompressedSize; CGSize fittingSize = UILayoutFittingCompressedSize;
fittingSize.width = self.maxTextViewWidth; fittingSize.width = bubbleReactionsViewWidth;
static BubbleReactionsView *bubbleReactionsView; static BubbleReactionsView *bubbleReactionsView;
@ -387,12 +362,13 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
bubbleReactionsView = [BubbleReactionsView new]; bubbleReactionsView = [BubbleReactionsView new];
}); });
bubbleReactionsView.frame = CGRectMake(0, 0, self.maxTextViewWidth, 1.0); bubbleReactionsView.frame = CGRectMake(0, 0, bubbleReactionsViewWidth, 1.0);
BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId]; BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId];
bubbleReactionsView.viewModel = viemModel; bubbleReactionsView.viewModel = viemModel;
[bubbleReactionsView setNeedsLayout];
[bubbleReactionsView layoutIfNeeded]; [bubbleReactionsView layoutIfNeeded];
CGFloat height = [bubbleReactionsView systemLayoutSizeFittingSize:fittingSize].height; CGFloat height = [bubbleReactionsView systemLayoutSizeFittingSize:fittingSize].height + RoomBubbleCellLayout.reactionsViewTopMargin;
[attributedString appendAttributedString:[RoomBubbleCellData verticalWhitespaceForHeight: height]]; [attributedString appendAttributedString:[RoomBubbleCellData verticalWhitespaceForHeight: height]];
} }
@ -400,10 +376,103 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Add vertical whitespace in case of read receipts. // Add vertical whitespace in case of read receipts.
if (self.readReceipts[eventId].count) if (self.readReceipts[eventId].count)
{ {
[attributedString appendAttributedString:[RoomBubbleCellData readReceiptVerticalWhitespace]]; [attributedString appendAttributedString:[RoomBubbleCellData verticalWhitespaceForHeight:RoomBubbleCellLayout.readReceiptsViewHeight + RoomBubbleCellLayout.readReceiptsViewTopMargin]];
} }
} }
- (CGFloat)computeAdditionalHeight
{
CGFloat height = 0;
for (MXKRoomBubbleComponent *bubbleComponent in self.bubbleComponents)
{
NSString *eventId = bubbleComponent.event.eventId;
height+= [self reactionHeightForEventId:eventId];
height+= [self readReceiptHeightForEventId:eventId];
}
return height;
}
- (void)updateAdditionalContentHeightIfNeeded;
{
if (self.shouldUpdateAdditionalContentHeight)
{
void(^updateAdditionalHeight)(void) = ^() {
self.additionalContentHeight = [self computeAdditionalHeight];
};
// The additional height depends on the room read receipts and reactions view which must be calculated on the main thread.
// Check here the current thread, this is just a sanity check because this method is called during the rendering step
// which takes place on the main thread.
if ([NSThread currentThread] != [NSThread mainThread])
{
NSLog(@"[RoomBubbleCellData] prepareBubbleComponentsPosition called on wrong thread");
dispatch_sync(dispatch_get_main_queue(), ^{
updateAdditionalHeight();
});
}
else
{
updateAdditionalHeight();
}
self.shouldUpdateAdditionalContentHeight = NO;
}
}
- (void)setNeedsUpdateAdditionalContentHeight
{
self.shouldUpdateAdditionalContentHeight = YES;
}
- (CGFloat)reactionHeightForEventId:(NSString*)eventId
{
CGFloat height = 0;
NSUInteger reactionCount = self.reactions[eventId].reactions.count;
MXAggregatedReactions *aggregatedReactions = self.reactions[eventId];
if (reactionCount)
{
CGFloat bubbleReactionsViewWidth = self.maxTextViewWidth - 4;
CGSize fittingSize = UILayoutFittingCompressedSize;
fittingSize.width = bubbleReactionsViewWidth;
static BubbleReactionsView *bubbleReactionsView;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
bubbleReactionsView = [BubbleReactionsView new];
});
bubbleReactionsView.frame = CGRectMake(0, 0, bubbleReactionsViewWidth, 1.0);
BubbleReactionsViewModel *viemModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:aggregatedReactions eventId:eventId];
bubbleReactionsView.viewModel = viemModel;
[bubbleReactionsView setNeedsLayout];
[bubbleReactionsView layoutIfNeeded];
height = [bubbleReactionsView systemLayoutSizeFittingSize:fittingSize].height + RoomBubbleCellLayout.reactionsViewTopMargin;
}
return height;
}
- (CGFloat)readReceiptHeightForEventId:(NSString*)eventId
{
CGFloat height = 0;
if (self.readReceipts[eventId].count)
{
height = RoomBubbleCellLayout.readReceiptsViewHeight + RoomBubbleCellLayout.readReceiptsViewTopMargin;
}
return height;
}
- (void)setContainsLastMessage:(BOOL)containsLastMessage - (void)setContainsLastMessage:(BOOL)containsLastMessage
{ {
// Check whether there is something to do // Check whether there is something to do
@ -509,33 +578,21 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
return timestampVerticalWhitespace; return timestampVerticalWhitespace;
} }
+ (NSAttributedString *)readReceiptVerticalWhitespace
{
@synchronized(self)
{
if (readReceiptVerticalWhitespace == nil)
{
readReceiptVerticalWhitespace = [[NSAttributedString alloc] initWithString:@"\n\n" attributes:@{NSForegroundColorAttributeName : [UIColor blackColor],
NSFontAttributeName: [UIFont systemFontOfSize:4]}];
}
}
return readReceiptVerticalWhitespace;
}
+ (NSAttributedString *)verticalWhitespaceForHeight:(CGFloat)height + (NSAttributedString *)verticalWhitespaceForHeight:(CGFloat)height
{ {
NSUInteger returns = height / 6; UIFont *sizingFont = [UIFont systemFontOfSize:2];
CGFloat returnHeight = sizingFont.lineHeight;
NSUInteger returns = (NSUInteger)round(height/returnHeight);
NSMutableString *returnString = [NSMutableString string]; NSMutableString *returnString = [NSMutableString string];
for (NSUInteger i = 0; i < returns; i++) for (NSUInteger i = 0; i < returns; i++)
{ {
[returnString appendString:@"\n"]; [returnString appendString:@"\n"];
} }
return [[NSAttributedString alloc] initWithString:returnString attributes:@{NSForegroundColorAttributeName : [UIColor blackColor], return [[NSAttributedString alloc] initWithString:returnString attributes:@{NSForegroundColorAttributeName : [UIColor blackColor],
NSFontAttributeName: [UIFont systemFontOfSize:6]}]; NSFontAttributeName: sizingFont}];
} }
- (BOOL)hasSameSenderAsBubbleCellData:(id<MXKRoomBubbleCellDataStoring>)bubbleCellData - (BOOL)hasSameSenderAsBubbleCellData:(id<MXKRoomBubbleCellDataStoring>)bubbleCellData
@ -569,9 +626,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
return NO; return NO;
} }
// Update read receipts for this bubble
self.readReceipts[event.eventId] = [roomDataSource.room getEventReceipts:event.eventId sorted:YES];
return [super addEvent:event andRoomState:roomState]; return [super addEvent:event andRoomState:roomState];
} }

View file

@ -16,7 +16,7 @@
import UIKit import UIKit
final class ReactionsMenuViewModel: ReactionsMenuViewModelType { @objc final class ReactionsMenuViewModel: NSObject, ReactionsMenuViewModelType {
// MARK: - Properties // MARK: - Properties
@ -33,14 +33,16 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
private(set) var isDislikeButtonSelected: Bool = false private(set) var isDislikeButtonSelected: Bool = false
weak var viewDelegate: ReactionsMenuViewModelDelegate? weak var viewDelegate: ReactionsMenuViewModelDelegate?
weak var coordinatorDelegate: ReactionsMenuViewModelCoordinatorDelegate? @objc weak var coordinatorDelegate: ReactionsMenuViewModelCoordinatorDelegate?
// MARK: - Setup // MARK: - Setup
init(aggregations: MXAggregations, roomId: String, eventId: String) { @objc init(aggregations: MXAggregations, roomId: String, eventId: String) {
self.aggregations = aggregations self.aggregations = aggregations
self.roomId = roomId self.roomId = roomId
self.eventId = eventId self.eventId = eventId
super.init()
self.loadData() self.loadData()
self.listenToDataUpdate() self.listenToDataUpdate()
@ -72,7 +74,7 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
return return
} }
self.react(withReaction: theReaction, selected: theNewState, delegate: self.coordinatorDelegate) self.react(withReaction: theReaction, selected: theNewState)
} }
// MARK: - Private // MARK: - Private
@ -85,7 +87,7 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
} }
private func loadData() { private func loadData() {
guard let reactionCounts = self.aggregations.aggregatedReactions(onEvent: self.eventId, inRoom: self.roomId)?.reactions else { guard let reactionCounts = self.aggregations.aggregatedReactions(onEvent: self.eventId, inRoom: self.roomId)?.withNonZeroCount()?.reactions else {
return return
} }
@ -122,54 +124,21 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
} }
} }
} }
private func react(withReaction reaction: ReactionsMenuReaction, selected: Bool, delegate: ReactionsMenuViewModelCoordinatorDelegate? = nil) { private func react(withReaction reaction: ReactionsMenuReaction, selected: Bool) {
// If required, unreact first // If required, unreact first
if selected { if selected {
self.ensure3StateButtons(withReaction: reaction) self.ensure3StateButtons(withReaction: reaction)
} }
let reactionString = reaction.rawValue
if selected { if selected {
self.aggregations.sendReaction(reaction.rawValue, toEvent: self.eventId, inRoom: self.roomId, success: {[weak self] _ in self.coordinatorDelegate?.reactionsMenuViewModel(self, didAddReaction: reactionString, forEventId: self.eventId)
guard let sself = self else {
return
}
delegate?.reactionsMenuViewModel(sself, didReactionComplete: reaction.rawValue, isAddReaction: true)
}, failure: {[weak self] (error) in
print("[ReactionsMenuViewModel] react: Error: \(error)")
guard let sself = self else {
return
}
delegate?.reactionsMenuViewModel(sself, didReactionFailedWithError: error, reaction: reaction.rawValue, isAddReaction: true)
})
} else { } else {
self.coordinatorDelegate?.reactionsMenuViewModel(self, didRemoveReaction: reactionString, forEventId: self.eventId)
self.aggregations.unReact(onReaction: reaction.rawValue, toEvent: self.eventId, inRoom: self.roomId, success: {[weak self] in
guard let sself = self else {
return
}
delegate?.reactionsMenuViewModel(sself, didReactionComplete: reaction.rawValue, isAddReaction: false)
}, failure: {[weak self] (error) in
print("[ReactionsMenuViewModel] react: Error: \(error)")
guard let sself = self else {
return
}
delegate?.reactionsMenuViewModel(sself, didReactionFailedWithError: error, reaction: reaction.rawValue, isAddReaction: false)
})
} }
delegate?.reactionsMenuViewModel(self, didSendReaction: reaction.rawValue, isAddReaction: !selected)
} }
// We can like, dislike, be indifferent but we cannot like & dislike at the same time // We can like, dislike, be indifferent but we cannot like & dislike at the same time

View file

@ -20,10 +20,9 @@ protocol ReactionsMenuViewModelDelegate: class {
func reactionsMenuViewModelDidUpdate(_ viewModel: ReactionsMenuViewModelType) func reactionsMenuViewModelDidUpdate(_ viewModel: ReactionsMenuViewModelType)
} }
protocol ReactionsMenuViewModelCoordinatorDelegate: class { @objc protocol ReactionsMenuViewModelCoordinatorDelegate: class {
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didSendReaction reaction: String, isAddReaction: Bool) func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didAddReaction reaction: String, forEventId eventId: String)
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didReactionComplete reaction: String, isAddReaction: Bool) func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didRemoveReaction reaction: String, forEventId eventId: String)
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didReactionFailedWithError error: Error, reaction: String, isAddReaction: Bool)
} }

View file

@ -106,10 +106,8 @@ final class RoomContextualMenuPresenter: NSObject {
animationCompletionInstructions() animationCompletionInstructions()
} }
} }
func showReactionsMenu(forEvent eventId: String, inRoom roomId: String, session: MXSession, func showReactionsMenu(reactionsMenuViewModel: ReactionsMenuViewModel, aroundFrame frame: CGRect) {
aroundFrame frame: CGRect) {
let reactionsMenuViewModel = ReactionsMenuViewModel(aggregations: session.aggregations, roomId: roomId, eventId: eventId)
self.roomContextualMenuViewController?.showReactionsMenu(withViewModel: reactionsMenuViewModel, aroundFrame: frame) self.roomContextualMenuViewController?.showReactionsMenu(withViewModel: reactionsMenuViewModel, aroundFrame: frame)
} }
} }

View file

@ -99,7 +99,6 @@ final class RoomContextualMenuViewController: UIViewController, Themable {
func showReactionsMenu(withViewModel viewModel: ReactionsMenuViewModel, aroundFrame frame: CGRect) { func showReactionsMenu(withViewModel viewModel: ReactionsMenuViewModel, aroundFrame frame: CGRect) {
self.reactionsMenuView.viewModel = viewModel self.reactionsMenuView.viewModel = viewModel
self.reactionsMenuView.viewModel?.coordinatorDelegate = self
self.reactionsMenuView.isHidden = false self.reactionsMenuView.isHidden = false
let menuHeight = self.reactionsMenuViewHeightConstraint.constant let menuHeight = self.reactionsMenuViewHeightConstraint.constant
@ -151,22 +150,6 @@ final class RoomContextualMenuViewController: UIViewController, Themable {
} }
} }
// MARK: - ReactionsMenuViewModelCoordinatorDelegate
extension RoomContextualMenuViewController: ReactionsMenuViewModelCoordinatorDelegate {
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didSendReaction reaction: String, isAddReaction: Bool) {
self.delegate?.roomContextualMenuViewControllerDidReaction(self)
}
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didReactionComplete reaction: String, isAddReaction: Bool) {
}
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didReactionFailedWithError error: Error, reaction: String, isAddReaction: Bool) {
self.errorPresenter?.presentError(from: self, forError: error, animated: true) {
}
}
}
// MARK: - UIGestureRecognizerDelegate // MARK: - UIGestureRecognizerDelegate
extension RoomContextualMenuViewController: UIGestureRecognizerDelegate { extension RoomContextualMenuViewController: UIGestureRecognizerDelegate {

View file

@ -28,8 +28,6 @@
#import "MXRoom+Riot.h" #import "MXRoom+Riot.h"
static CGFloat kBubbleReactionsViewLeftMargin = 55.0;
static CGFloat kBubbleReactionsViewRightMargin = 15.0;
@interface RoomDataSource() <BubbleReactionsViewModelDelegate> @interface RoomDataSource() <BubbleReactionsViewModelDelegate>
{ {
@ -122,87 +120,29 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
[super destroy]; [super destroy];
} }
- (void)didReceiveReceiptEvent:(MXEvent *)receiptEvent roomState:(MXRoomState *)roomState - (void)updateCellDataReactions:(id<MXKRoomBubbleCellDataStoring>)cellData forEventId:(NSString*)eventId
{ {
// Do the processing on the same processing queue as MXKRoomDataSource [super updateCellDataReactions:cellData forEventId:eventId];
dispatch_async(MXKRoomDataSource.processingQueue, ^{
// Remove the previous displayed read receipt for each user who sent a [self setNeedsUpdateAdditionalContentHeightForCellData:cellData];
// new read receipt. }
// To implement it, we need to find the sender id of each new read receipt
// among the read receipts array of all events in all bubbles.
NSArray *readReceiptSenders = receiptEvent.readReceiptSenders;
@synchronized(bubbles) - (void)updateCellData:(MXKRoomBubbleCellData*)cellData withReadReceipts:(NSArray<MXReceiptData*>*)readReceipts forEventId:(NSString*)eventId
{ {
for (RoomBubbleCellData *cellData in bubbles) [super updateCellData:cellData withReadReceipts:readReceipts forEventId:eventId];
{
NSMutableDictionary<NSString* /* eventId */, NSArray<MXReceiptData*> *> *updatedCellDataReadReceipts = [NSMutableDictionary dictionary]; [self setNeedsUpdateAdditionalContentHeightForCellData:cellData];
}
for (NSString *eventId in cellData.readReceipts) - (void)setNeedsUpdateAdditionalContentHeightForCellData:(id<MXKRoomBubbleCellDataStoring>)cellData
{ {
for (MXReceiptData *receiptData in cellData.readReceipts[eventId]) RoomBubbleCellData *roomBubbleCellData;
{
for (NSString *senderId in readReceiptSenders) if ([cellData isKindOfClass:[RoomBubbleCellData class]])
{ {
if ([receiptData.userId isEqualToString:senderId]) roomBubbleCellData = (RoomBubbleCellData*)cellData;
{ [roomBubbleCellData setNeedsUpdateAdditionalContentHeight];
if (!updatedCellDataReadReceipts[eventId]) }
{
updatedCellDataReadReceipts[eventId] = cellData.readReceipts[eventId];
}
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"userId!=%@", receiptData.userId];
updatedCellDataReadReceipts[eventId] = [updatedCellDataReadReceipts[eventId] filteredArrayUsingPredicate:predicate];
break;
}
}
}
}
// Flush found changed to the cell data
for (NSString *eventId in updatedCellDataReadReceipts)
{
if (updatedCellDataReadReceipts[eventId].count)
{
cellData.readReceipts[eventId] = updatedCellDataReadReceipts[eventId];
}
else
{
cellData.readReceipts[eventId] = nil;
}
}
}
}
// Update cell data we have received a read receipt for
NSArray *readEventIds = receiptEvent.readReceiptEventIds;
for (NSString* eventId in readEventIds)
{
RoomBubbleCellData *cellData = [self cellDataOfEventWithEventId:eventId];
if (cellData)
{
@synchronized(bubbles)
{
if (!cellData.hasNoDisplay)
{
cellData.readReceipts[eventId] = [self.room getEventReceipts:eventId sorted:YES];
}
else
{
// Ignore the read receipts on the events without an actual display.
cellData.readReceipts[eventId] = nil;
}
}
}
}
dispatch_async(dispatch_get_main_queue(), ^{
// TODO: Be smarter and update only updated cells
[super didReceiveReceiptEvent:receiptEvent roomState:roomState];
});
});
} }
#pragma mark - #pragma mark -
@ -267,6 +207,8 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
[bubbleCell addTimestampLabelForComponent:cellData.mostRecentComponentIndex]; [bubbleCell addTimestampLabelForComponent:cellData.mostRecentComponentIndex];
} }
NSMutableArray *temporaryViews = [NSMutableArray new];
// Handle read receipts and read marker display. // Handle read receipts and read marker display.
// Ignore the read receipts on the bubble without actual display. // Ignore the read receipts on the bubble without actual display.
// Ignore the read receipts on collapsed bubbles // Ignore the read receipts on collapsed bubbles
@ -274,17 +216,71 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
{ {
// Read receipts container are inserted here on the right side into the content view. // Read receipts container are inserted here on the right side into the content view.
// Some vertical whitespaces are added in message text view (see RoomBubbleCellData class) to insert correctly multiple receipts. // Some vertical whitespaces are added in message text view (see RoomBubbleCellData class) to insert correctly multiple receipts.
NSInteger index = bubbleComponents.count;
CGFloat bottomPositionY = bubbleCell.frame.size.height; NSInteger index = 0;
while (index--)
for (MXKRoomBubbleComponent *component in bubbleComponents)
{ {
MXKRoomBubbleComponent *component = bubbleComponents[index];
NSString *componentEventId = component.event.eventId; NSString *componentEventId = component.event.eventId;
if (component.event.sentState != MXEventSentStateFailed) if (component.event.sentState != MXEventSentStateFailed)
{ {
CGFloat bottomPositionY;
CGRect bubbleComponentFrame = [bubbleCell componentFrameInContentViewForIndex:index];
if (CGRectEqualToRect(bubbleComponentFrame, CGRectNull) == NO)
{
bottomPositionY = bubbleComponentFrame.origin.y + bubbleComponentFrame.size.height;
}
else
{
continue;
}
MXAggregatedReactions* reactions = cellData.reactions[componentEventId];
BubbleReactionsView *reactionsView;
if (reactions && !isCollapsableCellCollapsed)
{
BubbleReactionsViewModel *bubbleReactionsViewModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:reactions eventId:componentEventId];
reactionsView = [BubbleReactionsView new];
reactionsView.viewModel = bubbleReactionsViewModel;
[reactionsView updateWithTheme:ThemeService.shared.theme];
[temporaryViews addObject:reactionsView];
bubbleReactionsViewModel.viewModelDelegate = self;
reactionsView.translatesAutoresizingMaskIntoConstraints = NO;
[bubbleCell.contentView addSubview:reactionsView];
if (!bubbleCell.tmpSubviews)
{
bubbleCell.tmpSubviews = [NSMutableArray array];
}
[bubbleCell.tmpSubviews addObject:reactionsView];
CGFloat leftMargin = RoomBubbleCellLayout.reactionsViewLeftMargin;
if (self.room.summary.isEncrypted)
{
leftMargin+= RoomBubbleCellLayout.encryptedContentLeftMargin;
}
// Force receipts container size
[NSLayoutConstraint activateConstraints:
@[
[reactionsView.leadingAnchor constraintEqualToAnchor:reactionsView.superview.leadingAnchor constant:leftMargin],
[reactionsView.trailingAnchor constraintEqualToAnchor:reactionsView.superview.trailingAnchor constant:-RoomBubbleCellLayout.reactionsViewRightMargin],
[reactionsView.topAnchor constraintEqualToAnchor:reactionsView.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.reactionsViewTopMargin]
]];
}
MXKReceiptSendersContainer* avatarsContainer; MXKReceiptSendersContainer* avatarsContainer;
// Handle read receipts (if any) // Handle read receipts (if any)
if (self.showBubbleReceipts && cellData.readReceipts.count && !isCollapsableCellCollapsed) if (self.showBubbleReceipts && cellData.readReceipts.count && !isCollapsableCellCollapsed)
{ {
@ -315,7 +311,7 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
if (roomMembers.count) if (roomMembers.count)
{ {
// Define the read receipts container, positioned on the right border of the bubble cell (Note the right margin 6 pts). // Define the read receipts container, positioned on the right border of the bubble cell (Note the right margin 6 pts).
avatarsContainer = [[MXKReceiptSendersContainer alloc] initWithFrame:CGRectMake(bubbleCell.frame.size.width - 156, bottomPositionY - 13, 150, 12) andMediaManager:self.mxSession.mediaManager]; avatarsContainer = [[MXKReceiptSendersContainer alloc] initWithFrame:CGRectMake(bubbleCell.frame.size.width - RoomBubbleCellLayout.readReceiptsViewWidth + RoomBubbleCellLayout.readReceiptsViewRightMargin, bottomPositionY + RoomBubbleCellLayout.readReceiptsViewTopMargin, RoomBubbleCellLayout.readReceiptsViewWidth, RoomBubbleCellLayout.readReceiptsViewHeight) andMediaManager:self.mxSession.mediaManager];
// Custom avatar display // Custom avatar display
avatarsContainer.maxDisplayedAvatars = 5; avatarsContainer.maxDisplayedAvatars = 5;
@ -337,6 +333,8 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
avatarsContainer.translatesAutoresizingMaskIntoConstraints = NO; avatarsContainer.translatesAutoresizingMaskIntoConstraints = NO;
avatarsContainer.accessibilityIdentifier = @"readReceiptsContainer"; avatarsContainer.accessibilityIdentifier = @"readReceiptsContainer";
[temporaryViews addObject:avatarsContainer];
// Add this read receipts container in the content view // Add this read receipts container in the content view
if (!bubbleCell.tmpSubviews) if (!bubbleCell.tmpSubviews)
{ {
@ -355,14 +353,14 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
toItem:nil toItem:nil
attribute:NSLayoutAttributeNotAnAttribute attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0 multiplier:1.0
constant:150]; constant:RoomBubbleCellLayout.readReceiptsViewWidth];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
attribute:NSLayoutAttributeHeight attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual relatedBy:NSLayoutRelationEqual
toItem:nil toItem:nil
attribute:NSLayoutAttributeNotAnAttribute attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0 multiplier:1.0
constant:12]; constant:RoomBubbleCellLayout.readReceiptsViewHeight];
// Force receipts container position // Force receipts container position
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
@ -371,61 +369,25 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
toItem:avatarsContainer.superview toItem:avatarsContainer.superview
attribute:NSLayoutAttributeTrailing attribute:NSLayoutAttributeTrailing
multiplier:1.0 multiplier:1.0
constant:-6]; constant:-RoomBubbleCellLayout.readReceiptsViewRightMargin];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
attribute:NSLayoutAttributeTop // At the bottom, we have reactions or nothing
relatedBy:NSLayoutRelationEqual NSLayoutConstraint *topConstraint;
toItem:avatarsContainer.superview if (reactionsView)
attribute:NSLayoutAttributeTop {
multiplier:1.0 topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
constant:bottomPositionY - 13]; }
else
{
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:avatarsContainer.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.readReceiptsViewTopMargin];
}
// Available on iOS 8 and later // Available on iOS 8 and later
[NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, topConstraint, trailingConstraint]]; [NSLayoutConstraint activateConstraints:@[widthConstraint, heightConstraint, topConstraint, trailingConstraint]];
} }
} }
MXAggregatedReactions* reactions = cellData.reactions[componentEventId];
if (reactions && !isCollapsableCellCollapsed)
{
BubbleReactionsViewModel *bubbleReactionsViewModel = [[BubbleReactionsViewModel alloc] initWithAggregatedReactions:reactions eventId:componentEventId];
BubbleReactionsView *reactionsView = [BubbleReactionsView new];
reactionsView.viewModel = bubbleReactionsViewModel;
[reactionsView updateWithTheme:ThemeService.shared.theme];
bubbleReactionsViewModel.viewModelDelegate = self;
reactionsView.translatesAutoresizingMaskIntoConstraints = NO;
[bubbleCell.contentView addSubview:reactionsView];
if (!bubbleCell.tmpSubviews)
{
bubbleCell.tmpSubviews = [NSMutableArray array];
}
[bubbleCell.tmpSubviews addObject:reactionsView];
// At the bottom, we have read receipts or nothing
NSLayoutConstraint *bottomConstraint;
if (avatarsContainer)
{
bottomConstraint = [reactionsView.bottomAnchor constraintEqualToAnchor:avatarsContainer.topAnchor];
}
else
{
bottomConstraint = [reactionsView.bottomAnchor constraintEqualToAnchor:reactionsView.superview.topAnchor constant:bottomPositionY];
}
// Force receipts container size
[NSLayoutConstraint activateConstraints:
@[
[reactionsView.leadingAnchor constraintEqualToAnchor:reactionsView.superview.leadingAnchor constant:kBubbleReactionsViewLeftMargin],
[reactionsView.trailingAnchor constraintEqualToAnchor:reactionsView.superview.trailingAnchor constant:-kBubbleReactionsViewRightMargin],
bottomConstraint
]];
}
// Check whether the read marker must be displayed here. // Check whether the read marker must be displayed here.
if (self.showReadMarker) if (self.showReadMarker)
{ {
@ -438,7 +400,7 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
if ([componentEventId isEqualToString:self.room.accountData.readMarkerEventId]) if ([componentEventId isEqualToString:self.room.accountData.readMarkerEventId])
{ {
bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - 2, bubbleCell.bubbleOverlayContainer.frame.size.width, 2)]; bubbleCell.readMarkerView = [[UIView alloc] initWithFrame:CGRectMake(0, bottomPositionY - RoomBubbleCellLayout.readMarkerViewHeight, bubbleCell.bubbleOverlayContainer.frame.size.width, RoomBubbleCellLayout.readMarkerViewHeight)];
bubbleCell.readMarkerView.backgroundColor = ThemeService.shared.theme.tintColor; bubbleCell.readMarkerView.backgroundColor = ThemeService.shared.theme.tintColor;
// Hide by default the marker, it will be shown and animated when the cell will be rendered. // Hide by default the marker, it will be shown and animated when the cell will be rendered.
bubbleCell.readMarkerView.hidden = YES; bubbleCell.readMarkerView.hidden = YES;
@ -450,45 +412,58 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
// Force read marker constraints // Force read marker constraints
bubbleCell.readMarkerViewTopConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView bubbleCell.readMarkerViewTopConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView
attribute:NSLayoutAttributeTop attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:bottomPositionY - 2];
bubbleCell.readMarkerViewLeadingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0];
bubbleCell.readMarkerViewTrailingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual relatedBy:NSLayoutRelationEqual
toItem:bubbleCell.readMarkerView toItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeTrailing attribute:NSLayoutAttributeTop
multiplier:1.0 multiplier:1.0
constant:0]; constant:bottomPositionY - RoomBubbleCellLayout.readMarkerViewHeight];
bubbleCell.readMarkerViewLeadingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView
attribute:NSLayoutAttributeLeading
relatedBy:NSLayoutRelationEqual
toItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeLeading
multiplier:1.0
constant:0];
bubbleCell.readMarkerViewTrailingConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeTrailing
relatedBy:NSLayoutRelationEqual
toItem:bubbleCell.readMarkerView
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:0];
bubbleCell.readMarkerViewHeightConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView bubbleCell.readMarkerViewHeightConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView
attribute:NSLayoutAttributeHeight attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual relatedBy:NSLayoutRelationEqual
toItem:nil toItem:nil
attribute:NSLayoutAttributeNotAnAttribute attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0 multiplier:1.0
constant:2]; constant:RoomBubbleCellLayout.readMarkerViewHeight];
[NSLayoutConstraint activateConstraints:@[bubbleCell.readMarkerViewTopConstraint, bubbleCell.readMarkerViewLeadingConstraint, bubbleCell.readMarkerViewTrailingConstraint, bubbleCell.readMarkerViewHeightConstraint]]; [NSLayoutConstraint activateConstraints:@[bubbleCell.readMarkerViewTopConstraint, bubbleCell.readMarkerViewLeadingConstraint, bubbleCell.readMarkerViewTrailingConstraint, bubbleCell.readMarkerViewHeightConstraint]];
} }
} }
} }
// Prepare the bottom position for the next read receipt container (if any) index++;
bottomPositionY = bubbleCell.msgTextViewTopConstraint.constant + component.position.y;
} }
} }
// Update attachmentView bottom constraint to display reactions and read receipts if needed
UIView *attachmentView = bubbleCell.attachmentView;
NSLayoutConstraint *attachmentViewBottomConstraint = bubbleCell.attachViewBottomConstraint;
if (attachmentView && temporaryViews.count)
{
attachmentViewBottomConstraint.constant = roomBubbleCellData.additionalContentHeight;
}
else if (attachmentView)
{
[bubbleCell resetAttachmentViewBottomConstraintConstant];
}
// Check whether an event is currently selected: the other messages are then blurred // Check whether an event is currently selected: the other messages are then blurred
if (_selectedEventId) if (_selectedEventId)
{ {
@ -581,19 +556,19 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
- (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didAddReaction:(MXReactionCount *)reactionCount forEventId:(NSString *)eventId - (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didAddReaction:(MXReactionCount *)reactionCount forEventId:(NSString *)eventId
{ {
[self.mxSession.aggregations sendReaction:reactionCount.reaction toEvent:eventId inRoom:self.roomId success:^(NSString * _Nonnull eventId) { [self addReaction:reactionCount.reaction forEventId:eventId success:^{
} failure:^(NSError *error) {
} failure:^(NSError * _Nonnull error) {
NSLog(@"[MXKRoomDataSource] Fail to send reaction on eventId: %@", eventId);
}]; }];
} }
- (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didRemoveReaction:(MXReactionCount * _Nonnull)reactionCount forEventId:(NSString * _Nonnull)eventId - (void)bubbleReactionsViewModel:(BubbleReactionsViewModel *)viewModel didRemoveReaction:(MXReactionCount * _Nonnull)reactionCount forEventId:(NSString * _Nonnull)eventId
{ {
[self.mxSession.aggregations unReactOnReaction:reactionCount.reaction toEvent:eventId inRoom:self.roomId success:^{ [self removeReaction:reactionCount.reaction forEventId:eventId success:^{
} failure:^(NSError *error) {
} failure:^(NSError * _Nonnull error) {
NSLog(@"[MXKRoomDataSource] Fail to unreact on eventId: %@", eventId);
}]; }];
} }

View file

@ -123,7 +123,8 @@
#import "Riot-Swift.h" #import "Riot-Swift.h"
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate> @interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate,
ReactionsMenuViewModelCoordinatorDelegate>
{ {
// The expanded header // The expanded header
ExpandedRoomTitleView *expandedHeader; ExpandedRoomTitleView *expandedHeader;
@ -216,6 +217,8 @@
@property (nonatomic, weak) IBOutlet UIView *overlayContainerView; @property (nonatomic, weak) IBOutlet UIView *overlayContainerView;
@property (nonatomic, strong) RoomContextualMenuPresenter *roomContextualMenuPresenter; @property (nonatomic, strong) RoomContextualMenuPresenter *roomContextualMenuPresenter;
@property (nonatomic, strong) MXKErrorAlertPresentation *errorPresenter;
@property (nonatomic, strong) NSString *textMessageBeforeEditing;
@end @end
@ -409,6 +412,7 @@
} }
self.roomContextualMenuPresenter = [RoomContextualMenuPresenter new]; self.roomContextualMenuPresenter = [RoomContextualMenuPresenter new];
self.errorPresenter = [MXKErrorAlertPresentation new];
// Observe user interface theme change. // Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
@ -1121,6 +1125,13 @@
NSLog(@"[MXKRoomViewController] sendTextMessage failed."); NSLog(@"[MXKRoomViewController] sendTextMessage failed.");
}]; }];
} }
else if (self.inputToolBarSendMode == RoomInputToolbarViewSendModeEdit && customizedRoomDataSource.selectedEventId)
{
[self.roomDataSource replaceTextMessageForEventWithId:customizedRoomDataSource.selectedEventId withTextMessage:msgTxt success:nil failure:^(NSError *error) {
// Just log the error. The message will be displayed in red
NSLog(@"[MXKRoomViewController] sendTextMessage failed.");
}];
}
else else
{ {
// Let the datasource send it and manage the local echo // Let the datasource send it and manage the local echo
@ -2821,9 +2832,9 @@
NSString *fragment = [NSString stringWithFormat:@"/group/%@", [MXTools encodeURIComponent:absoluteURLString]]; NSString *fragment = [NSString stringWithFormat:@"/group/%@", [MXTools encodeURIComponent:absoluteURLString]];
[[AppDelegate theDelegate] handleUniversalLinkFragment:fragment]; [[AppDelegate theDelegate] handleUniversalLinkFragment:fragment];
} }
else if ([absoluteURLString hasPrefix:kEventFormatterOnReRequestKeysLinkAction]) else if ([absoluteURLString hasPrefix:EventFormatterOnReRequestKeysLinkAction])
{ {
NSArray<NSString*> *arguments = [absoluteURLString componentsSeparatedByString:kEventFormatterOnReRequestKeysLinkActionSeparator]; NSArray<NSString*> *arguments = [absoluteURLString componentsSeparatedByString:EventFormatterLinkActionSeparator];
if (arguments.count > 1) if (arguments.count > 1)
{ {
NSString *eventId = arguments[1]; NSString *eventId = arguments[1];
@ -2835,6 +2846,19 @@
} }
} }
} }
else if ([absoluteURLString hasPrefix:EventFormatterEditedEventLinkAction])
{
NSArray<NSString*> *arguments = [absoluteURLString componentsSeparatedByString:EventFormatterLinkActionSeparator];
if (arguments.count > 1)
{
// TODO: Handle event edition history.
NSString *eventId = arguments[1];
NSLog(@"[RoomViewController] Did tap edited mention for eventId: %@", eventId);
}
shouldDoAction = NO;
}
else if (url && urlItemInteractionValue) else if (url && urlItemInteractionValue)
{ {
// Fallback case for external links // Fallback case for external links
@ -2874,12 +2898,12 @@
- (void)selectEventWithId:(NSString*)eventId - (void)selectEventWithId:(NSString*)eventId
{ {
[self selectEventWithId:eventId enableReplyMode:NO showTimestamp:YES]; [self selectEventWithId:eventId inputToolBarSendMode:RoomInputToolbarViewSendModeSend showTimestamp:YES];
} }
- (void)selectEventWithId:(NSString*)eventId enableReplyMode:(BOOL)enableReplyMode showTimestamp:(BOOL)showTimestamp - (void)selectEventWithId:(NSString*)eventId inputToolBarSendMode:(RoomInputToolbarViewSendMode)inputToolBarSendMode showTimestamp:(BOOL)showTimestamp
{ {
[self setInputToolBarSendMode: enableReplyMode ? RoomInputToolbarViewSendModeReply : RoomInputToolbarViewSendModeSend]; [self setInputToolBarSendMode:inputToolBarSendMode];
customizedRoomDataSource.showBubbleDateTimeOnSelection = showTimestamp; customizedRoomDataSource.showBubbleDateTimeOnSelection = showTimestamp;
customizedRoomDataSource.selectedEventId = eventId; customizedRoomDataSource.selectedEventId = eventId;
@ -2901,6 +2925,8 @@
customizedRoomDataSource.showBubbleDateTimeOnSelection = YES; customizedRoomDataSource.showBubbleDateTimeOnSelection = YES;
customizedRoomDataSource.selectedEventId = nil; customizedRoomDataSource.selectedEventId = nil;
[self restoreTextMessageBeforeEditing];
// Force table refresh // Force table refresh
[self dataSource:self.roomDataSource didCellChange:nil]; [self dataSource:self.roomDataSource didCellChange:nil];
} }
@ -2911,6 +2937,45 @@
message:NSLocalizedStringFromTable(@"room_message_unable_open_link_error_message", @"Vector", nil)]; message:NSLocalizedStringFromTable(@"room_message_unable_open_link_error_message", @"Vector", nil)];
} }
- (void)editEventContentWithId:(NSString*)eventId
{
MXEvent *event = [self.roomDataSource eventWithEventId:eventId];
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
if (roomInputToolbarView)
{
self.textMessageBeforeEditing = roomInputToolbarView.textMessage;
roomInputToolbarView.textMessage = event.content[@"body"];
}
[self selectEventWithId:eventId inputToolBarSendMode:RoomInputToolbarViewSendModeEdit showTimestamp:YES];
}
- (void)restoreTextMessageBeforeEditing
{
RoomInputToolbarView *roomInputToolbarView = [self inputToolbarViewAsRoomInputToolbarView];
if (self.textMessageBeforeEditing)
{
roomInputToolbarView.textMessage = self.textMessageBeforeEditing;
}
self.textMessageBeforeEditing = nil;
}
- (RoomInputToolbarView*)inputToolbarViewAsRoomInputToolbarView
{
RoomInputToolbarView *roomInputToolbarView;
if (self.inputToolbarView && [self.inputToolbarView isKindOfClass:[RoomInputToolbarView class]])
{
roomInputToolbarView = (RoomInputToolbarView*)self.inputToolbarView;
}
return roomInputToolbarView;
}
#pragma mark - Segues #pragma mark - Segues
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
@ -5046,14 +5111,25 @@
MXStrongifyAndReturnIfNil(self); MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil]; [self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self selectEventWithId:eventId enableReplyMode:YES showTimestamp:NO]; [self selectEventWithId:eventId inputToolBarSendMode:RoomInputToolbarViewSendModeReply showTimestamp:NO];
// And display the keyboard
[self.inputToolbarView becomeFirstResponder];
}; };
// Edit action // Edit action
RoomContextualMenuItem *editMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionEdit]; RoomContextualMenuItem *editMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionEdit];
// TODO: Handle edit action editMenuItem.action = ^{
editMenuItem.isEnabled = NO; MXStrongifyAndReturnIfNil(self);
[self hideContextualMenuAnimated:YES cancelEventSelection:NO completion:nil];
[self editEventContentWithId:eventId];
// And display the keyboard
[self.inputToolbarView becomeFirstResponder];
};
editMenuItem.isEnabled = [self.roomDataSource canEditEventWithId:eventId];
// More action // More action
@ -5082,22 +5158,23 @@
return; return;
} }
[self selectEventWithId:event.eventId enableReplyMode:NO showTimestamp:YES]; [self selectEventWithId:event.eventId];
NSArray<RoomContextualMenuItem*>* contextualMenuItems = [self contextualMenuItemsForEvent:event andCell:cell]; NSArray<RoomContextualMenuItem*>* contextualMenuItems = [self contextualMenuItemsForEvent:event andCell:cell];
RoomContextualMenuViewController *roomContextualMenuViewController = [RoomContextualMenuViewController instantiateWith:contextualMenuItems]; RoomContextualMenuViewController *roomContextualMenuViewController = [RoomContextualMenuViewController instantiateWith:contextualMenuItems];
roomContextualMenuViewController.delegate = self; roomContextualMenuViewController.delegate = self;
[self enableOverlayContainerUserInteractions:YES];
[self.roomContextualMenuPresenter presentWithRoomContextualMenuViewController:roomContextualMenuViewController [self.roomContextualMenuPresenter presentWithRoomContextualMenuViewController:roomContextualMenuViewController
from:self from:self
on:self.overlayContainerView on:self.overlayContainerView
animated:YES animated:YES
completion:^{ completion:^{
[self contextualMenuAnimationCompletionAfterBeingShown:YES];
}]; }];
if (RiotSettings.shared.messageReaction && [cell isKindOfClass:MXKRoomBubbleTableViewCell.class]) if (RiotSettings.shared.messageReaction && [cell isKindOfClass:MXKRoomBubbleTableViewCell.class] && [self.roomDataSource canReactToEventWithId:event.eventId])
{ {
MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = (MXKRoomBubbleTableViewCell*)cell; MXKRoomBubbleTableViewCell *roomBubbleTableViewCell = (MXKRoomBubbleTableViewCell*)cell;
MXKRoomBubbleCellData *bubbleCellData = roomBubbleTableViewCell.bubbleData; MXKRoomBubbleCellData *bubbleCellData = roomBubbleTableViewCell.bubbleData;
@ -5117,16 +5194,22 @@
if (bubbleComponents.count > 0) if (bubbleComponents.count > 0)
{ {
NSInteger selectedComponentIndex = foundComponentIndex != NSNotFound ? foundComponentIndex : 0; NSInteger selectedComponentIndex = foundComponentIndex != NSNotFound ? foundComponentIndex : 0;
bubbleComponentFrame = [roomBubbleTableViewCell componentFrameForIndex:selectedComponentIndex]; bubbleComponentFrame = [roomBubbleTableViewCell componentFrameInTableViewForIndex:selectedComponentIndex];
} }
else else
{ {
bubbleComponentFrame = roomBubbleTableViewCell.frame; bubbleComponentFrame = roomBubbleTableViewCell.frame;
} }
CGRect bubbleComponentFrameInOverlayView = [self.bubblesTableView convertRect:bubbleComponentFrame toView:self.overlayContainerView]; CGRect bubbleComponentFrameInOverlayView = [self.bubblesTableView convertRect:bubbleComponentFrame toView:self.overlayContainerView];
[self.roomContextualMenuPresenter showReactionsMenuForEvent:event.eventId inRoom:event.roomId session:self.mainSession aroundFrame:bubbleComponentFrameInOverlayView]; NSString *roomId = self.roomDataSource.roomId;
MXAggregations *aggregations = self.mainSession.aggregations;
ReactionsMenuViewModel *reactionsMenuViewModel = [[ReactionsMenuViewModel alloc] initWithAggregations:aggregations roomId:roomId eventId:event.eventId];
reactionsMenuViewModel.coordinatorDelegate = self;
[self.roomContextualMenuPresenter showReactionsMenuWithReactionsMenuViewModel:reactionsMenuViewModel aroundFrame:bubbleComponentFrameInOverlayView];
} }
} }
@ -5153,7 +5236,7 @@
} }
[self.roomContextualMenuPresenter hideContextualMenuWithAnimated:animated completion:^{ [self.roomContextualMenuPresenter hideContextualMenuWithAnimated:animated completion:^{
[self contextualMenuAnimationCompletionAfterBeingShown:NO]; [self enableOverlayContainerUserInteractions:NO];
if (completion) if (completion)
{ {
@ -5162,11 +5245,11 @@
}]; }];
} }
- (void)contextualMenuAnimationCompletionAfterBeingShown:(BOOL)isShown - (void)enableOverlayContainerUserInteractions:(BOOL)enableOverlayContainerUserInteractions
{ {
self.inputToolbarView.editable = !isShown; self.inputToolbarView.editable = !enableOverlayContainerUserInteractions;
self.bubblesTableView.scrollsToTop = !isShown; self.bubblesTableView.scrollsToTop = !enableOverlayContainerUserInteractions;
self.overlayContainerView.userInteractionEnabled = isShown; self.overlayContainerView.userInteractionEnabled = enableOverlayContainerUserInteractions;
} }
#pragma mark - RoomContextualMenuViewControllerDelegate #pragma mark - RoomContextualMenuViewControllerDelegate
@ -5181,5 +5264,37 @@
[self hideContextualMenuAnimated:YES]; [self hideContextualMenuAnimated:YES];
} }
#pragma mark - ReactionsMenuViewModelCoordinatorDelegate
- (void)reactionsMenuViewModel:(ReactionsMenuViewModel *)viewModel didAddReaction:(NSString *)reaction forEventId:(NSString *)eventId
{
MXWeakify(self);
[self.roomDataSource addReaction:reaction forEventId:eventId success:^{
} failure:^(NSError *error) {
MXStrongifyAndReturnIfNil(self);
[self.errorPresenter presentErrorFromViewController:self forError:error animated:YES handler:nil];
}];
[self hideContextualMenuAnimated:YES];
}
- (void)reactionsMenuViewModel:(ReactionsMenuViewModel *)viewModel didRemoveReaction:(NSString *)reaction forEventId:(NSString *)eventId
{
MXWeakify(self);
[self.roomDataSource removeReaction:reaction forEventId:eventId success:^{
} failure:^(NSError *error) {
MXStrongifyAndReturnIfNil(self);
[self.errorPresenter presentErrorFromViewController:self forError:error animated:YES handler:nil];
}];
[self hideContextualMenuAnimated:YES];
}
@end @end

View file

@ -0,0 +1,48 @@
/*
Copyright 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import Foundation
/// MXKRoomBubbleTableViewCell layout constants
@objcMembers
final class RoomBubbleCellLayout: NSObject {
// Reactions
static let reactionsViewTopMargin: CGFloat = 1.0
static let reactionsViewLeftMargin: CGFloat = 55.0
static let reactionsViewRightMargin: CGFloat = 15.0
// Read receipts
static let readReceiptsViewTopMargin: CGFloat = 5.0
static let readReceiptsViewRightMargin: CGFloat = 6.0
static let readReceiptsViewHeight: CGFloat = 12.0
static let readReceiptsViewWidth: CGFloat = 150.0
// Read marker
static let readMarkerViewHeight: CGFloat = 2.0
// Timestamp
static let timestampLabelHeight: CGFloat = 18.0
static let timestampLabelWidth: CGFloat = 39.0
// Others
static let encryptedContentLeftMargin: CGFloat = 15.0
}

View file

@ -39,4 +39,16 @@
[self updateUserNameColor]; [self updateUserNameColor];
} }
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
if (rowHeight <= 0)
{
rowHeight = [super heightForCellData:cellData withMaximumWidth:maxWidth];
}
return rowHeight;
}
@end @end

View file

@ -45,4 +45,16 @@
} }
} }
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
if (rowHeight <= 0)
{
rowHeight = [super heightForCellData:cellData withMaximumWidth:maxWidth];
}
return rowHeight;
}
@end @end

View file

@ -16,6 +16,7 @@
*/ */
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h" #import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
#import "MXKRoomBubbleTableViewCell+Riot.h"
#import "ThemeService.h" #import "ThemeService.h"
#import "Riot-Swift.h" #import "Riot-Swift.h"
@ -29,4 +30,16 @@
self.messageTextView.tintColor = ThemeService.shared.theme.tintColor; self.messageTextView.tintColor = ThemeService.shared.theme.tintColor;
} }
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
if (rowHeight <= 0)
{
rowHeight = [super heightForCellData:cellData withMaximumWidth:maxWidth];
}
return rowHeight;
}
@end @end

View file

@ -62,4 +62,16 @@
} }
} }
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
if (rowHeight <= 0)
{
rowHeight = [super heightForCellData:cellData withMaximumWidth:maxWidth];
}
return rowHeight;
}
@end @end

View file

@ -19,6 +19,8 @@
#import "ThemeService.h" #import "ThemeService.h"
#import "Riot-Swift.h" #import "Riot-Swift.h"
#import "RoomBubbleCellData.h"
#import "MXKRoomBubbleTableViewCell+Riot.h"
@implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell @implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell
@ -36,4 +38,16 @@
[RoomOutgoingAttachmentBubbleCell render:cellData inBubbleCell:self]; [RoomOutgoingAttachmentBubbleCell render:cellData inBubbleCell:self];
} }
+ (CGFloat)heightForCellData:(MXKCellData*)cellData withMaximumWidth:(CGFloat)maxWidth
{
CGFloat rowHeight = [self attachmentBubbleCellHeightForCellData:cellData withMaximumWidth:maxWidth];
if (rowHeight <= 0)
{
rowHeight = [super heightForCellData:cellData withMaximumWidth:maxWidth];
}
return rowHeight;
}
@end @end

View file

@ -25,6 +25,7 @@ typedef enum : NSUInteger
{ {
RoomInputToolbarViewSendModeSend, RoomInputToolbarViewSendModeSend,
RoomInputToolbarViewSendModeReply, RoomInputToolbarViewSendModeReply,
RoomInputToolbarViewSendModeEdit
} RoomInputToolbarViewSendMode; } RoomInputToolbarViewSendMode;
@ -48,7 +49,7 @@ typedef enum : NSUInteger
/** /**
The delegate notified when inputs are ready. The delegate notified when inputs are ready.
*/ */
@property (nonatomic) id<RoomInputToolbarViewDelegate> delegate; @property (nonatomic, weak) id<RoomInputToolbarViewDelegate> delegate;
@property (weak, nonatomic) IBOutlet UIView *mainToolbarView; @property (weak, nonatomic) IBOutlet UIView *mainToolbarView;

View file

@ -172,7 +172,9 @@
case RoomInputToolbarViewSendModeReply: case RoomInputToolbarViewSendModeReply:
title = NSLocalizedStringFromTable(@"room_action_reply", @"Vector", nil); title = NSLocalizedStringFromTable(@"room_action_reply", @"Vector", nil);
break; break;
case RoomInputToolbarViewSendModeEdit:
title = NSLocalizedStringFromTable(@"save", @"Vector", nil);
break;
default: default:
title = [NSBundle mxk_localizedStringForKey:@"send"]; title = [NSBundle mxk_localizedStringForKey:@"send"];
break; break;

View file

@ -19,18 +19,35 @@
/** /**
Link string used in attributed strings to mark a keys re-request action. Link string used in attributed strings to mark a keys re-request action.
*/ */
FOUNDATION_EXPORT NSString *const kEventFormatterOnReRequestKeysLinkAction; FOUNDATION_EXPORT NSString *const EventFormatterOnReRequestKeysLinkAction;
/** /**
Parameters separator in the link string. Parameters separator in the link string.
*/ */
FOUNDATION_EXPORT NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator; FOUNDATION_EXPORT NSString *const EventFormatterLinkActionSeparator;
/**
Link string used in attributed strings to mark an edited event action.
*/
FOUNDATION_EXPORT NSString *const EventFormatterEditedEventLinkAction;
/** /**
`EventFormatter` class inherits from `MXKEventFormatter` to define Vector formatting `EventFormatter` class inherits from `MXKEventFormatter` to define Vector formatting
*/ */
@interface EventFormatter : MXKEventFormatter @interface EventFormatter : MXKEventFormatter
/**
Text color used to display message edited mention.
Default is `textSecondaryColor`.
*/
@property (nonatomic) UIColor *editionMentionTextColor;
/**
Text font used to display message edited mention.
Default is system font 12.
*/
@property (nonatomic) UIFont *editionMentionTextFont;
/** /**
String attributes for event timestamp displayed in chat history. String attributes for event timestamp displayed in chat history.
*/ */

View file

@ -27,8 +27,9 @@
#pragma mark - Constants definitions #pragma mark - Constants definitions
NSString *const kEventFormatterOnReRequestKeysLinkAction = @"kEventFormatterOnReRequestKeysLinkAction"; NSString *const EventFormatterOnReRequestKeysLinkAction = @"EventFormatterOnReRequestKeysLinkAction";
NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/"; NSString *const EventFormatterLinkActionSeparator = @"/";
NSString *const EventFormatterEditedEventLinkAction = @"EventFormatterEditedEventLinkAction";
static NSString *const kEventFormatterTimeFormat = @"HH:mm"; static NSString *const kEventFormatterTimeFormat = @"HH:mm";
@ -159,8 +160,8 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
NSMutableAttributedString *attributedStringWithRerequestMessage = [attributedString mutableCopy]; NSMutableAttributedString *attributedStringWithRerequestMessage = [attributedString mutableCopy];
[attributedStringWithRerequestMessage appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]]; [attributedStringWithRerequestMessage appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]];
NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", kEventFormatterOnReRequestKeysLinkAction, NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", EventFormatterOnReRequestKeysLinkAction,
kEventFormatterOnReRequestKeysLinkActionSeparator, EventFormatterLinkActionSeparator,
event.eventId]; event.eventId];
[attributedStringWithRerequestMessage appendAttributedString: [attributedStringWithRerequestMessage appendAttributedString:
@ -181,6 +182,26 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
attributedString = attributedStringWithRerequestMessage; attributedString = attributedStringWithRerequestMessage;
} }
} }
else if (event.contentHasBeenEdited)
{
NSMutableAttributedString *attributedStringWithEditMention = [attributedString mutableCopy];
NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", EventFormatterEditedEventLinkAction,
EventFormatterLinkActionSeparator,
event.eventId];
[attributedStringWithEditMention appendAttributedString:
[[NSAttributedString alloc] initWithString:[NSString stringWithFormat:@" %@", NSLocalizedStringFromTable(@"event_formatter_message_edited_mention", @"Vector", nil)]
attributes:@{
NSLinkAttributeName: linkActionString,
// NOTE: Color is curretly overidden by UIText.tintColor as we use `NSLinkAttributeName`.
// If we use UITextView.linkTextAttributes to set link color we will also have the issue that color will be the same for all kind of links.
NSForegroundColorAttributeName: self.editionMentionTextColor,
NSFontAttributeName: self.editionMentionTextFont
}]];
attributedString = attributedStringWithEditMention;
}
return attributedString; return attributedString;
} }
@ -234,6 +255,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
self.encryptingTextColor = ThemeService.shared.theme.tintColor; self.encryptingTextColor = ThemeService.shared.theme.tintColor;
self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor; self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor;
self.errorTextColor = ThemeService.shared.theme.warningColor; self.errorTextColor = ThemeService.shared.theme.warningColor;
self.editionMentionTextColor = ThemeService.shared.theme.textSecondaryColor;
self.defaultTextFont = [UIFont systemFontOfSize:15]; self.defaultTextFont = [UIFont systemFontOfSize:15];
self.prefixTextFont = [UIFont boldSystemFontOfSize:15]; self.prefixTextFont = [UIFont boldSystemFontOfSize:15];
@ -242,6 +264,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
self.callNoticesTextFont = [UIFont italicSystemFontOfSize:15]; self.callNoticesTextFont = [UIFont italicSystemFontOfSize:15];
self.encryptedMessagesTextFont = [UIFont italicSystemFontOfSize:15]; self.encryptedMessagesTextFont = [UIFont italicSystemFontOfSize:15];
self.emojiOnlyTextFont = [UIFont systemFontOfSize:48]; self.emojiOnlyTextFont = [UIFont systemFontOfSize:48];
self.editionMentionTextFont = [UIFont systemFontOfSize:12];
} }
return self; return self;
} }