Add accept/dismiss-menu (IOS-241)
This commit is contained in:
parent
ff48cc2f01
commit
f3c035ce92
@ -170,6 +170,7 @@
|
||||
D85DF9742C481B3500A01408 /* DataSourceFacade+Notifications.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85DF9732C481B3500A01408 /* DataSourceFacade+Notifications.swift */; };
|
||||
D85DF9762C4965A900A01408 /* NotificationRequestsViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85DF9752C4965A900A01408 /* NotificationRequestsViewModel.swift */; };
|
||||
D85DF97A2C4E49A400A01408 /* NotificationRequestCountView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85DF9792C4E49A400A01408 /* NotificationRequestCountView.swift */; };
|
||||
D85DF97E2C50EFA700A01408 /* AccountNotificationTimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D85DF97D2C50EFA700A01408 /* AccountNotificationTimelineViewController.swift */; };
|
||||
D87364F92AE28DB500C8F919 /* Kanna in Frameworks */ = {isa = PBXBuildFile; productRef = D87364F82AE28DB500C8F919 /* Kanna */; };
|
||||
D87BFC8B291D5C6B00FEE264 /* MastodonLoginView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */; };
|
||||
D87BFC8D291EB81200FEE264 /* MastodonLoginViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */; };
|
||||
@ -817,6 +818,7 @@
|
||||
D85DF9732C481B3500A01408 /* DataSourceFacade+Notifications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "DataSourceFacade+Notifications.swift"; sourceTree = "<group>"; };
|
||||
D85DF9752C4965A900A01408 /* NotificationRequestsViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRequestsViewModel.swift; sourceTree = "<group>"; };
|
||||
D85DF9792C4E49A400A01408 /* NotificationRequestCountView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationRequestCountView.swift; sourceTree = "<group>"; };
|
||||
D85DF97D2C50EFA700A01408 /* AccountNotificationTimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountNotificationTimelineViewController.swift; sourceTree = "<group>"; };
|
||||
D87BFC8A291D5C6B00FEE264 /* MastodonLoginView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginView.swift; sourceTree = "<group>"; };
|
||||
D87BFC8C291EB81200FEE264 /* MastodonLoginViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginViewModel.swift; sourceTree = "<group>"; };
|
||||
D87BFC8E291EC26A00FEE264 /* MastodonLoginServerTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonLoginServerTableViewCell.swift; sourceTree = "<group>"; };
|
||||
@ -1852,6 +1854,7 @@
|
||||
D85DF9702C481B1100A01408 /* Requests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D85DF97C2C50EF8700A01408 /* Account Notifications */,
|
||||
D85DF96E2C481B1100A01408 /* NotificationRequestsTableViewController.swift */,
|
||||
D85DF96F2C481B1100A01408 /* NotificationRequestTableViewCell.swift */,
|
||||
D85DF9752C4965A900A01408 /* NotificationRequestsViewModel.swift */,
|
||||
@ -1861,6 +1864,14 @@
|
||||
path = "Notification Filtering/Requests";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D85DF97C2C50EF8700A01408 /* Account Notifications */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D85DF97D2C50EFA700A01408 /* AccountNotificationTimelineViewController.swift */,
|
||||
);
|
||||
path = "Account Notifications";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D8A6AB68291C50F3003AB663 /* Login */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -3816,6 +3827,7 @@
|
||||
DB1D84382657B275000346B3 /* SegmentedControlNavigateable.swift in Sources */,
|
||||
0F20220726134DA4000C64BF /* HashtagTimelineViewModel+Diffable.swift in Sources */,
|
||||
DB7A9F932818F33C0016AF98 /* MastodonServerRulesViewController+Debug.swift in Sources */,
|
||||
D85DF97E2C50EFA700A01408 /* AccountNotificationTimelineViewController.swift in Sources */,
|
||||
2D5A3D2825CF8BC9002347D6 /* HomeTimelineViewModel+Diffable.swift in Sources */,
|
||||
DB6B74FC272FF55800C70B6E /* UserSection.swift in Sources */,
|
||||
DB0FCB862796BDA1006C02E2 /* SearchSection.swift in Sources */,
|
||||
|
@ -209,7 +209,7 @@ extension SceneCoordinator {
|
||||
// Notifications
|
||||
case notificationPolicy(viewModel: NotificationFilterViewModel)
|
||||
case notificationRequests(viewModel: NotificationRequestsViewModel)
|
||||
case notificationTimeline(viewModel: NotificationTimelineViewModel)
|
||||
case accountNotificationTimeline(viewModel: NotificationTimelineViewModel, request: Mastodon.Entity.NotificationRequest)
|
||||
|
||||
// report
|
||||
case report(viewModel: ReportViewModel)
|
||||
@ -567,8 +567,8 @@ private extension SceneCoordinator {
|
||||
viewController = NotificationRequestsTableViewController(viewModel: viewModel)
|
||||
case .notificationPolicy(let viewModel):
|
||||
viewController = NotificationPolicyViewController(viewModel: viewModel)
|
||||
case .notificationTimeline(let viewModel):
|
||||
viewController = NotificationTimelineViewController(viewModel: viewModel, context: appContext, coordinator: self)
|
||||
case .accountNotificationTimeline(let viewModel, let request):
|
||||
viewController = AccountNotificationTimelineViewController(viewModel: viewModel, context: appContext, coordinator: self, notificationRequest: request)
|
||||
}
|
||||
|
||||
setupDependency(for: viewController as? NeedsDependency)
|
||||
|
@ -28,13 +28,17 @@ extension DataSourceFacade {
|
||||
static func coordinateToNotificationRequest(
|
||||
request: Mastodon.Entity.NotificationRequest,
|
||||
provider: ViewControllerWithDependencies & AuthContextProvider
|
||||
) async {
|
||||
) async -> AccountNotificationTimelineViewController? {
|
||||
provider.coordinator.showLoading()
|
||||
|
||||
let notificationTimelineViewModel = NotificationTimelineViewModel(context: provider.context, authContext: provider.authContext, scope: .fromAccount(request.account))
|
||||
|
||||
provider.coordinator.hideLoading()
|
||||
provider.coordinator.present(scene: .notificationTimeline(viewModel: notificationTimelineViewModel), transition: .show)
|
||||
|
||||
guard let viewController = provider.coordinator.present(scene: .accountNotificationTimeline(viewModel: notificationTimelineViewModel, request: request), transition: .show) as? AccountNotificationTimelineViewController else { return nil }
|
||||
|
||||
return viewController
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,54 @@
|
||||
// Copyright © 2024 Mastodon gGmbH. All rights reserved.
|
||||
|
||||
import UIKit
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
protocol AccountNotificationTimelineViewControllerDelegate: AnyObject {
|
||||
func acceptRequest(_ viewController: AccountNotificationTimelineViewController, request: Mastodon.Entity.NotificationRequest, completion: @escaping (() -> Void))
|
||||
func dismissRequest(_ viewController: AccountNotificationTimelineViewController, request: Mastodon.Entity.NotificationRequest, completion: @escaping (() -> Void))
|
||||
}
|
||||
|
||||
class AccountNotificationTimelineViewController: NotificationTimelineViewController {
|
||||
|
||||
let request: Mastodon.Entity.NotificationRequest
|
||||
weak var delegate: AccountNotificationTimelineViewControllerDelegate?
|
||||
|
||||
init(viewModel: NotificationTimelineViewModel, context: AppContext, coordinator: SceneCoordinator, notificationRequest: Mastodon.Entity.NotificationRequest) {
|
||||
self.request = notificationRequest
|
||||
|
||||
super.init(viewModel: viewModel, context: context, coordinator: coordinator)
|
||||
|
||||
navigationItem.rightBarButtonItem = UIBarButtonItem(title: nil, image: UIImage(systemName: "ellipsis.circle"), target: nil, action: nil, menu: menu())
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
|
||||
// MARK: - Actions
|
||||
|
||||
//TODO: Localization
|
||||
func menu() -> UIMenu {
|
||||
let menu = UIMenu(children: [
|
||||
UIAction(title: "Accept", image: UIImage(systemName: "checkmark")) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
self.delegate?.acceptRequest(self, request: request) {
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
coordinator.hideLoading()
|
||||
},
|
||||
UIAction(title: "Dismiss", image: UIImage(systemName: "speaker.slash")) { [weak self] _ in
|
||||
guard let self else { return }
|
||||
|
||||
coordinator.showLoading()
|
||||
self.delegate?.dismissRequest(self, request: request) {
|
||||
self.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
coordinator.hideLoading()
|
||||
}
|
||||
])
|
||||
|
||||
return menu
|
||||
}
|
||||
}
|
@ -57,6 +57,7 @@ class NotificationRequestTableViewCell: UITableViewCell {
|
||||
acceptNotificationRequestButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
acceptNotificationRequestButton.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
|
||||
acceptNotificationRequestButton.setTitleColor(.white, for: .normal)
|
||||
//TODO: Localization
|
||||
acceptNotificationRequestButton.setTitle("Accept", for: .normal)
|
||||
acceptNotificationRequestButton.setImage(UIImage(systemName: "checkmark"), for: .normal)
|
||||
acceptNotificationRequestButton.imageView?.contentMode = .scaleAspectFit
|
||||
@ -82,6 +83,7 @@ class NotificationRequestTableViewCell: UITableViewCell {
|
||||
rejectNotificationRequestButton.translatesAutoresizingMaskIntoConstraints = false
|
||||
rejectNotificationRequestButton.titleLabel?.font = UIFont.systemFont(ofSize: 17, weight: .semibold)
|
||||
rejectNotificationRequestButton.setTitleColor(.black, for: .normal)
|
||||
//TODO: Localization
|
||||
rejectNotificationRequestButton.setTitle("Dismiss", for: .normal)
|
||||
rejectNotificationRequestButton.setImage(UIImage(systemName: "speaker.slash"), for: .normal)
|
||||
rejectNotificationRequestButton.imageView?.contentMode = .scaleAspectFit
|
||||
|
@ -4,6 +4,7 @@ import UIKit
|
||||
import MastodonSDK
|
||||
import MastodonCore
|
||||
import MastodonAsset
|
||||
import MastodonLocalization
|
||||
|
||||
enum NotificationRequestsSection: Hashable {
|
||||
case main
|
||||
@ -58,8 +59,7 @@ class NotificationRequestsTableViewController: UIViewController, NeedsDependency
|
||||
tableView.delegate = self
|
||||
self.dataSource = dataSource
|
||||
|
||||
//TODO: Localization
|
||||
title = "Filtered Notifications"
|
||||
title = L10n.Scene.Notification.FilteredNotificationBanner.title
|
||||
}
|
||||
|
||||
required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") }
|
||||
@ -81,8 +81,11 @@ extension NotificationRequestsTableViewController: UITableViewDelegate {
|
||||
|
||||
let request = viewModel.requests[indexPath.row]
|
||||
|
||||
Task {
|
||||
await DataSourceFacade.coordinateToNotificationRequest(request: request, provider: self)
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
|
||||
let viewController = await DataSourceFacade.coordinateToNotificationRequest(request: request, provider: self)
|
||||
viewController?.delegate = self
|
||||
}
|
||||
}
|
||||
|
||||
@ -167,30 +170,7 @@ extension NotificationRequestsTableViewController: NotificationRequestTableViewC
|
||||
Task { [weak self] in
|
||||
guard let self else { return }
|
||||
do {
|
||||
_ = try await context.apiService.rejectNotificationRequests(authenticationBox: authContext.mastodonAuthenticationBox,
|
||||
id: notificationRequest.id)
|
||||
|
||||
let requests = try await context.apiService.notificationRequests(authenticationBox: authContext.mastodonAuthenticationBox).value
|
||||
|
||||
NotificationCenter.default.post(name: .notificationFilteringChanged, object: nil)
|
||||
|
||||
if requests.count > 0 {
|
||||
|
||||
await MainActor.run { [weak self] in
|
||||
guard let self else { return }
|
||||
self.viewModel.requests = requests
|
||||
var snapshot = NSDiffableDataSourceSnapshot<NotificationRequestsSection, NotificationRequestItem>()
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems(self.viewModel.requests.compactMap { NotificationRequestItem.item($0) } )
|
||||
|
||||
self.dataSource?.apply(snapshot)
|
||||
}
|
||||
} else {
|
||||
await MainActor.run { [weak self] in
|
||||
_ = self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
try await rejectNotificationRequest(notificationRequest)
|
||||
} catch {
|
||||
cell.rejectNotificationRequestActivityIndicatorView.stopAnimating()
|
||||
cell.rejectNotificationRequestButton.tintColor = .black
|
||||
@ -200,4 +180,46 @@ extension NotificationRequestsTableViewController: NotificationRequestTableViewC
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func rejectNotificationRequest(_ notificationRequest: MastodonSDK.Mastodon.Entity.NotificationRequest) async throws {
|
||||
_ = try await context.apiService.rejectNotificationRequests(authenticationBox: authContext.mastodonAuthenticationBox,
|
||||
id: notificationRequest.id)
|
||||
|
||||
let requests = try await context.apiService.notificationRequests(authenticationBox: authContext.mastodonAuthenticationBox).value
|
||||
|
||||
NotificationCenter.default.post(name: .notificationFilteringChanged, object: nil)
|
||||
|
||||
if requests.count > 0 {
|
||||
await MainActor.run { [weak self] in
|
||||
guard let self else { return }
|
||||
self.viewModel.requests = requests
|
||||
var snapshot = NSDiffableDataSourceSnapshot<NotificationRequestsSection, NotificationRequestItem>()
|
||||
snapshot.appendSections([.main])
|
||||
snapshot.appendItems(self.viewModel.requests.compactMap { NotificationRequestItem.item($0) } )
|
||||
|
||||
self.dataSource?.apply(snapshot)
|
||||
}
|
||||
} else {
|
||||
await MainActor.run { [weak self] in
|
||||
_ = self?.navigationController?.popViewController(animated: true)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
extension NotificationRequestsTableViewController: AccountNotificationTimelineViewControllerDelegate {
|
||||
func acceptRequest(_ viewController: AccountNotificationTimelineViewController, request: MastodonSDK.Mastodon.Entity.NotificationRequest, completion: @escaping (() -> Void)) {
|
||||
Task {
|
||||
try? await rejectNotificationRequest(request)
|
||||
completion()
|
||||
}
|
||||
}
|
||||
|
||||
func dismissRequest(_ viewController: AccountNotificationTimelineViewController, request: MastodonSDK.Mastodon.Entity.NotificationRequest, completion: @escaping (() -> Void)) {
|
||||
Task {
|
||||
try? await rejectNotificationRequest(request)
|
||||
completion()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonLocalization
|
||||
|
||||
final class NotificationTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
class NotificationTimelineViewController: UIViewController, NeedsDependency, MediaPreviewableViewController {
|
||||
|
||||
weak var context: AppContext!
|
||||
weak var coordinator: SceneCoordinator!
|
||||
|
Loading…
x
Reference in New Issue
Block a user