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).
Bug fix:
* Registration with an email is broken (#2417).
* 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)
===============================================
@ -51,7 +53,7 @@ Changes in 0.8.4 (2019-03-21)
Improvements:
* 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).
Bug fix:
* Unable to open a file attachment of a room message (#2338).
@ -60,7 +62,7 @@ Changes in 0.8.3 (2019-03-13)
Improvements:
* Upgrade MatrixKit version ([v0.9.7](https://github.com/matrix-org/matrix-ios-kit/releases/tag/v0.9.7)).
Bug fix:
* Widgets: Attempt to re-register for a scalar token if ours is invalid (#2326).
* 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: Logout warning (#2245).
* Key backup: new recover method detected (#2230).
Bug fix:
* Use white scroll bar on dark themes (#2158).
* 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'
# Piwik for analytics
# While https://github.com/matomo-org/matomo-sdk-ios/pull/223 is not released, use the PR branch
pod 'PiwikTracker', :git => 'https://github.com/manuroe/matomo-sdk-ios.git', :branch => 'feature/CustomVariables'
#pod 'PiwikTracker', '~> 4.4.2'
pod 'MatomoTracker', '~> 6.0.1'
# Remove warnings from "bad" pods
pod 'OLMKit', :inhibit_warnings => true
pod 'cmark', :inhibit_warnings => true
pod 'DTCoreText', :inhibit_warnings => true
pod 'zxcvbn-ios'
# Tools
pod 'SwiftGen', '~> 6.1'
pod 'SwiftLint', '~> 0.30.1'
@ -101,13 +99,7 @@ post_install do |installer|
# Plus the app does not enable it
target.build_configurations.each do |config|
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

View file

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

View file

@ -205,6 +205,7 @@
B19EFA3921F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3821F8BB2C00FC070E /* KeyBackupRecoverCoordinatorType.swift */; };
B19EFA3B21F8BB4100FC070E /* KeyBackupRecoverCoordinator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B19EFA3A21F8BB4100FC070E /* KeyBackupRecoverCoordinator.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 */; };
B1B5571820EE6C4D00210D55 /* CountryPickerViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = B1B5567A20EE6C4C00210D55 /* CountryPickerViewController.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>"; };
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>"; };
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>"; };
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>"; };
@ -2885,6 +2887,7 @@
B1B5584220EF768E00210D55 /* Encryption */ = {
isa = PBXGroup;
children = (
B1A68592229E807800D6C09A /* RoomBubbleCellLayout.swift */,
B1B5584320EF768E00210D55 /* RoomIncomingEncryptedTextMsgWithPaginationTitleBubbleCell.h */,
B1B5584420EF768E00210D55 /* RoomOutgoingEncryptedTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h */,
B1B5584520EF768E00210D55 /* RoomOutgoingEncryptedAttachmentBubbleCell.h */,
@ -3688,10 +3691,10 @@
"${BUILT_PRODUCTS_DIR}/HPGrowingTextView/HPGrowingTextView.framework",
"${PODS_ROOT}/JitsiMeetSDK/Frameworks/JitsiMeet.framework",
"${PODS_ROOT}/JitsiMeetSDK/Frameworks/WebRTC.framework",
"${BUILT_PRODUCTS_DIR}/MatomoTracker/MatomoTracker.framework",
"${BUILT_PRODUCTS_DIR}/MatrixKit/MatrixKit.framework",
"${BUILT_PRODUCTS_DIR}/MatrixSDK.common-JingleCallStack/MatrixSDK.framework",
"${BUILT_PRODUCTS_DIR}/OLMKit/OLMKit.framework",
"${BUILT_PRODUCTS_DIR}/PiwikTracker/PiwikTracker.framework",
"${BUILT_PRODUCTS_DIR}/Realm/Realm.framework",
"${BUILT_PRODUCTS_DIR}/Reusable/Reusable.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}/JitsiMeet.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}/MatrixSDK.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}/Reusable.framework",
"${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cmark.framework",
@ -3920,6 +3923,7 @@
B1B558E820EF768F00210D55 /* RoomIncomingAttachmentWithPaginationTitleBubbleCell.m in Sources */,
B1B558F320EF768F00210D55 /* RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m in Sources */,
B1B557BD20EF5B4500210D55 /* KeyboardGrowingTextView.m in Sources */,
B1A68593229E807A00D6C09A /* RoomBubbleCellLayout.swift in Sources */,
B1B558F420EF768F00210D55 /* RoomOutgoingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m in Sources */,
B1B5572320EE6C4D00210D55 /* AttachmentsViewController.m in Sources */,
F083BDEE1E7009ED00A9B29C /* MXRoom+Riot.m in Sources */,

View file

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

View file

@ -1,5 +1,5 @@
/* 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 */
"MSG_FROM_USER_IN_ROOM" = "%@ публикува в %@";
/* 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. */
"ACTION_FROM_USER_IN_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. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ публикува снимка %@ в %@";
/* A single unread message in a room */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Групово повикване от %@: '%@'";
/* Incoming named video conference invite from a specific person */
"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_message" = "Изпратихме Ви SMS с код за активиране. Моля, въведете този код по-долу.";
"auth_msisdn_validation_error" = "Неуспешно потвърждение на телефонен номер.";
"auth_recaptcha_message" = "Този Home сървър би искал да се увери, че не сте робот";
"auth_recaptcha_message" = "Този сървър би искал да се увери, че не сте робот";
"auth_reset_password_message" = "За да възстановите Вашата парола, въведете имейл адреса, свързан с профила Ви:";
"auth_reset_password_missing_email" = "Имейл адресът, свързан с профила Ви, трябва да бъде въведен.";
"auth_reset_password_missing_password" = "Трябва да бъде въведена нова парола.";
"auth_reset_password_email_validation_message" = "Имейл беше изпратен на %@. След като проследите връзката, която съдържа, натиснете по-долу.";
"auth_reset_password_next_step_button" = "Потвърдих имейл адреса си";
"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_add_email_and_phone_warning" = "Регистрация с имейл и телефонен номер наведнъж не се поддържа в момента. Само телефонен номер се взима под внимание. Можете да добавите имейл към профила си в настройките.";
// Chat creation
@ -562,7 +562,7 @@
"settings_key_backup_info_version" = "Версия на резервното копие на ключовете: %@";
"settings_key_backup_info_algorithm" = "Алгоритъм: %@";
"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_done" = "Има резервно копие на всички ключове";
"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_part2" = " за да четете шифрованата история на съобщенията на това устройство";
"settings_key_backup_info" = "Шифрованите съобщения са защитени с шифроване от край до край. Само Вие и получателят (получателите) имате ключове за прочитането им.";
"settings_key_backup_info_signout_warning" = "Направете копие на ключовете преди да излезете от профила, за да не ги загубите.";
"settings_key_backup_info_signout_warning" = "Свържете това устройство с резервно копие за ключове преди да излезете от профила, за да не изгубите ключовете намиращи се само на устройството.";
"settings_key_backup_button_use" = "Използвай резервно копие на ключовете";
// Key backup wrong version
"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.";
"auth_autodiscover_invalid_response" = "Невалиден отговор при опит за откриване на адреса на сървъра";
"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.";
"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.";
"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. */
"ACTION_FROM_USER_IN_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. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ sendet ein Bild %@ in %@";
/* Multiple unread messages in a room */
@ -50,3 +50,7 @@
"SINGLE_UNREAD_IN_ROOM" = "Du hast eine Nachricht in %@ bekommen";
/* A single unread message */
"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";
"next" = "Weiter";
"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_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.";
@ -656,7 +656,14 @@
"key_backup_setup_intro_manual_export_action" = "Manueller Schlüssel Export";
// String for App Store
"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_autodiscover_invalid_response" = "Ungültige Antwort beim Entdecken des Heimservers";
"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_rerequest_keys_part1_link" = "Re-request encryption keys";
"event_formatter_rerequest_keys_part2" = " from your other devices.";
"event_formatter_message_edited_mention" = "(Edited)";
// Others
"or" = "or";

View file

@ -15,3 +15,5 @@
"room_jump_to_first_unread" = "Salti al unua nelegita mesaĝo";
"group_details_people" = "Homoj";
"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 */
"MSG_FROM_USER" = "Mensaje de %@";
"MSG_FROM_USER" = "%@ envió un mensaje";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ publicó en %@";
/* 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 %@: '%@'";
/* Incoming named video conference invite from a specific person */
"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_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)";
// 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.";
"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.";
"NSCalendarsUsageDescription" = "Ikusi zure programatutako batzarrak aplikazioan.";

View file

@ -1,5 +1,5 @@
/* 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 */
"MSG_FROM_USER_IN_ROOM" = "%@erabiltzaileak %@ gelan idatzi du";
/* 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. */
"ACTION_FROM_USER_IN_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. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ erabiltzaileak irudi bat %@ bidali du %@ gelara";
/* Multiple unread messages in a room */
@ -50,3 +50,7 @@
"SINGLE_UNREAD_IN_ROOM" = "Mezu bat jaso duzu %@ gelan";
/* A single unread message */
"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_new_password_placeholder" = "Pasahitz berria";
"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_optional_email_placeholder" = "E-mail helbidea (aukerakoa)";
"auth_optional_phone_placeholder" = "Telefono zenbakia (aukerakoa)";
@ -71,7 +71,7 @@
"auth_forgot_password" = "Pasahitza ahaztu duzu?";
"auth_use_server_options" = "Erabili zerbitzari pertsonalizatuaren ezarpenak (aurreratua)";
"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_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:";
@ -110,8 +110,8 @@
"room_participants_action_set_default_power_level" = "Berrezarri erabiltzaile arrunt gisa";
"room_participants_action_set_moderator" = "Bihurtu moderatzaile";
"room_participants_action_set_admin" = "Bihurtu kudeatzaile";
"room_participants_action_ignore" = "Ezkutatu kide honen mezu guztiak";
"room_participants_action_unignore" = "Erakutsi kide honen mezu guztiak";
"room_participants_action_ignore" = "Ezkutatu erabiltzaile honen mezu guztiak";
"room_participants_action_unignore" = "Erakutsi erabiltzaile honen mezu guztiak";
"room_participants_action_mention" = "Aipamena";
"contacts_address_book_matrix_users_toggle" = "Matrix erabiltzaileak besterik ez";
"encrypted_room_message_placeholder" = "Bidali zifratutako mezua…";
@ -222,7 +222,7 @@
"auth_untrusted_id_server" = "Identitate zerbitzaria ez da fidagarria";
"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_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_appearance" = "Itxura";
"room_creation_appearance_picture" = "Txateko irudia (aukerakoa)";
@ -312,7 +312,7 @@
"settings_config_no_build_info" = "Konpilazio daturik ez";
"settings_mark_all_as_read" = "Markatu mezu guztiak irakurrita gisa";
"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_user_id" = "%@ gisa hasi duzu saioa";
"settings_user_settings" = "ERABILTZAILE EZARPENAK";
@ -571,7 +571,7 @@
"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_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_use" = "Erabili gakoen babes-kopia";
"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_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_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_valid" = "Babes-kopiak gailu honen 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_autodiscover_invalid_response" = "Erantzun baliogabea hasiera-zerbitzarien bilaketari";
"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.";
"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.";
"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 */
"MSG_FROM_USER" = "Message de %@";
"MSG_FROM_USER" = "%@ a envoyé un message";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ a posté dans %@";
/* 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. */
"ACTION_FROM_USER_IN_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. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ a posté une image %@ dans %@";
/* A single unread message in a room */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Téléconférence vocale de %@ : '%@'";
/* Incoming named video conference invite from a specific person */
"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_phone" = "Le numéro de téléphone ne semble pas valide";
"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_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.";
@ -69,14 +69,14 @@
"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_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_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_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_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_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
@ -246,7 +246,7 @@
"settings_config_no_build_info" = "Aucune information sur la version";
"settings_mark_all_as_read" = "Marquer tous les messages comme lus";
"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_user_id" = "Identifié en tant que %@";
"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_algorithm" = "Algorithme : %@";
"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_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.";
@ -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_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_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";
"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";
@ -675,3 +675,105 @@
"auth_login_single_sign_on" = "Se connecter avec l'authentification unique";
"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";
"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.";
"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.";
"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 */
"MSG_FROM_USER" = "Üzenet tőle: %@";
"MSG_FROM_USER" = "%@ üzenet elküldve";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ küldte ebbe a szobába: %@";
/* 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: '%@'";
/* Incoming named video conference invite from a specific person */
"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_algorithm" = "Algoritmus: %@";
"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_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: %@.";
@ -630,7 +630,7 @@
"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";
"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";
"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";
@ -680,3 +680,104 @@
"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.";
"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_favourites" = "Favorieten";
"title_people" = "Personen";
"title_rooms" = "Kamers";
"title_rooms" = "Gesprekken";
"warning" = "Waarschuwing";
// Actions
"view" = "Weergeven";
@ -115,23 +115,23 @@
"room_recents_directory_section_network" = "Netwerk";
"room_recents_favourites_section" = "FAVORIETEN";
"room_recents_people_section" = "PERSONEN";
"room_recents_conversations_section" = "KAMERS";
"room_recents_no_conversation" = "Geen kamers";
"room_recents_conversations_section" = "GESPREKKEN";
"room_recents_no_conversation" = "Geen gesprekken";
"room_recents_low_priority_section" = "LAGE PRIORITEIT";
"room_recents_invites_section" = "UITNODIGINGEN";
"room_recents_start_chat_with" = "Gesprek beginnen";
"room_recents_create_empty_room" = "Gesprek aanmaken";
"room_recents_join_room" = "Gesprek toetreden";
"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_invites_section" = "UITNODIGINGEN";
"people_conversation_section" = "GESPREKKEN";
"people_no_conversation" = "Geen gesprekken";
// Rooms tab
"room_directory_no_public_room" = "Geen publieke kamers beschikbaar";
"room_directory_no_public_room" = "Geen publieke gesprekken beschikbaar";
// Search
"search_rooms" = "Kamers";
"search_rooms" = "Gesprekken";
"search_messages" = "Berichten";
"search_people" = "Personen";
"search_files" = "Bestanden";
@ -140,7 +140,7 @@
"search_no_result" = "Geen resultaten";
// Directory
"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" = "%tu resultaten gevonden voor %@";
"directory_search_results_more_than" = ">%tu resultaten gevonden voor %@";
@ -270,7 +270,7 @@
"settings_cryptography" = "CRYPTOGRAFIE";
"settings_sign_out" = "Afmelden";
"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_display_name" = "Weergavenaam";
"settings_first_name" = "Voornaam";
@ -288,8 +288,8 @@
"settings_fail_to_update_profile" = "Bijwerken van profiel is mislukt";
"settings_enable_push_notif" = "Meldingen op dit apparaat";
"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_unread" = "Kamers met ongelezen berichten vastprikken";
"settings_pin_rooms_with_missed_notif" = "Gesprekken met gemiste meldingen 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_enable_all_notif" = "Alle notificaties aanzetten";
//"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_new_address" = "Nieuw adres toevoegen";
"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_msg" = "%@ is geen geldig formaat voor een alias";
"room_details_addresses_invalid_address_prompt_title" = "Ongeldig bijnaamformaat";
"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_msg" = "U heeft geen hoofdadres opgegeven. Het standaardhoofdadres voor dit gesprek zal willekeurig gekozen worden";
"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_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_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_join_rule" = "Bijwerken van toetredingsregel is mislukt";
"room_details_fail_to_update_room_directory_visibility" = "Bijwerken van zichtbaarheid in de gesprekscatalogus is mislukt";
@ -389,9 +389,9 @@
// Directory
"directory_title" = "Catalogus";
"directory_server_picker_title" = "Selecteer een catalogus";
"directory_server_all_rooms" = "Alle kamers op server %@";
"directory_server_all_native_rooms" = "Alle lokale Matrix-kamers";
"directory_server_type_homeserver" = "Voer een thuisserver in om de publieke kamers ervan weer te geven";
"directory_server_all_rooms" = "Alle gesprekken op server %@";
"directory_server_all_native_rooms" = "Alle lokale Matrix-gesprekken";
"directory_server_type_homeserver" = "Voer een thuisserver in om de publieke gesprekken ervan weer te geven";
"directory_server_placeholder" = "matrix.org";
// Others
"or" = "of";
@ -399,7 +399,7 @@
"today" = "Vandaag";
"yesterday" = "Gisteren";
"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?";
"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";
@ -512,12 +512,12 @@
"group_details_title" = "Gemeenschapsdetails";
"group_details_home" = "Thuis";
"group_details_people" = "Personen";
"group_details_rooms" = "Kamers";
"group_details_rooms" = "Gesprekken";
// Group Home
"group_home_one_member_format" = "1 lid";
"group_home_multi_members_format" = "%tu leden";
"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 participants
"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_invited_section" = "UITGENODIGD";
// 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.";
"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";
@ -553,7 +553,7 @@
"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?";
"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_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. ";
@ -569,7 +569,7 @@
"room_message_reply_to_short_placeholder" = "Stuur een antwoord…";
// String for App Store
"store_short_description" = "Veilig en gedecentraliseerd chatten en bellen";
"store_full_description" = "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_accept_policies" = "Gelieve het beleid van deze thuisserver te lezen en aanvaarden:";
"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_contact_3" = " om deze limiet te verhogen.";
"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_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_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_algorithm" = "Algoritme: %@";
"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_done" = "Alle sleutels zijn geback-upt";
"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_skip_action" = "Overslaan";
"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_manual_export_info" = "(Geavanceerd)";
"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_discard_key_backup_action" = "Ik wil mijn versleutelde berichten niet";
"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_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_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";
// Settings
"settings_title" = "Ustawienia";
@ -314,7 +314,7 @@
"group_participants_remove_prompt_title" = "Potwierdzenie";
"group_participants_invite_prompt_title" = "Potwierdzenie";
"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_filter_rooms" = "Filtruj pokoje społeczności";
// Read Receipts
@ -488,3 +488,25 @@
"media_picker_library" = "Biblioteka";
"large_badge_value_k_format" = "%.1fK";
"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" = "Галерея используется для отправки фотографий и видео.";
"NSMicrophoneUsageDescription" = "Микрофон используется при съемке видео и выполнении звонков.";
"NSContactsUsageDescription" = "Для отображения контактов, использующих Riot или Matrix, мы можем отправить адреса email и номера телефонов из вашей адресной книги на ваш сервер идентификации Matrix. Новый Vector не хранит эти данные и не использует их для каких-либо других целей. Для получения дополнительной информации, пожалуйста, ознакомьтесь с Политикой конфиденциальности в настройках приложения.";
"NSCalendarsUsageDescription" = "Ознакомьтесь со своими запланированными встречами в приложении.";

View file

@ -11,7 +11,7 @@
/* 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" = "%@ отправил(а) вам фото %@";
"IMAGE_FROM_USER" = "%@ отправил(а) фото %@";
/* New action message from a specific person in a named room. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ отправил(а) фото %@ в %@";
/* Multiple unread messages in a room */
@ -50,3 +50,7 @@
"SINGLE_UNREAD_IN_ROOM" = "Вы получили сообщение в %@";
/* A single unread message */
"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_phone" = "Это не похоже на действительный номер телефона";
"auth_missing_password" = "Пароль отсутствует";
"auth_add_email_message" = "Добавьте адрес электронной почты в свою учетную запись, чтобы другим пользователям было проще вас найти. Также это поможет вам при необходимости восстановить пароль.";
"auth_add_email_message" = "Добавьте адрес электронной почты в свою учетную запись, чтобы другим пользователям было проще вас найти. Также это поможет вам при восстановлении паролья.";
"auth_add_phone_message" = "Добавьте номер телефона в свою учетную запись, чтобы другим пользователям было проще вас найти.";
"auth_add_email_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.";
"auth_login_single_sign_on" = "Вход с SSO";
"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 */
"MSG_FROM_USER" = "Mesazh prej %@";
"MSG_FROM_USER" = "%@ dërgoi një mesazh";
/* New message from a specific person in a named room */
"MSG_FROM_USER_IN_ROOM" = "%@ postuar te %@";
/* 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. */
"ACTION_FROM_USER_IN_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. */
"IMAGE_FROM_USER_IN_ROOM" = "%@ postoi një foto %@ në %@";
/* A single unread message in a room */
@ -50,3 +50,7 @@
"VOICE_CONF_NAMED_FROM_USER" = "Thirrje grupi nga %@: '%@'";
/* Incoming named video conference invite from a specific person */
"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_mark_all_as_read" = "Vëru shenjë krejt mesazheve si të lexuar";
"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_user_id" = "I futur si %@";
"settings_user_settings" = "RREGULLIME PËRDORUESI";
@ -390,7 +390,7 @@
"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_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_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";
@ -559,7 +559,7 @@
"settings_key_backup_info_version" = "Version Kopjeruajtjeje Kyçesh: %@";
"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_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_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 %@.";
@ -621,7 +621,7 @@
"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";
"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";
"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";
@ -672,3 +672,102 @@
"room_message_unable_open_link_error_message" = "Sarrihet të hapet lidhja.";
"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_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.
@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.

View file

@ -24,8 +24,6 @@
#import <objc/runtime.h>
#define VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH 39
#define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_X 48
#define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH 4
@ -42,7 +40,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
if (componentIndex < bubbleComponents.count)
{
component = bubbleComponents[componentIndex];
component = bubbleComponents[componentIndex];
}
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
BOOL displayLabelOnLeft = roomBubbleCellData.displayTimestampForSelectedComponentOnLeftWhenPossible && !isFirstDisplayedComponent && !isLastMessageMostRecentComponent;
BOOL displayLabelOnLeft = roomBubbleCellData.displayTimestampForSelectedComponentOnLeftWhenPossible
&& !isLastMessageMostRecentComponent
&& ( !isFirstDisplayedComponent || roomBubbleCellData.shouldHideSenderInformation);
[self addTimestampLabelForComponent:component
isFirstDisplayedComponent:isFirstDisplayedComponent
viewTag:componentIndex
displayOnLeft:displayLabelOnLeft];
[self addTimestampLabelForComponentIndex:componentIndex
isFirstDisplayedComponent:isFirstDisplayedComponent
viewTag:componentIndex
displayOnLeft:displayLabelOnLeft];
}
}
- (void)addTimestampLabelForComponent:(MXKRoomBubbleComponent*)component
isFirstDisplayedComponent:(BOOL)isFirstDisplayedComponent
viewTag:(NSInteger)viewTag
displayOnLeft:(BOOL)displayOnLeft
- (void)addTimestampLabelForComponentIndex:(NSInteger)componentIndex
isFirstDisplayedComponent:(BOOL)isFirstDisplayedComponent
viewTag:(NSInteger)viewTag
displayOnLeft:(BOOL)displayOnLeft
{
NSArray *bubbleComponents = bubbleData.bubbleComponents;
MXKRoomBubbleComponent *component = bubbleComponents[componentIndex];
self.bubbleInfoContainer.hidden = NO;
CGFloat timeLabelPosX;
CGFloat timeLabelPosY;
CGFloat timeLabelHeight = RoomBubbleCellLayout.timestampLabelHeight;
CGFloat timeLabelWidth;
NSTextAlignment timeLabelTextAlignment;
CGRect componentFrame = [self componentFrameInContentViewForIndex:componentIndex];
if (displayOnLeft)
{
CGFloat leftMargin = 10.0;
CGFloat rightMargin = (self.contentView.frame.size.width - (self.bubbleInfoContainer.frame.origin.x + self.bubbleInfoContainer.frame.size.width));
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;
timeLabelTextAlignment = NSTextAlignmentLeft;
}
else
{
timeLabelPosX = self.bubbleInfoContainer.frame.size.width - VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH;
timeLabelPosY = isFirstDisplayedComponent ? 0 : component.position.y + self.msgTextViewTopConstraint.constant - self.bubbleInfoContainerTopConstraint.constant;
timeLabelWidth = VECTOR_ROOMBUBBLETABLEVIEWCELL_TIMELABEL_WIDTH;
timeLabelPosX = self.bubbleInfoContainer.frame.size.width - RoomBubbleCellLayout.timestampLabelWidth;
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;
}
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.textAlignment = timeLabelTextAlignment;
@ -144,32 +174,10 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:18];
constant:timeLabelHeight];
// Available on iOS 8 and later
[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
@ -307,7 +315,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
NSDate *date = bubbleData.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.textAlignment = NSTextAlignmentRight;
@ -354,7 +362,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:18];
constant:RoomBubbleCellLayout.timestampLabelHeight];
// Available on iOS 8 and later
[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;
MXKRoomBubbleCellData *bubbleCellData = roomBubbleTableViewCell.bubbleData;
@ -518,21 +532,62 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
if (roomBubbleTableViewCell.attachmentView || roomBubbleTableViewCell.messageTextView)
{
CGRect roomBubbleTableViewCellFrame = roomBubbleTableViewCell.frame;
CGFloat x = roomBubbleTableViewCellFrame.origin.x;
CGFloat y = roomBubbleTableViewCellFrame.origin.y + selectedComponenContentViewYOffset + selectedComponentPositionY;
CGFloat width = roomBubbleTableViewCellFrame.size.width;
CGFloat x = 0;
CGFloat y = selectedComponenContentViewYOffset + selectedComponentPositionY;
CGFloat width = roomBubbleTableViewCell.contentView.frame.size.width;
componentFrame = CGRectMake(x, y, width, selectedComponentHeight);
}
else
{
componentFrame = roomBubbleTableViewCell.frame;
componentFrame = roomBubbleTableViewCell.bounds;
}
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
- (IBAction)onEditButtonPressed:(id)sender
@ -581,7 +636,7 @@ NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellT
// Define 'Edit' button frame
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;
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 {
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
internal static var eventFormatterRerequestKeysPart1Link: String {
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";
@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
@ -49,29 +72,24 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
- (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.
if (RiotSettings.shared.enableCrashReport)
{
[PiwikTracker shared].isOptedOut = NO;
[MatomoTracker shared].isOptedOut = NO;
[[PiwikTracker shared] setCustomVariableWithIndex:1 name:@"App Platform" value:@"iOS Platform"];
[[PiwikTracker shared] setCustomVariableWithIndex:2 name:@"App Version" value:[AppDelegate theDelegate].appVersion];
[[MatomoTracker shared] setCustomVariableWithIndex:1 name:@"App Platform" value:@"iOS Platform"];
[[MatomoTracker shared] setCustomVariableWithIndex:2 name:@"App Version" value:[AppDelegate theDelegate].appVersion];
// The language is either the one selected by the user within the app
// or, else, the one configured by the OS
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;
if (account)
{
[[PiwikTracker shared] setCustomVariableWithIndex:7 name:@"Homeserver URL" value:account.mxCredentials.homeServer];
[[PiwikTracker shared] setCustomVariableWithIndex:8 name:@"Identity Server URL" value:account.identityServerURL];
[[MatomoTracker shared] setCustomVariableWithIndex:7 name:@"Homeserver URL" value:account.mxCredentials.homeServer];
[[MatomoTracker shared] setCustomVariableWithIndex:8 name:@"Identity Server URL" value:account.identityServerURL];
}
// TODO: We should also track device and os version
@ -83,20 +101,20 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
#ifdef DEBUG
// Disable analytics in debug as it pollutes stats
[PiwikTracker shared].isOptedOut = YES;
[MatomoTracker shared].isOptedOut = YES;
#endif
}
else
{
NSLog(@"[AppDelegate] The user decided to not send analytics");
[PiwikTracker shared].isOptedOut = YES;
[MatomoTracker shared].isOptedOut = YES;
[MXLogger logCrashes:NO];
}
}
- (void)stop
{
[PiwikTracker shared].isOptedOut = YES;
[MatomoTracker shared].isOptedOut = YES;
[MXLogger logCrashes:NO];
}
@ -106,20 +124,20 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
NSString *appName = [[NSBundle mainBundle] infoDictionary][@"CFBundleDisplayName"];
NSString *appVersion = [AppDelegate theDelegate].appVersion;
[[PiwikTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName]
[[MatomoTracker shared] trackWithView:@[@"ios", appName, appVersion, screenName]
url:nil];
}
- (void)dispatch
{
[[PiwikTracker shared] dispatch];
[[MatomoTracker shared] dispatch];
}
- (void)trackLaunchScreenDisplayDuration:(NSTimeInterval)seconds
{
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
[[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action
name:kMXAnalyticsStartupLaunchScreen
number:@(seconds * 1000)
@ -132,7 +150,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
[[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action
name:kMXAnalyticsStartupStorePreload
number:@(seconds * 1000)
@ -143,7 +161,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
[[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action
name:kMXAnalyticsStartupMountData
number:@(seconds * 1000)
@ -154,7 +172,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStartupCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
[[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action
name:isInitial ? kMXAnalyticsStartupInititialSync : kMXAnalyticsStartupIncrementalSync
number:@(seconds * 1000)
@ -165,7 +183,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{
NSString *action = [NSString stringWithFormat:kAnalyticsMetricsActionPattern, kMXAnalyticsStatsCategory];
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
[[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsMetricsCategory
action:action
name:kMXAnalyticsStatsRooms
number:@(roomCount)
@ -178,7 +196,7 @@ NSString *const kAnalyticsE2eDecryptionFailureAction = @"Decryption failure";
{
for (NSString *reason in failuresCounts)
{
[[PiwikTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory
[[MatomoTracker shared] trackWithEventWithCategory:kAnalyticsE2eCategory
action:kAnalyticsE2eDecryptionFailureAction
name:reason
number:failuresCounts[reason]

View file

@ -65,4 +65,19 @@ typedef NS_ENUM(NSInteger, RoomBubbleCellDataTag)
*/
@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

View file

@ -25,11 +25,12 @@
#import "Riot-Swift.h"
static NSAttributedString *timestampVerticalWhitespace = nil;
static NSAttributedString *readReceiptVerticalWhitespace = nil;
@interface RoomBubbleCellData()
@property(nonatomic, readonly) BOOL addVerticalWhitespaceForSelectedComponentTimestamp;
@property(nonatomic, readwrite) CGFloat additionalContentHeight;
@property(nonatomic) BOOL shouldUpdateAdditionalContentHeight;
@end
@ -72,10 +73,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Increase maximum number of components
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
self.attributedTextMessage = nil;
@ -107,6 +104,8 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
shouldUpdateComponentsPosition = NO;
}
[self updateAdditionalContentHeightIfNeeded];
}
- (NSAttributedString*)attributedTextMessage
@ -274,12 +273,12 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Check whether there is at least one component.
if (bubbleComponents.count)
{
BOOL hasReadReceiptsOrReactions = NO;
// 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;
MXKRoomBubbleComponent *component;
NSUInteger index = 0;
// Use same position for first components without render (redacted)
for (; index < bubbleComponents.count; index++)
{
// Compute the vertical position for next component
@ -289,8 +288,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
if (component.attributedTextMessage)
{
hasReadReceiptsOrReactions = (self.reactions[component.event.eventId].reactions.count > 0);
hasReadReceiptsOrReactions |= (self.readReceipts[component.event.eventId].count > 0);
break;
}
}
@ -298,31 +295,11 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Check whether the position of other components need to be refreshed
if (!self.attachment && index < bubbleComponents.count)
{
NSMutableAttributedString *attributedString;
NSMutableAttributedString *attributedString = [NSMutableAttributedString new];
NSInteger selectedComponentIndex = self.selectedComponentIndex;
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
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++)
for (index = 0; index < bubbleComponents.count; index++)
{
// Compute the vertical position for next component
component = bubbleComponents[index];
@ -330,17 +307,12 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
if (component.attributedTextMessage)
{
// 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)
{
NSMutableAttributedString *componentAttributedString = [[NSMutableAttributedString alloc] initWithAttributedString:[RoomBubbleCellData timestampVerticalWhitespace]];
[componentAttributedString appendAttributedString:component.attributedTextMessage];
componentString = componentAttributedString;
}
else
{
componentString = component.attributedTextMessage;
[attributedString appendAttributedString:[RoomBubbleCellData timestampVerticalWhitespace]];
}
// Append this attributed string.
@ -353,9 +325,10 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
positionY = MXKROOMBUBBLECELLDATA_TEXTVIEW_DEFAULT_VERTICAL_INSET + (cumulatedHeight - [self rawTextHeight:componentString]);
component.position = CGPointMake(0, positionY);
// Vertical whitespace is added in case of read receipts or reactions
[self addVerticalWhitespaceToString:attributedString forEvent:component.event.eventId];
[attributedString appendAttributedString:[MXKRoomBubbleCellDataWithAppendingMode messageSeparator]];
}
else
@ -377,8 +350,10 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
if (reactionCount)
{
CGFloat bubbleReactionsViewWidth = self.maxTextViewWidth - 4;
CGSize fittingSize = UILayoutFittingCompressedSize;
fittingSize.width = self.maxTextViewWidth;
fittingSize.width = bubbleReactionsViewWidth;
static BubbleReactionsView *bubbleReactionsView;
@ -387,12 +362,13 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
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];
bubbleReactionsView.viewModel = viemModel;
[bubbleReactionsView setNeedsLayout];
[bubbleReactionsView layoutIfNeeded];
CGFloat height = [bubbleReactionsView systemLayoutSizeFittingSize:fittingSize].height;
CGFloat height = [bubbleReactionsView systemLayoutSizeFittingSize:fittingSize].height + RoomBubbleCellLayout.reactionsViewTopMargin;
[attributedString appendAttributedString:[RoomBubbleCellData verticalWhitespaceForHeight: height]];
}
@ -400,10 +376,103 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
// Add vertical whitespace in case of read receipts.
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
{
// Check whether there is something to do
@ -509,33 +578,21 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
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
{
NSUInteger returns = height / 6;
UIFont *sizingFont = [UIFont systemFontOfSize:2];
CGFloat returnHeight = sizingFont.lineHeight;
NSUInteger returns = (NSUInteger)round(height/returnHeight);
NSMutableString *returnString = [NSMutableString string];
for (NSUInteger i = 0; i < returns; i++)
{
[returnString appendString:@"\n"];
}
return [[NSAttributedString alloc] initWithString:returnString attributes:@{NSForegroundColorAttributeName : [UIColor blackColor],
NSFontAttributeName: [UIFont systemFontOfSize:6]}];
NSFontAttributeName: sizingFont}];
}
- (BOOL)hasSameSenderAsBubbleCellData:(id<MXKRoomBubbleCellDataStoring>)bubbleCellData
@ -569,9 +626,6 @@ static NSAttributedString *readReceiptVerticalWhitespace = nil;
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];
}

View file

@ -16,7 +16,7 @@
import UIKit
final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
@objc final class ReactionsMenuViewModel: NSObject, ReactionsMenuViewModelType {
// MARK: - Properties
@ -33,14 +33,16 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
private(set) var isDislikeButtonSelected: Bool = false
weak var viewDelegate: ReactionsMenuViewModelDelegate?
weak var coordinatorDelegate: ReactionsMenuViewModelCoordinatorDelegate?
@objc weak var coordinatorDelegate: ReactionsMenuViewModelCoordinatorDelegate?
// MARK: - Setup
init(aggregations: MXAggregations, roomId: String, eventId: String) {
@objc init(aggregations: MXAggregations, roomId: String, eventId: String) {
self.aggregations = aggregations
self.roomId = roomId
self.eventId = eventId
super.init()
self.loadData()
self.listenToDataUpdate()
@ -72,7 +74,7 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
return
}
self.react(withReaction: theReaction, selected: theNewState, delegate: self.coordinatorDelegate)
self.react(withReaction: theReaction, selected: theNewState)
}
// MARK: - Private
@ -85,7 +87,7 @@ final class ReactionsMenuViewModel: ReactionsMenuViewModelType {
}
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
}
@ -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 selected {
self.ensure3StateButtons(withReaction: reaction)
}
let reactionString = reaction.rawValue
if selected {
self.aggregations.sendReaction(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: 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)
})
self.coordinatorDelegate?.reactionsMenuViewModel(self, didAddReaction: reactionString, forEventId: self.eventId)
} else {
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)
})
self.coordinatorDelegate?.reactionsMenuViewModel(self, didRemoveReaction: reactionString, forEventId: self.eventId)
}
delegate?.reactionsMenuViewModel(self, didSendReaction: reaction.rawValue, isAddReaction: !selected)
}
// 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)
}
protocol ReactionsMenuViewModelCoordinatorDelegate: class {
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didSendReaction reaction: String, isAddReaction: Bool)
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didReactionComplete reaction: String, isAddReaction: Bool)
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModelType, didReactionFailedWithError error: Error, reaction: String, isAddReaction: Bool)
@objc protocol ReactionsMenuViewModelCoordinatorDelegate: class {
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didAddReaction reaction: String, forEventId eventId: String)
func reactionsMenuViewModel(_ viewModel: ReactionsMenuViewModel, didRemoveReaction reaction: String, forEventId eventId: String)
}

View file

@ -106,10 +106,8 @@ final class RoomContextualMenuPresenter: NSObject {
animationCompletionInstructions()
}
}
func showReactionsMenu(forEvent eventId: String, inRoom roomId: String, session: MXSession,
aroundFrame frame: CGRect) {
let reactionsMenuViewModel = ReactionsMenuViewModel(aggregations: session.aggregations, roomId: roomId, eventId: eventId)
func showReactionsMenu(reactionsMenuViewModel: ReactionsMenuViewModel, aroundFrame frame: CGRect) {
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) {
self.reactionsMenuView.viewModel = viewModel
self.reactionsMenuView.viewModel?.coordinatorDelegate = self
self.reactionsMenuView.isHidden = false
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
extension RoomContextualMenuViewController: UIGestureRecognizerDelegate {

View file

@ -28,8 +28,6 @@
#import "MXRoom+Riot.h"
static CGFloat kBubbleReactionsViewLeftMargin = 55.0;
static CGFloat kBubbleReactionsViewRightMargin = 15.0;
@interface RoomDataSource() <BubbleReactionsViewModelDelegate>
{
@ -122,87 +120,29 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
[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
dispatch_async(MXKRoomDataSource.processingQueue, ^{
[super updateCellDataReactions:cellData forEventId:eventId];
// Remove the previous displayed read receipt for each user who sent a
// 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;
[self setNeedsUpdateAdditionalContentHeightForCellData:cellData];
}
@synchronized(bubbles)
{
for (RoomBubbleCellData *cellData in bubbles)
{
NSMutableDictionary<NSString* /* eventId */, NSArray<MXReceiptData*> *> *updatedCellDataReadReceipts = [NSMutableDictionary dictionary];
- (void)updateCellData:(MXKRoomBubbleCellData*)cellData withReadReceipts:(NSArray<MXReceiptData*>*)readReceipts forEventId:(NSString*)eventId
{
[super updateCellData:cellData withReadReceipts:readReceipts forEventId:eventId];
[self setNeedsUpdateAdditionalContentHeightForCellData:cellData];
}
for (NSString *eventId in cellData.readReceipts)
{
for (MXReceiptData *receiptData in cellData.readReceipts[eventId])
{
for (NSString *senderId in readReceiptSenders)
{
if ([receiptData.userId isEqualToString:senderId])
{
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];
});
});
- (void)setNeedsUpdateAdditionalContentHeightForCellData:(id<MXKRoomBubbleCellDataStoring>)cellData
{
RoomBubbleCellData *roomBubbleCellData;
if ([cellData isKindOfClass:[RoomBubbleCellData class]])
{
roomBubbleCellData = (RoomBubbleCellData*)cellData;
[roomBubbleCellData setNeedsUpdateAdditionalContentHeight];
}
}
#pragma mark -
@ -267,6 +207,8 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
[bubbleCell addTimestampLabelForComponent:cellData.mostRecentComponentIndex];
}
NSMutableArray *temporaryViews = [NSMutableArray new];
// Handle read receipts and read marker display.
// Ignore the read receipts on the bubble without actual display.
// 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.
// 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;
while (index--)
NSInteger index = 0;
for (MXKRoomBubbleComponent *component in bubbleComponents)
{
MXKRoomBubbleComponent *component = bubbleComponents[index];
NSString *componentEventId = component.event.eventId;
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;
// Handle read receipts (if any)
if (self.showBubbleReceipts && cellData.readReceipts.count && !isCollapsableCellCollapsed)
{
@ -315,7 +311,7 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
if (roomMembers.count)
{
// 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
avatarsContainer.maxDisplayedAvatars = 5;
@ -337,6 +333,8 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
avatarsContainer.translatesAutoresizingMaskIntoConstraints = NO;
avatarsContainer.accessibilityIdentifier = @"readReceiptsContainer";
[temporaryViews addObject:avatarsContainer];
// Add this read receipts container in the content view
if (!bubbleCell.tmpSubviews)
{
@ -355,14 +353,14 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:150];
constant:RoomBubbleCellLayout.readReceiptsViewWidth];
NSLayoutConstraint *heightConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:12];
constant:RoomBubbleCellLayout.readReceiptsViewHeight];
// Force receipts container position
NSLayoutConstraint *trailingConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
@ -371,61 +369,25 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
toItem:avatarsContainer.superview
attribute:NSLayoutAttributeTrailing
multiplier:1.0
constant:-6];
NSLayoutConstraint *topConstraint = [NSLayoutConstraint constraintWithItem:avatarsContainer
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:avatarsContainer.superview
attribute:NSLayoutAttributeTop
multiplier:1.0
constant:bottomPositionY - 13];
constant:-RoomBubbleCellLayout.readReceiptsViewRightMargin];
// At the bottom, we have reactions or nothing
NSLayoutConstraint *topConstraint;
if (reactionsView)
{
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:reactionsView.bottomAnchor constant:RoomBubbleCellLayout.readReceiptsViewTopMargin];
}
else
{
topConstraint = [avatarsContainer.topAnchor constraintEqualToAnchor:avatarsContainer.superview.topAnchor constant:bottomPositionY + RoomBubbleCellLayout.readReceiptsViewTopMargin];
}
// Available on iOS 8 and later
[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.
if (self.showReadMarker)
{
@ -438,7 +400,7 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
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;
// Hide by default the marker, it will be shown and animated when the cell will be rendered.
bubbleCell.readMarkerView.hidden = YES;
@ -450,45 +412,58 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
// Force read marker constraints
bubbleCell.readMarkerViewTopConstraint = [NSLayoutConstraint constraintWithItem:bubbleCell.readMarkerView
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
attribute:NSLayoutAttributeTop
relatedBy:NSLayoutRelationEqual
toItem:bubbleCell.readMarkerView
attribute:NSLayoutAttributeTrailing
toItem:bubbleCell.bubbleOverlayContainer
attribute:NSLayoutAttributeTop
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
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:2];
attribute:NSLayoutAttributeHeight
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0
constant:RoomBubbleCellLayout.readMarkerViewHeight];
[NSLayoutConstraint activateConstraints:@[bubbleCell.readMarkerViewTopConstraint, bubbleCell.readMarkerViewLeadingConstraint, bubbleCell.readMarkerViewTrailingConstraint, bubbleCell.readMarkerViewHeightConstraint]];
}
}
}
// Prepare the bottom position for the next read receipt container (if any)
bottomPositionY = bubbleCell.msgTextViewTopConstraint.constant + component.position.y;
index++;
}
}
// 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
if (_selectedEventId)
{
@ -581,19 +556,19 @@ static CGFloat kBubbleReactionsViewRightMargin = 15.0;
- (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
{
[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"
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate>
@interface RoomViewController () <UISearchBarDelegate, UIGestureRecognizerDelegate, RoomTitleViewTapGestureDelegate, RoomParticipantsViewControllerDelegate, MXKRoomMemberDetailsViewControllerDelegate, ContactsTableViewControllerDelegate, MXServerNoticesDelegate, RoomContextualMenuViewControllerDelegate,
ReactionsMenuViewModelCoordinatorDelegate>
{
// The expanded header
ExpandedRoomTitleView *expandedHeader;
@ -216,6 +217,8 @@
@property (nonatomic, weak) IBOutlet UIView *overlayContainerView;
@property (nonatomic, strong) RoomContextualMenuPresenter *roomContextualMenuPresenter;
@property (nonatomic, strong) MXKErrorAlertPresentation *errorPresenter;
@property (nonatomic, strong) NSString *textMessageBeforeEditing;
@end
@ -409,6 +412,7 @@
}
self.roomContextualMenuPresenter = [RoomContextualMenuPresenter new];
self.errorPresenter = [MXKErrorAlertPresentation new];
// Observe user interface theme change.
kThemeServiceDidChangeThemeNotificationObserver = [[NSNotificationCenter defaultCenter] addObserverForName:kThemeServiceDidChangeThemeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) {
@ -1121,6 +1125,13 @@
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
{
// Let the datasource send it and manage the local echo
@ -2821,9 +2832,9 @@
NSString *fragment = [NSString stringWithFormat:@"/group/%@", [MXTools encodeURIComponent:absoluteURLString]];
[[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)
{
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)
{
// Fallback case for external links
@ -2874,12 +2898,12 @@
- (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.selectedEventId = eventId;
@ -2901,6 +2925,8 @@
customizedRoomDataSource.showBubbleDateTimeOnSelection = YES;
customizedRoomDataSource.selectedEventId = nil;
[self restoreTextMessageBeforeEditing];
// Force table refresh
[self dataSource:self.roomDataSource didCellChange:nil];
}
@ -2911,6 +2937,45 @@
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
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
@ -5046,14 +5111,25 @@
MXStrongifyAndReturnIfNil(self);
[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
RoomContextualMenuItem *editMenuItem = [[RoomContextualMenuItem alloc] initWithMenuAction:RoomContextualMenuActionEdit];
// TODO: Handle edit action
editMenuItem.isEnabled = NO;
editMenuItem.action = ^{
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
@ -5082,22 +5158,23 @@
return;
}
[self selectEventWithId:event.eventId enableReplyMode:NO showTimestamp:YES];
[self selectEventWithId:event.eventId];
NSArray<RoomContextualMenuItem*>* contextualMenuItems = [self contextualMenuItemsForEvent:event andCell:cell];
RoomContextualMenuViewController *roomContextualMenuViewController = [RoomContextualMenuViewController instantiateWith:contextualMenuItems];
roomContextualMenuViewController.delegate = self;
[self enableOverlayContainerUserInteractions:YES];
[self.roomContextualMenuPresenter presentWithRoomContextualMenuViewController:roomContextualMenuViewController
from:self
on:self.overlayContainerView
animated:YES
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;
MXKRoomBubbleCellData *bubbleCellData = roomBubbleTableViewCell.bubbleData;
@ -5117,16 +5194,22 @@
if (bubbleComponents.count > 0)
{
NSInteger selectedComponentIndex = foundComponentIndex != NSNotFound ? foundComponentIndex : 0;
bubbleComponentFrame = [roomBubbleTableViewCell componentFrameForIndex:selectedComponentIndex];
bubbleComponentFrame = [roomBubbleTableViewCell componentFrameInTableViewForIndex:selectedComponentIndex];
}
else
{
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 contextualMenuAnimationCompletionAfterBeingShown:NO];
[self enableOverlayContainerUserInteractions:NO];
if (completion)
{
@ -5162,11 +5245,11 @@
}];
}
- (void)contextualMenuAnimationCompletionAfterBeingShown:(BOOL)isShown
- (void)enableOverlayContainerUserInteractions:(BOOL)enableOverlayContainerUserInteractions
{
self.inputToolbarView.editable = !isShown;
self.bubblesTableView.scrollsToTop = !isShown;
self.overlayContainerView.userInteractionEnabled = isShown;
self.inputToolbarView.editable = !enableOverlayContainerUserInteractions;
self.bubblesTableView.scrollsToTop = !enableOverlayContainerUserInteractions;
self.overlayContainerView.userInteractionEnabled = enableOverlayContainerUserInteractions;
}
#pragma mark - RoomContextualMenuViewControllerDelegate
@ -5181,5 +5264,37 @@
[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

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];
}
+ (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

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

View file

@ -16,6 +16,7 @@
*/
#import "RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h"
#import "MXKRoomBubbleTableViewCell+Riot.h"
#import "ThemeService.h"
#import "Riot-Swift.h"
@ -29,4 +30,16 @@
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

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

View file

@ -19,6 +19,8 @@
#import "ThemeService.h"
#import "Riot-Swift.h"
#import "RoomBubbleCellData.h"
#import "MXKRoomBubbleTableViewCell+Riot.h"
@implementation RoomOutgoingAttachmentWithoutSenderInfoBubbleCell
@ -36,4 +38,16 @@
[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

View file

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

View file

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

View file

@ -19,18 +19,35 @@
/**
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.
*/
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
*/
@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.
*/

View file

@ -27,8 +27,9 @@
#pragma mark - Constants definitions
NSString *const kEventFormatterOnReRequestKeysLinkAction = @"kEventFormatterOnReRequestKeysLinkAction";
NSString *const kEventFormatterOnReRequestKeysLinkActionSeparator = @"/";
NSString *const EventFormatterOnReRequestKeysLinkAction = @"EventFormatterOnReRequestKeysLinkAction";
NSString *const EventFormatterLinkActionSeparator = @"/";
NSString *const EventFormatterEditedEventLinkAction = @"EventFormatterEditedEventLinkAction";
static NSString *const kEventFormatterTimeFormat = @"HH:mm";
@ -159,8 +160,8 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
NSMutableAttributedString *attributedStringWithRerequestMessage = [attributedString mutableCopy];
[attributedStringWithRerequestMessage appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n"]];
NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", kEventFormatterOnReRequestKeysLinkAction,
kEventFormatterOnReRequestKeysLinkActionSeparator,
NSString *linkActionString = [NSString stringWithFormat:@"%@%@%@", EventFormatterOnReRequestKeysLinkAction,
EventFormatterLinkActionSeparator,
event.eventId];
[attributedStringWithRerequestMessage appendAttributedString:
@ -181,6 +182,26 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
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;
}
@ -234,6 +255,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
self.encryptingTextColor = ThemeService.shared.theme.tintColor;
self.sendingTextColor = ThemeService.shared.theme.textSecondaryColor;
self.errorTextColor = ThemeService.shared.theme.warningColor;
self.editionMentionTextColor = ThemeService.shared.theme.textSecondaryColor;
self.defaultTextFont = [UIFont systemFontOfSize:15];
self.prefixTextFont = [UIFont boldSystemFontOfSize:15];
@ -242,6 +264,7 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm";
self.callNoticesTextFont = [UIFont italicSystemFontOfSize:15];
self.encryptedMessagesTextFont = [UIFont italicSystemFontOfSize:15];
self.emojiOnlyTextFont = [UIFont systemFontOfSize:48];
self.editionMentionTextFont = [UIFont systemFontOfSize:12];
}
return self;
}