diff --git a/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift b/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift
index 1dabc738a..a870d8808 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListCoordinator.swift
@@ -69,6 +69,10 @@ extension ThreadListCoordinator: ThreadListViewModelCoordinatorDelegate {
self.delegate?.threadListCoordinatorDidSelectThread(self, thread: thread)
}
+ func threadListViewModelDidSelectThreadViewInRoom(_ viewModel: ThreadListViewModelProtocol, thread: MXThread) {
+ self.delegate?.threadListCoordinatorDidSelectRoom(self, roomId: thread.roomId, eventId: thread.id)
+ }
+
func threadListViewModelDidCancel(_ viewModel: ThreadListViewModelProtocol) {
self.delegate?.threadListCoordinatorDidCancel(self)
}
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift b/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift
index a4227b909..e15c70f35 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListCoordinatorProtocol.swift
@@ -21,6 +21,7 @@ import Foundation
protocol ThreadListCoordinatorDelegate: AnyObject {
func threadListCoordinatorDidLoadThreads(_ coordinator: ThreadListCoordinatorProtocol)
func threadListCoordinatorDidSelectThread(_ coordinator: ThreadListCoordinatorProtocol, thread: MXThread)
+ func threadListCoordinatorDidSelectRoom(_ coordinator: ThreadListCoordinatorProtocol, roomId: String, eventId: String)
func threadListCoordinatorDidCancel(_ coordinator: ThreadListCoordinatorProtocol)
}
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewAction.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewAction.swift
index 629e430e8..a03d0332f 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListViewAction.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListViewAction.swift
@@ -25,5 +25,9 @@ enum ThreadListViewAction {
case showFilterTypes
case selectFilterType(_ type: ThreadListFilterType)
case selectThread(_ index: Int)
+ case longPressThread(_ index: Int)
+ case actionViewInRoom
+ case actionCopyLinkToThread
+ case actionShare
case cancel
}
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard b/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard
index ddfb9060c..c56d0f29d 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard
+++ b/Riot/Modules/Threads/ThreadList/ThreadListViewController.storyboard
@@ -20,9 +20,11 @@
+
+
@@ -52,6 +54,11 @@
+
+
+
+
+
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift
index 9b9b55bc8..1e7da734c 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListViewController.swift
@@ -147,15 +147,19 @@ final class ThreadListViewController: UIViewController {
case .idle:
break
case .loading:
- self.renderLoading()
+ renderLoading()
case .loaded:
- self.renderLoaded()
+ renderLoaded()
case .empty(let viewModel):
- self.renderEmptyView(withViewModel: viewModel)
+ renderEmptyView(withViewModel: viewModel)
case .showingFilterTypes:
- self.renderShowingFilterTypes()
+ renderShowingFilterTypes()
+ case .showingLongPressActions:
+ renderShowingLongPressActions()
+ case .share(let string):
+ renderShare(string)
case .error(let error):
- self.render(error: error)
+ render(error: error)
}
}
@@ -214,6 +218,44 @@ final class ThreadListViewController: UIViewController {
self.present(alertController, animated: true, completion: nil)
}
+ private func renderShowingLongPressActions() {
+ let controller = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
+
+ controller.addAction(UIAlertAction(title: VectorL10n.roomEventActionViewInRoom,
+ style: .default,
+ handler: { [weak self] action in
+ guard let self = self else { return }
+ self.viewModel.process(viewAction: .actionViewInRoom)
+ }))
+
+ controller.addAction(UIAlertAction(title: VectorL10n.threadCopyLinkToThread,
+ style: .default,
+ handler: { [weak self] action in
+ guard let self = self else { return }
+ self.viewModel.process(viewAction: .actionCopyLinkToThread)
+ }))
+
+ controller.addAction(UIAlertAction(title: VectorL10n.roomEventActionShare,
+ style: .default,
+ handler: { [weak self] action in
+ guard let self = self else { return }
+ self.viewModel.process(viewAction: .actionShare)
+ }))
+
+ controller.addAction(UIAlertAction(title: VectorL10n.cancel,
+ style: .cancel,
+ handler: nil))
+
+ self.present(controller, animated: true, completion: nil)
+ }
+
+ private func renderShare(_ string: String) {
+ let activityVC = UIActivityViewController(activityItems: [string],
+ applicationActivities: nil)
+ activityVC.modalTransitionStyle = .coverVertical
+ present(activityVC, animated: true, completion: nil)
+ }
+
private func render(error: Error) {
self.activityPresenter.removeCurrentActivityIndicator(animated: true)
self.errorPresenter.presentError(from: self, forError: error, animated: true, handler: nil)
@@ -225,6 +267,22 @@ final class ThreadListViewController: UIViewController {
private func filterButtonTapped(_ sender: UIBarButtonItem) {
self.viewModel.process(viewAction: .showFilterTypes)
}
+
+ @IBAction private func longPressed(_ sender: UILongPressGestureRecognizer) {
+ guard sender.state == .began else {
+ return
+ }
+ let point = sender.location(in: threadsTableView)
+ guard let indexPath = threadsTableView.indexPathForRow(at: point) else {
+ return
+ }
+ guard let cell = threadsTableView.cellForRow(at: indexPath) else {
+ return
+ }
+ if cell.isHighlighted {
+ viewModel.process(viewAction: .longPressThread(indexPath.row))
+ }
+ }
}
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift
index 4f03e3ed1..884f45711 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModel.swift
@@ -31,6 +31,7 @@ final class ThreadListViewModel: ThreadListViewModelProtocol {
private var roomState: MXRoomState?
private var currentOperation: MXHTTPOperation?
+ private var longPressedThread: MXThread?
// MARK: Public
@@ -73,6 +74,14 @@ final class ThreadListViewModel: ThreadListViewModelProtocol {
loadData()
case .selectThread(let index):
selectThread(index)
+ case .longPressThread(let index):
+ longPressThread(index)
+ case .actionViewInRoom:
+ actionViewInRoom()
+ case .actionCopyLinkToThread:
+ actionCopyLinkToThread()
+ case .actionShare:
+ actionShare()
case .cancel:
cancelOperations()
coordinatorDelegate?.threadListViewModelDidCancel(self)
@@ -264,6 +273,42 @@ final class ThreadListViewModel: ThreadListViewModelProtocol {
coordinatorDelegate?.threadListViewModelDidSelectThread(self, thread: thread)
}
+ private func longPressThread(_ index: Int) {
+ guard index < threads.count else {
+ return
+ }
+ longPressedThread = threads[index]
+ viewState = .showingLongPressActions
+ }
+
+ private func actionViewInRoom() {
+ guard let thread = longPressedThread else {
+ return
+ }
+ coordinatorDelegate?.threadListViewModelDidSelectThreadViewInRoom(self, thread: thread)
+ longPressedThread = nil
+ }
+
+ private func actionCopyLinkToThread() {
+ guard let thread = longPressedThread else {
+ return
+ }
+ if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId) {
+ MXKPasteboardManager.shared.pasteboard.string = permalink
+ }
+ longPressedThread = nil
+ }
+
+ private func actionShare() {
+ guard let thread = longPressedThread else {
+ return
+ }
+ if let permalink = MXTools.permalink(toEvent: thread.id, inRoom: thread.roomId) {
+ viewState = .share(permalink)
+ }
+ longPressedThread = nil
+ }
+
private func cancelOperations() {
self.currentOperation?.cancel()
}
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift
index be0892c47..457cf39d5 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListViewModelProtocol.swift
@@ -25,6 +25,7 @@ protocol ThreadListViewModelViewDelegate: AnyObject {
protocol ThreadListViewModelCoordinatorDelegate: AnyObject {
func threadListViewModelDidLoadThreads(_ viewModel: ThreadListViewModelProtocol)
func threadListViewModelDidSelectThread(_ viewModel: ThreadListViewModelProtocol, thread: MXThread)
+ func threadListViewModelDidSelectThreadViewInRoom(_ viewModel: ThreadListViewModelProtocol, thread: MXThread)
func threadListViewModelDidCancel(_ viewModel: ThreadListViewModelProtocol)
}
diff --git a/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift b/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift
index 073c70645..765e67fa2 100644
--- a/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift
+++ b/Riot/Modules/Threads/ThreadList/ThreadListViewState.swift
@@ -25,5 +25,7 @@ enum ThreadListViewState {
case loaded
case empty(_ viewModel: ThreadListEmptyViewModel)
case showingFilterTypes
+ case showingLongPressActions
+ case share(_ string: String)
case error(Error)
}
diff --git a/Riot/Modules/Threads/ThreadsCoordinator.swift b/Riot/Modules/Threads/ThreadsCoordinator.swift
index 807d6d125..9e6e63e8f 100644
--- a/Riot/Modules/Threads/ThreadsCoordinator.swift
+++ b/Riot/Modules/Threads/ThreadsCoordinator.swift
@@ -151,6 +151,10 @@ extension ThreadsCoordinator: ThreadListCoordinatorDelegate {
self.add(childCoordinator: roomCoordinator)
}
+ func threadListCoordinatorDidSelectRoom(_ coordinator: ThreadListCoordinatorProtocol, roomId: String, eventId: String) {
+ self.delegate?.threadsCoordinatorDidSelect(self, roomId: roomId, eventId: eventId)
+ }
+
func threadListCoordinatorDidCancel(_ coordinator: ThreadListCoordinatorProtocol) {
self.delegate?.threadsCoordinatorDidComplete(self)
}