Upload updated policy (IOS-241)

This commit is contained in:
Nathan Mattes 2024-07-09 15:06:05 +02:00
parent 363a521e68
commit 847cadb182
5 changed files with 120 additions and 13 deletions

View File

@ -3,6 +3,7 @@
import UIKit
import MastodonLocalization
import MastodonAsset
import MastodonCore
enum NotificationFilterSection: Hashable {
case main
@ -49,7 +50,10 @@ struct NotificationFilterViewModel {
var newAccount: Bool
var privateMentions: Bool
init(notFollowing: Bool, noFollower: Bool, newAccount: Bool, privateMentions: Bool) {
let appContext: AppContext
init(appContext: AppContext, notFollowing: Bool, noFollower: Bool, newAccount: Bool, privateMentions: Bool) {
self.appContext = appContext
self.notFollowing = notFollowing
self.noFollower = noFollower
self.newAccount = newAccount
@ -60,6 +64,7 @@ struct NotificationFilterViewModel {
class NotificationPolicyViewController: UIViewController {
let tableView: UITableView
var saveItem: UIBarButtonItem?
var dataSource: UITableViewDiffableDataSource<NotificationFilterSection, NotificationFilterItem>?
let items: [NotificationFilterItem]
var viewModel: NotificationFilterViewModel
@ -96,7 +101,8 @@ class NotificationPolicyViewController: UIViewController {
view.addSubview(tableView)
view.backgroundColor = .systemGroupedBackground
navigationItem.rightBarButtonItem = UIBarButtonItem(title: L10n.Common.Controls.Actions.save, style: .done, target: self, action: #selector(NotificationPolicyViewController.save(_:)))
saveItem = UIBarButtonItem(title: L10n.Common.Controls.Actions.save, style: .done, target: self, action: #selector(NotificationPolicyViewController.save(_:)))
navigationItem.rightBarButtonItem = saveItem
navigationItem.leftBarButtonItem = UIBarButtonItem(title: L10n.Common.Controls.Actions.cancel, style: .done, target: self, action: #selector(NotificationPolicyViewController.cancel(_:)))
setupConstraints()
@ -129,7 +135,39 @@ class NotificationPolicyViewController: UIViewController {
// MARK: - Action
@objc private func save(_ sender: UIBarButtonItem) {
//TODO: Save aka PATH viewModel to API and dismiss
guard let authenticationBox = viewModel.appContext.authenticationService.mastodonAuthenticationBoxes.first else { return }
navigationItem.leftBarButtonItem?.isEnabled = false
let activityIndicator = UIActivityIndicatorView(style: .medium)
navigationItem.rightBarButtonItem = UIBarButtonItem(customView: activityIndicator)
navigationItem.rightBarButtonItem?.isEnabled = false
activityIndicator.startAnimating()
Task { [weak self] in
guard let self else { return }
do {
let result = try await viewModel.appContext.apiService.updateNotificationPolicy(
authenticationBox: authenticationBox,
filterNotFollowing: viewModel.notFollowing,
filterNotFollowers: viewModel.noFollower,
filterNewAccounts: viewModel.newAccount,
filterPrivateMentions: viewModel.privateMentions
)
await MainActor.run {
self.dismiss(animated:true)
}
} catch {
navigationItem.rightBarButtonItem = saveItem
navigationItem.rightBarButtonItem?.isEnabled = true
navigationItem.leftBarButtonItem?.isEnabled = true
}
}
}
@objc private func cancel(_ sender: UIBarButtonItem) {

View File

@ -118,9 +118,15 @@ extension NotificationViewController {
//MARK: - Actions
@objc private func showNotificationPolicySettings(_ sender: Any) {
guard let policy = viewModel?.notificationPolicy else { return }
guard let viewModel, let policy = viewModel.notificationPolicy else { return }
let policyViewModel = NotificationFilterViewModel(notFollowing: policy.filterNotFollowing, noFollower: policy.filterNotFollowers, newAccount: policy.filterNewAccounts, privateMentions: policy.filterPrivateMentions)
let policyViewModel = NotificationFilterViewModel(
appContext: viewModel.context,
notFollowing: policy.filterNotFollowing,
noFollower: policy.filterNotFollowers,
newAccount: policy.filterNewAccounts,
privateMentions: policy.filterPrivateMentions
)
//TODO: Move to SceneCoordinator
let notificationPolicyViewController = NotificationPolicyViewController(viewModel: policyViewModel)
notificationPolicyViewController.modalPresentationStyle = .formSheet

View File

@ -113,7 +113,28 @@ extension APIService {
let domain = authenticationBox.domain
let authorization = authenticationBox.userAuthorization
let response = try await Mastodon.API.Notifications.getNotificationPolicy(session: session, domain: domain, authorization: authorization).singleOutput()
let response = try await Mastodon.API.Notifications.getNotificationPolicy(session: session, domain: domain, authorization: authorization)
return response
}
public func updateNotificationPolicy(
authenticationBox: MastodonAuthenticationBox,
filterNotFollowing: Bool,
filterNotFollowers: Bool,
filterNewAccounts: Bool,
filterPrivateMentions: Bool
) async throws -> Mastodon.Response.Content<Mastodon.Entity.NotificationPolicy> {
let domain = authenticationBox.domain
let authorization = authenticationBox.userAuthorization
let query = Mastodon.API.Notifications.UpdateNotificationPolicyQuery(filterNotFollowing: filterNotFollowing, filterNotFollowers: filterNotFollowers, filterNewAccounts: filterNewAccounts, filterPrivateMentions: filterPrivateMentions)
let response = try await Mastodon.API.Notifications.updateNotificationPolicy(
session: session,
domain: domain,
authorization: authorization,
query: query
)
return response
}

View File

@ -142,20 +142,57 @@ extension Mastodon.API.Notifications {
notificationsEndpointURL(domain: domain).appendingPathComponent("policy")
}
public struct UpdateNotificationPolicyQuery: Codable, PatchQuery {
public let filterNotFollowing: Bool
public let filterNotFollowers: Bool
public let filterNewAccounts: Bool
public let filterPrivateMentions: Bool
enum CodingKeys: String, CodingKey {
case filterNotFollowing = "filter_not_following"
case filterNotFollowers = "filter_not_followers"
case filterNewAccounts = "filter_new_accounts"
case filterPrivateMentions = "filter_private_mentions"
}
public init(filterNotFollowing: Bool, filterNotFollowers: Bool, filterNewAccounts: Bool, filterPrivateMentions: Bool) {
self.filterNotFollowing = filterNotFollowing
self.filterNotFollowers = filterNotFollowers
self.filterNewAccounts = filterNewAccounts
self.filterPrivateMentions = filterPrivateMentions
}
}
public static func getNotificationPolicy(
session: URLSession,
domain: String,
authorization: Mastodon.API.OAuth.Authorization
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.NotificationPolicy>, Error> {
) async throws -> Mastodon.Response.Content<Mastodon.Entity.NotificationPolicy> {
let request = Mastodon.API.get(
url: notificationPolicyEndpointURL(domain: domain),
authorization: authorization
)
return session.dataTaskPublisher(for: request)
.tryMap { data, response in
let value = try Mastodon.API.decode(type: Mastodon.Entity.NotificationPolicy.self, from: data, response: response)
return Mastodon.Response.Content(value: value, response: response)
}
.eraseToAnyPublisher()
let (data, response) = try await session.data(for: request)
let value = try Mastodon.API.decode(type: Mastodon.Entity.NotificationPolicy.self, from: data, response: response)
return Mastodon.Response.Content(value: value, response: response)
}
public static func updateNotificationPolicy(
session: URLSession,
domain: String,
authorization: Mastodon.API.OAuth.Authorization,
query: Mastodon.API.Notifications.UpdateNotificationPolicyQuery
) async throws -> Mastodon.Response.Content<Mastodon.Entity.NotificationPolicy> {
let request = Mastodon.API.patch(
url: notificationPolicyEndpointURL(domain: domain),
query: query,
authorization: authorization
)
let (data, response) = try await session.data(for: request)
let value = try Mastodon.API.decode(type: Mastodon.Entity.NotificationPolicy.self, from: data, response: response)
return Mastodon.Response.Content(value: value, response: response)
}
}

View File

@ -55,6 +55,11 @@ extension PostQuery {
// PATCH
protocol PatchQuery: RequestQuery { }
extension PatchQuery {
// By default a `PostQuery` does not have query items
var queryItems: [URLQueryItem]? { nil }
}
// PUT
protocol PutQuery: RequestQuery { }