From 2d838bcf98d9999e6e28bbaa8eea6f55c502600a Mon Sep 17 00:00:00 2001 From: opusforlife2 <53176348+opusforlife2@users.noreply.github.com> Date: Mon, 11 Oct 2021 19:15:04 +0000 Subject: [PATCH 001/122] Edited heading + subheadings to avoid redundancy Also made the subheadings one size smaller (4 #'s instead of 3) --- .github/ISSUE_TEMPLATE/bug.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index d50712529..d95e16935 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -23,12 +23,12 @@ body: - type: textarea id: result attributes: - label: What happened? + label: Intended result and actual result placeholder: Tell us what went wrong value: | - ### What did you expect? + #### What did you expect? - ### What happened? + #### What happened instead? validations: required: true - type: input From 16061e5d9ebedeecda757fb20ea319155e69c839 Mon Sep 17 00:00:00 2001 From: opusforlife2 <53176348+opusforlife2@users.noreply.github.com> Date: Mon, 11 Oct 2021 19:19:46 +0000 Subject: [PATCH 002/122] Add changelog file for PR #4984 --- changelog.d/4984.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4984.misc diff --git a/changelog.d/4984.misc b/changelog.d/4984.misc new file mode 100644 index 000000000..97b50d8c5 --- /dev/null +++ b/changelog.d/4984.misc @@ -0,0 +1 @@ +Fix redundancy in heading in the bug report issue form From df94b699a03e30e623ec0c7b88dfaad666307774 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 12 Oct 2021 20:48:30 +0200 Subject: [PATCH 003/122] Support pagination in the Space Summary API --- .../SpaceChildLoadingViewCell.swift | 45 ++++++++++++++++++ .../ExploreRoom/SpaceChildLoadingViewCell.xib | 47 +++++++++++++++++++ .../SpaceExploreRoomViewController.swift | 21 +++++++-- .../SpaceExploreRoomViewModel.swift | 35 +++++++++++--- .../SpaceExploreRoomViewState.swift | 2 +- changelog.d/4893.feature | 1 + 6 files changed, 140 insertions(+), 11 deletions(-) create mode 100644 Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift create mode 100644 Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib create mode 100644 changelog.d/4893.feature diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift new file mode 100644 index 000000000..e70a9565e --- /dev/null +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift @@ -0,0 +1,45 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import UIKit +import Reusable + +class SpaceChildLoadingViewCell: UITableViewCell, NibReusable, Themable { + + // MARK: - Properties + + @IBOutlet var circleProgressView: CircleProgressView! + + // MARK: - Life cycle + + override func awakeFromNib() { + super.awakeFromNib() + + setupViews() + } + + // MARK: - Public + + func update(theme: Theme) { + self.circleProgressView.lineColor = theme.colors.tertiaryContent + } + + // MARK: - Private + + private func setupViews() { + self.circleProgressView.startAnimating() + } +} diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib new file mode 100644 index 000000000..84fc0e1fe --- /dev/null +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift index 664493c2e..28a64b161 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift @@ -41,10 +41,11 @@ final class SpaceExploreRoomViewController: UIViewController { private var titleView: MainTitleView! private var emptyView: RootTabEmptyView! private var plusButtonImageView: UIImageView! + private var hasMore: Bool = false private var itemDataList: [SpaceExploreRoomListItemViewData] = [] { didSet { - tableView.reloadData() + self.tableView.reloadData() } } @@ -168,6 +169,7 @@ final class SpaceExploreRoomViewController: UIViewController { self.tableView.allowsSelection = true self.tableView.register(cellType: SpaceChildViewCell.self) self.tableView.register(cellType: SpaceChildSpaceViewCell.self) + self.tableView.register(cellType: SpaceChildLoadingViewCell.self) self.tableView.tableFooterView = UIView() } @@ -177,7 +179,8 @@ final class SpaceExploreRoomViewController: UIViewController { self.renderLoading() case .spaceNameFound(let spaceName): self.titleView.subtitleLabel.text = spaceName - case .loaded(let children): + case .loaded(let children, let hasMore): + self.hasMore = hasMore self.renderLoaded(children: children) case .emptySpace: self.renderEmptySpace() @@ -240,10 +243,16 @@ extension SpaceExploreRoomViewController: UITableViewDataSource { } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { - return self.itemDataList.count + return self.itemDataList.count + (self.hasMore ? 1 : 0) } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + guard indexPath.row < self.itemDataList.count else { + let cell = tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildLoadingViewCell.self) + cell.update(theme: self.theme) + return cell + } + let viewData = self.itemDataList[indexPath.row] let cell = viewData.childInfo.roomType == .space ? tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildSpaceViewCell.self) : tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildViewCell.self) @@ -262,6 +271,12 @@ extension SpaceExploreRoomViewController: UITableViewDelegate { tableView.deselectRow(at: indexPath, animated: true) self.viewModel.process(viewAction: .complete(self.itemDataList[indexPath.row], tableView.cellForRow(at: indexPath))) } + + func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if self.hasMore && indexPath.row >= self.itemDataList.count { + self.viewModel.process(viewAction: .loadData) + } + } } // MARK: - SpaceExploreRoomViewModelViewDelegate diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift index 349530bb9..171e8084e 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift @@ -29,13 +29,15 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { private let spaceName: String? private var currentOperation: MXHTTPOperation? + private var nextBatch: String? + private var rootSpaceChildInfo: MXSpaceChildInfo? private var itemDataList: [SpaceExploreRoomListItemViewData] = [] { didSet { self.updateFilteredItemList() } } - private var searchKeyword: String? = nil { + private var searchKeyword: String? { didSet { self.updateFilteredItemList() } @@ -49,7 +51,7 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { self.update(viewState: .emptyFilterResult) } } else { - self.update(viewState: .loaded(self.filteredItemDataList)) + self.update(viewState: .loaded(self.filteredItemDataList, self.nextBatch != nil && (self.searchKeyword ?? "").isEmpty)) } } } @@ -90,32 +92,51 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { // MARK: - Private private func loadData() { + guard self.currentOperation == nil else { + return + } + if let spaceName = self.spaceName { self.update(viewState: .spaceNameFound(spaceName)) } - self.update(viewState: .loading) + if self.nextBatch == nil { + self.update(viewState: .loading) + } - self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, completion: { [weak self] response in + self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, from: self.nextBatch, completion: { [weak self] response in guard let self = self else { return } switch response { case .success(let spaceSummary): - self.itemDataList = spaceSummary.childInfos.compactMap({ childInfo in - guard childInfo.parentIds.contains(self.spaceId) else { + self.nextBatch = spaceSummary.nextBatch + // The MXSpaceChildInfo of the root space is available only in the first batch + if let rootSpaceInfo = spaceSummary.spaceInfo { + self.rootSpaceChildInfo = rootSpaceInfo + } + + let batchedItemDataList: [SpaceExploreRoomListItemViewData] = spaceSummary.childInfos.compactMap({ childInfo in + guard let rootSpaceInfo = self.rootSpaceChildInfo, rootSpaceInfo.childrenIds.contains(childInfo.childRoomId) else { return nil } - let avatarViewData = AvatarViewData(matrixItemId: childInfo.childRoomId, displayName: childInfo.displayName, avatarUrl: childInfo.avatarUrl, mediaManager: self.session.mediaManager, fallbackImage: .matrixItem(childInfo.childRoomId, childInfo.name)) + let avatarViewData = AvatarViewData(matrixItemId: childInfo.childRoomId, + displayName: childInfo.displayName, + avatarUrl: childInfo.avatarUrl, + mediaManager: self.session.mediaManager, + fallbackImage: .matrixItem(childInfo.childRoomId, childInfo.name)) return SpaceExploreRoomListItemViewData(childInfo: childInfo, avatarViewData: avatarViewData) }).sorted(by: { item1, item2 in return !item2.childInfo.suggested || item1.childInfo.suggested }) + self.itemDataList.append(contentsOf: batchedItemDataList) case .failure(let error): self.update(viewState: .error(error)) } + + self.currentOperation = nil }) } diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewState.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewState.swift index c7c8ae50e..52203c190 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewState.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewState.swift @@ -22,7 +22,7 @@ import Foundation enum SpaceExploreRoomViewState { case loading case spaceNameFound(_ spaceName: String) - case loaded(_ children: [SpaceExploreRoomListItemViewData]) + case loaded(_ children: [SpaceExploreRoomListItemViewData], _ hasMore: Bool) case emptySpace case emptyFilterResult case error(Error) diff --git a/changelog.d/4893.feature b/changelog.d/4893.feature new file mode 100644 index 000000000..1cdb014be --- /dev/null +++ b/changelog.d/4893.feature @@ -0,0 +1 @@ +SpaceExploreRoomViewModel: Support pagination in the Space Summary API \ No newline at end of file From 3fa7468ba8491bba98085058a947d4542eb631c6 Mon Sep 17 00:00:00 2001 From: jelv Date: Sun, 24 Oct 2021 12:46:50 +0000 Subject: [PATCH 004/122] Translated using Weblate (Dutch) Currently translated at 100.0% (6 of 6 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/nl/ --- Riot/Assets/nl.lproj/InfoPlist.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/nl.lproj/InfoPlist.strings b/Riot/Assets/nl.lproj/InfoPlist.strings index ecf246480..c3c846e97 100644 --- a/Riot/Assets/nl.lproj/InfoPlist.strings +++ b/Riot/Assets/nl.lproj/InfoPlist.strings @@ -18,6 +18,6 @@ "NSCameraUsageDescription" = "De camera wordt gebruikt om foto’s en video’s te maken, en voor videogesprekken."; "NSPhotoLibraryUsageDescription" = "De fotogalerij wordt gebruikt om foto’s en video’s te versturen."; "NSMicrophoneUsageDescription" = "Element heeft toegang nodig tot uw microfoon nodig voor oproepen, maken van video's en spraakberichten opnemen."; -"NSContactsUsageDescription" = "Om u te kunnen tonen welke van uw contacten reeds Matrix gebruiken, kan Element de e-mailadressen en telefoonnummers in uw adresboek naar uw gekozen Matrix-identiteitsserver sturen. Waar mogelijk worden persoonlijke gegevens gehasht voor verzending - bekijk het privacybeleid van uw identiteitsserver voor meer informatie."; +"NSContactsUsageDescription" = "Element zal uw contacten tonen zodat u ze kunt uitnodigen om te chatten."; "NSCalendarsUsageDescription" = "Bekijk uw geplande afspraken in de app."; "NSFaceIDUsageDescription" = "Face ID wordt gebruikt om toegang te krijgen tot uw app."; From a26ae82a3d95d5b970940e2efe02dbf51c2367b5 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 26 Oct 2021 14:40:51 +0200 Subject: [PATCH 005/122] Support pagination in the Space Summary API - Move back to default iOS activity indicator --- .../SpaceChildLoadingViewCell.swift | 19 +++----------- .../ExploreRoom/SpaceChildLoadingViewCell.xib | 26 ++++++------------- .../SpaceExploreRoomViewModel.swift | 2 +- 3 files changed, 12 insertions(+), 35 deletions(-) diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift index e70a9565e..873241572 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift @@ -21,25 +21,12 @@ class SpaceChildLoadingViewCell: UITableViewCell, NibReusable, Themable { // MARK: - Properties - @IBOutlet var circleProgressView: CircleProgressView! + @IBOutlet var activityIndicator: UIActivityIndicatorView! - // MARK: - Life cycle - - override func awakeFromNib() { - super.awakeFromNib() - - setupViews() - } - // MARK: - Public func update(theme: Theme) { - self.circleProgressView.lineColor = theme.colors.tertiaryContent - } - - // MARK: - Private - - private func setupViews() { - self.circleProgressView.startAnimating() + self.activityIndicator.tintColor = theme.colors.tertiaryContent + self.activityIndicator.startAnimating() } } diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib index 84fc0e1fe..a49cc20a8 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib @@ -13,33 +13,23 @@ - + - - - - - - - - - - - - - + + + - - - + + + - + diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift index 171e8084e..7205f8f2e 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift @@ -104,7 +104,7 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { self.update(viewState: .loading) } - self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, from: self.nextBatch, completion: { [weak self] response in + self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: 20, maxDepth: 1, from: nil, completion: { [weak self] response in guard let self = self else { return } From 6e212707aa40499a16c87dbbf2f2f9413069dc0e Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Tue, 26 Oct 2021 14:44:51 +0200 Subject: [PATCH 006/122] Support pagination in the Space Summary API - Revert test tweaks --- .../SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift index 7205f8f2e..171e8084e 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift @@ -104,7 +104,7 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { self.update(viewState: .loading) } - self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: 20, maxDepth: 1, from: nil, completion: { [weak self] response in + self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, from: self.nextBatch, completion: { [weak self] response in guard let self = self else { return } From af20d2496039fbd67524dee088356c9acd766ce8 Mon Sep 17 00:00:00 2001 From: Philippe Loriaux Date: Tue, 26 Oct 2021 17:42:33 +0200 Subject: [PATCH 007/122] Improve the Obj-C Generated Interface Header Name definition --- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m | 2 +- Riot/Categories/MXRoomSummary+Riot.m | 6 +----- Riot/Categories/MXSession+Riot.m | 2 +- Riot/Categories/UIViewController+RiotSearch.m | 2 +- Riot/Common.xcconfig | 2 ++ Riot/Managers/Analytics/Analytics.m | 2 +- Riot/Managers/AppInfo/BuildInfo.m | 6 +----- Riot/Managers/BugReport/RageShakeManager.m | 2 +- Riot/Managers/PushNotification/PushNotificationService.m | 2 +- Riot/Managers/Theme/ThemeService.m | 6 +----- Riot/Managers/Widgets/WidgetManager.m | 2 +- Riot/Modules/Application/LegacyAppDelegate.m | 2 +- Riot/Modules/Authentication/AuthenticationViewController.m | 4 +--- Riot/Modules/Authentication/Views/AuthInputsView.h | 2 +- .../Modules/Authentication/Views/ForgotPasswordInputsView.m | 2 +- Riot/Modules/BugReport/BugReportViewController.m | 2 +- Riot/Modules/Call/CallViewController.m | 2 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- .../CallTransfer/SelectContact/MatrixContactsDataSource.m | 2 +- Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m | 2 +- Riot/Modules/Common/Recents/Model/RecentCellData.m | 6 +----- Riot/Modules/Common/Recents/RecentsViewController.m | 2 +- Riot/Modules/Common/Recents/Views/RecentTableViewCell.m | 2 +- .../SegmentedViewController/SegmentedViewController.m | 6 +----- .../Common/WebViewController/WebViewViewController.m | 2 +- Riot/Modules/Communities/DataSources/GroupsDataSource.m | 2 +- Riot/Modules/Communities/GroupsViewController.m | 2 +- Riot/Modules/Communities/Home/GroupHomeViewController.m | 2 +- .../Communities/Members/GroupParticipantsViewController.m | 2 +- Riot/Modules/Communities/Rooms/GroupRoomsViewController.m | 2 +- .../Communities/Rooms/Views/GroupRoomTableViewCell.m | 2 +- .../Communities/TabDetail/GroupDetailsViewController.m | 2 +- Riot/Modules/Communities/Views/GroupInviteTableViewCell.m | 2 +- Riot/Modules/Communities/Views/GroupTableViewCell.m | 2 +- Riot/Modules/Contacts/ContactsTableViewController.m | 2 +- Riot/Modules/Contacts/DataSources/ContactsDataSource.m | 2 +- .../Modules/Contacts/Details/ContactDetailsViewController.m | 2 +- Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m | 2 +- Riot/Modules/Contacts/Views/ContactTableViewCell.m | 2 +- Riot/Modules/EncryptionInfo/EncryptionInfoView.m | 2 +- Riot/Modules/Favorites/FavouritesViewController.m | 2 +- .../DataSources/UnifiedSearchRecentsDataSource.m | 2 +- .../GlobalSearch/Files/HomeFilesSearchViewController.m | 2 +- .../GlobalSearch/Files/Views/FilesSearchTableViewCell.m | 2 +- .../Messages/DataSources/HomeMessagesSearchDataSource.m | 2 +- .../Messages/HomeMessagesSearchViewController.m | 2 +- .../Views/MessagesSearchResultAttachmentBubbleCell.m | 2 +- .../Messages/Views/MessagesSearchResultTextMsgBubbleCell.m | 2 +- Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m | 2 +- Riot/Modules/GlobalSearch/UnifiedSearchViewController.m | 2 +- .../GlobalSearch/Views/DirectoryRecentTableViewCell.m | 2 +- .../Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m | 2 +- Riot/Modules/Home/Fallback/AuthFallBackViewController.m | 2 +- Riot/Modules/Home/HomeViewController.m | 2 +- Riot/Modules/Home/Views/RoomCollectionViewCell.m | 2 +- Riot/Modules/Home/Views/TableViewCellWithCollectionView.m | 2 +- .../Modules/Integrations/IntegrationManagerViewController.m | 2 +- .../Integrations/WidgetPicker/WidgetPickerViewController.m | 2 +- .../Integrations/Widgets/Jitsi/JitsiViewController.m | 2 +- .../Widgets/StickerPicker/StickerPickerViewController.m | 2 +- Riot/Modules/Integrations/Widgets/WidgetViewController.m | 2 +- .../MediaPicker/Library/MediaAlbumContentViewController.m | 2 +- Riot/Modules/MediaPicker/MediaPickerViewController.m | 2 +- Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m | 2 +- Riot/Modules/People/PeopleViewController.m | 2 +- Riot/Modules/People/Views/InviteRecentTableViewCell.m | 2 +- .../DataSources/PublicRoomsDirectoryDataSource.m | 2 +- Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m | 2 +- Riot/Modules/Room/Attachements/AttachmentsViewController.m | 2 +- .../Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m | 2 +- Riot/Modules/Room/CellData/RoomBubbleCellData.m | 2 +- Riot/Modules/Room/DataSources/RoomDataSource.m | 2 +- Riot/Modules/Room/Files/RoomFilesViewController.m | 2 +- .../Room/Members/Detail/RoomMemberDetailsViewController.m | 2 +- Riot/Modules/Room/Members/RoomParticipantsViewController.m | 2 +- .../Room/ReadReceiptsDetail/ReadReceiptsViewController.m | 2 +- Riot/Modules/Room/RoomViewController.m | 2 +- Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m | 2 +- .../Room/Search/Files/RoomFilesSearchViewController.m | 2 +- .../Room/Search/Messages/RoomMessagesSearchViewController.m | 2 +- Riot/Modules/Room/Search/RoomSearchViewController.m | 2 +- Riot/Modules/Room/Settings/RoomSettingsViewController.m | 2 +- .../Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m | 2 +- .../Room/Settings/Views/TableViewCellWithCheckBoxes.m | 2 +- .../Settings/Views/TableViewCellWithLabelAndLargeTextView.m | 2 +- Riot/Modules/Room/Views/Activities/RoomActivitiesView.m | 2 +- .../Views/BubbleCells/RoomCreationCollapsedBubbleCell.m | 2 +- .../RoomCreationWithPaginationCollapsedBubbleCell.m | 2 +- .../Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m | 2 +- .../RoomIncomingAttachmentWithPaginationTitleBubbleCell.m | 2 +- .../RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m | 2 +- .../RoomIncomingTextMsgWithPaginationTitleBubbleCell.m | 2 +- ...gTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m | 2 +- .../RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- .../RoomIncomingTextMsgWithoutSenderNameBubbleCell.m | 2 +- .../Room/Views/BubbleCells/RoomMembershipBubbleCell.m | 2 +- .../Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m | 2 +- .../RoomMembershipCollapsedWithPaginationTitleBubbleCell.m | 2 +- .../Views/BubbleCells/RoomMembershipExpandedBubbleCell.m | 2 +- .../RoomMembershipExpandedWithPaginationTitleBubbleCell.m | 2 +- .../RoomMembershipWithPaginationTitleBubbleCell.m | 2 +- .../Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m | 2 +- .../RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m | 2 +- .../RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m | 2 +- .../Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m | 2 +- .../RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m | 2 +- .../RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m | 2 +- .../Room/Views/BubbleCells/RoomPredecessorBubbleCell.m | 2 +- .../Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m | 2 +- Riot/Modules/Room/Views/Event/EventDetailsView.m | 2 +- .../Room/Views/InputToolbar/DisabledRoomInputToolbarView.m | 2 +- Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m | 2 +- .../Room/Views/Title/Expanded/ExpandedRoomTitleView.m | 2 +- .../Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m | 2 +- Riot/Modules/Room/Views/Title/RoomTitleView.m | 2 +- Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m | 2 +- .../DirectoryPicker/DirectoryServerPickerViewController.m | 2 +- .../Views/DirectoryServerDetailTableViewCell.m | 2 +- .../DirectoryPicker/Views/DirectoryServerTableViewCell.m | 2 +- Riot/Modules/Rooms/RoomsViewController.m | 2 +- .../DeactivateAccount/DeactivateAccountViewController.m | 2 +- .../Settings/Language/LanguagePickerViewController.m | 2 +- .../Settings/PhoneCountry/CountryPickerViewController.m | 2 +- .../Security/ManageSession/ManageSessionViewController.m | 2 +- Riot/Modules/Settings/Security/SecurityViewController.m | 2 +- Riot/Modules/Settings/SettingsViewController.m | 2 +- Riot/Modules/Settings/Views/DeviceView.m | 2 +- .../Settings/Views/TableViewCellWithPhoneNumberTextField.m | 2 +- Riot/Modules/StartChat/StartChatViewController.m | 2 +- Riot/Modules/TabBar/MasterTabBarController.m | 2 +- Riot/Modules/UserDevices/UsersDevicesViewController.m | 2 +- Riot/Modules/UserDevices/Views/DeviceTableViewCell.m | 2 +- Riot/Utils/AvatarGenerator.m | 6 +----- Riot/Utils/EventFormatter.m | 2 +- Riot/Utils/Tools.m | 2 +- RiotNSE/Common.xcconfig | 2 ++ RiotShareExtension/Common.xcconfig | 2 ++ RiotShareExtension/Shared/ShareManager.m | 6 +----- RiotShareExtension/Shared/View/FallbackViewController.m | 6 +----- RiotShareExtension/Shared/View/RecentRoomTableViewCell.m | 6 +----- RiotShareExtension/Shared/View/RoomsListViewController.m | 6 +----- RiotShareExtension/Shared/View/ShareViewController.m | 6 +----- .../Sources/ShareExtensionRootViewController.m | 6 +----- RiotSwiftUI/Common.xcconfig | 2 ++ RiotTests/Debug.xcconfig | 2 ++ RiotTests/Release.xcconfig | 2 ++ SiriIntents/Common.xcconfig | 4 +++- SiriIntents/IntentHandler.m | 2 +- 149 files changed, 157 insertions(+), 193 deletions(-) diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 11a0fa5a1..d5b58eb11 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -20,7 +20,7 @@ #import "RoomBubbleCellData.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import diff --git a/Riot/Categories/MXRoomSummary+Riot.m b/Riot/Categories/MXRoomSummary+Riot.m index 7a83d1d40..3ad3bef65 100644 --- a/Riot/Categories/MXRoomSummary+Riot.m +++ b/Riot/Categories/MXRoomSummary+Riot.m @@ -19,11 +19,7 @@ #import "AvatarGenerator.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @implementation MXRoomSummary (Riot) diff --git a/Riot/Categories/MXSession+Riot.m b/Riot/Categories/MXSession+Riot.m index 901c58406..51a2b3db9 100644 --- a/Riot/Categories/MXSession+Riot.m +++ b/Riot/Categories/MXSession+Riot.m @@ -17,7 +17,7 @@ #import "MXSession+Riot.h" #import "MXRoom+Riot.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation MXSession (Riot) diff --git a/Riot/Categories/UIViewController+RiotSearch.m b/Riot/Categories/UIViewController+RiotSearch.m index 73b14b55f..09b7896b3 100644 --- a/Riot/Categories/UIViewController+RiotSearch.m +++ b/Riot/Categories/UIViewController+RiotSearch.m @@ -20,7 +20,7 @@ #import #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" /** `UIViewControllerRiotSearchInternals` is the internal single point storage for the search feature. diff --git a/Riot/Common.xcconfig b/Riot/Common.xcconfig index 312fc83fe..b25a82689 100644 --- a/Riot/Common.xcconfig +++ b/Riot/Common.xcconfig @@ -30,3 +30,5 @@ CODE_SIGN_ENTITLEMENTS = Riot/SupportingFiles/Riot.entitlements SWIFT_OBJC_BRIDGING_HEADER = $(SRCROOT)/$(PRODUCT_NAME)/SupportingFiles/Riot-Bridging-Header.h LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/Riot/Managers/Analytics/Analytics.m b/Riot/Managers/Analytics/Analytics.m index cb7062932..6bf7269b8 100644 --- a/Riot/Managers/Analytics/Analytics.m +++ b/Riot/Managers/Analytics/Analytics.m @@ -16,7 +16,7 @@ #import "Analytics.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" NSString *const AnalyticsNoficationsCategory = @"notifications"; diff --git a/Riot/Managers/AppInfo/BuildInfo.m b/Riot/Managers/AppInfo/BuildInfo.m index a1dbffe14..525088caa 100644 --- a/Riot/Managers/AppInfo/BuildInfo.m +++ b/Riot/Managers/AppInfo/BuildInfo.m @@ -16,11 +16,7 @@ #import "BuildInfo.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" #define MAKE_STRING(x) #x #define MAKE_NS_STRING(x) @MAKE_STRING(x) diff --git a/Riot/Managers/BugReport/RageShakeManager.m b/Riot/Managers/BugReport/RageShakeManager.m index 13bd5c985..a0357d046 100644 --- a/Riot/Managers/BugReport/RageShakeManager.m +++ b/Riot/Managers/BugReport/RageShakeManager.m @@ -23,7 +23,7 @@ #import -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" static RageShakeManager* sharedInstance = nil; diff --git a/Riot/Managers/PushNotification/PushNotificationService.m b/Riot/Managers/PushNotification/PushNotificationService.m index 24ab4246d..fc6eab47d 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.m +++ b/Riot/Managers/PushNotification/PushNotificationService.m @@ -20,7 +20,7 @@ #import #import -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface PushNotificationService() diff --git a/Riot/Managers/Theme/ThemeService.m b/Riot/Managers/Theme/ThemeService.m index 175ab5f64..b205bbb6d 100644 --- a/Riot/Managers/Theme/ThemeService.m +++ b/Riot/Managers/Theme/ThemeService.m @@ -18,11 +18,7 @@ #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" NSString *const kThemeServiceDidChangeThemeNotification = @"kThemeServiceDidChangeThemeNotification"; diff --git a/Riot/Managers/Widgets/WidgetManager.m b/Riot/Managers/Widgets/WidgetManager.m index 416d5f4f6..1e6fbaa7c 100644 --- a/Riot/Managers/Widgets/WidgetManager.m +++ b/Riot/Managers/Widgets/WidgetManager.m @@ -17,7 +17,7 @@ #import "WidgetManager.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "JitsiWidgetData.h" #import "MXSession+Riot.h" diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 6b9816643..75060f84b 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -55,7 +55,7 @@ #import "MXSession+Riot.h" #import "MXRoom+Riot.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "PushNotificationService.h" //#define MX_CALL_STACK_OPENWEBRTC diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index d40090c3d..de5eadc32 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -18,15 +18,13 @@ #import "AuthenticationViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXSession+Riot.h" #import "AuthInputsView.h" #import "ForgotPasswordInputsView.h" #import "AuthFallBackViewController.h" -#import "Riot-Swift.h" - static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; @interface AuthenticationViewController () -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface AuthInputsView : MXKAuthInputsView diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m index 01fa1f500..9173043f7 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.m @@ -19,7 +19,7 @@ #import "MXHTTPOperation.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface ForgotPasswordInputsView () diff --git a/Riot/Modules/BugReport/BugReportViewController.m b/Riot/Modules/BugReport/BugReportViewController.m index 01b04e110..e43ec06d7 100644 --- a/Riot/Modules/BugReport/BugReportViewController.m +++ b/Riot/Modules/BugReport/BugReportViewController.m @@ -16,7 +16,7 @@ #import "BugReportViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "GBDeviceInfo_iOS.h" diff --git a/Riot/Modules/Call/CallViewController.m b/Riot/Modules/Call/CallViewController.m index 3a448e0b0..bb702ad15 100644 --- a/Riot/Modules/Call/CallViewController.m +++ b/Riot/Modules/Call/CallViewController.m @@ -18,7 +18,7 @@ #import "CallViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "AvatarGenerator.h" diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index e56e2f513..9da231175 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -22,7 +22,7 @@ #import "CircleButton.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" static const CGFloat kAvatarSize = 100.0; static const CGFloat kButtonSize = 80.0; diff --git a/Riot/Modules/CallTransfer/SelectContact/MatrixContactsDataSource.m b/Riot/Modules/CallTransfer/SelectContact/MatrixContactsDataSource.m index b86ecf711..1fb9e8d29 100644 --- a/Riot/Modules/CallTransfer/SelectContact/MatrixContactsDataSource.m +++ b/Riot/Modules/CallTransfer/SelectContact/MatrixContactsDataSource.m @@ -16,7 +16,7 @@ #import "MatrixContactsDataSource.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation MatrixContactsDataSource diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m index 9942f883f..82b5823b2 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.m @@ -26,7 +26,7 @@ #import "MXSession+Riot.h" #import "NSArray+Element.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #define RECENTSDATASOURCE_SECTION_DIRECTORY 0x01 #define RECENTSDATASOURCE_SECTION_INVITES 0x02 diff --git a/Riot/Modules/Common/Recents/Model/RecentCellData.m b/Riot/Modules/Common/Recents/Model/RecentCellData.m index be2d88d47..9697b85ea 100644 --- a/Riot/Modules/Common/Recents/Model/RecentCellData.m +++ b/Riot/Modules/Common/Recents/Model/RecentCellData.m @@ -20,11 +20,7 @@ #import "MXRoom+Riot.h" #import "MatrixSDK-Swift.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @implementation RecentCellData diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index f47f08a9d..3964ae1c7 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -32,7 +32,7 @@ #import "DirectoryRecentTableViewCell.h" #import "RoomIdOrAliasTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" NSString *const RecentsViewControllerDataReadyNotification = @"RecentsViewControllerDataReadyNotification"; diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m index 0d540399b..6b2df4055 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.m @@ -23,7 +23,7 @@ #import "MXRoom+Riot.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoomSummary+Riot.h" diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m index 8480205af..2b17874d8 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.m @@ -19,11 +19,7 @@ #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @interface SegmentedViewController () { diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.m b/Riot/Modules/Common/WebViewController/WebViewViewController.m index afb11bc6f..4826219ec 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.m +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.m @@ -15,7 +15,7 @@ */ #import "WebViewViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface WebViewViewController () { diff --git a/Riot/Modules/Communities/DataSources/GroupsDataSource.m b/Riot/Modules/Communities/DataSources/GroupsDataSource.m index 68aa32588..69b0100f5 100644 --- a/Riot/Modules/Communities/DataSources/GroupsDataSource.m +++ b/Riot/Modules/Communities/DataSources/GroupsDataSource.m @@ -15,7 +15,7 @@ */ #import "GroupsDataSource.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface GroupsDataSource() diff --git a/Riot/Modules/Communities/GroupsViewController.m b/Riot/Modules/Communities/GroupsViewController.m index 916c344ee..23cc6a6d4 100644 --- a/Riot/Modules/Communities/GroupsViewController.m +++ b/Riot/Modules/Communities/GroupsViewController.m @@ -19,7 +19,7 @@ #import "GroupTableViewCell.h" #import "GroupInviteTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface GroupsViewController () { diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 5fbfbf82e..42825da70 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -17,7 +17,7 @@ #import "GroupHomeViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "ThemeService.h" #import "Tools.h" diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m index f46a9cf72..7be31d255 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.m +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.m @@ -16,7 +16,7 @@ #import "GroupParticipantsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "Contact.h" #import "ContactTableViewCell.h" diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m index 019d34c6d..cabf6cdde 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.m @@ -16,7 +16,7 @@ #import "GroupRoomsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "GroupRoomTableViewCell.h" diff --git a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m index 0f11758c8..80d84a128 100644 --- a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m +++ b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.m @@ -20,7 +20,7 @@ #import "AvatarGenerator.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation GroupRoomTableViewCell diff --git a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m index c36120cc4..28e7e64de 100644 --- a/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m +++ b/Riot/Modules/Communities/TabDetail/GroupDetailsViewController.m @@ -20,7 +20,7 @@ #import "GroupParticipantsViewController.h" #import "GroupRoomsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface GroupDetailsViewController () { diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m index cd3c635cc..87b965266 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.m @@ -17,7 +17,7 @@ #import "GroupInviteTableViewCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #pragma mark - Constant definitions diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.m b/Riot/Modules/Communities/Views/GroupTableViewCell.m index 313b01ac2..029a8cb0e 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.m +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.m @@ -17,7 +17,7 @@ #import "GroupTableViewCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXGroup+Riot.h" diff --git a/Riot/Modules/Contacts/ContactsTableViewController.m b/Riot/Modules/Contacts/ContactsTableViewController.m index adbc1f9e9..4cd487068 100644 --- a/Riot/Modules/Contacts/ContactsTableViewController.m +++ b/Riot/Modules/Contacts/ContactsTableViewController.m @@ -20,7 +20,7 @@ #import "UIViewController+RiotSearch.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #define CONTACTS_TABLEVC_LOCALCONTACTS_BITWISE 0x01 #define CONTACTS_TABLEVC_USERDIRECTORY_BITWISE 0x02 diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m index 15d0b6238..c7d1692bd 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.m +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.m @@ -21,7 +21,7 @@ #import "LocalContactsSectionHeaderContainerView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #define CONTACTSDATASOURCE_LOCALCONTACTS_BITWISE 0x01 #define CONTACTSDATASOURCE_USERDIRECTORY_BITWISE 0x02 diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m index e26c94ab1..4226a8e89 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.m +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.m @@ -18,7 +18,7 @@ #import "ContactDetailsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXSession+Riot.h" #import "RoomMemberTitleView.h" diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m index cf6fcaee2..22036093c 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.m @@ -18,7 +18,7 @@ #import "RoomTableViewCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoomSummary+Riot.h" diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index 0a79aba0d..c07d2f33e 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -20,7 +20,7 @@ #import #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "AvatarGenerator.h" #import "Tools.h" diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m index a8a91125f..da56f1b66 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.m +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.m @@ -18,7 +18,7 @@ #import "EncryptionInfoView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface EncryptionInfoView() { diff --git a/Riot/Modules/Favorites/FavouritesViewController.m b/Riot/Modules/Favorites/FavouritesViewController.m index 2d2eca941..12f129d68 100644 --- a/Riot/Modules/Favorites/FavouritesViewController.m +++ b/Riot/Modules/Favorites/FavouritesViewController.m @@ -17,7 +17,7 @@ #import "FavouritesViewController.h" #import "RecentsDataSource.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface FavouritesViewController () { diff --git a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m index 1a4605ba6..59d169d7f 100644 --- a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m +++ b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.m @@ -22,7 +22,7 @@ #import "DirectoryRecentTableViewCell.h" #import "MXRoom+Riot.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface UnifiedSearchRecentsDataSource() { diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m index 05043e47b..63035f726 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.m @@ -17,7 +17,7 @@ #import "HomeFilesSearchViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "HomeViewController.h" diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m index 4dfbe686f..e2633d41c 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.m @@ -19,7 +19,7 @@ #import "FilesSearchTableViewCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation FilesSearchTableViewCell @synthesize delegate, mxkCellData; diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 4c69eab0f..8a60808cf 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -23,7 +23,7 @@ #import "RoomBubbleCellData.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m index 1050bbd1b..00fd9d20d 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.m @@ -17,7 +17,7 @@ #import "HomeMessagesSearchViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "HomeViewController.h" diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m index 1e1fc3e4b..074013b5b 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.m @@ -18,7 +18,7 @@ #import "MessagesSearchResultAttachmentBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation MessagesSearchResultAttachmentBubbleCell diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m index 3a29ef6b1..40818f8a0 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.m @@ -18,7 +18,7 @@ #import "MessagesSearchResultTextMsgBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation MessagesSearchResultTextMsgBubbleCell diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m index 2f6e791d7..0c0e26622 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.m @@ -19,7 +19,7 @@ #import "PublicRoomsDirectoryDataSource.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface DirectoryViewController () { diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m index 03375e8b9..bd0a07b3f 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.m @@ -31,7 +31,7 @@ #import "HomeFilesSearchViewController.h" #import "FilesSearchCellData.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "GBDeviceInfo_iOS.h" diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m index 9a168d3f7..1042d8265 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.m @@ -20,7 +20,7 @@ #import "PublicRoomsDirectoryDataSource.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation DirectoryRecentTableViewCell diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m index 44f788e91..0a798aefc 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.m @@ -19,7 +19,7 @@ #import "AvatarGenerator.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomIdOrAliasTableViewCell diff --git a/Riot/Modules/Home/Fallback/AuthFallBackViewController.m b/Riot/Modules/Home/Fallback/AuthFallBackViewController.m index 65084f110..93a770610 100644 --- a/Riot/Modules/Home/Fallback/AuthFallBackViewController.m +++ b/Riot/Modules/Home/Fallback/AuthFallBackViewController.m @@ -15,7 +15,7 @@ */ #import "AuthFallBackViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" // Generic method to make a bridge between JS and the WKWebView NSString *FallBackViewControllerJavascriptSendObjectMessage = @"window.sendObjectMessage = function(parameters) { \ diff --git a/Riot/Modules/Home/HomeViewController.m b/Riot/Modules/Home/HomeViewController.m index 411add2bb..0f7f5234b 100644 --- a/Riot/Modules/Home/HomeViewController.m +++ b/Riot/Modules/Home/HomeViewController.m @@ -17,7 +17,7 @@ #import "HomeViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RecentsDataSource.h" diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.m b/Riot/Modules/Home/Views/RoomCollectionViewCell.m index a030b9a6f..f13d7bc3b 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.m +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.m @@ -19,7 +19,7 @@ #import "AvatarGenerator.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoomSummary+Riot.h" #import "MXRoom+Riot.h" diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m index cae76808a..4da67b857 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.m @@ -16,7 +16,7 @@ #import "TableViewCellWithCollectionView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" static CGFloat const kEditionViewCornerRadius = 10.0; diff --git a/Riot/Modules/Integrations/IntegrationManagerViewController.m b/Riot/Modules/Integrations/IntegrationManagerViewController.m index 7ba021062..56dead207 100644 --- a/Riot/Modules/Integrations/IntegrationManagerViewController.m +++ b/Riot/Modules/Integrations/IntegrationManagerViewController.m @@ -19,7 +19,7 @@ #import "WidgetManager.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" NSString *const kIntegrationManagerMainScreen = nil; NSString *const kIntegrationManagerAddIntegrationScreen = @"add_integ"; diff --git a/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m b/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m index d3cb31902..74e8f2f22 100644 --- a/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m +++ b/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.m @@ -19,7 +19,7 @@ #import "WidgetManager.h" #import "WidgetViewController.h" #import "IntegrationManagerViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface WidgetPickerViewController () { diff --git a/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m b/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m index cbaceeed8..c8fa03fdd 100644 --- a/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m +++ b/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.m @@ -16,7 +16,7 @@ #import "JitsiViewController.h" #import "JitsiWidgetData.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #if __has_include() @import JitsiMeetSDK; diff --git a/Riot/Modules/Integrations/Widgets/StickerPicker/StickerPickerViewController.m b/Riot/Modules/Integrations/Widgets/StickerPicker/StickerPickerViewController.m index d56aeef6d..d665a06d0 100644 --- a/Riot/Modules/Integrations/Widgets/StickerPicker/StickerPickerViewController.m +++ b/Riot/Modules/Integrations/Widgets/StickerPicker/StickerPickerViewController.m @@ -18,7 +18,7 @@ #import "IntegrationManagerViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface StickerPickerViewController () diff --git a/Riot/Modules/Integrations/Widgets/WidgetViewController.m b/Riot/Modules/Integrations/Widgets/WidgetViewController.m index 6d04db4c0..a5e93b152 100644 --- a/Riot/Modules/Integrations/Widgets/WidgetViewController.m +++ b/Riot/Modules/Integrations/Widgets/WidgetViewController.m @@ -18,7 +18,7 @@ #import "WidgetViewController.h" #import "IntegrationManagerViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" NSString *const kJavascriptSendResponseToPostMessageAPI = @"riotIOS.sendResponse('%@', %@);"; diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m index fc3755331..b87015e59 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.m @@ -19,7 +19,7 @@ #import -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface MediaAlbumContentViewController () { diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index bd38cd2a8..69a183a2c 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -17,7 +17,7 @@ #import "MediaPickerViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import diff --git a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m index 2f2f1e40a..0ca5d5f38 100644 --- a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m +++ b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.m @@ -18,7 +18,7 @@ #import "MediaAlbumTableCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation MediaAlbumTableCell diff --git a/Riot/Modules/People/PeopleViewController.m b/Riot/Modules/People/PeopleViewController.m index ed9aaca76..93157578f 100644 --- a/Riot/Modules/People/PeopleViewController.m +++ b/Riot/Modules/People/PeopleViewController.m @@ -24,7 +24,7 @@ #import "RecentTableViewCell.h" #import "InviteRecentTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface PeopleViewController () { diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.m b/Riot/Modules/People/Views/InviteRecentTableViewCell.m index 738c8cb4a..d0ab6a9e3 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.m +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.m @@ -22,7 +22,7 @@ #import "MXEvent.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #pragma mark - Constant definitions diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m index db260be11..de80ee7b8 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.m @@ -19,7 +19,7 @@ #import "PublicRoomTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #pragma mark - Constants definitions diff --git a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m index 4195b241b..b6b65a2d4 100644 --- a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m +++ b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.m @@ -21,7 +21,7 @@ #import "AvatarGenerator.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation PublicRoomTableViewCell diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.m b/Riot/Modules/Room/Attachements/AttachmentsViewController.m index caeec8984..596c6a3b5 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.m +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.m @@ -17,7 +17,7 @@ #import "AttachmentsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface AttachmentsViewController () { diff --git a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m index 21caa32e5..a2c40fd6d 100644 --- a/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m +++ b/Riot/Modules/Room/BubbleReactions/BubbleReactionsViewSizer.m @@ -17,7 +17,7 @@ limitations under the License. #import "BubbleReactionsViewSizer.h" #import -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation BubbleReactionsViewSizer diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index a71e6d72e..697d67178 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -23,7 +23,7 @@ #import "Tools.h" #import "BubbleReactionsViewSizer.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import static NSAttributedString *timestampVerticalWhitespace = nil; diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.m b/Riot/Modules/Room/DataSources/RoomDataSource.m index 9817f503d..85dd4d7e1 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.m +++ b/Riot/Modules/Room/DataSources/RoomDataSource.m @@ -23,7 +23,7 @@ #import "MXKRoomBubbleTableViewCell+Riot.h" #import "AvatarGenerator.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoom+Riot.h" diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.m b/Riot/Modules/Room/Files/RoomFilesViewController.m index 5712ecffe..1e8e007c1 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.m +++ b/Riot/Modules/Room/Files/RoomFilesViewController.m @@ -19,7 +19,7 @@ #import "FilesSearchTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "AttachmentsViewController.h" diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m index aab1f1653..ca9339f55 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.m @@ -18,7 +18,7 @@ #import "RoomMemberDetailsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomMemberTitleView.h" diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 7858ab241..7a03da092 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -19,7 +19,7 @@ #import "RoomMemberDetailsViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "Contact.h" diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index d69f8f936..2bde90904 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -20,7 +20,7 @@ #import "RageShakeManager.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface ReadReceiptsViewController () { diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 5b4ad0c2b..679df272b 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -131,7 +131,7 @@ #import "MXSDKOptions.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" NSNotificationName const RoomCallTileTappedNotification = @"RoomCallTileTappedNotification"; NSNotificationName const RoomGroupCallTileTappedNotification = @"RoomGroupCallTileTappedNotification"; diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m index 3ff3145d6..f35ac5c7f 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.m @@ -20,7 +20,7 @@ #import "RoomBubbleCellData.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m index 78a7bfbf9..0e14b53ee 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.m @@ -24,7 +24,7 @@ #import "FilesSearchCellData.h" #import "FilesSearchTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface RoomFilesSearchViewController () { diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m index a674af70d..4e93f01d6 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.m @@ -26,7 +26,7 @@ #import "RoomIncomingAttachmentBubbleCell.h" #import "RoomIncomingTextMsgBubbleCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface RoomMessagesSearchViewController () { diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.m b/Riot/Modules/Room/Search/RoomSearchViewController.m index b6a17df46..a6cd8eeb7 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.m +++ b/Riot/Modules/Room/Search/RoomSearchViewController.m @@ -22,7 +22,7 @@ #import "RoomFilesSearchViewController.h" #import "FilesSearchCellData.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface RoomSearchViewController () { diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.m b/Riot/Modules/Room/Settings/RoomSettingsViewController.m index bf1e96655..7ca017b57 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.m +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.m @@ -28,7 +28,7 @@ #import "MXRoom+Riot.h" #import "MXRoomSummary+Riot.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomMemberDetailsViewController.h" diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m index 088f72b19..b623ffc7d 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.m @@ -18,7 +18,7 @@ #import "TableViewCellWithCheckBoxAndLabel.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation TableViewCellWithCheckBoxAndLabel diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m index 0b588bbdc..9504214a1 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.m @@ -17,7 +17,7 @@ #import "TableViewCellWithCheckBoxes.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" // The space between 2 check boxes #define TABLEVIEWCELLWITHCHECKBOXES_MARGIN 8 diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m index deecdd99e..641aff31a 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.m @@ -18,7 +18,7 @@ #import "TableViewCellWithLabelAndLargeTextView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation TableViewCellWithLabelAndLargeTextView diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m index 6c272a6d9..cb15df862 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.m @@ -19,7 +19,7 @@ #import "RoomActivitiesView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreationCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomCreationCollapsedBubbleCell.m index ae52d67fb..c06b34016 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomCreationCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomCreationCollapsedBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomCreationCollapsedBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomCreationWithPaginationCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomCreationWithPaginationCollapsedBubbleCell.m index c568691b7..7f2a00c48 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomCreationWithPaginationCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomCreationWithPaginationCollapsedBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomCreationWithPaginationCollapsedBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m index 2f7e4d80a..3dd06a1d8 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingAttachmentBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomIncomingAttachmentBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m index 16a614a46..2a7a96788 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingAttachmentWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomIncomingAttachmentWithPaginationTitleBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m index 5d63baf00..30b096e91 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.m @@ -19,7 +19,7 @@ #import "MXKRoomBubbleTableViewCell+Riot.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomIncomingAttachmentWithoutSenderInfoBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m index d308fcfea..28bbdb19c 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingTextMsgBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomIncomingTextMsgBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m index 2e8bdeb34..c66531dce 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingTextMsgWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomIncomingTextMsgWithPaginationTitleBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m index 5078a9405..ae4126049 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomIncomingTextMsgWithPaginationTitleWithoutSenderNameBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m index 56b0db94c..db4370dc5 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomIncomingTextMsgWithoutSenderInfoBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m index 15ab0389e..8678dd894 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderNameBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomIncomingTextMsgWithoutSenderNameBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomIncomingTextMsgWithoutSenderNameBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m index a15817d01..2fe69ff5f 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomMembershipBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m index c19773bf9..8302d4081 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomMembershipCollapsedBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m index b93c8be3a..1b78be112 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipCollapsedWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomMembershipCollapsedWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m index 56c0ca6c8..226528894 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomMembershipExpandedBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m index 63262f645..4378cd927 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipExpandedWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomMembershipExpandedWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m index 4ebebc70d..f7394c4a6 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomMembershipWithPaginationTitleBubbleCell.m @@ -17,7 +17,7 @@ #import "RoomMembershipWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m index e6417201b..456305e9c 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomOutgoingAttachmentBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomOutgoingAttachmentBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m index bd4df0000..d78362a65 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithPaginationTitleBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomOutgoingAttachmentWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomOutgoingAttachmentWithPaginationTitleBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m index 30a50ae2d..7021df5f6 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "RoomBubbleCellData.h" #import "MXKRoomBubbleTableViewCell+Riot.h" diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m index 374ed6da0..a31a52029 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomOutgoingTextMsgBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXKRoomBubbleTableViewCell+Riot.h" @implementation RoomOutgoingTextMsgBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m index 85d4afb55..4c0125e4e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithPaginationTitleBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomOutgoingTextMsgWithPaginationTitleBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomOutgoingTextMsgWithPaginationTitleBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m index 1e0ffeb61..0bc9f1de3 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomOutgoingTextMsgWithoutSenderInfoBubbleCell diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m index 9099d6815..0b852bc20 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.m @@ -18,7 +18,7 @@ #import "RoomPredecessorBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #pragma mark - Defines & Constants diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m index b1e6d9477..d5f48404a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m +++ b/Riot/Modules/Room/Views/BubbleCells/RoomSelectedStickerBubbleCell.m @@ -25,7 +25,7 @@ #import "RoomIncomingEncryptedAttachmentWithoutSenderInfoBubbleCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomSelectedStickerBubbleCell diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.m b/Riot/Modules/Room/Views/Event/EventDetailsView.m index 3f30e3987..bce9bf665 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.m +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.m @@ -17,7 +17,7 @@ #import "EventDetailsView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation EventDetailsView diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m index 3c10a800f..c3337e887 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.m @@ -17,7 +17,7 @@ #import "DisabledRoomInputToolbarView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation DisabledRoomInputToolbarView diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m index 06c509632..4afd41edd 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.m @@ -18,7 +18,7 @@ #import "RoomInputToolbarView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "GBDeviceInfo_iOS.h" diff --git a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m index f64f8fd6a..931d8437e 100644 --- a/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Expanded/ExpandedRoomTitleView.m @@ -18,7 +18,7 @@ #import "ExpandedRoomTitleView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoomSummary+Riot.h" diff --git a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m index c0948422b..81a128564 100644 --- a/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/Preview/PreviewRoomTitleView.m @@ -19,7 +19,7 @@ #import "PreviewRoomTitleView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoomSummary+Riot.h" diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.m b/Riot/Modules/Room/Views/Title/RoomTitleView.m index 6f7d38edf..a34543c28 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.m +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.m @@ -18,7 +18,7 @@ #import "RoomTitleView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation RoomTitleView diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m index f6141d9cf..a5bf789d6 100644 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.m @@ -16,7 +16,7 @@ #import "RoomKeyRequestViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface RoomKeyRequestViewController () { diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m index e31c5fb43..d04214673 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.m @@ -18,7 +18,7 @@ #import "DirectoryServerTableViewCell.h" #import "DirectoryServerDetailTableViewCell.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface DirectoryServerPickerViewController () { diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m index a43ee7b39..f604f7e6c 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerDetailTableViewCell.m @@ -17,7 +17,7 @@ #import "DirectoryServerDetailTableViewCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation DirectoryServerDetailTableViewCell diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m index 3c1ceeabe..fed334510 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.m @@ -19,7 +19,7 @@ #import "AvatarGenerator.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation DirectoryServerTableViewCell diff --git a/Riot/Modules/Rooms/RoomsViewController.m b/Riot/Modules/Rooms/RoomsViewController.m index 0fb4105eb..25ae25ce9 100644 --- a/Riot/Modules/Rooms/RoomsViewController.m +++ b/Riot/Modules/Rooms/RoomsViewController.m @@ -18,7 +18,7 @@ #import "RecentsDataSource.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface RoomsViewController () { diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m index 67b66479e..3e4b4297e 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.m @@ -17,7 +17,7 @@ #import "DeactivateAccountViewController.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #pragma mark - Defines & Constants diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.m b/Riot/Modules/Settings/Language/LanguagePickerViewController.m index b97da63e8..aac54c076 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.m +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.m @@ -16,7 +16,7 @@ #import "LanguagePickerViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface LanguagePickerViewController () { diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m index f34817db0..0ab2fe0d8 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.m @@ -16,7 +16,7 @@ #import "CountryPickerViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface CountryPickerViewController () { diff --git a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m index 930ab5899..49c49b087 100644 --- a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m +++ b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m @@ -24,7 +24,7 @@ #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" enum diff --git a/Riot/Modules/Settings/Security/SecurityViewController.m b/Riot/Modules/Settings/Security/SecurityViewController.m index fce6d5c9b..9feda8f59 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.m +++ b/Riot/Modules/Settings/Security/SecurityViewController.m @@ -26,7 +26,7 @@ #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" // Dev flag to have more options //#define CROSS_SIGNING_AND_BACKUP_DEV diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 0a5acf57c..c4f97b448 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -43,7 +43,7 @@ #import "GBDeviceInfo_iOS.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" NSString* const kSettingsViewControllerPhoneBookCountryCellId = @"kSettingsViewControllerPhoneBookCountryCellId"; diff --git a/Riot/Modules/Settings/Views/DeviceView.m b/Riot/Modules/Settings/Views/DeviceView.m index 7f1325990..dc8ed4578 100644 --- a/Riot/Modules/Settings/Views/DeviceView.m +++ b/Riot/Modules/Settings/Views/DeviceView.m @@ -18,7 +18,7 @@ #import "DeviceView.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation DeviceView diff --git a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m index 5c03e1fd3..4cfc489a3 100644 --- a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m +++ b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.m @@ -17,7 +17,7 @@ #import "TableViewCellWithPhoneNumberTextField.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "NBPhoneNumberUtil.h" diff --git a/Riot/Modules/StartChat/StartChatViewController.m b/Riot/Modules/StartChat/StartChatViewController.m index 3ee8985ec..18ef614dd 100644 --- a/Riot/Modules/StartChat/StartChatViewController.m +++ b/Riot/Modules/StartChat/StartChatViewController.m @@ -17,7 +17,7 @@ #import "StartChatViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXSession+Riot.h" @interface StartChatViewController () diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index 3cca72eb7..f1afa5821 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -27,7 +27,7 @@ #import "SettingsViewController.h" #import "SecurityViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface MasterTabBarController () { diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.m b/Riot/Modules/UserDevices/UsersDevicesViewController.m index 5d6a1f8eb..5f83b5bc5 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.m +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.m @@ -17,7 +17,7 @@ #import "UsersDevicesViewController.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @interface UsersDevicesViewController () { diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m index 6ac1a31fa..7fde39ca4 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.m @@ -18,7 +18,7 @@ #import "DeviceTableViewCell.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "MXRoom+Riot.h" diff --git a/Riot/Utils/AvatarGenerator.m b/Riot/Utils/AvatarGenerator.m index efbf42b59..3a08f8165 100644 --- a/Riot/Utils/AvatarGenerator.m +++ b/Riot/Utils/AvatarGenerator.m @@ -19,11 +19,7 @@ #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @implementation AvatarGenerator diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index 248850691..c7a11f1d0 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -18,7 +18,7 @@ #import "EventFormatter.h" #import "ThemeService.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" #import "WidgetManager.h" diff --git a/Riot/Utils/Tools.m b/Riot/Utils/Tools.m index 66fe38d0c..7cae95148 100644 --- a/Riot/Utils/Tools.m +++ b/Riot/Utils/Tools.m @@ -16,7 +16,7 @@ #import "Tools.h" -#import "Riot-Swift.h" +#import "GeneratedInterface-Swift.h" @implementation Tools diff --git a/RiotNSE/Common.xcconfig b/RiotNSE/Common.xcconfig index 5a9db3be7..7ef912fcc 100644 --- a/RiotNSE/Common.xcconfig +++ b/RiotNSE/Common.xcconfig @@ -29,3 +29,5 @@ CODE_SIGN_ENTITLEMENTS = RiotNSE/RiotNSE.entitlements SKIP_INSTALL = YES SWIFT_OBJC_BRIDGING_HEADER = $(SRCROOT)/$(PRODUCT_NAME)/SupportingFiles/RiotNSE-Bridging-Header.h + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/RiotShareExtension/Common.xcconfig b/RiotShareExtension/Common.xcconfig index bb52cb93c..f6e43035b 100644 --- a/RiotShareExtension/Common.xcconfig +++ b/RiotShareExtension/Common.xcconfig @@ -33,3 +33,5 @@ SKIP_INSTALL = YES SWIFT_OBJC_BRIDGING_HEADER = $(SRCROOT)/$(PRODUCT_NAME)/SupportingFiles/RiotShareExtension-Bridging-Header.h GCC_PREPROCESSOR_DEFINITIONS = $(inherited) IS_SHARE_EXTENSION=1 LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/RiotShareExtension/Shared/ShareManager.m b/RiotShareExtension/Shared/ShareManager.m index 5ca23a2b1..d749d82e0 100644 --- a/RiotShareExtension/Shared/ShareManager.m +++ b/RiotShareExtension/Shared/ShareManager.m @@ -24,11 +24,7 @@ #import "ShareViewController.h" #import "ShareDataSource.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" static const CGFloat kLargeImageSizeMaxDimension = 2048.0; static const CGSize kThumbnailSize = {800.0, 600.0}; diff --git a/RiotShareExtension/Shared/View/FallbackViewController.m b/RiotShareExtension/Shared/View/FallbackViewController.m index 57412f705..beafbca25 100644 --- a/RiotShareExtension/Shared/View/FallbackViewController.m +++ b/RiotShareExtension/Shared/View/FallbackViewController.m @@ -17,11 +17,7 @@ #import "FallbackViewController.h" #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @interface FallbackViewController () diff --git a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m index b6fc0d27c..fa1a2fbce 100644 --- a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m +++ b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m @@ -19,11 +19,7 @@ #import "MXRoomSummary+Riot.h" #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @interface RecentRoomTableViewCell () diff --git a/RiotShareExtension/Shared/View/RoomsListViewController.m b/RiotShareExtension/Shared/View/RoomsListViewController.m index 414e0364a..926b9c4b2 100644 --- a/RiotShareExtension/Shared/View/RoomsListViewController.m +++ b/RiotShareExtension/Shared/View/RoomsListViewController.m @@ -22,11 +22,7 @@ #import "RecentCellData.h" #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @interface RoomsListViewController () diff --git a/RiotShareExtension/Shared/View/ShareViewController.m b/RiotShareExtension/Shared/View/ShareViewController.m index cfe4f2a87..25dc09232 100644 --- a/RiotShareExtension/Shared/View/ShareViewController.m +++ b/RiotShareExtension/Shared/View/ShareViewController.m @@ -21,11 +21,7 @@ #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @interface ShareViewController () diff --git a/RiotShareExtension/Sources/ShareExtensionRootViewController.m b/RiotShareExtension/Sources/ShareExtensionRootViewController.m index aee019949..5b1a911af 100644 --- a/RiotShareExtension/Sources/ShareExtensionRootViewController.m +++ b/RiotShareExtension/Sources/ShareExtensionRootViewController.m @@ -18,11 +18,7 @@ #import "ShareManager.h" #import "ThemeService.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" @interface ShareExtensionRootViewController () diff --git a/RiotSwiftUI/Common.xcconfig b/RiotSwiftUI/Common.xcconfig index e7cb586cf..9c6902651 100644 --- a/RiotSwiftUI/Common.xcconfig +++ b/RiotSwiftUI/Common.xcconfig @@ -26,3 +26,5 @@ PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).riotswiftui INFOPLIST_FILE = RiotSwiftUI/Info.plist SKIP_INSTALL = YES + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/RiotTests/Debug.xcconfig b/RiotTests/Debug.xcconfig index be053c75b..6db535791 100644 --- a/RiotTests/Debug.xcconfig +++ b/RiotTests/Debug.xcconfig @@ -18,3 +18,5 @@ // https://help.apple.com/xcode/#/dev745c5c974 #include "Pods/Target Support Files/Pods-RiotTests/Pods-RiotTests.debug.xcconfig" + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/RiotTests/Release.xcconfig b/RiotTests/Release.xcconfig index 5a62ed9cd..f9e061251 100644 --- a/RiotTests/Release.xcconfig +++ b/RiotTests/Release.xcconfig @@ -18,3 +18,5 @@ // https://help.apple.com/xcode/#/dev745c5c974 #include "Pods/Target Support Files/Pods-RiotTests/Pods-RiotTests.release.xcconfig" + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/SiriIntents/Common.xcconfig b/SiriIntents/Common.xcconfig index 957ae3881..f112dcf97 100644 --- a/SiriIntents/Common.xcconfig +++ b/SiriIntents/Common.xcconfig @@ -20,7 +20,7 @@ #include "Config/AppIdentifiers.xcconfig" #include "Config/AppVersion.xcconfig" -PRODUCT_NAME= SiriIntents +PRODUCT_NAME = SiriIntents PRODUCT_BUNDLE_IDENTIFIER = $(BASE_BUNDLE_IDENTIFIER).SiriIntents INFOPLIST_FILE = SiriIntents/Info.plist @@ -29,3 +29,5 @@ CODE_SIGN_ENTITLEMENTS = SiriIntents/SiriIntents.entitlements LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks SKIP_INSTALL = YES + +SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/SiriIntents/IntentHandler.m b/SiriIntents/IntentHandler.m index c55a5357e..9161e7926 100644 --- a/SiriIntents/IntentHandler.m +++ b/SiriIntents/IntentHandler.m @@ -18,7 +18,7 @@ #import -#import "SiriIntents-Swift.h" +#import "GeneratedInterface-Swift.h" #if __has_include() #define CALL_STACK_JINGLE From 09012c7c7957bd62d6912ea766ec26a041c75358 Mon Sep 17 00:00:00 2001 From: libexus Date: Mon, 25 Oct 2021 17:29:39 +0000 Subject: [PATCH 008/122] Translated using Weblate (German) Currently translated at 100.0% (6 of 6 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/de/ --- Riot/Assets/de.lproj/InfoPlist.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/de.lproj/InfoPlist.strings b/Riot/Assets/de.lproj/InfoPlist.strings index d5f41184b..571d56f44 100644 --- a/Riot/Assets/de.lproj/InfoPlist.strings +++ b/Riot/Assets/de.lproj/InfoPlist.strings @@ -2,6 +2,6 @@ "NSCameraUsageDescription" = "Die Kamera wird verwendet, um Fotos und Videos aufzunehmen sowie Videoanrufe durchzuführen."; "NSPhotoLibraryUsageDescription" = "Die Fotobibliothek wird verwendet, um Fotos und Videos zu versenden."; "NSMicrophoneUsageDescription" = "Element benötigt Zugriff auf das Mikrofon um Anrufe zu tätigen und Videos oder Sprachnachrichten aufzunehmen."; -"NSContactsUsageDescription" = "Element kann E-Mail-Adressen und Telefonnummern aus deinem Adressbuch zu deinem Matrix-Identitätsserver schicken, um Kontakte zu finden, die bereits Matrix verwenden. Wenn verfügbar, werden persönliche Daten vor dem Versand gehasht. Für weitere Informationen schaue bitte in die Datenschutzerklärung deines Identitätsservers."; +"NSContactsUsageDescription" = "Element zeigt deine Kontakte an, damit du sie zum chatten einladen kannst."; "NSCalendarsUsageDescription" = "Sieh dir deine geplanten Meetings in der App an."; "NSFaceIDUsageDescription" = "Face-ID wird zum Zugriff auf deine App verwendet."; From 6cc944f7e13f2a6aa53b119856a36074765be9ef Mon Sep 17 00:00:00 2001 From: Philippe Loriaux Date: Wed, 27 Oct 2021 09:20:47 +0200 Subject: [PATCH 009/122] Update changelog --- changelog.d/4722.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/4722.misc diff --git a/changelog.d/4722.misc b/changelog.d/4722.misc new file mode 100644 index 000000000..c1725155c --- /dev/null +++ b/changelog.d/4722.misc @@ -0,0 +1 @@ +Improve the Obj-C Generated Interface Header Name definition \ No newline at end of file From 0dbb1d1e12d07a577d0e329cba18c7ad3df18d93 Mon Sep 17 00:00:00 2001 From: Gil Eluard Date: Wed, 27 Oct 2021 10:27:13 +0200 Subject: [PATCH 010/122] Support pagination in the Space Summary API - Update after review --- ...dLoadingViewCell.swift => PaginationLoadingViewCell.swift} | 2 +- ...ChildLoadingViewCell.xib => PaginationLoadingViewCell.xib} | 2 +- .../ExploreRoom/SpaceExploreRoomViewController.swift | 4 ++-- .../SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) rename Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/{SpaceChildLoadingViewCell.swift => PaginationLoadingViewCell.swift} (93%) rename Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/{SpaceChildLoadingViewCell.xib => PaginationLoadingViewCell.xib} (97%) diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/PaginationLoadingViewCell.swift similarity index 93% rename from Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift rename to Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/PaginationLoadingViewCell.swift index 873241572..94917b973 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/PaginationLoadingViewCell.swift @@ -17,7 +17,7 @@ import UIKit import Reusable -class SpaceChildLoadingViewCell: UITableViewCell, NibReusable, Themable { +class PaginationLoadingViewCell: UITableViewCell, NibReusable, Themable { // MARK: - Properties diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/PaginationLoadingViewCell.xib similarity index 97% rename from Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib rename to Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/PaginationLoadingViewCell.xib index a49cc20a8..28533154f 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceChildLoadingViewCell.xib +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/PaginationLoadingViewCell.xib @@ -10,7 +10,7 @@ - + diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift index 28a64b161..fc04d7473 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewController.swift @@ -169,7 +169,7 @@ final class SpaceExploreRoomViewController: UIViewController { self.tableView.allowsSelection = true self.tableView.register(cellType: SpaceChildViewCell.self) self.tableView.register(cellType: SpaceChildSpaceViewCell.self) - self.tableView.register(cellType: SpaceChildLoadingViewCell.self) + self.tableView.register(cellType: PaginationLoadingViewCell.self) self.tableView.tableFooterView = UIView() } @@ -248,7 +248,7 @@ extension SpaceExploreRoomViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard indexPath.row < self.itemDataList.count else { - let cell = tableView.dequeueReusableCell(for: indexPath, cellType: SpaceChildLoadingViewCell.self) + let cell = tableView.dequeueReusableCell(for: indexPath, cellType: PaginationLoadingViewCell.self) cell.update(theme: self.theme) return cell } diff --git a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift index 171e8084e..c9f54491c 100644 --- a/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift +++ b/Riot/Modules/Spaces/SpaceRoomList/ExploreRoom/SpaceExploreRoomViewModel.swift @@ -104,7 +104,7 @@ final class SpaceExploreRoomViewModel: SpaceExploreRoomViewModelType { self.update(viewState: .loading) } - self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, from: self.nextBatch, completion: { [weak self] response in + self.currentOperation = self.session.spaceService.getSpaceChildrenForSpace(withId: self.spaceId, suggestedOnly: false, limit: nil, maxDepth: 1, paginationToken: self.nextBatch, completion: { [weak self] response in guard let self = self else { return } From 276f5e0458e4af067d82498a3c45c909ed8bf8ff Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 29 Oct 2021 11:07:22 +0100 Subject: [PATCH 011/122] Add clientPermalinkBaseUrl and set in matrix-sdk options. --- Config/BuildSettings.swift | 6 ++++++ Config/CommonConfiguration.swift | 1 + 2 files changed, 7 insertions(+) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index bb1b25a0a..4daf809ad 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -133,8 +133,14 @@ final class BuildSettings: NSObject { // Official Matrix ones "matrix.to": ["/"], "www.matrix.to": ["/"], + // Client Permalinks (for use with `BuildSettings.clientPermalinkBaseUrl`) +// "clienturl.com": ["/"], +// "www.clienturl.com": ["/"], ] + // For use in clients that use a custom base url for permalinks rather than matrix.to. + // This baseURL is used to generate permalinks within the app (E.g. timeline message permalinks). + static let clientPermalinkBaseUrl: String? = nil // MARK: - VoIP static var allowVoIPUsage: Bool { diff --git a/Config/CommonConfiguration.swift b/Config/CommonConfiguration.swift index b6aa77dad..f2e4b68dc 100644 --- a/Config/CommonConfiguration.swift +++ b/Config/CommonConfiguration.swift @@ -75,6 +75,7 @@ class CommonConfiguration: NSObject, Configurable { // Disable key backup on common sdkOptions.enableKeyBackupWhenStartingMXCrypto = false + sdkOptions.clientPermalinkBaseUrl = BuildSettings.clientPermalinkBaseUrl // Configure key provider delegate MXKeyProvider.sharedInstance().delegate = EncryptionKeyManager.shared } From bd0f59a03d8c2fea0fe8b7569ae2bce3bab7517b Mon Sep 17 00:00:00 2001 From: Szimszon Date: Thu, 21 Oct 2021 18:35:06 +0000 Subject: [PATCH 012/122] Translated using Weblate (Hungarian) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/hu/ --- Riot/Assets/hu.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/hu.lproj/Vector.strings b/Riot/Assets/hu.lproj/Vector.strings index ed2f5b3a5..605aa6f70 100644 --- a/Riot/Assets/hu.lproj/Vector.strings +++ b/Riot/Assets/hu.lproj/Vector.strings @@ -1530,3 +1530,5 @@ "find_your_contacts_footer" = "Bármikor letiltható a beállításokban."; "contacts_address_book_permission_denied_alert_message" = "A névjegyzék engedélyezéséhez lépj be az eszköz beállításokba."; "contacts_address_book_permission_denied_alert_title" = "Névjegyzék letiltva"; +"space_home_show_all_rooms" = "Minden szoba megjelenítése"; +"room_event_action_forward" = "Továbbítás"; From 6224e64b6171e383d09d2e6b0cfc37974cbb8871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Priit=20J=C3=B5er=C3=BC=C3=BCt?= Date: Wed, 20 Oct 2021 15:52:35 +0000 Subject: [PATCH 013/122] Translated using Weblate (Estonian) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/et/ --- Riot/Assets/et.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/et.lproj/Vector.strings b/Riot/Assets/et.lproj/Vector.strings index e33a6047c..0c73787d9 100644 --- a/Riot/Assets/et.lproj/Vector.strings +++ b/Riot/Assets/et.lproj/Vector.strings @@ -1467,3 +1467,5 @@ "find_your_contacts_title" = "Alusta kontaktide looendist"; "contacts_address_book_permission_denied_alert_message" = "Palun luba seadistustest aadressiraamatu lugemine."; "contacts_address_book_permission_denied_alert_title" = "Kontaktid pole kasutusel"; +"space_home_show_all_rooms" = "Näita kõiki jututubasid"; +"room_event_action_forward" = "Edasta"; From 1e547fed76adbb58a9ddb3b8669796e850043a7f Mon Sep 17 00:00:00 2001 From: libexus Date: Wed, 27 Oct 2021 19:35:01 +0000 Subject: [PATCH 014/122] Translated using Weblate (German) Currently translated at 99.5% (1324 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/de/ --- Riot/Assets/de.lproj/Vector.strings | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/de.lproj/Vector.strings b/Riot/Assets/de.lproj/Vector.strings index 7dd14568c..63ea02f51 100644 --- a/Riot/Assets/de.lproj/Vector.strings +++ b/Riot/Assets/de.lproj/Vector.strings @@ -286,7 +286,7 @@ "auth_reset_password_success_message" = "Dein Passwort wurde zurückgesetzt.\n\nDu wurdest aus allen Sitzungen abgemeldet, diese bekommen jetzt keine Push-Benachrichtigungen mehr. Um diese wieder einzuschalten, melde dich auf den Geräten erneut an."; "auth_add_email_and_phone_warning" = "Registrierung mit E-Mail und Telefonnummer zugleich ist noch nicht unterstützt. Nur die Telefonnummer wird berücksichtigt. Du kannst deine E-Mail-Adresse in deinem Profil ergänzen."; "room_creation_make_public_prompt_msg" = "Sicher, dass du diesen Raum öffentlich machen willst? Jeder kann deine Nachrichten lesen und dem Raum beitreten."; -"room_creation_invite_another_user" = "Suchen/Einladen mittels Benutzer-ID, Name oder E-Mail-Adresse"; +"room_creation_invite_another_user" = "Benutzer-ID, Name oder E-Mail"; "room_recents_join_room_prompt" = "Gib eine Raum-ID oder einem Raum-Alias an"; "directory_cell_description" = "%tu Räume"; "directory_search_results" = "%tu Treffer gefunden für %@"; @@ -835,7 +835,7 @@ "settings_calls_stun_server_fallback_button" = "Ausweich-Anruf-Assistenz-Server zulassen"; "settings_devices_description" = "Der öffentliche Name der Sitzung ist für Personen sichtbar, mit denen du kommunizierst"; "settings_discovery_no_identity_server" = "Du verwendest derzeit keinen Identitätsserver. Füge einen hinzu, um für vorhandene, dir bekannte Kontakte sichtbar zu sein."; -"settings_discovery_terms_not_signed" = "Stimme den Nutzungsbedingungen des Identitätsservers (%@) zu, um zu erlauben per E-Mail oder Telefonnummer gefunden zu werden."; +"settings_discovery_terms_not_signed" = "Stimme den Nutzungsbedingungen des Identitätsservers (%@) zu, um per E-Mail oder Telefonnummer gefunden zu werden."; "settings_discovery_three_pids_management_information_part1" = "Verwalte, welche E-Mail-Adressen oder Telefonnummern andere Benutzer verwenden können, um dich zu entdecken und dich in Räume einzuladen. Füge in dieser Liste E-Mail-Adressen oder Telefonnummern hinzu oder entferne sie "; "settings_discovery_three_pids_management_information_part2" = "Nutzereinstellungen"; "settings_discovery_three_pids_management_information_part3" = "."; @@ -910,7 +910,7 @@ "room_participants_security_loading" = "Lade…"; "room_participants_security_information_room_not_encrypted" = "Nachrichten in diesem Raum sind nicht Ende-zu-Ende verschlüsselt."; "settings_security" = "SICHERHEIT"; -"settings_integrations_allow_description" = "Benutze einen Integrationsverwalter (%@), um Bots, Bridges, Widgets und Aufkleberpakete zu verwalten.\n\nIntegrationsverwalter erhalten Konfigurationsdaten und können Widgets verändern, Raum-Einladungen versenden sowie Berechtigungen in deinem Namen einstellen."; +"settings_integrations_allow_description" = "Benutze einen Integrationsmanager (%@), um Bots, Bridges, Widgets und Aufkleberpakete zu verwalten.\n\nIntegrationsmanager erhalten Konfigurationsdaten und können Widgets verändern, Raum-Einladungen versenden sowie Berechtigungen in deinem Namen einstellen."; "settings_labs_enable_cross_signing" = "Aktiviere Cross-Signing, um deinen Gesprächspartner anstatt dessen Gerät zu verifizieren (in Entwicklung)"; // Security settings "security_settings_title" = "Sicherheit"; @@ -1484,3 +1484,26 @@ "open" = "Öffnen"; "settings_links" = "LINKS"; "find_your_contacts_footer" = "Dies kann jederzeit in den Einstellungen deaktiviert werden."; +"settings_contacts_enable_sync" = "Finde deine Kontakte"; +"space_home_show_all_rooms" = "Alle Räume anzeigen"; +"service_terms_modal_information_description_integration_manager" = "Ein Integrationsmanager erlaubt dir, externe Funktionen hinzuzufügen."; +"service_terms_modal_information_description_identity_server" = "Der Identitätsserver sucht anhand der Telefonnummern und E-Mails in deinen Kontakten, ob diese einen Matrix-Account haben."; +"service_terms_modal_information_title_integration_manager" = "Integrationsmanager"; + +// Alert explaining what an identity server / integration manager is. +"service_terms_modal_information_title_identity_server" = "Indentitätsserver"; +"service_terms_modal_description_integration_manager" = "Das erlaubt dir Bots, Bridges und Stickerpacks zu verwenden."; +"service_terms_modal_description_identity_server" = "Dies erlaubt Personen, die deine Telefonnummer oder E-Mail in ihren Kontakten hat, dich zu finden."; +"service_terms_modal_table_header_identity_server" = "NUTZUNGSBEDINGUNGEN IDENTITÄTSSERVER"; +"service_terms_modal_table_header_integration_manager" = "NUTZUNGSBEDINGUNGEN INTEGRATIONSMANAGER"; +"service_terms_modal_footer" = "Dies kann jederzeit in den Einstellungen deaktiviert werden."; + +// Service terms +"service_terms_modal_title_message" = "Zum Fortfahren musst du die Nutzungsbedingungen akzeptieren"; +"settings_contacts_enable_sync_description" = "Dies verwendet deinen Identitätsserver um dich mit deinen Kontakten zu verbinden."; +"settings_phone_contacts" = "KONTAKTE AM HANDY"; +"room_event_action_forward" = "Weiter"; +"find_your_contacts_identity_service_error" = "Konnte keine Verbindung zum Identitätsserver aufbauen."; +"find_your_contacts_button_title" = "Finde deine Kontakte"; +"contacts_address_book_permission_denied_alert_message" = "Um Kontakte zu aktivieren, öffne die Einstellungen deines Gerätes."; +"contacts_address_book_permission_denied_alert_title" = "Kontakte deaktiviert"; From 6067bb639f7243d504bcf57693e5bae65ac961e6 Mon Sep 17 00:00:00 2001 From: lvre <7uu3qrbvm@relay.firefox.com> Date: Wed, 20 Oct 2021 16:09:16 +0000 Subject: [PATCH 015/122] Translated using Weblate (Portuguese (Brazil)) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/pt_BR/ --- Riot/Assets/pt_BR.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/pt_BR.lproj/Vector.strings b/Riot/Assets/pt_BR.lproj/Vector.strings index 77ab52883..0c64d526a 100644 --- a/Riot/Assets/pt_BR.lproj/Vector.strings +++ b/Riot/Assets/pt_BR.lproj/Vector.strings @@ -1498,3 +1498,5 @@ "find_your_contacts_title" = "Comece por listar seus contatos"; "contacts_address_book_permission_denied_alert_message" = "Para habilitar contatos, vá para as configurações de seu dispositivo."; "contacts_address_book_permission_denied_alert_title" = "Contatos desabilitados"; +"space_home_show_all_rooms" = "Mostrar todas as salas"; +"room_event_action_forward" = "Encaminhar"; From 59dbeab3fd837b144915e7f9bd3acc0331c42f07 Mon Sep 17 00:00:00 2001 From: Besnik Bleta Date: Thu, 21 Oct 2021 07:51:50 +0000 Subject: [PATCH 016/122] Translated using Weblate (Albanian) Currently translated at 99.5% (1324 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sq/ --- Riot/Assets/sq.lproj/Vector.strings | 1 + 1 file changed, 1 insertion(+) diff --git a/Riot/Assets/sq.lproj/Vector.strings b/Riot/Assets/sq.lproj/Vector.strings index 221b56ec4..75f1fc60e 100644 --- a/Riot/Assets/sq.lproj/Vector.strings +++ b/Riot/Assets/sq.lproj/Vector.strings @@ -1518,3 +1518,4 @@ "find_your_contacts_title" = "Fillojani duke shfaqur kontaktet tuaja"; "contacts_address_book_permission_denied_alert_message" = "Që të aktivizoni kontakte, kaloni te rregullimet e pajisjes tua."; "contacts_address_book_permission_denied_alert_title" = "Kontaktet u çaktivizuan"; +"space_home_show_all_rooms" = "Shfaqi krejt dhomat"; From ff4d1a0d5343b0fbcbbc2147394ef3e545e5f75e Mon Sep 17 00:00:00 2001 From: Nikita Epifanov Date: Wed, 27 Oct 2021 06:24:44 +0000 Subject: [PATCH 017/122] Translated using Weblate (Russian) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index ad004e9e0..98e41f479 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -1511,3 +1511,5 @@ "find_your_contacts_title" = "Начните с составления списка контактов"; "contacts_address_book_permission_denied_alert_message" = "Для включения контактов, перейдите в настройки устройства."; "contacts_address_book_permission_denied_alert_title" = "Контакты отключены"; +"space_home_show_all_rooms" = "Показать все комнаты"; +"room_event_action_forward" = "Переслать"; From d6f3a8024c0918db9a77f7cf82467d07635a3423 Mon Sep 17 00:00:00 2001 From: sr093906 Date: Thu, 21 Oct 2021 00:15:22 +0000 Subject: [PATCH 018/122] Translated using Weblate (Chinese (Simplified)) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/zh_Hans/ --- Riot/Assets/zh_Hans.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/zh_Hans.lproj/Vector.strings b/Riot/Assets/zh_Hans.lproj/Vector.strings index 12ee6b01a..07d29a933 100644 --- a/Riot/Assets/zh_Hans.lproj/Vector.strings +++ b/Riot/Assets/zh_Hans.lproj/Vector.strings @@ -1545,3 +1545,5 @@ "find_your_contacts_title" = "从列出你的联系人开始"; "contacts_address_book_permission_denied_alert_message" = "要启用联系人,请转到设备设置。"; "contacts_address_book_permission_denied_alert_title" = "联系人被禁用"; +"space_home_show_all_rooms" = "显示所有聊天室"; +"room_event_action_forward" = "转发"; From c853892f0d9d6ad87d03304d99375f9b344aacf5 Mon Sep 17 00:00:00 2001 From: Ihor Hordiichuk Date: Mon, 25 Oct 2021 13:56:50 +0000 Subject: [PATCH 019/122] Translated using Weblate (Ukrainian) Currently translated at 59.2% (788 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/uk/ --- Riot/Assets/uk.lproj/Vector.strings | 68 +++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) diff --git a/Riot/Assets/uk.lproj/Vector.strings b/Riot/Assets/uk.lproj/Vector.strings index a573557ce..8b88b65b4 100644 --- a/Riot/Assets/uk.lproj/Vector.strings +++ b/Riot/Assets/uk.lproj/Vector.strings @@ -895,3 +895,71 @@ "key_verification_manually_verify_device_validate_action" = "Звірити"; "room_participants_action_security_status_verify" = "Звірити"; "room_participants_action_security_status_verified" = "Звірений"; +"version_check_banner_title_deprecated" = "Ми більше не підтримуємо iOS %@"; +"version_check_modal_title_supported" = "Ми завершуємо підтримку iOS %@"; + +// Mark: - Version check + +"version_check_banner_title_supported" = "Ми завершуємо підтримку iOS %@"; +"space_public_join_rule" = "Загальнодоступний простір"; +"space_private_join_rule" = "Приватний простір"; +"space_home_show_all_rooms" = "Показати усі кімнати"; +"spaces_add_rooms_coming_soon_title" = "Скоро можна буде додавати кімнати"; +"spaces_coming_soon_title" = "Уже незабаром"; +"spaces_no_result_found_title" = "Результатів не знайдено"; +"spaces_empty_space_title" = "У просторі відсутні кімнати (поки що)"; +"space_tag" = "простір"; +"leave_space_title" = "Вийти з %@"; +"spaces_left_panel_title" = "Простори"; +"spaces_home_space_title" = "Домівка"; + +// Mark: - Spaces + +"space_feature_unavailable_title" = "Простори ще не додано"; +"room_info_list_section_other" = "Інше"; +"biometrics_cant_unlocked_alert_title" = "Не вдалося розблокувати застосунок"; +"pin_protection_settings_section_header_with_biometrics" = "PIN-код і %@"; +"pin_protection_settings_section_header" = "PIN-код"; +"major_update_learn_more_action" = "Докладніше"; + +// MARK: - Major update + +"major_update_title" = "Riot тепер %@"; +"secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Підтвердити фразу"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Підтвердити фразу"; +"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Підтвердити"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Підтвердити"; +"key_backup_setup_passphrase_passphrase_invalid" = "Спробуйте додати слово"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "фраза не збігається"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Чудово!"; +"key_backup_setup_passphrase_passphrase_valid" = "Чудово!"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Ввести фразу"; +"secrets_recovery_with_key_recovery_key_title" = "Ввід"; +"key_backup_recover_from_passphrase_recover_action" = "Розблокувати історію"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Ввести фразу"; +"key_backup_recover_from_passphrase_passphrase_title" = "Ввід"; +"secrets_recovery_with_passphrase_passphrase_title" = "Ввід"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Ввід"; +"key_backup_setup_passphrase_passphrase_title" = "Ввід"; +"key_backup_setup_skip_alert_title" = "Ви впевнені?"; +"room_event_action_reaction_history" = "Історія реакцій"; +"room_event_action_reaction_show_less" = "Згорнути"; +"room_event_action_reaction_show_all" = "Показати все"; +"room_action_reply" = "Відповідь"; +"room_event_action_reply" = "Відповідь"; +"room_event_action_delete_confirmation_title" = "Видалити не надіслане повідомлення"; +"room_event_action_report_prompt_ignore_user" = "Бажаєте сховати усі повідомлення від цього користувача?"; +"room_event_action_kick_prompt_reason" = "Причина викидання користувача"; +"room_participants_action_mention" = "Згадати"; +"room_participants_action_unignore" = "Показати усі повідомлення від цього користувача"; +"room_participants_action_ignore" = "Сховати усі повідомлення від цього користувача"; +"room_participants_unknown" = "Невідомо"; +"room_participants_offline" = "Не в мережі"; +"room_participants_online" = "У мережі"; +"find_your_contacts_identity_service_error" = "Не вдалося під'єднатися до сервера ідентифікації."; +"find_your_contacts_footer" = "Це будь-коли можна вимкнути у налаштуваннях."; +"settings_contacts_phonebook_country" = "Країна телефонної книги"; +"settings_contacts_enable_sync" = "Пошук контактів"; +"find_your_contacts_button_title" = "Пошук контактів"; +"contacts_address_book_permission_denied_alert_message" = "Увімкніть контакти з налаштувань пристрою."; +"contacts_address_book_permission_denied_alert_title" = "Контакти вимкнено"; From 5ad8a6040c7c79b3ae63602282dffb18c931868a Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 29 Oct 2021 19:29:11 +0000 Subject: [PATCH 020/122] Translated using Weblate (Swedish) Currently translated at 98.2% (1307 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sv/ --- Riot/Assets/sv.lproj/Vector.strings | 33 +++++++++++++++++++++++++---- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/sv.lproj/Vector.strings b/Riot/Assets/sv.lproj/Vector.strings index ccffe08ef..1cc6e7b2c 100644 --- a/Riot/Assets/sv.lproj/Vector.strings +++ b/Riot/Assets/sv.lproj/Vector.strings @@ -29,7 +29,7 @@ "warning" = "Varning"; "active_call" = "Aktivt samtal"; "active_call_details" = "Aktivt samtal (%@)"; -"rename" = "Byt namn"; +"rename" = "Döp om"; "send_to" = "Skicka till %@"; "sending" = "Skickar"; "close" = "Stäng"; @@ -62,7 +62,7 @@ "auth_email_is_required" = "Ingen identitetsserver är konfigurerad, så du kan inte lägga till en e-postadress för att återställa ditt lösenord i framtiden."; "auth_phone_is_required" = "Ingen identitetsserver är konfigurerad, så du kan inte lägga till ett telefonnummer för att återställa ditt lösenord i framtiden."; "auth_password_dont_match" = "Lösenorden matchar inte"; -"auth_username_in_use" = "Användarnamnet är upptaget"; +"auth_username_in_use" = "Användarnamn upptaget"; "auth_forgot_password" = "Glömt lösenordet?"; "auth_email_not_found" = "Misslyckades att skicka e-post: Den här e-postadressen hittades inte"; "auth_use_server_options" = "Använd anpassade serveralternativ (avancerat)"; @@ -97,7 +97,7 @@ "room_creation_keep_private" = "Behåll privat"; "room_creation_make_private" = "Gör privat"; "room_creation_wait_for_creation" = "Ett rum håller redan på att skapas. Vänligen vänta."; -"room_creation_invite_another_user" = "Sök / bjud in efter användar-ID, namn eller e-postadress"; +"room_creation_invite_another_user" = "Användar-ID, namn eller e-postadress"; "room_recents_favourites_section" = "FAVORITER"; "room_recents_people_section" = "PERSONER"; "room_recents_conversations_section" = "RUM"; @@ -274,7 +274,7 @@ "settings_integrations" = "INTEGRATIONER"; "settings_user_interface" = "ANVÄNDARGRÄNSSNITT"; "settings_ignored_users" = "IGNORERADE ANVÄNDARE"; -"settings_contacts" = "LOKALA KONTAKTER"; +"settings_contacts" = "ENHETSKONTAKTER"; "settings_advanced" = "AVANCERAT"; "settings_other" = "ANNAT"; "settings_labs" = "EXPERIMENT"; @@ -1417,3 +1417,28 @@ "room_recents_suggested_rooms_section" = "FÖRESLAGNA RUM"; "done" = "Klar"; "open" = "Öppna"; +"service_terms_modal_information_description_integration_manager" = "En integrationshanterare låter dig lägga till funktioner från tredje parter."; +"service_terms_modal_information_description_identity_server" = "En identitetsserver hjälper dig att hitta dina kontakter genom att leta upp deras telefonnummer eller e-postadress för att se om de redan har ett konto."; +"service_terms_modal_information_title_integration_manager" = "Integrationshanterare"; + +// Alert explaining what an identity server / integration manager is. +"service_terms_modal_information_title_identity_server" = "Identitetsserver"; +"service_terms_modal_description_integration_manager" = "Detta kommer att låta dig använda bottar, bryggor, widgets och dekalpaket."; +"service_terms_modal_description_identity_server" = "Detta kommer att låta personer hitta dig om de har ditt telefonnummer eller din e-postadress sparat i sina telefonkontakter."; +"service_terms_modal_table_header_integration_manager" = "INTEGRATIONSHANTERARVILLKOR"; +"service_terms_modal_table_header_identity_server" = "IDENTITETSSERVERVILLKOR"; +"service_terms_modal_footer" = "Detta kan inaktiveras när som helst i inställningarna."; + +// Service terms +"service_terms_modal_title_message" = "För att fortsätta, acceptera användarvillkoren nedan"; +"settings_contacts_enable_sync_description" = "Detta kommer att använda din identitetsserver för att koppla dig till dina kontakter, och hjälpa dem att hitta dig."; +"settings_contacts_enable_sync" = "Hitta dina kontakter"; +"settings_phone_contacts" = "TELEFONKONTAKTER"; +"room_event_action_forward" = "Vidarebefordra"; +"find_your_contacts_identity_service_error" = "Kan inte ansluta till identitetsservern."; +"find_your_contacts_footer" = "Detta kan inaktiveras när som helst från inställningarna."; +"find_your_contacts_button_title" = "Hitta dina kontakter"; +"find_your_contacts_message" = "Låt %@ visa dina kontakter så att du snabbt kan börja chatta med dem du känner bäst."; +"find_your_contacts_title" = "Börja genom att lista dina kontakter"; +"contacts_address_book_permission_denied_alert_message" = "För att aktivera kontakter, gå till dina enhetsinställningar."; +"contacts_address_book_permission_denied_alert_title" = "Kontakter inaktiverat"; From 74395841e06f14302c7e039e553a0b5ff9ccb787 Mon Sep 17 00:00:00 2001 From: random Date: Fri, 22 Oct 2021 09:02:05 +0000 Subject: [PATCH 021/122] Translated using Weblate (Italian) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/it/ --- Riot/Assets/it.lproj/Vector.strings | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Assets/it.lproj/Vector.strings b/Riot/Assets/it.lproj/Vector.strings index aa161e9da..e94c77666 100644 --- a/Riot/Assets/it.lproj/Vector.strings +++ b/Riot/Assets/it.lproj/Vector.strings @@ -1501,3 +1501,5 @@ "find_your_contacts_title" = "Inizia elencando i tuoi contatti"; "contacts_address_book_permission_denied_alert_message" = "Per attivare i contatti, vai nelle impostazioni del tuo dispositivo."; "contacts_address_book_permission_denied_alert_title" = "Contatti disattivati"; +"space_home_show_all_rooms" = "Mostra tutte le stanze"; +"room_event_action_forward" = "Inoltra"; From 6c423acf724cbb31094a521078c60b4faefa158f Mon Sep 17 00:00:00 2001 From: Linerly Date: Fri, 29 Oct 2021 01:16:57 +0000 Subject: [PATCH 022/122] Translated using Weblate (Indonesian) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/id/ --- Riot/Assets/id.lproj/Vector.strings | 1039 +++++++++++++++++++++++++++ 1 file changed, 1039 insertions(+) diff --git a/Riot/Assets/id.lproj/Vector.strings b/Riot/Assets/id.lproj/Vector.strings index aaeece68f..905e4a2fc 100644 --- a/Riot/Assets/id.lproj/Vector.strings +++ b/Riot/Assets/id.lproj/Vector.strings @@ -609,3 +609,1042 @@ "auth_msisdn_validation_title" = "Menunggu Verifikasi"; "done" = "Selesai"; "open" = "Buka"; +"version_check_banner_subtitle_deprecated" = "Kami tidak mendukung %@ di iOS %@ lagi. Untuk terus menggunakan %@ secara maksimal, kami menyarankan Anda untuk meningkatkan versi iOS Anda."; +"version_check_banner_subtitle_supported" = "Kami akan segera mengakhiri dukungan untuk %@ di iOS %@. Untuk terus menggunakan %@ secara maksimal, kami menyarankan Anda untuk meningkatkan versi iOS Anda."; +"spaces_coming_soon_detail" = "Fitur ini belum ada di sini, tetapi sedang dalam proses. Untuk saat ini, Anda dapat melakukannya dengan Element di komputer Anda."; +"spaces_no_member_found_detail" = "Mencari seseorang yang tidak ada di %@? Untuk saat ini, Anda dapat mengundangnya di web atau desktop."; +"spaces_no_room_found_detail" = "Beberapa hasil mungkin disembunyikan karena ruangannya pribadi dan Anda memerlukan sebuah undangan untuk bergabung."; +"spaces_empty_space_detail" = "Beberapa ruangan mungkin disembunyikan karena ruangannya pribadi dan Anda memerlukan sebuah undangan."; +"leave_space_message" = "Apakah anda Anda yakin ingin keluar dari %@? Apakah Anda juga ingin meninggalkan semua ruangan dan space lainnya di space ini?"; +"space_beta_announce_information" = "Space adalah cara baru untuk mengelompokkan ruangan dan orang. Mereka belum ada di iOS, tetapi Anda dapat menggunakannya sekarang di Web dan Desktop."; +"favourites_empty_view_information" = "Anda dapat memfavoritkan dengan beberapa cara - yang tercepat adalah dengan menekan dan menahan. Ketuk ikon bintang dan mereka akan secara otomatis muncul di sini."; +"home_empty_view_information" = "Aplikasi obrolan aman semua-dalam-satu untuk tim, teman, dan organisasi. Ketuk tombol + di bawah untuk menambahkan orang dan ruangan."; +"pin_protection_explanatory" = "Menyiapkan PIN memungkinkan Anda melindungi data seperti pesan dan kontak, jadi hanya Anda yang dapat mengaksesnya dengan memasukkan PIN di awal aplikasi."; +"major_update_information" = "Kami senang mengumumkan bahwa kami telah mengubah nama kami! Aplikasi Anda telah diperbarui dan Anda masuk ke akun Anda."; +"secrets_reset_warning_message" = "Anda akan memulai ulang tanpa sejarah, tanpa pesan, perangkat tepercaya, atau pengguna tepercaya."; +"secrets_setup_recovery_key_storage_alert_message" = "✓ Cetak dan simpan di tempat yang aman\n✓ Simpan di flashdisk USB atau drive cadangan\n✓ Salin ke penyimpanan awan pribadi Anda"; +"secrets_recovery_with_key_information_default" = "Akses sejarah pesan terenkripsi Anda dan identitas penandatanganan silang Anda untuk memverifikasi sesi lain dengan memasukkan Kunci Keamanan Anda."; +"secrets_recovery_with_passphrase_information_default" = "Akses sejarah pesan terenkripsi Anda dan identitas penandatanganan silang Anda untuk memverifikasi sesi lain dengan memasukkan Frasa Keamanan Anda."; +"user_verification_session_details_additional_information_untrusted_other_user" = "Hingga pengguna ini memercayai sesi ini, pesan yang dikirim ke dan dari sesi ini akan diberi label peringatan. Atau, Anda dapat memverifikasinya secara manual."; +"user_verification_session_details_information_untrusted_current_user" = "Verifikasi sesi ini untuk menandainya sebagai tepercaya & memberikan akses ke pesan terenkripsi:"; +"user_verification_sessions_list_information" = "Pesan dengan pengguna ini di ruangan ini dienkripsi secara ujung-ke-ujung dan tidak dapat dibaca oleh pihak ketiga."; + +// User + +"key_verification_verified_user_information" = "Pesan dengan pengguna ini dienkripsi secara ujung-ke-ujung dan tidak dapat dibaca oleh pihak ketiga."; +"key_verification_verified_this_session_information" = "Anda sekarang dapat membaca pesan aman di perangkat ini, dan pengguna lain akan tahu bahwa mereka dapat mempercayainya."; +"key_verification_verified_new_session_information" = "Anda sekarang dapat membaca pesan aman di perangkat baru Anda, dan pengguna lain akan tahu bahwa mereka dapat mempercayainya."; +"key_verification_verified_other_session_information" = "Anda sekarang dapat membaca pesan terenkripsi di sesi Anda yang lain, dan pengguna lain akan tahu bahwa mereka dapat mempercayainya."; +"key_verification_manually_verify_device_additional_information" = "Jika tidak cocok, keamanan komunikasi Anda mungkin dikompromikan."; +"key_verification_manually_verify_device_instruction" = "Konfirmasi dengan membandingkan berikut ini dengan Pengaturan Pengguna di sesi Anda yang lain:"; +"key_verification_verify_sas_additional_information" = "Untuk keamanan yang maksimal, gunakan sarana komunikasi tepercaya lainnya atau lakukan ini secara langsung."; +"device_verification_self_verify_wait_information" = "Verifikasi sesi ini dari salah satu sesi Anda yang lain, memberikan akses ke pesan terenkripsi.\n\nGunakan %@ yang terbaru di perangkat Anda yang lain:"; +"key_verification_self_verify_unverified_sessions_alert_message" = "Verifikasi semua sesi Anda untuk memastikan akun & pesan Anda aman."; +"device_verification_self_verify_start_information" = "Gunakan sesi ini untuk memverifikasi sesi Anda yang baru, memberikan akses ke pesan terenkripsi."; +"device_verification_start_use_legacy" = "Tidak ada yang muncul? Belum semua klien mendukung verifikasi interaktif. Gunakan verifikasi warisan."; +"device_verification_incoming_description_2" = "Memverifikasi sesi ini akan menandainya sebagai tepercaya, dan juga menandai sesi Anda sebagai terpercaya kepada pengguna yang lain."; +"device_verification_incoming_description_1" = "Verifikasi sesi ini untuk menandainya sebagai tepercaya. Mempercayai sesi pengguna memberi Anda ketenangan pikiran ekstra saat menggunakan enkripsi ujung-ke-ujung."; +"sign_out_key_backup_in_progress_alert_title" = "Pencadangan kunci sedang berlangsung. Jika Anda keluar sekarang, Anda akan kehilangan akses ke pesan terenkripsi Anda."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Anda akan kehilangan akses ke pesan terenkripsi Anda kecuali jika Anda mencadangkan kunci Anda sebelum keluar."; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Kehilangan Kunci Keamanan Anda dapat menyiapkan yang baru di pengaturan."; +"key_backup_recover_invalid_recovery_key" = "Cadangan tidak dapat didekripsi dengan kunci ini: harap verifikasi bahwa Anda memasukkan Kunci Keamanan yang benar."; +"key_backup_recover_invalid_passphrase" = "Cadangan tidak dapat didekripsi dengan frasa ini: harap verifikasi bahwa Anda memasukkan Frasa Keamanan yang benar."; + +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Kunci Anda sedang dicadangkan.\n\nBuat sebuah salinan dari Kunci Keamanan ini dan simpan di tempat yang aman."; +"key_backup_setup_skip_alert_message" = "Anda mungkin kehilangan akses ke pesan terenkripsi jika Anda keluar atau menghilangkan perangkat Anda."; +"secure_key_backup_setup_existing_backup_error_info" = "Buka kunci untuk menggunakannya kembali di cadangan aman atau hapus untuk membuat cadangan pesan baru di cadangan aman."; +"secure_key_backup_setup_intro_use_security_passphrase_info" = "Masukkan frasa rahasia yang hanya Anda yang tahu, dan buat kunci untuk cadangan."; +"secure_key_backup_setup_intro_use_security_key_info" = "Buat sebuah kunci keamanan untuk disimpan di tempat yang aman seperti pengelola kata sandi atau brankas."; +"secure_key_backup_setup_intro_info" = "Lindungi dari kehilangan akses ke pesan & data terenkripsi dengan mencadangkan kunci enkripsi di server Anda."; +"rerequest_keys_alert_message" = "Mohon buka %@ pada perangkat yang lain yang dapat mendekripsi pesan sehingga dapat mengirim kunci ke sesi ini."; +"deactivate_account_forget_messages_information_part3" = ": ini akan menyebabkan pengguna di masa mendatang melihat tampilan percakapan yang tidak lengkap)"; +"deactivate_account_forget_messages_information_part1" = "Mohon lupakan semua pesan yang saya telah kirim ketika akun saya dinonaktifkan ("; +"service_terms_modal_information_description_identity_server" = "Sebuah server identitas membantu Anda menemukan kontak Anda, dengan mencari nomor telepon atau alamat email mereka, untuk melihat apakah mereka sudah memiliki akun."; +"service_terms_modal_description_identity_server" = "Ini akan mengizinkan seseorang untuk menemukan Anda jika mereka menyimpan nomor telepon atau email Anda di kontak telepon mereka."; +"service_terms_modal_description_integration_manager" = "Ini akan mengizinkan Anda untuk menggunakan bot, jembatan, widget, dan paket stiker."; + +// GDPR +"gdpr_consent_not_given_alert_message" = "Untuk terus menggunakan homeserver %@, Anda harus menyetujui syarat dan ketentuannya."; +"share_extension_failed_to_encrypt" = "Gagal untuk mengirim. Periksa di aplikasi utama pengaturan enkripsi untuk ruangan ini"; +"bug_report_logs_description" = "Untuk mendiagnosis masalah, log dari klien ini akan dikirim dengan laporan bug ini. Jika Anda lebih memilih untuk hanya mengirim teks di atas, harap hapus centang:"; +"bug_report_description" = "Harap jelaskan bugnya. Apa yang Anda lakukan? Apa yang Anda harapkan terjadi? Apa yang sebenarnya terjadi?"; +"e2e_key_backup_wrong_version" = "Cadangan kunci pesan aman baru telah terdeteksi.\n\nJika ini bukan Anda, atur Frasa Keamanan baru di Pengaturan."; + +// Crypto +"e2e_enabling_on_app_update" = "%@ sekarang mendukung enkripsi ujung-ke-ujung tetapi Anda harus masuk lagi untuk mengaktifkannya.\n\nAnda dapat melakukannya sekarang atau nanti di pengaturan aplikasi."; + +// Crash report +"google_analytics_use_prompt" = "Apakah Anda ingin membantu meningkatkan %@ dengan secara otomatis melaporkan laporan kerusakan dan data penggunaan secara anonim?"; +"no_voip" = "%@ sedang memanggil Anda tetapi %@ belum mendukung panggilan.\nAnda dapat mengabaikan notifikasi ini dan jawab panggilannya di perangkat yang lain atau menolak panggilannya."; +"call_no_stun_server_error_message_1" = "Mohon hubungi administrator homeserver %@ Anda untuk mengatur sebuah server TURN supaya panggilan dapat bekerja dengan handal."; +"rage_shake_prompt" = "Anda tampaknya menggoyangkan telepon dengan frustrasi. Apakah Anda ingin mengirimkan laporan bug?"; +"bug_report_prompt" = "Aplikasi telah crash terakhir kali. Apakah Anda ingin mengirimkan laporan crash?"; +"room_notifs_settings_encrypted_room_notice" = "Harap dicatat bahwa notifikasi sebutan & keyword tidak tersedia di ruang terenkripsi di ponsel."; +"room_details_addresses_disable_main_address_prompt_msg" = "Anda tidak akan memiliki alamat utama yang ditentukan. Alamat utama default untuk ruangan ini akan dipilih secara acak"; +"room_details_history_section_prompt_msg" = "Perubahan siapa yang dapat membaca sejarah hanya akan berlaku untuk pesan berikutnya di ruang ini. Visibilitas sejarah yang ada tidak akan berubah."; +"identity_server_settings_alert_error_terms_not_accepted" = "Anda harus menerima syaratnya %@ untuk menyetelnya sebagai server identitas."; +"identity_server_settings_alert_change" = "Lepaskan hubungan dari server identitas %1$@ dan hubungkan ke %2$@?"; +"identity_server_settings_alert_no_terms" = "Server identitas ini yang Anda pilih tidak memiliki syarat layanan. Hanya lanjutkan jika Anda mempercayai pemilik server itu."; +"identity_server_settings_disconnect_info" = "Melepas hubungan dari server identitas Anda akan berarti Anda tidak akan dapat ditemukan oleh pengguna lain dan tidak akan dapat mengundang orang lain menggunakan email atau telepon."; +"identity_server_settings_no_is_description" = "Anda saat ini tidak menggunakan sebuah server identitas. Untuk menemukan dan dapat ditemukan oleh kontak yang sudah ada, tambahkan satu di atas."; +"identity_server_settings_description" = "Anda saat ini menggunakan %@ untuk menemukan dan dapat ditemukan oleh kontak yang Anda tahu."; + +// AuthenticatedSessionViewControllerFactory +"authenticated_session_flow_not_supported" = "Aplikasi ini tidak mendukung mekanisme otentikasi di homeserver Anda."; +"security_settings_coming_soon" = "Maaf. Aksi ini belum tersedia di %@ iOS. Mohon gunakan klien Matrix yang lain untuk menyiapkannya. %@ iOS akan menggunakannya."; +"security_settings_blacklist_unverified_devices_description" = "Verifikasi semua sesi pengguna untuk menandainya sebagai terpercaya dan kirim pesan ke mereka."; +"security_settings_crosssigning_info_exists" = "Akun Anda memiliki identitas penandatanganan silang, tetapi belum dipercayai oleh sesi ini. Selesaikan keamanan sesi ini."; +"security_settings_secure_backup_description" = "Cadangkan kunci enkripsi Anda dengan data akun Anda untuk berjaga-jaga jika Anda kehilangan akses ke sesi Anda. Kunci Anda akan diamankan dengan Kunci Keamanan yang unik."; +"security_settings_crypto_sessions_description_2" = "Jika Anda tidak tahu sebuah login, ubah kata sandi Anda dan atur ulang Cadangan Aman."; +"settings_identity_server_no_is_description" = "Anda saat ini tidak menggunakan sebuah server identitas. Untuk menemukan dan dapat ditemukan oleh kontak yang Anda tahu, tambahkan satu di atas."; +"settings_identity_server_description" = "Dengan menggunakan set server identitas di atas, Anda dapat menemukan dan dapat ditemukan oleh kontak yang ada yang Anda kenal."; +"settings_discovery_three_pid_details_information_phone_number" = "Kelola preferensi untuk nomor telepon ini, yang dapat digunakan pengguna lain untuk menemukan Anda dan digunakan untuk mengundang Anda ke ruangan. Tambahkan atau hapus nomor telepon di Akun."; +"settings_discovery_three_pid_details_information_email" = "Kelola preferensi untuk alamat email ini, yang dapat digunakan pengguna lain untuk menemukan Anda dan digunakan untuk mengundang Anda ke ruangan. Tambahkan atau hapus alamat email di Akun."; +"settings_discovery_terms_not_signed" = "Setujui server identitas (%@) Persyaratan Layanan agar Anda dapat ditemukan dengan alamat email atau nomor telepon."; +"settings_discovery_no_identity_server" = "Saat ini Anda tidak menggunakan sebuah server identitas. Supaya Anda dapat ditemukan oleh kontak yang sudah ada yang Anda kenal, tambahkan satu."; +"pin_protection_reset_alert_message" = "Untuk mengatur ulang PIN, Anda harus masuk kembali dan buat yang baru lagi"; +"device_verification_security_advice_emoji" = "Bandingkan emoji yang unik, memastikannya muncul dengan urutan yang sama."; +"secrets_reset_information" = "Lakukan ini hanya jika Anda tidak memiliki perangkat lain yang dapat digunakan untuk memverifikasi perangkat ini."; +"secrets_setup_recovery_passphrase_summary_information" = "Ingat Frasa Keamanan Anda. Itu dapat digunakan untuk mengakses pesan & data terenkripsi Anda."; +"secrets_setup_recovery_passphrase_information" = "Masukkan frasa keamanan yang hanya Anda tahu, akan digunakan untuk mengamankan rahasia di server Anda."; +"secrets_setup_recovery_key_information" = "Simpan Kunci Keamanan Anda di tempat yang aman. Itu bisa digunakan untuk mengakses pesan % data terenkripsi Anda."; +"leave_space_message_admin_warning" = "Anda adalah admin space ini, pastikan Anda telah mentransfer hak admin ke anggota lain sebelum keluar."; +"space_feature_unavailable_subtitle" = "Space belum ada di iOS, tetapi Anda bisa menggunakannya di Web dan Desktop"; +"room_intro_cell_information_multiple_dm_sentence2" = "Hanya Anda yang ada dalam obrolan ini, kecuali jika Anda mengundang seseorang untuk bergabung."; +"room_intro_cell_information_dm_sentence2" = "Hanya Anda berdua yang ada dalam obrolan ini, tidak ada orang lain yang bisa bergabung."; +"create_room_section_footer_type" = "Orang-orang bergabung ke ruang pribadi hanya dengan undangan ruangan."; +"biometrics_cant_unlocked_alert_message_x" = "Untuk mengakses, gunakan %@ atau masuk kembali dan aktifkan %@ lagi"; +"pin_protection_not_allowed_pin" = "Untuk keamanan, PIN ini tidak tersedia. Coba PIN yang lain"; +"pin_protection_settings_section_footer" = "Untuk mengatur ulang PIN, Anda harus masuk lagi dan buat yang baru."; +"pin_protection_mismatch_too_many_times_error_message" = "JIka Anda lupa PIN Anda, ketuk tombol lupa PIN."; +"secrets_recovery_with_key_invalid_recovery_key_message" = "Mohon verifikasi jika Anda telah masukkan Kunci Keamanan yang benar."; +"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Mohon verifikasi jika Anda telah masukkan Frasa Keamanan yang benar."; +"user_verification_session_details_additional_information_untrusted_current_user" = "Jika Anda tidak masuk ke sesi ini, akun Anda mungkin dikompromikan."; +"user_verification_session_details_information_trusted_current_user" = "Sesi ini dipercayai untuk perpesanan aman karena Anda memverifikasinya:"; +"user_verification_start_additional_information" = "Supaya aman, lakukan ini secara langsung atau gunakan cara yang lain untuk berkomunikasi."; +"user_verification_start_information_part2" = " dengan memeriksa sebuah kode sekali-pakai di kedua perangkat Anda."; +"key_verification_verify_qr_code_other_scan_my_code_title" = "Apakah pengguna yang lain berhasil memindai kode QR-nya?"; + + +// Generic errors +"error_invite_3pid_with_no_identity_server" = "Tambahkan sebuah server identitas di pengaturan Anda untuk mengundang dengan email."; +"device_verification_self_verify_wait_additional_information" = "Ini bekerja dengan %@ dan klien Matrix lainnya yang mampu melakukan penandatanganan silang."; +"device_verification_security_advice_number" = "Bandingkan nomornya, memastikannya muncul dengan urutan yang sama."; +"sign_out_non_existing_key_backup_alert_title" = "Anda akan kehilangan akses ke pesan terenkripsi jika Anda keluar"; + +// Recover from recovery key + +"key_backup_recover_from_recovery_key_info" = "Gunakan Frasa Keamanan Anda untuk mengakses sejarah pesan secara aman"; + +// Recover from passphrase + +"key_backup_recover_from_passphrase_info" = "Gunakan Frasa Keamanan Anda untuk mengakses sejarah pesan secara aman"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Atau, amankan cadangan Anda dengan sebuah Kunci Keamanan, menyimpannya di tempat yang aman."; +"secure_backup_setup_banner_subtitle" = "Amankan dari kehilangan akses ke pesan & data terenkripsi"; +"deactivate_account_informations_part4_emphasize" = "tidak secara default menyebabkan kami melupakan pesan yang telah Anda kirim. "; +"service_terms_modal_information_description_integration_manager" = "Sebuah pengelola integrasi mengizinkan Anda untuk menambahkan fitur dari pihak ketiga."; +"e2e_room_key_request_message_new_device" = "Anda menambahkan sebuah sesi baru '%@', yang meminta kunci enkripsi."; +"room_widget_permission_webview_information_title" = "Menggunakannya mungkin mengatur cookie dan membagikan data dengan %@:\n"; +"widget_integration_no_permission_in_room" = "Anda tidak memiliki izin untuk melakukannya di ruangan ini."; + +// Widget Integration Manager +"widget_integration_need_to_be_able_to_invite" = "Anda harus dapat mengundang pengguna untuk melakukannya."; +"widget_no_power_to_manage" = "Anda perlu izin untuk mengelola widget di ruangan ini"; +"photo_library_access_not_granted" = "%@ tidak memiliki izin untuk mengakses perpustakaan foto, mohon ubah pengaturan privasi"; +"camera_access_not_granted" = "%@ tidak memiliki izin untuk menggunakan Kamera, mohon ubah pengaturan privasi"; +"group_participants_invite_malformed_id" = "ID yang cacat. Seharusnya sebuah ID Matrix seperti '@pengguna:domain'"; +"group_participants_invite_prompt_msg" = "Apakah Anda yakin untuk mengundang %@ ke grup ini?"; +"group_participants_remove_prompt_msg" = "Apakah Anda yakin untuk mengeluarkan %@ dari grup ini?"; +"group_participants_leave_prompt_msg" = "Apakah Anda yakin untuk meninggalkan grup ini?"; +"room_details_fail_to_update_room_direct" = "Gagal untuk memperbarui detail ruangan ini"; +"room_details_flair_invalid_id_prompt_msg" = "%@ bukan pengenal yang valid untuk sebuah komunitas"; +"room_details_addresses_invalid_address_prompt_msg" = "%@ bukan format yang valid untuk sebuah alias"; +"room_details_history_section_members_only" = "Anggota saha (sejak opsi ini dipilih)"; +"room_details_access_section_no_address_warning" = "Untuk menautkan ke ruangan itu harus memiliki alamat"; +"voice_message_stop_locked_mode_recording" = "Ketuk pada rekaman Anda untuk berhenti atau dengarkan"; +"room_intro_cell_information_dm_sentence1_part1" = "Ini adalah awal dari pesan langsung Anda dengan "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " supaya orang tahu tentang ruangan ini."; +"invite_friends_share_text" = "Hai, bicara kepada saya di %@: %@"; +"biometrics_usage_reason" = "Otentikasi diperlukan untuk mengakses aplikasi ini"; +"pin_protection_kick_user_alert_message" = "Terlalu banyak kesalahan, Anda telah dikeluarkan"; +"secrets_setup_recovery_passphrase_confirm_information" = "Masukkan Frasa Keamanan Anda untuk mengkonfirmasi."; +"secrets_recovery_with_key_information_verify_device" = "Gunakan Kunci Keamanan Anda untuk memverifikasi perangkat ini."; +"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Tidak tahu Frasa Keamanan Anda? Anda dapat "; +"secrets_recovery_with_passphrase_information_verify_device" = "Gunakan Frasa Keamanan Anda untuk memverifikasi perangkat ini."; +"user_verification_session_details_information_trusted_other_user_part1" = "Sesi ini dipercayai untuk perpesanan Aman karena "; +"device_verification_self_verify_alert_message" = "Verifikasi login baru yang mengakses akun Anda: %@"; + +// MARK: Sign out warning + +"sign_out_existing_key_backup_alert_title" = "Apakah Anda yakin untuk keluar?"; + +// Passphrase + +"key_backup_setup_passphrase_title" = "Amankan cadangan Anda dengan sebuah Frasa Sandi"; + +// Service terms +"service_terms_modal_title_message" = "Untuk melanjutkan, setujui syarat dan ketentuan di bawah"; +"e2e_room_key_request_message" = "Sesi '%@' yang belum diverifikasi meminta kunci enkripsi."; + +// Share extension +"share_extension_auth_prompt" = "Masuk di aplikasi utama untuk membagikan konten"; +"widget_integration_manager_disabled" = "Anda perlu mengaktifkan pengelola integrasi di pengaturan"; +"bug_crash_report_description" = "Jelaskan apa yang Anda lakukan sebelum crashnya:"; +"directory_server_type_homeserver" = "Ketik sebuah homeserver untuk menampilkan daftar ruangan publik"; +"room_details_access_section_anyone_apart_from_guest" = "Siapa saja yang tahu tautan ruangan, selain dari tamu"; +"security_settings_complete_security_alert_message" = "Anda seharusnya menyelesaikan keamanan di sesi Anda saat ini dulu."; +"key_verification_scan_confirmation_scanned_device_information" = "Apakah perangkat yang lain menampilkan perisai yang sama?"; +"key_verification_verify_qr_code_information" = "Pindai kodenya untuk memverifikasi dengan sesama dengan aman."; +"error_not_supported_on_mobile" = "Anda tidak melakukannya dari %@ mobile."; +"device_verification_self_verify_wait_recover_secrets_additional_information" = "Jika Anda tidak dapat mengakses sesi yang sudah ada"; + +// MARK: Start +"device_verification_start_title" = "Verifikasi dengan membandingkan string teks pendek"; +"device_verification_cancelled_by_me" = "Verifikasi telah dibatalkan. Alasan: %@"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Tidak tahu Frasa Keamanan Anda? Anda dapat "; +"service_terms_modal_footer" = "Ini dapat dinonaktifkan di pengaturan."; +"room_widget_permission_information_title" = "Menggunakannya mungkin membagikan data dengan %@:\n"; +"widget_sticker_picker_no_stickerpacks_alert" = "Saat ini Anda tidak mengaktifkan paket stiker apapun."; +"call_already_displayed" = "Sudah ada panggilan yang sedang berlangsung."; +"camera_unavailable" = "Kamera tidak tersedia di perangkat Anda"; +"network_offline_prompt" = "Koneksi internetnya terlihat offline."; +"group_participants_invite_another_user" = "Cari/undang dengan ID Pengguna atau Nama"; +"group_invitation_format" = "%@ telah mengundang Anda untuk bergabung ke komunitas ini"; +"room_notifs_settings_manage_notifications" = "Anda dapat mengelola notifikasi di %@"; +"room_details_fail_to_enable_encryption" = "Gagal untuk mengaktifkan enkripsi di ruangan ini"; +"room_details_fail_to_add_room_aliases" = "Gagal untuk menambahkan alamat ruangan baru"; +"room_details_fail_to_update_room_guest_access" = "Gagal untuk memperbarui akses tamu"; +"room_details_fail_to_update_room_directory_visibility" = "Gagal untuk memperbarui visibilitas direktori ruangan"; +"room_details_advanced_e2e_encryption_disabled" = "Enkripsi tidak diaktifkan di ruangan ini."; +"room_details_advanced_enable_e2e_encryption" = "Aktifkan enkripsi (peringatan: tidak dapat dinonaktifkan lagi!)"; +"room_details_access_section_anyone_for_dm" = "Siapa saja yang tahu tautannya, termasuk tamu"; +"room_details_access_section_anyone" = "Siapa saja yang tahu tautannya ruangan, termasuk tamu"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "Siapa saja yang tahu linknya, selain dari tamu"; +"identity_server_settings_alert_error_invalid_identity_server" = "%@ bukan server identitas yang valid."; +"identity_server_settings_alert_no_terms_title" = "Server identitas tidak mempunyai kebijakan layanan"; +"security_settings_user_password_description" = "Konfirmasi identitas Anda dengan memasukkan kata sandi akun Anda"; +"security_settings_secure_backup_info_valid" = "Sesi ini mencadangkan kunci Anda."; +"version_check_modal_title_deprecated" = "Kami tidak mendukung iOS %@ lagi"; +"version_check_modal_title_supported" = "Kami mengakhiri dukungan untuk iOS %@"; +"version_check_banner_title_deprecated" = "Kami tidak mendukung iOS %@ lagi"; + +// Mark: - Version check + +"version_check_banner_title_supported" = "Kami mengakhiri dukungan untuk iOS %@"; + +// Mark: - Voice Messages + +"voice_message_release_to_send" = "Tahan untuk merekam, lepaskan untuk mengirim"; +"spaces_empty_space_title" = "Space ini belum ada ruangan"; +"create_room_show_in_directory" = "Tampilkan ruangan di direktori"; +"secrets_reset_authentication_message" = "Masukkan kata sandi akun Anda untuk mengkonfirmasi"; +"secrets_recovery_with_key_information_unlock_secure_backup_with_key" = "Masukkan Kunci Keamanan Anda untuk melanjutkan."; +"secrets_recovery_with_key_information_unlock_secure_backup_with_phrase" = "Masukkan Frasa Keamanan Anda untuk melanjutkan."; + +// MARK: - Secrets recovery + +"secrets_recovery_reset_action_part_1" = "Lupa atau kehilangan semua opsi pemulihan? "; +"user_verification_session_details_information_untrusted_other_user" = " masuk dengan sesi baru:"; +"key_verification_scan_confirmation_scanned_user_information" = "Apakah %@ menampilkan perisai yang sama?"; +"key_verification_verify_qr_code_scan_other_code_success_message" = "Kode QR berhasil divalidasi."; +"key_verification_verify_qr_code_information_other_device" = "Pindai kode di bawah untuk memverifikasi:"; +"key_verification_bootstrap_not_setup_message" = "Anda harus mem-bootstrap penandatanganan-silang dulu."; +"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Memeriksa untuk kemampuan verifikasi lain ..."; +"key_verification_self_verify_current_session_alert_message" = "Pengguna yang lain mungkin tidak mempercayainya."; +"device_verification_cancelled" = "Pengguna yang lain membatalkan verifikasinya."; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Saya tidak ingin pesan terenkripsi saya"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Anda akan kehilangan pesan terenkripsi Anda"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Saya tidak ingin pesan terenkripsi saya"; + +// Success from secure backup +"key_backup_setup_success_from_secure_backup_info" = "Kunci Anda sedang dicadangkan."; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Lanjutan) Siapkan dengan Kunci Keamanan"; +"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Hubungkan perangkat ini ke Cadangan Kunci"; +"secure_key_backup_setup_existing_backup_error_title" = "Sudah ada cadangan untuk pesan"; +"room_predecessor_link" = "Ketuk di sini untuk melihat pesan lama."; +"room_many_users_are_typing" = "%@, %@ & lainnya sedang mengetik…"; +"room_two_users_are_typing" = "%@ & %@ sedang mengetik…"; +"room_participants_security_information_room_not_encrypted_for_dm" = "Pesan di sini tidak terenkripsi secara ujung-ke-ujung."; +"room_participants_action_unignore" = "Tampilkan semua pesan dari penguna ini"; +"room_participants_action_ignore" = "Sembunyikan semua pesan dari pengguna ini"; +"find_your_contacts_title" = "Mulai dengan mendaftar kontak Anda"; +"contacts_address_book_permission_required" = "Izin diperlukan untuk mengakses kontak lokal"; +"settings_labs_message_reaction" = "Bereaksi ke pesan dengan emoji"; +"settings_labs_create_conference_with_jitsi" = "Buat panggilan konferensi dengan jitsi"; +"settings_unignore_user" = "Tampilkan semua pesan dari %@?"; +"settings_calls_stun_server_fallback_button" = "Izinkan cadangan server untuk panggilan"; +"settings_messages_by_a_bot" = "Pesan dari sebuah bot"; +"settings_pin_rooms_with_unread" = "Pin ruangan dengan pesan yang belum dibaca"; +"settings_pin_rooms_with_missed_notif" = "Pin ruangan dengan notifikasi yang terlewat"; +"settings_confirm_media_size" = "Konfirmasi ukuran saat mengirim"; +"settings_sending_media" = "MENGIRIM GAMBAR DAN VIDEO"; +"settings_mark_all_as_read" = "Tandai semua pesan sebagai terbaca"; +"room_resource_usage_limit_reached_message_contact_3" = " untuk menambahkan batas ini."; +"room_resource_limit_exceeded_message_contact_3" = " untuk melanjutkan menggunakan perangkat ini."; +"room_event_action_ban_prompt_reason" = "Alasan untuk mencekal pengguna ini"; +"room_event_action_kick_prompt_reason" = "Alasan untuk mengeluarkan pengguna ini"; +"room_event_action_report_prompt_reason" = "Alasan untuk melaporkan konten ini"; +"room_message_unable_open_link_error_message" = "Tidak dapat membuka tautan ini."; +"directory_search_results_more_than" = ">%tu hasil ditemukan untuk %@"; +"directory_search_results" = "%tu hasil ditemukan untuk %@"; +"room_creation_invite_another_user" = "ID Pengguna, nama atau email"; +"space_participants_action_ban" = "Cekal dari space ini"; +"space_participants_action_remove" = "Keluarkan dari space ini"; +"leave_space_only_action" = "Jangan tinggalkan ruangan apapun"; +"space_beta_announce_title" = "Space akan segera datang"; + +// Mark: - Spaces + +"space_feature_unavailable_title" = "Space belum ada disini"; + +// MARK: - Invite friends + +"invite_friends_action" = "Undang teman-teman ke %@"; + +// MARK: - Favourites + +"favourites_empty_view_title" = "Ruangan dan orang favorit"; + +// MARK: - Home + +"home_empty_view_title" = "Selamat datang di %@,\n%@"; + +// MARK: - Searchable Directory View Controller + +"searchable_directory_create_new_room" = "Buat sebuah ruangan baru"; + +// MARK: - Major update + +"major_update_title" = "Riot sekarang adalah %@"; +"secrets_reset_warning_title" = "Jika Anda mengatur ulang semua"; +"secrets_setup_recovery_passphrase_summary_title" = "Simpan Frasa Sandi Anda"; + +// Recovery passphrase + +"secrets_setup_recovery_passphrase_title" = "Atur sebuah Frasa Sandi"; + +// MARK: - Secrets set up + +// Recovery Key + +"secrets_setup_recovery_key_title" = "Simpan Kunci Keamanan Anda"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "gunakan Kunci Kemanan anda"; +"user_verification_session_details_verify_action_current_user_manually" = "Verifikasi dengan Teks Secara Manual"; +"user_verification_start_information_part1" = "Untuk keamanan lebih, verifikasi "; +"key_verification_scan_confirmation_scanning_device_waiting_other" = "Menunggu untuk perangkat lainnya…"; + +// Incoming key verification request + +"key_verification_incoming_request_incoming_alert_message" = "%@ ingin memverifikasi"; +"file_upload_error_unsupported_file_type_message" = "Tipe file tidak didukung."; + +// MARK: Manually Verify Device + +"key_verification_manually_verify_device_title" = "Verifikasi dengan Teks Secara Manual"; +"device_verification_error_cannot_load_device" = "Tidak dapat memuat informasi sesi."; +"key_verification_new_session_title" = "Verifikasi sesi baru Anda"; +"sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Mulai menggunakan Cadangan Aman"; +"secure_key_backup_setup_intro_use_security_passphrase_title" = "Gunakan sebuah Frasa Keamanan"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "gunakan Kunci Kemanan Anda"; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Saya telah membuat sebuah salinan"; +"key_backup_setup_passphrase_passphrase_invalid" = "Coba menambahkan sebuah kata"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Mulai menggunakan Cadangan Kunci"; + +// Intro + +"key_backup_setup_intro_title" = "Jangan kehilangan pesan terenkripsi"; +"secure_key_backup_setup_intro_use_security_key_title" = "Gunakan sebuah Kunci Keamanan"; +"deactivate_account_informations_part2_emphasize" = "Aksi ini tidak dapat diurungkan."; +"service_terms_modal_policy_checkbox_accessibility_hint" = "Periksa untuk menerima %@"; +"widget_integration_missing_user_id" = "Tidak ada user_id di permintaan."; +"widget_integration_missing_room_id" = "Tidak ada room_id di permintaan."; +"widget_integration_failed_to_send_request" = "Gagal untuk mengirim permintaan."; +"widget_integration_unable_to_create" = "Tidak dapat membuat widget."; +"widget_menu_revoke_permission" = "Hilangkan akses ke saya"; +"widget_creation_failure" = "Pembuatan widget gagal"; + +// Widget +"widget_no_integrations_server_configured" = "Tidak ada server integrasi yang diatur"; +"room_does_not_exist" = "%@ tidak ada"; +"do_not_ask_again" = "Jangan tanya lagi"; +"public_room_section_title" = "Ruangan Publik (di %@):"; +"event_formatter_jitsi_widget_removed_by_you" = "Anda menghilangkan konferensi VoIP"; +"event_formatter_jitsi_widget_added_by_you" = "Anda menambahkan konferensi VoIP"; +"event_formatter_rerequest_keys_part2" = " dari sesi Anda lainnya."; +"directory_server_all_native_rooms" = "Semua ruangan Matrix asli"; +"room_details_unset_main_address" = "Atur Ulang sebagai Alamat Utama"; +"room_details_set_main_address" = "Atur sebagai Alamat Utama"; +"room_details_advanced_e2e_encryption_enabled_for_dm" = "Enkripsi diaktifkan di sini"; +"room_details_flair_section" = "Tampilkan bakat untuk komunitas"; +"room_details_history_section" = "Siapa saja yang dapat membaca sejarah?"; +"room_details_access_section_directory_toggle_for_dm" = "Daftarkan di direktori ruangan"; +"room_details_access_section_for_dm" = "Siapa saja yang dapat mengakses?"; +"identity_server_settings_place_holder" = "Masukkan sebuah server identitas"; +"settings_show_NSFW_public_rooms" = "Tampilkan ruangan publik NSFW"; +"settings_identity_server_no_is" = "Tidak ada server identitas yang diatur"; +"settings_discovery_three_pid_details_enter_sms_code_action" = "Masukkan kode aktivasi SMS"; +"settings_key_backup_button_create" = "Mulai menggunakan Cadangan Kunci"; +"settings_key_backup_info_progress_done" = "Semua kunci telah dicadangkan"; +"settings_key_backup_info_progress" = "Mencadangkan %@ kunci…"; +"settings_key_backup_info_version" = "Versi Cadangan Kunci: %@"; +"settings_fail_to_update_password" = "Gagal untuk memperbarui kata sandi"; +"settings_labs_enable_ringing_for_group_calls" = "Dering untuk panggilan grup"; +"settings_enable_push_notif" = "Notifikasi di perangkat ini"; +"settings_fail_to_update_profile" = "Gagal untuk memperbarui profil"; +"settings_email_address_placeholder" = "Masukkan alamat email Anda"; +"settings_flair" = "Tampilkan bakat dimana yang diizinkan"; +"settings_config_user_id" = "Masuk sebagai %@"; +"settings_config_identity_server" = "Server identitas adalah %@"; + +// Unknown devices +"unknown_devices_alert_title" = "Ruangan berisi sesi yang tidak dikenal"; +"room_resource_limit_exceeded_message_contact_2_link" = "hubungi administrator anda"; +"room_replacement_link" = "Obrolan ini berlanjut di sini."; +"room_action_send_photo_or_video" = "Kirim foto atau video"; +"room_action_camera" = "Ambil foto atau video"; +"room_unsent_messages_notification" = "Pesan gagal untuk dikirim."; +"encrypted_room_message_reply_to_placeholder" = "Kirim sebuah balasan terenkripsi…"; +"encrypted_room_message_placeholder" = "Kirim sebuah pesan terenkripsi…"; +"room_message_reply_to_placeholder" = "Kirim sebuah balasan (tidak terenkripsi)…"; +"room_message_placeholder" = "Kirim sebuah pesan (tidak terenkripsi)…"; +"room_member_power_level_custom_in" = "Kustom (%@) di %@"; +"room_participants_action_set_default_power_level" = "Atur ulang ke pengguna normal"; +"room_participants_action_ban" = "Cekal dari ruangan ini"; +"room_participants_action_remove" = "Keluarkan dari ruangan ini"; +"contacts_address_book_no_identity_server" = "Tidak ada server identitas yang diatur"; +"directory_search_fail" = "Gagal untuk mendapatkan data"; + +// Rooms tab +"room_directory_no_public_room" = "Tidak ada ruangan publik yang tersedia"; +"room_creation_make_public_prompt_title" = "Buat obrolan ini publik?"; +"room_creation_public_room" = "Obrolan ini publik"; +"room_creation_private_room" = "Obrolan ini privat"; +"social_login_button_title_sign_up" = "Daftar dengan %@"; +"social_login_button_title_sign_in" = "Masuk dengan %@"; +"auth_autodiscover_invalid_response" = "Respons penemuan homeserver tidak valid"; +"pin_protection_settings_section_header_with_biometrics" = "PIN & %@"; +"service_terms_modal_table_header_integration_manager" = "SYARAT PENGELOLA INTEGRASI"; +"service_terms_modal_table_header_identity_server" = "SYARAT SERVER IDENTITAS"; +"event_formatter_call_missed_video" = "Panggilan video tidak dijawab"; +"event_formatter_call_missed_voice" = "Panggilan video tidak dijawab"; +"event_formatter_call_active_video" = "Panggilan video aktif"; +"event_formatter_call_active_voice" = "Panggilan suara aktif"; +"event_formatter_call_incoming_video" = "Panggilan video masuk"; +"event_formatter_call_incoming_voice" = "Panggilan suara masuk"; + +// Room Notification Settings +"room_notifs_settings_notify_me_for" = "Beritahu saya untuk"; +"security_settings_secure_backup_restore" = "Pulihkan dari Cadangan"; +"settings_contacts_enable_sync" = "Cari kontak Anda"; +"settings_show_url_previews" = "Tampilkan tampilan website"; +"settings_new_keyword" = "Tambahkan Keyword baru"; +"settings_messages_containing_display_name" = "Nama tampilan saya"; +"settings_encrypted_group_messages" = "Pesan grup terenkripsi"; +"settings_encrypted_direct_messages" = "Pesan langsung terenkripsi"; +"settings_notify_me_for" = "Beritahu saya untuk"; +"settings_mentions_and_keywords" = "Sebutan dan Keyword"; +"find_your_contacts_button_title" = "Cari kontak Anda"; +"call_incoming_voice" = "Panggilan masuk…"; +"widget_picker_manage_integrations" = "Kelola integrasi…"; +"e2e_room_key_request_start_verification" = "Mulai verifikasi…"; + +// Recover from private key +"key_backup_recover_from_private_key_info" = "Memulihkan cadangan…"; +"version_check_modal_action_title_deprecated" = "Pelajari lebih lanjut"; +"user_avatar_view_accessibility_hint" = "Ubah avatar pengguna"; +"space_avatar_view_accessibility_hint" = "Ubah avatar space"; +"space_public_join_rule" = "Space publik"; +"space_private_join_rule" = "Space privat"; +"space_home_show_all_rooms" = "Tampilkan semua ruangan"; +"spaces_invites_coming_soon_title" = "Undangan segera datang"; +"spaces_coming_soon_title" = "Segera datang"; +"spaces_no_result_found_title" = "Tidak ada hasil"; +"spaces_explore_rooms" = "Jelajahi ruangan"; +"leave_space_title" = "Tinggalkan %@"; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Tambahkan sebuah topik"; +"room_avatar_view_accessibility_hint" = "Ubah avatar ruangan"; +"call_transfer_error_message" = "Gagal memindahkan panggilan"; +"create_room_section_header_topic" = "Topik ruangan (opsional)"; +"searchable_directory_search_placeholder" = "Nama atau ID"; +"biometrics_cant_unlocked_alert_message_login" = "Masuk kembali"; +"biometrics_cant_unlocked_alert_title" = "Tidak dapat membuka kunci aplikasi"; +"biometrics_setup_subtitle" = "Hemat waktu Anda"; +"pin_protection_mismatch_error_message" = "Mohon coba lagi"; +"pin_protection_mismatch_error_title" = "PIN tidak cocok"; +"pin_protection_forgot_pin" = "Lupa PIN"; +"pin_protection_enter_pin" = "Masukkan PIN Anda"; +"pin_protection_confirm_pin" = "Konfirmasi PIN Anda"; + +// MARK: - Cross-signing + +// Banner + +"cross_signing_setup_banner_title" = "Siapkan enkripsi"; +"secrets_setup_recovery_key_storage_alert_title" = "Simpan dengan aman"; +"secrets_recovery_with_key_recovery_key_placeholder" = "Masukkan Kunci Keamanan"; +"secrets_recovery_with_passphrase_passphrase_placeholder" = "Masukkan Frasa Keamanan"; +"user_verification_start_waiting_partner" = "Menunggu untuk %@…"; +"key_verification_scan_confirmation_scanning_user_waiting_other" = "Menunggu untuk %@…"; +"key_verification_verify_qr_code_start_emoji_action" = "Verifikasi dengan emoji"; +"key_verification_verify_qr_code_scan_code_action" = "Pindai kodenya"; + +// MARK: QR code + +"key_verification_verify_qr_code_title" = "Verifikasi dengan memindai"; +"key_verification_tile_conclusion_warning_title" = "Sign in tidak dipercayai"; +"emoji_picker_places_category" = "Tempat Wisata"; +"emoji_picker_people_category" = "Smiley & Orang"; +"emoji_picker_foods_category" = "Makanan & Minuman"; +"emoji_picker_nature_category" = "Hewan & Alam"; +"key_verification_verified_new_session_title" = "Sesi baru telah verifikasi!"; +"key_verification_verify_sas_cancel_action" = "Mereka tidak cocok"; +"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Gunakan Kunci Keamanan"; +"device_verification_self_verify_wait_new_sign_in_title" = "Verifikasi login ini"; + +// Current session + +"key_verification_self_verify_current_session_alert_title" = "Verifikasi sesi ini"; +"device_verification_start_use_legacy_action" = "Gunakan Verifikasi Warisan"; + +// Mark: Incoming +"device_verification_incoming_title" = "Permintaan Verifikasi Masuk"; +"key_verification_this_session_title" = "Verifikasi sesi ini"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Masukkan Kunci Keamanan"; +"key_backup_recover_invalid_recovery_key_title" = "Kunci Keamanan Tidak Cocok"; +"key_backup_recover_invalid_passphrase_title" = "Frasa Sandi Tidak Benar"; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Buat sebuah Salinan"; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Simpan Kunci Keamanan"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "frasa tidak cocok"; +"key_backup_setup_intro_manual_export_action" = "Ekspor kunci secara manual"; +"key_backup_setup_skip_alert_title" = "Apakah Anda yakin?"; + + +// Cancel + +"secure_key_backup_setup_cancel_alert_title" = "Apakah Anda yakin?"; +"deactivate_account_informations_part3" = "\n\nMenonaktifkan akun Anda: "; +"service_terms_modal_information_title_integration_manager" = "Pengelola Integrasi"; + +// Alert explaining what an identity server / integration manager is. +"service_terms_modal_information_title_identity_server" = "Server Identitas"; +"e2e_room_key_request_share_without_verifying" = "Bagikan tanpa memverifikasi"; + +// Room key request dialog +"e2e_room_key_request_title" = "Permintaan kunci enkripsi"; +"room_widget_permission_user_id_permission" = "ID pengguna Anda"; +"room_widget_permission_avatar_url_permission" = "URL avatar Anda"; +"room_widget_permission_display_name_permission" = "Nama tampilan Anda"; +"widget_menu_remove" = "Hapus untuk semuanya"; +"widget_menu_open_outside" = "Buka di browser"; +"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Tambahkan satu sekarang?"; +"bug_report_background_mode" = "Lanjutkan di latar belakang"; +"e2e_key_backup_wrong_version_button_wasme" = "Itu adalah saya"; + +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Cadangan Kunci Baru"; +"call_no_stun_server_error_use_fallback_button" = "Coba menggunakan %@"; +"call_incoming_video" = "Panggilan video masuk…"; +"event_formatter_group_call_incoming" = "%@ di %@"; +"event_formatter_rerequest_keys_part1_link" = "Minta ulang kunci enkripsi"; + +// Events formatter +"event_formatter_member_updates" = "%tu perubahan keanggotaan"; +"directory_server_picker_title" = "Pilih sebuah direktori"; +"image_picker_action_library" = "Pilih dari perpustakaan"; + +// Read Receipts +"read_receipts_list" = "Daftar Laporan Dibaca"; + +// Group rooms +"group_rooms_filter_rooms" = "Filter ruangan komunitas"; +"group_participants_filter_members" = "Filter anggota komunitas"; +"room_notifs_settings_account_settings" = "Pengaturan akun"; +"room_notifs_settings_all_messages" = "Semua Pesan"; +"room_details_copy_room_url" = "Salid URL Ruangan"; +"room_details_copy_room_address" = "Salin Alamat Ruangan"; +"room_details_copy_room_id" = "Salin ID Ruangan"; +"room_details_addresses_disable_main_address_prompt_title" = "Peringatan alamat utama"; +"room_details_addresses_invalid_address_prompt_title" = "Format alias tidak valid"; +"room_details_new_address" = "Tambahkan alamat baru"; +"identity_server_settings_alert_disconnect_title" = "Putuskan server identitas"; +"identity_server_settings_alert_change_title" = "Ubah server identitas"; +"manage_session_trusted" = "Dipercayai oleh Anda"; +"security_settings_export_keys_manually" = "Ekspor kunci secara manual"; +"settings_discovery_three_pid_details_cancel_email_validation_action" = "Batalkan validasi email"; +"settings_discovery_three_pid_details_title_phone_number" = "Kelola nomor telepon"; +"settings_key_backup_button_restore" = "Pulihkan dari Cadangan"; +"settings_deactivate_my_account" = "Nonaktifkan akun saya"; +"settings_add_3pid_password_title_msidsn" = "Tambahkan nomor telepon"; +"settings_add_3pid_password_title_email" = "Tambahkan alamat email"; +"settings_term_conditions" = "Syarat & Ketentuan"; +"settings_olm_version" = "Versi Olm %@"; +"settings_labs_voice_messages" = "Pesan suara"; +"settings_ui_theme_picker_title" = "Pilih sebuah tema"; +"settings_your_keywords" = "Pesan suara"; +"settings_room_upgrades" = "Tingkatan ruangan"; +"settings_call_invitations" = "Undangan panggilan"; +"settings_room_invitations" = "Undangan ruangan"; +"settings_messages_containing_user_name" = "Nama pengguna saya"; +"settings_group_messages" = "Pesan grup"; +"settings_direct_messages" = "Pesan langsung"; +"settings_default" = "Notifikasi Default"; +"settings_notifications_disabled_alert_title" = "Notifikasi dinonaktifkan"; +"settings_show_decrypted_content" = "Tampilkan konten terdekripsi"; +"settings_device_notifications" = "Notifikasi perangkat"; +"settings_add_phone_number" = "Tambahkan nomor telepon"; +"settings_add_email_address" = "Tambahkan alamat email"; +"settings_sign_out_confirmation" = "Apakah Anda yakin?"; +"settings_phone_contacts" = "KONTAK PONSEL"; +"settings_config_home_server" = "Homeserver adalah %@"; +"settings_config_no_build_info" = "Tidak ada info build"; +"account_logout_all" = "Keluar dari semua akun"; +"room_title_one_active_member" = "%@/%@ anggota aktif"; +"room_title_multiple_active_members" = "%@/%@ anggota aktif"; +"room_multiple_typing_notification" = "%@ dan lainnya"; +"external_link_confirmation_title" = "Cek ulang tautan ini"; +"room_event_failed_to_send" = "Gagal untuk mengirim"; +"room_event_action_delete_confirmation_title" = "Hapus pesan yang belum terkirim"; +"room_event_action_view_decrypted_source" = "Tampilkan Sumber Yang Terdekripsi"; +"room_delete_unsent_messages" = "Hapus pesan yang belum terkirim"; +"room_resend_unsent_messages" = "Kirim ulang pesan yang belum terkirim"; +"room_unsent_messages_cancel_title" = "Hapus pesan yang belum terkirim"; +"room_message_reply_to_short_placeholder" = "Kirim sebuah balasan…"; +"room_message_short_placeholder" = "Kirim sebuah pesan…"; +"room_message_replying_to" = "Membalas ke %@"; +"room_one_user_is_typing" = "%@ sedang mengetik…"; +"room_new_messages_notification" = "%d pesan baru"; +"room_new_message_notification" = "%d pesan baru"; +"room_accessiblity_scroll_to_bottom" = "Scroll ke bawah"; +"room_jump_to_first_unread" = "Arahkan ke belum dibaca"; +"room_member_power_level_moderator_in" = "Moderator di %@"; +"room_member_power_level_admin_in" = "Admin di %@"; +"room_participants_action_start_video_call" = "Mulai panggilan video"; +"room_participants_action_start_voice_call" = "Mulai panggilan suara"; +"room_participants_action_start_new_chat" = "Mulai obrolan baru"; +"room_participants_action_leave" = "Tinggalkan ruangan ini"; +"room_participants_filter_room_members" = "Filter anggota ruangan"; +"contacts_user_directory_offline_section" = "DIREKTORI PENGGUNA (offline)"; +"contacts_address_book_permission_denied_alert_title" = "Kontak dinonaktifkan"; +"contacts_address_book_no_contact" = "Tidak ada kontak lokal"; +"contacts_address_book_matrix_users_toggle" = "Hanya pengguna Matrix"; +"directory_search_results_title" = "Jelajahi hasil direktori"; +"room_recents_join_room_title" = "Bergabung ke sebuah ruangan"; +"room_recents_suggested_rooms_section" = "RUANGAN YANG DISARANKAN"; +"room_creation_appearance_picture" = "Gambar obrolan (opsional)"; +"social_login_button_title_continue" = "Lanjut dengan %@"; +"auth_softlogout_clear_data_sign_out_title" = "Apakah Anda yakin?"; +"auth_softlogout_clear_data_button" = "Bersihkan semua data"; +"auth_softlogout_clear_data" = "Bersihkan data personal"; +"auth_softlogout_signed_out" = "Anda telah keluar"; +"version_check_modal_action_title_supported" = "Mengerti"; +"voice_message_lock_screen_placeholder" = "Pesan suara"; +"voice_message_remaining_recording_time" = "%@s keluar"; +"side_menu_app_version" = "Versi %@"; +"side_menu_action_invite_friends" = "Undang teman"; + +// Mark: - Side menu + +"side_menu_reveal_action_accessibility_label" = "Panel kiri"; +"room_intro_cell_information_room_with_topic_sentence2" = "Topik: %@"; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Tambahkan orang"; +"call_transfer_dialpad" = "Tombol penyetel"; + +// MARK: - Dial Pad +"dialpad_title" = "Tombol penyetel"; +"room_info_list_several_members" = "%@ anggota"; + +// MARK: - Room Info + +"room_info_list_one_member" = "1 anggota"; +"create_room_section_header_address" = "Alamat ruangan"; +"create_room_type_public" = "Ruangan Publik"; +"create_room_type_private" = "Ruangan Privat"; +"create_room_section_header_type" = "Tipe ruangan"; +"create_room_enable_encryption" = "Aktifkan Enkripsi"; +"create_room_section_header_encryption" = "Enkripsi ruangan"; +"create_room_section_header_name" = "Nama ruangan"; + +// MARK: - Create Room + +"create_room_title" = "Ruangan Baru"; +"searchable_directory_x_network" = "Jaringan %@"; +"biometrics_desetup_disable_button_title_x" = "Nonaktifkan %@"; +"biometrics_desetup_title_x" = "Nonaktifkan %@"; +"biometrics_setup_enable_button_title_x" = "Aktifkan %@"; +"biometrics_setup_title_x" = "Aktifkan %@"; +"biometrics_settings_enable_x" = "Aktifkan %@"; +"biometrics_mode_face_id" = "Face ID"; + +// MARK: - Biometrics Protection + +"biometrics_mode_touch_id" = "Touch ID"; +"pin_protection_settings_change_pin" = "Ubah PIN"; +"pin_protection_settings_enable_pin" = "Aktifkan PIN"; +"pin_protection_settings_enabled_forced" = "PIN diaktifkan"; +"pin_protection_reset_alert_title" = "Atur Ulang PIN"; + +// MARK: - PIN Protection + +"pin_protection_choose_pin_welcome_after_login" = "Selamat datang kembali."; +"major_update_done_action" = "Mengerti"; +"major_update_learn_more_action" = "Pelajari lebih lanjut"; + +// MARK: - Secrets reset + +"secrets_reset_title" = "Atur ulang semuanya"; +"secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Konfirmasi frasa"; +"secrets_recovery_with_key_recover_action" = "Gunakan Kunci"; + +// Recover with key + +"secrets_recovery_with_key_title" = "Kunci Keamanan"; +"secrets_recovery_with_passphrase_recover_action" = "Gunakan Frasa"; + +// Recover with passphrase + +"secrets_recovery_with_passphrase_title" = "Frasa Keamanan"; +"secrets_recovery_reset_action_part_2" = "Atur ulang semuanya"; +"user_verification_session_details_verify_action_other_user" = "Verifikasi secara manual"; +"user_verification_session_details_verify_action_current_user" = "Verifikasi Secara Interaktif"; +"user_verification_session_details_information_trusted_other_user_part2" = " memverifikasinya:"; +"user_verification_session_details_untrusted_title" = "Tidak Dipercayai"; +"user_verification_sessions_list_session_untrusted" = "Tidak dipercayai"; + +// MARK: - User verification + +// Start + +"user_verification_start_verify_action" = "Mulai verifikasi"; + +// Scanned +"key_verification_scan_confirmation_scanned_title" = "Hampir selesai!"; +"key_verification_verify_qr_code_scan_other_code_success_title" = "Kode tervalidasi!"; +"key_verification_verify_qr_code_cannot_scan_action" = "Tidak dapat memindai?"; +"key_verification_tile_request_status_accepted" = "Anda menerimanya"; +"key_verification_tile_request_status_cancelled" = "%@ membatalkannya"; +"key_verification_tile_request_status_cancelled_by_me" = "Anda membatalkannya"; +"key_verification_tile_request_status_data_loading" = "Memuat data…"; +"key_verification_tile_request_outgoing_title" = "Verifikasi terkirim"; + +// Tiles + +"key_verification_tile_request_incoming_title" = "Permintaan verifikasi"; + +// MARK: File upload +"file_upload_error_title" = "Unggahan file"; +"device_verification_emoji_light bulb" = "Bolham Lampu"; +"device_verification_emoji_thumbs up" = "Jempol"; +"device_verification_verified_got_it_button" = "Mengerti"; +"key_verification_manually_verify_device_key_title" = "Kunci sesi"; +"key_verification_manually_verify_device_id_title" = "ID Sesi"; +"key_verification_manually_verify_device_name_title" = "Nama sesi"; +"key_verification_verify_sas_validate_action" = "Mereka cocok"; +"key_verification_verify_sas_title_number" = "Bandingkan nomor"; + +// MARK: Verify + +"key_verification_verify_sas_title_emoji" = "Bandingkan emoji"; + +// MARK: Self verification wait + +"device_verification_self_verify_wait_title" = "Keamanan lengkap"; +"device_verification_self_verify_start_verify_action" = "Mulai verifikasi"; +"device_verification_start_verify_button" = "Mulai Memverifikasi"; +"key_verification_user_title" = "Verifikasi mereka"; + +// MARK: - Device Verification +"key_verification_other_session_title" = "Verifikasi sesi"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Saya akan tunggu"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Keluar"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Keluar"; + +// Success + +"key_backup_recover_success_info" = "Cadangan Terpulihkan!"; +"key_backup_recover_from_passphrase_recover_action" = "Buka Kunci Riwayat"; +"key_backup_recover_from_recovery_key_recover_action" = "Buka Kunci Riwayat"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Masukkan Frasa"; + +// MARK: Key backup recover + +"key_backup_recover_title" = "Pesan Aman"; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Kunci Keamanan"; +"key_backup_setup_passphrase_set_passphrase_action" = "Atur Frasa"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Konfirmasi frasa"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Masukkan frasa"; + + +// MARK: Key backup setup + +"key_backup_setup_title" = "Cadangan Kunci"; + +// Banner + +"secure_backup_setup_banner_title" = "Cadangan Aman"; +"secure_key_backup_setup_existing_backup_error_delete_it" = "Hapus"; +"secure_key_backup_setup_existing_backup_error_unlock_it" = "Buka kuncinya"; + +// MARK: Secure backup setup + +// Intro + +"secure_key_backup_setup_intro_title" = "Cadangan Aman"; + +// Re-request confirmation dialog +"rerequest_keys_alert_title" = "Permintaan Terkirim"; +"deactivate_account_password_alert_title" = "Nonaktifkan Akun"; +"deactivate_account_validate_action" = "Nonaktifkan akun"; + +// Deactivate account + +"deactivate_account_title" = "Nonaktifkan Akun"; +"gdpr_consent_not_given_alert_review_now_action" = "Lihat sekarang"; +"e2e_room_key_request_ignore_request" = "Tolak permintaan"; +"room_widget_permission_room_id_permission" = "ID Ruangan"; +"room_widget_permission_widget_id_permission" = "ID Widget"; +"room_widget_permission_theme_permission" = "Tema Anda"; + +// Room widget permissions +"room_widget_permission_title" = "Muat Widget"; +"bug_report_progress_uploading" = "Mengunggah laporan"; +"bug_report_progress_zipping" = "Mengumpulkan log"; +"bug_report_send_screenshot" = "Kirim tangkapan layar"; +"bug_report_send_logs" = "Kirim log"; +"bug_crash_report_title" = "Laporan Crash"; + +// Bug report +"bug_report_title" = "Laporan Bug"; +"deactivate_account_password_alert_message" = "Untuk melanjutkan, mohon masukkan kata sandi Anda"; +"widget_integration_must_be_in_room" = "Anda tidak berada di ruangan ini."; +"settings_devices_description" = "Nama publik sesi dapat dilihat oleh orang yang berkomunikasi dengan Anda"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Apakah Anda yakin? Anda akan kehilangan pesan terenkripsi jika kunci Anda tidak dicadangkan secara benar."; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Cadangan memiliki tanda tangan yang tidak valid dari %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Cadangan mempunyai tanda tangan yang tidak valid dari %@"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Cadangan mempunyai tanda tangan yang valid dari %@"; +"settings_key_backup_info_trust_signature_valid" = "Cadangan mempunyai tanda tangan yang valid dari sesi ini"; +"settings_key_backup_info_trust_signature_unknown" = "Cadangan mempunyai tanda tangan dari sesi dengan ID: %@"; +"settings_key_backup_info_not_valid" = "Sesi ini tidak mencadangkan kunci Anda, tetapi Anda memiliki cadangan yang ada yang dapat Anda pulihkan dan tambahkan untuk selanjutnya."; +"settings_key_backup_info_valid" = "Sesi ini mencadangkan kunci Anda."; +"settings_key_backup_info_signout_warning" = "Cadangkan kunci Anda sebelum keluar untuk mencegah kehilangannya."; +"settings_key_backup_info_none" = "Kunci Anda tidak dicadangkan dari sesi ini."; +"settings_key_backup_info" = "Pesan terenkripsi diamankan dengan enkripsi ujung-ke-ujung. Hanya Anda dan penerima punya kuncinya untuk membaca pesannya."; +"settings_labs_e2e_encryption_prompt_message" = "Untuk menyelesaikan enkripsi Anda harus masuk lagi."; +"settings_contacts_enable_sync_description" = "Ini akan menggunakan server identitas Anda untuk menghubung Anda dengan kontak Anda, dan membantunya untuk menemukan Anda."; +"settings_show_url_previews_description" = "Pratinjau akan ditampilkan di ruangan yang tidak dienkripsi."; +"settings_ui_theme_picker_message_invert_colours" = "\"Otomatis\" menggunakan pengaturan \"Balikkan Warna\" perangkat Anda"; +"settings_ui_theme_picker_message_match_system_theme" = "\"Otomatis\" mencocokkan dengan tema sistem perangkat Anda"; +"settings_calls_stun_server_fallback_description" = "Izinkan server panggilan %@ cadangan saat server homeserver Anda tidak menawarkannya (alamat IP Anda akan dibagikan selama panggilan)."; +"settings_mentions_and_keywords_encryption_notice" = "Anda tidak akan dapat notifikasi untuk sebutan & keyword di ruangan terenkripsi di ponsel."; +"settings_notifications_disabled_alert_message" = "Untuk mengaktifkan notifikasi, pergi ke pengaturan perangkat Anda."; +"settings_global_settings_info" = "Pengaturan notifikasi global tersedia di klien web %@ Anda"; +"settings_confirm_media_size_description" = "Saat ini aktif, Anda akan diminta untuk mengkonfirmasi ukuran gambar dan video yang akan dikirim."; +"settings_remove_phone_prompt_msg" = "Apakah Anda yakin untuk menghapus nomor telepon %@?"; +"settings_remove_email_prompt_msg" = "Apakah Anda yakin untuk menghapus alamat email %@?"; +"room_preview_try_join_an_unknown_room" = "Anda mencoba untuk mengakses %@. Apakah Anda ingin bergabung untuk ikut dengan obrolannya?"; +"room_preview_subtitle" = "Ini adalah pratinjau dari ruangan ini. Interaksi ruangan telah dinonaktifkan."; + +// Room Preview +"room_preview_invitation_format" = "Anda telah diundang untuk bergabung ke ruangan ini oleh %@"; +"external_link_confirmation_message" = "Tautan %@ akan membawa Anda ke situs yang lain: %@\n\nApakah Anda yakin untuk melanjutkan?"; +"room_no_privileges_to_create_group_call" = "Anda harus menjadi sebuah admin atau moderator untuk memulai sebuah panggilan."; +"room_resource_usage_limit_reached_message_2" = "beberapa pengguna tidak dapat masuk."; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Server rumah ini telah melampaui batas Pengguna Aktif Bulanannya, jadi "; +"room_resource_usage_limit_reached_message_1_default" = "Homeserver ini telah melampaui salah satu batas sumber dayanya, jadi "; +"room_predecessor_information" = "Ruangan ini adalah lanjutan dari obrolan lain."; +"room_replacement_information" = "Ruangan ini telah diganti dan tidak aktif lagi."; +"room_event_action_delete_confirmation_message" = "Apakah Anda yakin untuk menghapus pesan yang tidak terkirim ini?"; +"room_event_action_report_prompt_ignore_user" = "Apakah Anda ingin menyembunyikan semua pesan dari pengguna ini?"; +"room_conference_call_no_power" = "Anda membutuhkan izin untuk mengelola panggilan konferensi di ruangan ini"; +"room_ongoing_conference_call_with_close" = "Panggilan konferensi berjalan. Bergabung sebagai %@ atau %@. %@ dia."; +"room_ongoing_conference_call" = "Panggilan konferensi berjalan. Bergabung sebagai %@ atau %@."; +"room_unsent_messages_cancel_message" = "Apakah Anda yakin untuk menghapus semua pesan yang tidak terkirim di ruangan ini?"; +"room_unsent_messages_unknown_devices_notification" = "Pesan gagal dikirim karena sesi yang tidak dikenal yang ada."; +"room_offline_notification" = "Koneksi ke server telah hilang."; +"room_do_not_have_permission_to_post" = "Anda tidak memiliki izin untuk mengirim ke ruangan ini"; + +// Chat +"room_slide_to_end_group_call" = "Geser untuk mengakhiri panggilan untuk semuanya"; +"room_participants_security_information_room_not_encrypted" = "Pesan di ruangan ini tidak dienkripsi secara ujung-ke-ujung."; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Tidak ada server identitas yang diatur, jadi Anda tidak dapat mengobrol dengan sebuah kontak menggunakan email."; +"room_participants_invite_malformed_id" = "ID cacat. Seharusnya sebuah alamat email atau ID Matrix seperti '@pengguna:domain'"; +"room_participants_invite_another_user" = "Cari/Undang dengan ID Pengguna, Nama atau email"; +"room_participants_invite_prompt_msg" = "Apakah Anda yakin untuk mengundang %@ ke obrolan ini?"; +"room_participants_remove_third_party_invite_prompt_msg" = "Apakah Anda yakin untuk menghapus undangan ini?"; +"room_participants_remove_prompt_msg" = "Apakah Anda yakin untuk mengeluarkan %@ dari obrolan ini?"; +"room_participants_leave_prompt_msg_for_dm" = "Apakah Anda yakin Anda ingin keluar?"; +"room_participants_leave_prompt_msg" = "Apakah Anda yakin untuk meninggalkan ruangan ini?"; +"find_your_contacts_identity_service_error" = "Tidak dapat menghubung ke server identitasnya."; +"find_your_contacts_footer" = "Ini dapat dinonaktifkan di pengaturan kapan saja."; +"find_your_contacts_message" = "Izinkan %@ untuk menampilkan kontak Anda supaya Anda dapat mengobrol dengan orang yang Anda tahu dengan cepat."; +"contacts_address_book_permission_denied_alert_message" = "Untuk mengaktifkan kontak, pergi ke pengaturan perangkat Anda."; +"contacts_address_book_permission_denied" = "Anda tidak mengizinkan %@ untuk mengakses kontak lokal Anda"; +"search_people_placeholder" = "Cari dengan ID Pengguna, Nama atau email"; +"rooms_empty_view_information" = "Ruangan baik untuk obrolan grup apa saja, privat atau publik. Ketuk + untuk menambahkan ruangan yang sudah ada, atau buat yang baru."; +"people_empty_view_information" = "Obrol dengan aman dengan siapa saja. Ketuk + untuk mulai menambahkan orang."; +"room_recents_unknown_room_error_message" = "Tidak dapat menemukan ruangan ini. Pastikan ruangannya sudah ada"; +"room_recents_join_room_prompt" = "Masukkan ID ruangan atau alias ruangan"; +"room_creation_dm_error" = "Kami tidak dapat membuat DM Anda. Mohon cek ulang pengguna yang Anda ingin undang dan coba lagi."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Tidak ada server identitas yang diatur, jadi Anda tidak dapat menambahkan anggota dengan email."; +"room_creation_wait_for_creation" = "Sebuah ruangan telah dibuat. Mohon tunggu."; +"room_creation_make_public_prompt_msg" = "Apakah Anda ingin membuat obrolan ini publik? Siapa saja dapat membaca pesan Anda dan bergabung ke obrolan ini."; + +// Errors +"error_user_already_logged_in" = "Sepertinya Anda mencoba untuk menghubungkan ke homeserver yang lain. Apakah Anda ingin keluar?"; +"auth_softlogout_clear_data_message_2" = "Hapuslah jika Anda selesai menggunakan perangkat ini, atau ingin masuk ke akun yang lain."; +"auth_softlogout_clear_data_message_1" = "Peringatan: Data personal Anda (termasuk kunci enkripsi) masih disimpan di perangkat ini."; +"auth_softlogout_reason" = "Admin homeserver (%1$@) telah mengeluarkan Anda dari akun %2$@ Anda (%3$@)."; +"auth_accept_policies" = "Harap tinjau dan setujui kebijakan homeserver ini:"; +"widget_integration_positive_power_level" = "Tingkat daya harus bilangan bulat yang positif."; +"settings_integrations_allow_description" = "Gunakan sebuah pengelola integrasi (%@) untuk mengelola bot, jembatan, widget, dan paket stiker.\n\nPengelola integrasi mendapatkan data pengaturan, dan dapat mengubah widget, mengirim undangan ruangan dan mengatur tingkat daya dengan pengetahuan Anda."; +"widget_integrations_server_failed_to_connect" = "Gagal untuk menghubungkan ke server integrasi"; +"call_no_stun_server_error_title" = "Panggilan gagal karena server yang salah konfigurasinya"; +"call_jitsi_error" = "Gagal untuk bergabung ke panggilan konferensi."; +"homeserver_connection_lost" = "Tidak dapat menghubungkan ke homeservernya."; +"room_details_save_changes_prompt" = "Apakah Anda ingin menyimpan perubahannya?"; +"room_details_fail_to_update_room_canonical_alias" = "Gagal untuk memperbarui alamat utama"; +"room_details_fail_to_update_room_communities" = "Gagal untuk memperbarui komunitas terkait"; +"room_details_fail_to_remove_room_aliases" = "Gagal untuk menghapus alamat-alamat ruangan"; +"room_details_fail_to_update_history_visibility" = "Gagal untuk memperbarui visibilitas sejarah"; +"room_details_fail_to_update_room_join_rule" = "Gagal untuk memperbarui aturan bergabung"; +"room_details_fail_to_update_room_name" = "Gagal untuk memperbarui nama ruangannya"; +"room_details_fail_to_update_avatar" = "Gagal untuk memperbarui foto ruangannya"; +"room_details_advanced_e2e_encryption_enabled" = "Enkripsi diaktifkan di ruangan ini"; +"room_details_new_flair_placeholder" = "Tambahkan ID komunitas baru (mis. +foo%@)"; +"room_details_no_local_addresses" = "Ruangan ini tidak memiliki alamat lokal"; +"room_details_history_section_members_only_since_invited" = "Anggota saja (sejak mereka diundang)"; +"room_details_access_section_directory_toggle" = "Daftarkan ruangan ini ke direkori ruangan"; +"room_details_access_section_invited_only" = "Hanya orang yang diundang"; +"identity_server_settings_alert_disconnect" = "Lepaskan hubungan dari server identitas %@?"; +"security_settings_blacklist_unverified_devices" = "Jangan kirimkan pesan ke sesi yang tidak dipercayai"; +"security_settings_crosssigning_info_not_bootstrapped" = "Penandatanganan silang belum disiapkan."; +"settings_key_backup_button_connect" = "Hubungkan sesi ini ke Cadangan Kunci"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Cadangan memiliki tanda tangan dari %@"; +"settings_add_3pid_password_message" = "Untuk melanjutkan, mohon masukkan kata sandi Anda"; +"settings_send_crash_report" = "Kirim crash & data penggunaan anonim"; +"secure_key_backup_setup_cancel_alert_message" = "Jika Anda membatalkan sekarang, Anda mungkin kehilangan pesan & data terenkripsi jika Anda kehilangan akses ke login Anda.\n\nAnda juga dapat mengatur Cadangan Aman & kelola kunci Anda di Pengaturan."; +"room_participants_security_information_room_encrypted" = "Pesan di ruangan ini dienkripsi secara ujung-ke-ujung.\n\nPesan Anda diamankan dengan kunci dan hanya Anda dan penerima punya kunci uniknya untuk membukanya."; +"settings_callkit_info" = "Terima panggilan masuk di layar kunci Anda. Lihat panggilan %@ Anda di riwayat panggilan sistem. Jika iCloud diaktifkan, riwayat panggilannya akan dibagikan dengan Apple."; +"settings_three_pids_management_information_part1" = "Kelola alamat email dan nomor telepon apa saja Anda dapat gunakan untuk masuk atau memulihkan akun Anda di sini. Atur siapa saja yang dapat menemukan Anda di "; +"settings_sign_out_e2e_warn" = "Anda akan kehilangan kunci enkripsi ujung-ke-ujung Anda. Ini berarti Anda tidak akan lagi dapat membaca pesan lama di ruangan terenkripsi di perangkat ini."; +"room_participants_security_information_room_encrypted_for_dm" = "Pesan di pesan langsung ini dienkripsi secara ujung-ke-ujung.\n\nPesan Anda diamankan dengan kunci dan hanya Anda dan penerima punya kunci uniknya untuk membukanya."; +"auth_softlogout_clear_data_sign_out_msg" = "Apakah Anda yakin ingin menghapus semua data yang saat ini tersimpan di perangkat ini? Masuk lagi untuk mengakses data dan pesan akun Anda."; +"auth_softlogout_recover_encryption_keys" = "Masuk untuk memulihkan kunci enkripsi yang disimpan secara eksklusif di perangkat ini. Anda membutuhkannya untuk membaca semua pesan aman Anda di perangkat apa saja."; +"version_check_modal_subtitle_deprecated" = "Kami telah berupaya meningkatkan %@ untuk pengalaman yang lebih cepat dan lebih halus. Sayangnya versi iOS Anda saat ini tidak kompatibel dengan beberapa perbaikan tersebut dan tidak akan didukung lagi.\nKami menyarankan Anda untuk meningkatkan sistem operasi Anda untuk menggunakan %@ secara maksimal."; +"version_check_modal_subtitle_supported" = "Kami telah berupaya meningkatkan %@ untuk pengalaman yang lebih cepat dan lebih halus. Sayangnya versi iOS Anda saat ini tidak kompatibel dengan beberapa perbaikan tersebut dan tidak akan didukung lagi.\nKami menyarankan Anda untuk meningkatkan sistem operasi Anda untuk menggunakan %@ secara maksimal."; +"space_feature_unavailable_information" = "Space adalah cara baru untuk mengelompokkan ruangan dan pengguna.\n\nMereka akan segera datang. Untuk saat ini, jika Anda bergabung sebuah space di platform lain, Anda akan dapat mengakses ruang mana saja yang Anda ikuti di sini."; + +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Kunci Anda sedang dicadangkan.\n\nKunci Keamanan Anda adalah jaring pengaman - Anda dapat menggunakannya untuk memulihkan akses ke pesan terenkripsi jika Anda lupa frasa sandi.\n\nSimpan Kunci Keamanan Anda di suatu tempat yang sangat aman, seperti pengelola kata sandi (atau brankas)."; +"key_backup_setup_passphrase_info" = "Kami akan menyimpan salinan terenkripsi dari kunci Anda di server kami. Lindungi cadangan Anda dengan frasa agar tetap aman.\n\nUntuk keamanan maksimum, ini harus berbeda dari kata sandi akun Anda."; +"key_backup_setup_intro_info" = "Pesan di ruang terenkripsi diamankan dengan enkripsi ujung-ke-ujung. Hanya Anda dan penerima yang memiliki kunci untuk membaca pesan ini.\n\nCadangkan kunci Anda dengan aman untuk menghindari kehilangannya."; +"deactivate_account_informations_part5" = "Jika Anda ingin kami melupakan pesan Anda, silakan centang kotak di bawah ini\n\nVisibilitas pesan di Matrix mirip dengan email. Kami melupakan pesan Anda berarti bahwa pesan yang telah Anda kirim tidak akan dibagikan dengan pengguna baru atau tidak terdaftar, tetapi pengguna terdaftar yang sudah memiliki akses ke pesan ini akan tetap memiliki akses ke salinannya."; +"deactivate_account_informations_part1" = "Ini akan membuat akun Anda tidak dapat digunakan secara permanen. Anda tidak akan dapat masuk, dan tidak seorang pun dapat mendaftarkan ulang ID pengguna yang sama. Ini akan menyebabkan akun Anda meninggalkan semua ruangan yang diikutinya, dan akan menghapus detail akun Anda dari server identitas Anda. "; +"e2e_need_log_in_again" = "Anda harus masuk kembali untuk membuat kunci enkripsi ujung-ke-ujung untuk sesi ini dan mengirimkan kunci publik ke homeserver Anda.\nIni hanya dilakukan sekali saja; maaf untuk ketidaknyamanannya."; +"call_no_stun_server_error_message_2" = "Atau, Anda dapat mencoba menggunakan server publik di %@, tetapi ini tidak akan dapat diandalkan, dan alamat IP Anda akan dibagikan dengan server tersebut. Anda juga dapat mengelola ini di Pengaturan"; +"identity_server_settings_alert_disconnect_still_sharing_3pid" = "Anda masih membagikan data personal Anda di server identitas %@.\n\nKami mensarankan Anda untuk menghapus alamat email dan nomor telepon Anda dari server identitasnya sebelum memutuskan hubungannya."; +"security_settings_crosssigning_info_trusted" = "Penandatanganan silang diaktifkan. Anda dapat mempercayai pengguna lain dan sesi lain Anda berbasis penandatanganan silang tetapi Anda tidak dapat menandatangani sesi ini karena tidak memiliki kunci privat penandatanganan silang. Keamanan lengkap sesi ini."; +"settings_discovery_three_pids_management_information_part1" = "Kelola alamat email atau nomor telepon apa saja yang pengguna lain dapat menggunakan untuk menemukan Anda dan menggunakannya untuk mengundang Anda ke ruangan. Tambahkan atau hapus alamat email atau nomor telepon dari daftar ini di "; +"room_preview_unlinked_email_warning" = "Undangan ini telah dikirim ke %@, yang tidak diasosiasikan dengan akun ini. Anda mungkin ingin masuk ke akun yang lain, atau tambahkan email ini ke akun Anda."; +"unknown_devices_alert" = "Ruangan ini berisi sesi tidak dikenal yang belum diverifikasi.\nIni berarti tidak ada jaminan bahwa sesi tersebut adalah milik pengguna yang mereka klaim.\nKami menyarankan Anda memverifikasinya untuk setiap sesi sebelum melanjutkan, tetapi Anda dapat mengirim ulang pesan tanpa memverifikasi jika Anda mau."; +"room_warning_about_encryption" = "Enkripsi ujung-ke-ujung masih dalam beta dan mungkin tidak dapat dihandalkan.\n\nAnda seharusnya tidak mempercayainya dulu untuk mengamankan data.\n\nPerangkat masih belum dapat mendekripsi sejarah sebelum mereka bergabung ke ruangannya.\n\nPesan terenkripsi masih belum terlihat di client yang belum mengimplementasikan enkripsi."; +"auth_add_email_and_phone_warning" = "Pendaftaran dengan email dan nomor telepon sekaligus belum didukung sampai API-nya sudah ada. Hanya nomor telepon yang akan diperhitungkan. Anda dapat menambahkan email Anda di profil Anda di pengaturan."; +"auth_reset_password_success_message" = "Kata sandi Anda telah diatur ulang.\n\nAnda telah dikeluarkan dari semua sesi dan tidak akan menerima lagi notifikasi push. Untuk mengaktifkan ulang notifikasi, masuk ulang di setiap perangkat."; +"spaces_add_rooms_coming_soon_title" = "Penambahan ruangan akan segera datang"; +"leave_space_and_all_rooms_action" = "Tinggalkan semua ruangan dan space"; +"space_beta_announce_subtitle" = "Versi baru dari komunitas"; +"room_intro_cell_information_room_sentence1_part1" = "Ini adalah awal dari "; +"create_room_section_footer_encryption" = "Enkripsi tidak dapat dinonaktifkan setelah ini."; +"pin_protection_confirm_pin_to_change" = "Konfirmasi PIN untuk mengubah PIN"; +"pin_protection_confirm_pin_to_disable" = "Konfirmasi PIN untuk menonaktifkan PIN"; +"pin_protection_choose_pin" = "Buat sebuah PIN untuk keamanan"; +"cross_signing_setup_banner_subtitle" = "Verifikasi perangkat Anda yang lain dengan mudah"; +"secrets_setup_recovery_passphrase_additional_information" = "Jangan menggunakan kata sandi akun Anda."; +"secrets_recovery_with_key_invalid_recovery_key_title" = "Tidak dapat mengakses penyimpanan rahasia"; +"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Tidak dapat mengakses penyimpanan rahasia"; + +// MARK: Scan confirmation + +// Scanning +"key_verification_scan_confirmation_scanning_title" = "Hampir selesai! Menunggu untuk konfirmasi…"; +"key_verification_verify_qr_code_scan_code_other_device_action" = "Pindai dengan perangkat ini"; +"key_verification_verify_qr_code_emoji_information" = "Verifikasi dengan membandingkan emoji unik."; + +// Device + +"device_verification_verify_wait_partner" = "Menunggu lainnya untuk menerima…"; +"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Gunakan Frasa Sandi atau Kunci"; + +// Unverified sessions + +"key_verification_self_verify_unverified_sessions_alert_title" = "Lihat dimana Anda masuk"; + +// MARK: Self verification start + +// New login +"device_verification_self_verify_alert_title" = "Pemasukan baru. Apakah ini Anda?"; +"device_verification_start_wait_partner" = "Menunggu untuk lainnya untuk menerima…"; +"room_widget_permission_creator_info_title" = "Widget ini ditambahkan oleh:"; +"widget_integration_room_not_visible" = "Ruangan %@ tidak terlihat."; +"widget_integration_room_not_recognised" = "Ruangan ini tidak diketahui."; +"call_incoming_video_prompt" = "Panggilan video masuk dari %@"; + +// Call +"call_incoming_voice_prompt" = "Panggilan suara masuk dari %@"; +"event_formatter_widget_removed_by_you" = "Anda menghapus widget ini: %@"; + +// Events formatter with you +"event_formatter_widget_added_by_you" = "Anda menambahkan widget ini: %@"; +"event_formatter_call_has_ended_with_time" = "Panggilan berakhir • %@"; +"event_formatter_jitsi_widget_removed" = "Konferensi VoIP dihapus oleh %@"; +"event_formatter_jitsi_widget_added" = "Konferensi VoIP ditambahkan oleh %@"; +"event_formatter_widget_removed" = "Widget %@ dihapus oleh %@"; +"event_formatter_widget_added" = "Widget %@ ditambahkan oleh %@"; +"directory_server_all_rooms" = "Semua ruangan di server %@"; +"room_notifs_settings_mentions_and_keywords" = "Sebutan dan Keyword saja"; +"room_details_fail_to_update_topic" = "Gagal untuk memperbarui topiknya"; +"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Enkripsi ke sesi terverifikasi saja"; +"room_details_advanced_e2e_encryption_disabled_for_dm" = "Enkripsi tidak diaktifkan di sini."; +"room_details_new_address_placeholder" = "Tambahkan alamat baru (mis. #foo%@)"; +"room_details_no_local_addresses_for_dm" = "Ini tidak ada alamat lokal"; +"room_details_history_section_members_only_since_joined" = "Anggota saja (sejak mereka bergabung)"; +"room_details_access_section" = "Siapa saja yang dapat mengakses ruangan ini?"; +"manage_session_sign_out" = "Keluar dari sesi ini"; +"security_settings_crosssigning_info_ok" = "Penandatanganan silang siap dipakai."; +"settings_discovery_error_message" = "Sebuah kesalahan terjadi. Mohon coba lagi."; +"settings_crypto_blacklist_unverified_devices" = "Enkripsi ke sesi terverifikasi saja"; +"settings_password_updated" = "Kata sandi Anda telah diperbarui"; +"settings_enable_rageshake" = "Rage shake untuk melaporkan bug"; + +// No VoIP support +"no_voip_title" = "Panggilan masuk"; +"event_formatter_group_call" = "Panggilan grup"; +"event_formatter_call_end_call" = "Akhiri panggilan"; +"event_formatter_call_back" = "Panggil balik"; +"event_formatter_call_connection_failed" = "Koneksi gagal"; +"event_formatter_call_you_declined" = "Panggilan ditolak"; +"event_formatter_call_has_ended" = "Panggilan berakhir"; + +// Image picker +"image_picker_action_camera" = "Ambil foto"; + +// Media picker +"media_picker_title" = "Perpustakaan media"; +"group_participants_invite_malformed_id_title" = "Kesalahan Undangan"; +"group_participants_leave_prompt_title" = "Tinggalkan grup"; + +// Group participants +"group_participants_add_participant" = "Tambahkan peserta"; +"group_home_multi_rooms_format" = "%tu ruangan"; +"group_home_one_room_format" = "1 ruangan"; +"group_home_multi_members_format" = "%tu anggota"; + +// Group Home +"group_home_one_member_format" = "1 anggota"; + +// Group Details +"group_details_title" = "Detail Komunitas"; +"room_event_action_forward" = "Teruskan"; From 7e00cac79fac25fd9f59b132c389a0c85f5b0cc0 Mon Sep 17 00:00:00 2001 From: jelv Date: Sun, 24 Oct 2021 12:58:47 +0000 Subject: [PATCH 023/122] Translated using Weblate (Dutch) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ --- Riot/Assets/nl.lproj/Vector.strings | 34 +++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 2389ac4af..46b7042b7 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -77,7 +77,7 @@ "auth_missing_phone" = "Telefoonnummer ontbreekt"; "auth_missing_email_or_phone" = "E-mailadres of telefoonnummer ontbreekt"; "auth_password_dont_match" = "De wachtwoorden komen niet overeen"; -"auth_username_in_use" = "De gebruikersnaam is al in gebruik"; +"auth_username_in_use" = "Inlognaam al in gebruik"; "auth_forgot_password" = "Wachtwoord vergeten?"; "auth_use_server_options" = "Aangepaste serverinstellingen gebruiken (geavanceerd)"; "auth_email_validation_message" = "Bekijk uw e-mail om verder te gaan met de registratie"; @@ -109,7 +109,7 @@ "room_creation_keep_private" = "Privé houden"; "room_creation_make_private" = "Privé maken"; "room_creation_wait_for_creation" = "Er wordt al een kamer aangemaakt. Even geduld."; -"room_creation_invite_another_user" = "Zoeken/uitnodigen met gebruikers-ID, naam of e-mailadres"; +"room_creation_invite_another_user" = "Persoon-ID, naam of e-mail"; // Room recents "room_recents_directory_section" = "KAMERGIDS"; "room_recents_favourites_section" = "FAVORIETEN"; @@ -261,7 +261,7 @@ "settings_user_settings" = "GEBRUIKERSINSTELLINGEN"; "settings_notifications_settings" = "MELDINGSINSTELLINGEN"; "settings_ignored_users" = "GENEGEERDE GEBRUIKERS"; -"settings_contacts" = "LOKALE CONTACTEN"; +"settings_contacts" = "APPARAAT CONTACTEN"; "settings_advanced" = "GEAVANCEERD"; "settings_other" = "OVERIGE"; "settings_labs" = "EXPERIMENTEEL"; @@ -1371,7 +1371,7 @@ "settings_discovery_three_pids_management_information_part3" = "."; "settings_discovery_three_pids_management_information_part2" = "Gebruikersinstellingen"; "settings_discovery_three_pids_management_information_part1" = "Beheer e-mailadressen en telefoonnummers die andere personen kunnen gebruiken om u te vinden en u uit te nodigen voor kamers. E-mailadressen of telefoonnummers toevoegen of verwijderen van deze lijst kan in "; -"settings_discovery_terms_not_signed" = "Aanvaard de gebruikersvoorwaarden van de identiteitsserver (%@) om vindbaar te zijn op e-mailadres of telefoonnummer."; +"settings_discovery_terms_not_signed" = "Aanvaard de voorwaarden van de identiteitsserver (%@) om vindbaar te zijn op e-mailadres of telefoonnummer."; "settings_discovery_no_identity_server" = "U gebruikt momenteel geen identiteitsserver. Om door de u bekende contacten vindbaar te zijn, voeg er een toe."; "settings_devices_description" = "De publieke naam van een sessie is zichtbaar voor de personen waarmee u communiceert"; "settings_add_3pid_invalid_password_message" = "Ongeldig wachtwoord"; @@ -1606,3 +1606,29 @@ "spaces_suggested_room" = "Aanbevolen"; "done" = "Klaar"; "open" = "Openen"; +"space_home_show_all_rooms" = "Alle kamers tonen"; +"service_terms_modal_information_description_integration_manager" = "Met een integratiebeheerder kunt u functies van derden toevoegen."; +"service_terms_modal_information_description_identity_server" = "Een identiteitsserver helpt u uw contactpersonen te vinden, door hun telefoonnummer of e-mail op te zoeken, om te zien of zij al een account hebben."; +"service_terms_modal_information_title_integration_manager" = "Integratiebeheerder"; + +// Alert explaining what an identity server / integration manager is. +"service_terms_modal_information_title_identity_server" = "Indentiteitsserver"; +"service_terms_modal_description_integration_manager" = "Hiermee kunt u bots, bruggen, widgets en stickerpakketten gebruiken."; +"service_terms_modal_description_identity_server" = "Zo kan iemand u vinden als hij uw telefoonnummer of e-mail in zijn telefooncontacten heeft opgeslagen."; +"service_terms_modal_table_header_integration_manager" = "INTEGRATIEBEHEERDER VOORWAARDEN"; +"service_terms_modal_table_header_identity_server" = "IDENTITEITSSERVER VOORWAARDEN"; +"service_terms_modal_footer" = "Dit kan elk moment worden uitgeschakeld in uw instellingen."; + +// Service terms +"service_terms_modal_title_message" = "Om door te gaan, aanvaard de onderstaande voorwaarden"; +"settings_contacts_enable_sync_description" = "Dit zal uw identiteitsserver gebruiken om u te verbinden met uw contacten, en hen helpen u te vinden."; +"settings_contacts_enable_sync" = "Vind uw contacten"; +"settings_phone_contacts" = "TELEFOON CONTACTEN"; +"room_event_action_forward" = "Doorsturen"; +"find_your_contacts_identity_service_error" = "Kan geen verbinding maken met de identiteitsserver."; +"find_your_contacts_footer" = "Dit kan op elk moment worden uitgeschakeld via de instellingen."; +"find_your_contacts_button_title" = "Vind uw contacten"; +"find_your_contacts_message" = "Laat %@ uw contacten zien, zodat u snel kunt beginnen te chatten met degenen die u het beste kent."; +"find_your_contacts_title" = "Begin met een lijst van uw contacten"; +"contacts_address_book_permission_denied_alert_message" = "Om contacten in te schakelen, ga naar uw apparaatinstellingen."; +"contacts_address_book_permission_denied_alert_title" = "Contacten uitgeschakeld"; From 941938be106989ce7d1d8bcaa251dafaa12da53e Mon Sep 17 00:00:00 2001 From: Finn Behrens Date: Sun, 31 Oct 2021 19:53:57 +0100 Subject: [PATCH 024/122] Remember keyboard language for room This adds a `textInputContextIdentifier` to the RoomViewController to save the current language per room. Signed-off-by: Finn Behrens --- Riot/Modules/Room/RoomViewController.m | 5 +++++ changelog.d/5067.feature | 1 + 2 files changed, 6 insertions(+) create mode 100644 changelog.d/5067.feature diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 6d989d669..9b58f6621 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -2030,6 +2030,11 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; roomInputView.actionsBar.actionItems = actionItems; } +- (NSString *)textInputContextIdentifier +{ + return self.roomDataSource.roomId; +} + - (void)roomInputToolbarViewPresentStickerPicker { // Search for the sticker picker widget in the user account diff --git a/changelog.d/5067.feature b/changelog.d/5067.feature new file mode 100644 index 000000000..53e0a66b5 --- /dev/null +++ b/changelog.d/5067.feature @@ -0,0 +1 @@ +Remember keyboard layout per room and restore it when opening the room again. From 0ded628791fb72af29818fa241d6af44b4fea8d8 Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 1 Nov 2021 19:06:51 +0000 Subject: [PATCH 025/122] Remove duplicate sources for some strings files in Riot/target.yml. --- Riot/target.yml | 6 ------ changelog.d/3908.bugfix | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) create mode 100644 changelog.d/3908.bugfix diff --git a/Riot/target.yml b/Riot/target.yml index 0e9f722da..9775d4b88 100644 --- a/Riot/target.yml +++ b/Riot/target.yml @@ -77,10 +77,7 @@ targets: - path: Assets/ca.lproj/Localizable.strings - path: Assets/ca.lproj/Vector.strings - path: Assets/cy.lproj/InfoPlist.strings - - path: Assets/cy.lproj/InfoPlist.strings - path: Assets/cy.lproj/Localizable.strings - - path: Assets/cy.lproj/Localizable.strings - - path: Assets/cy.lproj/Vector.strings - path: Assets/cy.lproj/Vector.strings - path: Assets/de.lproj/InfoPlist.strings - path: Assets/de.lproj/Localizable.strings @@ -113,10 +110,7 @@ targets: - path: Assets/it.lproj/Localizable.strings - path: Assets/it.lproj/Vector.strings - path: Assets/ja.lproj/InfoPlist.strings - - path: Assets/ja.lproj/InfoPlist.strings - path: Assets/ja.lproj/Localizable.strings - - path: Assets/ja.lproj/Localizable.strings - - path: Assets/ja.lproj/Vector.strings - path: Assets/ja.lproj/Vector.strings - path: Assets/kab.lproj/InfoPlist.strings - path: Assets/kab.lproj/Localizable.strings diff --git a/changelog.d/3908.bugfix b/changelog.d/3908.bugfix new file mode 100644 index 000000000..823ffa095 --- /dev/null +++ b/changelog.d/3908.bugfix @@ -0,0 +1 @@ +Remove duplicate sources for some strings files in Riot/target.yml. \ No newline at end of file From 5dd798fa56938e10c03413234e646b0573ee891b Mon Sep 17 00:00:00 2001 From: Dinh Quang Tuyen Date: Wed, 3 Nov 2021 08:18:02 +0000 Subject: [PATCH 026/122] Translated using Weblate (Vietnamese) Currently translated at 100.0% (48 of 48 strings) Translation: Element iOS/Element iOS (Push) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-push/vi/ --- Riot/Assets/vi.lproj/Localizable.strings | 116 ++++++++++++++++++++--- 1 file changed, 101 insertions(+), 15 deletions(-) diff --git a/Riot/Assets/vi.lproj/Localizable.strings b/Riot/Assets/vi.lproj/Localizable.strings index 34cbdec88..9dc169788 100644 --- a/Riot/Assets/vi.lproj/Localizable.strings +++ b/Riot/Assets/vi.lproj/Localizable.strings @@ -1,5 +1,5 @@ /* New message from a specific person, not referencing a room */ -"MSG_FROM_USER" = "Tin nhắn từ %@"; +"MSG_FROM_USER" = "%@ đã gửi một tin nhắn"; /* New message from a specific person in a named room */ "MSG_FROM_USER_IN_ROOM" = "%@ đã đăng trong %@"; /* New message from a specific person, not referencing a room. Content included. */ @@ -13,36 +13,122 @@ /* New action message from a specific person, not referencing a room. */ "IMAGE_FROM_USER" = "%@ đã gửi bạn một hình ảnh %@"; /* New action message from a specific person in a named room. */ -"IMAGE_FROM_USER_IN_ROOM" = "%@ đã đăng một hình ảnh %@ trong %@"; +"IMAGE_FROM_USER_IN_ROOM" = "%@ đã đăng một ảnh %@ trong %@"; /* Multiple unread messages in a room */ -"UNREAD_IN_ROOM" = "%@ có tin nhắn mới trong %@"; +"UNREAD_IN_ROOM" = "%@ tin nhắn mới trong %@"; /* Multiple unread messages from a specific person, not referencing a room */ -"MSGS_FROM_USER" = "%@ có tin nhắn mới trong %@"; +"MSGS_FROM_USER" = "%@ tin nhắn mới trong %@"; /* Multiple unread messages from two people */ -"MSGS_FROM_TWO_USERS" = "%@ có tin nhắn mới từ %@ và %@"; +"MSGS_FROM_TWO_USERS" = "%@ tin nhắn mới từ %@ và %@"; /* Multiple unread messages from three people */ -"MSGS_FROM_THREE_USERS" = "%@ có tin nhắn mới từ %@, %@ và %@"; +"MSGS_FROM_THREE_USERS" = "%@ tin nhắn mới từ %@, %@ và %@"; /* Multiple unread messages from two plus people (ie. for 4+ people: 'others' replaces the third person) */ -"MSGS_FROM_TWO_PLUS_USERS" = "%@ có tin nhắn mới từ %@, %@ và những người khác"; +"MSGS_FROM_TWO_PLUS_USERS" = "%@ tin nhắn mới từ %@, %@ và những người khác"; /* Multiple messages in two rooms */ -"MSGS_IN_TWO_ROOMS" = "%@ có tin nhắn mới trong %@ và %@"; +"MSGS_IN_TWO_ROOMS" = "%@ tin nhắn mới trong %@ và %@"; /* Look, stuff's happened, alright? Just open the app. */ -"MSGS_IN_TWO_PLUS_ROOMS" = "%@ có tin nhắn mới từ %@, %@ và nhiều hơn nữa"; +"MSGS_IN_TWO_PLUS_ROOMS" = "%@ tin nhắn mới từ %@, %@ và nhiều hơn nữa"; /* A user has invited you to a chat */ -"USER_INVITE_TO_CHAT" = "%@ đã mời bạn tham gia trò chuyện"; +"USER_INVITE_TO_CHAT" = "%@ vừa mời bạn trò chuyện"; /* A user has invited you to an (unamed) group chat */ -"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ đã mời bạn tham gia vào một cuộc trò chuyện nhóm"; +"USER_INVITE_TO_CHAT_GROUP_CHAT" = "%@ vừa mời bạn trò chuyện nhóm"; /* A user has invited you to a named room */ -"USER_INVITE_TO_NAMED_ROOM" = "%@ đã mời bạn tham gia vào %@"; +"USER_INVITE_TO_NAMED_ROOM" = "%@ vừa mời bạn vào %@"; /* Incoming one-to-one voice call */ -"VOICE_CALL_FROM_USER" = "Gọi thoại từ %@"; +"VOICE_CALL_FROM_USER" = "Gọi từ %@"; /* Incoming one-to-one video call */ "VIDEO_CALL_FROM_USER" = "Gọi video từ %@"; /* Incoming unnamed voice conference invite from a specific person */ -"VOICE_CONF_FROM_USER" = "Gọi thoại nhóm từ %@"; +"VOICE_CONF_FROM_USER" = "Gọi nhóm từ %@"; /* Incoming unnamed video conference invite from a specific person */ "VIDEO_CONF_FROM_USER" = "Gọi video nhóm từ %@"; /* Incoming named voice conference invite from a specific person */ -"VOICE_CONF_NAMED_FROM_USER" = "Gọi thoại nhóm từ %@: '%@'"; +"VOICE_CONF_NAMED_FROM_USER" = "Gọi nhóm từ %@: '%@'"; /* Incoming named video conference invite from a specific person */ "VIDEO_CONF_NAMED_FROM_USER" = "Gọi video nhóm từ %@: '%@'"; + +/** Key verification **/ + +"KEY_VERIFICATION_REQUEST_FROM_USER" = "%@ muốn xác minh"; + +/* Group call from user, CallKit caller name */ +"GROUP_CALL_FROM_USER" = "%@ (cuộc gọi nhóm)"; + +/* A user added a Jitsi call to a room */ +"GROUP_CALL_STARTED" = "Cuộc gọi nhóm đã bắt đầu"; + +/* A user's membership has updated in an unknown way */ +"USER_MEMBERSHIP_UPDATED" = "%@ đã cập nhật hồ sơ"; + +/* A user has change their avatar */ +"USER_UPDATED_AVATAR" = "%@ đã đổi avatar"; + +/* A user has change their name to a new name which we don't know */ +"GENERIC_USER_UPDATED_DISPLAYNAME" = "%@ đã đổi tên"; + +/** Membership Updates **/ + +/* A user has change their name to a new name */ +"USER_UPDATED_DISPLAYNAME" = "%@ đã đổi tên sang %@"; + +/* A user has reacted to a message, but the reaction content is unknown */ +"GENERIC_REACTION_FROM_USER" = "%@ đã gửi một tương tác"; + +/** Reactions **/ + +/* A user has reacted to a message, including the reaction e.g. "Alice reacted 👍". */ +"REACTION_FROM_USER" = "%@ đã tương tác %@"; + +/* New message with hidden content due to PIN enabled */ +"MESSAGE_PROTECTED" = "Tin nhắn mới"; + +/* New message indicator on a room */ +"MESSAGE_IN_X" = "Tin nhắn trong %@"; + +/* New message indicator from a DM */ +"MESSAGE_FROM_X" = "Tin nhắn từ %@"; + +/** Notification messages **/ + +/* New message indicator on unknown room */ +"MESSAGE" = "Tin nhắn"; + +/* Sticker from a specific person, not referencing a room. */ +"STICKER_FROM_USER" = "%@ đã gửi một sticker"; + +/* A single unread message */ +"SINGLE_UNREAD" = "Bạn đã nhận một tin nhắn"; + +/* A single unread message in a room */ +"SINGLE_UNREAD_IN_ROOM" = "Bạn đã nhận một tin nhắn trong %@"; + +/* New file message from a specific person, not referencing a room. */ +"FILE_FROM_USER" = "%@ đã gửi một tệp %@"; + +/* New voice message from a specific person, not referencing a room. */ +"VOICE_MESSAGE_FROM_USER" = "%@ đã gửi một tin nhắn thoại"; + +/* New audio message from a specific person, not referencing a room. */ +"AUDIO_FROM_USER" = "%@ đã gửi một tệp âm thanh %@"; + +/* New video message from a specific person, not referencing a room. */ +"VIDEO_FROM_USER" = "%@ đã gửi video"; + +/** Media Messages **/ + +/* New image message from a specific person, not referencing a room. */ +"PICTURE_FROM_USER" = "%@ đã gửi ảnh"; + +/* New message reply from a specific person in a named room. */ +"REPLY_FROM_USER_IN_ROOM_TITLE" = "%@ đã trả lời trong %@"; + +/* New message reply from a specific person, not referencing a room. */ +"REPLY_FROM_USER_TITLE" = "%@ đã trả lời"; + +/** Titles **/ + +/* Message title for a specific person in a named room */ +"MSG_FROM_USER_IN_ROOM_TITLE" = "%@ trong %@"; +/** General **/ + +"NOTIFICATION" = "Thông báo"; From 1a0fa3dc873cc0a9c8498d293a2ff38b13872928 Mon Sep 17 00:00:00 2001 From: Dinh Quang Tuyen Date: Wed, 3 Nov 2021 08:16:15 +0000 Subject: [PATCH 027/122] Translated using Weblate (Vietnamese) Currently translated at 100.0% (6 of 6 strings) Translation: Element iOS/Element iOS (Dialogs) Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios-dialogs/vi/ --- Riot/Assets/vi.lproj/InfoPlist.strings | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Riot/Assets/vi.lproj/InfoPlist.strings b/Riot/Assets/vi.lproj/InfoPlist.strings index 69b136af6..41eb2f4aa 100644 --- a/Riot/Assets/vi.lproj/InfoPlist.strings +++ b/Riot/Assets/vi.lproj/InfoPlist.strings @@ -1,5 +1,7 @@ // Permissions usage explanations -"NSCameraUsageDescription" = "Máy ảnh được sử dụng để chụp ảnh và quay phim, thực hiện các cuộc gọi video thoại."; +"NSCameraUsageDescription" = "Máy ảnh được sử dụng để chụp ảnh và quay phim, thực hiện các cuộc gọi video."; "NSPhotoLibraryUsageDescription" = "Thư viện ảnh được dùng để gửi hình ảnh và videos."; -"NSMicrophoneUsageDescription" = "Microphone được dùng để thực hiện quay video, thực hiện các cuộc gọi."; -"NSContactsUsageDescription" = "Danh bạ được sử dụng để tìm kiếm người dùng bởi email hoặc số điện thoại trên Element."; +"NSMicrophoneUsageDescription" = "Element cần quyền truy cập vào mi-crô của bạn để nhận và thực hiện cuộc gọi, quay video, và ghi âm các tin nhắn thoại."; +"NSContactsUsageDescription" = "Element sẽ hiển thị danh bạ của bạn để bạn có thể mời họ trò chuyện."; +"NSFaceIDUsageDescription" = "Face ID được sử dụng để truy cập vào ứng dụng của bạn."; +"NSCalendarsUsageDescription" = "Xem các cuộc họp đã lên lịch trong ứng dụng."; From c6cf3a65999a6fecd969d549290bc914d90755dd Mon Sep 17 00:00:00 2001 From: Farhad Date: Wed, 3 Nov 2021 12:23:14 +0000 Subject: [PATCH 028/122] Translated using Weblate (Persian) Currently translated at 6.0% (80 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fa/ --- Riot/Assets/fa.lproj/Vector.strings | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Riot/Assets/fa.lproj/Vector.strings b/Riot/Assets/fa.lproj/Vector.strings index 06e5d76d2..d67b98658 100644 --- a/Riot/Assets/fa.lproj/Vector.strings +++ b/Riot/Assets/fa.lproj/Vector.strings @@ -91,3 +91,6 @@ // Titles "title_home" = "خانه"; "store_promotional_text" = "نرم‌افزار چت و همکاری حافظ حریم خصوصی، در یک شبکه باز. غیر متمرکز، جهت واگذاری اختیار کنترل به شما. بدون کندوکاو اطلاعات ، بدون درپشتی و بدون دسترسی شخص ثالث."; +"bug_report_send" = "ارسال"; +"done" = "انجام شد"; +"open" = "باز کردن"; From 8d154ba3e5a30d0621f3219c932534e36019f8e3 Mon Sep 17 00:00:00 2001 From: Dinh Quang Tuyen Date: Wed, 3 Nov 2021 08:09:45 +0000 Subject: [PATCH 029/122] Translated using Weblate (Vietnamese) Currently translated at 93.4% (1243 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/vi/ --- Riot/Assets/vi.lproj/Vector.strings | 1191 ++++++++++++++++++++++++++- 1 file changed, 1180 insertions(+), 11 deletions(-) diff --git a/Riot/Assets/vi.lproj/Vector.strings b/Riot/Assets/vi.lproj/Vector.strings index 0be4ee022..0b1c91386 100644 --- a/Riot/Assets/vi.lproj/Vector.strings +++ b/Riot/Assets/vi.lproj/Vector.strings @@ -67,7 +67,7 @@ "auth_missing_email_or_phone" = "Thiếu địa chỉ email hoặc số điện thoại"; "auth_email_in_use" = "Địa chỉ email này đã được sử dụng"; "auth_phone_in_use" = "Số điện thoại này đã được sử dụng"; -"auth_untrusted_id_server" = "Máy chủ nhận dạng không được tin cậy"; +"auth_untrusted_id_server" = "Máy chủ xác thực không được tin cậy"; "auth_password_dont_match" = "Mật khẩu không trùng khớp"; "auth_username_in_use" = "Tên đăng nhập đang được sử dụng"; "auth_forgot_password" = "Quên mật khẩu?"; @@ -153,12 +153,12 @@ "room_participants_one_participant" = "1 người tham gia"; "room_participants_multi_participants" = "%d người tham gia"; "room_participants_leave_prompt_title" = "Rời phòng"; -"room_participants_leave_prompt_msg" = "Bạn có muốn rời phòng này?"; +"room_participants_leave_prompt_msg" = "Bạn có chắc muốn rời phòng này?"; "room_participants_remove_prompt_title" = "Xác nhận"; "room_participants_remove_prompt_msg" = "Bạn có muốn gỡ bỏ %@ ra khỏi cuộc trò chuyện?"; "room_participants_remove_third_party_invite_msg" = "Gỡ bỏ lời mời của bên thứ ba chưa được hỗ trợ cho tới khi api được thực hiện"; "room_participants_invite_prompt_title" = "Xác nhận"; -"room_participants_invite_prompt_msg" = "Bạn có muốn mời %@ vào cuộc trò chuyện này?"; +"room_participants_invite_prompt_msg" = "Bạn có chắc muốn mời %@ vào cuộc trò chuyện này?"; "room_participants_filter_room_members" = "Lọc thành viên trong phòng"; "room_participants_invite_another_user" = "Tìm / mời bằng ID Người dùng, Tên hoặc Email"; "room_participants_invite_malformed_id_title" = "Lỗi mời"; @@ -199,7 +199,7 @@ "encrypted_room_message_placeholder" = "Gửi tin nhắn đã mã hoá…"; "room_message_short_placeholder" = "Gửi tin nhắn…"; "room_offline_notification" = "Kết nối tới máy chủ thất bại."; -"room_unsent_messages_notification" = "Các tin nhắn chưa được gửi."; +"room_unsent_messages_notification" = "Các tin nhắn gửi thất bại."; "room_unsent_messages_unknown_devices_notification" = "Các tin nhắn chưa được gửi tới các thiết bị không xác định hiện hành."; "room_ongoing_conference_call" = "Cuộc gọi hội nghị đang diễn ra. Tham gia như %@ hoặc %@."; "room_ongoing_conference_call_with_close" = "Cuộc gọi hội nghị đang diễn ra. Tham gia như %@ hoặc %@. %@ nó."; @@ -217,7 +217,7 @@ "room_event_action_permalink" = "Liên kết"; "room_event_action_view_source" = "Xem nguồn"; "room_event_action_report" = "Báo cáo nội dung"; -"room_event_action_report_prompt_reason" = "Lí do báo cáo nội dung"; +"room_event_action_report_prompt_reason" = "Lí do báo cáo nội dung này"; "room_event_action_report_prompt_ignore_user" = "Bạn có muốn ẩn tất cả tin nhắn từ người dùng này?"; "room_event_action_save" = "Lưu"; "room_event_action_resend" = "Gửi lại"; @@ -288,8 +288,8 @@ "settings_enable_push_notif" = "Thông báo trên thiết bị"; "settings_show_decrypted_content" = "Hiện nội dung đã giải mã"; "settings_global_settings_info" = "Cài đặt thông báo toàn cầu khả dụng trên %@ trình duyệt khách của bạn"; -"settings_pin_rooms_with_missed_notif" = "Neo phòng có thông báo bỏ lỡ"; -"settings_pin_rooms_with_unread" = "Neo phòng có tin nhắn chưa đọc"; +"settings_pin_rooms_with_missed_notif" = "Ghim các phòng có thông báo bị bỏ lỡ"; +"settings_pin_rooms_with_unread" = "Ghim các phòng có các tin nhắn chưa đọc"; "settings_enable_callkit" = "Cuộc gọi tích hợp"; "settings_callkit_info" = "Nhận cuộc gọi tới trên màn hình khóa. Xem lịch sử cuộc gọi trong lịch sử cuộc gọi của hệ thống. Nếu iCloud được kích hoạt, lịch sử cuộc gọi sẽ được chia sẻ với Apple."; "settings_ui_language" = "Ngôn ngữ"; @@ -302,9 +302,9 @@ "settings_unignore_user" = "Xem tất cả tin nhắn từ %@?"; "settings_contacts_discover_matrix_users" = "Sử dụng email và số điện thoại để tìm người dùng khác"; "settings_contacts_phonebook_country" = "Quốc gia trong danh bạ"; -"settings_labs_e2e_encryption" = "End-to-End Mã Hóa"; +"settings_labs_e2e_encryption" = "Mã hóa đầu-cuối"; "settings_labs_e2e_encryption_prompt_message" = "Để hoàn thành cài đặt mã hóa, bạn phải đăng nhập lại."; -"settings_labs_create_conference_with_jitsi" = "Tạo cuộc gọi hội họp bằng jitsi"; +"settings_labs_create_conference_with_jitsi" = "Tạo cuộc gọi hội thoại bằng jitsi"; "settings_version" = "Phiên bản %@"; "settings_olm_version" = "Phiên bản Olm %@"; "settings_copyright" = "Bản quyền"; @@ -362,8 +362,8 @@ "room_details_advanced_section" = "Nâng cao"; "room_details_advanced_room_id" = "ID Phòng:"; "room_details_advanced_enable_e2e_encryption" = "Bật mã hóa (cảnh báo: không thể tắt trở lại!)"; -"room_details_advanced_e2e_encryption_enabled" = "Mã hóa được bật cho phòng này"; -"room_details_advanced_e2e_encryption_disabled" = "Mã hóa chưa được bật cho phòng này."; +"room_details_advanced_e2e_encryption_enabled" = "Mã hóa được kích hoạt cho phòng này"; +"room_details_advanced_e2e_encryption_disabled" = "Mã hóa chưa được kích hoạt cho phòng này."; "room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "Chỉ mã hóa cho các thiết bị đã được xác thực"; "room_details_advanced_e2e_encryption_prompt_message" = "End-to-end, mã hoá đang trong giai đoạn thử nghiệm và có thể không đáng tin cậy.\n\nBạn không nên tin tưởng tuyệt đối vào nó về việc bảo mật dữ liệu hoàn toàn.\n\nThiết bị sẽ không thể giải mã lịch sử từ trước khi họ tham gia vào phòng.\n\nMột khi mã hóa được kích hoạt cho một căn phòng nó không thể tắt (cho đến bây giờ).\n\nTin nhắn được mã hóa sẽ không hiển thị trên các máy khách khi chúng chưa được tích hợp mã hoá."; "room_details_fail_to_update_avatar" = "Cập nhật ảnh phòng thất bại"; @@ -459,3 +459,1172 @@ "share_extension_auth_prompt" = "Đăng nhập vào ứng dụng chính để chia sẻ nội dung"; "share_extension_failed_to_encrypt" = "Gửi thất bại. Kiểm tra cài đặt bảo mật phòng trong ứng dụng chính"; "title_groups" = "Cộng đồng"; +"version_check_modal_action_title_deprecated" = "Tìm hiểu cách"; +"version_check_modal_subtitle_deprecated" = "Chúng tôi đã làm việc để nâng cao %@ để có trải nghiệm nhanh hơn và bóng bẩy hơn. Thật không may, phiên bản iOS hiện tại của bạn không tương thích với một số bản sửa lỗi và sẽ không còn được hỗ trợ.\nChúng tôi khuyến nghị bạn nên nâng cấp hệ điều hành của bạn để sử dụng %@ với tất cả tiềm năng của nó."; +"version_check_modal_title_deprecated" = "Chúng tôi không còn hỗ trợ iOS%@"; +"version_check_modal_action_title_supported" = "Đã nhận"; +"version_check_modal_subtitle_supported" = "Chúng tôi đã làm việc để nâng cao %@ để có trải nghiệm nhanh hơn và bóng bẩy hơn. Thật không may, phiên bản iOS hiện tại của bạn không tương thích với một số bản sửa lỗi và sẽ không còn được hỗ trợ.\nChúng tôi khuyến nghị bạn nên nâng cấp hệ điều hành của bạn để sử dụng %@ với tất cả tiềm năng của nó."; +"version_check_modal_title_supported" = "Chúng tôi đang chấm dứt hỗ trợ iOS %@"; +"version_check_banner_subtitle_deprecated" = "Chúng tôi không còn hỗ trợ %@ trên iOS %@. Để tiếp tục sử dụng %@ với đầy đủ tiềm năng của nó, chúng tôi khuyến nghị bạn nên nâng cấp phiên bản iOS của bạn."; +"version_check_banner_title_deprecated" = "Chúng tôi không còn hỗ trợ iOS%@"; +"version_check_banner_subtitle_supported" = "Chúng tôi sẽ sớm chấm dứt hỗ trợ %@ trên iOS %@. Để tiếp tục sử dụng %@ với đầy đủ tiềm năng của nó, chúng tôi khuyến nghị bạn nên nâng cấp phiên bản iOS của bạn."; + +// Mark: - Version check + +"version_check_banner_title_supported" = "Chúng tôi đang chấm dứt hỗ trợ iOS %@"; +"voice_message_lock_screen_placeholder" = "Tin nhắn thoại"; +"voice_message_stop_locked_mode_recording" = "Nhấn vào bản ghi âm của bạn để dừng hoặc nghe"; +"voice_message_remaining_recording_time" = "%@s còn lại"; + +// Mark: - Voice Messages + +"voice_message_release_to_send" = "Giữ để ghi âm, bỏ ra để gửi"; +"side_menu_app_version" = "Phiên bản %@"; +"side_menu_action_feedback" = "Phản hồi"; +"side_menu_action_help" = "Trợ giúp"; +"side_menu_action_settings" = "Cài đặt"; +"side_menu_action_invite_friends" = "Mời bạn bè"; + +// Mark: - Side menu + +"side_menu_reveal_action_accessibility_label" = "Bảng điều khiển trái"; +"user_avatar_view_accessibility_hint" = "Thay đổi avatar người dùng"; + +// Mark: - User avatar view + +"user_avatar_view_accessibility_label" = "avatar"; +"space_avatar_view_accessibility_hint" = "Thay đổi avatar space"; + +// Mark: Avatar + +"space_avatar_view_accessibility_label" = "avatar"; +"space_public_join_rule" = "Space công cộng"; +"space_private_join_rule" = "Space riêng tư"; +"space_participants_action_ban" = "Cấm từ space này"; +"space_participants_action_remove" = "Loại bỏ khỏi space này"; +"spaces_coming_soon_detail" = "Tính năng này chưa được triển khai ở đây, nhưng nó đang được tiến hành. Bây giờ, bạn có thể làm với Element trên máy tính của bạn."; +"spaces_invites_coming_soon_title" = "Mời sắp có"; +"spaces_add_rooms_coming_soon_title" = "Thêm phòng sắp có"; +"spaces_coming_soon_title" = "Sắp có"; +"spaces_no_member_found_detail" = "Tìm kiếm ai đó không có trong %@? Bây giờ, bạn có thể mời họ trên Web hoặc Desktop."; +"spaces_no_room_found_detail" = "Vài kết quả có thể bị ẩn vì chúng riêng tư và bạn cần một lời mời để tham gia vào chúng."; +"spaces_no_result_found_title" = "Không tìm thấy kết quả"; +"spaces_empty_space_detail" = "Vài phòng có thể bị ẩn vì chúng là phòng riêng và bạn cần một lời mời."; +"spaces_empty_space_title" = "Space này chưa có phòng"; +"space_tag" = "space"; +"spaces_suggested_room" = "Đề nghị"; +"spaces_explore_rooms" = "Khám phá phòng"; +"leave_space_and_all_rooms_action" = "Rời tất cả phòng và spaces"; +"leave_space_only_action" = "Không rời phòng nào"; +"leave_space_message_admin_warning" = "Bạn là quản trị viên của space này, chắc chắn là bạn vừa chuyển quyền quản trị cho thành viên khác trước khi rời khỏi."; +"leave_space_message" = "Bạn có chắc muốn rời khỏi %@? Bạn có muốn rời tất cả phòng và spaces của space này?"; +"leave_space_title" = "Rời khỏi %@"; +"spaces_left_panel_title" = "Spaces"; +"spaces_home_space_title" = "Nhà"; +"space_beta_announce_information" = "Spaces là cách mới để nhóm các phòng và người. Chúng chưa có trên iOS, nhưng bạn có thể sử dụng chúng bây giờ trên Web và Desktop."; +"space_beta_announce_subtitle" = "Phiên bản mới của cộng đồng"; +"space_beta_announce_title" = "Spaces sắp có ở đây"; +"space_beta_announce_badge" = "BETA"; +"space_feature_unavailable_information" = "Spaces là cách mới để nhóm các phòng và người.\n\nChúng sẽ sớm có mặt. Bây giờ, nếu bạn tham gia vào một nền tảng khác, bạn sẽ có thể truy cập bất cứ phòng nào bạn tham gia ở đây."; +"space_feature_unavailable_subtitle" = "Spaces chưa có trên iOS, nhưng bạn có thể sử dụng nó bây giờ trên Web và Desktop"; + +// Mark: - Spaces + +"space_feature_unavailable_title" = "Spaces chưa có ở đây"; +"room_intro_cell_information_multiple_dm_sentence2" = "Chỉ có bạn ở trong cuộc trò chuyện này, nếu bạn không mời ai khác tham gia."; +"room_intro_cell_information_dm_sentence2" = "Chỉ có hai người trong cuộc trò chuyện này, không ai khác có thể tham gia."; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_dm_sentence1_part1" = "Đây là khởi đầu của tin nhắn trực tiếp của bạn với "; +"room_intro_cell_information_room_without_topic_sentence2_part2" = " để mọi người biết phòng này là gì."; +"room_intro_cell_information_room_without_topic_sentence2_part1" = "Thêm chủ đề"; +"room_intro_cell_information_room_with_topic_sentence2" = "Chủ đề: %@"; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part1" = "Đây là khởi đầu của "; + +// Mark: - Room creation introduction cell + +"room_intro_cell_add_participants_action" = "Thêm người"; +"room_avatar_view_accessibility_hint" = "Thay đổi avatar phòng"; + +// Mark: - Room avatar view + +"room_avatar_view_accessibility_label" = "avatar"; +"invite_friends_share_text" = "Này, nói với tôi ở %@: %@"; + +// MARK: - Invite friends + +"invite_friends_action" = "Mời bạn bè vào %@"; +"favourites_empty_view_information" = "Bạn có thể yêu thích một số cách - nhanh nhất là nhấn và giữ. Nhấn vào dấu sao và chúng sẽ xuất hiện tự động ở đây để giữ an toàn."; + +// MARK: - Favourites + +"favourites_empty_view_title" = "Các phòng và danh bạ yêu thích"; +"home_empty_view_information" = "Ứng dụng trò chuyển bảo mật tất cả trong một cho các nhóm, bạn và tổ chức. Nhấn nút + bên dưới để thêm người và phòng."; + +// MARK: - Home + +"home_empty_view_title" = "Chào mừng đến %@,\n%@"; +"call_transfer_error_message" = "Chuyển tiếp cuộc gọi thất bại"; +"call_transfer_error_title" = "Lỗi"; +"call_transfer_contacts_all" = "Tất cả"; +"call_transfer_contacts_recent" = "Gần đây"; +"call_transfer_dialpad" = "Bàn phím số"; +"call_transfer_users" = "Các người dùng"; + +// MARK: - Call Transfer +"call_transfer_title" = "Chuyển tiếp"; + +// MARK: - Dial Pad +"dialpad_title" = "Bàn phím số"; +"room_info_list_section_other" = "Khác"; +"room_info_list_several_members" = "%@ thành viên"; + +// MARK: - Room Info + +"room_info_list_one_member" = "1 thành viên"; +"create_room_placeholder_address" = "#testroom:matrix.org"; +"create_room_section_header_address" = "Địa chỉ phòng"; +"create_room_show_in_directory" = "Hiển thị phòng trong thư mục"; +"create_room_section_footer_type" = "Mọi người chỉ tham gia vào phòng riêng bằng lời mời"; +"create_room_type_public" = "Phòng công cộng"; +"create_room_type_private" = "Phòng riêng"; +"create_room_section_header_type" = "Loại phòng"; +"create_room_section_footer_encryption" = "Mã hóa không thể tắt sau này."; +"create_room_enable_encryption" = "Bật mã hóa"; +"create_room_section_header_encryption" = "Mã hóa phòng"; +"create_room_placeholder_topic" = "Chủ đề"; +"create_room_section_header_topic" = "Chủ đề phòng (tùy chọn)"; +"create_room_placeholder_name" = "Tên"; +"create_room_section_header_name" = "Tên phòng"; + +// MARK: - Create Room + +"create_room_title" = "Phòng mới"; +"searchable_directory_search_placeholder" = "Tên hoặc ID"; +"searchable_directory_x_network" = "%@ Mạng"; + +// MARK: - Searchable Directory View Controller + +"searchable_directory_create_new_room" = "Tạo một phòng mới"; +"biometrics_cant_unlocked_alert_message_retry" = "Thử lại"; +"biometrics_cant_unlocked_alert_message_login" = "Đăng nhập lại"; +"biometrics_cant_unlocked_alert_message_x" = "Để mở, sử dụng %@ hoặc đăng nhập lại và bật lại %@"; +"biometrics_cant_unlocked_alert_title" = "Không thể mở ứng dụng"; +"biometrics_usage_reason" = "Việc xác thực là cần thiết để truy cập vào ứng dụng của bạn"; +"biometrics_desetup_disable_button_title_x" = "Tắt %@"; +"biometrics_desetup_title_x" = "Tắt %@"; +"biometrics_setup_subtitle" = "Tiết kiệm thời gian của bạn"; +"biometrics_setup_enable_button_title_x" = "Bật %@"; +"biometrics_setup_title_x" = "Bật %@"; +"biometrics_settings_enable_x" = "Bật %@"; +"biometrics_mode_face_id" = "Face ID"; + +// MARK: - Biometrics Protection + +"biometrics_mode_touch_id" = "Touch ID"; +"pin_protection_kick_user_alert_message" = "Quá nhiều lỗi, bạn vừa bị đăng xuất"; +"pin_protection_explanatory" = "Thiết lập một PIN cho phép bạn bảo vệ dữ liệu, như các tin nhắn và danh bạ, vì vậy chỉ có bạn có thể truy cập vào chúng bằng cách nhập PIN khi ứng dụng bắt đầu."; +"pin_protection_not_allowed_pin" = "Vì các lý do an toàn, PIN này không tồn tại. Vui lòng thử PIN khác"; +"pin_protection_settings_change_pin" = "Thay đổi PIN"; +"pin_protection_settings_enable_pin" = "Kích hoạt PIN"; +"pin_protection_settings_enabled_forced" = "PIN được kích hoạt"; +"pin_protection_settings_section_footer" = "Để đặt lại PIN của bạn, bạn sẽ cần đăng nhập lại và tạo một cái mới"; +"pin_protection_settings_section_header_with_biometrics" = "PIN & %@"; +"pin_protection_settings_section_header" = "PIN"; +"pin_protection_mismatch_too_many_times_error_message" = "Nếu bạn không thể nhớ PIN của bạn, nhấn vào nút quên PIN"; +"pin_protection_mismatch_error_message" = "Vui lòng thử lại"; +"pin_protection_mismatch_error_title" = "Các PIN không khớp"; +"pin_protection_reset_alert_action_reset" = "Đặt lại"; +"pin_protection_reset_alert_message" = "Để đặt lại PIN của bạn, bạn sẽ cần đăng nhập lại và tạo một cái mới"; +"pin_protection_reset_alert_title" = "Đặt lại PIN"; +"pin_protection_forgot_pin" = "Quên PIN"; +"pin_protection_enter_pin" = "Nhập PIN của bạn"; +"pin_protection_confirm_pin_to_change" = "Xác nhận PIN để thay đổi PIN"; +"pin_protection_confirm_pin_to_disable" = "Xác nhận PIN để vô hiệu hóa PIN"; +"pin_protection_confirm_pin" = "Xác nhận PIN của bạn"; +"pin_protection_choose_pin" = "Tạo một PIN để bảo mật"; +"pin_protection_choose_pin_welcome_after_register" = "Chào mừng."; + +// MARK: - PIN Protection + +"pin_protection_choose_pin_welcome_after_login" = "Chào mừng trở lại."; +"major_update_done_action" = "Đã nhận"; +"major_update_learn_more_action" = "Tìm hiểu thêm"; +"major_update_information" = "Chúng tôi vui mừng thông báo rằng chúng tôi vừa thay đổi tên! Ứng dụng của bạn đã được cập nhật và bạn đã đăng nhập vào tài khoản của bạn."; + +// MARK: - Major update + +"major_update_title" = "Bạo loạn bây giờ là %@"; +"cross_signing_setup_banner_subtitle" = "Xác minh các thiết bị khác của bạn dễ dàng hơn"; + +// MARK: - Cross-signing + +// Banner + +"cross_signing_setup_banner_title" = "Thiết lập mã hóa"; +"secrets_reset_authentication_message" = "Nhập mật khẩu tài khoản của bạn để xác nhận"; +"secrets_reset_reset_action" = "Đặt lại"; +"secrets_reset_warning_message" = "Bạn sẽ khởi động lại mà không có lịch sử, tin nhắn, các thiết bị tin cậy hoặc người dùng tin cậy."; +"secrets_reset_warning_title" = "Nếu bạn đặt lại mọi thứ"; +"secrets_reset_information" = "Chỉ làm điều này nếu bạn không có thiết bị khác mà bạn có thể xác minh thiết bị này."; + +// MARK: - Secrets reset + +"secrets_reset_title" = "Đặt lại mọi thứ"; +"secrets_setup_recovery_passphrase_summary_information" = "Nhớ Chuỗi Bảo mật của bạn. Nó có thể được dùng để mở các tin nhắn và dữ liệu mã hóa của bạn."; +"secrets_setup_recovery_passphrase_summary_title" = "Lưu Chuỗi Bảo mật của bạn"; +"secrets_setup_recovery_passphrase_confirm_passphrase_placeholder" = "Xác nhận chuỗi"; +"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "Xác nhận"; +"secrets_setup_recovery_passphrase_confirm_information" = "Nhập lại Chuỗi Bảo mật của bạn để xác nhận nó."; +"secrets_setup_recovery_passphrase_validate_action" = "Hoàn tất"; +"secrets_setup_recovery_passphrase_additional_information" = "Không sử dụng mật khẩu tài khoản của bạn."; +"secrets_setup_recovery_passphrase_information" = "Nhập một chuỗi bảo mật chỉ bạn biết, được sử dụng để bảo mật các bí mật trên máy chủ của bạn."; + +// Recovery passphrase + +"secrets_setup_recovery_passphrase_title" = "Đặt một Chuỗi Bảo mật"; +"secrets_setup_recovery_key_storage_alert_message" = "✓ In nó và lưu trữ nó ở nơi nào đó an toàn\n✓ Lưu nó trong một USB hoặc ổ cứng dự phòng\n✓ Sao chép nó lên kho lưu trữ đám mây cá nhân của bạn"; +"secrets_setup_recovery_key_storage_alert_title" = "Giữ nó an toàn"; +"secrets_setup_recovery_key_done_action" = "Hoàn tất"; +"secrets_setup_recovery_key_export_action" = "Lưu"; +"secrets_setup_recovery_key_loading" = "Đang tải…"; +"secrets_setup_recovery_key_information" = "Lưu Khóa Bảo mật của bạn ở nơi an toàn. Nó có thể được sử dụng để mở các tin nhắn và dữ liệu bảo mật của bạn."; + +// MARK: - Secrets set up + +// Recovery Key + +"secrets_setup_recovery_key_title" = "Lưu Khóa Bảo mật của bạn"; +"secrets_recovery_with_key_invalid_recovery_key_message" = "Vui lòng xác minh rằng bạn đã nhập đúng Khóa Bảo mật."; +"secrets_recovery_with_key_invalid_recovery_key_title" = "Không thể truy cập kho lưu bí mật"; +"secrets_recovery_with_key_recover_action" = "Sử dụng Khóa"; +"secrets_recovery_with_key_recovery_key_placeholder" = "Nhập Khóa Bảo mật"; +"user_verification_session_details_information_untrusted_other_user" = " đã đăng ký sử dụng một thiết bị mới:"; +"user_verification_session_details_information_untrusted_current_user" = "Xác minh thiết bị này để đánh dấu nó là tin tưởng & cấp cho nó quyền truy cập vào các tin nhắn mã hóa:"; +"user_verification_session_details_information_trusted_other_user_part2" = " đã xác minh nó:"; +"user_verification_session_details_information_trusted_other_user_part1" = "Thiết bị này được tin tưởng cho việc nhắn tin bảo mật bởi vì "; +"user_verification_session_details_information_trusted_current_user" = "Thiết bị này được tin tưởng cho việc nhắn tin bảo mật bởi vì bạn đã xác minh nó:"; +"user_verification_session_details_untrusted_title" = "Không tin tưởng"; + +// Session details + +"user_verification_session_details_trusted_title" = "Tin tưởng"; +"user_verification_sessions_list_session_untrusted" = "Không tin tưởng"; +"user_verification_sessions_list_session_trusted" = "Tin tưởng"; +"user_verification_sessions_list_table_title" = "Các thiết bị"; +"user_verification_sessions_list_information" = "Các tin nhắn với người dùng này trong phòng này được mã hóa đầu-cuối và không thể được đọc bởi các bên thứ ba."; +"user_verification_sessions_list_user_trust_level_unknown_title" = "Không biết"; +"user_verification_sessions_list_user_trust_level_warning_title" = "Cảnh báo"; + +// Sessions list + +"user_verification_sessions_list_user_trust_level_trusted_title" = "Tin tưởng"; +"user_verification_start_additional_information" = "Để bảo mật, hãy tự làm hoặc dùng một cách khác để giao tiếp."; +"user_verification_start_waiting_partner" = "Đang chờ %@…"; +"user_verification_start_information_part2" = " bằng việc kiểm tra mã một-lần trên cả 2 thiết bị của bạn."; +"user_verification_start_information_part1" = "Để bảo bật thêm, xác minh "; + +// MARK: - User verification + +// Start + +"user_verification_start_verify_action" = "Bắt đầu xác minh"; +"key_verification_scan_confirmation_scanned_device_information" = "Thiết bị khác có đang hiển thị cùng một lá chắn?"; +"key_verification_scan_confirmation_scanned_user_information" = "%@ có đang hiển thị cùng một lá chắn?"; + +// Scanned +"key_verification_scan_confirmation_scanned_title" = "Sắp xong!"; +"key_verification_scan_confirmation_scanning_device_waiting_other" = "Đang chờ thiết bị khác…"; +"key_verification_scan_confirmation_scanning_user_waiting_other" = "Đang chờ %@…"; + +// MARK: Scan confirmation + +// Scanning +"key_verification_scan_confirmation_scanning_title" = "Sắp xong! Đang chờ xác nhận…"; +"key_verification_verify_qr_code_scan_other_code_success_message" = "Mã QR vừa được xác minh thành công."; +"key_verification_verify_qr_code_scan_other_code_success_title" = "Mã được xác minh!"; +"key_verification_verify_qr_code_other_scan_my_code_title" = "Người dùng khác đã quét mã QR thành công không?"; +"key_verification_verify_qr_code_start_emoji_action" = "Xác minh bằng emoji"; +"key_verification_verify_qr_code_cannot_scan_action" = "Không thể quét?"; +"key_verification_verify_qr_code_scan_code_other_device_action" = "Quét mã bằng thiết bị này"; +"key_verification_verify_qr_code_scan_code_action" = "Quét mã của họ"; +"key_verification_verify_qr_code_emoji_information" = "Xác minh bằng việc so sánh emoji duy nhất."; +"key_verification_verify_qr_code_information_other_device" = "Quét mã bên dưới để xác minh:"; +"key_verification_verify_qr_code_information" = "Quét mã để xác minh một cách bảo mật lẫn nhau."; + +// MARK: QR code + +"key_verification_verify_qr_code_title" = "Xác minh bằng cách quét"; + +// Incoming key verification request + +"key_verification_incoming_request_incoming_alert_message" = "%@ muốn xác minh"; +"key_verification_tile_conclusion_warning_title" = "Đăng nhập không tin tưởng"; +"key_verification_tile_conclusion_done_title" = "Đã xác minh"; +"key_verification_tile_request_incoming_approval_decline" = "Từ chối"; +"key_verification_tile_request_incoming_approval_accept" = "Chấp nhận"; +"key_verification_tile_request_status_accepted" = "Bạn đã chấp nhận"; +"key_verification_tile_request_status_cancelled" = "%@ đã hủy"; +"key_verification_tile_request_status_cancelled_by_me" = "Bạn đã hủy"; +"key_verification_tile_request_status_expired" = "Hết hạn"; +"key_verification_tile_request_status_waiting" = "Đang chờ…"; +"key_verification_tile_request_status_data_loading" = "Đang tải dữ liệu…"; +"key_verification_tile_request_outgoing_title" = "Xác minh được gửi"; + +// Tiles + +"key_verification_tile_request_incoming_title" = "Yêu cầu xác minh"; +"key_verification_bootstrap_not_setup_message" = "Bạn cần phải khởi động xác thực chéo trước."; + +// MARK: - Key Verification + +"key_verification_bootstrap_not_setup_title" = "Lỗi mời"; +"error_not_supported_on_mobile" = "Bạn không thể làm điều này từ di động %@."; + + +// Generic errors +"error_invite_3pid_with_no_identity_server" = "Thêm một máy chủ xác thực trong cài đặt của bạn để mời bằng email."; + +// MARK: Reaction history +"reaction_history_title" = "Các phản ứng"; +"emoji_picker_flags_category" = "Cờ"; +"emoji_picker_symbols_category" = "Biểu tượng"; +"emoji_picker_objects_category" = "Đối tượng"; +"emoji_picker_places_category" = "Du lịch & các địa điểm"; +"emoji_picker_activity_category" = "Các hoạt động"; +"emoji_picker_foods_category" = "Đồ ăn và đồ uống"; +"emoji_picker_nature_category" = "Các động vật & thiên nhiên"; +"emoji_picker_people_category" = "Các mặt cười & con người"; + +// MARK: Emoji picker +"emoji_picker_title" = "Các phản ứng"; +"file_upload_error_unsupported_file_type_message" = "Loại tệp không được hỗ trợ."; + +// MARK: File upload +"file_upload_error_title" = "Tải lên tệp"; +"device_verification_emoji_pin" = "Ghim"; +"device_verification_emoji_folder" = "Thư mục"; +"device_verification_emoji_headphones" = "Tai nghe"; +"device_verification_emoji_anchor" = "Mỏ neo"; +"device_verification_emoji_bell" = "Chuông"; +"device_verification_emoji_trumpet" = "Kèn"; +"device_verification_emoji_guitar" = "Ghi-ta"; +"device_verification_emoji_ball" = "Banh"; +"device_verification_emoji_trophy" = "Cúp"; +"device_verification_emoji_rocket" = "Tên lửa"; +"device_verification_emoji_aeroplane" = "Máy bay"; +"device_verification_emoji_bicycle" = "Xe đạp"; +"device_verification_emoji_train" = "Tàu hỏa"; +"device_verification_emoji_flag" = "Cờ"; +"device_verification_emoji_telephone" = "Điện thoại"; +"device_verification_emoji_hammer" = "Búa"; +"device_verification_emoji_key" = "Chìa khóa"; +"device_verification_emoji_lock" = "Khóa"; +"device_verification_emoji_scissors" = "Kéo"; +"device_verification_emoji_paperclip" = "Kẹp giấy"; +"device_verification_emoji_pencil" = "Bút chì"; +"device_verification_emoji_book" = "Sách"; +"device_verification_emoji_light bulb" = "Bòng đèn tròn"; +"device_verification_emoji_gift" = "Quà"; +"device_verification_emoji_clock" = "Đồng hồ"; +"device_verification_emoji_hourglass" = "Đồng hồ cát"; +"device_verification_emoji_umbrella" = "Cây dù"; +"device_verification_emoji_thumbs up" = "Thích"; +"device_verification_emoji_santa" = "Santa"; +"device_verification_emoji_spanner" = "Spanner"; +"device_verification_emoji_glasses" = "Mắt kiếng"; +"device_verification_emoji_hat" = "Nón"; +"device_verification_emoji_robot" = "Rô-bô"; +"device_verification_emoji_smiley" = "Cười"; +"device_verification_emoji_heart" = "Tim"; +"device_verification_emoji_cake" = "Bánh"; +"device_verification_emoji_pizza" = "Pizza"; +"device_verification_emoji_corn" = "Bắp"; +"device_verification_emoji_strawberry" = "Dâu tây"; +"device_verification_emoji_apple" = "Táo"; +"device_verification_emoji_banana" = "Chuối"; +"device_verification_emoji_fire" = "Lửa"; +"device_verification_emoji_cloud" = "Mây"; +"device_verification_emoji_moon" = "Mặt trăng"; +"device_verification_emoji_globe" = "Địa cầu"; +"device_verification_emoji_mushroom" = "Nấm"; +"device_verification_emoji_cactus" = "Xương rồng"; +"device_verification_emoji_tree" = "Cây"; +"device_verification_emoji_flower" = "Hoa"; +"device_verification_emoji_butterfly" = "Bướm"; +"device_verification_emoji_octopus" = "Bạch tuộc"; +"device_verification_emoji_fish" = "Cá"; +"device_verification_emoji_turtle" = "Rùa"; +"device_verification_emoji_penguin" = "Chim cánh cụt"; +"device_verification_emoji_rooster" = "Gà trống"; +"device_verification_emoji_panda" = "Gấu trúc"; +"device_verification_emoji_rabbit" = "Thỏ"; +"device_verification_emoji_elephant" = "Voi"; +"device_verification_emoji_pig" = "Heo"; +"device_verification_emoji_unicorn" = "Kỳ lân"; +"device_verification_emoji_horse" = "Ngựa"; +"device_verification_emoji_lion" = "Sư tử"; +"device_verification_emoji_cat" = "Mèo"; + +// MARK: Emoji +"device_verification_emoji_dog" = "Chó"; + +// User + +"key_verification_verified_user_information" = "Các tin nhắn với người dùng này được mã hóa đầu-cuối và không thể được đọc bởi các bên thứ ba."; +"key_verification_verified_this_session_information" = "Bạn có thể đọc các tin nhắn bảo mật trên thiết bị này bây giờ, và các người dùng khác sẽ biết họ có thể tin tưởng nó."; +"key_verification_verified_new_session_information" = "Bạn có thể đọc các tin nhắn bảo mật trên thiết bị mới của bạn bây giờ, và các người dùng khác sẽ biết họ có thể tin tưởng nó."; +"key_verification_verified_other_session_information" = "Bạn có thể đọc các tin nhắn bảo mật trên thiết bị khác của bạn bây giờ, và các người dùng khác sẽ biết họ có thể tin tưởng nó."; +"key_verification_verified_new_session_title" = "Thiết bị mới được xác minh!"; +"device_verification_verified_got_it_button" = "Đã nhận được"; + +// MARK: Verified + +// Device + +"device_verification_verified_title" = "Đã xác minh!"; + +// Device + +"device_verification_verify_wait_partner" = "Chờ đối tác chấp nhận…"; +"key_verification_manually_verify_device_validate_action" = "Xác minh"; +"key_verification_manually_verify_device_additional_information" = "Nếu chúng không khớp, sự bảo mật của giao tiếp của bạn có thể bị tổn hại."; +"key_verification_manually_verify_device_key_title" = "Khóa thiết bị"; +"key_verification_manually_verify_device_id_title" = "ID thiết bị"; +"key_verification_manually_verify_device_name_title" = "Tên thiết bị"; +"key_verification_manually_verify_device_instruction" = "Xác nhận bằng việc so sánh điều sau đây với Cài đặt Người dùng trong thiết bị khác của bạn:"; + +// MARK: Manually Verify Device + +"key_verification_manually_verify_device_title" = "Xác minh thủ công bằng văn bản"; +"key_verification_verify_sas_additional_information" = "Để bảo mật tối đa, sử dụng các phương tiện liên lạc tin cậy khác hoặc tự làm điều này."; +"key_verification_verify_sas_validate_action" = "Chúng khớp"; +"key_verification_verify_sas_cancel_action" = "Chúng không khớp"; +"key_verification_verify_sas_title_number" = "So sánh các số"; + +// MARK: Verify + +"key_verification_verify_sas_title_emoji" = "So sánh emoji"; +"device_verification_self_verify_wait_recover_secrets_checking_availability" = "Kiểm tra các khả năng xác minh khác…"; +"device_verification_self_verify_wait_recover_secrets_additional_information" = "Nếu bạn không thể truy cập vào các thiệt bị hiện có"; +"device_verification_self_verify_wait_recover_secrets_with_passphrase" = "Sử dụng Chuỗi hoặc Khóa Bảo mật"; +"device_verification_self_verify_wait_recover_secrets_without_passphrase" = "Sử dụng Khóa Bảo mật"; +"device_verification_self_verify_wait_additional_information" = "Điều này hoạt động với %@ và các thiết bị Matrix đầu cuối khác có khả năng xác thực chéo"; +"device_verification_self_verify_wait_information" = "Xác minh thiết bị này từ một trong các thiết bị của bạn, cấp cho nó quyền truy cập vào các tin nhắn mã hóa.\n\nSử dụng cái %@ mới nhất trên các thiết bị của bạn:"; +"device_verification_self_verify_wait_new_sign_in_title" = "Xác minh đăng nhập này"; + +// MARK: Self verification wait + +"device_verification_self_verify_wait_title" = "Hoàn tất bảo mật"; +"key_verification_self_verify_unverified_sessions_alert_validate_action" = "Xem lại"; +"key_verification_self_verify_unverified_sessions_alert_message" = "Xác minh tất cả các thiết bị của bạn để chắc chắn các tin nhắn và tài khoản của bạn an toàn."; + +// Unverified sessions + +"key_verification_self_verify_unverified_sessions_alert_title" = "Xem lại nơi bạn được đăng nhập vào"; +"key_verification_self_verify_current_session_alert_validate_action" = "Xác minh"; +"key_verification_self_verify_current_session_alert_message" = "Các người dùng khác có thể không tin tưởng nó."; + +// Current session + +"key_verification_self_verify_current_session_alert_title" = "Xác minh thiết bị này"; +"device_verification_self_verify_start_waiting" = "Đang đợi…"; +"device_verification_self_verify_start_information" = "Sử dụng thiết bị này để xác minh thiết bị mới của bạn, cấp cho nó quyền truy cập vào các tin nhắn mã hóa."; +"device_verification_self_verify_start_verify_action" = "Bắt đầu xác minh"; +"device_verification_self_verify_alert_validate_action" = "Xác minh"; +"device_verification_self_verify_alert_message" = "Xác minh thông tin đăng nhập mới truy cập vào tài khoản của bạn: %@"; + +// MARK: Self verification start + +// New login +"device_verification_self_verify_alert_title" = "Đăng nhập mới. Đây có phải là bạn?"; +"device_verification_start_use_legacy_action" = "Sử dụng xác minh kế thừa"; +"device_verification_start_verify_button" = "Bắt đầu xác minh"; +"device_verification_start_use_legacy" = "Không có gì xuất hiện? Không phải tất cả thiết bị đầu cuối đều hỗ trợ xác minh tương tác. Sử dụng xác minh kế thừa."; +"device_verification_start_wait_partner" = "Chờ đối tác chấp nhận…"; + +// MARK: Start +"device_verification_start_title" = "Xác minh bằng việc so sánh một chuỗi văn bản ngắn"; +"device_verification_incoming_description_2" = "Xác minh thiết bị này sẽ đánh dấu nó là tin cậy, và cũng đánh dấu thiết bị của bạn là tin cậy đối với đối tác."; +"device_verification_incoming_description_1" = "Xác minh thiết bị này để đánh dấu nó là tin cậy. Các thiết bị tin cậy của các đối tác giúp bạn yên tâm thêm khi sử dụng các tin nhắn mã hóa đầu-cuối."; + +// Mark: Incoming +"device_verification_incoming_title" = "Yêu cầu xác minh đến"; +"device_verification_error_cannot_load_device" = "Không thể tải thông tin thiết bị."; +"device_verification_cancelled_by_me" = "Việc xác minh vừa bị hủy. Lý do: %@"; +"device_verification_cancelled" = "Bên kia đã hủy việc xác minh."; +"device_verification_security_advice_number" = "So sánh các số, đảm báo chúng xuất hiện theo cùng thứ tự."; +"device_verification_security_advice_emoji" = "So sánh emoji duy nhất, đảm bảo chúng xuất hiện theo cùng thứ tự."; +"key_verification_user_title" = "Xác minh chúng"; +"key_verification_this_session_title" = "Xác minh thiết bị này"; +"key_verification_new_session_title" = "Xác minh thiết bị mới của bạn"; + +// MARK: - Device Verification +"key_verification_other_session_title" = "Xác minh thiết bị"; +"sign_out_key_backup_in_progress_alert_cancel_action" = "Tôi sẽ đợi"; +"sign_out_key_backup_in_progress_alert_discard_key_backup_action" = "Tôi không muốn các tin nhắn mã hóa của tôi"; +"sign_out_key_backup_in_progress_alert_title" = "Sao luu khóa đang tiến hành. Nếu bạn đang xuất bây giờ bạn sẽ mất quyền truy cập vào các tin nhắn mã hóa của bạn."; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Sao lưu"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Đăng xuất"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "Bạn sẽ mất quyền truy cập vào các tin nhắn mã hóa nếu bạn không sao lưu các khóa trước khi đăng xuất"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "Bạn sẽ mất các tin nhắn mã hóa của bạn"; +"sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Tôi không muốn các tin nhắn mã hóa của tôi"; +"sign_out_non_existing_key_backup_alert_setup_secure_backup_action" = "Bắt đầu sử dụng Sao lưu Bảo mật"; +"sign_out_non_existing_key_backup_alert_title" = "Bạn sẽ mất quyền truy cập vào các tin nhắn bảo mật của bạn nếu bạn đăng xuất bây giờ"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Đăng xuất"; + +// MARK: Sign out warning + +"sign_out_existing_key_backup_alert_title" = "Bạn có chắc bạn muốn đăng xuất?"; +"key_backup_recover_done_action" = "Hoàn tất"; + +// Success + +"key_backup_recover_success_info" = "Sao lưu đã khôi phục!"; +"key_backup_recover_from_recovery_key_lost_recovery_key_action" = "Mất Khóa Bảo mật, bạn có thể thiết lập một cái mới trong cài đặt."; +"key_backup_recover_from_recovery_key_recover_action" = "Mở lịch sử"; +"key_backup_recover_from_recovery_key_recovery_key_placeholder" = "Nhập Khóa Bảo mật"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "Nhập"; + +// Recover from recovery key + +"key_backup_recover_from_recovery_key_info" = "Sử dụng Khóa Bảo mật để mở lịch sử tin nhắn bảo mật của bạn"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_passphrase_lost_passphrase_action_part2" = "dùng Khóa Bảo mật của bạn"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part1" = "Không biết Chuỗi Bảo mật của bạn? Bạn có thể "; +"key_backup_recover_from_passphrase_recover_action" = "Mở lịch sử"; +"key_backup_recover_from_passphrase_passphrase_placeholder" = "Nhập chuỗi"; +"key_backup_recover_from_passphrase_passphrase_title" = "Nhập"; + +// Recover from passphrase + +"key_backup_recover_from_passphrase_info" = "Sử dụng Chuỗi Bảo mật để mở lịch sử tin nhắn bảo mật của bạn"; + +// Recover from private key +"key_backup_recover_from_private_key_info" = "Đang khôi phục sao lưu…"; +"key_backup_recover_invalid_recovery_key" = "Sao lưu không thể được giải mã bằng khóa này: vui lòng kiểm tra rằng bạn đã nhập Chuỗi Bảo mật chính xác."; +"key_backup_recover_invalid_recovery_key_title" = "Khóa bảo mật không khớp"; +"key_backup_recover_invalid_passphrase" = "Sao lưu không thể được giải mã bằng chuỗi này: vui lòng kiểm tra rằng bạn đã nhập Chuỗi Bảo mật chính xác."; +"key_backup_setup_success_from_recovery_key_make_copy_action" = "Tạo bản sao"; +"key_backup_setup_success_from_recovery_key_recovery_key_title" = "Khóa bảo mật"; + +// Success from recovery key +"key_backup_setup_success_from_recovery_key_info" = "Các khóa của bạn đang được sao lưu.\n\nLàm một bản sao của khóa bảo mật này và giữ nó an toàn."; +"key_backup_setup_success_from_passphrase_done_action" = "Hoàn tất"; +"key_backup_setup_success_from_passphrase_save_recovery_key_action" = "Lưu khóa bảo mật"; + +// Success from passphrase +"key_backup_setup_success_from_passphrase_info" = "Các khóa của bạn đang được sao lưu.\n\nKhóa bảo mật của bạn là một mạng lưới an toàn - bạn có thể dùng nó để khôi phục quyền truy cập các tin nhắn mã hóa của bạn nếu bạn quên chuỗi mật khẩu của bạn.\n\nGiữ khóa bảo mật của bạn ở đâu đó thật an toàn, như một trình quản lý mật khẩu (hoặc một két sắt)."; + +// Success + +"key_backup_setup_success_title" = "Thành công!"; +"key_backup_setup_passphrase_setup_recovery_key_action" = "(Nâng cao) Thiết lập với khóa bảo mật"; +"key_backup_setup_passphrase_setup_recovery_key_info" = "Hoặc, bảo mật sao lưu của bạn bằng một khóa bảo mật, lưu nó ở đâu đó an toàn."; +"key_backup_setup_passphrase_set_passphrase_action" = "Đặt chuỗi"; +"key_backup_setup_passphrase_confirm_passphrase_invalid" = "Chuỗi không khớp"; +"key_backup_setup_passphrase_confirm_passphrase_valid" = "Tuyệt!"; +"key_backup_setup_passphrase_confirm_passphrase_placeholder" = "Xác nhận chuỗi"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "Xác nhận"; +"key_backup_setup_passphrase_passphrase_invalid" = "Thử thêm một từ"; +"key_backup_setup_passphrase_passphrase_valid" = "Tuyệt!"; +"key_backup_setup_passphrase_passphrase_placeholder" = "Nhập chuỗi"; +"key_backup_setup_passphrase_passphrase_title" = "Nhập"; +"key_backup_setup_passphrase_info" = "Chúng tôi sẽ lưu một bản sao được mã hóa của các khóa của bạn trên máy chủ của chúng tôi. Bảo vệ sao lưu của bạn bằng một chuỗi để giữ nó an toàn.\n\nĐể bảo mật tối đa, chuỗi này nên khác với mật khẩu tài khoản của bạn."; + +// Passphrase + +"key_backup_setup_passphrase_title" = "Bảo mật sao lưu của bạn bằng một chuỗi bảo mật"; +"key_backup_setup_intro_manual_export_action" = "Xuất các khóa thủ công"; +"key_backup_setup_intro_manual_export_info" = "(Nâng cao)"; +"key_backup_setup_intro_setup_connect_action_with_existing_backup" = "Kết nối thiết bị này đến khóa sao lưu"; +"key_backup_setup_intro_setup_action_without_existing_backup" = "Bắt đầu sử dụng bản sao khóa"; +"key_backup_setup_intro_info" = "Các tin nhắn trong các phòng mã hóa được bảo mật bằng mã hóa đầu-cuối. Chỉ có bạn và (các) người nhận có các khóa để đọc các tin nhắn này.\n\nSao lưu một cách bảo mật các khóa của bạn để tránh mất chúng."; + +// Intro + +"key_backup_setup_intro_title" = "Không bao giờ mất các tin nhắn mã hóa"; +"key_backup_setup_skip_alert_skip_action" = "Bỏ qua"; +"key_backup_setup_skip_alert_message" = "Bạn có thể mất bảo mật các tin nhắn nếu bạn đăng xuất hoặc mất thiết bị của bạn."; +"key_backup_setup_skip_alert_title" = "Bạn có chắc?"; + + +// MARK: Key backup setup + +"key_backup_setup_title" = "Sao lưu khóa"; +"secure_backup_setup_banner_subtitle" = "Bảo vệ chống lại việc mất truy cập vào các tin nhắn và dữ liệu mã hóa"; + +// Banner + +"secure_backup_setup_banner_title" = "Sao lưu bảo mật"; +"secure_key_backup_setup_cancel_alert_message" = "Nếu bạn hủy bây giờ, bạn có thể mất các tin nhắn và dữ liệu mã hóa nếu bạn mất quyền truy cập vào thông tin đăng nhập của bạn.\n\nBạn vẫn có thể thiết lập Sao lưu Bảo mật và quản lý các khóa trong Cài đặt."; + + +// Cancel + +"secure_key_backup_setup_cancel_alert_title" = "Bạn có chắc?"; +"secure_key_backup_setup_existing_backup_error_delete_it" = "Xóa nó"; +"secure_key_backup_setup_existing_backup_error_unlock_it" = "Mở khóa nó"; +"secure_key_backup_setup_existing_backup_error_info" = "Mở khóa nó để tái sử dụng nó trong bản sao bảo mật hoặc xóa nó để tao một bản sao mới các tin nhắn trong bản sao bảo mật."; +"secure_key_backup_setup_existing_backup_error_title" = "Một bản sao cho các tin nhắn đã tồn tại"; +"secure_key_backup_setup_intro_use_security_passphrase_info" = "Nhập một chuỗi bí mật chỉ bạn biết, và tạo một khóa để sao lưu."; +"secure_key_backup_setup_intro_use_security_passphrase_title" = "Sử dụng một chuỗi bảo mật"; +"secure_key_backup_setup_intro_use_security_key_info" = "Tạo một khóa bảo mật để lưu trữ ở đâu đó an toàn như trình quản lý mật khẩu hoặc một két sắt."; +"secure_key_backup_setup_intro_use_security_key_title" = "Sử dụng khóa bảo mật"; +"secure_key_backup_setup_intro_info" = "Bảo vệ chống lại việc mất truy cập vào các tin nhắn và dữ liệu mã hóa bằng việc sao lưu các khóa mã hóa trên máy chủ của bạn."; + +// MARK: Secure backup setup + +// Intro + +"secure_key_backup_setup_intro_title" = "Sao lưu bảo mật"; +"rerequest_keys_alert_message" = "Vui lòng khởi chạy %@ trên một thiết bị khác mà có thể giải mã tin nhắn vì vậy nó có thể gửi các khóa đến thiết bị này."; + +// Re-request confirmation dialog +"rerequest_keys_alert_title" = "Yêu cầu đã gửi"; +"deactivate_account_password_alert_message" = "Để tiếp tục, vui lòng nhập mật khẩu của bạn"; +"deactivate_account_password_alert_title" = "Hủy kích hoạt tài khoản"; +"deactivate_account_validate_action" = "Hủy kích hoạt tài khoản"; +"deactivate_account_forget_messages_information_part3" = ": điều này sẽ làm cho các người dùng trong tương lai thấy một khung cảnh không đầy đủ của các cuộc hội thoại)"; +"deactivate_account_forget_messages_information_part2_emphasize" = "Cảnh báo"; +"deactivate_account_forget_messages_information_part1" = "Vui lòng quên tất cả tin nhắn tôi vừa gửi khi tài khoản của tôi bị hủy kích hoạt ("; +"deactivate_account_informations_part5" = "Nếu bạn muốn chúng tôi quên các tin nhắn của bạn, vui lòng đánh dấu vào ô bên dưới\n\nKhả năng hiển thị tin nhắn trong Matrix là tương tự như email. Việc quên các tin nhắn của bạn nghĩa là các tin nhắn bạn vừa gửi sẽ không được chia sẻ với các người dùng mới hoặc chưa được đăng ký, nhưng các người dùng đã đăng ký, người đã có quyền truy cập vào các tin nhắn này, vẫn sẽ truy cập được vào bản sao của họ."; +"deactivate_account_informations_part4_emphasize" = "Không phải do mặc định làm cho chúng tôi quên các tin nhắn bạn vừa gửi. "; +"deactivate_account_informations_part3" = "\n\nĐang hủy kích hoạt tài khoản của bạn. "; +"deactivate_account_informations_part2_emphasize" = "Hành động này là không thể đảo ngược"; +"deactivate_account_informations_part1" = "Điều này sẽ làm cho tài khoản của bạn sẽ không sử dụng được vĩnh viễn. Bạn sẽ không thể đăng nhập, và không ai sẽ có thể đăng ký cùng ID người dùng. Điều này sẽ làm cho tài khoản của bạn rời khỏi tất cả phòng nó đang tham gia, và sẽ xóa chi tiết tài khoản của bạn khỏi máy chủ xác thực. "; + +// Deactivate account + +"deactivate_account_title" = "Hủy kích hoạt tài khoản"; +"service_terms_modal_policy_checkbox_accessibility_hint" = "Kiểm tra để chấp nhận %@"; +"service_terms_modal_information_description_integration_manager" = "Trình quản lý tích hợp cho phép bạn thêm các tính năng từ các bên thứ ba."; +"service_terms_modal_information_description_identity_server" = "Một máy chủ xác thực giúp bạn tìm thấy các danh bạ của bạn, bằng cách tra cứu các số điện thoại hoặc email của họ, để thấy nếu họ đã có một tài khoản chưa."; +"service_terms_modal_information_title_integration_manager" = "Trình quản lý tích hợp"; + +// Alert explaining what an identity server / integration manager is. +"service_terms_modal_information_title_identity_server" = "Máy chủ xác thực"; +"service_terms_modal_description_integration_manager" = "Điều này sẽ cho phép bạn dùng các bot, bridge, widget và gói sticker."; +"service_terms_modal_description_identity_server" = "Điều này sẽ cho phép ai đó tìm thấy bạn nếu họ có số điện thoại hoặc email của bạn được lưu trong danh bạ điện thoại của họ."; +"service_terms_modal_table_header_integration_manager" = "ĐIỀU KHOẢN TRÌNH QUẢN LÝ TÍCH HỢP"; +"service_terms_modal_table_header_identity_server" = "ĐIỀU KHOẢN MÁY CHỦ XÁC THỰC"; +"service_terms_modal_footer" = "Điều này có thể bị vô hiệu hóa bất cứ lúc nào từ cài đặt."; +"service_terms_modal_decline_button" = "Từ chối"; +"service_terms_modal_accept_button" = "Đồng ý"; + +// Service terms +"service_terms_modal_title_message" = "Để tiếp tục, đồng ý các điều khoản và điều kiện bên dưới"; +"gdpr_consent_not_given_alert_review_now_action" = "Xem lại ngay"; + +// GDPR +"gdpr_consent_not_given_alert_message" = "Để tiếp tục dùng homeserver %@ bạn phải xem lại và đồng ý các điều khoản và điều kiện."; +"e2e_room_key_request_ignore_request" = "Bỏ qua yêu cầu"; +"e2e_room_key_request_share_without_verifying" = "Chia sẻ không cần xác minh"; +"e2e_room_key_request_start_verification" = "Bắt đầu xác minh…"; +"e2e_room_key_request_message" = "Thiết bị chưa được xác minh của bạn '%@' đang yêu cầu các khóa mã hóa."; +"e2e_room_key_request_message_new_device" = "Bạn đã thêm một thiết bị mới '%@', thứ đang yêu cầu các khóa mã hóa."; + +// Room key request dialog +"e2e_room_key_request_title" = "Yêu cầu khóa mã hóa"; +"room_widget_permission_room_id_permission" = "ID Phòng"; +"room_widget_permission_widget_id_permission" = "ID Widget"; +"room_widget_permission_theme_permission" = "Chủ đề của bạn"; +"room_widget_permission_user_id_permission" = "User ID của bạn"; +"room_widget_permission_avatar_url_permission" = "URL avatar của bạn"; +"room_widget_permission_display_name_permission" = "Tên hiển thị của bạn"; +"room_widget_permission_information_title" = "Sử dụng nó có thể chia sẻ dữ liệu với %@:\n"; +"room_widget_permission_webview_information_title" = "Sử dụng nó có thể đặt cookie và chia sẻ dữ liệu với %@:\n"; +"room_widget_permission_creator_info_title" = "Widget này được thêm bởi:"; + +// Room widget permissions +"room_widget_permission_title" = "Tải Widget"; +"widget_picker_manage_integrations" = "Quản lý tích hợp…"; + +// Widget Picker +"widget_picker_title" = "Tích hợp"; +"widget_integration_manager_disabled" = "Bạn cần kích hoạt trình quản lý tích hợp trong cài đặt"; +"widget_menu_remove" = "Loại bỏ cho tất cả mọi người"; +"widget_menu_revoke_permission" = "Thu hồi quyền truy cập cho tôi"; +"widget_menu_open_outside" = "Mở trong trình duyệt"; +"widget_menu_refresh" = "Làm mới"; +"widget_sticker_picker_no_stickerpacks_alert_add_now" = "Thêm một số bây giờ?"; +"widget_sticker_picker_no_stickerpacks_alert" = "Bạn không có stickerpack nào được kích hoạt."; +"widget_integrations_server_failed_to_connect" = "Bạn cần quyền để quản lý các widget trong phòng này"; + +// Widget +"widget_no_integrations_server_configured" = "Không có máy chủ tích hợp được cấu hình"; +"bug_report_background_mode" = "Tiếp tục trong nền"; +"e2e_key_backup_wrong_version_button_wasme" = "Đó là tôi"; +"e2e_key_backup_wrong_version_button_settings" = "Cài đặt"; +"e2e_key_backup_wrong_version" = "Một bản sao khóa tin nhắn bảo mật mới được phát hiện.\n\nNếu đây không phải là bạn, đặt một Chuỗi Bảo mật mới trong Cài đặt."; + +// Key backup wrong version +"e2e_key_backup_wrong_version_title" = "Sao lưu khóa mới"; +"call_actions_unhold" = "Tiếp tục"; +"call_no_stun_server_error_use_fallback_button" = "Thử dùng %@"; +"call_no_stun_server_error_message_2" = "Ngoài ra, bạn có thể thử dùng máy chủ công cộng ở %@, nhưng điều này không tin cậy, và nó sẽ chia sẻ địa chỉ IP của bạn với máy chủ đó. Bạn cũng có thể quản lý việc này trong Cài đặt"; +"call_no_stun_server_error_message_1" = "Vui lòng yêu cầu quản trị viên của homeserver %@ của bạn cấu hình máy chủ TURN để cuộc gọi hoạt động tin cậy."; +"call_no_stun_server_error_title" = "Cuộc gọi thất bại do cấu hình máy chủ sai"; +"room_does_not_exist" = "%@ không tồn tại"; +"photo_library_access_not_granted" = "%@ không có quyền để truy cập thư viện ảnh, vui lòng thay đổi cài đặt quyền riêng tư"; +"camera_unavailable" = "Camera không có trên thiết bị của bạn"; +"homeserver_connection_lost" = "Không thể kết nối đến homeserver."; +"event_formatter_jitsi_widget_removed_by_you" = "Bạn đã xóa hội nghị VoIP"; +"event_formatter_jitsi_widget_added_by_you" = "Bạn đã thêm hội nghị VoIP"; +"event_formatter_widget_removed_by_you" = "Bạn đã xóa widget: %@"; + +// Events formatter with you +"event_formatter_widget_added_by_you" = "Bạn đã thêm widget: %@"; +"event_formatter_group_call_incoming" = "%@ trong %@"; +"event_formatter_group_call_leave" = "Rời khỏi"; +"event_formatter_group_call_join" = "Tham gia"; +"event_formatter_group_call" = "Gọi nhóm"; +"event_formatter_call_end_call" = "Kết thúc cuộc gọi"; +"event_formatter_call_retry" = "Thử lại"; +"event_formatter_call_answer" = "Trả lời"; +"event_formatter_call_decline" = "Từ chối"; +"event_formatter_call_back" = "Gọi lại"; +"event_formatter_call_connection_failed" = "Kết nối thất bại"; +"event_formatter_call_missed_video" = "Cuộc gọi video bị nhỡ"; +"event_formatter_call_missed_voice" = "Cuộc gọi thoại bị nhỡ"; +"event_formatter_call_you_declined" = "Cuộc gọi đã từ chối"; +"event_formatter_call_active_video" = "Cuộc gọi video đang hoạt động"; +"event_formatter_call_active_voice" = "Cuộc gọi thoại đang hoạt động"; +"event_formatter_call_incoming_video" = "Cuộc gọi video đến"; +"event_formatter_call_incoming_voice" = "Cuộc gọi thoại đến"; +"event_formatter_call_has_ended_with_time" = "Cuộc gọi đã kết thúc • %@"; +"event_formatter_call_has_ended" = "Cuộc gọi đã kết thúc"; +"event_formatter_call_ringing" = "Đang đổ chuông…"; +"event_formatter_call_connecting" = "Đang kết nối…"; +"event_formatter_message_edited_mention" = "(đã sửa)"; +"event_formatter_rerequest_keys_part2" = " từ các thiết bị khác của bạn."; +"event_formatter_rerequest_keys_part1_link" = "Yêu cầu lại các khóa mã hóa"; +"image_picker_action_library" = "Chọn từ thư viện"; + +// Image picker +"image_picker_action_camera" = "Chụp ảnh"; + +// Media picker +"media_picker_title" = "Thư viện phương tiện"; + +// Group rooms +"group_rooms_filter_rooms" = "Lọc các phòng cộng đồng"; +"group_participants_invited_section" = "ĐÃ MỜI"; +"group_participants_invite_malformed_id" = "ID lạ. Nên là Matrix ID giống như '@localpart:domain'"; +"group_participants_invite_malformed_id_title" = "Lỗi mời"; +"group_participants_invite_another_user" = "Tìm / mời bằng ID người dùng hoặc tên"; +"group_participants_filter_members" = "Lọc thành viên cộng đồng"; +"group_participants_invite_prompt_msg" = "Bạn có chắc muốn mời %@ vào nhóm này?"; +"group_participants_invite_prompt_title" = "Xác nhận"; +"group_participants_remove_prompt_msg" = "Bạn có chắc muốn loại bỏ %@ khỏi nhóm này?"; +"group_participants_remove_prompt_title" = "Xác nhận"; +"group_participants_leave_prompt_msg" = "Bạn có chắc muốn rời khỏi nhóm?"; +"group_participants_leave_prompt_title" = "Rời nhóm"; + +// Group participants +"group_participants_add_participant" = "Thêm người tham gia"; +"group_invitation_format" = "%@ đã mời bạn tham gia vào cộng đồng này"; +"group_home_multi_rooms_format" = "%tu phòng"; +"group_home_one_room_format" = "1 phòng"; +"group_home_multi_members_format" = "%tu thành viên"; + +// Group Home +"group_home_one_member_format" = "1 thành viên"; +"group_details_rooms" = "Phòng"; +"group_details_people" = "Danh bạ"; +"group_details_home" = "Nhà"; + +// Group Details +"group_details_title" = "Chi tiết cộng đồng"; +"room_notifs_settings_encrypted_room_notice" = "Vui lòng lưu ý rằng các thông báo đề cập và từ khóa không có trong các phòng mã hóa trên di động."; +"room_notifs_settings_account_settings" = "Cài đặt tài khoản"; +"room_notifs_settings_manage_notifications" = "Bạn có thể quản lý thông báo trong %@"; +"room_notifs_settings_cancel_action" = "Hủy"; +"room_notifs_settings_done_action" = "Xong"; +"room_notifs_settings_none" = "Không"; +"room_notifs_settings_mentions_and_keywords" = "Chỉ đề cập và từ khóa"; +"room_notifs_settings_all_messages" = "Tất cả tin nhắn"; + +// Room Notification Settings +"room_notifs_settings_notify_me_for" = "Thông báo tôi để"; +"room_details_fail_to_update_room_communities" = "Cập nhật các cộng đồng liên quan thất bại"; +"room_details_advanced_e2e_encryption_disabled_for_dm" = "Mã hóa chưa được kích hoạt ở đây."; +"room_details_advanced_e2e_encryption_enabled_for_dm" = "Mã hóa được kích hoạt ở đây"; +"room_details_advanced_room_id_for_dm" = "ID:"; +"room_details_flair_invalid_id_prompt_msg" = "%@ không phải là định danh hợp lệ cho cộng đồng"; +"room_details_flair_invalid_id_prompt_title" = "Định dạng không hợp lệ"; +"room_details_new_flair_placeholder" = "Thêm ID cộng đồng mới (ví dụ: +foo%@)"; +"room_details_flair_section" = "Hiển thị sự tinh tế cho cộng đồng"; +"room_details_no_local_addresses_for_dm" = "Phòng này không có địa chỉ nội bộ"; +"room_details_access_section_directory_toggle_for_dm" = "Liệt kê trong danh mục phòng"; +"room_details_access_section_anyone_for_dm" = "Bất cứ ai biết đường dẫn, kể cả khách"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "Bất cứ ai biết đường dẫn, ngoài khách"; +"secrets_recovery_with_key_recovery_key_title" = "Nhập"; +"secrets_recovery_with_key_information_unlock_secure_backup_with_key" = "Nhập Khóa Bảo mật của bạn để tiếp tục."; +"secrets_recovery_with_key_information_unlock_secure_backup_with_phrase" = "Nhập Chuỗi Bảo mật của bạn để tiếp tục."; +"secrets_recovery_with_key_information_verify_device" = "Sử dụng Khóa Bảo mật của bạn để xác minh thiết bị này."; +"secrets_recovery_with_key_information_default" = "Truy cập vào lịch sử tin nhắn bảo mật và danh tính xác thực chéo của bạn để xác minh các thiết bị khác bằng cách nhập Khóa Bảo mật của bạn."; + +// Recover with key + +"secrets_recovery_with_key_title" = "Khóa Bảo mật"; +"secrets_recovery_with_passphrase_invalid_passphrase_message" = "Vui lòng xác minh rằng bạn đã nhập đúng Chuỗi Bảo mật."; +"secrets_recovery_with_passphrase_invalid_passphrase_title" = "Không thể truy cập kho lưu bí mật"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = "."; +"secrets_recovery_with_passphrase_lost_passphrase_action_part2" = "sử dụng Khóa Bảo mật của bạn"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part1" = "Không biết Chuỗi Bảo mật của bạn? Bạn có thể "; +"secrets_recovery_with_passphrase_recover_action" = "Sử dụng Chuỗi"; +"secrets_recovery_with_passphrase_passphrase_placeholder" = "Nhập Chuỗi Bảo mật"; +"secrets_recovery_with_passphrase_passphrase_title" = "Nhập"; +"secrets_recovery_with_passphrase_information_verify_device" = "Sử dụng Chuỗi Bảo mật của bạn để xác minh thiết bị này."; +"secrets_recovery_with_passphrase_information_default" = "Truy cập vào lịch sử tin nhắn bảo mật và danh tính xác thực chéo của bạn để xác minh các thiết bị khác bằng cách nhập Chuỗi Bảo mật của bạn."; + +// Recover with passphrase + +"secrets_recovery_with_passphrase_title" = "Chuỗi bảo mật"; +"secrets_recovery_reset_action_part_2" = "Đặt lại mọi thứ"; + +// MARK: - Secrets recovery + +"secrets_recovery_reset_action_part_1" = "Quên hoặc mất các tùy chọn khôi phục? "; +"user_verification_session_details_verify_action_other_user" = "Xác minh thủ công"; +"user_verification_session_details_verify_action_current_user_manually" = "Xác minh thủ công bằng văn bản"; +"user_verification_session_details_verify_action_current_user" = "Xác minh tương tác"; +"user_verification_session_details_additional_information_untrusted_current_user" = "Nếu bạn không đăng nhập vào thiết bị này, tài khoản của bạn có thể bị xâm phạm."; +"user_verification_session_details_additional_information_untrusted_other_user" = "Cho đến khi người dùng này tin tưởng thiết bị này, các tin nhắn được gửi đến và đi từ nó được gán nhãn cảnh báo. Ngoài ra, bạn có thể xác minh nó một cách thủ công."; +"room_details_access_section_for_dm" = "Ai có thể truy cập vào đây?"; +"room_details_notifs" = "Thông báo"; +"room_details_room_name_for_dm" = "Tên"; +"room_details_photo_for_dm" = "Hình ảnh"; +"room_details_integrations" = "Tích hợp"; +"room_details_search" = "Tìm phòng"; +"room_details_title_for_dm" = "Chi tiết"; +"identity_server_settings_alert_error_invalid_identity_server" = "%@ không phải là máy chủ xác thực hợp lệ."; +"identity_server_settings_alert_error_terms_not_accepted" = "Bạn phải chấp nhận các điều khoản của %@ để thiết lập nó là máy chủ xác thực."; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "Vẫn ngắt kết nối"; +"identity_server_settings_alert_disconnect_still_sharing_3pid" = "Bạn vẫn đang chia sẻ dữ liệu cá nhân của bạn trên máy chủ xác thực %@.\n\nChúng tôi đề nghị bạn xóa các địa chỉ email và số điện thoại khỏi máy chủ xác thực trước khi ngắt kết nối."; +"identity_server_settings_alert_disconnect_button" = "Ngắt kết nối"; +"identity_server_settings_alert_disconnect" = "Ngắt kết nối từ máy chủ xác thực %@?"; +"identity_server_settings_alert_disconnect_title" = "Ngắt kết nối máy chủ xác thực"; +"identity_server_settings_alert_change" = "Ngắt kết nối từ máy chủ xác thực %1$@ và kết nối đến %2$@?"; +"identity_server_settings_alert_change_title" = "Thay đổi máy chủ xác thực"; +"identity_server_settings_alert_no_terms" = "Máy chủ xác thực bạn vừa chọn không có điều khoản dịch vụ. Chỉ tiếp tục khi bạn tin tưởng chủ sở hữu của máy chủ này."; +"identity_server_settings_alert_no_terms_title" = "Máy chủ xác thực không có điều khoản dịch vụ"; +"identity_server_settings_disconnect" = "Ngắt kết nối"; +"identity_server_settings_disconnect_info" = "Ngắt kết nối đến máy chủ xác thực của bạn sẽ có nghĩa là bạn không thể được tìm thấy bởi những người dùng khác và không thể mời những người khác bằng email hoặc điện thoại."; +"identity_server_settings_change" = "Thay đổi"; +"identity_server_settings_add" = "Thêm"; +"identity_server_settings_place_holder" = "Nhập một máy chủ xác thực"; +"identity_server_settings_no_is_description" = "Bạn đang không dùng máy chủ xác thực. Để tìm và được tìm bởi những liên hệ đang có, hãy thêm một vào bên trên"; +"identity_server_settings_description" = "Bạn đang dùng %@ để tìm kiếm và được tìm bởi những liên hệ bạn biết."; + +// Identity server settings +"identity_server_settings_title" = "Máy chủ xác thực"; + +// AuthenticatedSessionViewControllerFactory +"authenticated_session_flow_not_supported" = "Ứng dụng này không hỗ trợ cơ chế xác thực trên homeserver của bạn."; +"manage_session_sign_out" = "Đăng xuất khỏi thiết bị này"; +"manage_session_not_trusted" = "Không tin tưởng"; +"manage_session_trusted" = "Được bạn tin tưởng"; +"manage_session_name" = "Tên thiết bị"; +"manage_session_info" = "THÔNG TIN THIẾT BỊ"; + +// Manage session +"manage_session_title" = "Quản lý thiết bị"; +"security_settings_user_password_description" = "Xác nhận danh tính của bạn bằng cách nhập mật khẩu tài khoản của bạn"; +"security_settings_coming_soon" = "Xin lỗi. Hành động này vẫn chưa có trên %@ iOS. Vui lòng sử dụng client Matrix khác để thiết lập nó. %@ iOS sẽ sử dụng nó."; +"security_settings_complete_security_alert_message" = "Bạn nên hoàn thành bảo mật trên thiết bị hiện tại của bạn trước."; +"security_settings_complete_security_alert_title" = "Hoàn thành bảo mật"; +"security_settings_blacklist_unverified_devices_description" = "Xác minh tất cả các thiết bị người dùng để đánh dấu chúng là tin cậy và gửi tin nhắn đến chúng"; +"security_settings_blacklist_unverified_devices" = "Không bao giờ gửi tin nhắn đến các thiết bị không tin cậy"; +"security_settings_advanced" = "Nâng cao"; +"security_settings_export_keys_manually" = "Xuất các khóa thủ công"; +"security_settings_cryptography" = "MẬT MÃ HỌC"; +"security_settings_crosssigning_complete_security" = "Hoàn thành bảo mật"; +"security_settings_crosssigning_reset" = "Đặt lại"; +"security_settings_crosssigning_bootstrap" = "Thiết lập"; +"security_settings_crosssigning_info_ok" = "Xác thực chéo sẵn sàng để sử dụng."; +"security_settings_crosssigning_info_trusted" = "Xác thực chéo được kích hoạt. Bạn có thể tin tưởng các người dùng khác và các thiết bị khác của bạn dựa theo xác thực chéo nhưng bạn không thể xác thực chéo từ thiết bị này vì nó không có các khóa riêng của xác thực chéo. Hoàn thành bảo mật của thiết bị này."; +"security_settings_crosssigning_info_exists" = "Tài khoản của bạn có một danh tính xác thực chéo, nhưng nó chưa được thiết bị này tin tưởng. Hoàn thành bảo mật thiết bị này."; +"security_settings_crosssigning_info_not_bootstrapped" = "Xác thực chéo chưa được thiết lập."; +"security_settings_crosssigning" = "XÁC THỰC CHÉO"; +"security_settings_backup" = "SAO LƯU TIN NHẮN"; +"security_settings_secure_backup_delete" = "Xóa sao lưu"; +"security_settings_secure_backup_restore" = "Khôi phục từ sao lưu"; +"security_settings_secure_backup_reset" = "Đặt lại"; +"security_settings_secure_backup_setup" = "Thiết lập"; +"security_settings_secure_backup_info_valid" = "Thiết bị này đang sao lưu các khóa của bạn."; +"security_settings_secure_backup_info_checking" = "Đang kiểm tra…"; +"security_settings_secure_backup_description" = "Sao lưu các khóa mã hóa với thông tin tài khoản của bạn trong trường hợp bạn mất quyền truy cập vào các thiệt bị của bạn. Các khóa của bạn sẽ được bảo mật bằng một Khóa Bảo mật duy nhất."; +"security_settings_secure_backup" = "SAO LƯU BẢO MẬT"; +"security_settings_crypto_sessions_description_2" = "Nếu bạn không nhận ra một lượt đăng nhập, hãy thay đổi mật khẩu của bạn và đặt lại sao lưu bảo mật."; +"security_settings_crypto_sessions_loading" = "Đang tải các thiết bị…"; +"security_settings_crypto_sessions" = "CÁC THIẾT BỊ CỦA TÔI"; + +// Security settings +"security_settings_title" = "Bảo mật"; +"settings_show_NSFW_public_rooms" = "Hiện các phòng công cộng NSFW"; +"settings_identity_server_no_is_description" = "Bạn đang không dùng máy chủ xác thực. Để tìm thấy hoặc được tìm thấy bời các liên hệ bạn biết, hãy thêm vào một"; +"settings_identity_server_no_is" = "Không có máy chủ xác thực được cấu hình"; +"settings_identity_server_description" = "Sử dụng máy chủ xác thực được cài đặt bên trên, bạn có thể tìm thấy và được tìm thấy bởi các liên hệ bạn biết."; +"settings_discovery_three_pid_details_enter_sms_code_action" = "Nhập mã kích hoạt SMS"; +"settings_discovery_three_pid_details_cancel_email_validation_action" = "Hủy xác thực email"; +"settings_discovery_three_pid_details_revoke_action" = "Thu hồi"; +"settings_discovery_three_pid_details_share_action" = "Chia sẻ"; +"settings_discovery_three_pid_details_information_phone_number" = "Quản lý tùy chọn cho số điện thoại này, mà người dùng khác có thể dùng để tìm thấy bạn và sử dụng để mời bạn vào phòng. Thêm hoặc xóa các số điện thoại trong các tài khoản."; +"settings_discovery_three_pid_details_title_phone_number" = "Quản lý số điện thoại"; +"settings_discovery_three_pid_details_information_email" = "Quản lý tùy chọn cho địa chỉ email này, mà các người dùng khác có thể dùng để tìm thấy bạn và sử dụng để mời bạn vào phòng. Thêm hoặc xóa các địa chỉ email trong các tài khoản."; +"settings_discovery_three_pid_details_title_email" = "Quản lý email"; +"settings_discovery_error_message" = "Có lỗi xảy ra. Vui lòng thử lại."; +"settings_discovery_three_pids_management_information_part3" = "."; +"settings_discovery_three_pids_management_information_part2" = "Cài đặt người dùng"; +"settings_discovery_three_pids_management_information_part1" = "Quản lý các địa chỉ email hoặc số điện thoại mà người dùng khác có thể sử dụng để tìm thấy bạn và sử dụng để mời bạn vào phòng. Thêm hoặc xóa các địa chỉ email hoặc số điện thoại từ danh sách này trong "; +"settings_discovery_terms_not_signed" = "Chấp nhận Điều khoản dịch vụ của máy chủ xác thực (%@) để cho phép bạn có thể được tìm thấy bằng địa chỉ email hoặc số điện thoại."; +"settings_discovery_no_identity_server" = "Bạn đang không xài máy chủ xác thực. Để các liên hệ bạn biết tìm thấy bạn, hãy thêm một."; +"settings_devices_description" = "Tên công khai của một thiết bị hiển thị cho mọi người mà bạn đang giao tiếp"; +"settings_key_backup_delete_confirmation_prompt_msg" = "Bạn có chắc không? Bạn sẽ mất các tin nhắn mã hóa nếu các khóa của bạn không được sao lưu đúng."; +"settings_key_backup_delete_confirmation_prompt_title" = "Xóa sao lưu"; +"settings_key_backup_button_connect" = "Kết nối thiết bị này đến khóa sao lưu"; +"settings_key_backup_button_delete" = "Xóa sao lưu"; +"settings_key_backup_button_restore" = "Khôi phục từ sao lưu"; +"settings_key_backup_button_create" = "Bắt đầu sử dụng sao lưu khóa"; +"settings_key_backup_info_trust_signature_invalid_device_unverified" = "Sao lưu có một chữ ký không hợp lệ từ %@"; +"settings_key_backup_info_trust_signature_invalid_device_verified" = "Sao lưu có một chữ ký không hợp lệ từ %@"; +"settings_key_backup_info_trust_signature_valid_device_unverified" = "Sao lưu có một chữ ký từ %@"; +"settings_key_backup_info_trust_signature_valid_device_verified" = "Sao lưu có một chữ ký hợp lệ từ %@"; +"settings_key_backup_info_trust_signature_valid" = "Sao lưu có một chữ ký hợp lệ từ thiết bị này"; +"settings_key_backup_info_trust_signature_unknown" = "Sao lưu có một chữ ký từ thiết bị với ID: %@"; +"settings_key_backup_info_progress_done" = "Tất cả khóa được sao lưu"; +"settings_key_backup_info_progress" = "Đang sao lưu %@ khóa…"; +"settings_key_backup_info_not_valid" = "Thiết bị này không sao lưu các khóa của bạn, nhưng bạn có một bản sao hiện tại mà bạn có thể khôi phục và thêm vào"; +"settings_key_backup_info_valid" = "Thiết bị này đang sao lưu các khóa của bạn."; +"settings_key_backup_info_algorithm" = "Thuật toán: %@"; +"settings_key_backup_info_version" = "Phiên bản sao lưu khóa: %@"; +"settings_key_backup_info_signout_warning" = "Sao lưu các khóa của bạn trước khi đăng xuất để tránh làm mất chúng."; +"settings_key_backup_info_none" = "Các khóa của bạn không được sao lưu từ thiết bị này."; +"settings_key_backup_info_checking" = "Đang kiểm tra…"; +"settings_key_backup_info" = "Các tin nhắn mã hóa được bảo mật bằng mã hóa đầu-cuối. Chỉ có bạn và (các) người nhận có các khóa để đọc những tin nhắn này."; +"settings_deactivate_my_account" = "Hủy kích hoạt tài khoản của tôi"; +"settings_add_3pid_invalid_password_message" = "Thông tin xác thực không hợp lệ"; +"settings_add_3pid_password_message" = "Để tiếp tục, vui lòng nhập mật khẩu của bạn"; +"settings_add_3pid_password_title_msidsn" = "Thêm số điện thoại"; +"settings_add_3pid_password_title_email" = "Thêm địa chỉ email"; +"settings_labs_voice_messages" = "Các tin nhắn thoại"; +"settings_labs_enable_ringing_for_group_calls" = "Đổ chuông cho các cuộc gọi nhóm"; +"settings_labs_message_reaction" = "Phản ứng với các tin nhắn bằng emoji"; +"settings_contacts_enable_sync_description" = "Điều này sẽ dùng máy chủ xác thực của bạn để kết nối bạn với các liên hệ của bạn, và hỗ trợ họ tìm thấy bạn."; +"settings_contacts_enable_sync" = "Tìm các liên hệ của bạn"; +"settings_show_url_previews_description" = "Các bản xem trước chỉ được hiển thị trong các phòng không mã hóa."; +"settings_show_url_previews" = "Hiện bản xem trước trang web"; +"settings_ui_theme_picker_message_match_system_theme" = "\"Tự động\" khớp chủ đề hệ thống của thiết bị của bạn"; +"settings_ui_theme_picker_message_invert_colours" = "\"Tự động\" sử dụng cài đặt \"Các màu đảo ngược\" của thiết bị của bạn"; +"settings_ui_theme_black" = "Đen"; +"settings_integrations_allow_description" = "Sử dụng một trình quản lý tích hợp (%@) để quản lý bot, cầu nối, widget và các gói sticker.\n\nCác trình quản lý tích hợp nhận dữ liệu cấu hình, và có thể sửa đổi các widget, gửi các lời mời phòng và đặt cấp độ quản lý thay cho bạn"; +"settings_integrations_allow_button" = "Quản lý tích hợp"; +"settings_calls_stun_server_fallback_description" = "Cho phép máy chủ hỗ trợ cuộc gọi dự phòng %@ khi homeserver của bạn không cung cấp (địa chỉ IP của bạn sẽ được chia sẻ trong cuộc gọi)."; +"settings_calls_stun_server_fallback_button" = "Cho phép máy chủ hỗ trợ cuộc gọi dự phòng"; +"settings_mentions_and_keywords_encryption_notice" = "Bạn sẽ không nhận được thông báo cho các đề cập và từ khóa trong các phòng được mã hóa trên di động"; +"settings_new_keyword" = "Thêm từ khóa mới"; +"settings_your_keywords" = "Các từ khóa của bạn"; +"settings_room_upgrades" = "Các nâng cấp phòng"; +"settings_messages_by_a_bot" = "Các tin nhắn của bot"; +"settings_call_invitations" = "Các lời mời cuộc gọi"; +"settings_room_invitations" = "Các lời mời phòng"; +"settings_messages_containing_keywords" = "Các từ khóa"; +"settings_messages_containing_at_room" = "@room"; +"settings_messages_containing_user_name" = "Tên người dùng của tôi"; +"settings_messages_containing_display_name" = "Tên hiển thị của tôi"; +"settings_encrypted_group_messages" = "Các tin nhắn nhóm được mã hóa"; +"settings_group_messages" = "Các tin nhắn nhóm"; +"settings_encrypted_direct_messages" = "Các tin nhắn trực tiếp được mã hóa"; +"settings_direct_messages" = "Các tin nhắn trực tiếp"; +"settings_notify_me_for" = "Thông báo cho tôi biết"; +"settings_mentions_and_keywords" = "Các đề cập và từ khóa"; +"settings_default" = "Các thông báo mặc định"; +"settings_notifications_disabled_alert_message" = "Để bật thông báo, đi đến cài đặt thiết bị của bạn"; +"settings_notifications_disabled_alert_title" = "Thông báo bị vô hiệu hóa"; +"settings_device_notifications" = "Các thông báo thiết bị"; +"settings_security" = "BẢO MẬT"; +"settings_confirm_media_size_description" = "Khi điều này xảy ra, bạn sẽ được yêu cầu xác nhận kích thước hình ảnh và video nào sẽ được gửi"; +"settings_confirm_media_size" = "Xác nhận kích thước khi gửi"; +"settings_three_pids_management_information_part3" = "."; +"settings_three_pids_management_information_part2" = "Tìm kiếm"; +"settings_three_pids_management_information_part1" = "Quản lý các địa chỉ email hoặc số điện thoại bạn có thể sử dụng để đăng nhập hoặc khôi phục tài khoản của bạn ở đây. Điều khiển ai có thể tìm thấy bạn "; +"settings_deactivate_account" = "HỦY KÍCH HOẠT TÀI KHOẢN"; +"settings_key_backup" = "KHÓA DỰ PHÒNG"; +"settings_flair" = "Thể hiện sự tinh tế khi được phép"; +"settings_phone_contacts" = "DANH BẠ ĐIỆN THOẠI"; +"settings_integrations" = "TÍCH HỢP"; +"settings_identity_server_settings" = "MÁY CHỦ XÁC THỰC"; +"settings_discovery_settings" = "TÌM KIẾM"; +"settings_notifications" = "THÔNG BÁO"; +"settings_links" = "LIÊN KẾT"; +"settings_sending_media" = "GỬI HÌNH ẢNH VÀ VIDEO"; +"room_multiple_typing_notification" = "%@ và những người khác"; +"external_link_confirmation_message" = "Liên kết %@ đang đưa bạn đến mốt trang khác: %@\n\nBạn có chắc muốn tiếp tục?"; +"external_link_confirmation_title" = "Kiểm tra lại liên kết này"; +"media_type_accessibility_sticker" = "Sticker"; +"media_type_accessibility_file" = "Tệp"; +"media_type_accessibility_location" = "Địa điểm"; +"media_type_accessibility_video" = "Video"; +"media_type_accessibility_audio" = "Âm thanh"; +"media_type_accessibility_image" = "Hình ảnh"; +"room_no_privileges_to_create_group_call" = "Bạn cần phải là một quản trị viên hoặc điều hành viên để bắt đầu cuộc gọi."; +"room_join_group_call" = "Tham gia"; +"room_open_dialpad" = "Bàn phím quay số"; +"room_place_voice_call" = "Cuộc gọi thoại"; +"room_accessibility_hangup" = "Cúp máy"; +"room_accessibility_video_call" = "Gọi video"; +"room_accessibility_call" = "Gọi"; +"room_accessibility_upload" = "Tải lên"; +"room_accessibility_integrations" = "Tích hợp"; +"room_accessibility_search" = "Tìm kiếm"; +"room_message_edits_history_title" = "Sửa tin nhắn"; +"room_resource_usage_limit_reached_message_contact_3" = " để tăng giới hạn này."; +"room_resource_usage_limit_reached_message_2" = "một số người dùng sẽ không thể đăng nhập."; +"room_resource_usage_limit_reached_message_1_monthly_active_user" = "Homeserver này đạt giới hạn người dùng hoạt động hàng tháng của nó do đó "; +"room_resource_usage_limit_reached_message_1_default" = "Homeserver này đã vượt quá một trong các giới hạn tài nguyên của nó do đó "; +"room_resource_limit_exceeded_message_contact_3" = " để tiếp tục sử dụng dịch vụ này."; +"room_resource_limit_exceeded_message_contact_2_link" = "Liên hệ quản trị viên dịch vụ của bạn"; +"room_resource_limit_exceeded_message_contact_1" = " Vui lòng "; +"room_predecessor_link" = "Nhấn vào đây để xem các tin nhắn cũ."; +"room_predecessor_information" = "Phòng này là sự tiếp nối của cuộc trò chuyện khác."; +"room_replacement_link" = "Cuộc trò chuyện tiếp tục ở đây"; +"room_replacement_information" = "Phòng này đã được thay thế và không còn hoạt động nữa"; +"room_action_reply" = "Trả lời"; +"room_action_send_file" = "Gửi tệp"; +"room_action_send_sticker" = "Gửi sticker"; +"room_action_send_photo_or_video" = "Gửi ảnh hoặc video"; +"room_action_camera" = "Chụp ảnh hoặc quay video"; +"room_event_action_reaction_history" = "Lịch sử phản ứng"; +"room_event_action_reaction_show_less" = "Hiện ít hơn"; +"room_event_action_reaction_show_all" = "Hiện tất cả"; +"room_event_action_edit" = "Chỉnh sửa"; +"room_event_action_reply" = "Trả lời"; +"room_event_action_delete_confirmation_message" = "Bạn có chắc muốn xóa tin nhắn chưa được gửi này?"; +"room_event_action_delete_confirmation_title" = "Xóa tin nhắn chưa được gửi"; +"room_event_action_ban_prompt_reason" = "Lí do cấm người dùng này"; +"room_event_action_kick_prompt_reason" = "Lí do đá người dùng này"; +"room_event_action_view_decrypted_source" = "Xem nguồn được giải mã"; +"room_unsent_messages_cancel_message" = "Bạn có chắc muốn xóa tất cả các tin nhắn chưa được gửi trong phòng này?"; +"room_unsent_messages_cancel_title" = "Xóa các tin nhắn chưa được gửi"; +"room_message_reply_to_short_placeholder" = "Gửi trả lời…"; +"encrypted_room_message_reply_to_placeholder" = "Gửi trả lời đã mã hóa…"; +"key_backup_recover_invalid_passphrase_title" = "Chuỗi bảo mật không chính xác"; + +// MARK: Key backup recover + +"key_backup_recover_title" = "Các tin nhắn bảo mật"; + +// Success from secure backup +"key_backup_setup_success_from_secure_backup_info" = "Các khóa của bạn đang được sao lưu."; +"key_backup_setup_success_from_recovery_key_made_copy_action" = "Tôi vừa tạo một bản sao"; +"room_do_not_have_permission_to_post" = "Bạn không có quyền đăng bài vào phòng này"; +"room_message_replying_to" = "Đang trả lời %@"; +"room_message_editing" = "Chỉnh sửa"; +"room_message_unable_open_link_error_message" = "Không thể mở liên kết"; +"room_message_reply_to_placeholder" = "Gửi trả lời (không được mã hóa)…"; +"room_accessiblity_scroll_to_bottom" = "Cuộn đến cuối"; + +// Chat +"room_slide_to_end_group_call" = "Trượt để kết thúc cuộc gọi cho tất cả mọi người"; +"room_member_power_level_short_custom" = "Tùy chỉnh"; +"room_member_power_level_short_moderator" = "Điều hành viên"; +"room_member_power_level_short_admin" = "Quản trị viên"; +"room_member_power_level_custom_in" = "Tùy chỉnh (%@) trong %@"; +"room_member_power_level_moderator_in" = "Điều hành viên trong %@"; +"room_member_power_level_admin_in" = "Quản trị viên trong %@"; +"room_participants_security_information_room_encrypted_for_dm" = "Các tin nhắn ở đây được mã hóa đầu-cuối.\n\nCác tin nhắn của bạn được mã hóa bằng các khóa và chỉ có bạn và người nhận có những khóa duy nhất để mở chúng."; +"room_participants_security_information_room_encrypted" = "Các tin nhắn trong phòng này được mã hóa đầu-cuối.\n\nCác tin nhắn của bạn được bảo mật bằng các khóa và chỉ có bạn và người nhận có các khóa duy nhất để mở chúng."; +"room_participants_security_information_room_not_encrypted_for_dm" = "Các tin nhắn ở đây không được mã hóa đầu-cuối"; +"room_participants_security_information_room_not_encrypted" = "Các tin nhắn trong phòng này không được mã hóa đầu-cuối"; +"room_participants_security_loading" = "Đang tải…"; +"room_participants_action_security_status_loading" = "Đang tải…"; +"room_participants_action_security_status_warning" = "Cảnh báo"; +"room_participants_action_security_status_complete_security" = "Hoàn thành bảo mật"; +"room_participants_action_security_status_verify" = "Xác minh"; +"room_participants_action_security_status_verified" = "Đã xác minh"; +"room_participants_action_section_security" = "An ninh"; +"room_participants_start_new_chat_error_using_user_email_without_identity_server" = "Không có máy chủ xác thực nào được cài đặt do đó bạn không thể bắt đầu trò chuyện với một liên hệ bằng email"; +"room_participants_filter_room_members_for_dm" = "Lọc thành viên"; +"room_participants_remove_third_party_invite_prompt_msg" = "Ban có chắc muốn thu hồi lời mời này?"; +"room_participants_leave_prompt_msg_for_dm" = "Bạn có chắc muốn rời?"; +"room_participants_leave_prompt_title_for_dm" = "Rời"; +"find_your_contacts_identity_service_error" = "Không thể kết nối với máy chủ xác thực"; +"find_your_contacts_footer" = "Điều này có thể bị vô hiệu hóa bất cứ lúc nào từ cài đặt"; +"find_your_contacts_button_title" = "Tìm liên hệ của bạn"; +"find_your_contacts_message" = "Hãy để %@ hiển thị danh bạ của bạn để bạn có thể nhanh chóng bắt đầu trò chuyện với những người bạn biết rõ nhất"; +"find_your_contacts_title" = "Bắt đầu bằng cách liệt kê danh bạ của bạn"; +"contacts_address_book_permission_denied_alert_message" = "Để bật danh bạ, hãy đi tới cài đặt thiết bị của bạn"; +"contacts_address_book_permission_denied_alert_title" = "Danh bạ bị vô hiệu hóa"; +"contacts_address_book_no_identity_server" = "Không có máy chủ xác thực nào được cấu hình"; +"group_section" = "CỘNG ĐỒNG"; + +// Groups tab +"group_invite_section" = "MỜI"; +"rooms_empty_view_information" = "Phòng là tuyệt vời cho bất kỳ trò chuyện nhóm, riêng tư hoặc công cộng. Nhấn vào + để tìm các phòng hiện có hoặc tạo phòng mới."; +"rooms_empty_view_title" = "Phòng"; +"people_empty_view_information" = "Trò chuyện bảo mật với bất cứ ai. Nhấn vào + để bắt đầu thêm người"; +"people_empty_view_title" = "Danh bạ"; +"room_recents_unknown_room_error_message" = "Không thể tìm thấy phòng này. Hãy chắc chắn rằng nó tồn tại"; +"room_recents_suggested_rooms_section" = "PHÒNG GỢI Ý"; +"room_recents_server_notice_section" = "CẢNH BẢO HỆ THỐNG"; +"room_creation_dm_error" = "Chúng tôi không thể tạo DM của bạn. Vui lòng kiểm tra người dùng bạn muốn mời và thử lại."; +"room_creation_error_invite_user_by_email_without_identity_server" = "Không có máy chủ xác thực nào được cấu hình vì vậy bạn không thể thêm người dự bằng email."; + +// Errors +"error_user_already_logged_in" = "Có vẻ như bạn đang cố gắng kết nối với một homeserver khác. Bạn có muốn đăng xuất không?"; +"social_login_button_title_sign_up" = "Đăng ký với %@"; +"social_login_button_title_sign_in" = "Đăng nhập với %@"; +"social_login_button_title_continue" = "Tiếp tục với %@"; +"social_login_list_title_sign_up" = "Hoặc"; +"social_login_list_title_sign_in" = "Hoặc"; + +// Social login + +"social_login_list_title_continue" = "Tiếp tục với"; +"auth_softlogout_clear_data_sign_out" = "Đăng xuất"; +"auth_softlogout_clear_data_sign_out_msg" = "Bạn có chắc chắn muốn xóa tất cả dữ liệu hiện đang được lưu trữ trên thiết bị này không? Đăng nhập lại để truy cập dữ liệu tài khoản và tin nhắn của bạn."; +"auth_softlogout_clear_data_sign_out_title" = "Bạn có chắc không?"; +"auth_softlogout_clear_data_button" = "Xóa tất cả dữ liệu"; +"auth_softlogout_clear_data_message_2" = "Xóa nó nếu bạn đã hoàn tất việc sử dụng thiết bị này hoặc muốn đăng nhập vào tài khoản khác."; +"auth_softlogout_clear_data_message_1" = "Cảnh báo: Dữ liệu cá nhân của bạn (bao gồm cả khóa mã hóa) vẫn được lưu trữ trên thiết bị này."; +"auth_softlogout_clear_data" = "Xóa dữ liệu cá nhân"; +"auth_softlogout_recover_encryption_keys" = "Đăng nhập để khôi phục các khóa mã hóa được lưu trữ duy nhất trên thiết bị này. Bạn cần chúng để đọc tất cả các tin nhắn an toàn của bạn trên bất kỳ thiết bị nào."; +"auth_softlogout_reason" = "Người quản trị homeserver (%1$@) của bạn đã đăng xuất bạn ra khỏi account %2$@ (%3$@)."; +"auth_softlogout_sign_in" = "Đăng nhập"; +"auth_softlogout_signed_out" = "Bạn đã đăng xuất"; +"auth_autodiscover_invalid_response" = "Phản hồi tìm kiếm homeserver không hợp lệ"; +"auth_accept_policies" = "Vui lòng xem xét và chấp nhận các chính sách của homeserver này:"; +"auth_reset_password_error_is_required" = "Không có máy chủ xác thực nào được cấu hình: thêm một trong các tùy chọn máy chủ để đặt lại mật khẩu của bạn."; +"auth_forgot_password_error_no_configured_identity_server" = "Không có máy chủ xác thực nào được cấu hình: thêm một để đặt lại mật khẩu của bạn."; +"auth_phone_is_required" = "Không có máy chủ xác thực nào được cấu hình để bạn không thể thêm số điện thoại để đặt lại mật khẩu của mình trong tương lai."; +"auth_email_is_required" = "Không có máy chủ xác thực nào được cấu hình để bạn không thể thêm địa chỉ email để đặt lại mật khẩu của mình trong tương lai."; +"auth_add_email_phone_message_2" = "Đặt email để khôi phục tài khoản. Sử dụng email hoặc điện thoại sau này để được tùy chọn phát hiện bởi những người biết bạn."; +"auth_add_phone_message_2" = "Đặt điện thoại và sau đó có thể tùy chọn được tìm kiếm bởi những người biết bạn."; +"auth_add_email_message_2" = "Đặt email để khôi phục tài khoản và sau đó có thể tùy chọn được tìm kiếm bởi những người biết bạn."; +"auth_login_single_sign_on" = "Đăng nhập"; + +// Accessibility +"accessibility_checkbox_label" = "checkbox"; +"callbar_only_single_active_group" = "Nhấn để tham gia vào cuộc gọi nhóm (%@)"; +"callbar_return" = "Trở về"; +"callbar_only_multiple_paused" = "%@ cuộc gọi bị tạm dừng"; +"callbar_only_single_paused" = "Cuộc gọi bị tạm dừng"; +"callbar_active_and_multiple_paused" = "1 cuộc gọi đang hoạt động (%@) · %@ cuộc gọi bị tạm dừng"; +"callbar_active_and_single_paused" = "1 cuộc gọi đang hoạt động (%@) · 1 cuộc gọi đang tạm dừng"; + +// Call Bar +"callbar_only_single_active" = "Nhấn để quay lại cuộc gọi (%@)"; +"done" = "Hoàn thành"; +"open" = "Mở"; +"less" = "Ít hơn"; +"more" = "Nhiều hơn"; +"switch" = "Chuyển"; +"joined" = "Đã tham gia"; +"skip" = "Bỏ qua"; +"close" = "Đóng"; +"store_promotional_text" = "Ứng dụng trò chuyện và cộng tác bảo vệ quyền riêng tư, trên mạng mở. Phi tập trung để đưa bạn vào tầm kiểm soát. Không có datamining, không có backdoors và không có quyền truy cập của bên thứ ba."; +"store_full_description" = "Element là một loại ứng dụng cộng tác và nhắn tin mới:\n\n1. Đặt bạn kiểm soát để giữ quyền riêng tư của bạn\n2. Cho phép bạn giao tiếp với bất kỳ ai trong mạng Matrix, và thậm chí hơn thế nữa bằng cách tích hợp với các ứng dụng như Slack\n3. Bảo vệ bạn khỏi quảng cáo, datamining, cửa hậu và khu vườn có tường bao quanh\n4. Bảo mật bạn thông qua mã hóa đầu cuối, với việc ký chéo để xác minh người khác\n\nElement hoàn toàn khác với các ứng dụng nhắn tin và cộng tác khác vì nó được phân cấp và nguồn mở.\n\nElement cho phép bạn tự lưu trữ - hoặc chọn máy chủ - để bạn có quyền riêng tư, quyền sở hữu và kiểm soát dữ liệu và cuộc trò chuyện của mình. Nó cho phép bạn truy cập vào một mạng mở; vì vậy, bạn không chỉ bị mắc kẹt khi nói chuyện với những người dùng Element khác. Và nó rất an toàn.\n\nElement có thể làm tất cả điều này bởi vì nó hoạt động trên Matrix - tiêu chuẩn cho giao tiếp mở, phi tập trung. \n\nElement giúp bạn kiểm soát bằng cách cho phép bạn chọn người tổ chức các cuộc trò chuyện của bạn. Từ ứng dụng Element, bạn có thể chọn lưu trữ theo nhiều cách khác nhau:\n\n1. Nhận tài khoản miễn phí trên máy chủ công cộng matrix.org\n2. Tự lưu trữ tài khoản của bạn bằng cách chạy máy chủ trên phần cứng của riêng bạn\n3. Đăng ký tài khoản trên máy chủ tùy chỉnh bằng cách đăng ký vào nền tảng lưu trữ Dịch vụ Element Matrix\n\nTại sao chọn Element?\n\nSở hữu dữ liệu của bạn: Bạn quyết định nơi để giữ dữ liệu và tin nhắn của bạn. Bạn sở hữu nó và kiểm soát nó, không phải một số MEGACORP khai thác dữ liệu của bạn hoặc cho phép truy cập vào bên thứ ba.\n\nTIN NHẮN MỞ VÀ CỘNG TÁC: Bạn có thể trò chuyện với bất kỳ ai khác trong mạng Matrix, cho dù họ đang sử dụng Element hay ứng dụng Matrix khác và ngay cả khi họ đang sử dụng một hệ thống nhắn tin khác như Slack, IRC hoặc XMPP.\n\nSUPER-SECURE: Mã hóa đầu cuối thực sự (chỉ những người trong cuộc trò chuyện mới có thể giải mã tin nhắn) và ký chéo để xác minh các thiết bị của người tham gia hội thoại.\n\nGIAO TIẾP ĐẦY ĐỦ: Nhắn tin, cuộc gọi thoại và video, chia sẻ tệp, chia sẻ màn hình và một loạt các tích hợp, bot và tiện ích. Xây dựng phòng, cộng đồng, giữ liên lạc và hoàn thành công việc.\n\nỞ mọi nơi bạn đang có: Giữ liên lạc bất cứ nơi nào bạn đang có với lịch sử tin nhắn được đồng bộ hóa hoàn toàn trên tất cả các thiết bị của bạn và trên web tại https://element.io/app."; +// String for App Store +"store_short_description" = "Chat/VoIP bảo mật phi tập trung"; From 055c30e75b85328c8d4bcd02dff6b50ba038500e Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 4 Nov 2021 12:29:49 +0000 Subject: [PATCH 030/122] Expand on BuildingSetting description and add changelog --- Config/BuildSettings.swift | 6 ++++-- changelog.d/4981.feature | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) create mode 100644 changelog.d/4981.feature diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 4daf809ad..d740eb29a 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -134,12 +134,14 @@ final class BuildSettings: NSObject { "matrix.to": ["/"], "www.matrix.to": ["/"], // Client Permalinks (for use with `BuildSettings.clientPermalinkBaseUrl`) -// "clienturl.com": ["/"], -// "www.clienturl.com": ["/"], +// "example.com": ["/"], +// "www.example.com": ["/"], ] // For use in clients that use a custom base url for permalinks rather than matrix.to. // This baseURL is used to generate permalinks within the app (E.g. timeline message permalinks). + // Optional String that when set is used as permalink base, when nil matrix.to format is used. + // Example value would be "https://www.example.com", note there is no trailing '/'. static let clientPermalinkBaseUrl: String? = nil // MARK: - VoIP diff --git a/changelog.d/4981.feature b/changelog.d/4981.feature new file mode 100644 index 000000000..2d1a3e79f --- /dev/null +++ b/changelog.d/4981.feature @@ -0,0 +1 @@ +Adds clientPermalinkBaseUrl for a custom permalink base url. From 7f313ca4f5d46de26acdba75d3a6b7bcb560715d Mon Sep 17 00:00:00 2001 From: David Langley Date: Thu, 4 Nov 2021 16:22:58 +0000 Subject: [PATCH 031/122] Update matrixPermalinkPaths -> permalinkSupportedHosts for consistency with android naming --- Config/BuildSettings.swift | 8 ++++---- Riot/Utils/Tools.m | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index d740eb29a..bd6b63d83 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -118,9 +118,9 @@ final class BuildSettings: NSObject { "https://element.io/help" - // MARk: - Matrix permalinks - // Paths for URLs that will considered as Matrix permalinks. Those permalinks are opened within the app - static let matrixPermalinkPaths: [String: [String]] = [ + // MARK: - Permalinks + // Hosts/Paths for URLs that will considered as valid permalinks. Those permalinks are opened within the app. + static let permalinkSupportedHosts: [String: [String]] = [ "app.element.io": [], "staging.element.io": [], "develop.element.io": [], @@ -142,7 +142,7 @@ final class BuildSettings: NSObject { // This baseURL is used to generate permalinks within the app (E.g. timeline message permalinks). // Optional String that when set is used as permalink base, when nil matrix.to format is used. // Example value would be "https://www.example.com", note there is no trailing '/'. - static let clientPermalinkBaseUrl: String? = nil + static let clientPermalinkBaseUrl: String? = "https://app.element.io" // MARK: - VoIP static var allowVoIPUsage: Bool { diff --git a/Riot/Utils/Tools.m b/Riot/Utils/Tools.m index 66fe38d0c..c939b0fd4 100644 --- a/Riot/Utils/Tools.m +++ b/Riot/Utils/Tools.m @@ -66,11 +66,11 @@ { BOOL isUniversalLink = NO; - for (NSString *matrixPermalinkHost in BuildSettings.matrixPermalinkPaths) + for (NSString *matrixPermalinkHost in BuildSettings.permalinkSupportedHosts) { if ([url.host isEqualToString:matrixPermalinkHost]) { - NSArray *hostPaths = BuildSettings.matrixPermalinkPaths[matrixPermalinkHost]; + NSArray *hostPaths = BuildSettings.permalinkSupportedHosts[matrixPermalinkHost]; if (hostPaths.count) { // iOS Patch: fix urls before using it From ee2385a246a4b2063e67914c0a338ee4922cfd1d Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 5 Nov 2021 11:08:51 +0000 Subject: [PATCH 032/122] Set correct default for clientPermalinkBaseUrl --- Config/BuildSettings.swift | 2 +- changelog.d/5098.bugfix | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 changelog.d/5098.bugfix diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index bd6b63d83..6c15d412c 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -142,7 +142,7 @@ final class BuildSettings: NSObject { // This baseURL is used to generate permalinks within the app (E.g. timeline message permalinks). // Optional String that when set is used as permalink base, when nil matrix.to format is used. // Example value would be "https://www.example.com", note there is no trailing '/'. - static let clientPermalinkBaseUrl: String? = "https://app.element.io" + static let clientPermalinkBaseUrl: String? = nil // MARK: - VoIP static var allowVoIPUsage: Bool { diff --git a/changelog.d/5098.bugfix b/changelog.d/5098.bugfix new file mode 100644 index 000000000..77a90543a --- /dev/null +++ b/changelog.d/5098.bugfix @@ -0,0 +1 @@ +Invalid default value set for clientPermalinkBaseUrl. From 7985841123177561fc935c11bf7dd07fe25d96c6 Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 5 Nov 2021 15:07:08 +0000 Subject: [PATCH 033/122] Add concurrency to GitHub workflows to auto-cancel older runs. --- .github/workflows/ci-build.yml | 5 +++++ .github/workflows/ci-tests.yml | 5 +++++ .github/workflows/release-alpha.yml | 5 +++++ changelog.d/5039.build | 1 + 4 files changed, 16 insertions(+) create mode 100644 changelog.d/5039.build diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index c86de1d80..9f2480d88 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -17,6 +17,11 @@ jobs: build: name: Build runs-on: macos-11 + + # Only allow a single run of this workflow on each branch (cancel older runs automatically) + concurrency: + group: build-${{ github.head_ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 65846be15..aa9645b29 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -17,6 +17,11 @@ jobs: tests: name: Tests runs-on: macos-11 + + # Only allow a single run of this workflow on each branch (cancel older runs automatically) + concurrency: + group: tests-${{ github.head_ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/release-alpha.yml b/.github/workflows/release-alpha.yml index ed175fe20..544a05e28 100644 --- a/.github/workflows/release-alpha.yml +++ b/.github/workflows/release-alpha.yml @@ -16,6 +16,11 @@ jobs: build: name: Release runs-on: macos-11 + + # Only allow a single run of this workflow on each branch (cancel older runs automatically) + concurrency: + group: alpha-${{ github.head_ref }} + cancel-in-progress: true steps: - uses: actions/checkout@v2 diff --git a/changelog.d/5039.build b/changelog.d/5039.build new file mode 100644 index 000000000..0da3a457f --- /dev/null +++ b/changelog.d/5039.build @@ -0,0 +1 @@ +Add concurrency to the GitHub workflows to auto-cancel older runs of each action. \ No newline at end of file From 0a73f6cdac6cb4220a28e31b35bf27d63014186a Mon Sep 17 00:00:00 2001 From: Doug Date: Fri, 5 Nov 2021 16:05:35 +0000 Subject: [PATCH 034/122] Remove concurrency restriction on develop. --- .github/workflows/ci-build.yml | 5 +++-- .github/workflows/ci-tests.yml | 5 +++-- .github/workflows/release-alpha.yml | 5 +++-- changelog.d/5039.build | 2 +- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index 9f2480d88..fd5b34876 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -18,9 +18,10 @@ jobs: name: Build runs-on: macos-11 - # Only allow a single run of this workflow on each branch (cancel older runs automatically) concurrency: - group: build-${{ github.head_ref }} + # When running on develop, use the sha to allow all runs of this workflow to run concurrently. + # Otherwise only allow a single run of this workflow on each branch, automatically cancelling older runs. + group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}', github.sha) || format('build-{0}', github.ref) }} cancel-in-progress: true steps: diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index aa9645b29..0fd4f4f61 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -18,9 +18,10 @@ jobs: name: Tests runs-on: macos-11 - # Only allow a single run of this workflow on each branch (cancel older runs automatically) concurrency: - group: tests-${{ github.head_ref }} + # When running on develop, use the sha to allow all runs of this workflow to run concurrently. + # Otherwise only allow a single run of this workflow on each branch, automatically cancelling older runs. + group: ${{ github.ref == 'refs/heads/develop' && format('tests-develop-{0}', github.sha) || format('tests-{0}', github.ref) }} cancel-in-progress: true steps: diff --git a/.github/workflows/release-alpha.yml b/.github/workflows/release-alpha.yml index 544a05e28..887419e26 100644 --- a/.github/workflows/release-alpha.yml +++ b/.github/workflows/release-alpha.yml @@ -17,9 +17,10 @@ jobs: name: Release runs-on: macos-11 - # Only allow a single run of this workflow on each branch (cancel older runs automatically) concurrency: - group: alpha-${{ github.head_ref }} + # When running on develop, use the sha to allow all runs of this workflow to run concurrently. + # Otherwise only allow a single run of this workflow on each branch, automatically cancelling older runs. + group: ${{ github.ref == 'refs/heads/develop' && format('alpha-develop-{0}', github.sha) || format('alpha-{0}', github.ref) }} cancel-in-progress: true steps: diff --git a/changelog.d/5039.build b/changelog.d/5039.build index 0da3a457f..f791f36fb 100644 --- a/changelog.d/5039.build +++ b/changelog.d/5039.build @@ -1 +1 @@ -Add concurrency to the GitHub workflows to auto-cancel older runs of each action. \ No newline at end of file +Add concurrency to the GitHub workflows to auto-cancel older runs of each action for PRs. \ No newline at end of file From c9a19e60db0767916bbaa13aa74bdf8fa84e980f Mon Sep 17 00:00:00 2001 From: LinAGKar Date: Fri, 5 Nov 2021 21:57:16 +0000 Subject: [PATCH 035/122] Translated using Weblate (Swedish) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/sv/ --- Riot/Assets/sv.lproj/Vector.strings | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/Riot/Assets/sv.lproj/Vector.strings b/Riot/Assets/sv.lproj/Vector.strings index 1cc6e7b2c..eacf7e0f7 100644 --- a/Riot/Assets/sv.lproj/Vector.strings +++ b/Riot/Assets/sv.lproj/Vector.strings @@ -1442,3 +1442,29 @@ "find_your_contacts_title" = "Börja genom att lista dina kontakter"; "contacts_address_book_permission_denied_alert_message" = "För att aktivera kontakter, gå till dina enhetsinställningar."; "contacts_address_book_permission_denied_alert_title" = "Kontakter inaktiverat"; +"space_avatar_view_accessibility_hint" = "Byt utrymmesavatar"; + +// Mark: Avatar + +"space_avatar_view_accessibility_label" = "avatar"; +"space_public_join_rule" = "Offentligt utrymme"; +"space_private_join_rule" = "Privat utrymme"; +"space_home_show_all_rooms" = "Visa alla rum"; +"space_participants_action_ban" = "Banna från det här utrymmet"; +"space_participants_action_remove" = "Ta bort från det här utrymmet"; +"spaces_coming_soon_detail" = "Den här funktionen har inte bjudits in än, men den är på väg. För tillfället så kan du göra det med Element på din dator."; +"spaces_invites_coming_soon_title" = "Inbjudningar kommer snart"; +"spaces_add_rooms_coming_soon_title" = "Tilläggning av rum kommer snart"; +"spaces_coming_soon_title" = "Kommer snart"; +"spaces_no_member_found_detail" = "Söker du någon som inte är i %@? För tillfället så kan du bjuda in dem på webben eller i skrivbordsappen."; +"spaces_no_room_found_detail" = "Vissa resultat kan vara dolda för att de är privata och du behöver en inbjudan för att gå med i dem."; +"spaces_no_result_found_title" = "Inga resultat funna"; +"spaces_empty_space_detail" = "Vissa rum kan vara dolda för att det är privata och du behöver en inbjudan."; +"spaces_empty_space_title" = "Det här utrymmet har inge rum (än)"; +"space_tag" = "utrymme"; +"spaces_suggested_room" = "Föreslaget"; +"spaces_explore_rooms" = "Utforska rum"; +"leave_space_and_all_rooms_action" = "Lämna alla rum och utrymmen"; +"leave_space_only_action" = "Lämna inga rum"; +"leave_space_message_admin_warning" = "Du är admin för det här utrymmet, försäkra att du har överfört adminrättigheter till en annan medlem innan du lämnar."; +"leave_space_message" = "Är du säker på att du vill lämna %@? Vill du även lämna alla rum och utrymmen i det här utrymmet?"; From c201ebced1a5635673d4c3d850a60171becf2f6e Mon Sep 17 00:00:00 2001 From: Doug Date: Mon, 8 Nov 2021 18:27:46 +0000 Subject: [PATCH 036/122] Only run build CI on develop. --- .github/workflows/ci-build.yml | 7 +------ .github/workflows/release-alpha.yml | 5 ++--- changelog.d/pr-5112.build | 1 + 3 files changed, 4 insertions(+), 9 deletions(-) create mode 100644 changelog.d/pr-5112.build diff --git a/.github/workflows/ci-build.yml b/.github/workflows/ci-build.yml index fd5b34876..ea00a5276 100644 --- a/.github/workflows/ci-build.yml +++ b/.github/workflows/ci-build.yml @@ -4,7 +4,6 @@ on: # Triggers the workflow on any pull request and push to develop push: branches: [ develop ] - pull_request: # Allows you to run this workflow manually from the Actions tab workflow_dispatch: @@ -18,11 +17,7 @@ jobs: name: Build runs-on: macos-11 - concurrency: - # When running on develop, use the sha to allow all runs of this workflow to run concurrently. - # Otherwise only allow a single run of this workflow on each branch, automatically cancelling older runs. - group: ${{ github.ref == 'refs/heads/develop' && format('build-develop-{0}', github.sha) || format('build-{0}', github.ref) }} - cancel-in-progress: true + # Concurrency group not needed as this workflow only runs on develop which we always want to test. steps: - uses: actions/checkout@v2 diff --git a/.github/workflows/release-alpha.yml b/.github/workflows/release-alpha.yml index 887419e26..c0fd48646 100644 --- a/.github/workflows/release-alpha.yml +++ b/.github/workflows/release-alpha.yml @@ -18,9 +18,8 @@ jobs: runs-on: macos-11 concurrency: - # When running on develop, use the sha to allow all runs of this workflow to run concurrently. - # Otherwise only allow a single run of this workflow on each branch, automatically cancelling older runs. - group: ${{ github.ref == 'refs/heads/develop' && format('alpha-develop-{0}', github.sha) || format('alpha-{0}', github.ref) }} + # Only allow a single run of this workflow on each branch, automatically cancelling older runs. + group: alpha-${{ github.head_ref }} cancel-in-progress: true steps: diff --git a/changelog.d/pr-5112.build b/changelog.d/pr-5112.build new file mode 100644 index 000000000..438d21339 --- /dev/null +++ b/changelog.d/pr-5112.build @@ -0,0 +1 @@ +Only run Build CI on develop, as it is already covered by Tests and Alpha. \ No newline at end of file From 3fe141473c079bf480e4933f5530346e0683e9b6 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Thu, 28 Oct 2021 10:16:22 +0300 Subject: [PATCH 037/122] vector-im/element-ios/pull/5014 - Forward original message content and remove the need to re-upload media. --- Riot/Modules/Room/RoomViewController.m | 572 +++++------ Riot/SupportingFiles/Riot-Bridging-Header.h | 1 + .../Shared/ForwardingShareItemSender.swift | 75 ++ .../SimpleShareItemProvider.swift | 109 --- .../Shared/ShareItemSenderProtocol.h | 41 + RiotShareExtension/Shared/ShareManager.h | 6 +- RiotShareExtension/Shared/ShareManager.m | 904 +----------------- .../Shared/View/RecentRoomTableViewCell.m | 1 + .../Shared/View/ShareViewController.m | 2 +- .../ShareExtensionRootViewController.m | 29 +- .../ShareExtensionShareItemProvider.swift | 6 +- .../ShareItemProtocol.swift} | 12 +- RiotShareExtension/Sources/ShareItemSender.h | 32 + RiotShareExtension/Sources/ShareItemSender.m | 892 +++++++++++++++++ .../RiotShareExtension-Bridging-Header.h | 1 + changelog.d/5014.change | 1 + 16 files changed, 1341 insertions(+), 1343 deletions(-) create mode 100644 RiotShareExtension/Shared/ForwardingShareItemSender.swift delete mode 100644 RiotShareExtension/Shared/ShareItemProvider/SimpleShareItemProvider.swift create mode 100644 RiotShareExtension/Shared/ShareItemSenderProtocol.h rename RiotShareExtension/{Shared/ShareItemProvider/ShareItemProviderProtocol.swift => Sources/ShareItemProtocol.swift} (67%) create mode 100644 RiotShareExtension/Sources/ShareItemSender.h create mode 100644 RiotShareExtension/Sources/ShareItemSender.m create mode 100644 changelog.d/5014.change diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 3e9fca373..eba7a4ba4 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -3149,7 +3149,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; currentAlert = nil; } - __weak __typeof(self) weakSelf = self; + MXWeakify(self); currentAlert = [UIAlertController alertControllerWithTitle:nil message:nil preferredStyle:UIAlertControllerStyleActionSheet]; // Add actions for a failed event @@ -3158,32 +3158,22 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n retry] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Let the datasource resend. It will manage local echo, etc. - [self.roomDataSource resendEventWithEventId:selectedEvent.eventId success:nil failure:nil]; - } + [self cancelEventSelection]; + // Let the datasource resend. It will manage local echo, etc. + [self.roomDataSource resendEventWithEventId:selectedEvent.eventId success:nil failure:nil]; }]]; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionDelete] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; - } + [self cancelEventSelection]; + [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; }]]; } @@ -3210,60 +3200,42 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; { [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelSend] style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) - { - if (weakSelf) - { - typeof(self) self = weakSelf; - - self->currentAlert = nil; - - // Cancel and remove the outgoing message - [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; - [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; - - [self cancelEventSelection]; - } + handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + + // Cancel and remove the outgoing message + [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; + [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; + + [self cancelEventSelection]; }]]; } - [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward] - style:UIAlertActionStyleDefault - handler:^(UIAlertAction * action) { - self.shareManager = [[ShareManager alloc] initWithShareItemProvider:[[SimpleShareItemProvider alloc] initWithTextMessage:selectedComponent.textMessage] - type:ShareManagerTypeForward]; - - MXWeakify(self); - [self.shareManager setCompletionCallback:^(ShareManagerResult result) { + if (selectedEvent.sentState == MXEventSentStateSent) { + [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward] + style:UIAlertActionStyleDefault + handler:^(UIAlertAction * action) { MXStrongifyAndReturnIfNil(self); - [attachment onShareEnded]; - [self dismissViewControllerAnimated:YES completion:nil]; - self.shareManager = nil; - }]; - - [self presentViewController:self.shareManager.mainViewController animated:YES completion:nil]; - }]]; + [self presentEventForwardingDialogForSelectedEvent:selectedEvent]; + }]]; + } if (!isJitsiCallEvent) { [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionQuote] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Quote the message a la Markdown into the input toolbar composer - self.inputToolbarView.textMessage = [NSString stringWithFormat:@"%@\n>%@\n\n", self.inputToolbarView.textMessage, selectedComponent.textMessage]; - - // And display the keyboard - [self.inputToolbarView becomeFirstResponder]; - } + [self cancelEventSelection]; + // Quote the message a la Markdown into the input toolbar composer + self.inputToolbarView.textMessage = [NSString stringWithFormat:@"%@\n>%@\n\n", self.inputToolbarView.textMessage, selectedComponent.textMessage]; + + // And display the keyboard + [self.inputToolbarView becomeFirstResponder]; }]]; } @@ -3272,52 +3244,37 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionShare] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) + [self cancelEventSelection]; + + NSArray *activityItems = @[selectedComponent.textMessage]; + + UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; + + if (activityViewController) { - typeof(self) self = weakSelf; + activityViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; + activityViewController.popoverPresentationController.sourceView = roomBubbleTableViewCell; + activityViewController.popoverPresentationController.sourceRect = roomBubbleTableViewCell.bounds; - [self cancelEventSelection]; - - NSArray *activityItems = @[selectedComponent.textMessage]; - - UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil]; - - if (activityViewController) - { - activityViewController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - activityViewController.popoverPresentationController.sourceView = roomBubbleTableViewCell; - activityViewController.popoverPresentationController.sourceRect = roomBubbleTableViewCell.bounds; - - [self presentViewController:activityViewController animated:YES completion:nil]; - } + [self presentViewController:activityViewController animated:YES completion:nil]; } - }]]; } } else // Add action for attachment { - if (attachment.type == MXKAttachmentTypeFile || - attachment.type == MXKAttachmentTypeImage || - attachment.type == MXKAttachmentTypeVideo || - attachment.type == MXKAttachmentTypeVoiceMessage) { - + // Forwarding for already sent attachments + if (selectedEvent.sentState == MXEventSentStateSent && (attachment.type == MXKAttachmentTypeFile || + attachment.type == MXKAttachmentTypeImage || + attachment.type == MXKAttachmentTypeVideo || + attachment.type == MXKAttachmentTypeVoiceMessage)) { [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionForward] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - self.shareManager = [[ShareManager alloc] initWithShareItemProvider:[[SimpleShareItemProvider alloc] initWithAttachment:attachment] - type:ShareManagerTypeForward]; - - MXWeakify(self); - [self.shareManager setCompletionCallback:^(ShareManagerResult result) { - MXStrongifyAndReturnIfNil(self); - [attachment onShareEnded]; - [self dismissViewControllerAnimated:YES completion:nil]; - self.shareManager = nil; - }]; - - [self presentViewController:self.shareManager.mainViewController animated:YES completion:nil]; + MXStrongifyAndReturnIfNil(self); + [self presentEventForwardingDialogForSelectedEvent:selectedEvent]; }]]; } @@ -3328,34 +3285,26 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionSave] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - [self startActivityIndicator]; - - [attachment save:^{ - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - } failure:^(NSError *error) { - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - //Alert user - [self showError:error]; - - }]; - - // Start animation in case of download during attachment preparing - [roomBubbleTableViewCell startProgressUI]; - } + [self cancelEventSelection]; + [self startActivityIndicator]; + + MXWeakify(self); + [attachment save:^{ + MXStrongifyAndReturnIfNil(self); + [self stopActivityIndicator]; + } failure:^(NSError *error) { + MXStrongifyAndReturnIfNil(self); + [self stopActivityIndicator]; + + //Alert user + [self showError:error]; + }]; + + // Start animation in case of download during attachment preparing + [roomBubbleTableViewCell startProgressUI]; }]]; } } @@ -3374,6 +3323,8 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + // Get again the loader MXMediaLoader *loader = [MXMediaManager existingUploaderWithId:uploadId]; if (loader) @@ -3383,23 +3334,17 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; // Hide the progress animation roomBubbleTableViewCell.progressView.hidden = YES; - if (weakSelf) - { - typeof(self) self = weakSelf; - - self->currentAlert = nil; - - // Remove the outgoing message and its related cached file. - [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.cacheFilePath error:nil]; - [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.thumbnailCachePath error:nil]; - - // Cancel and remove the outgoing message - [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; - [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; - - [self cancelEventSelection]; - } + self->currentAlert = nil; + // Remove the outgoing message and its related cached file. + [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.cacheFilePath error:nil]; + [[NSFileManager defaultManager] removeItemAtPath:roomBubbleTableViewCell.bubbleData.attachment.thumbnailCachePath error:nil]; + + // Cancel and remove the outgoing message + [self.roomDataSource.room cancelSendingOperation:selectedEvent.eventId]; + [self.roomDataSource removeEventWithEventId:selectedEvent.eventId]; + + [self cancelEventSelection]; }]]; } } @@ -3411,39 +3356,36 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionShare] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - [self startActivityIndicator]; - - [attachment prepareShare:^(NSURL *fileURL) { - [self stopActivityIndicator]; - - __strong __typeof(weakSelf)self = weakSelf; - self->documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL]; - [self->documentInteractionController setDelegate:self]; - self->currentSharedAttachment = attachment; - - if (![self->documentInteractionController presentOptionsMenuFromRect:self.view.frame inView:self.view animated:YES]) - { - self->documentInteractionController = nil; - [attachment onShareEnded]; - self->currentSharedAttachment = nil; - } - - } failure:^(NSError *error) { - [self showError:error]; - [self stopActivityIndicator]; - }]; - - // Start animation in case of download during attachment preparing - [roomBubbleTableViewCell startProgressUI]; - } + [self cancelEventSelection]; + [self startActivityIndicator]; + + MXWeakify(self); + [attachment prepareShare:^(NSURL *fileURL) { + MXStrongifyAndReturnIfNil(self); + + [self stopActivityIndicator]; + + self->documentInteractionController = [UIDocumentInteractionController interactionControllerWithURL:fileURL]; + [self->documentInteractionController setDelegate:self]; + self->currentSharedAttachment = attachment; + + if (![self->documentInteractionController presentOptionsMenuFromRect:self.view.frame inView:self.view animated:YES]) + { + self->documentInteractionController = nil; + [attachment onShareEnded]; + self->currentSharedAttachment = nil; + } + + } failure:^(NSError *error) { + [self showError:error]; + [self stopActivityIndicator]; + }]; + + // Start animation in case of download during attachment preparing + [roomBubbleTableViewCell startProgressUI]; }]]; } } @@ -3461,23 +3403,18 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionCancelDownload] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) + [self cancelEventSelection]; + + // Get again the loader + MXMediaLoader *loader = [MXMediaManager existingDownloaderWithIdentifier:downloadId]; + if (loader) { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Get again the loader - MXMediaLoader *loader = [MXMediaManager existingDownloaderWithIdentifier:downloadId]; - if (loader) - { - [loader cancel]; - } - // Hide the progress animation - roomBubbleTableViewCell.progressView.hidden = YES; + [loader cancel]; } - + // Hide the progress animation + roomBubbleTableViewCell.progressView.hidden = YES; }]]; } } @@ -3489,32 +3426,24 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionRedact] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - [self startActivityIndicator]; - - [self.roomDataSource.room redactEvent:selectedEvent.eventId reason:nil success:^{ - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - } failure:^(NSError *error) { - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - MXLogDebug(@"[RoomVC] Redact event (%@) failed", selectedEvent.eventId); - //Alert user - [self showError:error]; - - }]; - } + [self cancelEventSelection]; + [self startActivityIndicator]; + + MXWeakify(self); + [self.roomDataSource.room redactEvent:selectedEvent.eventId reason:nil success:^{ + MXStrongifyAndReturnIfNil(self); + [self stopActivityIndicator]; + } failure:^(NSError *error) { + MXStrongifyAndReturnIfNil(self); + [self stopActivityIndicator]; + + MXLogDebug(@"[RoomVC] Redact event (%@) failed", selectedEvent.eventId); + //Alert user + [self showError:error]; + }]; }]]; } @@ -3523,26 +3452,21 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionPermalink] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) + [self cancelEventSelection]; + + // Create a matrix.to permalink that is common to all matrix clients + NSString *permalink = [MXTools permalinkToEvent:selectedEvent.eventId inRoom:selectedEvent.roomId]; + + if (permalink) { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Create a matrix.to permalink that is common to all matrix clients - NSString *permalink = [MXTools permalinkToEvent:selectedEvent.eventId inRoom:selectedEvent.roomId]; - - if (permalink) - { - MXKPasteboardManager.shared.pasteboard.string = permalink; - } - else - { - MXLogDebug(@"[RoomViewController] Contextual menu permalink action failed. Permalink is nil room id/event id: %@/%@", selectedEvent.roomId, selectedEvent.eventId); - } + MXKPasteboardManager.shared.pasteboard.string = permalink; + } + else + { + MXLogDebug(@"[RoomViewController] Contextual menu permalink action failed. Permalink is nil room id/event id: %@/%@", selectedEvent.roomId, selectedEvent.eventId); } - }]]; } @@ -3552,6 +3476,7 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionReactionHistory] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); [self cancelEventSelection]; @@ -3565,17 +3490,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewSource] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Display event details - [self showEventDetails:selectedEvent]; - } + [self cancelEventSelection]; + // Display event details + [self showEventDetails:selectedEvent]; }]]; @@ -3585,17 +3505,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewDecryptedSource] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - - [self cancelEventSelection]; - - // Display clear event details - [self showEventDetails:selectedEvent.clearEvent]; - } + [self cancelEventSelection]; + // Display clear event details + [self showEventDetails:selectedEvent.clearEvent]; }]]; } } @@ -3605,108 +3520,84 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionReport] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; + [self cancelEventSelection]; + + // Prompt user to enter a description of the problem content. + self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptReason] message:nil preferredStyle:UIAlertControllerStyleAlert]; + + [self->currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) { + textField.secureTextEntry = NO; + textField.placeholder = nil; + textField.keyboardType = UIKeyboardTypeDefault; + }]; + + MXWeakify(self); + [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - [self cancelEventSelection]; + NSString *text = [self->currentAlert textFields].firstObject.text; + self->currentAlert = nil; - // Prompt user to enter a description of the problem content. - self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptReason] message:nil preferredStyle:UIAlertControllerStyleAlert]; + [self startActivityIndicator]; - [self->currentAlert addTextFieldWithConfigurationHandler:^(UITextField *textField) { - textField.secureTextEntry = NO; - textField.placeholder = nil; - textField.keyboardType = UIKeyboardTypeDefault; - }]; - - [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n ok] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXWeakify(self); + [self.roomDataSource.room reportEvent:selectedEvent.eventId score:-100 reason:text success:^{ + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - NSString *text = [self->currentAlert textFields].firstObject.text; + [self stopActivityIndicator]; + + // Prompt user to ignore content from this user + self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptIgnoreUser] message:nil preferredStyle:UIAlertControllerStyleAlert]; + + MXWeakify(self); + [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + + MXStrongifyAndReturnIfNil(self); self->currentAlert = nil; [self startActivityIndicator]; - [self.roomDataSource.room reportEvent:selectedEvent.eventId score:-100 reason:text success:^{ - - __strong __typeof(weakSelf)self = weakSelf; + MXWeakify(self); + // Add the user to the blacklist: ignored users + [self.mainSession ignoreUsers:@[selectedEvent.sender] success:^{ + MXStrongifyAndReturnIfNil(self); [self stopActivityIndicator]; - - // Prompt user to ignore content from this user - self->currentAlert = [UIAlertController alertControllerWithTitle:[VectorL10n roomEventActionReportPromptIgnoreUser] message:nil preferredStyle:UIAlertControllerStyleAlert]; - - [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n yes] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - - [self startActivityIndicator]; - - // Add the user to the blacklist: ignored users - [self.mainSession ignoreUsers:@[selectedEvent.sender] success:^{ - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - } failure:^(NSError *error) { - - __strong __typeof(weakSelf)self = weakSelf; - [self stopActivityIndicator]; - - MXLogDebug(@"[RoomVC] Ignore user (%@) failed", selectedEvent.sender); - //Alert user - [self showError:error]; - - }]; - } - - }]]; - - [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; - self->currentAlert = nil; - } - - }]]; - - [self presentViewController:self->currentAlert animated:YES completion:nil]; - } failure:^(NSError *error) { - - __strong __typeof(weakSelf)self = weakSelf; + MXStrongifyAndReturnIfNil(self); [self stopActivityIndicator]; - MXLogDebug(@"[RoomVC] Report event (%@) failed", selectedEvent.eventId); + MXLogDebug(@"[RoomVC] Ignore user (%@) failed", selectedEvent.sender); //Alert user [self showError:error]; - }]; - } + }]]; - }]]; - - [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { - - if (weakSelf) - { - typeof(self) self = weakSelf; + [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n no] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); self->currentAlert = nil; - } + }]]; - }]]; - - [self presentViewController:self->currentAlert animated:YES completion:nil]; - } + [self presentViewController:self->currentAlert animated:YES completion:nil]; + + } failure:^(NSError *error) { + MXStrongifyAndReturnIfNil(self); + [self stopActivityIndicator]; + + MXLogDebug(@"[RoomVC] Report event (%@) failed", selectedEvent.eventId); + //Alert user + [self showError:error]; + + }]; + }]]; + [self->currentAlert addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + self->currentAlert = nil; + }]]; + + [self presentViewController:self->currentAlert animated:YES completion:nil]; }]]; } @@ -3715,16 +3606,12 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n roomEventActionViewEncryption] style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - [self cancelEventSelection]; - - // Display encryption details - [self showEncryptionInformation:selectedEvent]; - } + [self cancelEventSelection]; + // Display encryption details + [self showEncryptionInformation:selectedEvent]; }]]; } } @@ -3732,13 +3619,9 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [currentAlert addAction:[UIAlertAction actionWithTitle:[VectorL10n cancel] style:UIAlertActionStyleCancel handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); - if (weakSelf) - { - typeof(self) self = weakSelf; - [self hideContextualMenuAnimated:YES]; - } - + [self hideContextualMenuAnimated:YES]; }]]; // Do not display empty action sheet @@ -3759,6 +3642,25 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; } } +- (void)presentEventForwardingDialogForSelectedEvent:(MXEvent *)selectedEvent +{ + ForwardingShareItemSender *shareItemSender = [[ForwardingShareItemSender alloc] initWithEvent:selectedEvent]; + self.shareManager = [[ShareManager alloc] initWithShareItemSender:shareItemSender + type:ShareManagerTypeForward]; + + MXWeakify(self); + [self.shareManager setCompletionCallback:^(ShareManagerResult result) { + MXStrongifyAndReturnIfNil(self); + if ([self.presentedViewController isEqual:self.shareManager.mainViewController]) + { + [self dismissViewControllerAnimated:YES completion:nil]; + } + self.shareManager = nil; + }]; + + [self presentViewController:self.shareManager.mainViewController animated:YES completion:nil]; +} + - (BOOL)dataSource:(MXKDataSource *)dataSource shouldDoAction:(NSString *)actionIdentifier inCell:(id)cell userInfo:(NSDictionary *)userInfo defaultValue:(BOOL)defaultValue { BOOL shouldDoAction = defaultValue; diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index 68dff2986..bc899b068 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -45,3 +45,4 @@ #import "GroupDetailsViewController.h" #import "RoomInputToolbarView.h" #import "NSArray+Element.h" +#import "ShareItemSender.h" diff --git a/RiotShareExtension/Shared/ForwardingShareItemSender.swift b/RiotShareExtension/Shared/ForwardingShareItemSender.swift new file mode 100644 index 000000000..84b866b27 --- /dev/null +++ b/RiotShareExtension/Shared/ForwardingShareItemSender.swift @@ -0,0 +1,75 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation + +@objcMembers +class ForwardingShareItemSender: NSObject, ShareItemSenderProtocol { + + static let errorDomain = "ForwardingShareItemSenderErrorDomain" + + enum ErrorCode: Int { + case eventNotSentYet + } + + private let event: MXEvent + + weak var delegate: ShareItemSenderDelegate? + + @objc public init(withEvent event: MXEvent) { + self.event = event + } + + func sendItems(to rooms: [MXRoom], success: @escaping () -> Void, failure: @escaping ([Error]) -> Void) { + guard event.sentState == MXEventSentStateSent else { + MXLog.error("[ForwardingShareItemSender] Cannot forward unsent event") + failure([NSError(domain: Self.errorDomain, + code: ErrorCode.eventNotSentYet.rawValue, + userInfo: nil)]) + return + } + + self.delegate?.shareItemSenderDidStartSending(self) + + var errors = [Error]() + + let dispatchGroup = DispatchGroup() + for room in rooms { + dispatchGroup.enter() + + var localEcho: MXEvent? + room.sendMessage(withContent: event.content, localEcho: &localEcho) { result in + switch result { + case .failure(let innerError): + errors.append(innerError) + default: + break + } + + dispatchGroup.leave() + } + } + + dispatchGroup.notify(queue: DispatchQueue.main) { + guard errors.count == 0 else { + failure(errors) + return + } + + success() + } + } +} diff --git a/RiotShareExtension/Shared/ShareItemProvider/SimpleShareItemProvider.swift b/RiotShareExtension/Shared/ShareItemProvider/SimpleShareItemProvider.swift deleted file mode 100644 index e08435aec..000000000 --- a/RiotShareExtension/Shared/ShareItemProvider/SimpleShareItemProvider.swift +++ /dev/null @@ -1,109 +0,0 @@ -// -// Copyright 2021 New Vector Ltd -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. -// - -import Foundation - -private class SimpleShareItem: ShareItemProtocol { - let attachment: MXKAttachment? - let textMessage: String? - - init(withAttachment attachment: MXKAttachment) { - self.attachment = attachment - self.textMessage = nil - } - - init(withTextMessage textMessage: String) { - self.attachment = nil - self.textMessage = textMessage - } - - var type: ShareItemType { - guard textMessage == nil else { - return .text - } - - guard let attachment = attachment else { - return .unknown - } - - if attachment.type == MXKAttachmentTypeImage { - return .image - } else if attachment.type == MXKAttachmentTypeVideo { - return .video - } else if attachment.type == MXKAttachmentTypeFile { - return .fileURL - } else if attachment.type == MXKAttachmentTypeVoiceMessage { - return .voiceMessage - } else { - return .unknown - } - } -} - -@objc class SimpleShareItemProvider: NSObject, ShareItemProviderProtocol { - - private let attachment: MXKAttachment? - private let textMessage: String? - - let items: [ShareItemProtocol] - - private override init() { - attachment = nil - textMessage = nil - self.items = [] - } - - @objc public init(withAttachment attachment: MXKAttachment) { - self.attachment = attachment - self.items = [SimpleShareItem(withAttachment: attachment)]; - self.textMessage = nil - } - - @objc public init(withTextMessage textMessage: String) { - self.textMessage = textMessage - self.items = [SimpleShareItem(withTextMessage: textMessage)]; - self.attachment = nil - } - - func loadItem(_ item: ShareItemProtocol, completion: @escaping (Any?, Error?) -> Void) { - if let textMessage = self.textMessage { - completion(textMessage, nil) - return - } - - guard let attachment = attachment else { - fatalError("[SimpleShareItemProvider] Invalid item provider state.") - } - - attachment.prepareShare({ url in - DispatchQueue.main.async { - completion(url, nil) - } - }, failure: { error in - DispatchQueue.main.async { - completion(nil, error) - } - }) - } - - func areAllItemsLoaded() -> Bool { - return true - } - - func areAllItemsImages() -> Bool { - return (attachment != nil && attachment?.type == MXKAttachmentTypeImage) - } -} diff --git a/RiotShareExtension/Shared/ShareItemSenderProtocol.h b/RiotShareExtension/Shared/ShareItemSenderProtocol.h new file mode 100644 index 000000000..ff3730a5e --- /dev/null +++ b/RiotShareExtension/Shared/ShareItemSenderProtocol.h @@ -0,0 +1,41 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@protocol ShareItemSenderProtocol; + +@class MXRoom; + +NS_ASSUME_NONNULL_BEGIN + +@protocol ShareItemSenderDelegate + +- (void)shareItemSenderDidStartSending:(id)shareItemSender; + +- (void)shareItemSender:(id)shareItemSender didUpdateProgress:(CGFloat)progress; + +@end + +@protocol ShareItemSenderProtocol + +@property (nonatomic, weak) id delegate; + +- (void)sendItemsToRooms:(NSArray *)rooms + success:(void(^)(void))success + failure:(void(^)(NSArray *))failure; + +@end + +NS_ASSUME_NONNULL_END diff --git a/RiotShareExtension/Shared/ShareManager.h b/RiotShareExtension/Shared/ShareManager.h index bb7245040..aef3e21f5 100644 --- a/RiotShareExtension/Shared/ShareManager.h +++ b/RiotShareExtension/Shared/ShareManager.h @@ -16,7 +16,7 @@ #import -@protocol ShareItemProviderProtocol; +@protocol ShareItemSenderProtocol; NS_ASSUME_NONNULL_BEGIN @@ -35,8 +35,8 @@ typedef NS_ENUM(NSUInteger, ShareManagerResult) { @property (nonatomic, copy) void (^completionCallback)(ShareManagerResult); -- (instancetype)initWithShareItemProvider:(id)shareItemProvider - type:(ShareManagerType)type; +- (instancetype)initWithShareItemSender:(id)itemSender + type:(ShareManagerType)type; - (UIViewController *)mainViewController; diff --git a/RiotShareExtension/Shared/ShareManager.m b/RiotShareExtension/Shared/ShareManager.m index 34fe3f67a..da77bfa18 100644 --- a/RiotShareExtension/Shared/ShareManager.m +++ b/RiotShareExtension/Shared/ShareManager.m @@ -23,74 +23,36 @@ #import "ShareManager.h" #import "ShareViewController.h" #import "ShareDataSource.h" +#import "ShareItemSenderProtocol.h" #import "GeneratedInterface-Swift.h" -static const CGFloat kLargeImageSizeMaxDimension = 2048.0; -static const CGSize kThumbnailSize = {800.0, 600.0}; -/// A safe maximum file size for an image to send the original. -static const NSUInteger kImageMaxFileSize = 20 * 1024 * 1024; +@interface ShareManager () -typedef NS_ENUM(NSInteger, ImageCompressionMode) -{ - ImageCompressionModeNone, - ImageCompressionModeSmall, - ImageCompressionModeMedium, - ImageCompressionModeLarge -}; +@property (nonatomic, strong, readonly) id shareItemSender; -@interface ShareManager () - -@property (nonatomic, strong, readonly) id shareItemProvider; @property (nonatomic, strong, readonly) ShareViewController *shareViewController; -@property (nonatomic, strong, readonly) NSMutableArray *pendingImages; -@property (nonatomic, strong, readonly) NSMutableDictionary *imageUploadProgresses; -@property (nonatomic, strong, readonly) id configuration; - @property (nonatomic, strong) MXKAccount *userAccount; @property (nonatomic, strong) MXFileStore *fileStore; -@property (nonatomic, assign) ImageCompressionMode imageCompressionMode; -@property (nonatomic, assign) CGFloat actualLargeSize; - @end @implementation ShareManager -- (instancetype)initWithShareItemProvider:(id)shareItemProvider - type:(ShareManagerType)type +- (instancetype)initWithShareItemSender:(id)itemSender + type:(ShareManagerType)type { if (self = [super init]) { - _shareItemProvider = shareItemProvider; + _shareItemSender = itemSender; + _shareItemSender.delegate = self; - _pendingImages = [NSMutableArray array]; - _imageUploadProgresses = [NSMutableDictionary dictionary]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaLoaderStateDidChange:) name:kMXMediaLoaderStateDidChangeNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkUserAccount) name:kMXKAccountManagerDidRemoveAccountNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkUserAccount) name:NSExtensionHostWillEnterForegroundNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(checkUserAccount) name:kMXKAccountManagerDidRemoveAccountNotification object:nil]; + [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(checkUserAccount) name:NSExtensionHostWillEnterForegroundNotification object:nil]; [NSNotificationCenter.defaultCenter addObserver:self selector:@selector(didReceiveMemoryWarning:) name:UIApplicationDidReceiveMemoryWarningNotification object:nil]; - _configuration = [[CommonConfiguration alloc] init]; - [_configuration setupSettings]; - - // NSLog -> console.log file when not debugging the app - MXLogConfiguration *configuration = [[MXLogConfiguration alloc] init]; - configuration.logLevel = MXLogLevelVerbose; - configuration.logFilesSizeLimit = 0; - configuration.maxLogFilesCount = 10; - configuration.subLogName = @"share"; - - // Redirect NSLogs to files only if we are not debugging - if (!isatty(STDERR_FILENO)) { - configuration.redirectLogsToFiles = YES; - } - - [MXLog configure:configuration]; - _shareViewController = [[ShareViewController alloc] initWithType:(type == ShareManagerTypeForward ? ShareViewControllerTypeForward : ShareViewControllerTypeSend) currentState:ShareViewControllerAccountStateNotConfigured]; [_shareViewController setDelegate:self]; @@ -135,9 +97,9 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } } - [self sendContentToRooms:rooms success:^{ + [self.shareItemSender sendItemsToRooms:rooms success:^{ self.completionCallback(ShareManagerResultFinished); - } failure:^(NSError *error){ + } failure:^(NSArray *errors) { [self showFailureAlert:[VectorL10n roomEventFailedToSend]]; }]; @@ -151,6 +113,18 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) self.completionCallback(ShareManagerResultCancelled); } +#pragma mark - ShareItemSenderDelegate + +- (void)shareItemSenderDidStartSending:(id)shareItemSender +{ + [self.shareViewController showProgressIndicator]; +} + +- (void)shareItemSender:(id)shareItemSender didUpdateProgress:(CGFloat)progress +{ + [self.shareViewController setProgress:progress]; +} + #pragma mark - Private - (void)showFailureAlert:(NSString *)title @@ -172,208 +146,6 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) [self.mainViewController presentViewController:alertController animated:YES completion:nil]; } -- (void)sendContentToRooms:(NSArray *)rooms success:(void(^)(void))success failure:(void(^)(NSError *))failure -{ - [self resetPendingData]; - - __block NSError *firstRequestError = nil; - dispatch_group_t dispatchGroup = dispatch_group_create(); - - void (^requestSuccess)(void) = ^() { - dispatch_group_leave(dispatchGroup); - }; - - void (^requestFailure)(NSError *) = ^(NSError *requestError) { - if (requestError && !firstRequestError) - { - firstRequestError = requestError; - } - - dispatch_group_leave(dispatchGroup); - }; - - MXWeakify(self); - for (id item in self.shareItemProvider.items) - { - if (item.type == ShareItemTypeText || item.type == ShareItemTypeURL) { - dispatch_group_enter(dispatchGroup); - [self.shareItemProvider loadItem:item completion:^(id item, NSError *error) { - MXStrongifyAndReturnIfNil(self); - - if (error) - { - requestFailure(error); - return; - } - - NSString *text = nil; - if([item isKindOfClass:[NSString class]]) - { - text = item; - } - else if([item isKindOfClass:[NSURL class]]) - { - text = [(NSURL *)item absoluteString]; - } - - if(text.length == 0) - { - requestFailure(nil); - return; - } - - [self sendText:text toRooms:rooms success:requestSuccess failure:requestFailure]; - }]; - } - - if (item.type == ShareItemTypeFileURL) { - dispatch_group_enter(dispatchGroup); - [self.shareItemProvider loadItem:item completion:^(NSURL *url, NSError *error) { - MXStrongifyAndReturnIfNil(self); - - if (error) - { - requestFailure(error); - return; - } - - [self sendFileWithUrl:url toRooms:rooms success:requestSuccess failure:requestFailure]; - }]; - } - - if (item.type == ShareItemTypeVideo || item.type == ShareItemTypeMovie) - { - dispatch_group_enter(dispatchGroup); - [self.shareItemProvider loadItem:item completion:^(NSURL *videoLocalUrl, NSError *error) { - MXStrongifyAndReturnIfNil(self); - - if (error) - { - requestFailure(error); - return; - } - - [self sendVideo:videoLocalUrl toRooms:rooms success:requestSuccess failure:requestFailure]; - }]; - } - - if (item.type == ShareItemTypeVoiceMessage) - { - dispatch_group_enter(dispatchGroup); - [self.shareItemProvider loadItem:item completion:^(NSURL *fileURL, NSError *error) { - MXStrongifyAndReturnIfNil(self); - - if (error) - { - requestFailure(error); - return; - } - - [self sendVoiceMessage:fileURL toRooms:rooms success:requestSuccess failure:requestFailure]; - }]; - } - - if (item.type == ShareItemTypeImage) - { - dispatch_group_enter(dispatchGroup); - [self.shareItemProvider loadItem:item completion:^(id itemProviderItem, NSError *error) { - MXStrongifyAndReturnIfNil(self); - - if (error) - { - requestFailure(error); - return; - } - - NSData *imageData; - if ([(NSObject *)itemProviderItem isKindOfClass:[NSData class]]) - { - imageData = (NSData*)itemProviderItem; - } - else if ([(NSObject *)itemProviderItem isKindOfClass:[NSURL class]]) - { - NSURL *imageURL = (NSURL*)itemProviderItem; - imageData = [NSData dataWithContentsOfURL:imageURL]; - } - else if ([(NSObject *)itemProviderItem isKindOfClass:[UIImage class]]) - { - // An application can share directly an UIImage. - // The most common case is screenshot sharing without saving to file. - // As screenshot using PNG format when they are saved to file we also use PNG format when saving UIImage to NSData. - UIImage *image = (UIImage*)itemProviderItem; - imageData = UIImagePNGRepresentation(image); - } - - if (!imageData) - { - requestFailure(error); - return; - } - - if ([self.shareItemProvider areAllItemsImages]) - { - // When all items are images, they're processed together from the - // pending list, immediately after the final image has been loaded. - [self.pendingImages addObject:imageData]; - } - else - { - // Otherwise, the image is sent as is, without prompting for a resize - // as that wouldn't make much sense with multiple content types. - self.imageCompressionMode = ImageCompressionModeNone; - [self sendImageData:imageData toRooms:rooms success:requestSuccess failure:requestFailure]; - } - - // When there are multiple content types the image will have been sent above. - // Otherwise, if we have loaded all of the images we can send them all together. - if ([self.shareItemProvider areAllItemsImages]) - { - if ([self.shareItemProvider areAllItemsLoaded]) - { - MXWeakify(self); - void (^sendPendingImages)(void) = ^void() { - MXStrongifyAndReturnIfNil(self); - [self sendImageDatas:self.pendingImages.copy toRooms:rooms success:requestSuccess failure:requestFailure]; - }; - - if (RiotSettings.shared.showMediaCompressionPrompt) - { - // Create a compression prompt which will be nil when the sizes can't be determined or if there are no pending images. - UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:sendPendingImages]; - if (compressionPrompt) - { - [self presentCompressionPrompt:compressionPrompt]; - } - } - else - { - self.imageCompressionMode = ImageCompressionModeNone; - sendPendingImages(); - } - } - else - { - dispatch_group_leave(dispatchGroup); - } - } - }]; - } - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - [self resetPendingData]; - - if (firstRequestError) - { - failure(firstRequestError); - } - else - { - success(); - } - }); -} - - (void)checkUserAccount { // Force account manager to reload account from the local storage. @@ -421,220 +193,15 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } } -- (BOOL)roomsContainEncryptedRoom:(NSArray *)rooms -{ - BOOL foundEncryptedRoom = NO; - - for (MXRoom *room in rooms) - { - if (room.summary.isEncrypted) - { - foundEncryptedRoom = YES; - break; - } - } - - return foundEncryptedRoom; -} - -- (void)resetPendingData -{ - [self.pendingImages removeAllObjects]; - [self.imageUploadProgresses removeAllObjects]; -} - -// TODO: When select multiple images: -// - Enhance prompt to display sum of all file sizes for each compression. -// - Find a way to choose compression sizes for all images. -- (UIAlertController *)compressionPromptForPendingImagesWithShareBlock:(void(^)(void))shareBlock -{ - if (!self.pendingImages.count) - { - return nil; - } - - NSData *firstImageData = self.pendingImages.firstObject; - UIImage *firstImage = [UIImage imageWithData:firstImageData]; - - MXKImageCompressionSizes compressionSizes = [MXKTools availableCompressionSizesForImage:firstImage originalFileSize:firstImageData.length]; - - if (compressionSizes.small.fileSize == 0 && compressionSizes.medium.fileSize == 0 && compressionSizes.large.fileSize == 0) - { - self.imageCompressionMode = ImageCompressionModeNone; - MXLogDebug(@"[ShareManager] Bypass compression prompt and send originals for %lu image(s) due to undetermined file sizes", (unsigned long)self.pendingImages.count); - - shareBlock(); - - return nil; - } - - UIAlertController *compressionPrompt = [UIAlertController alertControllerWithTitle:[MatrixKitL10n attachmentSizePromptTitle] - message:[MatrixKitL10n attachmentSizePromptMessage] - preferredStyle:UIAlertControllerStyleActionSheet]; - - if (compressionSizes.small.fileSize) - { - NSString *title = [MatrixKitL10n attachmentSmall:[MXTools fileSizeToString:compressionSizes.small.fileSize]]; - - MXWeakify(self); - [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - MXStrongifyAndReturnIfNil(self); - - self.imageCompressionMode = ImageCompressionModeSmall; - [self logCompressionSizeChoice:compressionSizes.small]; - - shareBlock(); - }]]; - } - - if (compressionSizes.medium.fileSize) - { - NSString *title = [MatrixKitL10n attachmentMedium:[MXTools fileSizeToString:compressionSizes.medium.fileSize]]; - - MXWeakify(self); - [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - MXStrongifyAndReturnIfNil(self); - - self.imageCompressionMode = ImageCompressionModeMedium; - [self logCompressionSizeChoice:compressionSizes.medium]; - - shareBlock(); - }]]; - } - - // Do not offer the possibility to resize an image with a dimension above kLargeImageSizeMaxDimension, to prevent the risk of memory limit exception. - // TODO: Remove this condition when issue https://github.com/vector-im/riot-ios/issues/2341 will be fixed. - if (compressionSizes.large.fileSize && (MAX(compressionSizes.large.imageSize.width, compressionSizes.large.imageSize.height) <= kLargeImageSizeMaxDimension)) - { - NSString *title = [MatrixKitL10n attachmentLarge:[MXTools fileSizeToString:compressionSizes.large.fileSize]]; - - MXWeakify(self); - [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - MXStrongifyAndReturnIfNil(self); - - self.imageCompressionMode = ImageCompressionModeLarge; - self.actualLargeSize = compressionSizes.actualLargeSize; - - [self logCompressionSizeChoice:compressionSizes.large]; - - shareBlock(); - }]]; - } - - // To limit memory consumption when encrypting, we suggest the original resolution only if the image size is moderate - if (compressionSizes.original.fileSize < kImageMaxFileSize) - { - NSString *fileSizeString = [MXTools fileSizeToString:compressionSizes.original.fileSize]; - - NSString *title = [MatrixKitL10n attachmentOriginal:fileSizeString]; - - MXWeakify(self); - [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { - MXStrongifyAndReturnIfNil(self); - - self.imageCompressionMode = ImageCompressionModeNone; - [self logCompressionSizeChoice:compressionSizes.original]; - - shareBlock(); - }]]; - } - - [compressionPrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] - style:UIAlertActionStyleCancel - handler:nil]]; - - return compressionPrompt; -} - - (void)didStartSending { [self.shareViewController showProgressIndicator]; } -- (NSString*)utiFromImageData:(NSData*)imageData +- (void)didReceiveMemoryWarning:(NSNotification*)notification { - CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); - NSString *uti = (NSString*)CGImageSourceGetType(imageSource); - CFRelease(imageSource); - return uti; -} - -- (NSString*)mimeTypeFromUTI:(NSString*)uti -{ - return (__bridge_transfer NSString *) UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti, kUTTagClassMIMEType); -} - -- (BOOL)isResizingSupportedForImageData:(NSData*)imageData -{ - NSString *imageUTI = [self utiFromImageData:imageData]; - return [self isResizingSupportedForUTI:imageUTI]; -} - -- (BOOL)isResizingSupportedForUTI:(NSString*)imageUTI -{ - if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG] || [imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) - { - return YES; - } - return NO; -} - -- (CGSize)imageSizeFromImageData:(NSData*)imageData -{ - CGFloat width = 0.0f; - CGFloat height = 0.0f; - - CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); - - CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); - - CFRelease(imageSource); - - if (imageProperties != NULL) - { - CFNumberRef widthNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth); - CFNumberRef heightNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight); - CFNumberRef orientationNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); - - if (widthNumber != NULL) - { - CFNumberGetValue(widthNumber, kCFNumberCGFloatType, &width); - } - - if (heightNumber != NULL) - { - CFNumberGetValue(heightNumber, kCFNumberCGFloatType, &height); - } - - // Check orientation and flip size if required - if (orientationNumber != NULL) - { - int orientation; - CFNumberGetValue(orientationNumber, kCFNumberIntType, &orientation); - - // For orientation from kCGImagePropertyOrientationLeftMirrored to kCGImagePropertyOrientationLeft flip size - if (orientation >= 5) - { - CGFloat tempWidth = width; - width = height; - height = tempWidth; - } - } - - CFRelease(imageProperties); - } - - return CGSizeMake(width, height); -} - -- (void)logCompressionSizeChoice:(MXKImageCompressionSize)compressionSize -{ - NSString *fileSize = [MXTools fileSizeToString:compressionSize.fileSize round:NO]; - NSUInteger imageWidth = compressionSize.imageSize.width; - NSUInteger imageHeight = compressionSize.imageSize.height; - - MXLogDebug(@"[ShareManager] User choose image compression with output size %lu x %lu (output file size: %@)", (unsigned long)imageWidth, (unsigned long)imageHeight, fileSize); - MXLogDebug(@"[ShareManager] Number of images to send: %lu", (unsigned long)self.pendingImages.count); + MXLogDebug(@"[ShareManager] Did receive memory warning"); + [self logMemoryUsage]; } // Log memory usage. @@ -661,423 +228,4 @@ typedef NS_ENUM(NSInteger, ImageCompressionMode) } } -- (void)presentCompressionPrompt:(UIAlertController *)compressionPrompt -{ - [compressionPrompt popoverPresentationController].sourceView = self.mainViewController.view; - [compressionPrompt popoverPresentationController].sourceRect = self.mainViewController.view.frame; - [self.mainViewController presentViewController:compressionPrompt animated:YES completion:nil]; -} - -#pragma mark - Notifications - -- (void)onMediaLoaderStateDidChange:(NSNotification *)notification -{ - MXMediaLoader *loader = (MXMediaLoader*)notification.object; - // Consider only upload progress - switch (loader.state) { - case MXMediaLoaderStateUploadInProgress: - { - self.imageUploadProgresses[loader.uploadId] = (NSNumber *)loader.statisticsDict[kMXMediaLoaderProgressValueKey]; - - const NSInteger totalImagesCount = self.pendingImages.count; - CGFloat totalProgress = 0.0; - - for (NSNumber *progress in self.imageUploadProgresses.allValues) - { - totalProgress += progress.floatValue/totalImagesCount; - } - - [self.shareViewController setProgress:totalProgress]; - break; - } - default: - break; - } -} - -- (void)didReceiveMemoryWarning:(NSNotification*)notification -{ - MXLogDebug(@"[ShareManager] Did receive memory warning"); - [self logMemoryUsage]; -} - -#pragma mark - Sharing - -- (void)sendText:(NSString *)text - toRooms:(NSArray *)rooms - success:(dispatch_block_t)success - failure:(void(^)(NSError *error))failure -{ - [self didStartSending]; - if (!text) - { - MXLogError(@"[ShareManager] Invalid text."); - failure(nil); - return; - } - - __block NSError *error = nil; - dispatch_group_t dispatchGroup = dispatch_group_create(); - for (MXRoom *room in rooms) { - dispatch_group_enter(dispatchGroup); - [room sendTextMessage:text success:^(NSString *eventId) { - dispatch_group_leave(dispatchGroup); - } failure:^(NSError *innerError) { - MXLogError(@"[ShareManager] sendTextMessage failed with error %@", error); - error = innerError; - dispatch_group_leave(dispatchGroup); - }]; - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - if(error) { - failure(error); - } else { - success(); - } - }); -} - -- (void)sendFileWithUrl:(NSURL *)fileUrl - toRooms:(NSArray *)rooms - success:(dispatch_block_t)success - failure:(void(^)(NSError *error))failure -{ - [self didStartSending]; - if (!fileUrl) - { - MXLogError(@"[ShareManager] Invalid file url."); - failure(nil); - return; - } - - NSString *mimeType; - CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fileUrl pathExtension] , NULL); - mimeType = [self mimeTypeFromUTI:(__bridge NSString *)uti]; - CFRelease(uti); - - __block NSError *error = nil; - dispatch_group_t dispatchGroup = dispatch_group_create(); - for (MXRoom *room in rooms) { - dispatch_group_enter(dispatchGroup); - [room sendFile:fileUrl mimeType:mimeType localEcho:nil success:^(NSString *eventId) { - dispatch_group_leave(dispatchGroup); - } failure:^(NSError *innerError) { - MXLogError(@"[ShareManager] sendFile failed with error %@", innerError); - error = innerError; - dispatch_group_leave(dispatchGroup); - } keepActualFilename:YES]; - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - if(error) { - failure(error); - } else { - success(); - } - }); -} - -- (void)sendVideo:(NSURL *)videoLocalUrl - toRooms:(NSArray *)rooms - success:(dispatch_block_t)success - failure:(void(^)(NSError *error))failure -{ - AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil]; - - MXWeakify(self); - - void (^sendVideo)(void) = ^void() { - MXStrongifyAndReturnIfNil(self); - - [self didStartSending]; - if (!videoLocalUrl) - { - MXLogError(@"[ShareManager] Invalid video file url."); - failure(nil); - return; - } - - // Retrieve the video frame at 1 sec to define the video thumbnail - AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:videoAsset]; - assetImageGenerator.appliesPreferredTrackTransform = YES; - CMTime time = CMTimeMake(1, 1); - CGImageRef imageRef = [assetImageGenerator copyCGImageAtTime:time actualTime:NULL error:nil]; - // Finalize video attachment - UIImage *videoThumbnail = [[UIImage alloc] initWithCGImage:imageRef]; - CFRelease(imageRef); - - __block NSError *error = nil; - dispatch_group_t dispatchGroup = dispatch_group_create(); - for (MXRoom *room in rooms) { - dispatch_group_enter(dispatchGroup); - [room sendVideoAsset:videoAsset withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { - dispatch_group_leave(dispatchGroup); - } failure:^(NSError *innerError) { - MXLogError(@"[ShareManager] Failed sending video with error %@", innerError); - error = innerError; - dispatch_group_leave(dispatchGroup); - }]; - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - if(error) { - failure(error); - } else { - success(); - } - }); - }; - - BOOL allRoomsAreUnencrypted = ![self roomsContainEncryptedRoom:rooms]; - - // When rooms are unencrypted convert the video according to the user's normal preferences - if (allRoomsAreUnencrypted) - { - if (!RiotSettings.shared.showMediaCompressionPrompt) - { - [MXSDKOptions sharedInstance].videoConversionPresetName = AVCaptureSessionPreset1920x1080; - sendVideo(); - } - else - { - UIAlertController *compressionPrompt = [MXKTools videoConversionPromptForVideoAsset:videoAsset withCompletion:^(NSString *presetName) { - // If the preset name is nil, the user cancelled. - if (!presetName) - { - return; - } - - // Set the chosen video conversion preset. - [MXSDKOptions sharedInstance].videoConversionPresetName = presetName; - sendVideo(); - }]; - - [self presentCompressionPrompt:compressionPrompt]; - } - } - else - { - // When rooms are encrypted we quickly run out of memory encrypting the video - // Prompt the user if they're happy to send a low quality video (320p). - UIAlertController *lowQualityPrompt = [UIAlertController alertControllerWithTitle:VectorL10n.shareExtensionLowQualityVideoTitle - message:[VectorL10n shareExtensionLowQualityVideoMessage:AppInfo.current.displayName] - preferredStyle:UIAlertControllerStyleAlert]; - - UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:MatrixKitL10n.cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { - // Do nothing - }]; - UIAlertAction *sendAction = [UIAlertAction actionWithTitle:VectorL10n.shareExtensionSendNow style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { - [MXSDKOptions sharedInstance].videoConversionPresetName = AVAssetExportPresetMediumQuality; - sendVideo(); - }]; - - [lowQualityPrompt addAction:cancelAction]; - [lowQualityPrompt addAction:sendAction]; - [lowQualityPrompt setPreferredAction:sendAction]; - - [self presentCompressionPrompt:lowQualityPrompt]; - } -} - -- (void)sendVoiceMessage:(NSURL *)fileUrl - toRooms:(NSArray *)rooms - success:(dispatch_block_t)success - failure:(void(^)(NSError *error))failure -{ - [self didStartSending]; - if (!fileUrl) - { - MXLogError(@"[ShareManager] Invalid voice message file url."); - failure(nil); - return; - } - - __block NSError *error = nil; - dispatch_group_t dispatchGroup = dispatch_group_create(); - for (MXRoom *room in rooms) { - dispatch_group_enter(dispatchGroup); - [room sendVoiceMessage:fileUrl mimeType:nil duration:0.0 samples:nil localEcho:nil success:^(NSString *eventId) { - dispatch_group_leave(dispatchGroup); - } failure:^(NSError *innerError) { - MXLogError(@"[ShareManager] sendVoiceMessage failed with error %@", error); - error = innerError; - dispatch_group_leave(dispatchGroup); - } keepActualFilename:YES]; - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - if(error) { - failure(error); - } else { - success(); - } - }); -} - -- (void)sendImageDatas:(NSArray> *)imageDatas - toRooms:(NSArray *)rooms - success:(dispatch_block_t)success - failure:(void(^)(NSError *error))failure -{ - if (imageDatas.count == 0) - { - MXLogError(@"[ShareManager] sendImages: no images to send."); - failure(nil); - return; - } - - [self didStartSending]; - - dispatch_group_t requestsGroup = dispatch_group_create(); - __block NSError *firstRequestError; - - NSUInteger index = 0; - - for (NSData *imageData in imageDatas) - { - @autoreleasepool - { - dispatch_group_enter(requestsGroup); - [self sendImageData:imageData toRooms:rooms success:^{ - dispatch_group_leave(requestsGroup); - } failure:^(NSError *error) { - if (error && !firstRequestError) - { - firstRequestError = error; - } - - dispatch_group_leave(requestsGroup); - }]; - } - - index++; - } - - dispatch_group_notify(requestsGroup, dispatch_get_main_queue(), ^{ - - if (firstRequestError) - { - failure(firstRequestError); - } - else - { - success(); - } - }); -} - -- (void)sendImageData:(NSData *)imageData - toRooms:(NSArray *)rooms - success:(dispatch_block_t)success - failure:(void(^)(NSError *error))failure -{ - [self didStartSending]; - - NSString *imageUTI; - NSString *mimeType; - - if (!mimeType) - { - imageUTI = [self utiFromImageData:imageData]; - if (imageUTI) - { - mimeType = [self mimeTypeFromUTI:imageUTI]; - } - } - - if (!mimeType) - { - MXLogError(@"[ShareManager] sendImage failed. Cannot determine MIME type ."); - if (failure) - { - failure(nil); - } - return; - } - - CGSize imageSize; - NSData *finalImageData; - - // Only resize JPEG or PNG files - if ([self isResizingSupportedForUTI:imageUTI]) - { - UIImage *convertedImage; - CGSize newImageSize; - - switch (self.imageCompressionMode) { - case ImageCompressionModeSmall: - newImageSize = CGSizeMake(MXKTOOLS_SMALL_IMAGE_SIZE, MXKTOOLS_SMALL_IMAGE_SIZE); - break; - case ImageCompressionModeMedium: - newImageSize = CGSizeMake(MXKTOOLS_MEDIUM_IMAGE_SIZE, MXKTOOLS_MEDIUM_IMAGE_SIZE); - break; - case ImageCompressionModeLarge: - newImageSize = CGSizeMake(self.actualLargeSize, self.actualLargeSize); - break; - default: - newImageSize = CGSizeZero; - break; - } - - if (!CGSizeEqualToSize(newImageSize, CGSizeZero)) - { - // Resize the image and set image in right orientation too - convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize]; - } - - if (convertedImage) - { - if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG]) - { - finalImageData = UIImagePNGRepresentation(convertedImage); - } - else if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) - { - finalImageData = UIImageJPEGRepresentation(convertedImage, 0.9); - } - - imageSize = convertedImage.size; - } - else - { - finalImageData = imageData; - imageSize = [self imageSizeFromImageData:imageData]; - } - } - else - { - finalImageData = imageData; - imageSize = [self imageSizeFromImageData:imageData]; - } - - __block NSError *error = nil; - dispatch_group_t dispatchGroup = dispatch_group_create(); - for (MXRoom *room in rooms) { - - UIImage *thumbnail = nil; - if (room.summary.isEncrypted) // Thumbnail is useful only in case of encrypted room - { - thumbnail = [MXKTools resizeImageWithData:imageData toFitInSize:kThumbnailSize]; - } - - dispatch_group_enter(dispatchGroup); - [room sendImage:finalImageData withImageSize:imageSize mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { - dispatch_group_leave(dispatchGroup); - } failure:^(NSError *innerError) { - MXLogError(@"[ShareManager] sendImage failed with error %@", error); - error = innerError; - dispatch_group_leave(dispatchGroup); - }]; - } - - dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ - if(error) { - failure(error); - } else { - success(); - } - }); -} - @end diff --git a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m index c7a85ec68..d5f277193 100644 --- a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m +++ b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.m @@ -44,6 +44,7 @@ { return [UINib nibWithNibName:NSStringFromClass([self class]) bundle:mainBundle]; } + return nil; } diff --git a/RiotShareExtension/Shared/View/ShareViewController.m b/RiotShareExtension/Shared/View/ShareViewController.m index 25dc09232..dc2c8ff24 100644 --- a/RiotShareExtension/Shared/View/ShareViewController.m +++ b/RiotShareExtension/Shared/View/ShareViewController.m @@ -23,7 +23,7 @@ #import "GeneratedInterface-Swift.h" -@interface ShareViewController () +@interface ShareViewController () @property (nonatomic, assign, readonly) ShareViewControllerType type; diff --git a/RiotShareExtension/Sources/ShareExtensionRootViewController.m b/RiotShareExtension/Sources/ShareExtensionRootViewController.m index 5b1a911af..90b5006e8 100644 --- a/RiotShareExtension/Sources/ShareExtensionRootViewController.m +++ b/RiotShareExtension/Sources/ShareExtensionRootViewController.m @@ -17,11 +17,14 @@ #import "ShareExtensionRootViewController.h" #import "ShareManager.h" #import "ThemeService.h" +#import "ShareItemSender.h" #import "GeneratedInterface-Swift.h" @interface ShareExtensionRootViewController () +@property (nonatomic, strong, readonly) id configuration; + @property (nonatomic, strong, readonly) ShareManager *shareManager; @end @@ -32,10 +35,32 @@ { [super viewDidLoad]; + _configuration = [[CommonConfiguration alloc] init]; + [_configuration setupSettings]; + + // NSLog -> console.log file when not debugging the app + MXLogConfiguration *configuration = [[MXLogConfiguration alloc] init]; + configuration.logLevel = MXLogLevelVerbose; + configuration.logFilesSizeLimit = 0; + configuration.maxLogFilesCount = 10; + configuration.subLogName = @"share"; + + // Redirect NSLogs to files only if we are not debugging + if (!isatty(STDERR_FILENO)) { + configuration.redirectLogsToFiles = YES; + } + + [MXLog configure:configuration]; + + [ThemeService.shared setThemeId:RiotSettings.shared.userInterfaceTheme]; - ShareExtensionShareItemProvider *provider = [[ShareExtensionShareItemProvider alloc] initWithExtensionContext:self.extensionContext]; - _shareManager = [[ShareManager alloc] initWithShareItemProvider:provider type:ShareManagerTypeSend]; + ShareExtensionShareItemProvider *shareItemProvider = [[ShareExtensionShareItemProvider alloc] initWithExtensionContext:self.extensionContext]; + ShareItemSender *shareItemSender = [[ShareItemSender alloc] initWithRootViewController:self + shareItemProvider:shareItemProvider]; + + _shareManager = [[ShareManager alloc] initWithShareItemSender:shareItemSender + type:ShareManagerTypeSend]; MXWeakify(self); [_shareManager setCompletionCallback:^(ShareManagerResult result) { diff --git a/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift b/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift index 6a83e25c5..7ef463d81 100644 --- a/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift +++ b/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift @@ -47,7 +47,7 @@ private class ShareExtensionItem: ShareItemProtocol { } @objcMembers -class ShareExtensionShareItemProvider: NSObject, ShareItemProviderProtocol { +public class ShareExtensionShareItemProvider: NSObject { public let items: [ShareItemProtocol] @@ -66,7 +66,7 @@ class ShareExtensionShareItemProvider: NSObject, ShareItemProviderProtocol { self.items = items } - func areAllItemsLoaded() -> Bool { + public func areAllItemsLoaded() -> Bool { for case let item as ShareExtensionItem in self.items { if !item.loaded { return false @@ -121,8 +121,6 @@ class ShareExtensionShareItemProvider: NSObject, ShareItemProviderProtocol { return MXKUTI.video.rawValue case .movie: return MXKUTI.movie.rawValue - case .voiceMessage: - return MXKUTI.fileUrl.rawValue default: return "" } diff --git a/RiotShareExtension/Shared/ShareItemProvider/ShareItemProviderProtocol.swift b/RiotShareExtension/Sources/ShareItemProtocol.swift similarity index 67% rename from RiotShareExtension/Shared/ShareItemProvider/ShareItemProviderProtocol.swift rename to RiotShareExtension/Sources/ShareItemProtocol.swift index 417fea577..b47987463 100644 --- a/RiotShareExtension/Shared/ShareItemProvider/ShareItemProviderProtocol.swift +++ b/RiotShareExtension/Sources/ShareItemProtocol.swift @@ -17,19 +17,9 @@ import Foundation @objc public enum ShareItemType: UInt { - case fileURL, text, URL, image, video, movie, voiceMessage, unknown + case fileURL, text, URL, image, video, movie, unknown } @objc public protocol ShareItemProtocol { var type: ShareItemType { get } } - -@objc public protocol ShareItemProviderProtocol { - var items: [ShareItemProtocol] { get } - - func areAllItemsImages() -> Bool - - func areAllItemsLoaded() -> Bool - - func loadItem(_ item: ShareItemProtocol, completion: @escaping (Any?, Error?) -> Void) -} diff --git a/RiotShareExtension/Sources/ShareItemSender.h b/RiotShareExtension/Sources/ShareItemSender.h new file mode 100644 index 000000000..19670cead --- /dev/null +++ b/RiotShareExtension/Sources/ShareItemSender.h @@ -0,0 +1,32 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import + +#import "ShareItemSenderProtocol.h" + +@class ShareExtensionShareItemProvider; + +NS_ASSUME_NONNULL_BEGIN + +@interface ShareItemSender : NSObject + +- (instancetype)initWithRootViewController:(UIViewController *)rootViewController + shareItemProvider:(ShareExtensionShareItemProvider *)shareItemProvider; + +@end + +NS_ASSUME_NONNULL_END diff --git a/RiotShareExtension/Sources/ShareItemSender.m b/RiotShareExtension/Sources/ShareItemSender.m new file mode 100644 index 000000000..4844e89a6 --- /dev/null +++ b/RiotShareExtension/Sources/ShareItemSender.m @@ -0,0 +1,892 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +@import MobileCoreServices; + +#import "ShareItemSender.h" + +#ifdef IS_SHARE_EXTENSION +#import "RiotShareExtension-Swift.h" +#else +#import "Riot-Swift.h" +#endif + +static const CGFloat kLargeImageSizeMaxDimension = 2048.0; +static const CGSize kThumbnailSize = {800.0, 600.0}; +/// A safe maximum file size for an image to send the original. +static const NSUInteger kImageMaxFileSize = 20 * 1024 * 1024; + +typedef NS_ENUM(NSInteger, ImageCompressionMode) +{ + ImageCompressionModeNone, + ImageCompressionModeSmall, + ImageCompressionModeMedium, + ImageCompressionModeLarge +}; + +@interface ShareItemSender () + +@property (nonatomic, strong, readonly) UIViewController *rootViewController; +@property (nonatomic, strong, readonly) ShareExtensionShareItemProvider *shareItemProvider; + +@property (nonatomic, strong, readonly) NSMutableArray *pendingImages; +@property (nonatomic, strong, readonly) NSMutableDictionary *imageUploadProgresses; + +@property (nonatomic, assign) ImageCompressionMode imageCompressionMode; +@property (nonatomic, assign) CGFloat actualLargeSize; + +@end + +@implementation ShareItemSender +@synthesize delegate; + +- (instancetype)initWithRootViewController:(UIViewController *)rootViewController + shareItemProvider:(ShareExtensionShareItemProvider *)shareItemProvider +{ + if (self = [super init]) { + _rootViewController = rootViewController; + _shareItemProvider = shareItemProvider; + + _pendingImages = [NSMutableArray array]; + _imageUploadProgresses = [NSMutableDictionary dictionary]; + + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onMediaLoaderStateDidChange:) name:kMXMediaLoaderStateDidChangeNotification object:nil]; + } + + return self; +} + +- (void)didStartSending +{ + [self.delegate shareItemSenderDidStartSending:self]; +} + +- (void)presentCompressionPrompt:(UIAlertController *)compressionPrompt +{ + [compressionPrompt popoverPresentationController].sourceView = self.rootViewController.view; + [compressionPrompt popoverPresentationController].sourceRect = self.rootViewController.view.frame; + [self.rootViewController.presentedViewController presentViewController:compressionPrompt animated:YES completion:nil]; +} + +- (BOOL)roomsContainEncryptedRoom:(NSArray *)rooms +{ + BOOL foundEncryptedRoom = NO; + + for (MXRoom *room in rooms) + { + if (room.summary.isEncrypted) + { + foundEncryptedRoom = YES; + break; + } + } + + return foundEncryptedRoom; +} + +- (void)resetPendingData +{ + [self.pendingImages removeAllObjects]; + [self.imageUploadProgresses removeAllObjects]; +} + +- (void)sendItemsToRooms:(NSArray *)rooms success:(void (^)(void))success failure:(void (^)(NSArray *))failure +{ + [self resetPendingData]; + + __block NSMutableArray *errors; + dispatch_group_t dispatchGroup = dispatch_group_create(); + + void (^requestSuccess)(void) = ^() { + dispatch_group_leave(dispatchGroup); + }; + + void (^requestFailure)(NSError *) = ^(NSError *requestError) { + if (errors == nil) + { + errors = [NSMutableArray array]; + } + + if(requestError) + { + [errors addObject:requestError]; + } + + dispatch_group_leave(dispatchGroup); + }; + + MXWeakify(self); + for (id item in self.shareItemProvider.items) + { + if (item.type == ShareItemTypeText || item.type == ShareItemTypeURL) { + dispatch_group_enter(dispatchGroup); + [self.shareItemProvider loadItem:item completion:^(id item, NSError *error) { + MXStrongifyAndReturnIfNil(self); + + if (error) + { + requestFailure(error); + return; + } + + NSString *text = nil; + if([item isKindOfClass:[NSString class]]) + { + text = item; + } + else if([item isKindOfClass:[NSURL class]]) + { + text = [(NSURL *)item absoluteString]; + } + + if(text.length == 0) + { + requestFailure(nil); + return; + } + + [self sendText:text toRooms:rooms success:requestSuccess failure:requestFailure]; + }]; + } + + if (item.type == ShareItemTypeFileURL) { + dispatch_group_enter(dispatchGroup); + [self.shareItemProvider loadItem:item completion:^(NSURL *url, NSError *error) { + MXStrongifyAndReturnIfNil(self); + + if (error) + { + requestFailure(error); + return; + } + + [self sendFileWithUrl:url toRooms:rooms success:requestSuccess failure:requestFailure]; + }]; + } + + if (item.type == ShareItemTypeVideo || item.type == ShareItemTypeMovie) + { + dispatch_group_enter(dispatchGroup); + [self.shareItemProvider loadItem:item completion:^(NSURL *videoLocalUrl, NSError *error) { + MXStrongifyAndReturnIfNil(self); + + if (error) + { + requestFailure(error); + return; + } + + [self sendVideo:videoLocalUrl toRooms:rooms success:requestSuccess failure:requestFailure]; + }]; + } + + if (item.type == ShareItemTypeImage) + { + dispatch_group_enter(dispatchGroup); + [self.shareItemProvider loadItem:item completion:^(id itemProviderItem, NSError *error) { + MXStrongifyAndReturnIfNil(self); + + if (error) + { + requestFailure(error); + return; + } + + NSData *imageData; + if ([(NSObject *)itemProviderItem isKindOfClass:[NSData class]]) + { + imageData = (NSData*)itemProviderItem; + } + else if ([(NSObject *)itemProviderItem isKindOfClass:[NSURL class]]) + { + NSURL *imageURL = (NSURL*)itemProviderItem; + imageData = [NSData dataWithContentsOfURL:imageURL]; + } + else if ([(NSObject *)itemProviderItem isKindOfClass:[UIImage class]]) + { + // An application can share directly an UIImage. + // The most common case is screenshot sharing without saving to file. + // As screenshot using PNG format when they are saved to file we also use PNG format when saving UIImage to NSData. + UIImage *image = (UIImage*)itemProviderItem; + imageData = UIImagePNGRepresentation(image); + } + + if (!imageData) + { + requestFailure(error); + return; + } + + if ([self.shareItemProvider areAllItemsImages]) + { + // When all items are images, they're processed together from the + // pending list, immediately after the final image has been loaded. + [self.pendingImages addObject:imageData]; + } + else + { + // Otherwise, the image is sent as is, without prompting for a resize + // as that wouldn't make much sense with multiple content types. + self.imageCompressionMode = ImageCompressionModeNone; + [self sendImageData:imageData toRooms:rooms success:requestSuccess failure:requestFailure]; + } + + // When there are multiple content types the image will have been sent above. + // Otherwise, if we have loaded all of the images we can send them all together. + if ([self.shareItemProvider areAllItemsImages]) + { + if ([self.shareItemProvider areAllItemsLoaded]) + { + MXWeakify(self); + void (^sendPendingImages)(void) = ^void() { + MXStrongifyAndReturnIfNil(self); + [self sendImageDatas:self.pendingImages.copy toRooms:rooms success:requestSuccess failure:requestFailure]; + }; + + if (RiotSettings.shared.showMediaCompressionPrompt) + { + // Create a compression prompt which will be nil when the sizes can't be determined or if there are no pending images. + UIAlertController *compressionPrompt = [self compressionPromptForPendingImagesWithShareBlock:sendPendingImages]; + if (compressionPrompt) + { + [self presentCompressionPrompt:compressionPrompt]; + } + } + else + { + self.imageCompressionMode = ImageCompressionModeNone; + sendPendingImages(); + } + } + else + { + dispatch_group_leave(dispatchGroup); + } + } + }]; + } + } + + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + [self resetPendingData]; + + if (errors) + { + failure(errors); + } + else + { + success(); + } + }); +} + +// TODO: When select multiple images: +// - Enhance prompt to display sum of all file sizes for each compression. +// - Find a way to choose compression sizes for all images. +- (UIAlertController *)compressionPromptForPendingImagesWithShareBlock:(void(^)(void))shareBlock +{ + if (!self.pendingImages.count) + { + return nil; + } + + NSData *firstImageData = self.pendingImages.firstObject; + UIImage *firstImage = [UIImage imageWithData:firstImageData]; + + MXKImageCompressionSizes compressionSizes = [MXKTools availableCompressionSizesForImage:firstImage originalFileSize:firstImageData.length]; + + if (compressionSizes.small.fileSize == 0 && compressionSizes.medium.fileSize == 0 && compressionSizes.large.fileSize == 0) + { + self.imageCompressionMode = ImageCompressionModeNone; + MXLogDebug(@"[ShareManager] Bypass compression prompt and send originals for %lu image(s) due to undetermined file sizes", (unsigned long)self.pendingImages.count); + + shareBlock(); + + return nil; + } + + UIAlertController *compressionPrompt = [UIAlertController alertControllerWithTitle:[MatrixKitL10n attachmentSizePromptTitle] + message:[MatrixKitL10n attachmentSizePromptMessage] + preferredStyle:UIAlertControllerStyleActionSheet]; + + if (compressionSizes.small.fileSize) + { + NSString *title = [MatrixKitL10n attachmentSmall:[MXTools fileSizeToString:compressionSizes.small.fileSize]]; + + MXWeakify(self); + [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + + self.imageCompressionMode = ImageCompressionModeSmall; + [self logCompressionSizeChoice:compressionSizes.small]; + + shareBlock(); + }]]; + } + + if (compressionSizes.medium.fileSize) + { + NSString *title = [MatrixKitL10n attachmentMedium:[MXTools fileSizeToString:compressionSizes.medium.fileSize]]; + + MXWeakify(self); + [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + + self.imageCompressionMode = ImageCompressionModeMedium; + [self logCompressionSizeChoice:compressionSizes.medium]; + + shareBlock(); + }]]; + } + + // Do not offer the possibility to resize an image with a dimension above kLargeImageSizeMaxDimension, to prevent the risk of memory limit exception. + // TODO: Remove this condition when issue https://github.com/vector-im/riot-ios/issues/2341 will be fixed. + if (compressionSizes.large.fileSize && (MAX(compressionSizes.large.imageSize.width, compressionSizes.large.imageSize.height) <= kLargeImageSizeMaxDimension)) + { + NSString *title = [MatrixKitL10n attachmentLarge:[MXTools fileSizeToString:compressionSizes.large.fileSize]]; + + MXWeakify(self); + [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + + self.imageCompressionMode = ImageCompressionModeLarge; + self.actualLargeSize = compressionSizes.actualLargeSize; + + [self logCompressionSizeChoice:compressionSizes.large]; + + shareBlock(); + }]]; + } + + // To limit memory consumption when encrypting, we suggest the original resolution only if the image size is moderate + if (compressionSizes.original.fileSize < kImageMaxFileSize) + { + NSString *fileSizeString = [MXTools fileSizeToString:compressionSizes.original.fileSize]; + + NSString *title = [MatrixKitL10n attachmentOriginal:fileSizeString]; + + MXWeakify(self); + [compressionPrompt addAction:[UIAlertAction actionWithTitle:title style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) { + MXStrongifyAndReturnIfNil(self); + + self.imageCompressionMode = ImageCompressionModeNone; + [self logCompressionSizeChoice:compressionSizes.original]; + + shareBlock(); + }]]; + } + + [compressionPrompt addAction:[UIAlertAction actionWithTitle:[MatrixKitL10n cancel] + style:UIAlertActionStyleCancel + handler:nil]]; + + return compressionPrompt; +} + +- (NSString*)utiFromImageData:(NSData*)imageData +{ + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); + NSString *uti = (NSString*)CGImageSourceGetType(imageSource); + CFRelease(imageSource); + return uti; +} + +- (NSString*)mimeTypeFromUTI:(NSString*)uti +{ + return (__bridge_transfer NSString *) UTTypeCopyPreferredTagWithClass((__bridge CFStringRef)uti, kUTTagClassMIMEType); +} + +- (BOOL)isResizingSupportedForImageData:(NSData*)imageData +{ + NSString *imageUTI = [self utiFromImageData:imageData]; + return [self isResizingSupportedForUTI:imageUTI]; +} + +- (BOOL)isResizingSupportedForUTI:(NSString*)imageUTI +{ + if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG] || [imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) + { + return YES; + } + return NO; +} + +- (CGSize)imageSizeFromImageData:(NSData*)imageData +{ + CGFloat width = 0.0f; + CGFloat height = 0.0f; + + CGImageSourceRef imageSource = CGImageSourceCreateWithData((CFDataRef)imageData, NULL); + + CFDictionaryRef imageProperties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, NULL); + + CFRelease(imageSource); + + if (imageProperties != NULL) + { + CFNumberRef widthNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelWidth); + CFNumberRef heightNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyPixelHeight); + CFNumberRef orientationNumber = CFDictionaryGetValue(imageProperties, kCGImagePropertyOrientation); + + if (widthNumber != NULL) + { + CFNumberGetValue(widthNumber, kCFNumberCGFloatType, &width); + } + + if (heightNumber != NULL) + { + CFNumberGetValue(heightNumber, kCFNumberCGFloatType, &height); + } + + // Check orientation and flip size if required + if (orientationNumber != NULL) + { + int orientation; + CFNumberGetValue(orientationNumber, kCFNumberIntType, &orientation); + + // For orientation from kCGImagePropertyOrientationLeftMirrored to kCGImagePropertyOrientationLeft flip size + if (orientation >= 5) + { + CGFloat tempWidth = width; + width = height; + height = tempWidth; + } + } + + CFRelease(imageProperties); + } + + return CGSizeMake(width, height); +} + +- (void)logCompressionSizeChoice:(MXKImageCompressionSize)compressionSize +{ + NSString *fileSize = [MXTools fileSizeToString:compressionSize.fileSize round:NO]; + NSUInteger imageWidth = compressionSize.imageSize.width; + NSUInteger imageHeight = compressionSize.imageSize.height; + + MXLogDebug(@"[ShareItemSender] User choose image compression with output size %lu x %lu (output file size: %@)", (unsigned long)imageWidth, (unsigned long)imageHeight, fileSize); + MXLogDebug(@"[ShareItemSender] Number of images to send: %lu", (unsigned long)self.pendingImages.count); +} + +#pragma mark - Notifications + +- (void)onMediaLoaderStateDidChange:(NSNotification *)notification +{ + MXMediaLoader *loader = (MXMediaLoader*)notification.object; + // Consider only upload progress + switch (loader.state) { + case MXMediaLoaderStateUploadInProgress: + { + self.imageUploadProgresses[loader.uploadId] = (NSNumber *)loader.statisticsDict[kMXMediaLoaderProgressValueKey]; + + const NSInteger totalImagesCount = self.pendingImages.count; + CGFloat totalProgress = 0.0; + + for (NSNumber *progress in self.imageUploadProgresses.allValues) + { + totalProgress += progress.floatValue/totalImagesCount; + } + + [self.delegate shareItemSender:self didUpdateProgress:totalProgress]; + break; + } + default: + break; + } +} + +#pragma mark - Sharing + +- (void)sendText:(NSString *)text + toRooms:(NSArray *)rooms + success:(dispatch_block_t)success + failure:(void(^)(NSError *error))failure +{ + [self didStartSending]; + if (!text) + { + MXLogError(@"[ShareItemSender] Invalid text."); + failure(nil); + return; + } + + __block NSError *error = nil; + dispatch_group_t dispatchGroup = dispatch_group_create(); + for (MXRoom *room in rooms) { + dispatch_group_enter(dispatchGroup); + [room sendTextMessage:text success:^(NSString *eventId) { + dispatch_group_leave(dispatchGroup); + } failure:^(NSError *innerError) { + MXLogError(@"[ShareItemSender] sendTextMessage failed with error %@", error); + error = innerError; + dispatch_group_leave(dispatchGroup); + }]; + } + + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + if(error) { + failure(error); + } else { + success(); + } + }); +} + +- (void)sendFileWithUrl:(NSURL *)fileUrl + toRooms:(NSArray *)rooms + success:(dispatch_block_t)success + failure:(void(^)(NSError *error))failure +{ + [self didStartSending]; + if (!fileUrl) + { + MXLogError(@"[ShareItemSender] Invalid file url."); + failure(nil); + return; + } + + NSString *mimeType; + CFStringRef uti = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)[fileUrl pathExtension] , NULL); + mimeType = [self mimeTypeFromUTI:(__bridge NSString *)uti]; + CFRelease(uti); + + __block NSError *error = nil; + dispatch_group_t dispatchGroup = dispatch_group_create(); + for (MXRoom *room in rooms) { + dispatch_group_enter(dispatchGroup); + [room sendFile:fileUrl mimeType:mimeType localEcho:nil success:^(NSString *eventId) { + dispatch_group_leave(dispatchGroup); + } failure:^(NSError *innerError) { + MXLogError(@"[ShareItemSender] sendFile failed with error %@", innerError); + error = innerError; + dispatch_group_leave(dispatchGroup); + } keepActualFilename:YES]; + } + + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + if(error) { + failure(error); + } else { + success(); + } + }); +} + +- (void)sendVideo:(NSURL *)videoLocalUrl + toRooms:(NSArray *)rooms + success:(dispatch_block_t)success + failure:(void(^)(NSError *error))failure +{ + AVURLAsset *videoAsset = [[AVURLAsset alloc] initWithURL:videoLocalUrl options:nil]; + + MXWeakify(self); + + void (^sendVideo)(void) = ^void() { + MXStrongifyAndReturnIfNil(self); + + [self didStartSending]; + if (!videoLocalUrl) + { + MXLogError(@"[ShareManager] Invalid video file url."); + failure(nil); + return; + } + + // Retrieve the video frame at 1 sec to define the video thumbnail + AVAssetImageGenerator *assetImageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:videoAsset]; + assetImageGenerator.appliesPreferredTrackTransform = YES; + CMTime time = CMTimeMake(1, 1); + CGImageRef imageRef = [assetImageGenerator copyCGImageAtTime:time actualTime:NULL error:nil]; + // Finalize video attachment + UIImage *videoThumbnail = [[UIImage alloc] initWithCGImage:imageRef]; + CFRelease(imageRef); + + __block NSError *error = nil; + dispatch_group_t dispatchGroup = dispatch_group_create(); + for (MXRoom *room in rooms) { + dispatch_group_enter(dispatchGroup); + [room sendVideoAsset:videoAsset withThumbnail:videoThumbnail localEcho:nil success:^(NSString *eventId) { + dispatch_group_leave(dispatchGroup); + } failure:^(NSError *innerError) { + MXLogError(@"[ShareManager] Failed sending video with error %@", innerError); + error = innerError; + dispatch_group_leave(dispatchGroup); + }]; + } + + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + if(error) { + failure(error); + } else { + success(); + } + }); + }; + + BOOL allRoomsAreUnencrypted = ![self roomsContainEncryptedRoom:rooms]; + + // When rooms are unencrypted convert the video according to the user's normal preferences + if (allRoomsAreUnencrypted) + { + if (!RiotSettings.shared.showMediaCompressionPrompt) + { + [MXSDKOptions sharedInstance].videoConversionPresetName = AVCaptureSessionPreset1920x1080; + sendVideo(); + } + else + { + UIAlertController *compressionPrompt = [MXKTools videoConversionPromptForVideoAsset:videoAsset withCompletion:^(NSString *presetName) { + // If the preset name is nil, the user cancelled. + if (!presetName) + { + return; + } + + // Set the chosen video conversion preset. + [MXSDKOptions sharedInstance].videoConversionPresetName = presetName; + sendVideo(); + }]; + + [self presentCompressionPrompt:compressionPrompt]; + } + } + else + { + // When rooms are encrypted we quickly run out of memory encrypting the video + // Prompt the user if they're happy to send a low quality video (320p). + UIAlertController *lowQualityPrompt = [UIAlertController alertControllerWithTitle:VectorL10n.shareExtensionLowQualityVideoTitle + message:[VectorL10n shareExtensionLowQualityVideoMessage:AppInfo.current.displayName] + preferredStyle:UIAlertControllerStyleAlert]; + + UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:MatrixKitL10n.cancel style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { + // Do nothing + }]; + UIAlertAction *sendAction = [UIAlertAction actionWithTitle:VectorL10n.shareExtensionSendNow style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { + [MXSDKOptions sharedInstance].videoConversionPresetName = AVAssetExportPresetMediumQuality; + sendVideo(); + }]; + + [lowQualityPrompt addAction:cancelAction]; + [lowQualityPrompt addAction:sendAction]; + [lowQualityPrompt setPreferredAction:sendAction]; + + [self presentCompressionPrompt:lowQualityPrompt]; + } +} + +- (void)sendVoiceMessage:(NSURL *)fileUrl + toRooms:(NSArray *)rooms + success:(dispatch_block_t)success + failure:(void(^)(NSError *error))failure +{ + [self didStartSending]; + if (!fileUrl) + { + MXLogError(@"[ShareItemSender] Invalid voice message file url."); + failure(nil); + return; + } + + __block NSError *error = nil; + dispatch_group_t dispatchGroup = dispatch_group_create(); + for (MXRoom *room in rooms) { + dispatch_group_enter(dispatchGroup); + [room sendVoiceMessage:fileUrl mimeType:nil duration:0.0 samples:nil localEcho:nil success:^(NSString *eventId) { + dispatch_group_leave(dispatchGroup); + } failure:^(NSError *innerError) { + MXLogError(@"[ShareItemSender] sendVoiceMessage failed with error %@", error); + error = innerError; + dispatch_group_leave(dispatchGroup); + } keepActualFilename:YES]; + } + + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + if(error) { + failure(error); + } else { + success(); + } + }); +} + +- (void)sendImageDatas:(NSArray> *)imageDatas + toRooms:(NSArray *)rooms + success:(dispatch_block_t)success + failure:(void(^)(NSError *error))failure +{ + if (imageDatas.count == 0) + { + MXLogError(@"[ShareManager] sendImages: no images to send."); + failure(nil); + return; + } + + [self didStartSending]; + + dispatch_group_t requestsGroup = dispatch_group_create(); + __block NSError *firstRequestError; + + NSUInteger index = 0; + + for (NSData *imageData in imageDatas) + { + @autoreleasepool + { + dispatch_group_enter(requestsGroup); + [self sendImageData:imageData toRooms:rooms success:^{ + dispatch_group_leave(requestsGroup); + } failure:^(NSError *error) { + if (error && !firstRequestError) + { + firstRequestError = error; + } + + dispatch_group_leave(requestsGroup); + }]; + } + + index++; + } + + dispatch_group_notify(requestsGroup, dispatch_get_main_queue(), ^{ + + if (firstRequestError) + { + failure(firstRequestError); + } + else + { + success(); + } + }); +} + +- (void)sendImageData:(NSData *)imageData + toRooms:(NSArray *)rooms + success:(dispatch_block_t)success + failure:(void(^)(NSError *error))failure +{ + [self didStartSending]; + + NSString *imageUTI; + NSString *mimeType; + + if (!mimeType) + { + imageUTI = [self utiFromImageData:imageData]; + if (imageUTI) + { + mimeType = [self mimeTypeFromUTI:imageUTI]; + } + } + + if (!mimeType) + { + MXLogError(@"[ShareManager] sendImage failed. Cannot determine MIME type ."); + if (failure) + { + failure(nil); + } + return; + } + + CGSize imageSize; + NSData *finalImageData; + + // Only resize JPEG or PNG files + if ([self isResizingSupportedForUTI:imageUTI]) + { + UIImage *convertedImage; + CGSize newImageSize; + + switch (self.imageCompressionMode) { + case ImageCompressionModeSmall: + newImageSize = CGSizeMake(MXKTOOLS_SMALL_IMAGE_SIZE, MXKTOOLS_SMALL_IMAGE_SIZE); + break; + case ImageCompressionModeMedium: + newImageSize = CGSizeMake(MXKTOOLS_MEDIUM_IMAGE_SIZE, MXKTOOLS_MEDIUM_IMAGE_SIZE); + break; + case ImageCompressionModeLarge: + newImageSize = CGSizeMake(self.actualLargeSize, self.actualLargeSize); + break; + default: + newImageSize = CGSizeZero; + break; + } + + if (!CGSizeEqualToSize(newImageSize, CGSizeZero)) + { + // Resize the image and set image in right orientation too + convertedImage = [MXKTools resizeImageWithData:imageData toFitInSize:newImageSize]; + } + + if (convertedImage) + { + if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypePNG]) + { + finalImageData = UIImagePNGRepresentation(convertedImage); + } + else if ([imageUTI isEqualToString:(__bridge NSString *)kUTTypeJPEG]) + { + finalImageData = UIImageJPEGRepresentation(convertedImage, 0.9); + } + + imageSize = convertedImage.size; + } + else + { + finalImageData = imageData; + imageSize = [self imageSizeFromImageData:imageData]; + } + } + else + { + finalImageData = imageData; + imageSize = [self imageSizeFromImageData:imageData]; + } + + __block NSError *error = nil; + dispatch_group_t dispatchGroup = dispatch_group_create(); + for (MXRoom *room in rooms) { + + UIImage *thumbnail = nil; + if (room.summary.isEncrypted) // Thumbnail is useful only in case of encrypted room + { + thumbnail = [MXKTools resizeImageWithData:imageData toFitInSize:kThumbnailSize]; + } + + dispatch_group_enter(dispatchGroup); + [room sendImage:finalImageData withImageSize:imageSize mimeType:mimeType andThumbnail:thumbnail localEcho:nil success:^(NSString *eventId) { + dispatch_group_leave(dispatchGroup); + } failure:^(NSError *innerError) { + MXLogError(@"[ShareManager] sendImage failed with error %@", error); + error = innerError; + dispatch_group_leave(dispatchGroup); + }]; + } + + dispatch_group_notify(dispatchGroup, dispatch_get_main_queue(), ^{ + if(error) { + failure(error); + } else { + success(); + } + }); +} + +@end diff --git a/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h b/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h index 9d1bfc7d9..cf576b194 100644 --- a/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h +++ b/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h @@ -5,3 +5,4 @@ #import "ThemeService.h" #import "AvatarGenerator.h" #import "BuildInfo.h" +#import "ShareItemSender.h" diff --git a/changelog.d/5014.change b/changelog.d/5014.change new file mode 100644 index 000000000..4c1c0e9a4 --- /dev/null +++ b/changelog.d/5014.change @@ -0,0 +1 @@ +Forward original message content and remove the need to re-upload media. \ No newline at end of file From 8e813b920bad298a5844d041824da82a45e17629 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Wed, 10 Nov 2021 19:19:17 +0200 Subject: [PATCH 038/122] Fix build: use correct swift generated header in share extension item sender. --- RiotShareExtension/Sources/ShareItemSender.m | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/RiotShareExtension/Sources/ShareItemSender.m b/RiotShareExtension/Sources/ShareItemSender.m index 4844e89a6..e1cd1add6 100644 --- a/RiotShareExtension/Sources/ShareItemSender.m +++ b/RiotShareExtension/Sources/ShareItemSender.m @@ -18,11 +18,7 @@ #import "ShareItemSender.h" -#ifdef IS_SHARE_EXTENSION -#import "RiotShareExtension-Swift.h" -#else -#import "Riot-Swift.h" -#endif +#import "GeneratedInterface-Swift.h" static const CGFloat kLargeImageSizeMaxDimension = 2048.0; static const CGSize kThumbnailSize = {800.0, 600.0}; From 1ea030889569be1a3e0762a6b5a8caf9192eb479 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Mon, 1 Nov 2021 16:52:00 +0200 Subject: [PATCH 039/122] vector-im/element-ios/issues/5114 - Poll creation screen - added input toolbar poll creation action. - reordered input toolbar actions as per designs. - added multiline text field and extracted common components. --- Config/BuildSettings.swift | 7 + DesignKit/Source/FontsSwiftUI.swift | 6 +- Podfile | 17 +- Podfile.lock | 22 +- .../xcshareddata/xcschemes/Riot.xcscheme | 3 +- .../action_poll.imageset/Contents.json | 23 ++ .../action_poll.imageset/action_poll.png | Bin 0 -> 213 bytes .../action_poll.imageset/action_poll@2x.png | Bin 0 -> 245 bytes .../action_poll.imageset/action_poll@3x.png | Bin 0 -> 322 bytes .../Images.xcassets/Room/Polls/Contents.json | 6 + .../poll_delete_icon.imageset/Contents.json | 23 ++ .../poll_delete_icon.png | Bin 0 -> 341 bytes .../poll_delete_icon@2x.png | Bin 0 -> 581 bytes .../poll_delete_icon@3x.png | Bin 0 -> 787 bytes .../Contents.json | 23 ++ .../poll_delete_option_icon.png | Bin 0 -> 630 bytes .../poll_delete_option_icon@2x.png | Bin 0 -> 1142 bytes .../poll_delete_option_icon@3x.png | Bin 0 -> 1693 bytes .../poll_edit_icon.imageset/Contents.json | 23 ++ .../poll_edit_icon.png | Bin 0 -> 461 bytes .../poll_edit_icon@2x.png | Bin 0 -> 763 bytes .../poll_edit_icon@3x.png | Bin 0 -> 1039 bytes .../poll_end_icon.imageset/Contents.json | 23 ++ .../poll_end_icon.imageset/poll_end_icon.png | Bin 0 -> 414 bytes .../poll_end_icon@2x.png | Bin 0 -> 624 bytes .../poll_end_icon@3x.png | Bin 0 -> 959 bytes Riot/Assets/en.lproj/Vector.strings | 16 ++ Riot/Generated/Images.swift | 5 + Riot/Generated/Strings.swift | 28 +++ Riot/Managers/Settings/RiotSettings.swift | 2 +- Riot/Modules/Room/RoomCoordinator.swift | 14 ++ Riot/Modules/Room/RoomViewController.h | 7 + Riot/Modules/Room/RoomViewController.m | 30 ++- RiotSwiftUI/Debug.xcconfig | 1 + .../Modules/Common/Mock/MockAppScreens.swift | 3 +- .../Util}/BorderedInputFieldStyle.swift | 27 ++- .../Common/Util/MultilineTextField.swift | 207 ++++++++++++++++++ .../Util/PrimaryActionButtonStyle.swift | 52 +++++ .../SafeBindingCollectionEnumerator.swift | 40 ++++ .../Coordinator/PollEditFormCoordinator.swift | 81 +++++++ .../PollEditForm/PollEditFormModels.swift | 77 +++++++ .../PollEditFormScreenState.swift | 34 +++ .../PollEditForm/PollEditFormViewModel.swift | 91 ++++++++ .../Test/UI/PollEditFormUITests.swift | 82 +++++++ .../Unit/PollEditFormViewModelTests.swift | 123 +++++++++++ .../Room/PollEditForm/View/PollEditForm.swift | 146 ++++++++++++ .../Service/UserSuggestionService.swift | 18 +- .../Unit/UserSuggestionServiceTests.swift | 4 +- RiotSwiftUI/Release.xcconfig | 1 + RiotSwiftUI/RiotSwiftUIApp.swift | 8 + 50 files changed, 1231 insertions(+), 42 deletions(-) create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_poll.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_poll.imageset/action_poll.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_poll.imageset/action_poll@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Actions/action_poll.imageset/action_poll@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/poll_edit_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/poll_edit_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/poll_edit_icon@3x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/Contents.json create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon@2x.png create mode 100644 Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon@3x.png rename RiotSwiftUI/Modules/{Settings/Notifications/View => Common/Util}/BorderedInputFieldStyle.swift (81%) create mode 100644 RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift create mode 100644 RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift create mode 100644 RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift create mode 100644 RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 6c15d412c..2d080c6d2 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -288,6 +288,13 @@ final class BuildSettings: NSObject { static let roomScreenAllowMediaLibraryAction: Bool = true static let roomScreenAllowStickerAction: Bool = true static let roomScreenAllowFilesAction: Bool = true + static var roomScreenAllowPollsAction: Bool { + guard #available(iOS 14, *) else { + return false + } + + return false + } /// Allow split view detail view stacking static let allowSplitViewDetailsScreenStacking: Bool = true diff --git a/DesignKit/Source/FontsSwiftUI.swift b/DesignKit/Source/FontsSwiftUI.swift index 223936286..ddf6a1754 100644 --- a/DesignKit/Source/FontsSwiftUI.swift +++ b/DesignKit/Source/FontsSwiftUI.swift @@ -22,6 +22,9 @@ import SwiftUI */ @available(iOS 14.0, *) public struct FontSwiftUI: Fonts { + + public let uiFonts: ElementFonts + public var largeTitle: Font public var largeTitleB: Font @@ -63,6 +66,8 @@ public struct FontSwiftUI: Fonts { public var caption2SB: Font public init(values: ElementFonts) { + self.uiFonts = values + self.largeTitle = Font(values.largeTitle) self.largeTitleB = Font(values.largeTitleB) self.title1 = Font(values.title1) @@ -85,4 +90,3 @@ public struct FontSwiftUI: Fonts { self.caption2SB = Font(values.caption2SB) } } - diff --git a/Podfile b/Podfile index f2fab251b..4cf944f90 100644 --- a/Podfile +++ b/Podfile @@ -43,6 +43,10 @@ end ######################################## +def import_SwiftUI_pods + pod 'Introspect', '~> 0.1' +end + abstract_target 'RiotPods' do pod 'GBDeviceInfo', '~> 6.6.0' @@ -63,6 +67,9 @@ abstract_target 'RiotPods' do target "Riot" do import_MatrixKit + + import_SwiftUI_pods + pod 'DGCollectionViewLeftAlignFlowLayout', '~> 1.0.4' pod 'KTCenterFlowLayout', '~> 1.3.1' pod 'ZXingObjC', '~> 3.6.5' @@ -73,7 +80,7 @@ abstract_target 'RiotPods' do pod 'SideMenu', '~> 6.5' pod 'DSWaveformImage', '~> 6.1.1' pod 'ffmpeg-kit-ios-audio', '~> 4.5' - + pod 'FLEX', '~> 4.5.0', :configurations => ['Debug'] target 'RiotTests' do @@ -85,6 +92,14 @@ abstract_target 'RiotPods' do import_MatrixKit end + target "RiotSwiftUI" do + import_SwiftUI_pods + end + + target "RiotSwiftUITests" do + import_SwiftUI_pods + end + target "SiriIntents" do import_MatrixKit end diff --git a/Podfile.lock b/Podfile.lock index 00be05819..9e25bd5ec 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -16,7 +16,7 @@ PODS: - AFNetworking/NSURLSession - BlueCryptor (1.0.32) - BlueECC (1.2.5) - - BlueRSA (1.0.34) + - BlueRSA (1.0.200) - DGCollectionViewLeftAlignFlowLayout (1.0.4) - Down (0.11.0) - DSWaveformImage (6.1.1) @@ -39,13 +39,13 @@ PODS: - DTFoundation/Core - ffmpeg-kit-ios-audio (4.5) - FLEX (4.5.0) - - FlowCommoniOS (1.12.0) + - FlowCommoniOS (1.12.2) - GBDeviceInfo (6.6.0): - GBDeviceInfo/Core (= 6.6.0) - GBDeviceInfo/Core (6.6.0) - - GrowingTextView (0.7.2) - GZIP (1.3.0) - HPGrowingTextView (1.1) + - Introspect (0.1.3) - JitsiMeetSDK (3.10.2) - KeychainAccess (4.2.2) - KituraContracts (1.2.1): @@ -100,7 +100,7 @@ PODS: - Reusable/View (4.1.2) - SideMenu (6.5.0) - SwiftBase32 (0.9.0) - - SwiftGen (6.4.0) + - SwiftGen (6.5.1) - SwiftJWT (3.6.200): - BlueCryptor (~> 1.0) - BlueECC (~> 1.1) @@ -122,7 +122,7 @@ DEPENDENCIES: - FLEX (~> 4.5.0) - FlowCommoniOS (~> 1.12.0) - GBDeviceInfo (~> 6.6.0) - - GrowingTextView (~> 0.7.2) + - Introspect (~> 0.1) - KeychainAccess (~> 4.2.2) - KTCenterFlowLayout (~> 1.3.1) - MatomoTracker (~> 7.4.1) @@ -156,9 +156,9 @@ SPEC REPOS: - FLEX - FlowCommoniOS - GBDeviceInfo - - GrowingTextView - GZIP - HPGrowingTextView + - Introspect - JitsiMeetSDK - KeychainAccess - KituraContracts @@ -188,7 +188,7 @@ SPEC CHECKSUMS: AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce BlueCryptor: b0aee3d9b8f367b49b30de11cda90e1735571c24 BlueECC: 0d18e93347d3ec6d41416de21c1ffa4d4cd3c2cc - BlueRSA: 6f9776d62d9773502415a7db3bcbb2bbb3f71fc3 + BlueRSA: dfeef51db96bcc4edec654956c1581adbda4e6a3 DGCollectionViewLeftAlignFlowLayout: a0fa58797373ded039cafba8133e79373d048399 Down: b6ba1bc985c9d2f4e15e3b293d2207766fa12612 DSWaveformImage: 3c718a0cf99291887ee70d1d0c18d80101d3d9ce @@ -196,11 +196,11 @@ SPEC CHECKSUMS: DTFoundation: a53f8cda2489208cbc71c648be177f902ee17536 ffmpeg-kit-ios-audio: 8c44d93054e1a9743a7014ec3dd26cd1ad8f2a59 FLEX: e51461dd6f0bfb00643c262acdfea5d5d12c596b - FlowCommoniOS: e9ecbc97fb9ce5c593fb3da0e1073b65a3902026 + FlowCommoniOS: ca92071ab526dc89905495a37844fd7e78d1a7f2 GBDeviceInfo: ed0db16230d2fa280e1cbb39a5a7f60f6946aaec - GrowingTextView: 876bf42005b5e4a4fd740597db12caaf41f0fe6c GZIP: 416858efbe66b41b206895ac6dfd5493200d95b3 HPGrowingTextView: 88a716d97fb853bcb08a4a08e4727da17efc9b19 + Introspect: 2be020f30f084ada52bb4387fff83fa52c5c400e JitsiMeetSDK: 2f118fa770f23e518f3560fc224fae3ac7062223 KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51 KituraContracts: e845e60dc8627ad0a76fa55ef20a45451d8f830b @@ -218,7 +218,7 @@ SPEC CHECKSUMS: Reusable: 6bae6a5e8aa793c9c441db0213c863a64bce9136 SideMenu: f583187d21c5b1dd04c72002be544b555a2627a2 SwiftBase32: 9399c25a80666dc66b51e10076bf591e3bbb8f17 - SwiftGen: 67860cc7c3cfc2ed25b9b74cfd55495fc89f9108 + SwiftGen: a6d22010845f08fe18fbdf3a07a8e380fd22e0ea SwiftJWT: 88c412708f58c169d431d344c87bc79a87c830ae SwiftLint: e96c0a8c770c7ebbc4d36c55baf9096bb65c4584 SwiftyBeaver: 84069991dd5dca07d7069100985badaca7f0ce82 @@ -226,6 +226,6 @@ SPEC CHECKSUMS: zxcvbn-ios: fef98b7c80f1512ff0eec47ac1fa399fc00f7e3c ZXingObjC: fdbb269f25dd2032da343e06f10224d62f537bdb -PODFILE CHECKSUM: 2740772a9b2d32e17876526875dfc58f67240ba0 +PODFILE CHECKSUM: 56547a5087a419eb4461b0fb59380381194392dc COCOAPODS: 1.11.2 diff --git a/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme b/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme index 84ecb908a..a9bea1d96 100644 --- a/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme +++ b/Riot.xcodeproj/xcshareddata/xcschemes/Riot.xcscheme @@ -4,7 +4,8 @@ version = "1.3"> + buildImplicitDependencies = "YES" + runPostActionsOnFailure = "NO"> Fx9i0A3EOw>w z)(eaxjxH>!Y=KOb+Z#R#)-idcFSNTe|2OLz&Zpn!Uw3>N?Wk7w&hW@GF-CsTGvYa! z2V;*)-DKGlnj`QfJ%=qO>t^Y!1#{-g&EjI=c=DLx-#O9FE{>XHpsfs^u6{1-oD!M< DZ%IRm literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Actions/action_poll.imageset/action_poll@2x.png b/Riot/Assets/Images.xcassets/Room/Actions/action_poll.imageset/action_poll@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..8880642457b1a3e236a66bb7bd9895b894acfa19 GIT binary patch literal 245 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=GY bFvRg6pD!kOBO-D)&{Yhcu6{1-oD!Mr&0DvkyOC){ z=R6Gt4vh!a30sY-^yj@e&6jqJp&?ZEm|tD~^~;|>TAV*4*Y~*Q|L^@hvNFg0(jMuFu8}$pShsL{!Q0s?}AXiH_;!CVkl3{5|2JA vX8kyP?*iR2w|E`w=3r<8Tgt((?;5vumR8EO?2cBT7a2TV{an^LB{Ts5XmDk} literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/Contents.json b/Riot/Assets/Images.xcassets/Room/Polls/Contents.json new file mode 100644 index 000000000..73c00596a --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Polls/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/Contents.json new file mode 100644 index 000000000..19dac30ff --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "poll_delete_icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "poll_delete_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "poll_delete_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..e2ad145460bbd3ad36e04019b089a4c6966fb35f GIT binary patch literal 341 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjoCO|{#S9GG!XV7ZFl!D-1!HlL zyA#8@b22Z19F}xPUq=Rpjs4tz5?O)#SDr48Ar*{or`n!l3>0a*Z~W}H(4*}}LYzzc zg4$(oG>Jwu2c@$ov6onRot|;%{L)XxN?ewHN`h%^Jre`ZUcNK?^S$bMk3`rxB&x)v z+5%I$e4a#JoVm%fCR1anPlaeo@y~5CXREoLS|wgyzkhRz*t5gGU#3~U-y>|WFJ$8#=k)YRWPRZN$g%&J;gj15U-!kl{&4O?&8Dd6gK{o!S|gOMDhCM954`mM-(vS{ z`)%yA_9~p^{=mHWP1rR7gM|trElmLrf;TvCV48P`okecPRoUMUGGx;}x)>>6*RoOQ ju3K%m%S*Q^@2BVucbnIaE7#cpea+zM>gTe~DWM4fUa*Kb literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon@2x.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_icon.imageset/poll_delete_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..b45ce02ed6f5e9d3271e1926f87da17a1022f99e GIT binary patch literal 581 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpTC&H|6fVg?2=RS;(M3{v?36l5$8 za(7}_cTVOdki(Mh=M~gUNFz zqx%8r0_Mk@J>KDu&dn`gDtxK?fu*QrQiF)O&z}wfkNNA@#dtiQTF0aK*?X4Wul!s0 zYf99NSq)yeI(YbbP4yPJAjDDWH*eDYyr1V7%Nz0SeA!J=JY!GU*u+HBhEZuJ?zYHFIww0~*$1*WwR zuBO;z{Z_4ESry!PBI~-LlKSI^jqwTWW>QmD9r0pp%u|W)G~f{FKh<;Jb-$mC`jwrk zdu#3&w%Oh&yC!v_%k^{D{yhCSjVwo_6FFEO+g-9hs@T9=E^E3Sbv%`o_+btGCJOqs`vyP7QWP{M$EM{};cuU&vT9edXfA x%dcFT8!Q+Z;x}f*BH0>;F*aVZoe$6kNso$Kk0M17}|4`7y;G7oG1U1Rm?*lU?oMYdXw>Hn3A3T#F z%(UOi_jrEd$*P4J*XjkOo_#7ZVqPk??n?H?)OmH!yp$YS_b|6UytYn~h5yu!xet@g z1dJc$oI1RD^Tw|wb<>?T--x|tK2L7uk)LM-W?stGx%lVv{6GhNxvy0_EdKwMR4w2$ z>1Mv?&U<$K?q6w@p9JU4@!M!{=T7pX zpaoID&lJeS&$oXvpVYS}_e>huUpxGl+m>X)roQj}_YHg|o|FD?bY0}R=bvre>v&{C z9s99IXYUDoW}G*N>8!kAS782PqqzBxZMp^h*-h(|55M?w{0FbsgRf_@w(18KIiGod zxnxiKq>8o8pPX;}S-$P8AFqVQTgNE%o*%zB4}W^}bP0 Hl+XkK^XFW7 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/Contents.json new file mode 100644 index 000000000..29638e38a --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "poll_delete_option_icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "poll_delete_option_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "poll_delete_option_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..0a1dc0a326db65609476253fa9a4867ed3389349 GIT binary patch literal 630 zcmV-+0*U>JP)8e(B5g^m`|%L`E1sI5OZriow}Cm`o8 zCK_Wd#4&zNF8A|&x4XBy2obn4&7A%=u|>lbL@Y@uXL%k4bmb6kL<*Z)Hr*`hdRxVT zVUwn9mtMR5DicE-NZH8bwf!)m9|HI0^A_FIpd04k7a*c80@mhcrs{$DFWf#_27L_p z8*1}2g_`#xyaC@l0dj_M|2X3M5@4URTOc7wkOp&p3cPllz2EvgS^#qHBLQ?@%z4Ut_xFn$G>J-9qst6vB=}yo$br8^LDDgDxBV+3<~fIuzNl2__VQTJ$JMq zIj zC4AuQQ8B4NJhV8Do?FHW_=Ox8l)2*4#szL9qeGPaZi2RKt6yJQDk>kyJNCdj$GD}l Q6951J07*qoM6N<$f&-)sW&i*H literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon@2x.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..bfc0e272d3cb18510907adc56b99b00fef97e3dd GIT binary patch literal 1142 zcmV-+1d02JP)7%C?z6kLJ1hI3Q@taDcD5T(BSf544IpK`99X zkO&YKWEup;J%o^5##okr($u4D`}>qsC=kd(n-H)G8XZu*^ZYbc{Yb+A(o~@U zAPgrI=8bQ-Z5Uha8SpL33Xu|!**lCoZg?Y!vEeHTt2bK`kSi9$C;9RcKaD^aV8F7y zL0{ZTZ?qJ!lRKINrY&^%tvA38%ku&Md@MZprp0~cpv&+>94?m&UCLB|ON|e85JkW3xt0K(%|^5Ag*fyPL58W!ao4IQgsccqfevNNc&3Sdthtp z^U%hJPh&o>SG^mX+MSBt*zeZ!7~~2{`SD~Zl-GNpbgW9RCO@V&N6O{0QanEPt!=y? z-{b~aeHM*>&7Tp^zvV(e0%I@e0yI^70+QfAH(py6A&fV+`FSsZJo-zg`n+#rk#>Lj zPNu%Cm564>Be!EwJGnp%2Q#(fKFCz``u@Y2d*ABY%|w_PKRYx1{Z{nmFR%e-fmGAf z39yM(5uGp|LEAlqk+#Om=?$e(6N?-Q4;zR4>8| zCyYn1P(YnpI+(drJx&>~!&s1lgR~OisPS+X4;&SM5d2!xzYzuwLwS`U4-R2A+X!SM zwiPHa;)sA&#tWPjp$}s2Noi=4i{^QmU?&TfDm@yn!4UfuM$19UEKbO-VvR7u>#US2 z+h7x`#>*}{tb(@F0+iOl2C~b8PKfY>lA@Rt@beT%g84vwTdR5AOoVJcP$eA-1+pRz zNDHXX2doCEW+Lq51B935@u&+ZD&?eXJivUQzpw8UQ$pDYD@2Ir?c@XKK6tE6KQ1dJ zUJTz$;6>kOcv@RZ*y)AKqQ~P~7UwkqIGA}wE(z`@frD3EG(@l;dxtBeOB)%oVC20P z9(-hMYgmo;D&7S*x)RocdOf~|G1?$N?;cHi0WJe~YmBZVXqpd<4qwG8o#lZ~-;~O8{+dD}2@X4f^&(|Zp(G4AR zDSc}dAnEu$8drD zT+%>IOhujGiFSm4!p8BU4@iQ=1D4h_mc^gj6!uH&c8xaj7rl8*HgPT7H2?qr07*qo IM6N<$f_w%5tN;K2 literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_delete_option_icon.imageset/poll_delete_option_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..a209b1b37bb66b85967b4d854268d60397a56bbd GIT binary patch literal 1693 zcmV;O24eY%P)<<)LSg!Kf1F!N zT#}_Yh5<_xAaf@|{yCXeB}E`Fg{j6AYVh3Y8IVBJ0>_BTe844uav`q~Q zBwUKYl-F%dqm;%|HwGh(xm-g6J<06EdDs0NbTAai^xNlNpLKe@V}aH-vI+hx0o}oj z(_W4`xd<%>xoYe6^&>~?Vw9+pJ#UG2_W3bdBl9&Ps#vP|$@ zaeQZW&Qc&^(5uj66m@nTo0aP0#{|OhPA|AtHRx)Xk*GdiA&}^`2pNMOh4)zTYAdP` z=y|R%-iy{_!T>_mR#ef=KYqG%Tb4jezuk-6f3W-(evV!k+Prf4(i%ua)%`K3&1;3P z&2In5f*xo7ACo1{-G!y|$v^%aC=?1B{ybP-d2{~G-64>~4?ixvTYdkf-|t000%%1c zJ#f^_90|m9V;m%rTK)Tt>SL=9ADxvU5{k28asT^&9a@tN3=oqI0wGXoxUG8jp=puq z#8E)ZY^;Sq`+K@naX$KR6|Ga-;n_d-7Z^yBpK1^a)vQIYD2 zgU`D1N13Em|oKf@_p0 zCFB&ekb3TBN2|p#pUd^SIb zHHplBThOqfy?`l^^W}8vOGR9tTHFT}L?V@dIRLyFiOlCK- z&kDCXt-8=DxL`A=`6sFy=5lK0r16VkMN zPx=ChdJVD_u4Y#8L3w)cO(zT{#nu!%#R)g!AWd&>B3#a(SKDrL6K*v=AGzM_j#bk3 z55im$)|z=Ol-Pm-V0JfKm>n4jH=VkXy1^2*P0#hhxEDgn7N+dJY7pgBhb0cmx9Gxr zdT#SzUZyZ6$~SovJs#*WSz?teC8bi7s^_&9QThNRirWNoSBzo-8?Lmq+9vSu6H6He nOXD_y0U*iE&Hc1$QObD%A$hZ>Ro=x900000NkvXXu0mjfhlmib literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/Contents.json new file mode 100644 index 000000000..b83445a6b --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "poll_edit_icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "poll_edit_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "poll_edit_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/poll_edit_icon.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_edit_icon.imageset/poll_edit_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..9bcc9356e115cf14d34761bf77187cab51406f30 GIT binary patch literal 461 zcmV;;0W$uHP)wd1!@Ii1!4tY2Ur0mfF0z4$e}MhIO8~@S@&?%u!N9{ zd4lgH$!720yWPD7*n6rC@48m^#)nMWe}sRa#gU-<{Y4?t=ebfUO!`<*5Z?90pST8n zLc1^h3I(XR$8CP}k~TtEAbkYV*EmHL*KJxcj-@@e==3FuCem(n0>^QDBpgXQ+k!N4 zjSU9kga;$eyXY3WQffNbv@X{Pe#CVllXebvGoMAhthHNfkR{GL?`~V4nIe68xb=qo z>K74T`eyy)Ue|>?Srw;yrJ@exWMd7g4Yx1FnMV_Gjh!yO9046E{{HrQ28N{9fS@G| zdd{>K3>cD{A}&l*h_4N?ysVu-w`Hv7N(>XO=mU!ni;4q?E@EvTN`m(kt^}ynk8U{~ zmrxRfG1zq8s!eQN>9-At#73#D5^kN#0yo4 zN~PlIER;rsINq_>Hc|Y&n4bY=yt}iX4M0grN#X45AH3e(^S^nX7l0543PvZ71T6pz z2;GmhnqQZE9-%;Pl3!uWuN^7Xzcl%d!V1{kJ9x#1^QiZcoTgIWFCYdN3ZUjcKSrXr z_XZ&~wzju_Tu**}zAr5IHBj^Yx)X+NvuF%rBOpg~mkFK97oOu)gYeGqs(%z0l-mgC zhOpA%he3R_ zJb6u~Yv9SVt@nI*5f?|OH!peen#>B=+4tY^;bmN$PM(kwC9lb(fQ2Gp(+&v9qNtHC*>#9AATle3i{<>dLyx4;5c3ea+9>Nhr% zpMM{uM9Ud3SR+MX1HDjc&;*O5DnKM>1eZhAKLpDpUc_QKn@(cQG6{*=XqIv&MLdPF zmNO}$5y(T%q=?o4%bE6@Oyx|9aRHv^H~G*oiA^JCQj7~AM57x{yeFKbkuxchH4r;> zY{;1uYa?Jw&ZHO>Pz{1AYe3|NW!rBg7)_z4(?4~(YsVn!@lNuF{U-M_zr?73nM-57 za$=o*x2MXxIDp&XSd(xYg>W`0N=Tu=e{-qykR|n&cf~cA8Q35g=etguy6hU>*>xe tq|K86k73i`*}*6H18kAT=ILEWQ=i9~iH7A)nq5GJfo8O)RNJ&XaNl8gbn3=iq&dl8WuTp7Y4GfZj zM*xZWfC4uW;2EG;c~K}p_v-Qx4B)(=P!4S0|BOT}nUdtRpoiq#VM>y-f?mzezb6Tw zhMglNCJ2sEESIa)kPm2SO#_dk z-gRgBg5X@_R0Wkvr3zr?yMmnl|caf2X$(#R%0CuU|j_b%U2_EOatKt7{aPaT3?Q+ z_pZB(+-Z3j)+{j@K0#9sia*OH_h5^d6QO4gMlP%OtKN0OKz6XBB#ZL}K=b^zs&NRu{^ugK2UdGnMVKDms&f=q?a zvu5KnjDfLMkPYFJ%UCOj!l%qviH1-1?}RZS!zVql)i_q-t31!dyPR~%vyWOMlBVqB2z;ggHeChbD_dj}|XbJL!sDcUt{G`Gs7cD_Fx2Om@?%i}&!4Y(u^h?&+7KBeOniYhM3bH3( zaZnZ%#tJdw)a<4liADuwE2Eqx^OdV|B+5OALS^-#&45q{`T)Tp9gohMr#?80vLJc$ zB%?0`0<0kh$ALHHw;Oe;zb+*yBI=lVO+1FzN-c zr?=1J3Zfp|!fLxcxM3G5NX|Kdm;Isj^%VD@C-C5Yc;p-uU}k&5B_+j8{sQFtw)|#DMB literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/Contents.json b/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/Contents.json new file mode 100644 index 000000000..165d80098 --- /dev/null +++ b/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/Contents.json @@ -0,0 +1,23 @@ +{ + "images" : [ + { + "filename" : "poll_end_icon.png", + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "poll_end_icon@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "poll_end_icon@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..8ca40ab42ed11516c32f5cd653fa3733b637f471 GIT binary patch literal 414 zcmV;P0b%}$P)Ivis9zjo_H&Acj))m|Uy@4hYhFwjYrY>}xhtL)n zLR-3l@U1#CFW=vJGXt<^r)X$|I6hC$Sx^!}h<4Sk4-`T#9a2gF$rZ950Jdq2_|urJ zRbWGw*&v5009x>zaKKg`qE@1UV7kqQmBi ztIO}K3J!!gy)qTkJw$o4K>S>*vh+7o;p5%2t)|c3w zOdz;5o4-)I5;>eD@?jS;uyn{mw7PmH57VKi+io&Ye6KMf zf$9I!)?~g7Vcu)_esmZf07xVfiA3^`NkM`smd_fw?D2g%ozs`gg(m7@kWh*hwa++f zZC3cxd^YWF_bHG-cI63nE9yOfgi)+ipBabNZiVMX{fW8*fASqs4cB|3^~3~lkblv% z=|EV61mG+`=~!JGdw?MFW)H+jPKAvln6@EP1mZBIdMQeZYsVsODAPyapnq zpq@7s!x&hUd-K`k5j+xE06Tfc`756DE%1RbKpr_tXS!It#+EVTtG1?TWAMqo|*PAjkDCKR4UcL0|iyRM9aQK`7NkC zAq;@GMHj4k3PJKX5|8j?5lxXFKi^+%2mx^b-1D?;1Qk~yT*%+(2!w#;DMXSaOVYbl z>(4}#@`UX%>NSLYfB5o*?e77SBS|;g$vNz*5w^T(;ikz+&QRb^F<|I*yM=-4Z(<5z zD2MNOcIUx0`;{kL|D+@dybE>Cn9FUje|f_5EL2cyc*?9t_IDy0dBWE)XCERudBXQJ zDh?5?JmLGl(d9zdGTD<)9MrDxeaOcl9~yW-)j%SVNF)-8cYXm0jyYpC>liWs0000< KMNUMnLSTZu#tmNp literal 0 HcmV?d00001 diff --git a/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon@3x.png b/Riot/Assets/Images.xcassets/Room/Polls/poll_end_icon.imageset/poll_end_icon@3x.png new file mode 100644 index 0000000000000000000000000000000000000000..282514b329dfbd2df438875577e325bb51ca9c8b GIT binary patch literal 959 zcmV;w13>(VP)Vt%hAi(v2%4FFxeknfU>w}x`;1$gLGW`wF1PT4rfao2N^i0e2NKkgZY6{H|1!nRrL=Y?Eis&W8$O3cS$_av#9Z7+mJ{WHq2wVa$^`?-OAcaO7jp%9$w7?T2ceva$CF3m(wD`iAt!nc7{ZX8MOiH4 zd_M@9n~(xV2pX51=y{+y~EMM^^yzaz+jnYo%6 zld?@|Acv!~;A9mtKq}~Z*o|+!!~ex&#(NtoL+|^dEC=9+7@MxdjZH^Ey2J*1j$2>x zI^M_n02!c*93)l{PUi03kTG8r&(tN&%+0^mMGg`x$nG=QA74*X(m)RED1_!B2Zqsx+K)I%Z}G+w?9Jybe4lC?}J{<&SN)Qk;RE~@4fTi%`H$scR7gi zPWo!1w86#xM;3=22-~zQ&ICC~qIWUZ_ucYU?@%PkmRsyM$rL$=v<3}>McaA)?7;4a zYeJG27mGD(vRZXJm+h~^_f3+6Boc%qkt8%NSEi<*)4uqIzfIR(y|y@4IFHgp4s!2t zN0PZPXRyPW)v&^FPa(Etg}o&mgOVNf%0W4zcCG$tHdQvLxiIp;EGAP9mW h2!bF8f*^>@`41s_%TS$pm3sgH002ovPDHLkV1g@Xv)ljx literal 0 HcmV?d00001 diff --git a/Riot/Assets/en.lproj/Vector.strings b/Riot/Assets/en.lproj/Vector.strings index 0ff5e437d..c8b57ab05 100644 --- a/Riot/Assets/en.lproj/Vector.strings +++ b/Riot/Assets/en.lproj/Vector.strings @@ -1780,3 +1780,19 @@ Tap the + to start adding people."; "version_check_modal_title_deprecated" = "We’re no longer supporting iOS %@"; "version_check_modal_subtitle_deprecated" = "We've been working on enhancing %@ for a faster and more polished experience. Unfortunately your current version of iOS is not compatible with some of those fixes and is no longer supported.\nWe're advising you to upgrade your operating system to use %@ to its full potential."; "version_check_modal_action_title_deprecated" = "Find out how"; + +// Mark: - Polls + +"poll_edit_form_create_poll" = "Create poll"; + +"poll_edit_form_poll_question_or_topic" = "Poll question or topic"; + +"poll_edit_form_question_or_topic" = "Question or topic"; + +"poll_edit_form_input_placeholder" = "Write something"; + +"poll_edit_form_create_options" = "Create options"; + +"poll_edit_form_option_number" = "Option %d"; + +"poll_edit_form_add_option" = "Add option"; diff --git a/Riot/Generated/Images.swift b/Riot/Generated/Images.swift index cd4a5b92e..92e82c765 100644 --- a/Riot/Generated/Images.swift +++ b/Riot/Generated/Images.swift @@ -114,6 +114,7 @@ internal enum Asset { internal static let actionCamera = ImageAsset(name: "action_camera") internal static let actionFile = ImageAsset(name: "action_file") internal static let actionMediaLibrary = ImageAsset(name: "action_media_library") + internal static let actionPoll = ImageAsset(name: "action_poll") internal static let actionSticker = ImageAsset(name: "action_sticker") internal static let error = ImageAsset(name: "error") internal static let errorMessageTick = ImageAsset(name: "error_message_tick") @@ -142,6 +143,10 @@ internal enum Asset { internal static let videoCall = ImageAsset(name: "video_call") internal static let voiceCallHangonIcon = ImageAsset(name: "voice_call_hangon_icon") internal static let voiceCallHangupIcon = ImageAsset(name: "voice_call_hangup_icon") + internal static let pollDeleteIcon = ImageAsset(name: "poll_delete_icon") + internal static let pollDeleteOptionIcon = ImageAsset(name: "poll_delete_option_icon") + internal static let pollEditIcon = ImageAsset(name: "poll_edit_icon") + internal static let pollEndIcon = ImageAsset(name: "poll_end_icon") internal static let urlPreviewClose = ImageAsset(name: "url_preview_close") internal static let urlPreviewCloseDark = ImageAsset(name: "url_preview_close_dark") internal static let voiceMessageCancelGradient = ImageAsset(name: "voice_message_cancel_gradient") diff --git a/Riot/Generated/Strings.swift b/Riot/Generated/Strings.swift index f3622c608..3ddc20669 100644 --- a/Riot/Generated/Strings.swift +++ b/Riot/Generated/Strings.swift @@ -2363,6 +2363,34 @@ public class VectorL10n: NSObject { public static func pinProtectionSettingsSectionHeaderWithBiometrics(_ p1: String) -> String { return VectorL10n.tr("Vector", "pin_protection_settings_section_header_with_biometrics", p1) } + /// Add option + public static var pollEditFormAddOption: String { + return VectorL10n.tr("Vector", "poll_edit_form_add_option") + } + /// Create options + public static var pollEditFormCreateOptions: String { + return VectorL10n.tr("Vector", "poll_edit_form_create_options") + } + /// Create poll + public static var pollEditFormCreatePoll: String { + return VectorL10n.tr("Vector", "poll_edit_form_create_poll") + } + /// Write something + public static var pollEditFormInputPlaceholder: String { + return VectorL10n.tr("Vector", "poll_edit_form_input_placeholder") + } + /// Option %d + public static func pollEditFormOptionNumber(_ p1: Int) -> String { + return VectorL10n.tr("Vector", "poll_edit_form_option_number", p1) + } + /// Poll question or topic + public static var pollEditFormPollQuestionOrTopic: String { + return VectorL10n.tr("Vector", "poll_edit_form_poll_question_or_topic") + } + /// Question or topic + public static var pollEditFormQuestionOrTopic: String { + return VectorL10n.tr("Vector", "poll_edit_form_question_or_topic") + } /// Preview public static var preview: String { return VectorL10n.tr("Vector", "preview") diff --git a/Riot/Managers/Settings/RiotSettings.swift b/Riot/Managers/Settings/RiotSettings.swift index 9e1ccd05b..4b372d460 100644 --- a/Riot/Managers/Settings/RiotSettings.swift +++ b/Riot/Managers/Settings/RiotSettings.swift @@ -165,7 +165,7 @@ final class RiotSettings: NSObject { @UserDefault(key: "roomScreenAllowFilesAction", defaultValue: BuildSettings.roomScreenAllowFilesAction, storage: defaults) var roomScreenAllowFilesAction - + @UserDefault(key: "roomScreenShowsURLPreviews", defaultValue: true, storage: defaults) var roomScreenShowsURLPreviews diff --git a/Riot/Modules/Room/RoomCoordinator.swift b/Riot/Modules/Room/RoomCoordinator.swift index 4764e03e9..fa9a5d2db 100644 --- a/Riot/Modules/Room/RoomCoordinator.swift +++ b/Riot/Modules/Room/RoomCoordinator.swift @@ -29,6 +29,8 @@ final class RoomCoordinator: NSObject, RoomCoordinatorProtocol { private let roomViewController: RoomViewController private let activityIndicatorPresenter: ActivityIndicatorPresenterType private var selectedEventId: String? + + private var pollEditFormCoordinator: PollEditFormCoordinator? private var roomDataSourceManager: MXKRoomDataSourceManager { return MXKRoomDataSourceManager.sharedManager(forMatrixSession: self.parameters.session) @@ -240,4 +242,16 @@ extension RoomCoordinator: RoomViewControllerDelegate { func roomViewController(_ roomViewController: RoomViewController, handleUniversalLinkWith parameters: UniversalLinkParameters) -> Bool { return AppDelegate.theDelegate().handleUniversalLink(with: parameters) } + + func roomViewControllerDidRequestPollCreationFormPresentation(_ roomViewController: RoomViewController) { + guard #available(iOS 14.0, *) else { + return + } + + let parameters = PollEditFormCoordinatorParameters(navigationRouter: self.navigationRouter) + + pollEditFormCoordinator = PollEditFormCoordinator(parameters: parameters) + + pollEditFormCoordinator?.start() + } } diff --git a/Riot/Modules/Room/RoomViewController.h b/Riot/Modules/Room/RoomViewController.h index 5016dec0f..3723eb5d8 100644 --- a/Riot/Modules/Room/RoomViewController.h +++ b/Riot/Modules/Room/RoomViewController.h @@ -176,6 +176,13 @@ extern NSNotificationName const RoomGroupCallTileTappedNotification; - (BOOL)roomViewController:(RoomViewController *)roomViewController handleUniversalLinkWithParameters:(UniversalLinkParameters*)parameters; +/** + Ask the coordinator to invoke the poll creation form coordinator. + + @param roomViewController the `RoomViewController` instance. + */ +- (void)roomViewControllerDidRequestPollCreationFormPresentation:(RoomViewController *)roomViewController; + @end NS_ASSUME_NONNULL_END diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index eba7a4ba4..589b6be8c 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -1987,16 +1987,6 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; RoomInputToolbarView *roomInputView = ((RoomInputToolbarView *) self.inputToolbarView); MXWeakify(self); NSMutableArray *actionItems = [NSMutableArray new]; - if (RiotSettings.shared.roomScreenAllowCameraAction) - { - [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_camera"] andAction:^{ - MXStrongifyAndReturnIfNil(self); - if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { - ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; - } - [self showCameraControllerAnimated:YES]; - }]]; - } if (RiotSettings.shared.roomScreenAllowMediaLibraryAction) { [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_media_library"] andAction:^{ @@ -2027,6 +2017,26 @@ const NSTimeInterval kResizeComposerAnimationDuration = .05; [self roomInputToolbarViewDidTapFileUpload]; }]]; } + if (BuildSettings.roomScreenAllowPollsAction) + { + [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_poll"] andAction:^{ + MXStrongifyAndReturnIfNil(self); + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; + } + [self.delegate roomViewControllerDidRequestPollCreationFormPresentation:self]; + }]]; + } + if (RiotSettings.shared.roomScreenAllowCameraAction) + { + [actionItems addObject:[[RoomActionItem alloc] initWithImage:[UIImage imageNamed:@"action_camera"] andAction:^{ + MXStrongifyAndReturnIfNil(self); + if ([self.inputToolbarView isKindOfClass:RoomInputToolbarView.class]) { + ((RoomInputToolbarView *) self.inputToolbarView).actionMenuOpened = NO; + } + [self showCameraControllerAnimated:YES]; + }]]; + } roomInputView.actionsBar.actionItems = actionItems; } diff --git a/RiotSwiftUI/Debug.xcconfig b/RiotSwiftUI/Debug.xcconfig index 11a7288a4..d890f7e35 100644 --- a/RiotSwiftUI/Debug.xcconfig +++ b/RiotSwiftUI/Debug.xcconfig @@ -18,3 +18,4 @@ // https://help.apple.com/xcode/#/dev745c5c974 #include "Common.xcconfig" +#include "Pods/Target Support Files/Pods-RiotPods-RiotSwiftUI/Pods-RiotPods-RiotSwiftUI.debug.xcconfig" diff --git a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift index 1195cd4ff..51c3e182c 100644 --- a/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift +++ b/RiotSwiftUI/Modules/Common/Mock/MockAppScreens.swift @@ -23,7 +23,8 @@ enum MockAppScreens { MockTemplateUserProfileScreenState.self, MockTemplateRoomListScreenState.self, MockTemplateRoomChatScreenState.self, - MockUserSuggestionScreenState.self + MockUserSuggestionScreenState.self, + MockPollEditFormScreenState.self ] } diff --git a/RiotSwiftUI/Modules/Settings/Notifications/View/BorderedInputFieldStyle.swift b/RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift similarity index 81% rename from RiotSwiftUI/Modules/Settings/Notifications/View/BorderedInputFieldStyle.swift rename to RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift index 89e4349fd..5fbcac5e6 100644 --- a/RiotSwiftUI/Modules/Settings/Notifications/View/BorderedInputFieldStyle.swift +++ b/RiotSwiftUI/Modules/Common/Util/BorderedInputFieldStyle.swift @@ -16,6 +16,7 @@ import Foundation import SwiftUI +import Introspect @available(iOS 14.0, *) /// A bordered style of text input @@ -49,10 +50,11 @@ struct BorderedInputFieldStyle: TextFieldStyle { } private var textColor: Color { - if !isEnabled { - return theme.colors.quarterlyContent + if (theme.identifier == ThemeIdentifier.dark) { + return (isEnabled ? theme.colors.primaryContent : theme.colors.tertiaryContent) + } else { + return (isEnabled ? theme.colors.primaryContent : theme.colors.quarterlyContent) } - return theme.colors.primaryContent } private var backgroundColor: Color { @@ -62,21 +64,31 @@ struct BorderedInputFieldStyle: TextFieldStyle { return theme.colors.background } + private var placeholderColor: Color { + return theme.colors.tertiaryContent + } + private var borderWidth: CGFloat { - return isEditing || isError ? 2 : 1.5 + return isEditing || isError ? 2.0 : 1.5 } func _body(configuration: TextField<_Label>) -> some View { - let rect = RoundedRectangle(cornerRadius: 8) + let rect = RoundedRectangle(cornerRadius: 8.0) return configuration .font(theme.fonts.callout) .foregroundColor(textColor) .accentColor(accentColor) - .frame(height: 48) - .padding(.horizontal, 8) + .frame(height: 48.0) + .padding(.horizontal, 8.0) .background(backgroundColor) .clipShape(rect) .overlay(rect.stroke(borderColor, lineWidth: borderWidth)) + .introspectTextField { textField in + textField.returnKeyType = .done + textField.clearButtonMode = .whileEditing + textField.attributedPlaceholder = NSAttributedString(string: textField.placeholder ?? "", + attributes: [NSAttributedString.Key.foregroundColor: UIColor(placeholderColor)]) + } } } @@ -118,6 +130,5 @@ struct BorderedInputFieldStyle_Previews: PreviewProvider { .padding() .theme(ThemeIdentifier.dark) } - } } diff --git a/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift b/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift new file mode 100644 index 000000000..dd710f70e --- /dev/null +++ b/RiotSwiftUI/Modules/Common/Util/MultilineTextField.swift @@ -0,0 +1,207 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +@available(iOS 14.0, *) +struct MultilineTextField: View { + + @Environment(\.theme) private var theme: ThemeSwiftUI + + @Binding private var text: String + @State private var dynamicHeight: CGFloat = 100 + @State private var isEditing = false + + private var placeholder: String = "" + + private var showingPlaceholder: Bool { + text.isEmpty + } + + init(_ placeholder: String, text: Binding) { + self.placeholder = placeholder + self._text = text + } + + private var textColor: Color { + if (theme.identifier == ThemeIdentifier.dark) { + return theme.colors.primaryContent + } else { + return theme.colors.primaryContent + } + } + + private var backgroundColor: Color { + return theme.colors.background + } + + private var placeholderColor: Color { + return theme.colors.tertiaryContent + } + + private var borderColor: Color { + if isEditing { + return theme.colors.accent + } + + return theme.colors.quarterlyContent + } + + private var borderWidth: CGFloat { + return isEditing ? 2.0 : 1.5 + } + + var body: some View { + let rect = RoundedRectangle(cornerRadius: 8.0) + return UITextViewWrapper(text: $text, calculatedHeight: $dynamicHeight, isEditing: $isEditing) + .frame(minHeight: dynamicHeight, maxHeight: dynamicHeight) + .padding(4.0) + .background(placeholderView, alignment: .topLeading) + .animation(.none) + .background(backgroundColor) + .clipShape(rect) + .overlay(rect.stroke(borderColor, lineWidth: borderWidth)) + .introspectTextView { textView in + textView.textColor = UIColor(textColor) + textView.font = theme.fonts.uiFonts.callout + } + } + + @ViewBuilder + private var placeholderView: some View { + if showingPlaceholder { + Text(placeholder) + .foregroundColor(placeholderColor) + .font(theme.fonts.callout) + .padding(.leading, 8.0) + .padding(.top, 12.0) + } + } +} + +@available(iOS 14.0, *) +fileprivate struct UITextViewWrapper: UIViewRepresentable { + typealias UIViewType = UITextView + + @Binding var text: String + @Binding var calculatedHeight: CGFloat + @Binding var isEditing: Bool + + func makeUIView(context: UIViewRepresentableContext) -> UITextView { + let textView = UITextView() + textView.delegate = context.coordinator + + textView.isEditable = true + textView.font = UIFont.preferredFont(forTextStyle: .body) + textView.isSelectable = true + textView.isUserInteractionEnabled = true + textView.isScrollEnabled = false + textView.backgroundColor = UIColor.clear + textView.returnKeyType = .done + + textView.setContentCompressionResistancePriority(.defaultLow, for: .horizontal) + return textView + } + + func updateUIView(_ uiView: UITextView, context: UIViewRepresentableContext) { + if uiView.text != self.text { + uiView.text = self.text + } + + UITextViewWrapper.recalculateHeight(view: uiView, result: $calculatedHeight) + } + + fileprivate static func recalculateHeight(view: UIView, result: Binding) { + let newSize = view.sizeThatFits(CGSize(width: view.frame.size.width, height: CGFloat.greatestFiniteMagnitude)) + if result.wrappedValue != newSize.height { + DispatchQueue.main.async { + result.wrappedValue = newSize.height // !! must be called asynchronously + } + } + } + + func makeCoordinator() -> Coordinator { + return Coordinator(text: $text, height: $calculatedHeight, isEditing: $isEditing) + } + + final class Coordinator: NSObject, UITextViewDelegate { + var text: Binding + var calculatedHeight: Binding + var isEditing: Binding + + init(text: Binding, height: Binding, isEditing: Binding) { + self.text = text + self.calculatedHeight = height + self.isEditing = isEditing + } + + func textViewDidChange(_ uiView: UITextView) { + text.wrappedValue = uiView.text + UITextViewWrapper.recalculateHeight(view: uiView, result: calculatedHeight) + } + + func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { + if text == "\n" { + textView.resignFirstResponder() + return false + } + + return true + } + + func textViewDidBeginEditing(_ textView: UITextView) { + isEditing.wrappedValue = true + } + + func textViewDidEndEditing(_ textView: UITextView) { + isEditing.wrappedValue = false + } + } +} + +@available(iOS 14.0, *) +struct MultilineTextField_Previews: PreviewProvider { + + static var previews: some View { + return Group { + VStack { + PreviewWrapper() + PlaceholderPreviewWrapper() + PreviewWrapper() + .theme(ThemeIdentifier.dark) + PlaceholderPreviewWrapper() + .theme(ThemeIdentifier.dark) + } + } + .padding() + } + + struct PreviewWrapper: View { + @State(initialValue: "123") var text: String + + var body: some View { + MultilineTextField("Placeholder", text: $text) + } + } + + struct PlaceholderPreviewWrapper: View { + @State(initialValue: "") var text: String + + var body: some View { + MultilineTextField("Placeholder", text: $text) + } + } +} diff --git a/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift b/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift new file mode 100644 index 000000000..9d94bac8d --- /dev/null +++ b/RiotSwiftUI/Modules/Common/Util/PrimaryActionButtonStyle.swift @@ -0,0 +1,52 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +@available(iOS 14.0, *) +struct PrimaryActionButtonStyle: ButtonStyle { + @Environment(\.theme) private var theme: ThemeSwiftUI + + var enabled: Bool = false + + func makeBody(configuration: Self.Configuration) -> some View { + configuration.label + .padding(12.0) + .frame(maxWidth: .infinity) + .foregroundColor(.white) + .font(theme.fonts.body) + .background(configuration.isPressed ? theme.colors.accent.opacity(0.6) : theme.colors.accent) + .opacity(enabled ? 1.0 : 0.6) + .cornerRadius(8.0) + } +} + +@available(iOS 14.0, *) +struct PrimaryActionButtonStyle_Previews: PreviewProvider { + static var previews: some View { + Group { + VStack { + Button("Enabled") { } + .buttonStyle(PrimaryActionButtonStyle(enabled: true)) + + Button("Disabled") { } + .buttonStyle(PrimaryActionButtonStyle(enabled: false)) + .disabled(true) + } + .padding() + } + } +} diff --git a/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift b/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift new file mode 100644 index 000000000..45ea51855 --- /dev/null +++ b/RiotSwiftUI/Modules/Common/Util/SafeBindingCollectionEnumerator.swift @@ -0,0 +1,40 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +/** + Used to avoid crashes when enumerating through bindings in the AnswerOptions ForEach + https://stackoverflow.com/q/65375372 + Replace with Swift 5.5 bindings enumerator later. + */ +@available(iOS 14.0, *) +struct SafeBindingCollectionEnumerator: View { + + typealias BoundElement = Binding + private let binding: BoundElement + private let content: (BoundElement) -> C + + init(_ binding: Binding, index: T.Index, @ViewBuilder content: @escaping (BoundElement) -> C) { + self.content = content + self.binding = .init(get: { binding.wrappedValue[index] }, + set: { binding.wrappedValue[index] = $0 }) + } + + var body: some View { + content(binding) + } +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift new file mode 100644 index 000000000..1df71686e --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Coordinator/PollEditFormCoordinator.swift @@ -0,0 +1,81 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/PollEditForm PollEditForm +/* + Copyright 2021 New Vector Ltd + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + */ + +import Foundation +import UIKit +import SwiftUI + +struct PollEditFormCoordinatorParameters { + let navigationRouter: NavigationRouterType? +} + +final class PollEditFormCoordinator: Coordinator { + + // MARK: - Properties + + // MARK: Private + + private let parameters: PollEditFormCoordinatorParameters + private let pollEditFormHostingController: UIViewController + private var _pollEditFormViewModel: Any? = nil + + @available(iOS 14.0, *) + fileprivate var pollEditFormViewModel: PollEditFormViewModel { + return _pollEditFormViewModel as! PollEditFormViewModel + } + + // MARK: Public + + // Must be used only internally + var childCoordinators: [Coordinator] = [] + + // MARK: - Setup + + @available(iOS 14.0, *) + init(parameters: PollEditFormCoordinatorParameters) { + self.parameters = parameters + + let viewModel = PollEditFormViewModel() + let view = PollEditForm(viewModel: viewModel.context) + + _pollEditFormViewModel = viewModel + pollEditFormHostingController = VectorHostingController(rootView: view) + } + + // MARK: - Public + func start() { + guard #available(iOS 14.0, *) else { + MXLog.debug("[PollEditFormCoordinator] start: Invalid iOS version, returning.") + return + } + + MXLog.debug("[PollEditFormCoordinator] did start.") + + parameters.navigationRouter?.present(pollEditFormHostingController, animated: true) + + pollEditFormViewModel.completion = { [weak self] result in + guard let self = self else { return } + switch result { + case .cancel: + self.parameters.navigationRouter?.dismissModule(animated: true, completion: nil) + case .create(_, _): + break + } + } + } +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift new file mode 100644 index 000000000..9e6657506 --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormModels.swift @@ -0,0 +1,77 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/PollEditForm PollEditForm +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI + +enum PollEditFormStateAction { + case viewAction(PollEditFormViewAction) +} + +enum PollEditFormViewAction { + case addAnswerOption + case deleteAnswerOption(PollEditFormAnswerOption) + case cancel + case create +} + +enum PollEditFormViewModelResult { + case cancel + case create(String, [String]) +} + +struct PollEditFormQuestion { + var text: String { + didSet { + text = String(text.prefix(maxLength)) + } + } + + let maxLength: Int +} + +struct PollEditFormAnswerOption: Identifiable, Equatable { + let id = UUID() + + var text: String { + didSet { + text = String(text.prefix(maxLength)) + } + } + + let maxLength: Int +} + +struct PollEditFormViewState: BindableState { + let maxAnswerOptionsCount: Int + var bindings: PollEditFormViewStateBindings + + var confirmationButtonEnabled: Bool { + !bindings.question.text.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty && + bindings.answerOptions.filter({ !$0.text.isEmpty }).count >= 2 + } + + var addAnswerOptionButtonEnabled: Bool { + bindings.answerOptions.count < maxAnswerOptionsCount + } +} + +struct PollEditFormViewStateBindings { + var question: PollEditFormQuestion + var answerOptions: [PollEditFormAnswerOption] +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift new file mode 100644 index 000000000..2e545a9d4 --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormScreenState.swift @@ -0,0 +1,34 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/UserSuggestion UserSuggestion +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import Foundation +import SwiftUI + +@available(iOS 14.0, *) +enum MockPollEditFormScreenState: MockScreenState, CaseIterable { + case standard + + var screenType: Any.Type { + MockPollEditFormScreenState.self + } + + var screenView: ([Any], AnyView) { + let viewModel = PollEditFormViewModel() + return ([viewModel], AnyView(PollEditForm(viewModel: viewModel.context))) + } +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift new file mode 100644 index 000000000..b77274bcb --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/PollEditFormViewModel.swift @@ -0,0 +1,91 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/PollEditForm PollEditForm +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import Combine + +@available(iOS 14, *) +typealias PollEditFormViewModelType = StateStoreViewModel< PollEditFormViewState, + PollEditFormStateAction, + PollEditFormViewAction > +@available(iOS 14, *) +class PollEditFormViewModel: PollEditFormViewModelType { + + private struct Constants { + static let maxAnswerOptionsCount = 20 + static let maxQuestionLength = 200 + static let maxAnswerOptionLength = 200 + } + + // MARK: - Properties + + // MARK: Private + + // MARK: Public + + var completion: ((PollEditFormViewModelResult) -> Void)? + + // MARK: - Setup + + init() { + super.init(initialViewState: Self.defaultState()) + } + + private static func defaultState() -> PollEditFormViewState { + return PollEditFormViewState( + maxAnswerOptionsCount: Constants.maxAnswerOptionsCount, + bindings: PollEditFormViewStateBindings( + question: PollEditFormQuestion(text: "", maxLength: Constants.maxQuestionLength), + answerOptions: [PollEditFormAnswerOption(text: "", maxLength: Constants.maxAnswerOptionLength), + PollEditFormAnswerOption(text: "", maxLength: Constants.maxAnswerOptionLength) + ] + ) + ) + } + + // MARK: - Public + + override func process(viewAction: PollEditFormViewAction) { + switch viewAction { + case .cancel: + completion?(.cancel) + case .create: + completion?(.create(state.bindings.question.text.trimmingCharacters(in: .whitespacesAndNewlines), + state.bindings.answerOptions.compactMap({ answerOption in + let text = answerOption.text.trimmingCharacters(in: .whitespacesAndNewlines) + return text.isEmpty ? nil : text + }))) + default: + dispatch(action: .viewAction(viewAction)) + } + } + + override class func reducer(state: inout PollEditFormViewState, action: PollEditFormStateAction) { + switch action { + case .viewAction(let viewAction): + switch viewAction { + case .deleteAnswerOption(let answerOption): + state.bindings.answerOptions.removeAll { $0 == answerOption } + case .addAnswerOption: + state.bindings.answerOptions.append(PollEditFormAnswerOption(text: "", maxLength: Constants.maxAnswerOptionLength)) + default: + break + } + } + } +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift new file mode 100644 index 000000000..daee82cbd --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Test/UI/PollEditFormUITests.swift @@ -0,0 +1,82 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/PollEditForm PollEditForm +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest +import RiotSwiftUI + +@available(iOS 14.0, *) +class PollEditFormUITests: XCTestCase { + + private var app: XCUIApplication! + + override func setUp() { + continueAfterFailure = false + + app = XCUIApplication() + app.launch() + app.buttons[MockPollEditFormScreenState.screenStateKeys.first!].tap() + } + + func testInitialStateComponents() { + + XCTAssert(app.scrollViews.firstMatch.exists) + + XCTAssert(app.staticTexts["Create poll"].exists) + XCTAssert(app.staticTexts["Poll question or topic"].exists) + XCTAssert(app.staticTexts["Question or topic"].exists) + XCTAssert(app.staticTexts["Create options"].exists) + + XCTAssert(app.textViews.count == 1) + + XCTAssert(app.textFields.count == 2) + XCTAssert(app.staticTexts["Option 1"].exists) + XCTAssert(app.staticTexts["Option 2"].exists) + + let cancelButton = app.buttons["Cancel"] + XCTAssert(cancelButton.exists) + XCTAssertTrue(cancelButton.isEnabled) + + let addOptionButton = app.buttons["Add option"] + XCTAssert(addOptionButton.exists) + XCTAssertTrue(addOptionButton.isEnabled) + + let createPollButton = app.buttons["Create poll"] + XCTAssert(createPollButton.exists) + XCTAssertFalse(createPollButton.isEnabled) + } + + func testRemoveAddAnswerOptions() { + + let deleteAnswerOptionButton = app.buttons["Delete answer option"].firstMatch + + XCTAssert(deleteAnswerOptionButton.waitForExistence(timeout: 2.0)) + deleteAnswerOptionButton.tap() + + XCTAssert(deleteAnswerOptionButton.waitForExistence(timeout: 2.0)) + deleteAnswerOptionButton.tap() + + let addOptionButton = app.buttons["Add option"] + XCTAssert(addOptionButton.waitForExistence(timeout: 2.0)) + XCTAssertTrue(addOptionButton.isEnabled) + + for i in 1...3 { + addOptionButton.tap() + XCTAssert(app.staticTexts["Option \(i)"].waitForExistence(timeout: 2.0)) + } + } +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift b/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift new file mode 100644 index 000000000..739361197 --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/Test/Unit/PollEditFormViewModelTests.swift @@ -0,0 +1,123 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/PollEditForm PollEditForm +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import XCTest +import Combine + +@testable import RiotSwiftUI + +@available(iOS 14.0, *) +class PollEditFormViewModelTests: XCTestCase { + var viewModel: PollEditFormViewModel! + var context: PollEditFormViewModelType.Context! + var cancellables = Set() + + override func setUpWithError() throws { + viewModel = PollEditFormViewModel() + context = viewModel.context + } + + func testInitialState() { + XCTAssertTrue(context.question.text.isEmpty) + XCTAssertFalse(context.viewState.confirmationButtonEnabled) + XCTAssertTrue(context.viewState.addAnswerOptionButtonEnabled) + + XCTAssertEqual(context.answerOptions.count, 2) + for answerOption in context.answerOptions { + XCTAssertTrue(answerOption.text.isEmpty) + } + } + + func testDeleteAllAnswerOptions() { + while !context.answerOptions.isEmpty { + context.send(viewAction: .deleteAnswerOption(context.answerOptions.first!)) + } + + XCTAssertEqual(context.answerOptions.count, 0) + XCTAssertFalse(context.viewState.confirmationButtonEnabled) + XCTAssertTrue(context.viewState.addAnswerOptionButtonEnabled) + } + + func testAddRemoveAnswerOption() { + context.send(viewAction: .addAnswerOption) + + XCTAssertEqual(context.answerOptions.count, 3) + + context.send(viewAction: .deleteAnswerOption(context.answerOptions.first!)) + + XCTAssertEqual(context.answerOptions.count, 2) + } + + func testCreateEnabled() { + context.question.text = "Some question" + context.answerOptions[0].text = "First answer" + context.answerOptions[1].text = "Second answer" + + XCTAssertTrue(context.viewState.confirmationButtonEnabled) + } + + func testReachedMaxAnswerOptions() { + for _ in 0...context.viewState.maxAnswerOptionsCount { + context.send(viewAction: .addAnswerOption) + } + + XCTAssertFalse(context.viewState.addAnswerOptionButtonEnabled) + } + + func testQuestionMaxLength() { + let question = String(repeating: "S", count: context.question.maxLength + 100) + context.question.text = question + + XCTAssertEqual(context.question.text.count, context.question.maxLength) + } + + func testAnswerOptionMaxLength() { + let answerOption = String(repeating: "S", count: context.answerOptions[0].maxLength + 100) + context.answerOptions[0].text = answerOption + + XCTAssertEqual(context.answerOptions[0].text.count, context.answerOptions[0].maxLength) + } + + func testFormCompletion() { + let question = "Some question " + let firstAnswer = "First answer " + let secondAnswer = "Second answer " + let thirdAnswer = " " + + viewModel.completion = { result in + if case PollEditFormViewModelResult.create(let resultQuestion, let resultAnswerOptions) = result { + XCTAssertEqual(question.trimmingCharacters(in: .whitespacesAndNewlines), resultQuestion) + + // The last answer option should be automatically dropped as it's empty + XCTAssertEqual(resultAnswerOptions.count, 2) + + XCTAssertEqual(resultAnswerOptions[0], firstAnswer.trimmingCharacters(in: .whitespacesAndNewlines)) + XCTAssertEqual(resultAnswerOptions[1], secondAnswer.trimmingCharacters(in: .whitespacesAndNewlines)) + } + } + + context.question.text = question + context.answerOptions[0].text = firstAnswer + context.answerOptions[1].text = secondAnswer + + context.send(viewAction: .addAnswerOption) + context.answerOptions[2].text = thirdAnswer + + context.send(viewAction: .create) + } +} diff --git a/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift new file mode 100644 index 000000000..1d874688b --- /dev/null +++ b/RiotSwiftUI/Modules/Room/PollEditForm/View/PollEditForm.swift @@ -0,0 +1,146 @@ +// File created from SimpleUserProfileExample +// $ createScreen.sh Room/PollEditForm PollEditForm +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +@available(iOS 14.0, *) +struct PollEditForm: View { + + // MARK: - Properties + + // MARK: Private + + @Environment(\.theme) private var theme: ThemeSwiftUI + + // MARK: Public + + @ObservedObject var viewModel: PollEditFormViewModel.Context + + var body: some View { + NavigationView { + GeometryReader { proxy in + ScrollView { + VStack(alignment: .leading, spacing: 32.0) { + + VStack(alignment: .leading, spacing: 16.0) { + Text(VectorL10n.pollEditFormPollQuestionOrTopic) + .font(theme.fonts.title3SB) + .foregroundColor(theme.colors.primaryContent) + + VStack(alignment: .leading, spacing: 8.0) { + Text(VectorL10n.pollEditFormQuestionOrTopic) + .font(theme.fonts.subheadline) + .foregroundColor(theme.colors.primaryContent) + + MultilineTextField(VectorL10n.pollEditFormInputPlaceholder, text: $viewModel.question.text) + } + } + + VStack(alignment: .leading, spacing: 16.0) { + Text(VectorL10n.pollEditFormCreateOptions) + .font(theme.fonts.title3SB) + .foregroundColor(theme.colors.primaryContent) + + ForEach(0.. Void + + var body: some View { + VStack(alignment: .leading, spacing: 8.0) { + Text(VectorL10n.pollEditFormOptionNumber(index + 1)) + .font(theme.fonts.subheadline) + .foregroundColor(theme.colors.primaryContent) + + HStack(spacing: 16.0) { + TextField(VectorL10n.pollEditFormInputPlaceholder, text: $text, onEditingChanged: { edit in + self.focused = edit + }) + .textFieldStyle(BorderedInputFieldStyle(theme: _theme, isEditing: focused)) + Button { + onDelete() + } label: { + Image(uiImage:Asset.Images.pollDeleteOptionIcon.image) + } + .accessibilityIdentifier("Delete answer option") + } + } + } +} + +// MARK: - Previews + +@available(iOS 14.0, *) +struct PollEditForm_Previews: PreviewProvider { + static let stateRenderer = MockPollEditFormScreenState.stateRenderer + static var previews: some View { + stateRenderer.screenGroup() + } +} diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift index 6e4fab347..1491aa579 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Service/UserSuggestionService.swift @@ -61,14 +61,20 @@ class UserSuggestionService: UserSuggestionServiceProtocol { // MARK: - Setup - init(roomMemberProvider: RoomMembersProviderProtocol) { + init(roomMemberProvider: RoomMembersProviderProtocol, shouldDebounce: Bool = true) { self.roomMemberProvider = roomMemberProvider - currentTextTriggerSubject - .debounce(for: 0.5, scheduler: RunLoop.main) - .removeDuplicates() - .sink { [weak self] in self?.fetchAndFilterMembersForTextTrigger($0) } - .store(in: &cancellables) + if (shouldDebounce) { + currentTextTriggerSubject + .debounce(for: 0.5, scheduler: RunLoop.main) + .removeDuplicates() + .sink { [weak self] in self?.fetchAndFilterMembersForTextTrigger($0) } + .store(in: &cancellables) + } else { + currentTextTriggerSubject + .sink { [weak self] in self?.fetchAndFilterMembersForTextTrigger($0) } + .store(in: &cancellables) + } } // MARK: - UserSuggestionServiceProtocol diff --git a/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift b/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift index 1c34f7eb3..fce852059 100644 --- a/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift +++ b/RiotSwiftUI/Modules/Room/UserSuggestion/Test/Unit/UserSuggestionServiceTests.swift @@ -27,7 +27,7 @@ class UserSuggestionServiceTests: XCTestCase { var service: UserSuggestionService? override func setUp() { - service = UserSuggestionService(roomMembersProvider: self) + service = UserSuggestionService(roomMemberProvider: self, shouldDebounce: false) } func testAlice() { @@ -116,7 +116,7 @@ extension UserSuggestionServiceTests: RoomMembersProviderProtocol { ("Bob", "@bob:matrix.org")] members(users.map({ user in - RoomMembersProviderMember(identifier: user.1, displayName: user.0, avatarURL: "") + RoomMembersProviderMember(userId: user.1, displayName: user.0, avatarUrl: "") })) } } diff --git a/RiotSwiftUI/Release.xcconfig b/RiotSwiftUI/Release.xcconfig index 11a7288a4..561518704 100644 --- a/RiotSwiftUI/Release.xcconfig +++ b/RiotSwiftUI/Release.xcconfig @@ -18,3 +18,4 @@ // https://help.apple.com/xcode/#/dev745c5c974 #include "Common.xcconfig" +#include "Pods/Target Support Files/Pods-RiotPods-RiotSwiftUI/Pods-RiotPods-RiotSwiftUI.release.xcconfig" diff --git a/RiotSwiftUI/RiotSwiftUIApp.swift b/RiotSwiftUI/RiotSwiftUIApp.swift index 63dbece0d..902f7327d 100644 --- a/RiotSwiftUI/RiotSwiftUIApp.swift +++ b/RiotSwiftUI/RiotSwiftUIApp.swift @@ -21,6 +21,14 @@ import SwiftUI struct RiotSwiftUIApp: App { init() { UILog.configure(logger: PrintLogger.self) + + switch UITraitCollection.current.userInterfaceStyle { + case .dark: + ThemePublisher.configure(themeId: .dark) + default: + ThemePublisher.configure(themeId: .light) + } + } var body: some Scene { WindowGroup { From cb04e132618e5efbbbf35ff6879cb10b83c28fd3 Mon Sep 17 00:00:00 2001 From: Farhad Date: Wed, 10 Nov 2021 12:26:49 +0000 Subject: [PATCH 040/122] Translated using Weblate (Persian) Currently translated at 12.4% (166 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fa/ --- Riot/Assets/fa.lproj/Vector.strings | 99 +++++++++++++++++++++++++++++ 1 file changed, 99 insertions(+) diff --git a/Riot/Assets/fa.lproj/Vector.strings b/Riot/Assets/fa.lproj/Vector.strings index d67b98658..3e279a22e 100644 --- a/Riot/Assets/fa.lproj/Vector.strings +++ b/Riot/Assets/fa.lproj/Vector.strings @@ -94,3 +94,102 @@ "bug_report_send" = "ارسال"; "done" = "انجام شد"; "open" = "باز کردن"; +"contacts_address_book_matrix_users_toggle" = "فقط کاربران ماتریس"; +"directory_search_results_more_than" = ">%tu نتیجه یافت شد برای %@"; +"directory_search_results" = "%tu نتیجه یافت شد برای %@"; +"search_in_progress" = "در حال جست وجو"; +"search_no_result" = "نتیچه ای یافت نشد"; +"search_people_placeholder" = "جستجو بر اساس شناسه کاربری، نام یا ایمیل"; +"search_default_placeholder" = "جست و جو"; +"search_files" = "فایل ها"; +"search_people" = "افراد"; +"search_messages" = "پیام ها"; + +// Search +"search_rooms" = "اتاق های گفت و گو"; + +// Groups tab +"group_invite_section" = "دعوت ها"; +"rooms_empty_view_information" = "اتاق ها برای هر چت گروهی، خصوصی یا عمومی عالی هستند. برای پیدا کردن اتاق‌های موجود یا ایجاد اتاق‌های جدید، روی + ضربه بزنید."; +"rooms_empty_view_title" = "اتاق های گفت و گو"; + +// Rooms tab +"room_directory_no_public_room" = "هیچ اتاق گفت و گو عمومی موجود نیست"; +"people_empty_view_information" = "با همه ایمن چت کنید. برای شروع اضافه کردن افراد، روی + ضربه بزنید."; +"people_empty_view_title" = "افراد"; +"people_no_conversation" = "هیچ گفت و گویی موجود نیست"; +"people_conversation_section" = "گفت و گو ها"; + +// People tab +"people_invites_section" = "دعوت ها"; +"room_recents_unknown_room_error_message" = "اتاق گفت و گو مورد نظر پیدا نشد. مطمئن شوید که این اتاق وجود دارد"; +"room_recents_join_room_prompt" = "شناسه اتاق گفت و گو یا نام مستعار اتاق گفت و گو را تایپ کنید"; +"room_recents_join_room_title" = "به یک اتاق گفت و گو بپیوندید"; +"room_recents_join_room" = "پیوستن به اتاق گفت و گو"; +"room_recents_create_empty_room" = "ایجاد اتاق گفت و گو"; +"room_recents_start_chat_with" = "شروع چت"; +"room_recents_suggested_rooms_section" = "تالارهای گفت و گوی پیشنهادی"; +"room_recents_invites_section" = "دعوت ها"; +"room_recents_server_notice_section" = "هشدارهای سیستم"; +"room_recents_no_conversation" = "چت رومی موجود نیست"; +"room_recents_conversations_section" = "تالارهای گفت و گو"; +"room_recents_people_section" = "افراد"; +"room_recents_favourites_section" = "علاقه مندی ها"; +"room_creation_make_public_prompt_title" = "چت عمومی شود؟"; +"room_creation_invite_another_user" = "شناسه کاربری، نام یا ایمیل"; +"room_creation_wait_for_creation" = "یک تالار گفت و گو از قبل در حال ایجاد است. لطفا صبر کنید."; +"room_creation_make_private" = "شخصی سازی"; +"room_creation_keep_private" = "خصوصی نگه دارید"; +"room_creation_make_public_prompt_msg" = "آیا مطمئن هستید که می خواهید این چت را عمومی کنید؟ هر کسی می تواند پیام های شما را بخواند و به چت بپیوندد."; +"room_creation_make_public" = "عمومی کردن"; +"room_creation_public_room" = "این چت عمومی است"; +"room_creation_private_room" = "این چت خصوصی است"; +"room_creation_privacy" = "حریم خصوصی"; +"room_creation_appearance_picture" = "عکس چت (اختیاری)"; +"room_creation_appearance_name" = "نام"; +"room_creation_account" = "حساب کاربری"; + +// Chat creation +"room_creation_title" = "گفت و گو جدید"; +"social_login_button_title_sign_up" = "ثبت نام با %@"; +"social_login_button_title_sign_in" = "ورود با %@"; +"social_login_button_title_continue" = "ادامه دادن با %@"; +"social_login_list_title_sign_up" = "یا"; +"social_login_list_title_sign_in" = "یا"; + +// Social login + +"social_login_list_title_continue" = "ادامه دادن با"; +"auth_softlogout_clear_data_sign_out" = "خروج"; +"auth_softlogout_clear_data_sign_out_msg" = "آیا مطمئن هستید که می خواهید تمام داده های ذخیره شده در این دستگاه را پاک کنید؟ برای دسترسی به داده ها و پیام های حساب خود دوباره وارد شوید."; +"auth_softlogout_clear_data_sign_out_title" = "آیا مطمئن هستید؟"; +"auth_softlogout_clear_data_button" = "تمام داده ها را پاک کنید"; +"auth_softlogout_clear_data_message_2" = "اگر استفاده از این دستگاه را تمام کرده‌اید یا می‌خواهید به حساب دیگری وارد شوید، آن را پاک کنید."; +"auth_softlogout_clear_data_message_1" = "هشدار: اطلاعات شخصی شما (از جمله کلیدهای رمزگذاری) همچنان در این دستگاه ذخیره شده است."; +"auth_softlogout_clear_data" = "پاک کردن اطلاعات شخصی"; +"auth_softlogout_recover_encryption_keys" = "برای بازیابی کلیدهای رمزگذاری ذخیره شده منحصراً در این دستگاه وارد سیستم شوید. برای خواندن همه پیام‌های امن خود در هر دستگاهی به آنها نیاز دارید."; +"auth_softlogout_sign_in" = "ورود"; +"auth_softlogout_signed_out" = "شما از سیستم خارج شده اید"; +"auth_add_email_and_phone_warning" = "ثبت نام همزمان با ایمیل و شماره تلفن هنوز پشتیبانی نمی شود تا زمانی که api وجود داشته باشد. فقط شماره تلفن در نظر گرفته خواهد شد. می توانید ایمیل خود را در تنظیمات به نمایه خود اضافه کنید."; +"auth_reset_password_success_message" = "رمز عبور شما بازنشانی شده است\nشما از تمام قسمت ها خارج شده اید و دیگر اعلان ها را دریافت نخواهید کرد. برای فعال کردن مجدد اعلان‌ها، مجدداً در هر دستگاه وارد سیستم شوید."; +"auth_reset_password_error_unauthorized" = "آدرس ایمیل تأیید نشد: مطمئن شوید که روی لینک موجود در ایمیل کلیک کرده اید"; +"auth_reset_password_next_step_button" = "من آدرس ایمیلم را تایید کرده ام"; +"auth_reset_password_email_validation_message" = "یک ایمیل به %@ ارسال شده است. پس از دنبال کردن پیوند موجود در آن، در قسمت پایین کلیک کنید."; +"auth_reset_password_missing_password" = "رمز جدید را وارد نمایید."; +"auth_reset_password_missing_email" = "آدرس ایمیل مرتبط با حساب کاربری شما باید وارد شود."; +"auth_reset_password_message" = "برای بازنشانی رمز عبور، آدرس ایمیل مرتبط با حساب کاربری خود را وارد کنید:"; +"auth_msisdn_validation_error" = "تأیید شماره تلفن امکان پذیر نیست."; +"auth_msisdn_validation_message" = "ما یک پیامک حاوی کد فعال سازی ارسال کرده ایم. لطفا این کد را در زیر وارد کنید."; +"auth_msisdn_validation_title" = "تأیید در حال انتظار"; +"auth_email_validation_message" = "لطفا برای ادامه ثبت نام ایمیل خود را بررسی کنید"; +"auth_email_not_found" = "خطا در ارسال ایمیل: آدرس ایمیل مورد نظر یافت نشد"; +"auth_forgot_password" = "فراموشی رمز؟"; +"auth_username_in_use" = "نام کاربری اشتباه است"; +"auth_password_dont_match" = "رمز ورود اشتباه است"; +"auth_phone_in_use" = "این شماره تلفن همراه در حال حاضر موجود است"; +"auth_email_in_use" = "این آدرس ایمیل در حال حاضر موجود است"; +"auth_missing_email_or_phone" = "فراموشی آدرس ایمیل یا شماره تلفن همراه"; +"auth_missing_phone" = "فراموشی تلفن همراه"; +"auth_add_phone_message_2" = "یک شماره تلفن تنظیم نمایید که بعداً برای افرادی که شما را می شناسند به صورت اختیاری قابل شناسایی باشد."; +"auth_add_email_message_2" = "یک ایمیل برای بازیابی حساب کاربری خود تنظیم کنید که بعداً برای افرادی که شما را می شناسند به صورت اختیاری قابل شناسایی باشد."; +"auth_missing_email" = "فراموشی آدرس ایمیل"; From 76a518c3931a6a43762e20362704595d9ff2513e Mon Sep 17 00:00:00 2001 From: opusforlife2 <53176348+opusforlife2@users.noreply.github.com> Date: Fri, 12 Nov 2021 15:48:35 +0000 Subject: [PATCH 041/122] Address PR review --- .github/ISSUE_TEMPLATE/bug.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/ISSUE_TEMPLATE/bug.yml b/.github/ISSUE_TEMPLATE/bug.yml index d95e16935..8ba0402c6 100644 --- a/.github/ISSUE_TEMPLATE/bug.yml +++ b/.github/ISSUE_TEMPLATE/bug.yml @@ -23,7 +23,7 @@ body: - type: textarea id: result attributes: - label: Intended result and actual result + label: Outcome placeholder: Tell us what went wrong value: | #### What did you expect? From fe85e9bd796afe37834bd6cae9c5ca48f33bfcd1 Mon Sep 17 00:00:00 2001 From: jelv Date: Fri, 12 Nov 2021 14:39:32 +0000 Subject: [PATCH 042/122] Translated using Weblate (Dutch) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ --- Riot/Assets/nl.lproj/Vector.strings | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index 46b7042b7..f08f1d901 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -267,7 +267,7 @@ "settings_labs" = "EXPERIMENTEEL"; "settings_devices" = "APPARATEN"; "settings_cryptography" = "CRYPTOGRAFIE"; -"settings_sign_out" = "Afmelden"; +"settings_sign_out" = "Uitloggen"; "settings_sign_out_confirmation" = "Weet u het zeker?"; "settings_sign_out_e2e_warn" = "U zult uw sleutels voor eind-tot-eindversleuteling kwijtraken. Dat betekent dat u op dit apparaat geen oude berichten in versleutelde gesprekken meer zult kunnen lezen."; "settings_profile_picture" = "Profielfoto"; @@ -667,13 +667,13 @@ "key_backup_setup_banner_subtitle" = "Begin sleutelback-up te gebruiken"; "key_backup_recover_banner_title" = "Verlies nooit uw versleutelde berichten"; "sign_out_existing_key_backup_alert_title" = "Weet u zeker dat u zich wilt afmelden?"; -"sign_out_existing_key_backup_alert_sign_out_action" = "Afmelden"; +"sign_out_existing_key_backup_alert_sign_out_action" = "Uitloggen"; "sign_out_non_existing_key_backup_alert_title" = "Als u zich nu afmeldt, zult u de toegang tot uw versleutelde berichten verliezen"; "sign_out_non_existing_key_backup_alert_setup_key_backup_action" = "Begin sleutelback-up te gebruiken"; "sign_out_non_existing_key_backup_alert_discard_key_backup_action" = "Ik wil mijn versleutelde berichten niet"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_title" = "U zult uw versleutelde berichten verliezen"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_message" = "U zult de toegang tot uw versleutelde berichten verliezen, tenzij u een back-up van uw sleutels maakt vooraleer u zich afmeldt."; -"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Afmelden"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "Uitloggen"; "sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "Back-up"; "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"; @@ -795,7 +795,7 @@ "auth_softlogout_clear_data_button" = "Alle gegevens wissen"; "auth_softlogout_clear_data_sign_out_title" = "Weet u het zeker?"; "auth_softlogout_clear_data_sign_out_msg" = "Weet u zeker dat u alle gegevens die op dit moment op dit apparaat worden opgeslagen wilt wissen? Meld u opnieuw aan om toegang te verkrijgen tot uw accountgegevens en berichten."; -"auth_softlogout_clear_data_sign_out" = "Afmelden"; +"auth_softlogout_clear_data_sign_out" = "Uitloggen"; "room_event_action_reaction_show_all" = "Alles tonen"; "room_event_action_reaction_show_less" = "Minder tonen"; "room_event_action_reaction_history" = "Reactiegeschiedenis"; From bdaea7e5cca89157a53e4e8127145d87d93dd10b Mon Sep 17 00:00:00 2001 From: Farhad Date: Sat, 13 Nov 2021 13:25:29 +0000 Subject: [PATCH 043/122] Translated using Weblate (Persian) Currently translated at 25.5% (340 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fa/ --- Riot/Assets/fa.lproj/Vector.strings | 230 +++++++++++++++++++++++++--- 1 file changed, 207 insertions(+), 23 deletions(-) diff --git a/Riot/Assets/fa.lproj/Vector.strings b/Riot/Assets/fa.lproj/Vector.strings index 3e279a22e..ff078be25 100644 --- a/Riot/Assets/fa.lproj/Vector.strings +++ b/Riot/Assets/fa.lproj/Vector.strings @@ -95,11 +95,11 @@ "done" = "انجام شد"; "open" = "باز کردن"; "contacts_address_book_matrix_users_toggle" = "فقط کاربران ماتریس"; -"directory_search_results_more_than" = ">%tu نتیجه یافت شد برای %@"; -"directory_search_results" = "%tu نتیجه یافت شد برای %@"; +"directory_search_results_more_than" = ">%tu نتیجه برای %@ یافت شد"; +"directory_search_results" = "%tu نتیجه برای %@ یافت شد"; "search_in_progress" = "در حال جست وجو"; "search_no_result" = "نتیچه ای یافت نشد"; -"search_people_placeholder" = "جستجو بر اساس شناسه کاربری، نام یا ایمیل"; +"search_people_placeholder" = "جستجو بر اساس شناسه کاربری، نام یا آدرس ایمیل"; "search_default_placeholder" = "جست و جو"; "search_files" = "فایل ها"; "search_people" = "افراد"; @@ -110,34 +110,34 @@ // Groups tab "group_invite_section" = "دعوت ها"; -"rooms_empty_view_information" = "اتاق ها برای هر چت گروهی، خصوصی یا عمومی عالی هستند. برای پیدا کردن اتاق‌های موجود یا ایجاد اتاق‌های جدید، روی + ضربه بزنید."; +"rooms_empty_view_information" = "اتاق ها برای هر چت گروهی، خصوصی یا عمومی عالی هستند. برای پیدا کردن اتاق‌های موجود یا ایجاد اتاق‌های جدید، روی علامت + ضربه بزنید."; "rooms_empty_view_title" = "اتاق های گفت و گو"; // Rooms tab "room_directory_no_public_room" = "هیچ اتاق گفت و گو عمومی موجود نیست"; -"people_empty_view_information" = "با همه ایمن چت کنید. برای شروع اضافه کردن افراد، روی + ضربه بزنید."; +"people_empty_view_information" = "ایمن چت کنید. برای اضافه کردن افراد، روی علامت + ضربه بزنید."; "people_empty_view_title" = "افراد"; "people_no_conversation" = "هیچ گفت و گویی موجود نیست"; "people_conversation_section" = "گفت و گو ها"; // People tab "people_invites_section" = "دعوت ها"; -"room_recents_unknown_room_error_message" = "اتاق گفت و گو مورد نظر پیدا نشد. مطمئن شوید که این اتاق وجود دارد"; -"room_recents_join_room_prompt" = "شناسه اتاق گفت و گو یا نام مستعار اتاق گفت و گو را تایپ کنید"; +"room_recents_unknown_room_error_message" = "اتاق گفت و گو مورد نظر یافت نشد. مطمئن شوید که این اتاق وجود دارد"; +"room_recents_join_room_prompt" = "شناسه اتاق گفت و گو یا نام مستعار آن را تایپ کنید"; "room_recents_join_room_title" = "به یک اتاق گفت و گو بپیوندید"; "room_recents_join_room" = "پیوستن به اتاق گفت و گو"; "room_recents_create_empty_room" = "ایجاد اتاق گفت و گو"; "room_recents_start_chat_with" = "شروع چت"; -"room_recents_suggested_rooms_section" = "تالارهای گفت و گوی پیشنهادی"; +"room_recents_suggested_rooms_section" = "اتاق های گفت و گوی پیشنهادی"; "room_recents_invites_section" = "دعوت ها"; "room_recents_server_notice_section" = "هشدارهای سیستم"; -"room_recents_no_conversation" = "چت رومی موجود نیست"; -"room_recents_conversations_section" = "تالارهای گفت و گو"; +"room_recents_no_conversation" = "اتاق گفت و گو موجود نیست"; +"room_recents_conversations_section" = "اتاق های گفت و گو(چت)"; "room_recents_people_section" = "افراد"; "room_recents_favourites_section" = "علاقه مندی ها"; "room_creation_make_public_prompt_title" = "چت عمومی شود؟"; -"room_creation_invite_another_user" = "شناسه کاربری، نام یا ایمیل"; -"room_creation_wait_for_creation" = "یک تالار گفت و گو از قبل در حال ایجاد است. لطفا صبر کنید."; +"room_creation_invite_another_user" = "شناسه کاربری، نام یاآدرس ایمیل"; +"room_creation_wait_for_creation" = "یک اتاق گفت و گو از قبل در حال ایجاد است. لطفا صبر کنید."; "room_creation_make_private" = "شخصی سازی"; "room_creation_keep_private" = "خصوصی نگه دارید"; "room_creation_make_public_prompt_msg" = "آیا مطمئن هستید که می خواهید این چت را عمومی کنید؟ هر کسی می تواند پیام های شما را بخواند و به چت بپیوندد."; @@ -145,12 +145,12 @@ "room_creation_public_room" = "این چت عمومی است"; "room_creation_private_room" = "این چت خصوصی است"; "room_creation_privacy" = "حریم خصوصی"; -"room_creation_appearance_picture" = "عکس چت (اختیاری)"; +"room_creation_appearance_picture" = "تصویر چت (اختیاری)"; "room_creation_appearance_name" = "نام"; "room_creation_account" = "حساب کاربری"; // Chat creation -"room_creation_title" = "گفت و گو جدید"; +"room_creation_title" = "چت جدید"; "social_login_button_title_sign_up" = "ثبت نام با %@"; "social_login_button_title_sign_in" = "ورود با %@"; "social_login_button_title_continue" = "ادامه دادن با %@"; @@ -165,16 +165,16 @@ "auth_softlogout_clear_data_sign_out_title" = "آیا مطمئن هستید؟"; "auth_softlogout_clear_data_button" = "تمام داده ها را پاک کنید"; "auth_softlogout_clear_data_message_2" = "اگر استفاده از این دستگاه را تمام کرده‌اید یا می‌خواهید به حساب دیگری وارد شوید، آن را پاک کنید."; -"auth_softlogout_clear_data_message_1" = "هشدار: اطلاعات شخصی شما (از جمله کلیدهای رمزگذاری) همچنان در این دستگاه ذخیره شده است."; +"auth_softlogout_clear_data_message_1" = "هشدار: اطلاعات شخصی شما (از جمله کلیدهای رمزگذاری) همچنان در این دستگاه ذخیره است."; "auth_softlogout_clear_data" = "پاک کردن اطلاعات شخصی"; "auth_softlogout_recover_encryption_keys" = "برای بازیابی کلیدهای رمزگذاری ذخیره شده منحصراً در این دستگاه وارد سیستم شوید. برای خواندن همه پیام‌های امن خود در هر دستگاهی به آنها نیاز دارید."; "auth_softlogout_sign_in" = "ورود"; "auth_softlogout_signed_out" = "شما از سیستم خارج شده اید"; -"auth_add_email_and_phone_warning" = "ثبت نام همزمان با ایمیل و شماره تلفن هنوز پشتیبانی نمی شود تا زمانی که api وجود داشته باشد. فقط شماره تلفن در نظر گرفته خواهد شد. می توانید ایمیل خود را در تنظیمات به نمایه خود اضافه کنید."; -"auth_reset_password_success_message" = "رمز عبور شما بازنشانی شده است\nشما از تمام قسمت ها خارج شده اید و دیگر اعلان ها را دریافت نخواهید کرد. برای فعال کردن مجدد اعلان‌ها، مجدداً در هر دستگاه وارد سیستم شوید."; +"auth_add_email_and_phone_warning" = "تا زمانی که api وجود داشته باشد ثبت نام همزمان با آدرس ایمیل و شماره تلفن همراه پشتیبانی نمی شود. فقط شماره تلفن همراه شما در نظر گرفته خواهد شد. می توانید ایمیل خود را در تنظیمات به نمایه خود اضافه کنید."; +"auth_reset_password_success_message" = "رمز عبور شما بازنشانی شده است\n\nشما از تمام قسمت ها خارج شده اید و دیگر اعلان ها را دریافت نخواهید کرد. برای فعال کردن دوباره اعلان‌ها، مجدداً در هر دستگاه وارد سیستم شوید."; "auth_reset_password_error_unauthorized" = "آدرس ایمیل تأیید نشد: مطمئن شوید که روی لینک موجود در ایمیل کلیک کرده اید"; "auth_reset_password_next_step_button" = "من آدرس ایمیلم را تایید کرده ام"; -"auth_reset_password_email_validation_message" = "یک ایمیل به %@ ارسال شده است. پس از دنبال کردن پیوند موجود در آن، در قسمت پایین کلیک کنید."; +"auth_reset_password_email_validation_message" = "یک ایمیل به %@ ارسال شده است. پس از دنبال کردن لینک موجود در آن، در قسمت پایین کلیک کنید."; "auth_reset_password_missing_password" = "رمز جدید را وارد نمایید."; "auth_reset_password_missing_email" = "آدرس ایمیل مرتبط با حساب کاربری شما باید وارد شود."; "auth_reset_password_message" = "برای بازنشانی رمز عبور، آدرس ایمیل مرتبط با حساب کاربری خود را وارد کنید:"; @@ -184,12 +184,196 @@ "auth_email_validation_message" = "لطفا برای ادامه ثبت نام ایمیل خود را بررسی کنید"; "auth_email_not_found" = "خطا در ارسال ایمیل: آدرس ایمیل مورد نظر یافت نشد"; "auth_forgot_password" = "فراموشی رمز؟"; -"auth_username_in_use" = "نام کاربری اشتباه است"; -"auth_password_dont_match" = "رمز ورود اشتباه است"; +"auth_username_in_use" = "این نام کاربری در حال حاضر موجود است"; +"auth_password_dont_match" = "رمز ورود همخوانی است"; "auth_phone_in_use" = "این شماره تلفن همراه در حال حاضر موجود است"; "auth_email_in_use" = "این آدرس ایمیل در حال حاضر موجود است"; -"auth_missing_email_or_phone" = "فراموشی آدرس ایمیل یا شماره تلفن همراه"; -"auth_missing_phone" = "فراموشی تلفن همراه"; +"auth_missing_email_or_phone" = "لطفا آدرس ایمیل یا شماره تلفن همراه خود را وارد کنید"; +"auth_missing_phone" = "لطفا شماره تلفن همراه خود را وارد کنید"; "auth_add_phone_message_2" = "یک شماره تلفن تنظیم نمایید که بعداً برای افرادی که شما را می شناسند به صورت اختیاری قابل شناسایی باشد."; "auth_add_email_message_2" = "یک ایمیل برای بازیابی حساب کاربری خود تنظیم کنید که بعداً برای افرادی که شما را می شناسند به صورت اختیاری قابل شناسایی باشد."; -"auth_missing_email" = "فراموشی آدرس ایمیل"; +"auth_missing_email" = "لطفا آدرس ایمیل خود را وارد کنید"; +"settings_other" = "سایر"; +"settings_phone_contacts" = "مخاطبین تلفن همراه"; +"settings_contacts" = "مخاطبین دستگاه"; +"settings_calls_settings" = "تماس ها"; +"settings_notifications" = "اعلان ها"; +"settings_links" = "لینک ها"; +"settings_sending_media" = "ارسال عکس ها و ویدیو ها"; +"settings_user_settings" = "تنظیمات کاربر"; +"settings_config_user_id" = "ورود به عنوان %@"; +"settings_clear_cache" = "پاک کردن حافظه پنهان"; +"settings_report_bug" = "گزارش اشکال"; +"settings_mark_all_as_read" = "همه پیام ها را به عنوان خوانده شده علامت گذاری کنید"; +"settings_config_no_build_info" = "بدون اطلاعات ساخت"; +"account_logout_all" = "خروج از تمامی حساب ها"; + +// Settings +"settings_title" = "تنظیمات"; +"room_preview_try_join_an_unknown_room_default" = "یک اتاق گفت و گو"; +"room_preview_try_join_an_unknown_room" = "شما در حال تلاش برای دسترسی به %@ هستید. آیا می خواهید در بحث شرکت کنید؟"; +"room_preview_unlinked_email_warning" = "این دعوت نامه به %@ ارسال شد که با این حساب مرتبط نیست. ممکن است بخواهید با حساب دیگری وارد شوید یا این ایمیل را به حساب خود اضافه کنید."; + +// Room Preview +"room_preview_invitation_format" = "شما توسط %@ برای پیوستن به این اتاق دعوت شده اید"; +"room_title_one_member" = "۱ عضو"; +"room_title_members" = "٪@ اعضا"; +"room_title_invite_members" = "دعوت از اعضا"; +"room_title_one_active_member" = "%@/%@ عضو فعال"; +"room_title_multiple_active_members" = "%@/%@ اعضای فعال"; + +// Room Title +"room_title_new_room" = "اتاق گفت و گو جدید"; +"unknown_devices_verify" = "تایید…"; +"unknown_devices_answer_anyway" = "به هر حال پاسخ دهید"; +"unknown_devices_call_anyway" = "به هر حال تماس بگیرید"; +"unknown_devices_send_anyway" = "به هر حال ارسال کنید"; +"room_multiple_typing_notification" = "٪@ و دیگران"; +"external_link_confirmation_message" = "پیوند %@ شما را به سایت دیگری انتقال می دهد: %@\n\nآیا مطمئن هستید که میخواهید ادامه دهید؟"; +"external_link_confirmation_title" = "این لینک را دوبار بررسی کنید"; +"media_type_accessibility_sticker" = "استیکر"; +"media_type_accessibility_file" = "فایل"; +"media_type_accessibility_location" = "موقعیت"; +"media_type_accessibility_video" = "ویدیو"; +"media_type_accessibility_audio" = "شنیداری"; +"media_type_accessibility_image" = "تصویر"; +"room_no_privileges_to_create_group_call" = "برای شروع تماس باید ادمین یا ناظر باشید."; +"room_join_group_call" = "پیوستن"; +"room_open_dialpad" = "صفحه شماره گیری"; +"room_place_voice_call" = "تماس صوتی"; +"room_accessibility_hangup" = "پایان دادن به تماس"; +"room_accessibility_video_call" = "تماس تصویری"; +"room_accessibility_call" = "تماس"; +"room_accessibility_upload" = "بارگذاری"; +"room_accessibility_search" = "جستجو"; +"room_message_edits_history_title" = "ویرایش های پیام"; +"room_resource_usage_limit_reached_message_2" = "برخی از کاربران نمی توانند وارد سیستم شوند."; +"room_resource_limit_exceeded_message_contact_3" = " برای ادامه استفاده از این سرویس"; +"room_resource_limit_exceeded_message_contact_2_link" = "با سرپرست سرویس خود تماس بگیرید"; +"room_resource_limit_exceeded_message_contact_1" = " لطفا "; +"room_predecessor_link" = "برای دیدن پیام‌های قدیمی‌تر به اینجاضربه بزنید."; +"room_predecessor_information" = "این اتاق ادامه گفتگوی دیگری است."; +"room_replacement_link" = "گفتگو در اینجا ادامه دارد."; +"room_replacement_information" = "این اتاق جایگزین شده است و دیگر فعال نیست."; +"room_action_reply" = "پاسخ"; +"room_action_send_file" = "ارسال فایل"; +"room_action_send_sticker" = "ارسال استیکر"; +"room_action_camera" = "گرفتن عکس یا فیلم"; +"room_action_send_photo_or_video" = "ارسال عکس یا فیلم"; +"room_event_failed_to_send" = "ارسال نشد"; +"room_event_action_reaction_show_less" = "نمایش کمتر"; +"room_event_action_reaction_show_all" = "نمایش همه"; +"room_event_action_edit" = "ویرایش"; +"room_event_action_reply" = "پاسخ"; +"room_event_action_cancel_send" = "لغو ارسال"; +"room_event_action_cancel_download" = "لغو دانلود"; +"room_event_action_view_encryption" = "اطلاعات رمزگذاری"; +"room_event_action_delete_confirmation_message" = "آیا مطمئن هستید که می خواهید این پیام ارسال نشده را حذف کنید؟"; +"room_event_action_delete_confirmation_title" = "حذف پیام های ارسال نشده"; +"room_event_action_delete" = "پاک کردن"; +"room_event_action_resend" = "ارسال مجدد"; +"room_event_action_save" = "ذخیره"; +"room_event_action_report_prompt_ignore_user" = "آیا می خواهید همه پیام های این کاربر را پنهان کنید؟"; +"room_event_action_ban_prompt_reason" = "دلیل ممنوعیت این کاربر"; +"room_event_action_kick_prompt_reason" = "دلیل حذف این کاربر"; +"room_event_action_report_prompt_reason" = "دلیل گزارش این محتوا"; +"room_event_action_report" = "گزارش محتوا"; +"room_event_action_forward" = "فوروارد کردن"; +"room_event_action_share" = "اشتراک گذاری"; +"room_event_action_more" = "بیشتر"; +"room_event_action_redact" = "حذف"; +"room_event_action_quote" = "نقل قول"; +"room_event_action_copy" = "کپی کردن"; +"room_delete_unsent_messages" = "حذف پیام های ارسال نشده"; +"room_resend_unsent_messages" = "ارسال مجدد پیام های ارسال نشده"; +"room_prompt_cancel" = "کنسل کردن همه"; +"room_prompt_resend" = "ارسال مجدد همه"; +"room_conference_call_no_power" = "برای مدیریت تماس کنفرانسی در این اتاق به مجوز نیاز دارید"; +"room_ongoing_conference_call_close" = "بستن"; +"room_ongoing_conference_call" = "به عنوان %@ یا %@ به تماس کنفرانسی بپیوندید."; +"room_unsent_messages_cancel_message" = "آیا مطمئن هستید که می خواهید همه پیام های ارسال نشده در این اتاق را حذف کنید؟"; +"room_unsent_messages_cancel_title" = "حذف پیام های ارسال نشده"; +"room_unsent_messages_notification" = "پیام ها ارسال نشدند."; +"room_offline_notification" = "اتصال به سرور قطع شده است."; +"room_message_reply_to_short_placeholder" = "ارسال پاسخ…"; +"room_message_short_placeholder" = "ارسال پیام…"; +"encrypted_room_message_reply_to_placeholder" = "ارسال پاسخ رمزگذاری شده…"; +"encrypted_room_message_placeholder" = "ارسال پیام رمزگذاری شده…"; +"room_do_not_have_permission_to_post" = "شما اجازه ندارید در این اتاق پست ارسال کنید"; +"room_message_replying_to" = "در حال پاسخ دادن به %@"; +"room_message_editing" = "ویرایش"; +"room_message_unable_open_link_error_message" = "لینک باز نشد."; +"room_message_reply_to_placeholder" = "ارسال پاسخ (بدون رمز)…"; +"room_message_placeholder" = "ارسال پیام (بدون رمز)…"; +"room_many_users_are_typing" = "%@, %@ و دیگران در حال تایپ کردن…"; +"room_two_users_are_typing" = "%@ & %@ در حال تایپ کردن…"; +"room_one_user_is_typing" = "%@ در حال تایپ کردن…"; +"room_new_messages_notification" = "%d پیام های جدید"; +"room_new_message_notification" = "%d پیام جدید"; +"room_accessiblity_scroll_to_bottom" = "به پایین اسکرول کنید"; +"room_jump_to_first_unread" = "گریز به پیام های خوانده نشده"; +"room_participants_security_loading" = "درحال بارگذاری…"; +"room_participants_action_security_status_loading" = "درحال بارگذاری…"; + +// Chat +"room_slide_to_end_group_call" = "برای پایان دادن به تماس صفحه را بکشید"; +"room_member_power_level_short_admin" = "ادمین"; +"room_participants_security_information_room_encrypted_for_dm" = "پیام‌های موجود در این اتاق رمزگذاری شده‌اند.\n\nپیام‌های شما با قفل محافظت می‌شوند و فقط شما و گیرنده کلیدهای باز کردن قفل آن‌ها را دارید."; +"room_participants_security_information_room_encrypted" = "پیام‌های موجود در این اتاق رمزگذاری شده‌اند.\n\nپیام‌های شما با قفل محافظت می‌شوند و فقط شما و گیرنده کلیدهای باز کردن قفل آن‌ها را دارید."; +"room_participants_security_information_room_not_encrypted_for_dm" = "پیام‌های اینجا رمزگذاری‌شده نیستند."; +"room_participants_security_information_room_not_encrypted" = "پیام‌های موجود در این اتاق رمزگذاری‌شده نیستند."; +"room_participants_action_security_status_warning" = "هشدار"; +"room_participants_action_security_status_complete_security" = "امنیت کامل"; +"room_participants_action_security_status_verified" = "تایید شد"; +"room_participants_action_security_status_verify" = "تایید"; +"room_participants_action_mention" = "اشاره"; +"room_participants_action_start_video_call" = "شروع تماس تصویری"; +"room_participants_action_start_voice_call" = "شروع تماس صوتی"; +"room_participants_action_start_new_chat" = "شروع چت جدید"; +"room_participants_action_set_admin" = "ایجاد ادمین ( مدیر)"; +"room_participants_action_set_default_power_level" = "بازنشانی به کاربر عادی"; +"room_participants_action_ignore" = "عدم نمایش پیام های این کاربر"; +"room_participants_action_unignore" = "نمایش همه پیام های این کاربر"; +"room_participants_action_unban" = "لغو ممنوعیت"; +"room_participants_action_ban" = "ممنوعیت ورود به این اتاق"; +"room_participants_action_remove" = "از این اتاق حذف کنید"; +"room_participants_action_leave" = "این اتاق را ترک کنید"; +"room_participants_action_invite" = "دعوت"; +"room_participants_action_section_security" = "امنیت"; +"room_participants_action_section_other" = "گزینه ها"; +"room_participants_action_section_direct_chats" = "چت های مستقیم"; +"room_participants_action_section_admin_tools" = "ابزارهای مدیریت"; +"room_participants_ago" = "گذشته"; +"room_participants_now" = "اکنون"; +"room_participants_unknown" = "ناشناس"; +"room_participants_offline" = "آفلاین"; +"room_participants_online" = "آنلاین"; +"room_participants_invited_section" = "دعوت شده ها"; +"room_participants_invite_malformed_id" = "شناسه ناقص. باید یک آدرس ایمیل یا یک شناسه ماتریکس مانند '@localpart:domain' باشد"; +"room_participants_invite_malformed_id_title" = "خطای دعوت"; +"room_participants_invite_another_user" = "جستجو / دعوت با شناسه کاربری، نام یاآدرس ایمیل"; +"room_participants_filter_room_members_for_dm" = "فیلتر کردن اعضا"; +"room_participants_filter_room_members" = "اعضای اتاق را فیلتر کنید"; +"room_participants_invite_prompt_msg" = "آیا مطمئنید که می‌خواهید %@ را به این چت دعوت کنید؟"; +"room_participants_invite_prompt_title" = "تایید"; +"room_participants_remove_third_party_invite_prompt_msg" = "آیا مطمئنید که می خواهید این دعوت را لغو کنید؟"; +"room_participants_remove_prompt_msg" = "آیا مطمئن هستید که می خواهید %@ را از این چت حذف کنید؟"; +"room_participants_remove_prompt_title" = "تایید"; +"room_participants_leave_prompt_msg_for_dm" = "آیا مطمئن هستید که می خواهید اتاق را ترک کنید؟"; +"room_participants_leave_prompt_msg" = "آیا مطمئن هستید که می خواهید اتاق را ترک کنید؟"; +"room_participants_leave_prompt_title_for_dm" = "ترک کردن"; +"room_participants_leave_prompt_title" = "ترک کردن اتاق گفت و گو"; +"room_participants_multi_participants" = "%d شرکت کننده ها"; +"room_participants_one_participant" = "۱شرکت کننده"; +"room_participants_add_participant" = "افزودن شرکت کننده"; + +// Chat participants +"room_participants_title" = "شركت كنندگان"; +"find_your_contacts_footer" = "این گزینه را می توان در هر زمان از قسمت تنظیمات غیرفعال کرد."; +"find_your_contacts_button_title" = "مخاطبین خود را پیدا کنید"; +"find_your_contacts_message" = "به %@ اجازه دهید مخاطبین شما را نشان دهد تا بتوانید سریعاً با کسانی که می شناسید چت کنید."; +"find_your_contacts_title" = "با فهرست کردن مخاطبین خود شروع کنید"; +"contacts_address_book_permission_denied_alert_message" = "برای فعال کردن مخاطبین، به تنظیمات دستگاه خود بروید."; +"contacts_address_book_permission_denied_alert_title" = "لیست مخاطبین غیرفعال شد"; +"directory_cell_description" = "%tu اتاق ها"; +"auth_add_email_phone_message_2" = "یک ایمیل برای بازیابی حساب کاربری خود تنظیم کنید. از این ایمیل یا شماره تلفن استفاده کنید تا به صورت اختیاری توسط افرادی که شما را می شناسند قابل شناسایی باشید."; From 8bae72c5eb1138e82d210b6aa668166683548406 Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Tue, 16 Nov 2021 10:10:36 +0000 Subject: [PATCH 044/122] Update issue triage automation for P1 and need info Move P1 issues to app and crypto team boards. Move unlabelled issues without X-Needs-Info out of column on Triage board. --- .github/workflows/triage-move-unlabelled.yml | 35 +++++++++++++ .github/workflows/triage-priority-bugs.yml | 55 ++++++++++++++++++++ changelog.d/5153.misc | 1 + 3 files changed, 91 insertions(+) create mode 100644 .github/workflows/triage-move-unlabelled.yml create mode 100644 .github/workflows/triage-priority-bugs.yml create mode 100644 changelog.d/5153.misc diff --git a/.github/workflows/triage-move-unlabelled.yml b/.github/workflows/triage-move-unlabelled.yml new file mode 100644 index 000000000..94bd049b9 --- /dev/null +++ b/.github/workflows/triage-move-unlabelled.yml @@ -0,0 +1,35 @@ +name: Move unlabelled from needs info columns to triaged + +on: + issues: + types: [unlabeled] + +jobs: + Move_Unabeled_Issue_On_Project_Board: + name: Move no longer X-Needs-Info issues to Triaged + runs-on: ubuntu-latest + if: > + ${{ + !contains(github.event.issue.labels.*.name, 'X-Needs-Info') }} + env: + BOARD_NAME: "Issue triage" + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + ISSUE: ${{ github.event.issue.number }} + steps: + - name: Check if issue is already in "${{ env.BOARD_NAME }}" + run: | + if curl -i -H 'Content-Type: application/json' -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -X POST -d '{"query": "query($issue: Int!, $owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { issue(number: $issue) { projectCards { nodes { project { name } } } } } } ", "variables" : "{ \"issue\": '${ISSUE}', \"owner\": \"'${OWNER}'\", \"repo\": \"'${REPO}'\" }" }' https://api.github.com/graphql | grep "\b$BOARD_NAME\b"; then + echo "Issue is already in Project '$BOARD_NAME', proceeding"; + echo "ALREADY_IN_BOARD=true" >> $GITHUB_ENV + else + echo "Issue is not in project '$BOARD_NAME', cancelling this workflow" + echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV + fi + - name: Move issue + uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 + if: ${{ env.ALREADY_IN_BOARD == 'true' }} + with: + project: Issue triage + column: Triaged + repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/.github/workflows/triage-priority-bugs.yml b/.github/workflows/triage-priority-bugs.yml new file mode 100644 index 000000000..c2147d2f6 --- /dev/null +++ b/.github/workflows/triage-priority-bugs.yml @@ -0,0 +1,55 @@ +name: Move P1 issues into the P1 column for the App Team and Crypto team + +on: + issues: + types: [labeled, unlabeled] + +jobs: + p1_issues_to_team_workboard: + runs-on: ubuntu-latest + if: > + (!contains(github.event.issue.labels.*.name, 'A-E2EE') && + !contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') && + !contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') && + !contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') && + !contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') && + !contains(github.event.issue.labels.*.name, 'A-Spaces') && + !contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') && + !contains(github.event.issue.labels.*.name, 'A-Subspaces')) && + (contains(github.event.issue.labels.*.name, 'T-Defect') && + contains(github.event.issue.labels.*.name, 'S-Critical') && + (contains(github.event.issue.labels.*.name, 'O-Frequent') || + contains(github.event.issue.labels.*.name, 'O-Occasional')) || + contains(github.event.issue.labels.*.name, 'S-Major') && + contains(github.event.issue.labels.*.name, 'O-Frequent') || + contains(github.event.issue.labels.*.name, 'A11y') && + contains(github.event.issue.labels.*.name, 'O-Frequent')) + steps: + - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 + with: + project: iOS App Team + column: P1 + repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} + + P1_issues_to_crypto_team_workboard: + runs-on: ubuntu-latest + if: > + (contains(github.event.issue.labels.*.name, 'A-E2EE') || + contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') || + contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') || + contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') || + contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) && + (contains(github.event.issue.labels.*.name, 'T-Defect') && + contains(github.event.issue.labels.*.name, 'S-Critical') && + (contains(github.event.issue.labels.*.name, 'O-Frequent') || + contains(github.event.issue.labels.*.name, 'O-Occasional')) || + contains(github.event.issue.labels.*.name, 'S-Major') && + contains(github.event.issue.labels.*.name, 'O-Frequent') || + contains(github.event.issue.labels.*.name, 'A11y') && + contains(github.event.issue.labels.*.name, 'O-Frequent')) + steps: + - uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488 + with: + project: Crypto Team + column: Ready + repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }} diff --git a/changelog.d/5153.misc b/changelog.d/5153.misc new file mode 100644 index 000000000..5cfb4f32e --- /dev/null +++ b/changelog.d/5153.misc @@ -0,0 +1 @@ +Update automation for issue triage From 577fee75dd5323ab7792ca2639edf0a31c590cb1 Mon Sep 17 00:00:00 2001 From: Stefan Ceriu Date: Tue, 16 Nov 2021 13:41:41 +0200 Subject: [PATCH 045/122] Fix build after changing aggregation method limits from UInt to Int in the SDK. --- Riot/Modules/Room/EditHistory/EditHistoryViewModel.swift | 2 +- .../Modules/Room/ReactionHistory/ReactionHistoryViewModel.swift | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Riot/Modules/Room/EditHistory/EditHistoryViewModel.swift b/Riot/Modules/Room/EditHistory/EditHistoryViewModel.swift index 2f9b4f0d0..ea27098e1 100644 --- a/Riot/Modules/Room/EditHistory/EditHistoryViewModel.swift +++ b/Riot/Modules/Room/EditHistory/EditHistoryViewModel.swift @@ -105,7 +105,7 @@ final class EditHistoryViewModel: EditHistoryViewModelType { self.update(viewState: .loading) - self.operation = self.aggregations.replaceEvents(forEvent: self.event.eventId, isEncrypted: self.event.isEncrypted, inRoom: self.roomId, from: self.nextBatch, limit: Pagination.count, success: { [weak self] (response) in + self.operation = self.aggregations.replaceEvents(forEvent: self.event.eventId, isEncrypted: self.event.isEncrypted, inRoom: self.roomId, from: self.nextBatch, limit: Int(Pagination.count), success: { [weak self] (response) in guard let sself = self else { return } diff --git a/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModel.swift b/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModel.swift index b98ec19c5..69042ee5f 100644 --- a/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModel.swift +++ b/Riot/Modules/Room/ReactionHistory/ReactionHistoryViewModel.swift @@ -108,7 +108,7 @@ final class ReactionHistoryViewModel: ReactionHistoryViewModelType { self.update(viewState: .loading) - self.operation = self.aggregations.reactionsEvents(forEvent: self.eventId, inRoom: self.roomId, from: self.nextBatch, limit: Pagination.count, success: { [weak self] (response) in + self.operation = self.aggregations.reactionsEvents(forEvent: self.eventId, inRoom: self.roomId, from: self.nextBatch, limit: Int(Pagination.count), success: { [weak self] (response) in guard let self = self else { return } From 81f1a946f65bae11169b6d34db07ff63aa1bca62 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 12:00:20 +0000 Subject: [PATCH 046/122] Ignore badge updates for virtual rooms. --- Config/BuildSettings.swift | 2 ++ RiotNSE/NotificationService.swift | 49 ++++++++++++++++++++++++++----- 2 files changed, 43 insertions(+), 8 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 2d080c6d2..4c7927f5e 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -154,6 +154,8 @@ final class BuildSettings: NSObject { } static let stunServerFallbackUrlString: String? = "stun:turn.matrix.org" + // For use in conjunction with virtual rooms. Events from virtual rooms should not be reflected in badge count for unread messages. + static let ignoreBadgeUpdatesForVirtualRooms = true // MARK: - Public rooms Directory #warning("Unused build setting: should this be implemented in ShowDirectory?") diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 0b2ff4758..76192fee7 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -53,6 +53,12 @@ class NotificationService: UNNotificationServiceExtension { private lazy var configuration: Configurable = { return CommonConfiguration() }() + private lazy var mxRestClient: MXRestClient? = { + guard let userAccount = userAccount else { + return nil + } + return MXRestClient(credentials: userAccount.mxCredentials, unrecognizedCertificateHandler: nil) + }() private static var isLoggerInitialized: Bool = false private lazy var pushGatewayRestClient: MXPushGatewayRestClient = { let url = URL(string: BuildSettings.serverConfigSygnalAPIUrlString)! @@ -222,7 +228,7 @@ class NotificationService: UNNotificationServiceExtension { return } - self.notificationContent(forEvent: event, forAccount: userAccount) { (notificationContent) in + self.notificationContent(forEvent: event, forAccount: userAccount) { (notificationContent, ignoreBadgeUpdate) in var isUnwantedNotification = false // Modify the notification content here... @@ -240,6 +246,10 @@ class NotificationService: UNNotificationServiceExtension { isUnwantedNotification = true } + if ignoreBadgeUpdate { + content.badge = nil + } + if self.ongoingVoIPPushRequests[event.eventId] == true { // modify the best attempt content, to be able to use in the future self.bestAttemptContents[event.eventId] = content @@ -279,10 +289,10 @@ class NotificationService: UNNotificationServiceExtension { MXLog.debug("--------------------------------------------------------------------------------") } - private func notificationContent(forEvent event: MXEvent, forAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?) -> Void) { + private func notificationContent(forEvent event: MXEvent, forAccount account: MXKAccount, onComplete: @escaping (UNNotificationContent?, Bool) -> Void) { guard let content = event.content, content.count > 0 else { MXLog.debug("[NotificationService] notificationContentForEvent: empty event content") - onComplete(nil) + onComplete(nil, false) return } @@ -298,7 +308,7 @@ class NotificationService: UNNotificationServiceExtension { var notificationTitle: String? var notificationBody: String? var additionalUserInfo: [AnyHashable: Any]? - + var ignoreBadgeUpdate = false var threadIdentifier: String? = roomId let currentUserId = account.mxCredentials.userId let roomDisplayName = roomSummary?.displayname @@ -322,6 +332,10 @@ class NotificationService: UNNotificationServiceExtension { if let callInviteContent = MXCallInviteEventContent(fromJSON: event.content), callInviteContent.lifetime > event.age, (callInviteContent.lifetime - event.age) > UInt(NSE.Constants.timeNeededToSendVoIPPushes * MSEC_PER_SEC) { + if BuildSettings.ignoreBadgeUpdatesForVirtualRooms { + self.sendReadReceipt(forEvent: event) + ignoreBadgeUpdate = true + } self.sendVoipPush(forEvent: event) } else { MXLog.debug("[NotificationService] notificationContent: Do not attempt to send a VoIP push, there is not enough time to process it.") @@ -351,7 +365,7 @@ class NotificationService: UNNotificationServiceExtension { #warning("In practice, this only hides the notification's content. An empty notification may be less useful in this instance?") // Ignore this notif. MXLog.debug("[NotificationService] notificationContentForEvent: Ignore non highlighted notif in mentions only room") - onComplete(nil) + onComplete(nil, false) return } } @@ -483,7 +497,7 @@ class NotificationService: UNNotificationServiceExtension { guard notificationBody != nil else { MXLog.debug("[NotificationService] notificationContentForEvent: notificationBody is nil") - onComplete(nil) + onComplete(nil, false) return } @@ -496,10 +510,10 @@ class NotificationService: UNNotificationServiceExtension { additionalInfo: additionalUserInfo) MXLog.debug("[NotificationService] notificationContentForEvent: Calling onComplete.") - onComplete(notificationContent) + onComplete(notificationContent, ignoreBadgeUpdate) case .failure(let error): MXLog.debug("[NotificationService] notificationContentForEvent: error: \(error)") - onComplete(nil) + onComplete(nil, false) } }) } @@ -710,4 +724,23 @@ class NotificationService: UNNotificationServiceExtension { } } + private func sendReadReceipt(forEvent event: MXEvent) { + guard let mxRestClient = mxRestClient else { + MXLog.error("[NotificationService] sendVoipReadReceipt: Missing mxRestClient for read receipt request.") + return + } + guard let eventId = event.eventId, + let roomId = event.roomId else { + MXLog.error("[NotificationService] sendVoipReadReceipt: Event information missing for read receipt request.") + return + } + + mxRestClient.sendReadReceipt(toRoom: roomId, forEvent: eventId) { response in + if response.isSuccess { + MXLog.debug("[NotificationService] sendVoipReadReceipt: Read receipt send successfully.") + } else if let error = response.error { + MXLog.error("[NotificationService] sendVoipReadReceipt: Read receipt send failed with error \(error).") + } + } + } } From d49b65b22cf5b754f8c78678f8f57679f13485fc Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 12:19:35 +0000 Subject: [PATCH 047/122] changelog --- changelog.d/5155.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5155.bugfix diff --git a/changelog.d/5155.bugfix b/changelog.d/5155.bugfix new file mode 100644 index 000000000..0d821ee92 --- /dev/null +++ b/changelog.d/5155.bugfix @@ -0,0 +1 @@ +Add BuildSetting to ignore badge updates from virtual rooms. From 3bce1c6df65d71600459f597b826cc369ecf791a Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 12:24:21 +0000 Subject: [PATCH 048/122] Fix logging function name --- RiotNSE/NotificationService.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 76192fee7..6c10eb6c8 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -726,20 +726,20 @@ class NotificationService: UNNotificationServiceExtension { private func sendReadReceipt(forEvent event: MXEvent) { guard let mxRestClient = mxRestClient else { - MXLog.error("[NotificationService] sendVoipReadReceipt: Missing mxRestClient for read receipt request.") + MXLog.error("[NotificationService] sendReadReceipt: Missing mxRestClient for read receipt request.") return } guard let eventId = event.eventId, let roomId = event.roomId else { - MXLog.error("[NotificationService] sendVoipReadReceipt: Event information missing for read receipt request.") + MXLog.error("[NotificationService] sendReadReceipt: Event information missing for read receipt request.") return } mxRestClient.sendReadReceipt(toRoom: roomId, forEvent: eventId) { response in if response.isSuccess { - MXLog.debug("[NotificationService] sendVoipReadReceipt: Read receipt send successfully.") + MXLog.debug("[NotificationService] sendReadReceipt: Read receipt send successfully.") } else if let error = response.error { - MXLog.error("[NotificationService] sendVoipReadReceipt: Read receipt send failed with error \(error).") + MXLog.error("[NotificationService] sendReadReceipt: Read receipt send failed with error \(error).") } } } From 4e721897391f443c9b4d2b43dd142d8846a5d8b3 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 14:40:22 +0000 Subject: [PATCH 049/122] Remove build setting and get check virtual info --- RiotNSE/NotificationService.swift | 92 ++++++++++++++++++++++--------- 1 file changed, 67 insertions(+), 25 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 6c10eb6c8..b0d14f089 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -332,11 +332,25 @@ class NotificationService: UNNotificationServiceExtension { if let callInviteContent = MXCallInviteEventContent(fromJSON: event.content), callInviteContent.lifetime > event.age, (callInviteContent.lifetime - event.age) > UInt(NSE.Constants.timeNeededToSendVoIPPushes * MSEC_PER_SEC) { - if BuildSettings.ignoreBadgeUpdatesForVirtualRooms { - self.sendReadReceipt(forEvent: event) - ignoreBadgeUpdate = true + NotificationService.backgroundSyncService.roomAccountData(forRoomId: roomId) { response in + if let accountData = response.value, accountData.virtualRoomInfo.isVirtual { + self.sendReadReceipt(forEvent: event) + ignoreBadgeUpdate = true + } + self.sendVoipPush(forEvent: event) + self.validateNotificationContentAndComplete( + notificationTitle: notificationTitle, + notificationBody: notificationBody, + additionalUserInfo: additionalUserInfo, + ignoreBadgeUpdate: ignoreBadgeUpdate, + threadIdentifier: threadIdentifier, + currentUserId: currentUserId, + event: event, + pushRule: pushRule, + onComplete: onComplete + ) } - self.sendVoipPush(forEvent: event) + return } else { MXLog.debug("[NotificationService] notificationContent: Do not attempt to send a VoIP push, there is not enough time to process it.") } @@ -489,28 +503,18 @@ class NotificationService: UNNotificationServiceExtension { break } - if self.localAuthenticationService.isProtectionSet { - MXLog.debug("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set") - notificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: []) - notificationTitle = nil - } - guard notificationBody != nil else { - MXLog.debug("[NotificationService] notificationContentForEvent: notificationBody is nil") - onComplete(nil, false) - return - } - - let notificationContent = self.notificationContent(withTitle: notificationTitle, - body: notificationBody, - threadIdentifier: threadIdentifier, - userId: currentUserId, - event: event, - pushRule: pushRule, - additionalInfo: additionalUserInfo) - - MXLog.debug("[NotificationService] notificationContentForEvent: Calling onComplete.") - onComplete(notificationContent, ignoreBadgeUpdate) + self.validateNotificationContentAndComplete( + notificationTitle: notificationTitle, + notificationBody: notificationBody, + additionalUserInfo: additionalUserInfo, + ignoreBadgeUpdate: ignoreBadgeUpdate, + threadIdentifier: threadIdentifier, + currentUserId: currentUserId, + event: event, + pushRule: pushRule, + onComplete: onComplete + ) case .failure(let error): MXLog.debug("[NotificationService] notificationContentForEvent: error: \(error)") onComplete(nil, false) @@ -518,6 +522,44 @@ class NotificationService: UNNotificationServiceExtension { }) } + private func validateNotificationContentAndComplete( + notificationTitle: String?, + notificationBody: String?, + additionalUserInfo: [AnyHashable: Any]?, + ignoreBadgeUpdate: Bool, + threadIdentifier: String?, + currentUserId: String?, + event: MXEvent, + pushRule: MXPushRule?, + onComplete: @escaping (UNNotificationContent?, Bool) -> Void + ) { + + var validatedNotificationBody: String? = notificationBody + var validatedNotificationTitle: String? = notificationTitle + if self.localAuthenticationService.isProtectionSet { + MXLog.debug("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set") + validatedNotificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: []) + validatedNotificationTitle = nil + } + + guard notificationBody != nil else { + MXLog.debug("[NotificationService] notificationContentForEvent: notificationBody is nil") + onComplete(nil, false) + return + } + + let notificationContent = self.notificationContent(withTitle: validatedNotificationTitle, + body: validatedNotificationBody, + threadIdentifier: threadIdentifier, + userId: currentUserId, + event: event, + pushRule: pushRule, + additionalInfo: additionalUserInfo) + + MXLog.debug("[NotificationService] notificationContentForEvent: Calling onComplete.") + onComplete(notificationContent, ignoreBadgeUpdate) + } + /// Returns the default title for message notifications. /// - Parameters: /// - eventSenderName: The displayname of the sender. From 14c42865e5024141444109a815a4611e2338ecb0 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 14:55:07 +0000 Subject: [PATCH 050/122] Fix changelog description --- changelog.d/5155.bugfix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/changelog.d/5155.bugfix b/changelog.d/5155.bugfix index 0d821ee92..1e21bfc43 100644 --- a/changelog.d/5155.bugfix +++ b/changelog.d/5155.bugfix @@ -1 +1 @@ -Add BuildSetting to ignore badge updates from virtual rooms. +Ignore badge updates from virtual rooms. From 08b6b25e01723e5f29105e39efc6b5c61f8445b1 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 15:02:52 +0000 Subject: [PATCH 051/122] Remove buildsetting --- Config/BuildSettings.swift | 3 --- 1 file changed, 3 deletions(-) diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 4c7927f5e..44c32742c 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -154,9 +154,6 @@ final class BuildSettings: NSObject { } static let stunServerFallbackUrlString: String? = "stun:turn.matrix.org" - // For use in conjunction with virtual rooms. Events from virtual rooms should not be reflected in badge count for unread messages. - static let ignoreBadgeUpdatesForVirtualRooms = true - // MARK: - Public rooms Directory #warning("Unused build setting: should this be implemented in ShowDirectory?") static let publicRoomsAllowServerChange: Bool = true From c507166aa4096e00b635edff7137be2e5626f6d4 Mon Sep 17 00:00:00 2001 From: David Langley Date: Tue, 16 Nov 2021 16:16:04 +0000 Subject: [PATCH 052/122] Don't wait for accountData to start voip call. --- RiotNSE/NotificationService.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index b0d14f089..99a9bba12 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -337,7 +337,6 @@ class NotificationService: UNNotificationServiceExtension { self.sendReadReceipt(forEvent: event) ignoreBadgeUpdate = true } - self.sendVoipPush(forEvent: event) self.validateNotificationContentAndComplete( notificationTitle: notificationTitle, notificationBody: notificationBody, @@ -350,6 +349,7 @@ class NotificationService: UNNotificationServiceExtension { onComplete: onComplete ) } + self.sendVoipPush(forEvent: event) return } else { MXLog.debug("[NotificationService] notificationContent: Do not attempt to send a VoIP push, there is not enough time to process it.") @@ -537,13 +537,13 @@ class NotificationService: UNNotificationServiceExtension { var validatedNotificationBody: String? = notificationBody var validatedNotificationTitle: String? = notificationTitle if self.localAuthenticationService.isProtectionSet { - MXLog.debug("[NotificationService] notificationContentForEvent: Resetting title and body because app protection is set") + MXLog.debug("[NotificationService] validateNotificationContentAndComplete: Resetting title and body because app protection is set") validatedNotificationBody = NSString.localizedUserNotificationString(forKey: "MESSAGE_PROTECTED", arguments: []) validatedNotificationTitle = nil } - guard notificationBody != nil else { - MXLog.debug("[NotificationService] notificationContentForEvent: notificationBody is nil") + guard validatedNotificationBody != nil else { + MXLog.debug("[NotificationService] validateNotificationContentAndComplete: notificationBody is nil") onComplete(nil, false) return } @@ -556,7 +556,7 @@ class NotificationService: UNNotificationServiceExtension { pushRule: pushRule, additionalInfo: additionalUserInfo) - MXLog.debug("[NotificationService] notificationContentForEvent: Calling onComplete.") + MXLog.debug("[NotificationService] validateNotificationContentAndComplete: Calling onComplete.") onComplete(notificationContent, ignoreBadgeUpdate) } From f75dd542b9b1f89a193db6297826e967a433be78 Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Wed, 17 Nov 2021 08:48:29 +0000 Subject: [PATCH 053/122] Add automation to move labelled issues Move X-Needs-Info on the triage board to needs info column Design issues to Design team Spaces to Delight Voice messages to Voice message board Threads to threads board Fixes #5143 Covered by changelog entry 5153.misc --- .github/workflows/triage-move-labelled.yml | 124 +++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 .github/workflows/triage-move-labelled.yml diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml new file mode 100644 index 000000000..440fc42cd --- /dev/null +++ b/.github/workflows/triage-move-labelled.yml @@ -0,0 +1,124 @@ +name: Move labelled issues to correct boards and columns + +on: + issues: + types: [labeled] + +jobs: + move_needs_info_issues: + name: Move X-Needs-Info issues to Need info on triage board + runs-on: ubuntu-latest + steps: + - uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338 + with: + action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}" + project-url: "https://github.com/vector-im/element-android/projects/4" + column-name: "Need info" + label-name: "X-Needs-Info" + + add_priority_design_issues_to_project: + name: Move priority X-Needs-Design issues to Design project board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'X-Needs-Design') && + (contains(github.event.issue.labels.*.name, 'O-Frequent') || + contains(github.event.issue.labels.*.name, 'O-Occasional')) && + (contains(github.event.issue.labels.*.name, 'S-Critical') || + contains(github.event.issue.labels.*.name, 'S-Major') || + contains(github.event.issue.labels.*.name, 'S-Minor')) + steps: + - uses: octokit/graphql-action@v2.x + id: add_to_project + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:String!,$contentid:String!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc0sUA" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + + move_spaces_issues: + name: Move Spaces issues to Delight project board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'A-Spaces') || + contains(github.event.issue.labels.*.name, 'A-Space-Settings') || + contains(github.event.issue.labels.*.name, 'A-Subspaces') + steps: + - uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338 + with: + action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}" + project-url: "https://github.com/orgs/vector-im/projects/6" + column-name: "📥 Inbox" + label-name: "A-Spaces" + - uses: octokit/graphql-action@v2.x + id: add_to_delight2 + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:String!,$contentid:String!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc1HvQ" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + + move_voice-message_issues: + name: Move A-Voice Messages to Voice message board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'A-Voice Messages') + steps: + - uses: octokit/graphql-action@v2.x + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:String!,$contentid:String!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc2KCw" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} + + move_threads_issues: + name: Move A-Threads to Thread board + runs-on: ubuntu-latest + if: > + contains(github.event.issue.labels.*.name, 'A-Threads') + steps: + - uses: octokit/graphql-action@v2.x + with: + headers: '{"GraphQL-Features": "projects_next_graphql"}' + query: | + mutation add_to_project($projectid:String!,$contentid:String!) { + addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) { + projectNextItem { + id + } + } + } + projectid: ${{ env.PROJECT_ID }} + contentid: ${{ github.event.issue.node_id }} + env: + PROJECT_ID: "PN_kwDOAM0swc0rRA" + GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }} From 648c4e2645a852697a4fc6f4db61bbee8cfd82d7 Mon Sep 17 00:00:00 2001 From: Doug Date: Wed, 17 Nov 2021 18:00:36 +0000 Subject: [PATCH 054/122] Prepare for new sprint --- Config/AppVersion.xcconfig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Config/AppVersion.xcconfig b/Config/AppVersion.xcconfig index 4b18e27d3..d414d01ef 100644 --- a/Config/AppVersion.xcconfig +++ b/Config/AppVersion.xcconfig @@ -15,5 +15,5 @@ // // Version -MARKETING_VERSION = 1.6.8 -CURRENT_PROJECT_VERSION = 1.6.8 +MARKETING_VERSION = 1.6.9 +CURRENT_PROJECT_VERSION = 1.6.9 From ad00629a9e7e5680b7b81eca843a4f449ed32273 Mon Sep 17 00:00:00 2001 From: Sergey Date: Wed, 17 Nov 2021 13:26:29 +0000 Subject: [PATCH 055/122] Translated using Weblate (Russian) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/ru/ --- Riot/Assets/ru.lproj/Vector.strings | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Assets/ru.lproj/Vector.strings b/Riot/Assets/ru.lproj/Vector.strings index 98e41f479..d91945d9f 100644 --- a/Riot/Assets/ru.lproj/Vector.strings +++ b/Riot/Assets/ru.lproj/Vector.strings @@ -898,7 +898,7 @@ "room_participants_action_security_status_complete_security" = "Завершите настройку безопасности"; "room_participants_action_security_status_loading" = "Загрузка…"; "room_participants_security_information_room_not_encrypted" = "Сообщения в этой комнате не шифруются сквозным шифрованием."; -"room_participants_security_information_room_encrypted" = "Сообщения в этой комнате не шифруются сквозным шифрованием. \n \nВаши сообщения защищены замками, и только у вас и получателя есть уникальные ключи, чтобы разблокировать их."; +"room_participants_security_information_room_encrypted" = "Сообщения в этой комнате зашифрованы сквозным шифрованием. \n \nВаши сообщения защищены замками, и только у вас и получателя есть уникальные ключи, чтобы разблокировать их."; "room_member_power_level_admin_in" = "Администратор в %@"; "room_member_power_level_moderator_in" = "Модератор в %@"; "room_member_power_level_custom_in" = "Пользовательский (%@) в %@"; From 05c9907a171f6f5dac1236f9943da2b82ff57240 Mon Sep 17 00:00:00 2001 From: Doug Date: Thu, 18 Nov 2021 14:23:34 +0000 Subject: [PATCH 056/122] Use DTCoreText callback for sanitizing HTML in GroupHomeViewController. --- .../Home/GroupHomeViewController.m | 196 ++++++++++-------- Riot/Utils/EventFormatter.m | 3 + changelog.d/5165.change | 1 + 3 files changed, 110 insertions(+), 90 deletions(-) create mode 100644 changelog.d/5165.change diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.m b/Riot/Modules/Communities/Home/GroupHomeViewController.m index 42825da70..018c15eb9 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.m +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.m @@ -40,11 +40,14 @@ // The options used to load long description html content. NSDictionary *options; - NSString *sanitisedGroupLongDescription; + NSString *groupLongDescription; // The current pushed view controller UIViewController *pushedViewController; } + +@property (nonatomic, readonly) DTHTMLAttributedStringBuilderWillFlushCallback longDescriptionSanitizationCallback; + @end @implementation GroupHomeViewController @@ -75,6 +78,23 @@ // Keep visible the status bar by default. isStatusBarHidden = NO; + + // Set up sanitization for the long description + NSArray *allowedHTMLTags = @[ + @"font", // custom to matrix for IRC-style font coloring + @"del", // for markdown + @"body", // added internally by DTCoreText + @"h1", @"h2", @"h3", @"h4", @"h5", @"h6", @"blockquote", @"p", @"a", @"ul", @"ol", + @"nl", @"li", @"b", @"i", @"u", @"strong", @"em", @"strike", @"code", @"hr", @"br", @"div", + @"table", @"thead", @"caption", @"tbody", @"tr", @"th", @"td", @"pre", + @"img" + ]; + + MXWeakify(self); + _longDescriptionSanitizationCallback = ^(DTHTMLElement *element) { + MXStrongifyAndReturnIfNil(self); + [element sanitizeWith:allowedHTMLTags bodyFont:self->_groupLongDescription.font imageHandler:[self groupLongDescriptionImageHandler]]; + }; } - (void)viewDidLoad @@ -154,7 +174,7 @@ font-size: small; \ }", (unsigned long)bgColor]; - // Apply the css style + // Apply the css style with some sanitisation. options = @{ DTUseiOS6Attributes: @(YES), // Enable it to be able to display the attributed string in a UITextView DTDefaultFontFamily: _groupLongDescription.font.familyName, @@ -162,7 +182,8 @@ DTDefaultFontSize: @(_groupLongDescription.font.pointSize), DTDefaultTextColor: _groupLongDescription.textColor, DTDefaultLinkDecoration: @(NO), - DTDefaultStyleSheet: [[DTCSSStylesheet alloc] initWithStyleBlock:defaultCSS] + DTDefaultStyleSheet: [[DTCSSStylesheet alloc] initWithStyleBlock:defaultCSS], + DTWillFlushBlockCallBack: self.longDescriptionSanitizationCallback }; } @@ -489,94 +510,11 @@ { if (_group.summary.profile.longDescription.length) { - // Render this html content in a text view. - NSArray * allowedHTMLTags = @[ - @"font", // custom to matrix for IRC-style font coloring - @"del", // for markdown - @"h1", @"h2", @"h3", @"h4", @"h5", @"h6", @"blockquote", @"p", @"a", @"ul", @"ol", - @"nl", @"li", @"b", @"i", @"u", @"strong", @"em", @"strike", @"code", @"hr", @"br", @"div", - @"table", @"thead", @"caption", @"tbody", @"tr", @"th", @"td", @"pre", - @"img" - ]; - - // Do some sanitisation by handling the potential image - MXWeakify(self); - sanitisedGroupLongDescription = [MXKTools sanitiseHTML:_group.summary.profile.longDescription withAllowedHTMLTags:allowedHTMLTags imageHandler:^NSString *(NSString *sourceURL, CGFloat width, CGFloat height) { - - MXStrongifyAndReturnValueIfNil(self, nil); - NSString *localSourcePath; - - if (width != -1 && height != -1) - { - CGSize size = CGSizeMake(width, height); - // Build the cache path for the a thumbnail of this image. - NSString *cacheFilePath = [MXMediaManager thumbnailCachePathForMatrixContentURI:sourceURL - andType:nil - inFolder:kMXMediaManagerDefaultCacheFolder - toFitViewSize:size - withMethod:MXThumbnailingMethodScale]; - // Check whether the provided URL is a valid Matrix Content URI. - if (cacheFilePath) - { - // Download the thumbnail if it is not already stored in the cache. - if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath]) - { - MXWeakify(self); - [self.mxSession.mediaManager downloadThumbnailFromMatrixContentURI:sourceURL - withType:nil - inFolder:kMXMediaManagerDefaultCacheFolder - toFitViewSize:size - withMethod:MXThumbnailingMethodScale - success:^(NSString *outputFilePath) { - MXStrongifyAndReturnIfNil(self); - [self refreshGroupLongDescription]; - } - failure:nil]; - } - else - { - // Update the local path - localSourcePath = [NSString stringWithFormat:@"file://%@", cacheFilePath]; - } - } - } - else - { - // Build the cache path for this image. - NSString* cacheFilePath = [MXMediaManager cachePathForMatrixContentURI:sourceURL - andType:nil - inFolder:kMXMediaManagerDefaultCacheFolder]; - - // Check whether the provided URL is a valid Matrix Content URI. - if (cacheFilePath) - { - // Download the image if it is not already stored in the cache. - if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath]) - { - MXWeakify(self); - [self.mxSession.mediaManager downloadMediaFromMatrixContentURI:sourceURL - withType:nil - inFolder:kMXMediaManagerDefaultCacheFolder - success:^(NSString *outputFilePath) { - MXStrongifyAndReturnIfNil(self); - [self refreshGroupLongDescription]; - } - failure:nil]; - } - else - { - // Update the local path - localSourcePath = [NSString stringWithFormat:@"file://%@", cacheFilePath]; - } - } - } - return localSourcePath; - - }]; + groupLongDescription = _group.summary.profile.longDescription; } else { - sanitisedGroupLongDescription = nil; + groupLongDescription = nil; } [self renderGroupLongDescription]; @@ -584,12 +522,13 @@ - (void)renderGroupLongDescription { - if (sanitisedGroupLongDescription) + if (groupLongDescription) { // Using DTCoreText, which renders static string, helps to avoid code injection attacks // that could happen with the default HTML renderer of NSAttributedString which is a // webview. - NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[sanitisedGroupLongDescription dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL]; + // The supplied options include a callback to sanitize html tags and load image data. + NSAttributedString *attributedString = [[NSAttributedString alloc] initWithHTMLData:[groupLongDescription dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:NULL]; // Apply additional treatments NSInteger mxIdsBitMask = (MXKTOOLS_USER_IDENTIFIER_BITWISE | MXKTOOLS_ROOM_IDENTIFIER_BITWISE | MXKTOOLS_ROOM_ALIAS_BITWISE | MXKTOOLS_EVENT_IDENTIFIER_BITWISE | MXKTOOLS_GROUP_IDENTIFIER_BITWISE); @@ -605,6 +544,83 @@ } } +- (NSURL *(^)(NSString *sourceURL, CGFloat width, CGFloat height))groupLongDescriptionImageHandler +{ + MXWeakify(self); + return ^NSURL *(NSString *sourceURL, CGFloat width, CGFloat height) { + + MXStrongifyAndReturnValueIfNil(self, nil); + NSURL *localSourceURL; + + if (width != -1 && height != -1) + { + CGSize size = CGSizeMake(width, height); + // Build the cache path for the a thumbnail of this image. + NSString *cacheFilePath = [MXMediaManager thumbnailCachePathForMatrixContentURI:sourceURL + andType:nil + inFolder:kMXMediaManagerDefaultCacheFolder + toFitViewSize:size + withMethod:MXThumbnailingMethodScale]; + // Check whether the provided URL is a valid Matrix Content URI. + if (cacheFilePath) + { + // Download the thumbnail if it is not already stored in the cache. + if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath]) + { + MXWeakify(self); + [self.mxSession.mediaManager downloadThumbnailFromMatrixContentURI:sourceURL + withType:nil + inFolder:kMXMediaManagerDefaultCacheFolder + toFitViewSize:size + withMethod:MXThumbnailingMethodScale + success:^(NSString *outputFilePath) { + MXStrongifyAndReturnIfNil(self); + [self refreshGroupLongDescription]; + } + failure:nil]; + } + else + { + // Update the local url + localSourceURL = [NSURL fileURLWithPath:cacheFilePath]; + } + } + } + else + { + // Build the cache path for this image. + NSString* cacheFilePath = [MXMediaManager cachePathForMatrixContentURI:sourceURL + andType:nil + inFolder:kMXMediaManagerDefaultCacheFolder]; + + // Check whether the provided URL is a valid Matrix Content URI. + if (cacheFilePath) + { + // Download the image if it is not already stored in the cache. + if (![[NSFileManager defaultManager] fileExistsAtPath:cacheFilePath]) + { + MXWeakify(self); + [self.mxSession.mediaManager downloadMediaFromMatrixContentURI:sourceURL + withType:nil + inFolder:kMXMediaManagerDefaultCacheFolder + success:^(NSString *outputFilePath) { + MXStrongifyAndReturnIfNil(self); + [self refreshGroupLongDescription]; + } + failure:nil]; + } + else + { + // Update the local path + localSourceURL = [NSURL fileURLWithPath:cacheFilePath]; + } + } + } + return localSourceURL; + + }; +} + - (void)didSelectRoomId:(NSString*)roomId { // Check first if the user already joined this room. diff --git a/Riot/Utils/EventFormatter.m b/Riot/Utils/EventFormatter.m index c7a11f1d0..d97386aaa 100644 --- a/Riot/Utils/EventFormatter.m +++ b/Riot/Utils/EventFormatter.m @@ -342,6 +342,9 @@ static NSString *const kEventFormatterTimeFormat = @"HH:mm"; white-space: pre; \ -coretext-fontname: Menlo-Regular; \ font-size: small; \ + } \ + h1,h2 { \ + font-size: 1.2em; \ }", (unsigned long)bgColor]; self.defaultTextColor = ThemeService.shared.theme.textPrimaryColor; diff --git a/changelog.d/5165.change b/changelog.d/5165.change new file mode 100644 index 000000000..59fea57b5 --- /dev/null +++ b/changelog.d/5165.change @@ -0,0 +1 @@ +Use DTCoreText's callback option to sanitise formatted messages \ No newline at end of file From 83f843285c0b4ffb06b6b76c62ee1f94bc427d67 Mon Sep 17 00:00:00 2001 From: Farhad Date: Mon, 22 Nov 2021 08:25:47 +0000 Subject: [PATCH 057/122] Translated using Weblate (Persian) Currently translated at 47.8% (636 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/fa/ --- Riot/Assets/fa.lproj/Vector.strings | 359 +++++++++++++++++++++++++++- 1 file changed, 358 insertions(+), 1 deletion(-) diff --git a/Riot/Assets/fa.lproj/Vector.strings b/Riot/Assets/fa.lproj/Vector.strings index ff078be25..70464fddd 100644 --- a/Riot/Assets/fa.lproj/Vector.strings +++ b/Riot/Assets/fa.lproj/Vector.strings @@ -17,7 +17,7 @@ "back" = "بازگشت"; "store_full_description" = "المنت یک پیام‌رسان جدید و ابزاری برای همکاری افراد است که:\n\n۱. امکانات کنترلی لازم برای حفاظت از حریم خصوصی را در اختیار شما قرار می‌دهد.\n۲. امکان برقراری ارتباط با هر کسی را بر بستر شبکه‌ی ماتریکس و حتی فراتر از آن، امکان برقراری ارتباط با برنامه‌های دیگر نظیر Slack را در اختیار شما قرار می‌دهد.\n۳. شما را در برابر تبلیغات، کندوکاو داده‌هایتان، در پشتی و همچنین یک زیست‌بوم بسته و محصور محافظت می‌کند.\n۴. شما را از طریق رمزنگاری سرتاسری و همچنین امضاء متقابل برای تائيد هویت دیگران، امن می‌کند.\n\nالمنت یک پیام‌رسان و ابزار ارتباطی کاملا متفاوت است، چرا که از معماری غیرمتمرکز بهره برده و متن‌باز است.\n\nالمنت امکان استقرار محلی - یا انتخاب هر میزبان دلخواهی - را به شما داده و از این طریق حریم خصوصی، مالکیت و کنترل داده‌ها و گفتگوهایتان برای شما به ارمغان می‌آورد. همچنین دسترسی به یک شبکه‌ی باز را برای شما فراهم کرده، به طوری که مجبور نیستید فقط با کاربران المنت به گفتگو و صحبت بپردازید. در کنار همه‌ی این‌ها، بسیار امن است.\n\nپشتوانه‌ی قابلیت‌های بالا، استفاده از ماتریکس است - یک استاندارد برای ارتباطات غیرمحدود و متمرکز.\n\nالمنت به شما اختیار می‌دهد سرور گفتگو‌های خود را انتخاب کنید. در برنامه المنت، به طرق مختلف می‌توانید سرور مورد نظر خود را انتخاب کنید:\n\n۱. ساختن یک حساب‌کاربری رایگان بر روی سرور عمومی matrix.org\n۲. استقرار محلی و راه‌اندازی سرور بر روی سخت‌افزار خودتان و ایجاد حساب کاربری بر روی آن\n۳. ایجاد حساب کاربری بر روی یک سرور دلخواه از طریق عضویت در پلتفورم استقرار Element Matrix Services\n\nچرا المنت گزینه‌ی جذابی است؟\n\nمالک حقیقی داده‌های خود باشید: شما تصمیم بگیرید داده‌ها و پیام‌هایتان کجا ذخیره شوند. المنت مانند برخی اَبَرشرکت ها، در داده‌های شما کاوش نکرده و آن‌ها را در اختیار شخص ثالثی قرار نمی‌دهد.\n\nپیام‌رسانی و ارتباطات باز: شما می‌توانید با هر کسی بر بستر ماتریکس ارتباط بگیرید، فارغ از اینکه از کدام کلاینت ماتریکسی استفاده می‌کنند؛ حتی فراتر، شما می‌توانید افراد بر بستر سازوکارهای پیام‌رسانی دیگر نظیر Slack ،XMPP و یا IRC نیز ارتباط برقرار نمائید.\n\nفوق‌العاده امن: رمزنگاری سرتاسری واقعی (فقط افرادی که در حال گفتگو هستند امکان رمزگشایی پیام‌ها را دارند)، به همراه قابلیت امضاء متقابل برای تائید هویت دستگاه و هویت طرف‌های گفتگو.\n\nپکیج ارتباطی کامل: پیام‌رسانی، تماس‌های صوتی و تصویری، ارسال فایل، به اشتراک‌گذاری صفحه نمایش و یک طیف گسترده‌ای از یکپارچه‌سازی‌ها، بات‌ها و ابزارک‌ها. اتاق‌ها و فضاهای کاری مختلف بسازید و برای به سرانجام رسیدن امور، در ارتباط باشید.\n\nحاضر در همه جا: هرجا و هر زمان در دسترس بوده و پیام‌های خود را به صورت همگام‌سازی‌شده بر روی دستگاه‌های مختلف در اختیار داشته باشید."; // String for App Store -"store_short_description" = "پیامرسان/تماس صوتی تصویری اینترنتی امن مبتنی بر بستر غیرمتمرکز"; +"store_short_description" = "پیام رسان/تماس صوتی تصویری اینترنتی امن مبتنی بر بستر غیرمتمرکز"; "auth_missing_password" = "لطفا رمز عبور را وارد نمایید"; "auth_invalid_phone" = "شماره تماس وارد شده بنظر اشتباه است"; "auth_invalid_email" = "آدرس پست الکترونیکی وارد شده بنظر اشتباه است"; @@ -377,3 +377,360 @@ "contacts_address_book_permission_denied_alert_title" = "لیست مخاطبین غیرفعال شد"; "directory_cell_description" = "%tu اتاق ها"; "auth_add_email_phone_message_2" = "یک ایمیل برای بازیابی حساب کاربری خود تنظیم کنید. از این ایمیل یا شماره تلفن استفاده کنید تا به صورت اختیاری توسط افرادی که شما را می شناسند قابل شناسایی باشید."; +"no_voip" = "%@ در حال تماس با شما است اما %@ هنوز از تماس ها پشتیبانی نمی کند.\nمی توانید این اعلان را نادیده بگیرید و به تماس از دستگاه دیگری پاسخ دهید یا می توانید آن را رد کنید."; + +// No VoIP support +"no_voip_title" = "تماس ورودی"; +"call_actions_unhold" = "ادامه"; +"call_no_stun_server_error_use_fallback_button" = "سعی کنید از %@ استفاده کنید"; +"call_no_stun_server_error_message_2" = "از طرف دیگر، می‌توانید سعی کنید از سرور عمومی در %@ استفاده کنید، اما قابل اعتماد نخواهد بود و آدرس IP شما را با آن سرور به اشتراک می‌گذارد. شما همچنین می توانید این را در تنظیمات مدیریت کنید"; +"call_no_stun_server_error_title" = "تماس به دلیل پیکربندی اشتباه سرور انجام نشد"; +"call_jitsi_error" = "پیوستن به تماس کنفرانس ناموفق بود."; +"call_already_displayed" = "در حال حاضر یک تماس در حال انجام است."; +"call_incoming_video" = "تماس تصویری ورودی…"; +"call_incoming_voice" = "تماس ورودی…"; +"call_incoming_video_prompt" = "تماس تصویری ورودی از %@"; + +// Call +"call_incoming_voice_prompt" = "تماس صوتی ورودی از %@"; +"room_does_not_exist" = "٪@ وجود ندارد"; +"photo_library_access_not_granted" = "%@ اجازه دسترسی به عکس های دستگاه شما را ندارد، لطفاً تنظیمات حریم خصوصی را تغییر دهید"; +"camera_unavailable" = "دوربین در دستگاه شما قابل دسترسی نیست"; +"camera_access_not_granted" = "%@ اجازه استفاده از دوربین را ندارد، لطفاً تنظیمات حریم خصوصی را تغییر دهید"; +"do_not_ask_again" = "دوباره نپرس"; +"bug_report_prompt" = "برنامه آخرین بار از کار افتاده بود. آیا می خواهید یک گزارش خرابی ارسال کنید؟"; +"public_room_section_title" = "اتاق‌های عمومی (در %@):"; +"homeserver_connection_lost" = "عدم اتصال به سرور خانگی."; +"network_offline_prompt" = "به نظر می رسد اتصال اینترنت آفلاین است."; +"yesterday" = "دیروز"; +"today" = "امروز"; +"you" = "شما"; + +// Others +"or" = "یا"; +"event_formatter_jitsi_widget_removed_by_you" = "کنفرانس VoIP را حذف کردید"; +"event_formatter_jitsi_widget_added_by_you" = "شما کنفرانس VoIP را اضافه کردید"; +"event_formatter_widget_removed_by_you" = "ویجت را حذف کردید:@%"; + +// Events formatter with you +"event_formatter_widget_added_by_you" = "ویجت را اضافه کردید:@ %"; +"event_formatter_group_call_incoming" = "@٪ در@ ٪"; +"event_formatter_group_call_leave" = "ترک"; +"event_formatter_group_call_join" = "پیوستن"; +"event_formatter_group_call" = "تماس گروهی"; +"event_formatter_call_end_call" = "پایان تماس"; +"event_formatter_call_retry" = "تلاش مجدد"; +"event_formatter_call_answer" = "پاسخ"; +"event_formatter_call_decline" = "رد تماس"; +"event_formatter_call_back" = "تماس"; +"event_formatter_call_connection_failed" = "ارتباط ناموفق بود"; +"event_formatter_call_missed_video" = "تماس ویدیویی از دست رفته"; +"event_formatter_call_missed_voice" = "تماس صوتی از دست رفته"; +"event_formatter_call_you_declined" = "تماس رد شد"; +"event_formatter_call_active_video" = "فعال کردن تماس تصویری"; +"event_formatter_call_active_voice" = "فعال کردن تماس صوتی"; +"event_formatter_call_incoming_video" = "تماس تصویری ورودی"; +"event_formatter_call_incoming_voice" = "تماس صوتی ورودی"; +"event_formatter_call_has_ended_with_time" = "تماس تلفنی پایان یافت.%@"; +"event_formatter_call_has_ended" = "تماس تلفنی پایان یافت"; +"event_formatter_call_ringing" = "در حال زنگ خوردن…"; +"event_formatter_call_connecting" = "در حال برقراری ارتباط…"; +"event_formatter_message_edited_mention" = "(ویرایش شده)"; +"event_formatter_rerequest_keys_part2" = " از سشن های دیگر شما."; +"event_formatter_rerequest_keys_part1_link" = "درخواست مجدد کلیدهای رمزگذاری"; +"event_formatter_jitsi_widget_removed" = "کنفرانس VoIP توسط %@ حذف شد"; +"event_formatter_jitsi_widget_added" = "کنفرانس VoIP توسط %@ اضافه شد"; +"event_formatter_widget_removed" = "%@ ویجت توسط %@ حذف شد"; +"event_formatter_widget_added" = "%@ ویجت اضافه شده توسط %@"; + +// Events formatter +"event_formatter_member_updates" = "%tu تغییر عضویت"; +"directory_server_placeholder" = "matrix.org"; +"directory_server_type_homeserver" = "برای فهرست کردن اتاق های عمومی یک سرور خانگی را تایپ کنید"; +"directory_server_all_rooms" = "همه اتاق ها در سرور %@"; + +// Directory +"directory_title" = "فهرست راهنما"; +"image_picker_action_library" = "انتخاب از کتابخانه"; + +// Image picker +"image_picker_action_camera" = "گرفتن عکس"; +"media_picker_select" = "انتخاب"; +"media_picker_library" = "کتابخانه"; + +// Media picker +"media_picker_title" = "کتابخانه ی رسانه"; +"receipt_status_read" = "خواندن: "; + +// Read Receipts +"read_receipts_list" = "خواندن لیست رسیدها"; + +// Group rooms +"group_rooms_filter_rooms" = "فیلتر کردن اتاق های انجمن"; +"group_participants_invited_section" = "دعوت شده"; +"group_participants_invite_malformed_id_title" = "خطای دعوت"; +"group_participants_invite_another_user" = "جستجو / دعوت با شناسه کاربری یا نام"; +"group_participants_filter_members" = "اعضای انجمن را فیلتر کنید"; +"group_participants_invite_prompt_msg" = "آیا مطمئنید که می خواهید %@ را به این گروه دعوت کنید؟"; +"group_participants_invite_prompt_title" = "تایید"; +"group_participants_remove_prompt_msg" = "آیا مطمئنید که می خواهید %@ را از این گروه حذف کنید؟"; +"room_notifs_settings_encrypted_room_notice" = "لطفاً توجه داشته باشید که اشاره‌ها و اعلان‌های کلید واژه در اتاق‌های رمزگذاری‌شده روی موبایل در دسترس نیستند."; +"group_participants_leave_prompt_title" = "ترک گروه"; +"group_participants_remove_prompt_title" = "تایید"; +"group_participants_leave_prompt_msg" = "آیا مطمئن هستید که می خواهید گروه را ترک کنید؟"; + +// Group participants +"group_participants_add_participant" = "افزودن شرکت کننده(عضو)"; +"group_invitation_format" = "%@ از شما دعوت کرده است که به این انجمن بپیوندید"; +"group_home_multi_rooms_format" = "%tu اتاق ها"; +"group_home_one_room_format" = "۱ اتاق"; +"group_home_multi_members_format" = "%tu اعضا"; + +// Group Home +"group_home_one_member_format" = "۱ عضو"; +"group_details_rooms" = "اتاق ها"; +"group_details_people" = "افراد"; +"group_details_home" = "خانه"; + +// Group Details +"group_details_title" = "جزئیات انجمن"; +"room_notifs_settings_account_settings" = "تنظیمات حساب"; +"room_notifs_settings_manage_notifications" = "می توانید اعلان ها را در %@ مدیریت کنید"; +"room_notifs_settings_cancel_action" = "لغو"; +"room_notifs_settings_done_action" = "انجام شد"; +"room_notifs_settings_none" = "هیچ کدام"; +"room_notifs_settings_mentions_and_keywords" = "فقط ذکر و کلمات کلیدی"; +"room_notifs_settings_all_messages" = "تمام پیام ها"; + +// Room Notification Settings +"room_notifs_settings_notify_me_for" = "به من اطلاع بده برای"; +"room_details_copy_room_url" = "کپی کردن URL اتاق"; +"room_details_copy_room_address" = "کپی کردن آدرس اتاق"; +"room_details_copy_room_id" = "کپی کردن شناسه اتاق"; +"room_details_unset_main_address" = "به عنوان آدرس اصلی تنظیم نشود"; +"room_details_set_main_address" = "به عنوان آدرس اصلی تنظیم کنید"; +"room_details_save_changes_prompt" = "آیا می خواهید تغییرات را ذخیره کنید؟"; +"room_details_fail_to_enable_encryption" = "رمزگذاری در این اتاق فعال نشد"; +"room_details_fail_to_update_room_communities" = "به‌روزرسانی انجمن‌های مرتبط انجام نشد"; +"room_details_fail_to_update_room_canonical_alias" = "آدرس اصلی به روز نشد"; +"room_details_fail_to_remove_room_aliases" = "آدرس‌های اتاق حذف نشد"; +"room_details_fail_to_add_room_aliases" = "آدرس اتاق جدید اضافه نشد"; +"room_details_fail_to_update_room_directory_visibility" = "مشاهده فهرست راهنمای اتاق به روز رسانی نشد"; +"room_details_fail_to_update_history_visibility" = "مشاهده تاریخچه به روز نشد"; +"room_details_fail_to_update_room_join_rule" = "قانون پیوستن به روز نشد"; +"room_details_fail_to_update_room_guest_access" = "دسترسی مهمان اتاق به‌روزرسانی نشد"; +"room_details_fail_to_update_topic" = "موضوع به روز نشد"; +"room_details_fail_to_update_room_name" = "نام اتاق به‌روزرسانی نشد"; +"room_details_fail_to_update_avatar" = "عکس اتاق به روز نشد"; +"room_details_advanced_e2e_encryption_blacklist_unverified_devices" = "فقط در سشن های تأیید شده رمزگذاری شود"; +"room_details_advanced_e2e_encryption_disabled_for_dm" = "رمزگذاری در اینجا فعال نیست."; +"room_details_advanced_e2e_encryption_disabled" = "رمزگذاری در این اتاق فعال نیست."; +"room_details_advanced_e2e_encryption_enabled_for_dm" = "رمزگذاری در اینجا فعال است"; +"room_details_advanced_e2e_encryption_enabled" = "رمزگذاری در این اتاق فعال است"; +"room_details_advanced_enable_e2e_encryption" = "رمزگذاری را فعال کنید (هشدار: غیر قابل فعال سازی مجدد!)"; +"room_details_advanced_room_id_for_dm" = "شناسه:"; +"room_details_advanced_room_id" = "شناسه اتاق:"; +"room_details_advanced_section" = "پیشرفته"; +"room_details_banned_users_section" = "کاربران ممنوع"; +"room_details_flair_invalid_id_prompt_msg" = "%@ یک شناسه معتبر برای یک انجمن نیست"; +"room_details_flair_invalid_id_prompt_title" = "قالب نامعتبر"; +"room_details_new_flair_placeholder" = "افزودن شناسه انجمن جدید (به عنوان مثال +foo%@)"; +"room_details_addresses_disable_main_address_prompt_msg" = "هیچ آدرس اصلی مشخصی نخواهید داشت. آدرس اصلی پیش‌فرض برای این اتاق به‌طور تصادفی انتخاب می‌شود"; +"room_details_addresses_disable_main_address_prompt_title" = "هشدار آدرس اصلی"; +"room_details_addresses_invalid_address_prompt_msg" = "%@ قالب معتبری برای نام مستعار نیست"; +"room_details_addresses_invalid_address_prompt_title" = "قالب نامعتبر است"; +"room_details_new_address_placeholder" = "افزودن آدرس جدید( به طور مثال %@ #foo)"; +"room_details_new_address" = "افزودن آدرس جدید"; +"room_details_no_local_addresses_for_dm" = "این آدرس محلی ندارد"; +"room_details_no_local_addresses" = "این اتاق هیچ آدرس محلی ندارد"; +"room_details_addresses_section" = "آدرس ها"; +"room_details_history_section_prompt_msg" = "تغییرات مربوط به افرادی که می توانند تاریخچه را بخوانند فقط برای پیام های بعدی در این اتاق اعمال می شود. نمایان شدن تاریخچه موجود بدون تغییر خواهد بود."; +"room_details_history_section_prompt_title" = "هشدار حفظ حریم خصوصی"; +"room_details_history_section_members_only_since_joined" = "فقط اعضا (از زمانی که عضو شدند)"; +"room_details_history_section_members_only_since_invited" = "فقط اعضا (از زمانی که دعوت شده اند)"; +"room_details_history_section_members_only" = "فقط اعضا (از زمان انتخاب این گزینه)"; +"room_details_history_section_anyone" = "همه"; +"room_details_history_section" = "چه کسی می تواند تاریخچه را بخواند؟"; +"room_details_access_section_directory_toggle_for_dm" = "لیست کردن در فهرست اتاق"; +"room_details_access_section_directory_toggle" = "این اتاق را در فهرست راهنمای اتاق لیست کنید"; +"room_details_access_section_no_address_warning" = "برای لینک شدن به یک اتاق، باید یک آدرس داشته باشد"; +"room_details_access_section_anyone_for_dm" = "هر کسی که لینک را می داند، از جمله مهمانان"; +"room_details_access_section_anyone" = "هر کسی که لینک اتاق را می داند، از جمله مهمانان"; +"room_details_access_section_anyone_apart_from_guest_for_dm" = "هر کسی که لینک را می داند، به غیر از مهمانان"; +"room_details_access_section_anyone_apart_from_guest" = "هر کسی که لینک اتاق را می داند، به غیر از مهمانان"; +"room_details_access_section_invited_only" = "فقط افرادی که دعوت شده اند"; +"room_details_access_section_for_dm" = "چه کسی می تواند به این دسترسی داشته باشد؟"; +"room_details_access_section" = "چه کسی می تواند به این اتاق دسترسی داشته باشد؟"; +"room_details_direct_chat" = "چت مستقیم"; +"room_details_mute_notifs" = "بی صدا کردن اعلان ها"; +"room_details_notifs" = "اعلان ها"; +"room_details_low_priority_tag" = "اولویت کم"; +"room_details_favourite_tag" = "علاقه مندی"; +"room_details_topic" = "موضوع"; +"room_details_room_name_for_dm" = "نام"; +"room_details_room_name" = "نام اتاق"; +"room_details_photo_for_dm" = "عکس"; +"room_details_photo" = "عکس اتاق"; +"room_details_settings" = "تنظیمات"; +"room_details_search" = "جستجو اتاق"; +"room_details_files" = "بارگذاری شده ها"; +"room_details_people" = "اعضا"; +"room_details_title_for_dm" = "جزییات"; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "به هر حال قطع کن"; +"identity_server_settings_alert_disconnect_button" = "قطع کردن"; +"identity_server_settings_disconnect" = "قطع کردن"; +"identity_server_settings_change" = "تغییر دادن"; +"identity_server_settings_add" = "افزودن"; +"identity_server_settings_description" = "شما در حال حاضر از %@ استفاده می‌کنید تا مخاطبینی را که می‌شناسید را پیدا کنید و برای آن ها قابل شناسایی باشید."; + +// AuthenticatedSessionViewControllerFactory +"authenticated_session_flow_not_supported" = "این برنامه از مکانیسم احراز هویت در سرور خانه شما پشتیبانی نمی کند."; +"manage_session_sign_out" = "خروج از این سشن"; +"manage_session_not_trusted" = "قابل اعتماد نیست"; +"manage_session_trusted" = "مورد اعتماد شما است"; +"manage_session_name" = "نام سشن"; +"manage_session_info" = "اطلاعات سشن"; + +// Manage session +"manage_session_title" = "مدیریت سشن"; +"security_settings_user_password_description" = "هویت خود را با وارد کردن رمز عبور حساب خود تأیید کنید"; +"security_settings_complete_security_alert_message" = "ابتدا باید امنیت را در سشن فعلی خود کامل کنید."; +"security_settings_complete_security_alert_title" = "امنیت کامل"; +"security_settings_blacklist_unverified_devices_description" = "تمام سشن های کاربران را تأیید کنید تا آنها به عنوان مورد اعتماد علامت گذاری شوند و برای آنها پیام ارسال کنید."; +"security_settings_blacklist_unverified_devices" = "هرگز به سشن های غیرقابل اعتماد پیام ارسال نشود"; +"security_settings_cryptography" = "رمزنگاری"; +"security_settings_crosssigning_complete_security" = "امنیت کامل"; +"security_settings_crosssigning_reset" = "بازنشانی کردن"; +"security_settings_crosssigning_bootstrap" = "راه اندازی کردن"; +"security_settings_backup" = "پشتیبانی پیام"; +"security_settings_secure_backup_delete" = "حذف نسخه پشتیبان"; +"security_settings_secure_backup_restore" = "بازیابی ازنسخه پشتیبان"; +"security_settings_secure_backup_reset" = "بازنشانی کردن"; +"security_settings_secure_backup_setup" = "راه اندازی کردن"; +"security_settings_secure_backup_info_valid" = "این سشن از کلیدهای شما نسخه پشتیبان تهیه می کند."; +"security_settings_secure_backup_info_checking" = "چک کردن…"; +"security_settings_secure_backup_description" = "در صورت از دست دادن دسترسی به سشن های خود، از کلیدهای رمزگذاری خود بوسیله داده های حساب خود نسخه پشتیبان تهیه کنید. کلیدهای شما با یک کلید امنیتی منحصر به فرد ایمن می شوند."; +"security_settings_secure_backup" = "نسخه پشتیبان ایمن"; +"security_settings_crypto_sessions_description_2" = "اگر ورود به سیستم را نمی شناسید، رمز عبور خود را تغییر دهید و نسخه پشتیبان امن را بازنشانی کنید."; +"security_settings_crypto_sessions_loading" = "در حال بار گذاری سشن ها…"; +"security_settings_crypto_sessions" = "سشن های من"; + +// Security settings +"security_settings_title" = "امنیت"; +"settings_discovery_three_pid_details_enter_sms_code_action" = "کد فعال سازی پیامکی را وارد کنید"; +"settings_discovery_three_pid_details_cancel_email_validation_action" = "لغو اعتبارسنجی ایمیل"; +"settings_discovery_three_pid_details_revoke_action" = "لغو"; +"settings_discovery_three_pid_details_share_action" = "اشتراک گذاری"; +"settings_discovery_three_pid_details_information_phone_number" = "تنظیمات برگزیده برای این آدرس شماره تلفن ، که سایر کاربران می توانند از آن برای پیدا کردن و دعوت شما به اتاق استفاده کنند را مدیریت کنید. شماره تلقن ها را در حساب‌ها اضافه یا حذف کنید."; +"settings_discovery_three_pid_details_title_phone_number" = "مدیریت شماره تلفن"; +"settings_discovery_three_pid_details_information_email" = "تنظیمات برگزیده برای این آدرس ایمیل ، که سایر کاربران می توانند از آن برای پیدا کردن و دعوت شما به اتاق استفاده کنند را مدیریت کنید. آدرس‌های ایمیل را در حساب‌ها اضافه یا حذف کنید."; +"settings_discovery_three_pid_details_title_email" = "مدیریت ایمیل"; +"settings_discovery_error_message" = "خطایی رخ داده است. لطفا دوباره امتحان کنید."; +"settings_discovery_three_pids_management_information_part3" = "."; +"settings_discovery_three_pids_management_information_part2" = "تنظیمات کاربر"; +"settings_discovery_three_pids_management_information_part1" = "آدرس‌های ایمیل یا شماره تلفن‌هایی را که کاربران دیگر می‌توانند برای پیداکردن شما و دعوت شما به اتاق‌ها استفاده کنند، مدیریت کنید. آدرس ایمیل یا شماره تلفن را از این لیست اضافه یا حذف کنید "; +"settings_devices_description" = "نام عمومی سشن برای افرادی که با آنها ارتباط برقرار می کنید قابل مشاهده است"; +"settings_key_backup_delete_confirmation_prompt_msg" = "آیامطمئن هستید؟ اگر از کلیدهای شما به درستی پشتیبان گیری نشود، پیام های رمزگذاری شده خود را از دست خواهید داد."; +"settings_key_backup_delete_confirmation_prompt_title" = "حذف نسخه پشتیبان"; +"settings_key_backup_button_connect" = "این سشن را به کلید پشتیبان متصل کنید"; +"settings_key_backup_button_delete" = "حذف پشتیبان"; +"settings_key_backup_button_restore" = "بازیابی از نسخه پشتیبان"; +"settings_key_backup_button_create" = "استفاده ازکلید نسخه پشتیبان را شروع کنید"; +"settings_key_backup_info_progress_done" = "از همه کلیدها نسخه پشتیبان تهیه شد"; +"settings_key_backup_info_progress" = "در حال پشتیبان گیری از کلیدهای %@…"; +"settings_key_backup_info_not_valid" = "این سشن از کلیدهای شما نسخه پشتیبان تهیه نمی کند، اما شما یک نسخه پشتیبان موجود دارید که می توانید آن را بازیابی کنید و به آن اضافه کنید."; +"settings_key_backup_info_valid" = "این سشن از کلیدهای شما نسخه پشتیبان تهیه می کند."; +"settings_key_backup_info_algorithm" = "الگوریتم: %@"; +"settings_key_backup_info_version" = "نسخه پشتیبان کلید: %@"; +"settings_key_backup_info_signout_warning" = "قبل از خروج از سیستم، برای جلوگیری از گم شدن از کلیدهای خود نسخه پشتیبان تهیه کنید ."; +"settings_key_backup_info_none" = "از کلیدهای شما در این سشن پشتیبان‌گیری نمی‌شود."; +"settings_key_backup_info_checking" = "چک کردن…"; +"settings_key_backup_info" = "پیام های رمزگذاری شده با رمزگذاری سراسری ایمن می شوند. فقط شما و گیرنده(ها) کلید خواندن این پیام ها را دارید."; +"settings_deactivate_my_account" = "حساب من را غیر فعال کنید"; +"settings_crypto_blacklist_unverified_devices" = "فقط در سشن تأیید شده رمزگذاری کنید"; +"settings_crypto_device_key" = "\nکلید سشن\n"; +"settings_crypto_device_id" = "\nآیدی سشن "; +"settings_add_3pid_password_message" = "برای ادامه، لطفا رمز عبور خود را وارد کنید"; +"settings_add_3pid_password_title_msidsn" = "شماره تلفن را اضافه کنید"; +"settings_add_3pid_password_title_email" = "آدرس ایمیل را اضافه کنید"; +"settings_password_updated" = "رمز عبور شما به روز شده است"; +"settings_fail_to_update_password" = "رمز عبور به روز نشد"; +"settings_confirm_password" = "تایید رمز"; +"settings_new_password" = "رمز جدید"; +"settings_old_password" = "رمز قدیمی"; +"settings_third_party_notices" = "اعلامیه های شخص ثالث"; +"settings_privacy_policy" = "سیاست حفظ حریم خصوصی"; +"settings_term_conditions" = "شرایط و ضوابط"; +"settings_copyright" = "کپی رایت"; +"settings_version" = "نسخه %@"; +"settings_labs_voice_messages" = "پیام صوتی"; +"settings_labs_message_reaction" = "با ایموجی به پیام ها واکنش نشان دهید"; +"settings_labs_create_conference_with_jitsi" = "با jitsi تماس های کنفرانسی ایجاد کنید"; +"settings_labs_e2e_encryption_prompt_message" = "برای تکمیل تنظیمات رمزگذاری، باید دوباره وارد شوید."; +"settings_contacts_enable_sync_description" = "این گزینه از سرور هویت شما برای اتصال شما به مخاطبینتان استفاده می کند و به آنها کمک می کند شما را پیدا کنند."; +"settings_contacts_phonebook_country" = "کشور دفترچه تلفن"; +"settings_contacts_enable_sync" = "مخاطبین خود را پیدا کنید"; +"settings_unignore_user" = "نمایش همه پیام‌های %@؟"; +"settings_show_url_previews_description" = "پیش‌نمایش‌ها فقط در اتاق‌های رمزگذاری نشده نشان داده می‌شوند."; +"settings_show_url_previews" = "نمایش پیش نمایش وب سایت"; +"settings_ui_theme_picker_message_match_system_theme" = "\"حالت خودکار\" با زمینه سیستم دستگاه شما مطابقت دارد"; +"settings_ui_theme_picker_message_invert_colours" = "\"حالت خودکار\" از تنظیمات \"Invert Colors\" دستگاه شما استفاده می کند"; +"settings_ui_theme_picker_title" = "انتخاب زمینه"; +"settings_ui_theme" = "زمینه"; +"settings_ui_theme_black" = "سیاه"; +"settings_ui_theme_dark" = "تیره"; +"settings_ui_theme_light" = "روشن"; +"settings_ui_theme_auto" = "خودکار"; +"settings_ui_language" = "زبان"; +"settings_calls_stun_server_fallback_button" = "به سرور کمک تماس مجدد اجازه دهید"; +"settings_callkit_info" = "تماس های دریافتی را در صفحه قفل خود دریافت کنید. تماس های %@ خود را در تاریخچه تماس های سیستم مشاهده کنید. اگر iCloud فعال باشد، این سابقه تماس با اپل به اشتراک گذاشته خواهد شد."; +"settings_mentions_and_keywords_encryption_notice" = "در اتاق‌های رمزگذاری‌شده در تلفن همراه، اعلان‌هایی برای ذکر و کلمات کلیدی دریافت نخواهید کرد."; +"settings_new_keyword" = "اضافه کردن کلمات کلیدی"; +"settings_your_keywords" = "کلمات کلیدی شما"; +"settings_room_upgrades" = "ارتقاء اتاق"; +"settings_messages_by_a_bot" = "پیام های ربات"; +"settings_call_invitations" = "دعوت نامه های تماس"; +"settings_room_invitations" = "دعوت نامه های اتاق"; +"settings_messages_containing_keywords" = "کلمات کلیدی"; +"settings_messages_containing_at_room" = "@ اتاق"; +"settings_messages_containing_user_name" = "نام کاربری من"; +"settings_messages_containing_display_name" = "نام نمایشی من"; +"settings_encrypted_group_messages" = "پیام های گروهی رمزگذاری شده"; +"settings_group_messages" = "پیام های گروهی"; +"settings_encrypted_direct_messages" = "پیام های مستقیم رمزگذاری شده"; +"settings_direct_messages" = "پیام مستقیم"; +"settings_notify_me_for" = "به من اطلاع بده برای"; +"settings_mentions_and_keywords" = "ذکر و کلمات کلیدی"; +"settings_default" = "اعلان های پیش فرض"; +"settings_notifications_disabled_alert_message" = "برای فعال کردن اعلان‌ها، به تنظیمات دستگاه خود بروید."; +"settings_notifications_disabled_alert_title" = "غیر فعال کردن اعلان ها"; +"settings_pin_rooms_with_missed_notif" = "پین کردن اتاق هایی با اعلان های از دست رفته"; +"settings_pin_rooms_with_unread" = "پین کردن اتاق هایی با پیام های خوانده نشده"; +"settings_global_settings_info" = "تنظیمات اعلان جهانی در سرویس گیرنده وب %@ شما موجود است"; +"settings_show_decrypted_content" = "نمایش محتوای رمزگشایی شده"; +"settings_device_notifications" = "اعلان های دستگاه"; +"settings_enable_push_notif" = "اعلان ها در این دستگاه"; +"settings_security" = "امنیت"; +"settings_confirm_media_size_description" = "وقتی این گزینه روشن است، از شما خواسته می‌شود که تأیید کنید تصاویر و ویدیوها با چه اندازه ای ارسال شوند."; +"settings_confirm_media_size" = "هنگام ارسال اندازه را تأیید کنید"; +"settings_three_pids_management_information_part3" = "."; +"settings_three_pids_management_information_part1" = "آدرس‌های ایمیل یا شماره تلفن‌هایی را که می‌توانید برای ورود به سیستم یا بازیابی حساب خود در اینجا استفاده کنید، مدیریت کنید. کنترل کنید چه کسی می تواند شما را در آن پیدا کند "; +"settings_fail_to_update_profile" = "پروفایل به روز نشد"; +"settings_night_mode" = "حالت شب"; +"settings_change_password" = "رمز را تغییر دهید"; +"settings_add_phone_number" = "شماره تلفن را اضافه کنید"; +"settings_phone_number" = "تلفن"; +"settings_add_email_address" = "آدرس ایمیل را اضافه کنید"; +"settings_email_address_placeholder" = "آدرس ایمیل خود را وارد نمایید"; +"settings_email_address" = "ایمیل"; +"settings_remove_phone_prompt_msg" = "آیا مطمئن هستید که می خواهید شماره تلفن %@ را حذف کنید؟"; +"settings_remove_email_prompt_msg" = "آیا مطمئن هستید که می خواهید آدرس ایمیل %@ را حذف کنید؟"; +"settings_remove_prompt_title" = "تایید"; +"settings_surname" = "نام خانوادگی"; +"settings_first_name" = "نام"; +"settings_display_name" = "نام نمایشی"; +"settings_profile_picture" = "عکس پروفایل"; +"settings_sign_out_e2e_warn" = "کلیدهای رمزگذاری خود را از دست خواهید داد. یعنی دیگر نمی‌توانید پیام‌های قدیمی را در اتاق‌های رمزگذاری‌شده این دستگاه بخوانید."; +"settings_sign_out_confirmation" = "آیا مطمئن هستید؟"; +"settings_sign_out" = "خروج"; +"settings_deactivate_account" = "غیرفعال کردن حساب"; From 2ec380172f6cef3c62043c9affc0868d3e7c69ca Mon Sep 17 00:00:00 2001 From: Ekaterina Gerasimova Date: Wed, 24 Nov 2021 10:52:03 +0000 Subject: [PATCH 058/122] Fix link to board in issue automation Changelog covered by 5153.misc --- .github/workflows/triage-move-labelled.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/triage-move-labelled.yml b/.github/workflows/triage-move-labelled.yml index 440fc42cd..5db597239 100644 --- a/.github/workflows/triage-move-labelled.yml +++ b/.github/workflows/triage-move-labelled.yml @@ -12,7 +12,7 @@ jobs: - uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338 with: action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}" - project-url: "https://github.com/vector-im/element-android/projects/4" + project-url: "https://github.com/vector-im/element-ios/projects/12" column-name: "Need info" label-name: "X-Needs-Info" From efb25ddcbe1ef3f83994f294c1c8103945e41899 Mon Sep 17 00:00:00 2001 From: David Langley Date: Wed, 24 Nov 2021 11:38:32 +0000 Subject: [PATCH 059/122] Fix hidden rooms from showing. --- .../MatrixSDK/RecentsListService.swift | 19 +++++++++++-------- changelog.d/5185.bugfix | 1 + 2 files changed, 12 insertions(+), 8 deletions(-) create mode 100644 changelog.d/5185.bugfix diff --git a/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift b/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift index 6651fddba..32d06807f 100644 --- a/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift +++ b/Riot/Modules/Common/Recents/Service/MatrixSDK/RecentsListService.swift @@ -430,15 +430,18 @@ public class RecentsListService: NSObject, RecentsListServiceProtocol { } private func updateDirectFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) { - switch mode { - case .home: - fetcher.fetchOptions.filterOptions.notDataTypes = [.invited, .favorited, .lowPriority] - case .people: - fetcher.fetchOptions.filterOptions.notDataTypes = [.lowPriority] - default: - break + var notDataTypes: MXRoomSummaryDataTypes = [.hidden, .conferenceUser, .space] + switch mode { + case .home: + notDataTypes.insert([.invited, .favorited, .lowPriority]) + fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes + case .people: + notDataTypes.insert([.lowPriority]) + fetcher.fetchOptions.filterOptions.notDataTypes = notDataTypes + default: + break + } } - } private func updateFavoritedFetcher(_ fetcher: MXRoomListDataFetcher, for mode: RecentsDataSourceMode) { switch mode { diff --git a/changelog.d/5185.bugfix b/changelog.d/5185.bugfix new file mode 100644 index 000000000..dfc98744d --- /dev/null +++ b/changelog.d/5185.bugfix @@ -0,0 +1 @@ +Fix rooms that should be hidden(such as virtual rooms) from showing. From 3593c1cfa5a4c4c5acbcd30be6ec3d5fd4a54c96 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 25 Nov 2021 23:11:53 +0100 Subject: [PATCH 060/122] Improve generated Swift header imports. --- Riot/Model/Room/RoomPreviewData.m | 3 ++- Riot/Modules/Authentication/Views/AuthInputsView.h | 2 +- Riot/Modules/Authentication/Views/AuthInputsView.m | 2 ++ Riot/Modules/Common/Recents/Model/RecentCellData.m | 1 - Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m | 2 ++ Riot/Modules/Room/CellData/RoomBubbleCellData.m | 1 - 6 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Riot/Model/Room/RoomPreviewData.m b/Riot/Model/Room/RoomPreviewData.m index 07ece4510..f619344ed 100644 --- a/Riot/Model/Room/RoomPreviewData.m +++ b/Riot/Model/Room/RoomPreviewData.m @@ -16,7 +16,8 @@ */ #import "RoomPreviewData.h" -#import + +#import "GeneratedInterface-Swift.h" @implementation RoomPreviewData diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.h b/Riot/Modules/Authentication/Views/AuthInputsView.h index 684f44f66..79e30d638 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.h +++ b/Riot/Modules/Authentication/Views/AuthInputsView.h @@ -17,7 +17,7 @@ #import -#import "GeneratedInterface-Swift.h" +@class TermsView; @interface AuthInputsView : MXKAuthInputsView diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 68a79c202..d3b9c65b4 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -26,6 +26,8 @@ #import "RiotNavigationController.h" +#import "GeneratedInterface-Swift.h" + @interface AuthInputsView () { /** diff --git a/Riot/Modules/Common/Recents/Model/RecentCellData.m b/Riot/Modules/Common/Recents/Model/RecentCellData.m index 9697b85ea..01800996f 100644 --- a/Riot/Modules/Common/Recents/Model/RecentCellData.m +++ b/Riot/Modules/Common/Recents/Model/RecentCellData.m @@ -18,7 +18,6 @@ #import "RecentCellData.h" #import "MXRoom+Riot.h" -#import "MatrixSDK-Swift.h" #import "GeneratedInterface-Swift.h" diff --git a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m index d7af35024..f9dcf9ea2 100644 --- a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m +++ b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m @@ -18,6 +18,8 @@ #import "FilesSearchCellData.h" +#import "GeneratedInterface-Swift.h" + @implementation FilesSearchCellData @synthesize roomId, senderDisplayName; @synthesize searchResult, title, message, date, shouldShowRoomDisplayName, roomDisplayName, attachment, isAttachmentWithThumbnail, attachmentIcon; diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 697d67178..f73e211c3 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -24,7 +24,6 @@ #import "BubbleReactionsViewSizer.h" #import "GeneratedInterface-Swift.h" -#import static NSAttributedString *timestampVerticalWhitespace = nil; From 15d7dfcf6ac9b56a736297756a06b9cea98cc71f Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Thu, 25 Nov 2021 23:13:00 +0100 Subject: [PATCH 061/122] Update changes --- changelog.d/5194.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5194.bugfix diff --git a/changelog.d/5194.bugfix b/changelog.d/5194.bugfix new file mode 100644 index 000000000..56d98768e --- /dev/null +++ b/changelog.d/5194.bugfix @@ -0,0 +1 @@ +Improve generated Swift header imports. From 50c67b3b6c0faa4dc70e3320b1eb647e8c52d1c2 Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 26 Nov 2021 10:32:50 +0000 Subject: [PATCH 062/122] Don't allow concurrent initializations of MXBackgroundSyncService --- RiotNSE/NotificationService.swift | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 99a9bba12..214579e7e 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -67,6 +67,7 @@ class NotificationService: UNNotificationServiceExtension { private var pushNotificationStore: PushNotificationStore = PushNotificationStore() private let localAuthenticationService = LocalAuthenticationService(pinCodePreferences: .shared) + private let backgroundServiceInitQueue = DispatchQueue(label: "backgroundServiceInitQueue") // MARK: - Method Overrides override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { @@ -169,14 +170,16 @@ class NotificationService: UNNotificationServiceExtension { MXKAccountManager.shared()?.forceReloadAccounts() self.userAccount = MXKAccountManager.shared()?.activeAccounts.first if let userAccount = userAccount { - if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials { - MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE") - self.logMemory() - NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials) - MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: AFTER") - self.logMemory() + backgroundServiceInitQueue.sync { + if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials { + MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE") + self.logMemory() + NotificationService.backgroundSyncService = MXBackgroundSyncService(withCredentials: userAccount.mxCredentials) + MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: AFTER") + self.logMemory() + } + completion() } - completion() } else { MXLog.debug("[NotificationService] setup: No active accounts") fallbackToBestAttemptContent(forEventId: eventId) From 56086788900c47248e7bbf6e38fb5dae4c52e54e Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 26 Nov 2021 12:47:53 +0000 Subject: [PATCH 063/122] Make backgroundServiceInitQueue static and follow convention for queue naming. --- RiotNSE/NotificationService.swift | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 214579e7e..f6125baca 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -66,8 +66,7 @@ class NotificationService: UNNotificationServiceExtension { }() private var pushNotificationStore: PushNotificationStore = PushNotificationStore() private let localAuthenticationService = LocalAuthenticationService(pinCodePreferences: .shared) - - private let backgroundServiceInitQueue = DispatchQueue(label: "backgroundServiceInitQueue") + private static let backgroundServiceInitQueue = DispatchQueue(label: "io.element.NotificationService.backgroundServiceInitQueue") // MARK: - Method Overrides override func didReceive(_ request: UNNotificationRequest, withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void) { @@ -170,7 +169,7 @@ class NotificationService: UNNotificationServiceExtension { MXKAccountManager.shared()?.forceReloadAccounts() self.userAccount = MXKAccountManager.shared()?.activeAccounts.first if let userAccount = userAccount { - backgroundServiceInitQueue.sync { + Self.backgroundServiceInitQueue.sync { if NotificationService.backgroundSyncService?.credentials != userAccount.mxCredentials { MXLog.debug("[NotificationService] setup: MXBackgroundSyncService init: BEFORE") self.logMemory() From f3938739fab8d45ba4ad1635f606d81797654e87 Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 26 Nov 2021 12:52:40 +0000 Subject: [PATCH 064/122] Restore the pushkit token after login/logout when configuring PushKit --- Riot/Managers/PushNotification/PushNotificationService.m | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Riot/Managers/PushNotification/PushNotificationService.m b/Riot/Managers/PushNotification/PushNotificationService.m index fc6eab47d..4e22554af 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.m +++ b/Riot/Managers/PushNotification/PushNotificationService.m @@ -266,6 +266,15 @@ Matrix session observer used to detect new opened sessions. - (void)configurePushKit { MXLogDebug(@"[PushNotificationService] configurePushKit") + NSData* token = [_pushRegistry pushTokenForType:PKPushTypeVoIP]; + if (token) { + // If the token is available, store it. This can happen if you sign out and back in. + // i.e We are registered, but we have cleared it form the the store on logout and the + // _pushRegistry lives through signin/signout as PushNotificationService is a singleton + // on app delegate. + _pushNotificationStore.pushKitToken = token; + MXLogDebug(@"[PushNotificationService] configurePushKit: Restored pushKit token") + } _pushRegistry.delegate = self; _pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP]; From 5d618824b589a3f37ae1fd29dd3ec57fae548576 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 26 Nov 2021 14:39:00 +0100 Subject: [PATCH 065/122] MasterTabBarController: Don't use MXCrypto private property. --- Riot/Modules/TabBar/MasterTabBarController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/TabBar/MasterTabBarController.m b/Riot/Modules/TabBar/MasterTabBarController.m index f1afa5821..4a4751d83 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.m +++ b/Riot/Modules/TabBar/MasterTabBarController.m @@ -1021,7 +1021,7 @@ return; } - NSArray *devices = [session.crypto.store devicesForUser:session.myUserId].allValues; + NSArray *devices = [session.crypto devicesForUser:session.myUserId].allValues; BOOL isUserHasOneUnverifiedDevice = NO; From e15eb26872c4c9c49f232e122a702d919490647a Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 26 Nov 2021 15:25:36 +0100 Subject: [PATCH 066/122] SecurityViewController: Don't use private properties from SDK. --- Riot/Modules/Settings/Security/SecurityViewController.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Riot/Modules/Settings/Security/SecurityViewController.m b/Riot/Modules/Settings/Security/SecurityViewController.m index 9feda8f59..76a80fedc 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.m +++ b/Riot/Modules/Settings/Security/SecurityViewController.m @@ -169,9 +169,8 @@ TableViewSectionsDelegate> if (self.mainSession.crypto.backup) { - MXDeviceInfo *deviceInfo = [self.mainSession.crypto.deviceList storedDevice:self.mainSession.matrixRestClient.credentials.userId - deviceId:self.mainSession.matrixRestClient.credentials.deviceId]; - + MXDeviceInfo *deviceInfo = [self.mainSession.crypto deviceWithDeviceId:self.mainSession.myDeviceId ofUser:self.mainSession.myUserId]; + if (deviceInfo) { secureBackupSection = [[SettingsSecureBackupTableViewSection alloc] initWithRecoveryService:self.mainSession.crypto.recoveryService keyBackup:self.mainSession.crypto.backup userDevice:deviceInfo]; From 30d6cdc4051e513d1386a4be9b49af85b9c47e40 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Fri, 26 Nov 2021 15:26:34 +0100 Subject: [PATCH 067/122] LegacyAppDelegate: Don't use private interface from SDK. --- Riot/Modules/Application/LegacyAppDelegate.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 75060f84b..0a2aaed0e 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -2500,17 +2500,17 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni - (void)checkLocalPrivateKeysInSession:(MXSession*)mxSession { - id cryptoStore = mxSession.crypto.store; + MXRecoveryService *recoveryService = mxSession.crypto.recoveryService; NSUInteger keysCount = 0; - if ([cryptoStore secretWithSecretId:MXSecretId.keyBackup]) + if ([recoveryService hasSecretWithSecretId:MXSecretId.keyBackup]) { keysCount++; } - if ([cryptoStore secretWithSecretId:MXSecretId.crossSigningUserSigning]) + if ([recoveryService hasSecretWithSecretId:MXSecretId.crossSigningUserSigning]) { keysCount++; } - if ([cryptoStore secretWithSecretId:MXSecretId.crossSigningSelfSigning]) + if ([recoveryService hasSecretWithSecretId:MXSecretId.crossSigningSelfSigning]) { keysCount++; } From 45e4492bf951f2c19708bba43920f664d8c90daa Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 26 Nov 2021 14:38:28 +0000 Subject: [PATCH 068/122] Create 5199.bugfix --- changelog.d/5199.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/5199.bugfix diff --git a/changelog.d/5199.bugfix b/changelog.d/5199.bugfix new file mode 100644 index 000000000..d363f1449 --- /dev/null +++ b/changelog.d/5199.bugfix @@ -0,0 +1 @@ +Fix bug where VoIP calls would not connect reliably after signout/signin. From 67c22b9c5e3317e8f52954ea79e8474d867c4d48 Mon Sep 17 00:00:00 2001 From: David Langley Date: Fri, 26 Nov 2021 14:57:58 +0000 Subject: [PATCH 069/122] Update Riot/Managers/PushNotification/PushNotificationService.m Co-authored-by: ismailgulek --- Riot/Managers/PushNotification/PushNotificationService.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Managers/PushNotification/PushNotificationService.m b/Riot/Managers/PushNotification/PushNotificationService.m index 4e22554af..13db25148 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.m +++ b/Riot/Managers/PushNotification/PushNotificationService.m @@ -269,7 +269,7 @@ Matrix session observer used to detect new opened sessions. NSData* token = [_pushRegistry pushTokenForType:PKPushTypeVoIP]; if (token) { // If the token is available, store it. This can happen if you sign out and back in. - // i.e We are registered, but we have cleared it form the the store on logout and the + // i.e We are registered, but we have cleared it from the the store on logout and the // _pushRegistry lives through signin/signout as PushNotificationService is a singleton // on app delegate. _pushNotificationStore.pushKitToken = token; From 8803061b3c3d75a8efa9b1063adfc7184eaf8816 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:20:17 +0100 Subject: [PATCH 070/122] Riot target: Exclude markdown files from MatrixKit folder. --- Riot/target.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Riot/target.yml b/Riot/target.yml index 9775d4b88..aaac28a9b 100644 --- a/Riot/target.yml +++ b/Riot/target.yml @@ -67,6 +67,9 @@ targets: - "Modules/Room/EmojiPicker/Data/EmojiMart/EmojiJSONStore.swift" - "**/*.strings" # Exclude all strings files - path: ../RiotShareExtension/Shared + - path: Modules/MatrixKit + excludes: + - "**/*.md" # excludes all files with the .md extension # Add separately localizable files # Once a language has enough translations (>80%), it must be declared here From fee09050cb88591efcc98afb380d8acf20711730 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:22:33 +0100 Subject: [PATCH 071/122] SiriIntents: Add bridging header. --- SiriIntents/Common.xcconfig | 2 ++ .../SiriIntents-Bridging-Header.h | 17 +++++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 SiriIntents/SupportingFiles/SiriIntents-Bridging-Header.h diff --git a/SiriIntents/Common.xcconfig b/SiriIntents/Common.xcconfig index f112dcf97..13f54f302 100644 --- a/SiriIntents/Common.xcconfig +++ b/SiriIntents/Common.xcconfig @@ -30,4 +30,6 @@ CODE_SIGN_ENTITLEMENTS = SiriIntents/SiriIntents.entitlements LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @executable_path/../../Frameworks SKIP_INSTALL = YES +SWIFT_OBJC_BRIDGING_HEADER = $(SRCROOT)/$(PRODUCT_NAME)/SupportingFiles/SiriIntents-Bridging-Header.h + SWIFT_OBJC_INTERFACE_HEADER_NAME = GeneratedInterface-Swift.h diff --git a/SiriIntents/SupportingFiles/SiriIntents-Bridging-Header.h b/SiriIntents/SupportingFiles/SiriIntents-Bridging-Header.h new file mode 100644 index 000000000..306e2e582 --- /dev/null +++ b/SiriIntents/SupportingFiles/SiriIntents-Bridging-Header.h @@ -0,0 +1,17 @@ +// +// Copyright 2021 New Vector Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +#import "MatrixKit-Bridging-Header.h" From 751e7aac745181b684b58ff34b6dec7a184bbab6 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:24:03 +0100 Subject: [PATCH 072/122] SiriIntents target: Handle new MatrixKit location. --- SiriIntents/target.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/SiriIntents/target.yml b/SiriIntents/target.yml index 01b844632..05aea0ea9 100644 --- a/SiriIntents/target.yml +++ b/SiriIntents/target.yml @@ -48,3 +48,9 @@ targets: - path: ../Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift - path: ../Riot/Managers/KeyValueStorage - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift + - path: ../Riot/Managers/Locale/LocaleProviderType.swift + - path: ../Riot/Managers/Locale/LocaleProvider.swift + - path: ../Riot/Modules/MatrixKit + excludes: + - "**/*.md" # excludes all files with the .md extension + - path: ../Riot/Generated/MatrixKitStrings.swift From 1754469302dfb3214338b0bc8a7b5394c2a97190 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:25:31 +0100 Subject: [PATCH 073/122] SwiftGen: Handle MatrixKit strings. --- Tools/SwiftGen/swiftgen-config.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Tools/SwiftGen/swiftgen-config.yml b/Tools/SwiftGen/swiftgen-config.yml index 2a4015052..e8a00a129 100755 --- a/Tools/SwiftGen/swiftgen-config.yml +++ b/Tools/SwiftGen/swiftgen-config.yml @@ -16,6 +16,14 @@ strings: params: className: VectorL10n publicAccess: true +strings: + inputs: Modules/MatrixKit/Assets/MatrixKitAssets.bundle/en.lproj/MatrixKit.strings + outputs: + templatePath: Templates/Strings/flat-swift4-vector.stencil + output: MatrixKitStrings.swift + params: + className: MatrixKitL10n + publicAccess: true xcassets: inputs: - Assets/Images.xcassets From 309c3f9729a8c98a430d068b7597ef38e3773308 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:28:35 +0100 Subject: [PATCH 074/122] Share extension target: Handle new MatrixKit location. --- RiotShareExtension/target.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RiotShareExtension/target.yml b/RiotShareExtension/target.yml index a02fc10ca..7f32196f4 100644 --- a/RiotShareExtension/target.yml +++ b/RiotShareExtension/target.yml @@ -68,3 +68,7 @@ targets: buildPhase: resources - path: ../Riot/Assets/SharedImages.xcassets buildPhase: resources + - path: ../Riot/Modules/MatrixKit + excludes: + - "**/*.md" # excludes all files with the .md extension + - path: ../Riot/Generated/MatrixKitStrings.swift From bdae669000d1c27e07696d5ee25ad293d37964b3 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:31:48 +0100 Subject: [PATCH 075/122] Share extension: Add MatrixKit bridging header. --- .../SupportingFiles/RiotShareExtension-Bridging-Header.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h b/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h index cf576b194..9a7cf3af1 100644 --- a/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h +++ b/RiotShareExtension/SupportingFiles/RiotShareExtension-Bridging-Header.h @@ -6,3 +6,6 @@ #import "AvatarGenerator.h" #import "BuildInfo.h" #import "ShareItemSender.h" + +// MatrixKit imports +#import "MatrixKit-Bridging-Header.h" From eb696ea34fe6e3bf96730a6d0f139d5ef8409ab1 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:33:36 +0100 Subject: [PATCH 076/122] NSE target: Handle new MatrixKit location. --- RiotNSE/target.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RiotNSE/target.yml b/RiotNSE/target.yml index 84aa3f64b..f01b619a3 100644 --- a/RiotNSE/target.yml +++ b/RiotNSE/target.yml @@ -61,3 +61,7 @@ targets: - path: ../Riot/Categories/Character.swift - path: ../Riot/Managers/Widgets/WidgetConstants.m - path: ../Riot/PropertyWrappers/UserDefaultsBackedPropertyWrapper.swift + - path: ../Riot/Modules/MatrixKit + excludes: + - "**/*.md" # excludes all files with the .md extension + - path: ../Riot/Generated/MatrixKitStrings.swift From e2b85ef907818cf4aa5c9ece2e78d888dc1b091b Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:34:57 +0100 Subject: [PATCH 077/122] NSE: Import MatrixKit bridging header. --- RiotNSE/SupportingFiles/RiotNSE-Bridging-Header.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RiotNSE/SupportingFiles/RiotNSE-Bridging-Header.h b/RiotNSE/SupportingFiles/RiotNSE-Bridging-Header.h index aa38f8734..41b0ba485 100644 --- a/RiotNSE/SupportingFiles/RiotNSE-Bridging-Header.h +++ b/RiotNSE/SupportingFiles/RiotNSE-Bridging-Header.h @@ -19,4 +19,6 @@ #import "WidgetConstants.h" +#import "MatrixKit-Bridging-Header.h" + #endif /* RiotNSE_Bridging_Header_h */ From e3de692c857dd3b276f8f0c6a01326f4ee240782 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:45:35 +0100 Subject: [PATCH 078/122] Remove unnecessary MatrixKit imports. --- Riot/Categories/UINavigationController+Riot.h | 4 ++-- Riot/Categories/UIViewController+RiotSearch.h | 4 ++-- Riot/Managers/Theme/ThemeService.h | 2 +- Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h | 1 - Riot/Utils/Tools.h | 3 +-- 5 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Riot/Categories/UINavigationController+Riot.h b/Riot/Categories/UINavigationController+Riot.h index e5632e7d7..6e82c2b3e 100644 --- a/Riot/Categories/UINavigationController+Riot.h +++ b/Riot/Categories/UINavigationController+Riot.h @@ -15,12 +15,12 @@ limitations under the License. */ -#import - /** The `UINavigationController` category overrides the default auto rotation handling. */ +#import + @interface UINavigationController (Riot) @end diff --git a/Riot/Categories/UIViewController+RiotSearch.h b/Riot/Categories/UIViewController+RiotSearch.h index fd077f18d..db29e0183 100644 --- a/Riot/Categories/UIViewController+RiotSearch.h +++ b/Riot/Categories/UIViewController+RiotSearch.h @@ -15,12 +15,12 @@ limitations under the License. */ -#import - /** The `RiotSearch` category adds the management of the search bar in Riot screens. */ +#import + @interface UIViewController (RiotSearch) /** diff --git a/Riot/Managers/Theme/ThemeService.h b/Riot/Managers/Theme/ThemeService.h index 7fcaff121..24e01f82f 100644 --- a/Riot/Managers/Theme/ThemeService.h +++ b/Riot/Managers/Theme/ThemeService.h @@ -16,7 +16,7 @@ limitations under the License. */ -#import +#import @protocol Theme; diff --git a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h index 92358b5a8..be19d7b71 100644 --- a/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h +++ b/Riot/Modules/RoomKeyRequest/RoomKeyRequestViewController.h @@ -17,7 +17,6 @@ #import #import -#import /** The `RoomKeyRequestViewController` display a modal dialog at the top of the diff --git a/Riot/Utils/Tools.h b/Riot/Utils/Tools.h index 2ac18f8bb..2d411a716 100644 --- a/Riot/Utils/Tools.h +++ b/Riot/Utils/Tools.h @@ -15,8 +15,7 @@ */ #import - -#import "MatrixKit/MatrixKit.h" +#import @interface Tools : NSObject From fe84f0d862985d8138837555cc6c8a0e3571803c Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:50:30 +0100 Subject: [PATCH 079/122] Remove MatrixKit import from Swift files. --- Config/AppConfiguration.swift | 1 - Config/BuildSettings.swift | 2 -- Config/CommonConfiguration.swift | 2 +- Config/Configurable.swift | 4 +--- Riot/Managers/Call/CallPresenter.swift | 1 - Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift | 2 +- .../LocalAuthentication/LocalAuthenticationService.swift | 1 - .../Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift | 1 - RiotNSE/NotificationService.swift | 1 - .../Sources/ShareExtensionShareItemProvider.swift | 1 - 10 files changed, 3 insertions(+), 13 deletions(-) diff --git a/Config/AppConfiguration.swift b/Config/AppConfiguration.swift index 597876852..52b041656 100644 --- a/Config/AppConfiguration.swift +++ b/Config/AppConfiguration.swift @@ -15,7 +15,6 @@ // import Foundation -import MatrixKit /// AppConfiguration is CommonConfiguration plus configurations dedicated to the app class AppConfiguration: CommonConfiguration { diff --git a/Config/BuildSettings.swift b/Config/BuildSettings.swift index 44c32742c..0919c08fd 100644 --- a/Config/BuildSettings.swift +++ b/Config/BuildSettings.swift @@ -16,8 +16,6 @@ import Foundation -import MatrixKit - /// BuildSettings provides settings computed at build time. /// In future, it may be automatically generated from xcconfig files @objcMembers diff --git a/Config/CommonConfiguration.swift b/Config/CommonConfiguration.swift index f2e4b68dc..5edcacc37 100644 --- a/Config/CommonConfiguration.swift +++ b/Config/CommonConfiguration.swift @@ -15,7 +15,7 @@ // import Foundation -import MatrixKit +import MatrixSDK /// CommonConfiguration is the central point to setup settings for MatrixSDK, MatrixKit and common configurations for all targets. class CommonConfiguration: NSObject, Configurable { diff --git a/Config/Configurable.swift b/Config/Configurable.swift index a5a6d980e..acfb97605 100644 --- a/Config/Configurable.swift +++ b/Config/Configurable.swift @@ -15,9 +15,7 @@ // import Foundation - -import Foundation -import MatrixKit +import MatrixSDK /// Configurable expose settings app and its entensions must use. @objc protocol Configurable { diff --git a/Riot/Managers/Call/CallPresenter.swift b/Riot/Managers/Call/CallPresenter.swift index c0d286ab9..4a08f0e45 100644 --- a/Riot/Managers/Call/CallPresenter.swift +++ b/Riot/Managers/Call/CallPresenter.swift @@ -15,7 +15,6 @@ // import Foundation -import MatrixKit // swiftlint:disable file_length diff --git a/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift b/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift index 3203fdf11..5085e9efb 100644 --- a/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift +++ b/Riot/Managers/EncryptionKeyManager/EncryptionKeyManager.swift @@ -16,8 +16,8 @@ import UIKit import KeychainAccess -import MatrixKit import CommonCrypto +import MatrixSDK @objcMembers class EncryptionKeyManager: NSObject, MXKeyProviderDelegate { diff --git a/Riot/Managers/LocalAuthentication/LocalAuthenticationService.swift b/Riot/Managers/LocalAuthentication/LocalAuthenticationService.swift index 14e97094b..83b9ec265 100644 --- a/Riot/Managers/LocalAuthentication/LocalAuthenticationService.swift +++ b/Riot/Managers/LocalAuthentication/LocalAuthenticationService.swift @@ -15,7 +15,6 @@ // import Foundation -import MatrixKit @objcMembers class LocalAuthenticationService: NSObject { diff --git a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift index 51b47e9a3..6c0db2280 100644 --- a/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift +++ b/Riot/Modules/Room/Views/BubbleCells/BaseBubbleCell/BaseBubbleCell.swift @@ -15,7 +15,6 @@ limitations under the License. */ import UIKit -import MatrixKit @objc protocol BaseBubbleCellType: Themable { var bubbleCellContentView: BubbleCellContentView? { get } diff --git a/RiotNSE/NotificationService.swift b/RiotNSE/NotificationService.swift index 99a9bba12..26617c52e 100644 --- a/RiotNSE/NotificationService.swift +++ b/RiotNSE/NotificationService.swift @@ -15,7 +15,6 @@ */ import UserNotifications -import MatrixKit import MatrixSDK /// The number of milliseconds in one second. diff --git a/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift b/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift index 7ef463d81..1ef2f4bbf 100644 --- a/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift +++ b/RiotShareExtension/Sources/ShareExtensionShareItemProvider.swift @@ -16,7 +16,6 @@ import Foundation import MobileCoreServices -import MatrixKit private class ShareExtensionItem: ShareItemProtocol { let itemProvider: NSItemProvider From 0094db4425ff462c369e415a6092bab0f443239b Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:51:22 +0100 Subject: [PATCH 080/122] AvatarGenerator: Remove unnecessary MatrixKit import. --- Riot/Utils/AvatarGenerator.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Utils/AvatarGenerator.h b/Riot/Utils/AvatarGenerator.h index 1c1625c78..2bd981d99 100644 --- a/Riot/Utils/AvatarGenerator.h +++ b/Riot/Utils/AvatarGenerator.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import /** `AvatarGenerator` class generate an avatar image from objects From 6266b6d77253c6c43bf9c0c7f066ce6fda8846c2 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Mon, 29 Nov 2021 17:56:31 +0100 Subject: [PATCH 081/122] MXKRoomBubbleTableViewCell+Riot: Fix constant defined twice. --- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h | 5 ----- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m | 1 - 2 files changed, 6 deletions(-) diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h index 91b69a123..491401fe1 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h @@ -39,11 +39,6 @@ extern NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer; */ extern NSString *const kMXKRoomBubbleCellLongPressOnReactionView; -/** - 'userInfo' dictionary key 'kMXKRoomBubbleCellEventIdKey' is associated to a 'NSString' object representing an event id. - */ -extern NSString *const kMXKRoomBubbleCellEventIdKey; - /** Action identifier used when the user pressed accept button for an incoming key verification request. diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index d5b58eb11..25499c2d6 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -30,7 +30,6 @@ NSString *const kMXKRoomBubbleCellRiotEditButtonPressed = @"kMXKRoomBubbleCellRiotEditButtonPressed"; NSString *const kMXKRoomBubbleCellTapOnReceiptsContainer = @"kMXKRoomBubbleCellTapOnReceiptsContainer"; NSString *const kMXKRoomBubbleCellLongPressOnReactionView = @"kMXKRoomBubbleCellLongPressOnReactionView"; -NSString *const kMXKRoomBubbleCellEventIdKey = @"kMXKRoomBubbleCellEventIdKey"; NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestAcceptPressed = @"kMXKRoomBubbleCellKeyVerificationAcceptPressed"; NSString *const kMXKRoomBubbleCellKeyVerificationIncomingRequestDeclinePressed = @"kMXKRoomBubbleCellKeyVerificationDeclinePressed"; From 84b4f80f95505468bf57134c3c47a5e5412c19f3 Mon Sep 17 00:00:00 2001 From: jelv Date: Mon, 29 Nov 2021 09:02:18 +0000 Subject: [PATCH 082/122] Translated using Weblate (Dutch) Currently translated at 100.0% (1330 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/nl/ --- Riot/Assets/nl.lproj/Vector.strings | 32 ++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Riot/Assets/nl.lproj/Vector.strings b/Riot/Assets/nl.lproj/Vector.strings index f08f1d901..3e1e99512 100644 --- a/Riot/Assets/nl.lproj/Vector.strings +++ b/Riot/Assets/nl.lproj/Vector.strings @@ -564,7 +564,7 @@ "room_message_reply_to_short_placeholder" = "Stuur een antwoord…"; // String for App Store "store_short_description" = "Veilig en gedecentraliseerd chatten en bellen"; -"store_full_description" = "Element is een nieuw type messenger en samenwerkings app die:\n\n1. U de controle geeft om uw privacy te behouden\n2. U laat communiceren met iedereen in het Matrix-netwerk, en zelfs daarbuiten door integratie met apps zoals Slack\n3. Beschermt u tegen reclame, datamining, achterdeurtjes en ommuurde netwerken\n4. Beveiligt u door eind-tot-eind versleuteling, met kruislings ondertekenen om anderen te verifiëren\n\nElement is compleet anders dan andere messengers en samenwerkings-apps, omdat het gedecentraliseerd en open source is.\n\nMet Element kunt u zelf hosten - of een host kiezen - zodat u privacy, eigendom en controle heeft over uw gegevens en gesprekken. Het geeft u toegang tot een open netwerk; u zit dus niet vast aan het praten met alleen andere Element-gebruikers. En het is zeer veilig.\n\nElement is hiertoe in staat omdat het werkt op basis van Matrix - de standaard voor open, gedecentraliseerde communicatie. \n\nElement geeft u de controle door u te laten kiezen wie uw gesprekken host. Vanuit de Element app kunt u kiezen om op verschillende manieren te hosten:\n\n1. Neem een gratis account op de publieke server matrix.org\n2. Host het zelf, uw account door draait op uw eigen server\n3. Laat ons het hosten, meld u aan voor een account op een aangepaste server bij het Element Matrix Services hosting platform\n\nWaarom kiest u voor Element?\n\nEIGENAAR VAN UW GEGEVENS: U bepaalt waar uw gegevens en berichten worden bewaard. U bent de eigenaar en heeft de controle, niet een of andere MEGACORP die uw gegevens mijnt of toegang geeft aan derden.\n\nOPEN MESSAGING EN SAMENWERKING: U kunt met iedereen in het Matrix-netwerk chatten, of ze nu Element of een andere Matrix-app gebruiken, en zelfs als ze een ander messaging-systeem gebruiken zoals Slack, IRC of XMPP.\n\nSUPER-VEILIG: Echte eind-tot-eind versleuteling (alleen degenen in de conversatie kunnen berichten ontsleutelen), en kruislings ondertekenen om de apparaten van gespreksdeelnemers te verifiëren.\n\nCOMPLETE COMMUNICATIE: Berichten, spraak- en videogesprekken, bestandsdeling, schermdeling en een heleboel integraties, bots en widgets. Bouw kamers, ruimtes, blijf in contact en krijg het gedaan.\n\nOVERAL WAAR U BENT: Blijf in contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten en op het web op https://element.io/app."; +"store_full_description" = "Element is een nieuw type messenger en samenwerkings app die:\n\n1. U de controle geeft om uw privacy te behouden\n2. U laat communiceren met iedereen in het Matrix-netwerk, en zelfs daarbuiten door integratie met apps zoals Slack\n3. Beschermt u tegen reclame, datamining, achterdeurtjes en ommuurde netwerken\n4. Beveiligt u door eind-tot-eind versleuteling, met kruislings ondertekenen om anderen te verifiëren\n\nElement is compleet anders dan andere messengers en samenwerkings-apps, omdat het gedecentraliseerd en open source is.\n\nMet Element kunt u zelf hosten - of een host kiezen - zodat u privacy, eigendom en controle heeft over uw gegevens en gesprekken. Het geeft u toegang tot een open netwerk; u zit dus niet vast aan het praten met alleen andere Element-gebruikers. En het is zeer veilig.\n\nElement is hiertoe in staat omdat het werkt op basis van Matrix - de standaard voor open, gedecentraliseerde communicatie. \n\nElement geeft u de controle door u te laten kiezen wie uw gesprekken host. Vanuit de Element app kunt u kiezen om op verschillende manieren te hosten:\n\n1. Neem een gratis account op de publieke server matrix.org\n2. Host het zelf, uw account door draait op uw eigen server\n3. Laat ons het hosten, meld u aan voor een account op een aangepaste server bij het Element Matrix Services hosting platform\n\nWaarom kiest u voor Element?\n\nEIGENAAR VAN UW GEGEVENS: U bepaalt waar uw gegevens en berichten worden bewaard. U bent de eigenaar en heeft de controle, niet een of andere MEGACORP die uw gegevens mijnt of toegang geeft aan derden.\n\nOPEN MESSAGING EN SAMENWERKING: U kunt met iedereen in het Matrix-netwerk chatten, of ze nu Element of een andere Matrix-app gebruiken, en zelfs als ze een ander messaging-systeem gebruiken zoals Slack, IRC of XMPP.\n\nSUPER-VEILIG: Echte eind-tot-eind versleuteling (alleen degenen in de conversatie kunnen berichten ontsleutelen), en kruislings ondertekenen om de apparaten van gespreksdeelnemers te verifiëren.\n\nCOMPLETE COMMUNICATIE: Berichten, spraak- en videogesprekken, bestandsdeling, schermdeling en een heleboel integraties, bots en widgets. Bouw kamers, Spaces, blijf in contact en krijg het gedaan.\n\nOVERAL WAAR U BENT: Blijf in contact waar u ook bent met volledig gesynchroniseerde berichtgeschiedenis op al uw apparaten en op het web op https://element.io/app."; "auth_login_single_sign_on" = "Aanmelden met enkele aanmelding"; "auth_accept_policies" = "Gelieve het beleid van deze server te lezen en aanvaarden:"; "auth_autodiscover_invalid_response" = "Ongeldig server-ontdekkings-antwoord"; @@ -1469,16 +1469,16 @@ // Chat "room_slide_to_end_group_call" = "Schuif om voor iedereen de oproep te beëindigen"; -"space_beta_announce_information" = "Ruimtes zijn de nieuwe manier om kamers en personen te groeperen. Dit is nog niet beschikbaar op iOS, maar u kunt ze nu al gebruiken op Web en Desktop."; -"space_feature_unavailable_information" = "Ruimtes zijn de nieuwe manier om kamers en personen te groeperen. \n\nHet is binnenkort beschikbaar. U kan aan ruimtes deelnemen via andere platformen en die kamers worden dan hier beschikbaar."; +"space_beta_announce_information" = "Spaces zijn de nieuwe manier om kamers en personen te groeperen. Dit is nog niet beschikbaar op iOS, maar u kunt ze nu al gebruiken op Web en Desktop."; +"space_feature_unavailable_information" = "Spaces zijn de nieuwe manier om kamers en personen te groeperen. \n\nHet is binnenkort beschikbaar. U kan aan Spaces deelnemen via andere platformen en die kamers worden dan hier beschikbaar."; "space_beta_announce_subtitle" = "De nieuwe versie van gemeenschappen"; -"space_beta_announce_title" = "Ruimtes komen binnenkort"; +"space_beta_announce_title" = "Spaces komen binnenkort"; "space_beta_announce_badge" = "BETA"; -"space_feature_unavailable_subtitle" = "Ruimtes zijn nog niet beschikbaar op iOS, maar u kunt het nu al testen op Web en Desktop"; +"space_feature_unavailable_subtitle" = "Spaces zijn nog niet beschikbaar op iOS, maar u kunt het nu al testen op Web en Desktop"; // Mark: - Spaces -"space_feature_unavailable_title" = "Ruimtes zijn nog niet klaar"; +"space_feature_unavailable_title" = "Spaces zijn nog niet klaar"; "side_menu_app_version" = "Versie %@"; "side_menu_action_feedback" = "Feedback"; "side_menu_action_help" = "Help"; @@ -1574,14 +1574,14 @@ "settings_confirm_media_size_description" = "Wanneer dit aan staat wordt u elke keer gevraagd welk formaat afbeeldingen en video's u wilt versturen."; "settings_confirm_media_size" = "Bevestig afmeting bij versturen"; "settings_sending_media" = "AFBEELDINGEN EN VIDEO'S VERSTUREN"; -"space_avatar_view_accessibility_hint" = "Ruimte-afbeelding wijzigen"; +"space_avatar_view_accessibility_hint" = "Space-afbeelding wijzigen"; // Mark: Avatar "space_avatar_view_accessibility_label" = "afbeelding"; -"space_public_join_rule" = "Publieke ruimte"; -"space_private_join_rule" = "Privéruimte"; -"space_participants_action_ban" = "Uit deze ruimte verbannen"; +"space_public_join_rule" = "Publieke Space"; +"space_private_join_rule" = "Privé Space"; +"space_participants_action_ban" = "Uit deze Space verbannen"; "space_participants_action_remove" = "Uit deze kamer verwijderen"; "spaces_coming_soon_detail" = "Deze functies is nog niet klaar, maar er wordt aan gewerkt. Voor nu kan u dit wel doen met Element via uw computer."; "spaces_invites_coming_soon_title" = "Uitnodigen komt binnenkort"; @@ -1591,15 +1591,15 @@ "spaces_no_room_found_detail" = "Sommige resultaten kunnen verborgen zijn doordat ze privé zijn. U heeft dan een uitnodiging nodig om deel te nemen."; "spaces_empty_space_detail" = "Sommige kamers kunnen verborgen zijn doordat ze privé zijn. U heeft dan een uitnodiging nodig om deel te nemen."; "spaces_no_result_found_title" = "Geen resultaten gevonden"; -"spaces_empty_space_title" = "Deze ruimte heeft (nog) geen kamers"; -"space_tag" = "ruimte"; +"spaces_empty_space_title" = "Deze Space heeft (nog) geen kamers"; +"space_tag" = "space"; "spaces_explore_rooms" = "Kamers ontdekken"; -"leave_space_and_all_rooms_action" = "Alle kamers en ruimtes verlaten"; +"leave_space_and_all_rooms_action" = "Alle kamers en Spaces verlaten"; "leave_space_only_action" = "Geen kamers verlaten"; -"leave_space_message_admin_warning" = "U bent beheerder van deze ruimte, controleer of u de beheerrechten heeft overgedragen aan een andere deelnemer voordat u vertrekt."; -"leave_space_message" = "Weet u zeker dat u %@ wilt verlaten? Wilt u ook alle kamers en ruimtes in deze ruimte verlaten?"; +"leave_space_message_admin_warning" = "U bent beheerder van deze Space, controleer of u de beheerrechten heeft overgedragen aan een andere deelnemer voordat u vertrekt."; +"leave_space_message" = "Weet u zeker dat u %@ wilt verlaten? Wilt u ook alle kamers en Spaces in deze Space verlaten?"; "leave_space_title" = "%@ verlaten"; -"spaces_left_panel_title" = "Ruimtes"; +"spaces_left_panel_title" = "Spaces"; "spaces_home_space_title" = "Thuis"; "settings_links" = "LINKS"; "room_recents_suggested_rooms_section" = "AANBEVOLEN KAMERS"; From 0b0e80ed73c05fe39b6f0851251bffb36c5e6384 Mon Sep 17 00:00:00 2001 From: SiderealArt Date: Sun, 28 Nov 2021 13:37:50 +0000 Subject: [PATCH 083/122] Translated using Weblate (Chinese (Traditional)) Currently translated at 59.9% (797 of 1330 strings) Translation: Element iOS/Element iOS Translate-URL: https://translate.element.io/projects/riot-ios/riot-ios/zh_Hant/ --- Riot/Assets/zh_Hant.lproj/Vector.strings | 256 ++++++++++++++++++++++- 1 file changed, 251 insertions(+), 5 deletions(-) diff --git a/Riot/Assets/zh_Hant.lproj/Vector.strings b/Riot/Assets/zh_Hant.lproj/Vector.strings index dea57af66..327f1ae02 100644 --- a/Riot/Assets/zh_Hant.lproj/Vector.strings +++ b/Riot/Assets/zh_Hant.lproj/Vector.strings @@ -181,7 +181,7 @@ "room_creation_keep_private" = "維持私人"; "room_creation_make_private" = "設成私人"; "room_creation_wait_for_creation" = "聊天室正在建立,請稍後。"; -"room_creation_invite_another_user" = "透過使用者ID、名稱、電子郵件地址來搜尋/邀請"; +"room_creation_invite_another_user" = "使用者 ID、名稱、或電子郵件地址"; // Room recents "room_recents_directory_section" = "聊天室目錄"; "room_recents_favourites_section" = "收藏夾"; @@ -258,7 +258,7 @@ "room_participants_action_start_video_call" = "開始視訊通話"; "room_event_action_view_encryption" = "加密資訊"; // Chat -"room_jump_to_first_unread" = "跳到第一條未讀訊息"; +"room_jump_to_first_unread" = "跳到未讀訊息"; "room_new_message_notification" = "%d 條未讀訊息"; "room_new_messages_notification" = "%d 條未讀訊息"; "room_one_user_is_typing" = "%@ 正在輸入…"; @@ -318,7 +318,7 @@ "settings_calls_settings" = "通話"; "settings_user_interface" = "使用者介面"; "settings_ignored_users" = "已忽略使用者"; -"settings_contacts" = "本地聯絡人"; +"settings_contacts" = "裝置聯絡人"; "settings_advanced" = "進階"; "settings_other" = "其他"; "settings_labs" = "實驗室"; @@ -383,7 +383,7 @@ "settings_deactivate_my_account" = "註銷我的帳號"; // Room Details "room_details_title" = "聊天室詳細資料"; -"room_details_files" = "文件"; +"room_details_files" = "上傳"; "room_details_settings" = "設定"; "room_details_photo" = "聊天室圖片"; "room_details_room_name" = "聊天室名稱"; @@ -615,7 +615,7 @@ "auth_add_email_phone_message_2" = "設置一個電子郵件以便日後恢復帳戶和使以後可以由認識您的人發現你。"; "auth_add_email_message_2" = "設置一個電子郵件以便日後恢復帳戶和使以後可以由認識您的人發現你。"; "auth_add_phone_message_2" = "設置一個電話號碼,以後可以由認識您的人發現你。"; -"auth_login_single_sign_on" = "以單一登入方式登入"; +"auth_login_single_sign_on" = "登入"; // Accessibility "accessibility_checkbox_label" = "複選框"; @@ -661,3 +661,249 @@ "rooms_empty_view_title" = "聊天室"; "people_empty_view_information" = "和任何人安全地通話。按 + 添加聯絡人。"; "people_empty_view_title" = "聯絡人"; + +// MARK: - Room Info + +"room_info_list_one_member" = "1 位成員"; +"biometrics_mode_face_id" = "Face ID"; + +// MARK: - PIN Protection + +"pin_protection_choose_pin_welcome_after_login" = "歡迎回來。"; +"major_update_done_action" = "了解了"; +"major_update_learn_more_action" = "了解詳情"; + +// Scanned +"key_verification_scan_confirmation_scanned_title" = "就快完成了!"; + +// MARK: File upload +"file_upload_error_title" = "上傳檔案"; +"device_verification_emoji_light bulb" = "燈泡"; +"device_verification_emoji_thumbs up" = "讚"; +"device_verification_verified_got_it_button" = "了解了"; +"side_menu_action_feedback" = "反饋"; +"side_menu_action_help" = "協助"; +"side_menu_action_settings" = "設定"; +"room_intro_cell_information_dm_sentence1_part3" = ". "; +"room_intro_cell_information_room_sentence1_part3" = ". "; +"call_transfer_error_title" = "錯誤"; +"call_transfer_contacts_all" = "全部"; +"call_transfer_contacts_recent" = "最近"; +"call_transfer_users" = "使用者"; + +// MARK: - Call Transfer +"call_transfer_title" = "傳輸"; +"room_info_list_section_other" = "其他"; +"create_room_placeholder_topic" = "主題"; +"create_room_placeholder_name" = "名稱"; +"biometrics_cant_unlocked_alert_message_retry" = "重試"; +"pin_protection_reset_alert_action_reset" = "重設"; +"pin_protection_choose_pin_welcome_after_register" = "歡迎。"; +"secrets_reset_reset_action" = "重設"; +"secrets_setup_recovery_passphrase_confirm_passphrase_title" = "確認"; +"secrets_setup_recovery_passphrase_validate_action" = "完成"; +"room_message_editing" = "正在編輯"; +"secrets_setup_recovery_key_done_action" = "完成"; +"secrets_setup_recovery_key_export_action" = "儲存"; +"secrets_setup_recovery_key_loading" = "正在載入…"; +"secrets_recovery_with_key_recovery_key_title" = "輸入"; +"secrets_recovery_with_passphrase_lost_passphrase_action_part3" = "."; +"secrets_recovery_with_passphrase_passphrase_title" = "輸入"; +"user_verification_sessions_list_table_title" = "工作階段"; +"user_verification_sessions_list_user_trust_level_unknown_title" = "未知"; +"user_verification_sessions_list_user_trust_level_warning_title" = "警告"; + +// MARK: - Key Verification + +"key_verification_bootstrap_not_setup_title" = "錯誤"; +"key_verification_tile_request_incoming_approval_decline" = "拒絕"; +"key_verification_tile_request_incoming_approval_accept" = "接受"; + +// MARK: Reaction history +"reaction_history_title" = "反應"; +"emoji_picker_objects_category" = "物件"; +"emoji_picker_activity_category" = "活動"; + +// MARK: Emoji picker +"emoji_picker_title" = "反應"; +"device_verification_emoji_pin" = "釘選"; +"device_verification_emoji_folder" = "資料夾"; +"device_verification_emoji_headphones" = "耳機"; +"device_verification_emoji_anchor" = "錨"; +"device_verification_emoji_bell" = "鐘"; +"device_verification_emoji_trumpet" = "喇叭"; +"device_verification_emoji_guitar" = "吉他"; +"device_verification_emoji_ball" = "球"; +"device_verification_emoji_trophy" = "獎盃"; +"device_verification_emoji_rocket" = "火箭"; +"device_verification_emoji_aeroplane" = "飛機"; +"device_verification_emoji_bicycle" = "腳踏車"; +"device_verification_emoji_train" = "火車"; +"device_verification_emoji_flag" = "旗幟"; +"device_verification_emoji_telephone" = "電話"; +"device_verification_emoji_hammer" = "槌子"; +"device_verification_emoji_key" = "鑰匙"; +"device_verification_emoji_scissors" = "剪刀"; +"device_verification_emoji_paperclip" = "迴紋針"; +"device_verification_emoji_pencil" = "鉛筆"; +"device_verification_emoji_book" = "書"; +"device_verification_emoji_gift" = "禮物"; +"device_verification_emoji_clock" = "時鐘"; +"device_verification_emoji_hourglass" = "沙漏"; +"device_verification_emoji_umbrella" = "雨傘"; +"device_verification_emoji_santa" = "聖誕老人"; +"device_verification_emoji_glasses" = "眼鏡"; +"device_verification_emoji_hat" = "帽子"; +"device_verification_emoji_robot" = "機器人"; +"device_verification_emoji_smiley" = "笑臉"; +"device_verification_emoji_cloud" = "雲朵"; +"device_verification_emoji_apple" = "蘋果"; +"device_verification_emoji_heart" = "愛心"; +"device_verification_emoji_cake" = "蛋糕"; +"device_verification_emoji_pizza" = "披薩"; +"device_verification_emoji_corn" = "玉米"; +"device_verification_emoji_strawberry" = "草莓"; +"device_verification_emoji_banana" = "香蕉"; +"device_verification_emoji_fire" = "火"; +"device_verification_emoji_moon" = "月亮"; +"device_verification_emoji_mushroom" = "蘑菇"; +"device_verification_emoji_cactus" = "仙人掌"; +"device_verification_emoji_tree" = "樹"; +"device_verification_emoji_flower" = "花"; +"device_verification_emoji_butterfly" = "蝴蝶"; +"device_verification_emoji_octopus" = "章魚"; +"device_verification_emoji_fish" = "魚"; +"device_verification_emoji_turtle" = "烏龜"; +"device_verification_emoji_penguin" = "企鵝"; +"device_verification_emoji_rooster" = "公雞"; +"device_verification_emoji_panda" = "熊貓"; +"device_verification_emoji_rabbit" = "兔子"; +"device_verification_emoji_elephant" = "大象"; +"device_verification_emoji_pig" = "豬"; +"device_verification_emoji_unicorn" = "獨角獸"; +"device_verification_emoji_horse" = "馬"; +"device_verification_emoji_lion" = "獅子"; +"device_verification_emoji_cat" = "貓"; + +// MARK: Emoji +"device_verification_emoji_dog" = "狗"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_backup_action" = "備份"; +"sign_out_non_existing_key_backup_sign_out_confirmation_alert_sign_out_action" = "登出"; +"sign_out_existing_key_backup_alert_sign_out_action" = "登出"; + +// MARK: Sign out warning + +"sign_out_existing_key_backup_alert_title" = "您確定要登出嗎?"; +"key_backup_recover_done_action" = "完成"; +"key_backup_recover_from_recovery_key_recovery_key_title" = "輸入"; +"key_backup_recover_from_passphrase_lost_passphrase_action_part3" = "."; +"key_backup_recover_from_passphrase_passphrase_title" = "輸入"; +"key_backup_setup_success_from_passphrase_done_action" = "完成"; + +// Success + +"key_backup_setup_success_title" = "成功!"; +"key_backup_setup_passphrase_confirm_passphrase_title" = "確認"; +"key_backup_setup_passphrase_passphrase_title" = "輸入"; +"key_backup_setup_intro_manual_export_action" = "手動匯出金鑰"; +"key_backup_setup_intro_manual_export_info" = "(進階)"; +"key_backup_setup_skip_alert_skip_action" = "略過"; +"key_backup_setup_skip_alert_title" = "您確定嗎?"; +"service_terms_modal_decline_button" = "拒絕"; +"service_terms_modal_accept_button" = "接受"; +"room_widget_permission_room_id_permission" = "房間 ID"; +"room_widget_permission_widget_id_permission" = "小工具 ID"; +"room_widget_permission_theme_permission" = "您的主題"; +"room_widget_permission_user_id_permission" = "您的使用者 ID"; +"room_widget_permission_display_name_permission" = "您的顯示名稱"; + +// Room widget permissions +"room_widget_permission_title" = "載入小工具"; +"widget_menu_open_outside" = "在瀏覽器開啟"; +"widget_menu_refresh" = "重新整理"; +"bug_report_background_mode" = "在背景繼續"; +"e2e_key_backup_wrong_version_button_settings" = "設定"; +"call_actions_unhold" = "繼續"; +"room_does_not_exist" = "%@ 不存在"; +"event_formatter_group_call_leave" = "離開"; +"event_formatter_group_call_join" = "加入"; +"event_formatter_group_call" = "群組通話"; +"event_formatter_call_end_call" = "結束通話"; +"event_formatter_call_retry" = "重試"; +"event_formatter_call_answer" = "接聽"; +"event_formatter_call_back" = "回撥"; +"event_formatter_call_has_ended" = "通話結束"; +"event_formatter_call_connecting" = "正在連接…"; +"event_formatter_message_edited_mention" = "(已編輯)"; +"image_picker_action_library" = "從媒體庫挑選"; + +// Image picker +"image_picker_action_camera" = "拍照"; + +// Media picker +"media_picker_title" = "媒體庫"; +"room_notifs_settings_account_settings" = "帳號設定"; +"room_notifs_settings_cancel_action" = "取消"; +"room_notifs_settings_done_action" = "完成"; +"room_notifs_settings_none" = "無"; +"room_notifs_settings_all_messages" = "所有訊息"; +"room_details_notifs" = "通知"; +"room_details_room_name_for_dm" = "名稱"; +"room_details_photo_for_dm" = "照片"; +"room_details_title_for_dm" = "詳細資訊"; +"identity_server_settings_alert_disconnect_still_sharing_3pid_button" = "仍要斷開連接"; +"identity_server_settings_alert_disconnect_button" = "斷開連接"; +"identity_server_settings_disconnect" = "斷開連接"; +"identity_server_settings_change" = "修改"; +"identity_server_settings_add" = "新增"; +"manage_session_name" = "工作階段名稱"; +"manage_session_info" = "工作階段資訊"; + +// Manage session +"manage_session_title" = "管理工作階段"; +"security_settings_advanced" = "進階"; +"security_settings_crosssigning_reset" = "重設"; +"security_settings_secure_backup_delete" = "刪除備份"; +"security_settings_secure_backup_reset" = "重設"; +"security_settings_secure_backup_info_checking" = "正在檢查…"; +"security_settings_crypto_sessions_loading" = "正在載入工作階段…"; + +// Security settings +"security_settings_title" = "安全性"; +"settings_discovery_three_pid_details_share_action" = "分享"; +"settings_discovery_three_pid_details_title_phone_number" = "管理電話號碼"; +"settings_discovery_three_pid_details_title_email" = "管理電子郵件"; +"settings_discovery_error_message" = "發生錯誤。請重試。"; +"settings_discovery_three_pids_management_information_part3" = "."; +"settings_discovery_three_pids_management_information_part2" = "使用者設定"; +"settings_key_backup_delete_confirmation_prompt_title" = "刪除備份"; +"settings_key_backup_button_delete" = "刪除備份"; +"settings_key_backup_info_algorithm" = "演算法:%@"; +"settings_key_backup_info_checking" = "正在檢查…"; +"settings_add_3pid_password_title_msidsn" = "新增電話號碼"; +"settings_add_3pid_password_title_email" = "新增電子郵件地址"; +"settings_new_keyword" = "新增關鍵字"; +"settings_your_keywords" = "您的關鍵字"; +"settings_messages_by_a_bot" = "機器人傳送的訊息"; +"settings_messages_containing_keywords" = "關鍵字"; +"settings_messages_containing_user_name" = "我的使用者名稱"; +"settings_messages_containing_display_name" = "我的顯示名稱"; +"settings_encrypted_group_messages" = "加密群組訊息"; +"settings_group_messages" = "群組訊息"; +"settings_encrypted_direct_messages" = "加密私人訊息"; +"settings_direct_messages" = "私人訊息"; +"settings_default" = "預設通知"; +"settings_notifications_disabled_alert_title" = "已停用通知"; +"settings_device_notifications" = "裝置通知"; +"settings_three_pids_management_information_part3" = "."; +"room_join_group_call" = "加入"; +"room_place_voice_call" = "語音通話"; +"room_accessibility_video_call" = "視訊通話"; +"social_login_button_title_sign_up" = "以 %@ 身分註冊"; +"social_login_button_title_sign_in" = "以 %@ 身分登入"; +"social_login_button_title_continue" = "以 %@ 身分繼續"; +"social_login_list_title_sign_up" = "或"; +"social_login_list_title_sign_in" = "或"; +"callbar_return" = "返回"; +"done" = "完成"; +"open" = "開啟"; From d635f0eff17886dbf0b26c0dd0133d608ecc8626 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 11:43:48 +0100 Subject: [PATCH 084/122] Podfile: First iteration to handle new MatrixKit location. --- Podfile | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/Podfile b/Podfile index 2fed586f1..05a0b671c 100644 --- a/Podfile +++ b/Podfile @@ -34,15 +34,23 @@ $matrixKitVersionSpec = $matrixKitVersion $matrixSDKVersionSpec = {} end -# Method to import the MatrixKit -def import_MatrixKit +# Method to import the MatrixSDK +def import_MatrixSDK pod 'MatrixSDK', $matrixSDKVersionSpec pod 'MatrixSDK/JingleCallStack', $matrixSDKVersionSpec - pod 'MatrixKit', $matrixKitVersionSpec + # pod 'MatrixKit', $matrixKitVersionSpec end ######################################## +def import_MatrixKit_pods + pod 'HPGrowingTextView', '~> 1.1' + pod 'libPhoneNumber-iOS', '~> 0.9.13' + pod 'DTCoreText', '~> 1.6.25' + #pod 'DTCoreText/Extension', '~> 1.6.25' + pod 'Down', '~> 0.11.0' +end + def import_SwiftUI_pods pod 'Introspect', '~> 0.1' end @@ -66,7 +74,7 @@ abstract_target 'RiotPods' do pod 'SwiftLint', '~> 0.44.0' target "Riot" do - import_MatrixKit + import_MatrixSDK import_SwiftUI_pods @@ -89,7 +97,8 @@ abstract_target 'RiotPods' do end target "RiotShareExtension" do - import_MatrixKit + import_MatrixSDK + import_MatrixKit_pods end target "RiotSwiftUI" do @@ -101,11 +110,13 @@ abstract_target 'RiotPods' do end target "SiriIntents" do - import_MatrixKit + import_MatrixSDK + import_MatrixKit_pods end target "RiotNSE" do - import_MatrixKit + import_MatrixSDK + import_MatrixKit_pods end end From e6ef1be7b69d8d0ab00d394c1aa53e24a00df714 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 16:09:53 +0100 Subject: [PATCH 085/122] Update all Objective-C MatrixKit imports to handle new location. --- Riot/Categories/MXGroup+Riot.h | 3 ++- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h | 2 +- Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m | 10 +++++----- Riot/Categories/MXRoom+Riot.h | 3 +-- Riot/Categories/MXRoom+Riot.m | 1 + Riot/Categories/MXRoomSummary+Riot.h | 2 +- Riot/Managers/BugReport/RageShakeManager.h | 2 +- Riot/Managers/BugReport/RageShakeManager.m | 2 -- .../PushNotification/PushNotificationService.m | 2 -- Riot/Managers/Widgets/WidgetManager.m | 2 -- Riot/Model/Contact/Contact.h | 3 ++- Riot/Model/Room/RoomPreviewData.h | 2 +- Riot/Modules/Application/LegacyAppDelegate.h | 2 +- Riot/Modules/Application/LegacyAppDelegate.m | 3 --- .../Authentication/AuthenticationViewController.h | 2 +- .../Authentication/AuthenticationViewController.m | 3 ++- Riot/Modules/Authentication/Views/AuthInputsView.h | 6 ++---- Riot/Modules/Authentication/Views/AuthInputsView.m | 2 +- .../Authentication/Views/ForgotPasswordInputsView.h | 2 +- Riot/Modules/BugReport/BugReportViewController.h | 2 +- Riot/Modules/Call/CallViewController.h | 2 +- Riot/Modules/Call/Views/IncomingCallView.m | 2 +- Riot/Modules/Common/Cells/TableViewCellWithButton.h | 2 +- .../Common/Recents/DataSources/RecentsDataSource.h | 2 +- Riot/Modules/Common/Recents/Model/RecentCellData.h | 2 +- Riot/Modules/Common/Recents/Model/RecentCellData.m | 1 - Riot/Modules/Common/Recents/RecentsViewController.h | 2 +- Riot/Modules/Common/Recents/RecentsViewController.m | 2 -- .../Modules/Common/Recents/Views/RecentTableViewCell.h | 2 +- .../SegmentedViewController/SegmentedViewController.h | 1 + .../Common/WebViewController/WebViewViewController.h | 2 +- .../Modules/Communities/DataSources/GroupsDataSource.h | 2 +- Riot/Modules/Communities/GroupsViewController.h | 2 +- .../Modules/Communities/Home/GroupHomeViewController.h | 2 +- .../Members/GroupParticipantsViewController.h | 1 + .../Communities/Rooms/GroupRoomsViewController.h | 2 +- .../Communities/Rooms/Views/GroupRoomTableViewCell.h | 2 +- .../Communities/Views/GroupInviteTableViewCell.h | 2 -- Riot/Modules/Communities/Views/GroupTableViewCell.h | 2 +- Riot/Modules/Contacts/DataSources/ContactsDataSource.h | 2 +- .../Contacts/Details/ContactDetailsViewController.h | 2 +- .../Modules/Contacts/Details/Views/RoomTableViewCell.h | 2 +- Riot/Modules/Contacts/Views/ContactTableViewCell.h | 2 +- Riot/Modules/Contacts/Views/ContactTableViewCell.m | 2 -- Riot/Modules/EncryptionInfo/EncryptionInfoView.h | 2 +- .../DataSources/UnifiedSearchRecentsDataSource.h | 2 -- .../GlobalSearch/Files/CellData/FilesSearchCellData.h | 2 +- .../GlobalSearch/Files/CellData/FilesSearchCellData.m | 2 ++ .../GlobalSearch/Files/HomeFilesSearchViewController.h | 2 +- .../Files/Views/FilesSearchTableViewCell.h | 2 +- .../DataSources/HomeMessagesSearchDataSource.h | 2 +- .../Messages/HomeMessagesSearchViewController.h | 2 +- .../Views/MessagesSearchResultAttachmentBubbleCell.h | 2 +- .../Views/MessagesSearchResultTextMsgBubbleCell.h | 2 +- .../GlobalSearch/Rooms/DirectoryViewController.h | 2 +- .../Modules/GlobalSearch/UnifiedSearchViewController.h | 2 -- .../GlobalSearch/Views/DirectoryRecentTableViewCell.h | 2 +- .../GlobalSearch/Views/RoomIdOrAliasTableViewCell.h | 2 +- Riot/Modules/Home/Views/RoomCollectionViewCell.h | 2 +- .../Home/Views/TableViewCellWithCollectionView.h | 2 +- .../WidgetPicker/WidgetPickerViewController.h | 2 +- .../Integrations/Widgets/Jitsi/JitsiViewController.h | 2 +- .../Integrations/Widgets/WidgetViewController.h | 2 +- .../Library/MediaAlbumContentViewController.h | 2 +- Riot/Modules/MediaPicker/MediaPickerViewController.h | 2 +- Riot/Modules/MediaPicker/MediaPickerViewController.m | 2 -- Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.h | 2 +- Riot/Modules/People/Views/InviteRecentTableViewCell.h | 2 -- .../DataSources/PublicRoomsDirectoryDataSource.h | 2 +- .../PublicRoomList/Views/PublicRoomTableViewCell.h | 2 +- .../Room/Attachements/AttachmentsViewController.h | 2 +- Riot/Modules/Room/CellData/RoomBubbleCellData.h | 2 +- Riot/Modules/Room/CellData/RoomBubbleCellData.m | 1 - Riot/Modules/Room/DataSources/RoomDataSource.h | 2 +- Riot/Modules/Room/Files/RoomFilesViewController.h | 2 +- .../Members/Detail/RoomMemberDetailsViewController.h | 2 +- .../Room/Members/Detail/Views/RoomMemberTitleView.h | 2 +- .../Room/Members/RoomParticipantsViewController.m | 2 +- .../ReadReceiptsDetail/ReadReceiptsViewController.h | 2 +- .../ReadReceiptsDetail/ReadReceiptsViewController.m | 1 - .../RoomInfoList/Views/RoomInfoBasicViewData.swift | 1 - Riot/Modules/Room/RoomViewController.h | 2 +- Riot/Modules/Room/RoomViewController.m | 1 - .../Room/Search/DataSources/RoomSearchDataSource.h | 2 +- .../Room/Search/Files/RoomFilesSearchViewController.h | 2 +- .../Search/Messages/RoomMessagesSearchViewController.h | 4 +++- Riot/Modules/Room/Search/RoomSearchViewController.h | 2 +- .../Modules/Room/Settings/RoomSettingsViewController.h | 2 +- .../Settings/Views/TableViewCellWithCheckBoxAndLabel.h | 2 +- .../Room/Settings/Views/TableViewCellWithCheckBoxes.h | 2 +- .../Views/TableViewCellWithLabelAndLargeTextView.h | 2 +- .../Modules/Room/Views/Activities/RoomActivitiesView.h | 2 +- .../Encryption/RoomEncryptedDataBubbleCell.h | 2 +- .../Room/Views/BubbleCells/RoomEmptyBubbleCell.h | 2 +- .../BubbleCells/RoomIncomingAttachmentBubbleCell.h | 2 +- ...omIncomingAttachmentWithPaginationTitleBubbleCell.h | 2 +- ...RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h | 2 +- .../Views/BubbleCells/RoomIncomingTextMsgBubbleCell.h | 2 +- .../RoomIncomingTextMsgWithPaginationTitleBubbleCell.h | 2 +- .../RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h | 2 +- .../BubbleCells/RoomOutgoingAttachmentBubbleCell.h | 2 +- ...RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h | 2 +- .../Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.h | 2 +- .../RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h | 2 +- .../Room/Views/BubbleCells/RoomPredecessorBubbleCell.h | 3 ++- Riot/Modules/Room/Views/Event/EventDetailsView.h | 2 +- .../Views/InputToolbar/DisabledRoomInputToolbarView.h | 2 +- .../Room/Views/InputToolbar/RoomInputToolbarView.h | 2 +- .../Room/Views/Title/Avatar/RoomAvatarTitleView.h | 2 +- Riot/Modules/Room/Views/Title/RoomTitleView.h | 2 +- .../Room/Views/Title/Simple/SimpleRoomTitleView.h | 4 ++-- .../DirectoryServerPickerViewController.h | 2 +- .../Views/DirectoryServerTableViewCell.h | 2 +- .../DeactivateAccountViewController.h | 3 ++- .../Settings/Language/LanguagePickerViewController.h | 2 +- .../PhoneCountry/CountryPickerViewController.h | 2 +- .../ManageSession/ManageSessionViewController.h | 2 +- .../ManageSession/ManageSessionViewController.m | 2 -- .../Modules/Settings/Security/SecurityViewController.h | 2 +- .../Modules/Settings/Security/SecurityViewController.m | 2 -- Riot/Modules/Settings/SettingsViewController.h | 6 ++---- Riot/Modules/Settings/SettingsViewController.m | 6 +++--- Riot/Modules/Settings/Views/DeviceView.h | 2 +- .../Views/TableViewCellWithPhoneNumberTextField.h | 2 +- Riot/Modules/TabBar/MasterTabBarController.h | 2 -- Riot/Modules/UserDevices/UsersDevicesViewController.h | 2 +- Riot/Modules/UserDevices/Views/DeviceTableViewCell.h | 4 +++- Riot/Utils/EventFormatter.h | 2 +- RiotShareExtension/Shared/ShareDataSource.h | 2 +- RiotShareExtension/Shared/ShareManager.h | 2 +- RiotShareExtension/Shared/ShareManager.m | 2 -- .../Shared/View/RecentRoomTableViewCell.h | 2 +- .../Shared/View/RoomsListViewController.m | 2 -- SiriIntents/IntentHandler.m | 2 -- 134 files changed, 131 insertions(+), 162 deletions(-) diff --git a/Riot/Categories/MXGroup+Riot.h b/Riot/Categories/MXGroup+Riot.h index 0d1beb543..76b1e76e5 100644 --- a/Riot/Categories/MXGroup+Riot.h +++ b/Riot/Categories/MXGroup+Riot.h @@ -14,7 +14,8 @@ limitations under the License. */ -#import +#import +#import "MatrixKit.h" /** Define a `MXGroup` category at Riot level. diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h index 491401fe1..24a0ff136 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class CircleProgressView; diff --git a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m index 25499c2d6..2d2a0dbfc 100644 --- a/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m +++ b/Riot/Categories/MXKRoomBubbleTableViewCell+Riot.m @@ -17,13 +17,13 @@ #import "MXKRoomBubbleTableViewCell+Riot.h" -#import "RoomBubbleCellData.h" - -#import "ThemeService.h" -#import "GeneratedInterface-Swift.h" - #import +#import "RoomBubbleCellData.h" +#import "ThemeService.h" + +#import "GeneratedInterface-Swift.h" + #define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_X 48 #define VECTOR_ROOMBUBBLETABLEVIEWCELL_MARK_WIDTH 4 diff --git a/Riot/Categories/MXRoom+Riot.h b/Riot/Categories/MXRoom+Riot.h index 42a6a6c01..e57cd21a2 100644 --- a/Riot/Categories/MXRoom+Riot.h +++ b/Riot/Categories/MXRoom+Riot.h @@ -15,9 +15,8 @@ limitations under the License. */ -#import - #import "UserEncryptionTrustLevel.h" +#import /** Define a `MXRoom` category at Riot level. diff --git a/Riot/Categories/MXRoom+Riot.m b/Riot/Categories/MXRoom+Riot.m index 5bef645be..801221597 100644 --- a/Riot/Categories/MXRoom+Riot.m +++ b/Riot/Categories/MXRoom+Riot.m @@ -19,6 +19,7 @@ #import "MXRoom+Riot.h" #import "AvatarGenerator.h" +#import "MatrixKit.h" #import diff --git a/Riot/Categories/MXRoomSummary+Riot.h b/Riot/Categories/MXRoomSummary+Riot.h index 0ae7c7359..d25cdee5f 100644 --- a/Riot/Categories/MXRoomSummary+Riot.h +++ b/Riot/Categories/MXRoomSummary+Riot.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** RoomEncryptionTrustLevel represents the trust level in an encrypted room. diff --git a/Riot/Managers/BugReport/RageShakeManager.h b/Riot/Managers/BugReport/RageShakeManager.h index a220800b7..2caff3e88 100644 --- a/Riot/Managers/BugReport/RageShakeManager.h +++ b/Riot/Managers/BugReport/RageShakeManager.h @@ -17,7 +17,7 @@ #import #import -#import +#import "MatrixKit.h" @interface RageShakeManager : NSObject diff --git a/Riot/Managers/BugReport/RageShakeManager.m b/Riot/Managers/BugReport/RageShakeManager.m index a0357d046..4ce848240 100644 --- a/Riot/Managers/BugReport/RageShakeManager.m +++ b/Riot/Managers/BugReport/RageShakeManager.m @@ -21,8 +21,6 @@ #import "BugReportViewController.h" -#import - #import "GeneratedInterface-Swift.h" static RageShakeManager* sharedInstance = nil; diff --git a/Riot/Managers/PushNotification/PushNotificationService.m b/Riot/Managers/PushNotification/PushNotificationService.m index fc6eab47d..30cb7da3a 100644 --- a/Riot/Managers/PushNotification/PushNotificationService.m +++ b/Riot/Managers/PushNotification/PushNotificationService.m @@ -17,8 +17,6 @@ #import "PushNotificationService.h" -#import - #import #import "GeneratedInterface-Swift.h" diff --git a/Riot/Managers/Widgets/WidgetManager.m b/Riot/Managers/Widgets/WidgetManager.m index 1e6fbaa7c..2b25d2e13 100644 --- a/Riot/Managers/Widgets/WidgetManager.m +++ b/Riot/Managers/Widgets/WidgetManager.m @@ -21,8 +21,6 @@ #import "JitsiWidgetData.h" #import "MXSession+Riot.h" -#import - #pragma mark - Contants NSString *const kWidgetManagerDidUpdateWidgetNotification = @"kWidgetManagerDidUpdateWidgetNotification"; diff --git a/Riot/Model/Contact/Contact.h b/Riot/Model/Contact/Contact.h index 31036dedd..93a243609 100644 --- a/Riot/Model/Contact/Contact.h +++ b/Riot/Model/Contact/Contact.h @@ -14,7 +14,8 @@ limitations under the License. */ -#import +#import "MatrixKit.h" +#import @interface Contact : MXKContact diff --git a/Riot/Model/Room/RoomPreviewData.h b/Riot/Model/Room/RoomPreviewData.h index f6f51bdca..f67712ccc 100644 --- a/Riot/Model/Room/RoomPreviewData.h +++ b/Riot/Model/Room/RoomPreviewData.h @@ -16,7 +16,7 @@ #import -#import +#import "MatrixKit.h" #import "RoomEmailInvitation.h" #import "RoomDataSource.h" diff --git a/Riot/Modules/Application/LegacyAppDelegate.h b/Riot/Modules/Application/LegacyAppDelegate.h index 6a3e2c3be..72dc4f61e 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.h +++ b/Riot/Modules/Application/LegacyAppDelegate.h @@ -16,7 +16,7 @@ */ #import -#import +#import "MatrixKit.h" #import "MasterTabBarController.h" #import "JitsiViewController.h" diff --git a/Riot/Modules/Application/LegacyAppDelegate.m b/Riot/Modules/Application/LegacyAppDelegate.m index 75060f84b..b7130dafd 100644 --- a/Riot/Modules/Application/LegacyAppDelegate.m +++ b/Riot/Modules/Application/LegacyAppDelegate.m @@ -36,8 +36,6 @@ #import "RoomKeyRequestViewController.h" #import "DecryptionFailureTracker.h" -#import - #import "Tools.h" #import "WidgetManager.h" @@ -393,7 +391,6 @@ NSString *const AppDelegateUniversalLinkDidChangeNotification = @"AppDelegateUni MXLogDebug(@"------------------------------"); MXLogDebug(@"Application info:"); MXLogDebug(@"%@ version: %@", appDisplayName, appVersion); - MXLogDebug(@"MatrixKit version: %@", MatrixKitVersion); MXLogDebug(@"MatrixSDK version: %@", MatrixSDKVersion); MXLogDebug(@"Build: %@\n", build); MXLogDebug(@"------------------------------\n"); diff --git a/Riot/Modules/Authentication/AuthenticationViewController.h b/Riot/Modules/Authentication/AuthenticationViewController.h index a689fd5ae..133f0a867 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.h +++ b/Riot/Modules/Authentication/AuthenticationViewController.h @@ -16,7 +16,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @protocol AuthenticationViewControllerDelegate; diff --git a/Riot/Modules/Authentication/AuthenticationViewController.m b/Riot/Modules/Authentication/AuthenticationViewController.m index de5eadc32..188e33268 100644 --- a/Riot/Modules/Authentication/AuthenticationViewController.m +++ b/Riot/Modules/Authentication/AuthenticationViewController.m @@ -18,13 +18,14 @@ #import "AuthenticationViewController.h" -#import "GeneratedInterface-Swift.h" #import "MXSession+Riot.h" #import "AuthInputsView.h" #import "ForgotPasswordInputsView.h" #import "AuthFallBackViewController.h" +#import "GeneratedInterface-Swift.h" + static const CGFloat kAuthInputContainerViewMinHeightConstraintConstant = 150.0; @interface AuthenticationViewController () +#import "MatrixKit.h" -#import "GeneratedInterface-Swift.h" - -@interface AuthInputsView : MXKAuthInputsView +@interface AuthInputsView : MXKAuthInputsView @property (weak, nonatomic) IBOutlet UITextField *userLoginTextField; @property (weak, nonatomic) IBOutlet UITextField *passWordTextField; diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 68a79c202..5e037f5bf 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -26,7 +26,7 @@ #import "RiotNavigationController.h" -@interface AuthInputsView () +@interface AuthInputsView () { /** The current email validation diff --git a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.h b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.h index c5f088545..7aead4034 100644 --- a/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.h +++ b/Riot/Modules/Authentication/Views/ForgotPasswordInputsView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface ForgotPasswordInputsView : MXKAuthInputsView diff --git a/Riot/Modules/BugReport/BugReportViewController.h b/Riot/Modules/BugReport/BugReportViewController.h index 972e02d24..715639661 100644 --- a/Riot/Modules/BugReport/BugReportViewController.h +++ b/Riot/Modules/BugReport/BugReportViewController.h @@ -16,7 +16,7 @@ #import -#import +#import "MatrixKit.h" @interface BugReportViewController : MXKViewController diff --git a/Riot/Modules/Call/CallViewController.h b/Riot/Modules/Call/CallViewController.h index 98bedce60..1fe7837da 100644 --- a/Riot/Modules/Call/CallViewController.h +++ b/Riot/Modules/Call/CallViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** 'CallViewController' instance displays a call. Only one matrix session is supported by this view controller. diff --git a/Riot/Modules/Call/Views/IncomingCallView.m b/Riot/Modules/Call/Views/IncomingCallView.m index 9da231175..35500cf4e 100644 --- a/Riot/Modules/Call/Views/IncomingCallView.m +++ b/Riot/Modules/Call/Views/IncomingCallView.m @@ -17,7 +17,7 @@ #import "IncomingCallView.h" -#import +#import "MatrixKit.h" #import #import "CircleButton.h" diff --git a/Riot/Modules/Common/Cells/TableViewCellWithButton.h b/Riot/Modules/Common/Cells/TableViewCellWithButton.h index 78c703ba1..3a8a172a6 100644 --- a/Riot/Modules/Common/Cells/TableViewCellWithButton.h +++ b/Riot/Modules/Common/Cells/TableViewCellWithButton.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface TableViewCellWithButton : MXKTableViewCellWithButton diff --git a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h index 585453317..2dbf20bc5 100644 --- a/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h +++ b/Riot/Modules/Common/Recents/DataSources/RecentsDataSource.h @@ -15,7 +15,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "PublicRoomsDirectoryDataSource.h" diff --git a/Riot/Modules/Common/Recents/Model/RecentCellData.h b/Riot/Modules/Common/Recents/Model/RecentCellData.h index 53bc182bd..43efda4ef 100644 --- a/Riot/Modules/Common/Recents/Model/RecentCellData.h +++ b/Riot/Modules/Common/Recents/Model/RecentCellData.h @@ -17,7 +17,7 @@ #import #import -#import +#import "MatrixKit.h" /** `RecentCellData` is Vector cuustomized MXKRecentCellData` cell. diff --git a/Riot/Modules/Common/Recents/Model/RecentCellData.m b/Riot/Modules/Common/Recents/Model/RecentCellData.m index 9697b85ea..01800996f 100644 --- a/Riot/Modules/Common/Recents/Model/RecentCellData.m +++ b/Riot/Modules/Common/Recents/Model/RecentCellData.m @@ -18,7 +18,6 @@ #import "RecentCellData.h" #import "MXRoom+Riot.h" -#import "MatrixSDK-Swift.h" #import "GeneratedInterface-Swift.h" diff --git a/Riot/Modules/Common/Recents/RecentsViewController.h b/Riot/Modules/Common/Recents/RecentsViewController.h index 6a475073a..a9e9c4863 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.h +++ b/Riot/Modules/Common/Recents/RecentsViewController.h @@ -15,7 +15,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class RootTabEmptyView; diff --git a/Riot/Modules/Common/Recents/RecentsViewController.m b/Riot/Modules/Common/Recents/RecentsViewController.m index c9b9bb3c0..6e8adb76e 100644 --- a/Riot/Modules/Common/Recents/RecentsViewController.m +++ b/Riot/Modules/Common/Recents/RecentsViewController.m @@ -24,8 +24,6 @@ #import "MXRoom+Riot.h" -#import - #import "RoomViewController.h" #import "InviteRecentTableViewCell.h" diff --git a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.h b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.h index e3feee4e4..347a92f76 100644 --- a/Riot/Modules/Common/Recents/Views/RecentTableViewCell.h +++ b/Riot/Modules/Common/Recents/Views/RecentTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RecentTableViewCell` instances display a room in the context of the recents list. diff --git a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h index f68d498ae..fb0c3b583 100644 --- a/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h +++ b/Riot/Modules/Common/SegmentedViewController/SegmentedViewController.h @@ -18,6 +18,7 @@ limitations under the License. #import #import "UIViewController+RiotSearch.h" +#import "MatrixKit.h" /** This view controller manages several uiviewcontrollers like UISegmentedController manages uiTableView diff --git a/Riot/Modules/Common/WebViewController/WebViewViewController.h b/Riot/Modules/Common/WebViewController/WebViewViewController.h index 8426ae613..24c95c42c 100644 --- a/Riot/Modules/Common/WebViewController/WebViewViewController.h +++ b/Riot/Modules/Common/WebViewController/WebViewViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** WebViewViewController extends MXKWebViewViewController to handle customization. diff --git a/Riot/Modules/Communities/DataSources/GroupsDataSource.h b/Riot/Modules/Communities/DataSources/GroupsDataSource.h index 7a8a4f9d6..836f6fdaa 100644 --- a/Riot/Modules/Communities/DataSources/GroupsDataSource.h +++ b/Riot/Modules/Communities/DataSources/GroupsDataSource.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** 'GroupsDataSource' class inherits from 'MXKSessionGroupsDataSource' to define the Riot groups source. diff --git a/Riot/Modules/Communities/GroupsViewController.h b/Riot/Modules/Communities/GroupsViewController.h index 08ab81101..ef2a4c486 100644 --- a/Riot/Modules/Communities/GroupsViewController.h +++ b/Riot/Modules/Communities/GroupsViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** The `GroupsViewController` screen is the view controller displayed when `Groups` tab is selected. diff --git a/Riot/Modules/Communities/Home/GroupHomeViewController.h b/Riot/Modules/Communities/Home/GroupHomeViewController.h index d07b59471..69b2300da 100644 --- a/Riot/Modules/Communities/Home/GroupHomeViewController.h +++ b/Riot/Modules/Communities/Home/GroupHomeViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface GroupHomeViewController : MXKViewController diff --git a/Riot/Modules/Communities/Members/GroupParticipantsViewController.h b/Riot/Modules/Communities/Members/GroupParticipantsViewController.h index 012b148c1..83b862664 100644 --- a/Riot/Modules/Communities/Members/GroupParticipantsViewController.h +++ b/Riot/Modules/Communities/Members/GroupParticipantsViewController.h @@ -15,6 +15,7 @@ */ #import "ContactsTableViewController.h" +#import "MatrixKit.h" @class Contact; diff --git a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h index 34e0bbe9a..792865b96 100644 --- a/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h +++ b/Riot/Modules/Communities/Rooms/GroupRoomsViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** 'GroupRoomsViewController' instance is used to list the rooms of the group defined by the property 'mxGroup'. diff --git a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.h b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.h index be8dd1ef9..e140b3585 100644 --- a/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.h +++ b/Riot/Modules/Communities/Rooms/Views/GroupRoomTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface GroupRoomTableViewCell : MXKTableViewCell diff --git a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.h b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.h index c640d95f9..b746d6ba1 100644 --- a/Riot/Modules/Communities/Views/GroupInviteTableViewCell.h +++ b/Riot/Modules/Communities/Views/GroupInviteTableViewCell.h @@ -14,8 +14,6 @@ limitations under the License. */ -#import - #import "GroupTableViewCell.h" /** diff --git a/Riot/Modules/Communities/Views/GroupTableViewCell.h b/Riot/Modules/Communities/Views/GroupTableViewCell.h index 867ee5183..61f8f6849 100644 --- a/Riot/Modules/Communities/Views/GroupTableViewCell.h +++ b/Riot/Modules/Communities/Views/GroupTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `GroupTableViewCell` instances display a group in the context of the groups list. diff --git a/Riot/Modules/Contacts/DataSources/ContactsDataSource.h b/Riot/Modules/Contacts/DataSources/ContactsDataSource.h index ea6db9c2e..5b665377e 100644 --- a/Riot/Modules/Contacts/DataSources/ContactsDataSource.h +++ b/Riot/Modules/Contacts/DataSources/ContactsDataSource.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** The state of the users search from the homeserver user directory. diff --git a/Riot/Modules/Contacts/Details/ContactDetailsViewController.h b/Riot/Modules/Contacts/Details/ContactDetailsViewController.h index a41a8df84..737dd6532 100644 --- a/Riot/Modules/Contacts/Details/ContactDetailsViewController.h +++ b/Riot/Modules/Contacts/Details/ContactDetailsViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** Available actions on contact diff --git a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.h b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.h index db8a7590c..a99bd2df5 100644 --- a/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.h +++ b/Riot/Modules/Contacts/Details/Views/RoomTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** The `RoomTableViewCell` cell displays a room (avatar and displayname). diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.h b/Riot/Modules/Contacts/Views/ContactTableViewCell.h index eadf78150..acb9e0097 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.h +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** 'ContactTableCell' extends MXKTableViewCell. diff --git a/Riot/Modules/Contacts/Views/ContactTableViewCell.m b/Riot/Modules/Contacts/Views/ContactTableViewCell.m index c07d2f33e..a1c3b12a2 100644 --- a/Riot/Modules/Contacts/Views/ContactTableViewCell.m +++ b/Riot/Modules/Contacts/Views/ContactTableViewCell.m @@ -17,8 +17,6 @@ #import "ContactTableViewCell.h" -#import - #import "ThemeService.h" #import "GeneratedInterface-Swift.h" diff --git a/Riot/Modules/EncryptionInfo/EncryptionInfoView.h b/Riot/Modules/EncryptionInfo/EncryptionInfoView.h index 3c772b423..ce61e04c4 100644 --- a/Riot/Modules/EncryptionInfo/EncryptionInfoView.h +++ b/Riot/Modules/EncryptionInfo/EncryptionInfoView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** TODO: This view as it is implemented in this class must disappear. diff --git a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.h b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.h index 6102584de..7c89ea8b1 100644 --- a/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.h +++ b/Riot/Modules/GlobalSearch/DataSources/UnifiedSearchRecentsDataSource.h @@ -14,8 +14,6 @@ limitations under the License. */ -#import - #import "RecentsDataSource.h" /** diff --git a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.h b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.h index b8f6d3955..15832ca55 100644 --- a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.h +++ b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `FilesSearchCellData` prepares the data for the Vector cell used to display the files search result. diff --git a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m index d7af35024..f9dcf9ea2 100644 --- a/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m +++ b/Riot/Modules/GlobalSearch/Files/CellData/FilesSearchCellData.m @@ -18,6 +18,8 @@ #import "FilesSearchCellData.h" +#import "GeneratedInterface-Swift.h" + @implementation FilesSearchCellData @synthesize roomId, senderDisplayName; @synthesize searchResult, title, message, date, shouldShowRoomDisplayName, roomDisplayName, attachment, isAttachmentWithThumbnail, attachmentIcon; diff --git a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.h b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.h index bf64d5bf2..bf9826858 100644 --- a/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.h +++ b/Riot/Modules/GlobalSearch/Files/HomeFilesSearchViewController.h @@ -15,7 +15,7 @@ */ -#import +#import "MatrixKit.h" /** `HomeFilesSearchViewController` displays the files search in user's rooms under a `HomeViewController` segment. diff --git a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.h b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.h index 46f6e97e0..01ebbbd03 100644 --- a/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.h +++ b/Riot/Modules/GlobalSearch/Files/Views/FilesSearchTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** Each `FilesSearchTableViewCell` instance displays a files search result. diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.h b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.h index 511d9e540..1f1136942 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.h +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `HomeMessagesSearchDataSource` overrides `MXKSearchDataSource` to render search results diff --git a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.h b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.h index 1c4468201..8a3553771 100644 --- a/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.h +++ b/Riot/Modules/GlobalSearch/Messages/HomeMessagesSearchViewController.h @@ -15,7 +15,7 @@ */ -#import +#import "MatrixKit.h" /** `HomeMessagesSearchViewController` displays messages search in user's rooms under a `HomeViewController` segment. diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.h b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.h index 7c01be438..709b25cfd 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.h +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultAttachmentBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `MessagesSearchResultAttachmentBubbleCell` displays an attachment with the information of the room and the sender. diff --git a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.h b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.h index 04228a453..4c12d1d17 100644 --- a/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.h +++ b/Riot/Modules/GlobalSearch/Messages/Views/MessagesSearchResultTextMsgBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `MessagesSearchResultTextMsgBubbleCell` displays a message text with the information of the room and the sender. diff --git a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.h b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.h index ada83aca8..c4cf2dc9a 100644 --- a/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.h +++ b/Riot/Modules/GlobalSearch/Rooms/DirectoryViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class PublicRoomsDirectoryDataSource; diff --git a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.h b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.h index 3a22f76e4..72fddaef6 100644 --- a/Riot/Modules/GlobalSearch/UnifiedSearchViewController.h +++ b/Riot/Modules/GlobalSearch/UnifiedSearchViewController.h @@ -14,8 +14,6 @@ limitations under the License. */ -#import - #import "SegmentedViewController.h" #import "ContactsTableViewController.h" diff --git a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.h b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.h index 15be3d4dd..04266edb6 100644 --- a/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.h +++ b/Riot/Modules/GlobalSearch/Views/DirectoryRecentTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class PublicRoomsDirectoryDataSource; diff --git a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.h b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.h index 1f3ab2398..36d082255 100644 --- a/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.h +++ b/Riot/Modules/GlobalSearch/Views/RoomIdOrAliasTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** The `RoomIdOrAliasTableViewCell` cell displays a room identifier or a room alias. diff --git a/Riot/Modules/Home/Views/RoomCollectionViewCell.h b/Riot/Modules/Home/Views/RoomCollectionViewCell.h index 439cf0527..f08116c11 100644 --- a/Riot/Modules/Home/Views/RoomCollectionViewCell.h +++ b/Riot/Modules/Home/Views/RoomCollectionViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class BadgeLabel; diff --git a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.h b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.h index aa71ab9d4..832037a88 100644 --- a/Riot/Modules/Home/Views/TableViewCellWithCollectionView.h +++ b/Riot/Modules/Home/Views/TableViewCellWithCollectionView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface TableViewCellWithCollectionView : MXKTableViewCell diff --git a/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.h b/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.h index 8293c1029..0396a55f0 100644 --- a/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.h +++ b/Riot/Modules/Integrations/WidgetPicker/WidgetPickerViewController.h @@ -17,7 +17,7 @@ #import #import -#import +#import "MatrixKit.h" /** `WidgetPickerViewController` displays the list of widgets within a room plus a diff --git a/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.h b/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.h index 2fb2b368f..c79a07b2a 100644 --- a/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.h +++ b/Riot/Modules/Integrations/Widgets/Jitsi/JitsiViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "WidgetManager.h" diff --git a/Riot/Modules/Integrations/Widgets/WidgetViewController.h b/Riot/Modules/Integrations/Widgets/WidgetViewController.h index 49b6a6ac2..895f229c5 100644 --- a/Riot/Modules/Integrations/Widgets/WidgetViewController.h +++ b/Riot/Modules/Integrations/Widgets/WidgetViewController.h @@ -17,7 +17,7 @@ #import "WebViewViewController.h" #import "WidgetManager.h" -#import "MatrixKit/MatrixKit.h" +#import "MatrixKit.h" /** `WidgetViewController` displays widget within a webview. diff --git a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.h b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.h index 32424d8eb..0d8479d1d 100644 --- a/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.h +++ b/Riot/Modules/MediaPicker/Library/MediaAlbumContentViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.h b/Riot/Modules/MediaPicker/MediaPickerViewController.h index 71487e1ea..a032ec2eb 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.h +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "MediaAlbumContentViewController.h" diff --git a/Riot/Modules/MediaPicker/MediaPickerViewController.m b/Riot/Modules/MediaPicker/MediaPickerViewController.m index 69a183a2c..92261789c 100644 --- a/Riot/Modules/MediaPicker/MediaPickerViewController.m +++ b/Riot/Modules/MediaPicker/MediaPickerViewController.m @@ -29,8 +29,6 @@ #import "MediaAlbumTableCell.h" -#import - @interface MediaPickerViewController () { diff --git a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.h b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.h index 40cd11bec..835ef6afc 100644 --- a/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.h +++ b/Riot/Modules/MediaPicker/Views/MediaAlbumTableCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** 'MediaAlbumTableCell' is a base class for displaying a user album. diff --git a/Riot/Modules/People/Views/InviteRecentTableViewCell.h b/Riot/Modules/People/Views/InviteRecentTableViewCell.h index 314f7f7e8..f3fe96891 100644 --- a/Riot/Modules/People/Views/InviteRecentTableViewCell.h +++ b/Riot/Modules/People/Views/InviteRecentTableViewCell.h @@ -14,8 +14,6 @@ limitations under the License. */ -#import - #import "RecentTableViewCell.h" /** diff --git a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h index 750daac05..6fce1d92b 100644 --- a/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h +++ b/Riot/Modules/PublicRoomList/DataSources/PublicRoomsDirectoryDataSource.h @@ -17,7 +17,7 @@ #import -#import "MatrixKit/MatrixKit.h" +#import "MatrixKit.h" /** `PublicRoomsDirectoryDataSource` is a base class to display public rooms directory. diff --git a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.h b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.h index e0f145028..02b82820b 100644 --- a/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.h +++ b/Riot/Modules/PublicRoomList/Views/PublicRoomTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface PublicRoomTableViewCell : MXKPublicRoomTableViewCell diff --git a/Riot/Modules/Room/Attachements/AttachmentsViewController.h b/Riot/Modules/Room/Attachements/AttachmentsViewController.h index dae04e21f..069ea957c 100644 --- a/Riot/Modules/Room/Attachements/AttachmentsViewController.h +++ b/Riot/Modules/Room/Attachements/AttachmentsViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface AttachmentsViewController : MXKAttachmentsViewController diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.h b/Riot/Modules/Room/CellData/RoomBubbleCellData.h index ebbf94aaa..526abea1b 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.h +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" extern NSString *const URLPreviewDidUpdateNotification; diff --git a/Riot/Modules/Room/CellData/RoomBubbleCellData.m b/Riot/Modules/Room/CellData/RoomBubbleCellData.m index 697d67178..f73e211c3 100644 --- a/Riot/Modules/Room/CellData/RoomBubbleCellData.m +++ b/Riot/Modules/Room/CellData/RoomBubbleCellData.m @@ -24,7 +24,6 @@ #import "BubbleReactionsViewSizer.h" #import "GeneratedInterface-Swift.h" -#import static NSAttributedString *timestampVerticalWhitespace = nil; diff --git a/Riot/Modules/Room/DataSources/RoomDataSource.h b/Riot/Modules/Room/DataSources/RoomDataSource.h index 725171572..28af89097 100644 --- a/Riot/Modules/Room/DataSources/RoomDataSource.h +++ b/Riot/Modules/Room/DataSources/RoomDataSource.h @@ -15,7 +15,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "WidgetManager.h" diff --git a/Riot/Modules/Room/Files/RoomFilesViewController.h b/Riot/Modules/Room/Files/RoomFilesViewController.h index 3173c2d0a..e8f3b7f29 100644 --- a/Riot/Modules/Room/Files/RoomFilesViewController.h +++ b/Riot/Modules/Room/Files/RoomFilesViewController.h @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -#import +#import "MatrixKit.h" /** This view controller displays the attachments of a room. Only one matrix session is handled by this view controller. diff --git a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.h b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.h index 9881e328b..18f6bef28 100644 --- a/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.h +++ b/Riot/Modules/Room/Members/Detail/RoomMemberDetailsViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "DeviceTableViewCell.h" diff --git a/Riot/Modules/Room/Members/Detail/Views/RoomMemberTitleView.h b/Riot/Modules/Room/Members/Detail/Views/RoomMemberTitleView.h index 6111b6939..16f216ac3 100644 --- a/Riot/Modules/Room/Members/Detail/Views/RoomMemberTitleView.h +++ b/Riot/Modules/Room/Members/Detail/Views/RoomMemberTitleView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" // We add here a protocol to handle title view layout update. @class RoomMemberTitleView; diff --git a/Riot/Modules/Room/Members/RoomParticipantsViewController.m b/Riot/Modules/Room/Members/RoomParticipantsViewController.m index 7a03da092..1776b8775 100644 --- a/Riot/Modules/Room/Members/RoomParticipantsViewController.m +++ b/Riot/Modules/Room/Members/RoomParticipantsViewController.m @@ -29,7 +29,7 @@ #import "RageShakeManager.h" -@interface RoomParticipantsViewController () +@interface RoomParticipantsViewController () { // Search result NSString *currentSearchText; diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.h b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.h index eca67c3ce..09e38b13e 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.h +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.h @@ -15,7 +15,7 @@ */ #import -#import +#import "MatrixKit.h" @interface ReadReceiptsViewController : MXKViewController diff --git a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m index 2bde90904..bf7daf16d 100644 --- a/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m +++ b/Riot/Modules/Room/ReadReceiptsDetail/ReadReceiptsViewController.m @@ -16,7 +16,6 @@ */ #import "ReadReceiptsViewController.h" -#import #import "RageShakeManager.h" #import "ThemeService.h" diff --git a/Riot/Modules/Room/RoomInfo/RoomInfoList/Views/RoomInfoBasicViewData.swift b/Riot/Modules/Room/RoomInfo/RoomInfoList/Views/RoomInfoBasicViewData.swift index 085f0e2ae..b96ce90fd 100644 --- a/Riot/Modules/Room/RoomInfo/RoomInfoList/Views/RoomInfoBasicViewData.swift +++ b/Riot/Modules/Room/RoomInfo/RoomInfoList/Views/RoomInfoBasicViewData.swift @@ -15,7 +15,6 @@ // import Foundation -import MatrixKit struct RoomInfoBasicViewData { let avatarUrl: String? diff --git a/Riot/Modules/Room/RoomViewController.h b/Riot/Modules/Room/RoomViewController.h index 3723eb5d8..4aa3818bf 100644 --- a/Riot/Modules/Room/RoomViewController.h +++ b/Riot/Modules/Room/RoomViewController.h @@ -15,7 +15,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "RoomTitleView.h" diff --git a/Riot/Modules/Room/RoomViewController.m b/Riot/Modules/Room/RoomViewController.m index 10c75553e..4ac30f4a5 100644 --- a/Riot/Modules/Room/RoomViewController.m +++ b/Riot/Modules/Room/RoomViewController.m @@ -122,7 +122,6 @@ #import "StickerPickerViewController.h" #import "EventFormatter.h" -#import #import "SettingsViewController.h" #import "SecurityViewController.h" diff --git a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.h b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.h index 4b1b9a6be..341226ef2 100644 --- a/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.h +++ b/Riot/Modules/Room/Search/DataSources/RoomSearchDataSource.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomSearchDataSource` overrides `MXKSearchDataSource` to render search results diff --git a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.h b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.h index 3e2061098..a01848797 100644 --- a/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.h +++ b/Riot/Modules/Room/Search/Files/RoomFilesSearchViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface RoomFilesSearchViewController : MXKSearchViewController diff --git a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.h b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.h index bff2f4439..b8d0d6d51 100644 --- a/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.h +++ b/Riot/Modules/Room/Search/Messages/RoomMessagesSearchViewController.h @@ -14,7 +14,9 @@ limitations under the License. */ -#import +#import + +#import "MatrixKit.h" @interface RoomMessagesSearchViewController : MXKSearchViewController diff --git a/Riot/Modules/Room/Search/RoomSearchViewController.h b/Riot/Modules/Room/Search/RoomSearchViewController.h index 14c1460b5..7d72226b5 100644 --- a/Riot/Modules/Room/Search/RoomSearchViewController.h +++ b/Riot/Modules/Room/Search/RoomSearchViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "SegmentedViewController.h" diff --git a/Riot/Modules/Room/Settings/RoomSettingsViewController.h b/Riot/Modules/Room/Settings/RoomSettingsViewController.h index 950f9c6d7..dd960e8a6 100644 --- a/Riot/Modules/Room/Settings/RoomSettingsViewController.h +++ b/Riot/Modules/Room/Settings/RoomSettingsViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "MediaPickerViewController.h" #import "TableViewCellWithCheckBoxes.h" diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.h b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.h index d22b79ff2..11d0c6f6a 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.h +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxAndLabel.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface TableViewCellWithCheckBoxAndLabel : MXKTableViewCell diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.h b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.h index 407c9bc6c..a3b690e9e 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.h +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithCheckBoxes.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class TableViewCellWithCheckBoxes; diff --git a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.h b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.h index d786b1881..a8a671c49 100644 --- a/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.h +++ b/Riot/Modules/Room/Settings/Views/TableViewCellWithLabelAndLargeTextView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface TableViewCellWithLabelAndLargeTextView : MXKTableViewCell diff --git a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h index b66c61a5f..c48a01d45 100644 --- a/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h +++ b/Riot/Modules/Room/Views/Activities/RoomActivitiesView.h @@ -15,7 +15,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** diff --git a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h index 31d5ccaa9..77613aa9a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/Encryption/RoomEncryptedDataBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** Action identifier used when the user tapped on the marker displayed in front of an encrypted event. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomEmptyBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomEmptyBubbleCell.h index 5ce42873c..ce1289131 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomEmptyBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomEmptyBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomEmptyBubbleCell` displays empty bubbles. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.h index 23157a7e5..5ebb2edbf 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomIncomingAttachmentBubbleCell` displays incoming attachment bubbles with sender's information. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h index 72273f706..ffea85ea4 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithPaginationTitleBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomIncomingAttachmentWithPaginationTitleBubbleCell` displays incoming attachment bubbles with sender's information and a pagination title. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h index 2c865f742..31d79802e 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingAttachmentWithoutSenderInfoBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomIncomingAttachmentWithoutSenderInfoBubbleCell` displays incoming message bubbles without sender's information. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.h index e10ae971d..a00448824 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomIncomingTextMsgBubbleCell` displays incoming message bubbles with sender's information. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h index 146ad5f53..436dc3173 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithPaginationTitleBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomIncomingTextMsgWithPaginationTitleBubbleCell` displays incoming message bubbles with sender's information. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h index bd3d2172f..a38e18655 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomIncomingTextMsgWithoutSenderInfoBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomIncomingTextMsgWithoutSenderInfoBubbleCell` displays incoming message bubbles without sender's information. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.h index ab94b9832..57809990a 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomOutgoingAttachmentBubbleCell` displays outgoing attachment bubbles. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h index e7b30e50c..90fab30c2 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingAttachmentWithoutSenderInfoBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "RoomOutgoingAttachmentBubbleCell.h" /** diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.h index 14074912c..08cab9b9f 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomOutgoingTextMsgBubbleCell` displays outgoing message bubbles with user's picture and name. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h index 46879d91f..6fac9533d 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomOutgoingTextMsgWithoutSenderInfoBubbleCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `RoomOutgoingTextMsgWithoutSenderInfoBubbleCell` displays outgoing message bubbles without user's name. diff --git a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.h b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.h index 7e026f5a1..192499066 100644 --- a/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.h +++ b/Riot/Modules/Room/Views/BubbleCells/RoomPredecessorBubbleCell.h @@ -16,7 +16,8 @@ @import UIKit; -@import MatrixKit; + +#import "MatrixKit.h" @interface RoomPredecessorBubbleCell : MXKRoomBubbleTableViewCell diff --git a/Riot/Modules/Room/Views/Event/EventDetailsView.h b/Riot/Modules/Room/Views/Event/EventDetailsView.h index 382bd9d02..35ae67034 100644 --- a/Riot/Modules/Room/Views/Event/EventDetailsView.h +++ b/Riot/Modules/Room/Views/Event/EventDetailsView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface EventDetailsView : MXKEventDetailsView diff --git a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.h b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.h index 0e3880d9e..5736fa60a 100644 --- a/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.h +++ b/Riot/Modules/Room/Views/InputToolbar/DisabledRoomInputToolbarView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** `DisabledRoomInputToolbarView` instance is an input toolbar to show to the end user diff --git a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h index d126ba22f..282687128 100644 --- a/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h +++ b/Riot/Modules/Room/Views/InputToolbar/RoomInputToolbarView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "MediaPickerViewController.h" diff --git a/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.h b/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.h index 923e23c02..ac41ab8f8 100644 --- a/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.h +++ b/Riot/Modules/Room/Views/Title/Avatar/RoomAvatarTitleView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface RoomAvatarTitleView : MXKRoomTitleView diff --git a/Riot/Modules/Room/Views/Title/RoomTitleView.h b/Riot/Modules/Room/Views/Title/RoomTitleView.h index 92aaed306..b59191205 100644 --- a/Riot/Modules/Room/Views/Title/RoomTitleView.h +++ b/Riot/Modules/Room/Views/Title/RoomTitleView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "RoomPreviewData.h" diff --git a/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.h b/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.h index dc62aa734..67d095c69 100644 --- a/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.h +++ b/Riot/Modules/Room/Views/Title/Simple/SimpleRoomTitleView.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** This title view display the room display name only. @@ -24,4 +24,4 @@ @property (weak, nonatomic) IBOutlet NSLayoutConstraint *displayNameCenterXConstraint; -@end \ No newline at end of file +@end diff --git a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.h b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.h index e4f3edbe4..cde40f6a4 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.h +++ b/Riot/Modules/Rooms/DirectoryPicker/DirectoryServerPickerViewController.h @@ -16,7 +16,7 @@ #import -#import +#import "MatrixKit.h" @interface DirectoryServerPickerViewController : MXKTableViewController diff --git a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.h b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.h index e145ef51f..8c68d5409 100644 --- a/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.h +++ b/Riot/Modules/Rooms/DirectoryPicker/Views/DirectoryServerTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** The `DirectoryServerTableViewCell` cell displays a server . diff --git a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.h b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.h index 4d403aa40..8916e0fa0 100644 --- a/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.h +++ b/Riot/Modules/Settings/DeactivateAccount/DeactivateAccountViewController.h @@ -15,7 +15,8 @@ */ @import UIKit; -@import MatrixKit; + +#import "MatrixKit.h" #pragma mark - Types diff --git a/Riot/Modules/Settings/Language/LanguagePickerViewController.h b/Riot/Modules/Settings/Language/LanguagePickerViewController.h index 0e65d0494..e4311bf08 100644 --- a/Riot/Modules/Settings/Language/LanguagePickerViewController.h +++ b/Riot/Modules/Settings/Language/LanguagePickerViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface LanguagePickerViewController : MXKLanguagePickerViewController diff --git a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.h b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.h index e77f6e66c..fe4bafe13 100644 --- a/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.h +++ b/Riot/Modules/Settings/PhoneCountry/CountryPickerViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface CountryPickerViewController : MXKCountryPickerViewController diff --git a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.h b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.h index c61242f7a..12a3d0b1a 100644 --- a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.h +++ b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface ManageSessionViewController : MXKTableViewController diff --git a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m index 49c49b087..b9b9ac474 100644 --- a/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m +++ b/Riot/Modules/Settings/Security/ManageSession/ManageSessionViewController.m @@ -16,8 +16,6 @@ #import "ManageSessionViewController.h" -#import - #import #import "AvatarGenerator.h" diff --git a/Riot/Modules/Settings/Security/SecurityViewController.h b/Riot/Modules/Settings/Security/SecurityViewController.h index 1452f3144..dd5d7001c 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.h +++ b/Riot/Modules/Settings/Security/SecurityViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface SecurityViewController : MXKTableViewController diff --git a/Riot/Modules/Settings/Security/SecurityViewController.m b/Riot/Modules/Settings/Security/SecurityViewController.m index 9feda8f59..7b5fd7d5f 100644 --- a/Riot/Modules/Settings/Security/SecurityViewController.m +++ b/Riot/Modules/Settings/Security/SecurityViewController.m @@ -18,8 +18,6 @@ #import "ManageSessionViewController.h" -#import - #import #import "AvatarGenerator.h" diff --git a/Riot/Modules/Settings/SettingsViewController.h b/Riot/Modules/Settings/SettingsViewController.h index 6d17449b1..dfe764538 100644 --- a/Riot/Modules/Settings/SettingsViewController.h +++ b/Riot/Modules/Settings/SettingsViewController.h @@ -14,11 +14,9 @@ limitations under the License. */ -#import +#import "MatrixKit.h" -#import "MediaPickerViewController.h" - -@interface SettingsViewController : MXKTableViewController +@interface SettingsViewController : MXKTableViewController + (instancetype)instantiate; diff --git a/Riot/Modules/Settings/SettingsViewController.m b/Riot/Modules/Settings/SettingsViewController.m index 87763dca2..91fa9afa7 100644 --- a/Riot/Modules/Settings/SettingsViewController.m +++ b/Riot/Modules/Settings/SettingsViewController.m @@ -18,8 +18,6 @@ #import "SettingsViewController.h" -#import - #import #import "AvatarGenerator.h" @@ -43,6 +41,8 @@ #import "GBDeviceInfo_iOS.h" +#import "MediaPickerViewController.h" + #import "GeneratedInterface-Swift.h" NSString* const kSettingsViewControllerPhoneBookCountryCellId = @"kSettingsViewControllerPhoneBookCountryCellId"; @@ -167,7 +167,7 @@ typedef void (^blockSettingsViewController_onReadyToDestroy)(void); #pragma mark - SettingsViewController -@interface SettingsViewController () +#import "MatrixKit.h" @interface DeviceView : MXKDeviceView diff --git a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.h b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.h index e237f5f31..f2b43da4f 100644 --- a/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.h +++ b/Riot/Modules/Settings/Views/TableViewCellWithPhoneNumberTextField.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** 'TableViewCellWithPhoneNumberTextField' inherits 'MXKTableViewCellWithLabelAndTextField' class. diff --git a/Riot/Modules/TabBar/MasterTabBarController.h b/Riot/Modules/TabBar/MasterTabBarController.h index 8207629a4..170e912d1 100644 --- a/Riot/Modules/TabBar/MasterTabBarController.h +++ b/Riot/Modules/TabBar/MasterTabBarController.h @@ -15,8 +15,6 @@ limitations under the License. */ -#import - #import "AuthenticationViewController.h" #import "RoomPreviewData.h" diff --git a/Riot/Modules/UserDevices/UsersDevicesViewController.h b/Riot/Modules/UserDevices/UsersDevicesViewController.h index 8e63d9968..3fad25b24 100644 --- a/Riot/Modules/UserDevices/UsersDevicesViewController.h +++ b/Riot/Modules/UserDevices/UsersDevicesViewController.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "DeviceTableViewCell.h" diff --git a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.h b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.h index b51cee2b5..9728603ca 100644 --- a/Riot/Modules/UserDevices/Views/DeviceTableViewCell.h +++ b/Riot/Modules/UserDevices/Views/DeviceTableViewCell.h @@ -14,7 +14,9 @@ limitations under the License. */ -#import +#import + +#import "MatrixKit.h" /** The `DeviceTableViewCell` cell displays the information on a device. diff --git a/Riot/Utils/EventFormatter.h b/Riot/Utils/EventFormatter.h index 4952f1441..3d7a39b1e 100644 --- a/Riot/Utils/EventFormatter.h +++ b/Riot/Utils/EventFormatter.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" /** Link string used in attributed strings to mark a keys re-request action. diff --git a/RiotShareExtension/Shared/ShareDataSource.h b/RiotShareExtension/Shared/ShareDataSource.h index d030ec795..9dc36d5f5 100644 --- a/RiotShareExtension/Shared/ShareDataSource.h +++ b/RiotShareExtension/Shared/ShareDataSource.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @class ShareDataSource; diff --git a/RiotShareExtension/Shared/ShareManager.h b/RiotShareExtension/Shared/ShareManager.h index aef3e21f5..c2b110a05 100644 --- a/RiotShareExtension/Shared/ShareManager.h +++ b/RiotShareExtension/Shared/ShareManager.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @protocol ShareItemSenderProtocol; diff --git a/RiotShareExtension/Shared/ShareManager.m b/RiotShareExtension/Shared/ShareManager.m index da77bfa18..d955f9da1 100644 --- a/RiotShareExtension/Shared/ShareManager.m +++ b/RiotShareExtension/Shared/ShareManager.m @@ -18,8 +18,6 @@ #import -#import - #import "ShareManager.h" #import "ShareViewController.h" #import "ShareDataSource.h" diff --git a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.h b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.h index 63eb213f7..34a7123e5 100644 --- a/RiotShareExtension/Shared/View/RecentRoomTableViewCell.h +++ b/RiotShareExtension/Shared/View/RecentRoomTableViewCell.h @@ -14,7 +14,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" @interface RecentRoomTableViewCell : MXKRecentTableViewCell diff --git a/RiotShareExtension/Shared/View/RoomsListViewController.m b/RiotShareExtension/Shared/View/RoomsListViewController.m index 926b9c4b2..ca4102564 100644 --- a/RiotShareExtension/Shared/View/RoomsListViewController.m +++ b/RiotShareExtension/Shared/View/RoomsListViewController.m @@ -14,8 +14,6 @@ limitations under the License. */ -#import - #import "RoomsListViewController.h" #import "RecentRoomTableViewCell.h" #import "ShareDataSource.h" diff --git a/SiriIntents/IntentHandler.m b/SiriIntents/IntentHandler.m index 9161e7926..e73af8312 100644 --- a/SiriIntents/IntentHandler.m +++ b/SiriIntents/IntentHandler.m @@ -16,8 +16,6 @@ #import "IntentHandler.h" -#import - #import "GeneratedInterface-Swift.h" #if __has_include() From d140c1ee88ed1d25bda048c575a39e07bf214ac3 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:06:25 +0100 Subject: [PATCH 086/122] HomeMessagesSearchDataSource: Fix MatrixKit import. --- .../Messages/DataSources/HomeMessagesSearchDataSource.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m index 8a60808cf..950715c17 100644 --- a/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m +++ b/Riot/Modules/GlobalSearch/Messages/DataSources/HomeMessagesSearchDataSource.m @@ -16,7 +16,7 @@ limitations under the License. */ -#import +#import "MatrixKit.h" #import "HomeMessagesSearchDataSource.h" From 5aa347814f68beaac8ad9bbf5043c5ed95407663 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:06:52 +0100 Subject: [PATCH 087/122] AuthInputsView: Add Swift generated header import. --- Riot/Modules/Authentication/Views/AuthInputsView.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Riot/Modules/Authentication/Views/AuthInputsView.m b/Riot/Modules/Authentication/Views/AuthInputsView.m index 5e037f5bf..43efbce8b 100644 --- a/Riot/Modules/Authentication/Views/AuthInputsView.m +++ b/Riot/Modules/Authentication/Views/AuthInputsView.m @@ -26,6 +26,8 @@ #import "RiotNavigationController.h" +#import "GeneratedInterface-Swift.h" + @interface AuthInputsView () { /** From 0be8a8df6477536751907cd7b4d4ebd5d6bc2719 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:10:04 +0100 Subject: [PATCH 088/122] Update Riot bridging header with new MatrixKit location. --- Riot/SupportingFiles/Riot-Bridging-Header.h | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/Riot/SupportingFiles/Riot-Bridging-Header.h b/Riot/SupportingFiles/Riot-Bridging-Header.h index bc899b068..96f80d271 100644 --- a/Riot/SupportingFiles/Riot-Bridging-Header.h +++ b/Riot/SupportingFiles/Riot-Bridging-Header.h @@ -3,7 +3,6 @@ // @import MatrixSDK; -@import MatrixKit; @import DTCoreText; #import "WebViewViewController.h" @@ -46,3 +45,21 @@ #import "RoomInputToolbarView.h" #import "NSArray+Element.h" #import "ShareItemSender.h" + +// MatrixKit common imports +#import "MatrixKit-Bridging-Header.h" + +// MatrixKit application imports +#import "MXKBarButtonItem.h" +#import "MXKPieChartView.h" +#import "MXKErrorAlertPresentation.h" +#import "MXKErrorPresentation.h" +#import "MXKErrorViewModel.h" +#import "MXKEncryptionKeysExportView.h" +#import "MXKTableViewCellWithLabelAndSwitch.h" +#import "MXKTableViewCellWithTextView.h" +#import "MXKTableViewCellWithButton.h" +#import "MXKRoomDataSourceManager.h" +#import "MXRoom+Sync.h" +#import "UIAlertController+MatrixKit.h" +#import "MXKAnalyticsConstants.h" From b991b6b48e743311da35c7d0b2bb172aad3af648 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:10:28 +0100 Subject: [PATCH 089/122] Add generated MatrixKit strings. --- Riot/Generated/MatrixKitStrings.swift | 1797 +++++++++++++++++++++++++ 1 file changed, 1797 insertions(+) create mode 100644 Riot/Generated/MatrixKitStrings.swift diff --git a/Riot/Generated/MatrixKitStrings.swift b/Riot/Generated/MatrixKitStrings.swift new file mode 100644 index 000000000..23a0802bc --- /dev/null +++ b/Riot/Generated/MatrixKitStrings.swift @@ -0,0 +1,1797 @@ +// swiftlint:disable all +// Generated using SwiftGen, by O.Halligon — https://github.com/SwiftGen/SwiftGen + +import Foundation + +// swiftlint:disable superfluous_disable_command +// swiftlint:disable file_length + +// MARK: - Strings + +// swiftlint:disable function_parameter_count identifier_name line_length type_body_length +@objcMembers +public class MatrixKitL10n: NSObject { + /// Abort + public static var abort: String { + return MatrixKitL10n.tr("MatrixKit", "abort") + } + /// Unable to verify email address. Please check your email and click on the link it contains. Once this is done, click continue + public static var accountEmailValidationError: String { + return MatrixKitL10n.tr("MatrixKit", "account_email_validation_error") + } + /// Please check your email and click on the link it contains. Once this is done, click continue. + public static var accountEmailValidationMessage: String { + return MatrixKitL10n.tr("MatrixKit", "account_email_validation_message") + } + /// Verification Pending + public static var accountEmailValidationTitle: String { + return MatrixKitL10n.tr("MatrixKit", "account_email_validation_title") + } + /// Display name change failed + public static var accountErrorDisplayNameChangeFailed: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_display_name_change_failed") + } + /// This doesn't appear to be a valid email address + public static var accountErrorEmailWrongDescription: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_email_wrong_description") + } + /// Invalid Email Address + public static var accountErrorEmailWrongTitle: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_email_wrong_title") + } + /// Matrix session is not opened + public static var accountErrorMatrixSessionIsNotOpened: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_matrix_session_is_not_opened") + } + /// This doesn't appear to be a valid phone number + public static var accountErrorMsisdnWrongDescription: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_msisdn_wrong_description") + } + /// Invalid Phone Number + public static var accountErrorMsisdnWrongTitle: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_msisdn_wrong_title") + } + /// Picture change failed + public static var accountErrorPictureChangeFailed: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_picture_change_failed") + } + /// Notifications not allowed + public static var accountErrorPushNotAllowed: String { + return MatrixKitL10n.tr("MatrixKit", "account_error_push_not_allowed") + } + /// Link Email + public static var accountLinkEmail: String { + return MatrixKitL10n.tr("MatrixKit", "account_link_email") + } + /// Linked emails + public static var accountLinkedEmails: String { + return MatrixKitL10n.tr("MatrixKit", "account_linked_emails") + } + /// Unable to verify phone number. + public static var accountMsisdnValidationError: String { + return MatrixKitL10n.tr("MatrixKit", "account_msisdn_validation_error") + } + /// We've sent an SMS with an activation code. Please enter this code below. + public static var accountMsisdnValidationMessage: String { + return MatrixKitL10n.tr("MatrixKit", "account_msisdn_validation_message") + } + /// Verification Pending + public static var accountMsisdnValidationTitle: String { + return MatrixKitL10n.tr("MatrixKit", "account_msisdn_validation_title") + } + /// Save changes + public static var accountSaveChanges: String { + return MatrixKitL10n.tr("MatrixKit", "account_save_changes") + } + /// Logout + public static var actionLogout: String { + return MatrixKitL10n.tr("MatrixKit", "action_logout") + } + /// Answer Call + public static var answerCall: String { + return MatrixKitL10n.tr("MatrixKit", "answer_call") + } + /// Attach Media from Library + public static var attachMedia: String { + return MatrixKitL10n.tr("MatrixKit", "attach_media") + } + /// Cancel the download? + public static var attachmentCancelDownload: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_cancel_download") + } + /// Cancel the upload? + public static var attachmentCancelUpload: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_cancel_upload") + } + /// This file contains encryption keys exported from a Matrix client.\nDo you want to view the file content or import the keys it contains? + public static var attachmentE2eKeysFilePrompt: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_e2e_keys_file_prompt") + } + /// Import... + public static var attachmentE2eKeysImport: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_e2e_keys_import") + } + /// Large (~%@) + public static func attachmentLarge(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_large", p1) + } + /// Large %@ (~%@) + public static func attachmentLargeWithResolution(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_large_with_resolution", p1, p2) + } + /// Medium (~%@) + public static func attachmentMedium(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_medium", p1) + } + /// Medium %@ (~%@) + public static func attachmentMediumWithResolution(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_medium_with_resolution", p1, p2) + } + /// Actual Size + public static var attachmentMultiselectionOriginal: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_multiselection_original") + } + /// Do you want to send images as: + public static var attachmentMultiselectionSizePrompt: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_multiselection_size_prompt") + } + /// Actual Size (%@) + public static func attachmentOriginal(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_original", p1) + } + /// Do you want to send as: + public static var attachmentSizePrompt: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_size_prompt") + } + /// You can turn this off in settings. + public static var attachmentSizePromptMessage: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_size_prompt_message") + } + /// Confirm size to send + public static var attachmentSizePromptTitle: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_size_prompt_title") + } + /// Small (~%@) + public static func attachmentSmall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_small", p1) + } + /// Small %@ (~%@) + public static func attachmentSmallWithResolution(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "attachment_small_with_resolution", p1, p2) + } + /// This file type is not supported. + public static var attachmentUnsupportedPreviewMessage: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_unsupported_preview_message") + } + /// Unable to preview + public static var attachmentUnsupportedPreviewTitle: String { + return MatrixKitL10n.tr("MatrixKit", "attachment_unsupported_preview_title") + } + /// Invalid username + public static var authInvalidUserName: String { + return MatrixKitL10n.tr("MatrixKit", "auth_invalid_user_name") + } + /// Not found + public static var authResetPasswordErrorNotFound: String { + return MatrixKitL10n.tr("MatrixKit", "auth_reset_password_error_not_found") + } + /// Unauthorized + public static var authResetPasswordErrorUnauthorized: String { + return MatrixKitL10n.tr("MatrixKit", "auth_reset_password_error_unauthorized") + } + /// Username in use + public static var authUsernameInUse: String { + return MatrixKitL10n.tr("MatrixKit", "auth_username_in_use") + } + /// Back + public static var back: String { + return MatrixKitL10n.tr("MatrixKit", "back") + } + /// Ban + public static var ban: String { + return MatrixKitL10n.tr("MatrixKit", "ban") + } + /// Connecting… + public static var callConnecting: String { + return MatrixKitL10n.tr("MatrixKit", "call_connecting") + } + /// Consulting with %@ + public static func callConsultingWithUser(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "call_consulting_with_user", p1) + } + /// Call ended + public static var callEnded: String { + return MatrixKitL10n.tr("MatrixKit", "call_ended") + } + /// You held the call + public static var callHolded: String { + return MatrixKitL10n.tr("MatrixKit", "call_holded") + } + /// Call Invite Expired + public static var callInviteExpired: String { + return MatrixKitL10n.tr("MatrixKit", "call_invite_expired") + } + /// Device Speaker + public static var callMoreActionsAudioUseDevice: String { + return MatrixKitL10n.tr("MatrixKit", "call_more_actions_audio_use_device") + } + /// Change Audio Device + public static var callMoreActionsChangeAudioDevice: String { + return MatrixKitL10n.tr("MatrixKit", "call_more_actions_change_audio_device") + } + /// Dial pad + public static var callMoreActionsDialpad: String { + return MatrixKitL10n.tr("MatrixKit", "call_more_actions_dialpad") + } + /// Hold + public static var callMoreActionsHold: String { + return MatrixKitL10n.tr("MatrixKit", "call_more_actions_hold") + } + /// Transfer + public static var callMoreActionsTransfer: String { + return MatrixKitL10n.tr("MatrixKit", "call_more_actions_transfer") + } + /// Resume + public static var callMoreActionsUnhold: String { + return MatrixKitL10n.tr("MatrixKit", "call_more_actions_unhold") + } + /// %@ held the call + public static func callRemoteHolded(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "call_remote_holded", p1) + } + /// Ringing… + public static var callRinging: String { + return MatrixKitL10n.tr("MatrixKit", "call_ringing") + } + /// Transfer to %@ + public static func callTransferToUser(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "call_transfer_to_user", p1) + } + /// Video call with %@ + public static func callVideoWithUser(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "call_video_with_user", p1) + } + /// Voice call with %@ + public static func callVoiceWithUser(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "call_voice_with_user", p1) + } + /// Video calls require access to the Camera but %@ doesn't have permission to use it + public static func cameraAccessNotGrantedForCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "camera_access_not_granted_for_call", p1) + } + /// Cancel + public static var cancel: String { + return MatrixKitL10n.tr("MatrixKit", "cancel") + } + /// Cancel Download + public static var cancelDownload: String { + return MatrixKitL10n.tr("MatrixKit", "cancel_download") + } + /// Cancel Upload + public static var cancelUpload: String { + return MatrixKitL10n.tr("MatrixKit", "cancel_upload") + } + /// Take Photo/Video + public static var captureMedia: String { + return MatrixKitL10n.tr("MatrixKit", "capture_media") + } + /// Close + public static var close: String { + return MatrixKitL10n.tr("MatrixKit", "close") + } + /// Local Contacts + public static var contactLocalContacts: String { + return MatrixKitL10n.tr("MatrixKit", "contact_local_contacts") + } + /// Matrix Users + public static var contactMxUsers: String { + return MatrixKitL10n.tr("MatrixKit", "contact_mx_users") + } + /// Continue + public static var `continue`: String { + return MatrixKitL10n.tr("MatrixKit", "continue") + } + /// Copy + public static var copyButtonName: String { + return MatrixKitL10n.tr("MatrixKit", "copy_button_name") + } + /// Choose a country + public static var countryPickerTitle: String { + return MatrixKitL10n.tr("MatrixKit", "country_picker_title") + } + /// Create Account + public static var createAccount: String { + return MatrixKitL10n.tr("MatrixKit", "create_account") + } + /// Create Room + public static var createRoom: String { + return MatrixKitL10n.tr("MatrixKit", "create_room") + } + /// default + public static var `default`: String { + return MatrixKitL10n.tr("MatrixKit", "default") + } + /// Delete + public static var delete: String { + return MatrixKitL10n.tr("MatrixKit", "delete") + } + /// This operation requires additional authentication.\nTo continue, please enter your password. + public static var deviceDetailsDeletePromptMessage: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_delete_prompt_message") + } + /// Authentication + public static var deviceDetailsDeletePromptTitle: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_delete_prompt_title") + } + /// ID\n + public static var deviceDetailsIdentifier: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_identifier") + } + /// Last seen\n + public static var deviceDetailsLastSeen: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_last_seen") + } + /// %@ @ %@\n + public static func deviceDetailsLastSeenFormat(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "device_details_last_seen_format", p1, p2) + } + /// Public Name\n + public static var deviceDetailsName: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_name") + } + /// A session's public name is visible to people you communicate with + public static var deviceDetailsRenamePromptMessage: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_rename_prompt_message") + } + /// Session Name + public static var deviceDetailsRenamePromptTitle: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_rename_prompt_title") + } + /// Session information\n + public static var deviceDetailsTitle: String { + return MatrixKitL10n.tr("MatrixKit", "device_details_title") + } + /// Discard + public static var discard: String { + return MatrixKitL10n.tr("MatrixKit", "discard") + } + /// Dismiss + public static var dismiss: String { + return MatrixKitL10n.tr("MatrixKit", "dismiss") + } + /// Export + public static var e2eExport: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_export") + } + /// This process allows you to export the keys for messages you have received in encrypted rooms to a local file. You will then be able to import the file into another Matrix client in the future, so that client will also be able to decrypt these messages.\nThe exported file will allow anyone who can read it to decrypt any encrypted messages that you can see, so you should be careful to keep it secure. + public static var e2eExportPrompt: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_export_prompt") + } + /// Export room keys + public static var e2eExportRoomKeys: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_export_room_keys") + } + /// Import + public static var e2eImport: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_import") + } + /// This process allows you to import encryption keys that you had previously exported from another Matrix client. You will then be able to decrypt any messages that the other client could decrypt.\nThe export file is protected with a passphrase. You should enter the passphrase here, to decrypt the file. + public static var e2eImportPrompt: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_import_prompt") + } + /// Import room keys + public static var e2eImportRoomKeys: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_import_room_keys") + } + /// Confirm passphrase + public static var e2ePassphraseConfirm: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_passphrase_confirm") + } + /// Create passphrase + public static var e2ePassphraseCreate: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_passphrase_create") + } + /// Passphrase must not be empty + public static var e2ePassphraseEmpty: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_passphrase_empty") + } + /// Enter passphrase + public static var e2ePassphraseEnter: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_passphrase_enter") + } + /// Passphrases must match + public static var e2ePassphraseNotMatch: String { + return MatrixKitL10n.tr("MatrixKit", "e2e_passphrase_not_match") + } + /// Passphrase too short (It must be at a minimum %d characters in length) + public static func e2ePassphraseTooShort(_ p1: Int) -> String { + return MatrixKitL10n.tr("MatrixKit", "e2e_passphrase_too_short", p1) + } + /// End Call + public static var endCall: String { + return MatrixKitL10n.tr("MatrixKit", "end_call") + } + /// Error + public static var error: String { + return MatrixKitL10n.tr("MatrixKit", "error") + } + /// An error occured. Please try again later. + public static var errorCommonMessage: String { + return MatrixKitL10n.tr("MatrixKit", "error_common_message") + } + /// d + public static var formatTimeD: String { + return MatrixKitL10n.tr("MatrixKit", "format_time_d") + } + /// h + public static var formatTimeH: String { + return MatrixKitL10n.tr("MatrixKit", "format_time_h") + } + /// m + public static var formatTimeM: String { + return MatrixKitL10n.tr("MatrixKit", "format_time_m") + } + /// s + public static var formatTimeS: String { + return MatrixKitL10n.tr("MatrixKit", "format_time_s") + } + /// Invites + public static var groupInviteSection: String { + return MatrixKitL10n.tr("MatrixKit", "group_invite_section") + } + /// Groups + public static var groupSection: String { + return MatrixKitL10n.tr("MatrixKit", "group_section") + } + /// Ignore + public static var ignore: String { + return MatrixKitL10n.tr("MatrixKit", "ignore") + } + /// Incoming Video Call + public static var incomingVideoCall: String { + return MatrixKitL10n.tr("MatrixKit", "incoming_video_call") + } + /// Incoming Voice Call + public static var incomingVoiceCall: String { + return MatrixKitL10n.tr("MatrixKit", "incoming_voice_call") + } + /// I'd like to chat with you with matrix. Please, visit the website http://matrix.org to have more information. + public static var invitationMessage: String { + return MatrixKitL10n.tr("MatrixKit", "invitation_message") + } + /// Invite + public static var invite: String { + return MatrixKitL10n.tr("MatrixKit", "invite") + } + /// Invite matrix User + public static var inviteUser: String { + return MatrixKitL10n.tr("MatrixKit", "invite_user") + } + /// Kick + public static var kick: String { + return MatrixKitL10n.tr("MatrixKit", "kick") + } + /// Default (%@) + public static func languagePickerDefaultLanguage(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "language_picker_default_language", p1) + } + /// Choose a language + public static var languagePickerTitle: String { + return MatrixKitL10n.tr("MatrixKit", "language_picker_title") + } + /// Leave + public static var leave: String { + return MatrixKitL10n.tr("MatrixKit", "leave") + } + /// To discover contacts already using Matrix, %@ can send email addresses and phone numbers in your address book to your chosen Matrix identity server. Where supported, personal data is hashed before sending - please check your identity server's privacy policy for more details. + public static func localContactsAccessDiscoveryWarning(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "local_contacts_access_discovery_warning", p1) + } + /// Users discovery + public static var localContactsAccessDiscoveryWarningTitle: String { + return MatrixKitL10n.tr("MatrixKit", "local_contacts_access_discovery_warning_title") + } + /// Users discovery from local contacts requires access to you contacts but %@ doesn't have permission to use it + public static func localContactsAccessNotGranted(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "local_contacts_access_not_granted", p1) + } + /// Login + public static var login: String { + return MatrixKitL10n.tr("MatrixKit", "login") + } + /// Create account: + public static var loginCreateAccount: String { + return MatrixKitL10n.tr("MatrixKit", "login_create_account") + } + /// Desktop + public static var loginDesktopDevice: String { + return MatrixKitL10n.tr("MatrixKit", "login_desktop_device") + } + /// Display name (e.g. Bob Obson) + public static var loginDisplayNamePlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "login_display_name_placeholder") + } + /// Specify an email address lets other users find you on Matrix more easily, and will give you a way to reset your password in the future. + public static var loginEmailInfo: String { + return MatrixKitL10n.tr("MatrixKit", "login_email_info") + } + /// Email address + public static var loginEmailPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "login_email_placeholder") + } + /// Already logged in + public static var loginErrorAlreadyLoggedIn: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_already_logged_in") + } + /// Malformed JSON + public static var loginErrorBadJson: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_bad_json") + } + /// Currently we do not support any or all login flows defined by this homeserver + public static var loginErrorDoNotSupportLoginFlows: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_do_not_support_login_flows") + } + /// Invalid username/password + public static var loginErrorForbidden: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_forbidden") + } + /// Forgot password is not currently supported + public static var loginErrorForgotPasswordIsNotSupported: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_forgot_password_is_not_supported") + } + /// Too many requests have been sent + public static var loginErrorLimitExceeded: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_limit_exceeded") + } + /// The email link which has not been clicked yet + public static var loginErrorLoginEmailNotYet: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_login_email_not_yet") + } + /// URL must start with http[s]:// + public static var loginErrorMustStartHttp: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_must_start_http") + } + /// We failed to retrieve authentication information from this homeserver + public static var loginErrorNoLoginFlow: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_no_login_flow") + } + /// Did not contain valid JSON + public static var loginErrorNotJson: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_not_json") + } + /// Registration is not currently supported + public static var loginErrorRegistrationIsNotSupported: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_registration_is_not_supported") + } + /// Contact Administrator + public static var loginErrorResourceLimitExceededContactButton: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_resource_limit_exceeded_contact_button") + } + /// \n\nPlease contact your service administrator to continue using this service. + public static var loginErrorResourceLimitExceededMessageContact: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_resource_limit_exceeded_message_contact") + } + /// This homeserver has exceeded one of its resource limits. + public static var loginErrorResourceLimitExceededMessageDefault: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_resource_limit_exceeded_message_default") + } + /// This homeserver has hit its Monthly Active User limit. + public static var loginErrorResourceLimitExceededMessageMonthlyActiveUser: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_resource_limit_exceeded_message_monthly_active_user") + } + /// Resource Limit Exceeded + public static var loginErrorResourceLimitExceededTitle: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_resource_limit_exceeded_title") + } + /// Login Failed + public static var loginErrorTitle: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_title") + } + /// The access token specified was not recognised + public static var loginErrorUnknownToken: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_unknown_token") + } + /// This user name is already used + public static var loginErrorUserInUse: String { + return MatrixKitL10n.tr("MatrixKit", "login_error_user_in_use") + } + /// Your homeserver stores all your conversations and account data + public static var loginHomeServerInfo: String { + return MatrixKitL10n.tr("MatrixKit", "login_home_server_info") + } + /// Homeserver URL: + public static var loginHomeServerTitle: String { + return MatrixKitL10n.tr("MatrixKit", "login_home_server_title") + } + /// Matrix provides identity servers to track which emails etc. belong to which Matrix IDs. Only https://matrix.org currently exists. + public static var loginIdentityServerInfo: String { + return MatrixKitL10n.tr("MatrixKit", "login_identity_server_info") + } + /// Identity server URL: + public static var loginIdentityServerTitle: String { + return MatrixKitL10n.tr("MatrixKit", "login_identity_server_title") + } + /// Invalid parameter + public static var loginInvalidParam: String { + return MatrixKitL10n.tr("MatrixKit", "login_invalid_param") + } + /// Cancel + public static var loginLeaveFallback: String { + return MatrixKitL10n.tr("MatrixKit", "login_leave_fallback") + } + /// Mobile + public static var loginMobileDevice: String { + return MatrixKitL10n.tr("MatrixKit", "login_mobile_device") + } + /// optional + public static var loginOptionalField: String { + return MatrixKitL10n.tr("MatrixKit", "login_optional_field") + } + /// Password + public static var loginPasswordPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "login_password_placeholder") + } + /// Please enter your email validation token: + public static var loginPromptEmailToken: String { + return MatrixKitL10n.tr("MatrixKit", "login_prompt_email_token") + } + /// URL (e.g. https://matrix.org) + public static var loginServerUrlPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "login_server_url_placeholder") + } + /// Tablet + public static var loginTabletDevice: String { + return MatrixKitL10n.tr("MatrixKit", "login_tablet_device") + } + /// Use fallback page + public static var loginUseFallback: String { + return MatrixKitL10n.tr("MatrixKit", "login_use_fallback") + } + /// Matrix ID (e.g. @bob:matrix.org or bob) + public static var loginUserIdPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "login_user_id_placeholder") + } + /// Matrix + public static var matrix: String { + return MatrixKitL10n.tr("MatrixKit", "matrix") + } + /// Banned + public static var membershipBan: String { + return MatrixKitL10n.tr("MatrixKit", "membership_ban") + } + /// Invited + public static var membershipInvite: String { + return MatrixKitL10n.tr("MatrixKit", "membership_invite") + } + /// Left + public static var membershipLeave: String { + return MatrixKitL10n.tr("MatrixKit", "membership_leave") + } + /// Mention + public static var mention: String { + return MatrixKitL10n.tr("MatrixKit", "mention") + } + /// In reply to + public static var messageReplyToMessageToReplyToPrefix: String { + return MatrixKitL10n.tr("MatrixKit", "message_reply_to_message_to_reply_to_prefix") + } + /// sent a file. + public static var messageReplyToSenderSentAFile: String { + return MatrixKitL10n.tr("MatrixKit", "message_reply_to_sender_sent_a_file") + } + /// sent a video. + public static var messageReplyToSenderSentAVideo: String { + return MatrixKitL10n.tr("MatrixKit", "message_reply_to_sender_sent_a_video") + } + /// sent a voice message. + public static var messageReplyToSenderSentAVoiceMessage: String { + return MatrixKitL10n.tr("MatrixKit", "message_reply_to_sender_sent_a_voice_message") + } + /// sent an audio file. + public static var messageReplyToSenderSentAnAudioFile: String { + return MatrixKitL10n.tr("MatrixKit", "message_reply_to_sender_sent_an_audio_file") + } + /// sent an image. + public static var messageReplyToSenderSentAnImage: String { + return MatrixKitL10n.tr("MatrixKit", "message_reply_to_sender_sent_an_image") + } + /// There are unsaved changes. Leaving will discard them. + public static var messageUnsavedChanges: String { + return MatrixKitL10n.tr("MatrixKit", "message_unsaved_changes") + } + /// Calls require access to the Microphone but %@ doesn't have permission to use it + public static func microphoneAccessNotGrantedForCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "microphone_access_not_granted_for_call", p1) + } + /// Voice messages require access to the Microphone but %@ doesn't have permission to use it + public static func microphoneAccessNotGrantedForVoiceMessage(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "microphone_access_not_granted_for_voice_message", p1) + } + /// Please check your network connectivity + public static var networkErrorNotReachable: String { + return MatrixKitL10n.tr("MatrixKit", "network_error_not_reachable") + } + /// No + public static var no: String { + return MatrixKitL10n.tr("MatrixKit", "no") + } + /// Not supported yet + public static var notSupportedYet: String { + return MatrixKitL10n.tr("MatrixKit", "not_supported_yet") + } + /// %@ answered the call + public static func noticeAnsweredVideoCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_answered_video_call", p1) + } + /// You answered the call + public static var noticeAnsweredVideoCallByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_answered_video_call_by_you") + } + /// audio attachment + public static var noticeAudioAttachment: String { + return MatrixKitL10n.tr("MatrixKit", "notice_audio_attachment") + } + /// (avatar was changed too) + public static var noticeAvatarChangedToo: String { + return MatrixKitL10n.tr("MatrixKit", "notice_avatar_changed_too") + } + /// %@ changed their avatar + public static func noticeAvatarUrlChanged(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_avatar_url_changed", p1) + } + /// You changed your avatar + public static var noticeAvatarUrlChangedByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_avatar_url_changed_by_you") + } + /// VoIP conference finished + public static var noticeConferenceCallFinished: String { + return MatrixKitL10n.tr("MatrixKit", "notice_conference_call_finished") + } + /// %@ requested a VoIP conference + public static func noticeConferenceCallRequest(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_conference_call_request", p1) + } + /// You requested a VoIP conference + public static var noticeConferenceCallRequestByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_conference_call_request_by_you") + } + /// VoIP conference started + public static var noticeConferenceCallStarted: String { + return MatrixKitL10n.tr("MatrixKit", "notice_conference_call_started") + } + /// The sender's session has not sent us the keys for this message. + public static var noticeCryptoErrorUnknownInboundSessionId: String { + return MatrixKitL10n.tr("MatrixKit", "notice_crypto_error_unknown_inbound_session_id") + } + /// ** Unable to decrypt: %@ ** + public static func noticeCryptoUnableToDecrypt(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_crypto_unable_to_decrypt", p1) + } + /// %@ declined the call + public static func noticeDeclinedVideoCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_declined_video_call", p1) + } + /// You declined the call + public static var noticeDeclinedVideoCallByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_declined_video_call_by_you") + } + /// %@ changed their display name from %@ to %@ + public static func noticeDisplayNameChangedFrom(_ p1: String, _ p2: String, _ p3: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_display_name_changed_from", p1, p2, p3) + } + /// You changed your display name from %@ to %@ + public static func noticeDisplayNameChangedFromByYou(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_display_name_changed_from_by_you", p1, p2) + } + /// %@ removed their display name + public static func noticeDisplayNameRemoved(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_display_name_removed", p1) + } + /// You removed your display name + public static var noticeDisplayNameRemovedByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_display_name_removed_by_you") + } + /// %@ set their display name to %@ + public static func noticeDisplayNameSet(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_display_name_set", p1, p2) + } + /// You set your display name to %@ + public static func noticeDisplayNameSetByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_display_name_set_by_you", p1) + } + /// Encrypted message + public static var noticeEncryptedMessage: String { + return MatrixKitL10n.tr("MatrixKit", "notice_encrypted_message") + } + /// %@ turned on end-to-end encryption. + public static func noticeEncryptionEnabledOk(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_encryption_enabled_ok", p1) + } + /// You turned on end-to-end encryption. + public static var noticeEncryptionEnabledOkByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_encryption_enabled_ok_by_you") + } + /// %1$@ turned on end-to-end encryption (unrecognised algorithm %2$@). + public static func noticeEncryptionEnabledUnknownAlgorithm(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_encryption_enabled_unknown_algorithm", p1, p2) + } + /// You turned on end-to-end encryption (unrecognised algorithm %@). + public static func noticeEncryptionEnabledUnknownAlgorithmByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_encryption_enabled_unknown_algorithm_by_you", p1) + } + /// %@ ended the call + public static func noticeEndedVideoCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_ended_video_call", p1) + } + /// You ended the call + public static var noticeEndedVideoCallByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_ended_video_call_by_you") + } + /// Unexpected event + public static var noticeErrorUnexpectedEvent: String { + return MatrixKitL10n.tr("MatrixKit", "notice_error_unexpected_event") + } + /// Unknown event type + public static var noticeErrorUnknownEventType: String { + return MatrixKitL10n.tr("MatrixKit", "notice_error_unknown_event_type") + } + /// Unsupported event + public static var noticeErrorUnsupportedEvent: String { + return MatrixKitL10n.tr("MatrixKit", "notice_error_unsupported_event") + } + /// + public static func noticeEventRedacted(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_event_redacted", p1) + } + /// by %@ + public static func noticeEventRedactedBy(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_event_redacted_by", p1) + } + /// by you + public static var noticeEventRedactedByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_event_redacted_by_you") + } + /// [reason: %@] + public static func noticeEventRedactedReason(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_event_redacted_reason", p1) + } + /// Feedback event (id: %@): %@ + public static func noticeFeedback(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_feedback", p1, p2) + } + /// file attachment + public static var noticeFileAttachment: String { + return MatrixKitL10n.tr("MatrixKit", "notice_file_attachment") + } + /// image attachment + public static var noticeImageAttachment: String { + return MatrixKitL10n.tr("MatrixKit", "notice_image_attachment") + } + /// In reply to + public static var noticeInReplyTo: String { + return MatrixKitL10n.tr("MatrixKit", "notice_in_reply_to") + } + /// invalid attachment + public static var noticeInvalidAttachment: String { + return MatrixKitL10n.tr("MatrixKit", "notice_invalid_attachment") + } + /// location attachment + public static var noticeLocationAttachment: String { + return MatrixKitL10n.tr("MatrixKit", "notice_location_attachment") + } + /// %@ placed a video call + public static func noticePlacedVideoCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_placed_video_call", p1) + } + /// You placed a video call + public static var noticePlacedVideoCallByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_placed_video_call_by_you") + } + /// %@ placed a voice call + public static func noticePlacedVoiceCall(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_placed_voice_call", p1) + } + /// You placed a voice call + public static var noticePlacedVoiceCallByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_placed_voice_call_by_you") + } + /// %@ updated their profile %@ + public static func noticeProfileChangeRedacted(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_profile_change_redacted", p1, p2) + } + /// You updated your profile %@ + public static func noticeProfileChangeRedactedByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_profile_change_redacted_by_you", p1) + } + /// %@ redacted an event (id: %@) + public static func noticeRedaction(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_redaction", p1, p2) + } + /// You redacted an event (id: %@) + public static func noticeRedactionByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_redaction_by_you", p1) + } + /// The room aliases are: %@ + public static func noticeRoomAliases(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_aliases", p1) + } + /// The aliases are: %@ + public static func noticeRoomAliasesForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_aliases_for_dm", p1) + } + /// %@ banned %@ + public static func noticeRoomBan(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_ban", p1, p2) + } + /// You banned %@ + public static func noticeRoomBanByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_ban_by_you", p1) + } + /// %@ created and configured the room. + public static func noticeRoomCreated(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_created", p1) + } + /// You created and configured the room. + public static var noticeRoomCreatedByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_created_by_you") + } + /// You joined. + public static var noticeRoomCreatedByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_created_by_you_for_dm") + } + /// %@ joined. + public static func noticeRoomCreatedForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_created_for_dm", p1) + } + /// %@ made future room history visible to anyone. + public static func noticeRoomHistoryVisibleToAnyone(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_anyone", p1) + } + /// You made future room history visible to anyone. + public static var noticeRoomHistoryVisibleToAnyoneByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_anyone_by_you") + } + /// %@ made future room history visible to all room members. + public static func noticeRoomHistoryVisibleToMembers(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members", p1) + } + /// You made future room history visible to all room members. + public static var noticeRoomHistoryVisibleToMembersByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_by_you") + } + /// You made future messages visible to all room members. + public static var noticeRoomHistoryVisibleToMembersByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_by_you_for_dm") + } + /// %@ made future messages visible to all room members. + public static func noticeRoomHistoryVisibleToMembersForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_for_dm", p1) + } + /// %@ made future room history visible to all room members, from the point they are invited. + public static func noticeRoomHistoryVisibleToMembersFromInvitedPoint(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_invited_point", p1) + } + /// You made future room history visible to all room members, from the point they are invited. + public static var noticeRoomHistoryVisibleToMembersFromInvitedPointByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_invited_point_by_you") + } + /// You made future messages visible to everyone, from when they get invited. + public static var noticeRoomHistoryVisibleToMembersFromInvitedPointByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_invited_point_by_you_for_dm") + } + /// %@ made future messages visible to everyone, from when they get invited. + public static func noticeRoomHistoryVisibleToMembersFromInvitedPointForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_invited_point_for_dm", p1) + } + /// %@ made future room history visible to all room members, from the point they joined. + public static func noticeRoomHistoryVisibleToMembersFromJoinedPoint(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_joined_point", p1) + } + /// You made future room history visible to all room members, from the point they joined. + public static var noticeRoomHistoryVisibleToMembersFromJoinedPointByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_joined_point_by_you") + } + /// You made future messages visible to everyone, from when they joined. + public static var noticeRoomHistoryVisibleToMembersFromJoinedPointByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_joined_point_by_you_for_dm") + } + /// %@ made future messages visible to everyone, from when they joined. + public static func noticeRoomHistoryVisibleToMembersFromJoinedPointForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_history_visible_to_members_from_joined_point_for_dm", p1) + } + /// %@ invited %@ + public static func noticeRoomInvite(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_invite", p1, p2) + } + /// You invited %@ + public static func noticeRoomInviteByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_invite_by_you", p1) + } + /// %@ invited you + public static func noticeRoomInviteYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_invite_you", p1) + } + /// %@ joined + public static func noticeRoomJoin(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join", p1) + } + /// You joined + public static var noticeRoomJoinByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_by_you") + } + /// The join rule is: %@ + public static func noticeRoomJoinRule(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule", p1) + } + /// %@ made the room invite only. + public static func noticeRoomJoinRuleInvite(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_invite", p1) + } + /// You made the room invite only. + public static var noticeRoomJoinRuleInviteByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_invite_by_you") + } + /// You made this invite only. + public static var noticeRoomJoinRuleInviteByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_invite_by_you_for_dm") + } + /// %@ made this invite only. + public static func noticeRoomJoinRuleInviteForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_invite_for_dm", p1) + } + /// %@ made the room public. + public static func noticeRoomJoinRulePublic(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_public", p1) + } + /// You made the room public. + public static var noticeRoomJoinRulePublicByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_public_by_you") + } + /// You made this public. + public static var noticeRoomJoinRulePublicByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_public_by_you_for_dm") + } + /// %@ made this public. + public static func noticeRoomJoinRulePublicForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_join_rule_public_for_dm", p1) + } + /// %@ kicked %@ + public static func noticeRoomKick(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_kick", p1, p2) + } + /// You kicked %@ + public static func noticeRoomKickByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_kick_by_you", p1) + } + /// %@ left + public static func noticeRoomLeave(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_leave", p1) + } + /// You left + public static var noticeRoomLeaveByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_leave_by_you") + } + /// %@ changed the room name to %@. + public static func noticeRoomNameChanged(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_changed", p1, p2) + } + /// You changed the room name to %@. + public static func noticeRoomNameChangedByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_changed_by_you", p1) + } + /// You changed the name to %@. + public static func noticeRoomNameChangedByYouForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_changed_by_you_for_dm", p1) + } + /// %@ changed the name to %@. + public static func noticeRoomNameChangedForDm(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_changed_for_dm", p1, p2) + } + /// %@ removed the room name + public static func noticeRoomNameRemoved(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_removed", p1) + } + /// You removed the room name + public static var noticeRoomNameRemovedByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_removed_by_you") + } + /// You removed the name + public static var noticeRoomNameRemovedByYouForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_removed_by_you_for_dm") + } + /// %@ removed the name + public static func noticeRoomNameRemovedForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_name_removed_for_dm", p1) + } + /// The minimum power levels that a user must have before acting are: + public static var noticeRoomPowerLevelActingRequirement: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_power_level_acting_requirement") + } + /// The minimum power levels related to events are: + public static var noticeRoomPowerLevelEventRequirement: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_power_level_event_requirement") + } + /// The power level of room members are: + public static var noticeRoomPowerLevelIntro: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_power_level_intro") + } + /// The power level of members are: + public static var noticeRoomPowerLevelIntroForDm: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_power_level_intro_for_dm") + } + /// . Reason: %@ + public static func noticeRoomReason(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_reason", p1) + } + /// %@ rejected the invitation + public static func noticeRoomReject(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_reject", p1) + } + /// You rejected the invitation + public static var noticeRoomRejectByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_reject_by_you") + } + /// The groups associated with this room are: %@ + public static func noticeRoomRelatedGroups(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_related_groups", p1) + } + /// %@ sent an invitation to %@ to join the room + public static func noticeRoomThirdPartyInvite(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_invite", p1, p2) + } + /// You sent an invitation to %@ to join the room + public static func noticeRoomThirdPartyInviteByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_invite_by_you", p1) + } + /// You invited %@ + public static func noticeRoomThirdPartyInviteByYouForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_invite_by_you_for_dm", p1) + } + /// %@ invited %@ + public static func noticeRoomThirdPartyInviteForDm(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_invite_for_dm", p1, p2) + } + /// %@ accepted the invitation for %@ + public static func noticeRoomThirdPartyRegisteredInvite(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_registered_invite", p1, p2) + } + /// You accepted the invitation for %@ + public static func noticeRoomThirdPartyRegisteredInviteByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_registered_invite_by_you", p1) + } + /// %@ revoked the invitation for %@ to join the room + public static func noticeRoomThirdPartyRevokedInvite(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_revoked_invite", p1, p2) + } + /// You revoked the invitation for %@ to join the room + public static func noticeRoomThirdPartyRevokedInviteByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_revoked_invite_by_you", p1) + } + /// You revoked %@'s invitation + public static func noticeRoomThirdPartyRevokedInviteByYouForDm(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_revoked_invite_by_you_for_dm", p1) + } + /// %@ revoked %@'s invitation + public static func noticeRoomThirdPartyRevokedInviteForDm(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_third_party_revoked_invite_for_dm", p1, p2) + } + /// %@ removed the topic + public static func noticeRoomTopicRemoved(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_topic_removed", p1) + } + /// You removed the topic + public static var noticeRoomTopicRemovedByYou: String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_topic_removed_by_you") + } + /// %@ unbanned %@ + public static func noticeRoomUnban(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_unban", p1, p2) + } + /// You unbanned %@ + public static func noticeRoomUnbanByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_unban_by_you", p1) + } + /// %@ withdrew %@'s invitation + public static func noticeRoomWithdraw(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_withdraw", p1, p2) + } + /// You withdrew %@'s invitation + public static func noticeRoomWithdrawByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_room_withdraw_by_you", p1) + } + /// sticker + public static var noticeSticker: String { + return MatrixKitL10n.tr("MatrixKit", "notice_sticker") + } + /// %@ changed the topic to "%@". + public static func noticeTopicChanged(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_topic_changed", p1, p2) + } + /// You changed the topic to "%@". + public static func noticeTopicChangedByYou(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_topic_changed_by_you", p1) + } + /// Unsupported attachment: %@ + public static func noticeUnsupportedAttachment(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notice_unsupported_attachment", p1) + } + /// video attachment + public static var noticeVideoAttachment: String { + return MatrixKitL10n.tr("MatrixKit", "notice_video_attachment") + } + /// Always notify + public static var notificationSettingsAlwaysNotify: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_always_notify") + } + /// By default... + public static var notificationSettingsByDefault: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_by_default") + } + /// Notify me with sound about messages that contain my display name + public static var notificationSettingsContainMyDisplayName: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_contain_my_display_name") + } + /// Notify me with sound about messages that contain my user name + public static var notificationSettingsContainMyUserName: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_contain_my_user_name") + } + /// Custom sound + public static var notificationSettingsCustomSound: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_custom_sound") + } + /// Disable all notifications + public static var notificationSettingsDisableAll: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_disable_all") + } + /// Enable notifications + public static var notificationSettingsEnableNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_enable_notifications") + } + /// All notifications are currently disabled for all devices. + public static var notificationSettingsEnableNotificationsWarning: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_enable_notifications_warning") + } + /// Notification settings are saved to your user account and are shared between all clients which support them (including desktop notifications).\n\nRules are applied in order; the first rule which matches defines the outcome for the message.\nSo: Per-word notifications are more important than per-room notifications which are more important than per-sender notifications.\nFor multiple rules of the same kind, the first one in the list that matches takes priority. + public static var notificationSettingsGlobalInfo: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_global_info") + } + /// Highlight + public static var notificationSettingsHighlight: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_highlight") + } + /// Notify me when I am invited to a new room + public static var notificationSettingsInviteToANewRoom: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_invite_to_a_new_room") + } + /// Notify me with sound about messages sent just to me + public static var notificationSettingsJustSentToMe: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_just_sent_to_me") + } + /// Never notify + public static var notificationSettingsNeverNotify: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_never_notify") + } + /// Notify for all other messages/rooms + public static var notificationSettingsNotifyAllOther: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_notify_all_other") + } + /// Other Alerts + public static var notificationSettingsOtherAlerts: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_other_alerts") + } + /// Notify me when people join or leave rooms + public static var notificationSettingsPeopleJoinLeaveRooms: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_people_join_leave_rooms") + } + /// Per-room notifications + public static var notificationSettingsPerRoomNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_per_room_notifications") + } + /// Per-sender notifications + public static var notificationSettingsPerSenderNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_per_sender_notifications") + } + /// Words match case insensitively, and may include a * wildcard. So:\nfoo matches the string foo surrounded by word delimiters (e.g. punctuation and whitespace or start/end of line).\nfoo* matches any such word that begins foo.\n*foo* matches any such word which includes the 3 letters foo. + public static var notificationSettingsPerWordInfo: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_per_word_info") + } + /// Per-word notifications + public static var notificationSettingsPerWordNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_per_word_notifications") + } + /// Notify me when I receive a call + public static var notificationSettingsReceiveACall: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_receive_a_call") + } + /// Room: '%@' + public static func notificationSettingsRoomRuleTitle(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_room_rule_title", p1) + } + /// Select a room + public static var notificationSettingsSelectRoom: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_select_room") + } + /// @user:domain.com + public static var notificationSettingsSenderHint: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_sender_hint") + } + /// Suppress notifications from bots + public static var notificationSettingsSuppressFromBots: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_suppress_from_bots") + } + /// word to match + public static var notificationSettingsWordToMatch: String { + return MatrixKitL10n.tr("MatrixKit", "notification_settings_word_to_match") + } + /// %@ user + public static func numMembersOne(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "num_members_one", p1) + } + /// %@ users + public static func numMembersOther(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "num_members_other", p1) + } + /// offline + public static var offline: String { + return MatrixKitL10n.tr("MatrixKit", "offline") + } + /// OK + public static var ok: String { + return MatrixKitL10n.tr("MatrixKit", "ok") + } + /// Power Level + public static var powerLevel: String { + return MatrixKitL10n.tr("MatrixKit", "power_level") + } + /// Private + public static var `private`: String { + return MatrixKitL10n.tr("MatrixKit", "private") + } + /// Public + public static var `public`: String { + return MatrixKitL10n.tr("MatrixKit", "public") + } + /// Remove + public static var redact: String { + return MatrixKitL10n.tr("MatrixKit", "redact") + } + /// Registration Failed + public static var registerErrorTitle: String { + return MatrixKitL10n.tr("MatrixKit", "register_error_title") + } + /// Reject Call + public static var rejectCall: String { + return MatrixKitL10n.tr("MatrixKit", "reject_call") + } + /// Rename + public static var rename: String { + return MatrixKitL10n.tr("MatrixKit", "rename") + } + /// Resend + public static var resend: String { + return MatrixKitL10n.tr("MatrixKit", "resend") + } + /// Resend the message + public static var resendMessage: String { + return MatrixKitL10n.tr("MatrixKit", "resend_message") + } + /// Reset to default + public static var resetToDefault: String { + return MatrixKitL10n.tr("MatrixKit", "reset_to_default") + } + /// Resume + public static var resumeCall: String { + return MatrixKitL10n.tr("MatrixKit", "resume_call") + } + /// Retry + public static var retry: String { + return MatrixKitL10n.tr("MatrixKit", "retry") + } + /// (e.g. #foo:example.org) + public static var roomCreationAliasPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_alias_placeholder") + } + /// (e.g. #foo%@) + public static func roomCreationAliasPlaceholderWithHomeserver(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_alias_placeholder_with_homeserver", p1) + } + /// Room alias: + public static var roomCreationAliasTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_alias_title") + } + /// (e.g. lunchGroup) + public static var roomCreationNamePlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_name_placeholder") + } + /// Room name: + public static var roomCreationNameTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_name_title") + } + /// (e.g. @bob:homeserver1; @john:homeserver2...) + public static var roomCreationParticipantsPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_participants_placeholder") + } + /// Participants: + public static var roomCreationParticipantsTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_creation_participants_title") + } + /// Room Details + public static var roomDetailsTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_details_title") + } + /// %@ (Left) + public static func roomDisplaynameAllOtherMembersLeft(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "room_displayname_all_other_members_left", p1) + } + /// Empty room + public static var roomDisplaynameEmptyRoom: String { + return MatrixKitL10n.tr("MatrixKit", "room_displayname_empty_room") + } + /// %@ and %@ others + public static func roomDisplaynameMoreThanTwoMembers(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "room_displayname_more_than_two_members", p1, p2) + } + /// %@ and %@ + public static func roomDisplaynameTwoMembers(_ p1: String, _ p2: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "room_displayname_two_members", p1, p2) + } + /// Failed to load timeline + public static var roomErrorCannotLoadTimeline: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_cannot_load_timeline") + } + /// It is not currently possible to join an empty room. + public static var roomErrorJoinFailedEmptyRoom: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_join_failed_empty_room") + } + /// Failed to join room + public static var roomErrorJoinFailedTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_join_failed_title") + } + /// You are not authorized to edit this room name + public static var roomErrorNameEditionNotAuthorized: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_name_edition_not_authorized") + } + /// The application was trying to load a specific point in this room's timeline but was unable to find it + public static var roomErrorTimelineEventNotFound: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_timeline_event_not_found") + } + /// Failed to load timeline position + public static var roomErrorTimelineEventNotFoundTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_timeline_event_not_found_title") + } + /// You are not authorized to edit this room topic + public static var roomErrorTopicEditionNotAuthorized: String { + return MatrixKitL10n.tr("MatrixKit", "room_error_topic_edition_not_authorized") + } + /// Blacklist + public static var roomEventEncryptionInfoBlock: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_block") + } + /// \nSender session information\n + public static var roomEventEncryptionInfoDevice: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device") + } + /// Blacklisted + public static var roomEventEncryptionInfoDeviceBlocked: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_blocked") + } + /// Ed25519 fingerprint\n + public static var roomEventEncryptionInfoDeviceFingerprint: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_fingerprint") + } + /// ID\n + public static var roomEventEncryptionInfoDeviceId: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_id") + } + /// Public Name\n + public static var roomEventEncryptionInfoDeviceName: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_name") + } + /// NOT verified + public static var roomEventEncryptionInfoDeviceNotVerified: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_not_verified") + } + /// unknown session\n + public static var roomEventEncryptionInfoDeviceUnknown: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_unknown") + } + /// Verification\n + public static var roomEventEncryptionInfoDeviceVerification: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_verification") + } + /// Verified + public static var roomEventEncryptionInfoDeviceVerified: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_device_verified") + } + /// Event information\n + public static var roomEventEncryptionInfoEvent: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event") + } + /// Algorithm\n + public static var roomEventEncryptionInfoEventAlgorithm: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_algorithm") + } + /// Decryption error\n + public static var roomEventEncryptionInfoEventDecryptionError: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_decryption_error") + } + /// Claimed Ed25519 fingerprint key\n + public static var roomEventEncryptionInfoEventFingerprintKey: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_fingerprint_key") + } + /// Curve25519 identity key\n + public static var roomEventEncryptionInfoEventIdentityKey: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_identity_key") + } + /// none + public static var roomEventEncryptionInfoEventNone: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_none") + } + /// Session ID\n + public static var roomEventEncryptionInfoEventSessionId: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_session_id") + } + /// unencrypted + public static var roomEventEncryptionInfoEventUnencrypted: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_unencrypted") + } + /// User ID\n + public static var roomEventEncryptionInfoEventUserId: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_event_user_id") + } + /// End-to-end encryption information\n\n + public static var roomEventEncryptionInfoTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_title") + } + /// Unblacklist + public static var roomEventEncryptionInfoUnblock: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_unblock") + } + /// Unverify + public static var roomEventEncryptionInfoUnverify: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_unverify") + } + /// Verify... + public static var roomEventEncryptionInfoVerify: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_info_verify") + } + /// To verify that this session can be trusted, please contact its owner using some other means (e.g. in person or a phone call) and ask them whether the key they see in their User Settings for this session matches the key below:\n\n Session name: %@\n Session ID: %@\n Session key: %@\n\nIf it matches, press the verify button below. If it doesnt, then someone else is intercepting this session and you probably want to press the blacklist button instead.\n\nIn future this verification process will be more sophisticated. + public static func roomEventEncryptionVerifyMessage(_ p1: String, _ p2: String, _ p3: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_verify_message", p1, p2, p3) + } + /// Verify + public static var roomEventEncryptionVerifyOk: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_verify_ok") + } + /// Verify session\n\n + public static var roomEventEncryptionVerifyTitle: String { + return MatrixKitL10n.tr("MatrixKit", "room_event_encryption_verify_title") + } + /// You left the room + public static var roomLeft: String { + return MatrixKitL10n.tr("MatrixKit", "room_left") + } + /// You left + public static var roomLeftForDm: String { + return MatrixKitL10n.tr("MatrixKit", "room_left_for_dm") + } + /// Are you sure you want to hide all messages from this user? + public static var roomMemberIgnorePrompt: String { + return MatrixKitL10n.tr("MatrixKit", "room_member_ignore_prompt") + } + /// You will not be able to undo this change as you are promoting the user to have the same power level as yourself.\nAre you sure? + public static var roomMemberPowerLevelPrompt: String { + return MatrixKitL10n.tr("MatrixKit", "room_member_power_level_prompt") + } + /// Conference calls are not supported in encrypted rooms + public static var roomNoConferenceCallInEncryptedRooms: String { + return MatrixKitL10n.tr("MatrixKit", "room_no_conference_call_in_encrypted_rooms") + } + /// You need permission to invite to start a conference in this room + public static var roomNoPowerToCreateConferenceCall: String { + return MatrixKitL10n.tr("MatrixKit", "room_no_power_to_create_conference_call") + } + /// Please select a room + public static var roomPleaseSelect: String { + return MatrixKitL10n.tr("MatrixKit", "room_please_select") + } + /// Save + public static var save: String { + return MatrixKitL10n.tr("MatrixKit", "save") + } + /// No Results + public static var searchNoResults: String { + return MatrixKitL10n.tr("MatrixKit", "search_no_results") + } + /// Search in progress... + public static var searchSearching: String { + return MatrixKitL10n.tr("MatrixKit", "search_searching") + } + /// Select an account + public static var selectAccount: String { + return MatrixKitL10n.tr("MatrixKit", "select_account") + } + /// Select All + public static var selectAll: String { + return MatrixKitL10n.tr("MatrixKit", "select_all") + } + /// Send + public static var send: String { + return MatrixKitL10n.tr("MatrixKit", "send") + } + /// Set Admin + public static var setAdmin: String { + return MatrixKitL10n.tr("MatrixKit", "set_admin") + } + /// Reset Power Level + public static var setDefaultPowerLevel: String { + return MatrixKitL10n.tr("MatrixKit", "set_default_power_level") + } + /// Set Moderator + public static var setModerator: String { + return MatrixKitL10n.tr("MatrixKit", "set_moderator") + } + /// Set Power Level + public static var setPowerLevel: String { + return MatrixKitL10n.tr("MatrixKit", "set_power_level") + } + /// Settings + public static var settings: String { + return MatrixKitL10n.tr("MatrixKit", "settings") + } + /// Homeserver: %@ + public static func settingsConfigHomeServer(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "settings_config_home_server", p1) + } + /// Identity server: %@ + public static func settingsConfigIdentityServer(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "settings_config_identity_server", p1) + } + /// User ID: %@ + public static func settingsConfigUserId(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "settings_config_user_id", p1) + } + /// Enable In-App notifications + public static var settingsEnableInappNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "settings_enable_inapp_notifications") + } + /// Enable push notifications + public static var settingsEnablePushNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "settings_enable_push_notifications") + } + /// Enter validation token for %@: + public static func settingsEnterValidationTokenFor(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "settings_enter_validation_token_for", p1) + } + /// Configuration + public static var settingsTitleConfig: String { + return MatrixKitL10n.tr("MatrixKit", "settings_title_config") + } + /// Notifications + public static var settingsTitleNotifications: String { + return MatrixKitL10n.tr("MatrixKit", "settings_title_notifications") + } + /// Share + public static var share: String { + return MatrixKitL10n.tr("MatrixKit", "share") + } + /// Show Details + public static var showDetails: String { + return MatrixKitL10n.tr("MatrixKit", "show_details") + } + /// Sign up + public static var signUp: String { + return MatrixKitL10n.tr("MatrixKit", "sign_up") + } + /// If the server administrator has said that this is expected, ensure that the fingerprint below matches the fingerprint provided by them. + public static var sslCertNewAccountExpl: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_cert_new_account_expl") + } + /// This could mean that someone is maliciously intercepting your traffic, or that your phone does not trust the certificate provided by the remote server. + public static var sslCertNotTrust: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_cert_not_trust") + } + /// Could not verify identity of remote server. + public static var sslCouldNotVerify: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_could_not_verify") + } + /// The certificate has changed from a previously trusted one to one that is not trusted. The server may have renewed its certificate. Contact the server administrator for the expected fingerprint. + public static var sslExpectedExistingExpl: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_expected_existing_expl") + } + /// Fingerprint (%@): + public static func sslFingerprintHash(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "ssl_fingerprint_hash", p1) + } + /// Homeserver URL: %@ + public static func sslHomeserverUrl(_ p1: String) -> String { + return MatrixKitL10n.tr("MatrixKit", "ssl_homeserver_url", p1) + } + /// Logout + public static var sslLogoutAccount: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_logout_account") + } + /// ONLY accept the certificate if the server administrator has published a fingerprint that matches the one above. + public static var sslOnlyAccept: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_only_accept") + } + /// Ignore + public static var sslRemainOffline: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_remain_offline") + } + /// Trust + public static var sslTrust: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_trust") + } + /// The certificate has changed from one that was trusted by your phone. This is HIGHLY UNUSUAL. It is recommended that you DO NOT ACCEPT this new certificate. + public static var sslUnexpectedExistingExpl: String { + return MatrixKitL10n.tr("MatrixKit", "ssl_unexpected_existing_expl") + } + /// Start Chat + public static var startChat: String { + return MatrixKitL10n.tr("MatrixKit", "start_chat") + } + /// Start Video Call + public static var startVideoCall: String { + return MatrixKitL10n.tr("MatrixKit", "start_video_call") + } + /// Start Voice Call + public static var startVoiceCall: String { + return MatrixKitL10n.tr("MatrixKit", "start_voice_call") + } + /// Submit + public static var submit: String { + return MatrixKitL10n.tr("MatrixKit", "submit") + } + /// Submit code + public static var submitCode: String { + return MatrixKitL10n.tr("MatrixKit", "submit_code") + } + /// Un-ban + public static var unban: String { + return MatrixKitL10n.tr("MatrixKit", "unban") + } + /// Unignore + public static var unignore: String { + return MatrixKitL10n.tr("MatrixKit", "unignore") + } + /// Unsent + public static var unsent: String { + return MatrixKitL10n.tr("MatrixKit", "unsent") + } + /// ex: @bob:homeserver + public static var userIdPlaceholder: String { + return MatrixKitL10n.tr("MatrixKit", "user_id_placeholder") + } + /// User ID: + public static var userIdTitle: String { + return MatrixKitL10n.tr("MatrixKit", "user_id_title") + } + /// View + public static var view: String { + return MatrixKitL10n.tr("MatrixKit", "view") + } + /// Yes + public static var yes: String { + return MatrixKitL10n.tr("MatrixKit", "yes") + } +} +// swiftlint:enable function_parameter_count identifier_name line_length type_body_length + +// MARK: - Implementation Details + +extension MatrixKitL10n { + static func tr(_ table: String, _ key: String, _ args: CVarArg...) -> String { + let format = NSLocalizedString(key, tableName: table, bundle: Bundle(for: BundleToken.self), comment: "") + let locale: Locale + if let providedLocale = LocaleProvider.locale { + locale = providedLocale + } else { + locale = Locale.current + } + + return String(format: format, locale: locale, arguments: args) + } +} + +private final class BundleToken {} From dabf38fb796c4fcf587a03ef2e4fb7bd21553737 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:24:12 +0100 Subject: [PATCH 090/122] Prepare the MatrixKit-Bridging-Header.h for new MatrixKit location. --- .../MatrixKit/MatrixKit-Bridging-Header.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 Riot/Modules/MatrixKit/MatrixKit-Bridging-Header.h diff --git a/Riot/Modules/MatrixKit/MatrixKit-Bridging-Header.h b/Riot/Modules/MatrixKit/MatrixKit-Bridging-Header.h new file mode 100644 index 000000000..1653472db --- /dev/null +++ b/Riot/Modules/MatrixKit/MatrixKit-Bridging-Header.h @@ -0,0 +1,16 @@ +// +// Use this file to import your target's public headers that you would like to expose to Swift. +// + +#import "MXKAppSettings.h" +#import "MXKTools.h" +#import "NSBundle+MatrixKit.h" +#import "NSBundle+MXKLanguage.h" +#import "MXKAccount.h" +#import "MXKAccountManager.h" +#import "MXKContactManager.h" +#import "MXSDKOptions.h" +#import "MXKeyProvider.h" + +#import "MXKRoomInputToolbarView.h" +#import "MXKImageView.h" From 1aee16a6ac98e657e3fd9ae192701d7c73fceeb0 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:25:43 +0100 Subject: [PATCH 091/122] Update MXKSwiftHeader.h for new MatrixKit location. --- Riot/Modules/MatrixKit/Utils/MXKSwiftHeader.h | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 Riot/Modules/MatrixKit/Utils/MXKSwiftHeader.h diff --git a/Riot/Modules/MatrixKit/Utils/MXKSwiftHeader.h b/Riot/Modules/MatrixKit/Utils/MXKSwiftHeader.h new file mode 100644 index 000000000..5821e944b --- /dev/null +++ b/Riot/Modules/MatrixKit/Utils/MXKSwiftHeader.h @@ -0,0 +1,21 @@ +/* + Copyright 2020 The Matrix.org Foundation C.I.C + + 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. + */ +/* + Never import this file in header files (.h) only in implementation files (.m). + If you want to reference a Swift class from the project please use forward declaration in the header file and then import this header in your implementation file. +*/ + +#import "GeneratedInterface-Swift.h" From 6a2adf3f73252c55b09badeacb4ce18355054599 Mon Sep 17 00:00:00 2001 From: SBiOSoftWhare Date: Tue, 30 Nov 2021 17:44:02 +0100 Subject: [PATCH 092/122] Remove MatrixKit from third party licenses file. --- Riot/Assets/third_party_licenses.html | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/Riot/Assets/third_party_licenses.html b/Riot/Assets/third_party_licenses.html index fc4b54a43..b615810b2 100644 --- a/Riot/Assets/third_party_licenses.html +++ b/Riot/Assets/third_party_licenses.html @@ -15,21 +15,7 @@

This application is making use of the following third party softwares:

-