mirror of
https://github.com/metabolist/metatext.git
synced 2024-12-22 13:37:01 +00:00
Notification type preferences
This commit is contained in:
parent
fb7d23b5d6
commit
888604497c
10 changed files with 128 additions and 12 deletions
|
@ -106,4 +106,8 @@ extension PostingReadingPreferencesViewModel {
|
|||
static let development = PostingReadingPreferencesViewModel(identityService: .development)
|
||||
}
|
||||
|
||||
extension NotificationTypesPreferencesViewModel {
|
||||
static let development = NotificationTypesPreferencesViewModel(identityService: .development)
|
||||
}
|
||||
|
||||
// swiftlint:enable force_try
|
||||
|
|
|
@ -86,6 +86,10 @@
|
|||
D074577824D29006004758DB /* MockWebAuthSession.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577624D29006004758DB /* MockWebAuthSession.swift */; };
|
||||
D074577A24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; };
|
||||
D074577B24D29366004758DB /* URLSessionConfiguration+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */; };
|
||||
D075817924E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D075817824E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift */; };
|
||||
D075817A24E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D075817824E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift */; };
|
||||
D075817C24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D075817B24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift */; };
|
||||
D075817D24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D075817B24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift */; };
|
||||
D081A40524D0F1A8001B016E /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D081A40424D0F1A8001B016E /* String+Extensions.swift */; };
|
||||
D081A40624D0F1A8001B016E /* String+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D081A40424D0F1A8001B016E /* String+Extensions.swift */; };
|
||||
D0A1CA7424DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A1CA7324DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift */; };
|
||||
|
@ -266,6 +270,8 @@
|
|||
D06B491E24D3F7FE00642749 /* Localizable.strings */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; path = Localizable.strings; sourceTree = "<group>"; };
|
||||
D074577624D29006004758DB /* MockWebAuthSession.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockWebAuthSession.swift; sourceTree = "<group>"; };
|
||||
D074577924D29366004758DB /* URLSessionConfiguration+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "URLSessionConfiguration+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D075817824E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTypesPreferencesViewModel.swift; sourceTree = "<group>"; };
|
||||
D075817B24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationTypesPreferencesView.swift; sourceTree = "<group>"; };
|
||||
D081A40424D0F1A8001B016E /* String+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "String+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D0A1CA7324DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "KingfisherOptionsInfo+Extensions.swift"; sourceTree = "<group>"; };
|
||||
D0A652AC24DE3EB6002EA33F /* PreferencesEndpoint+Stubbing.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PreferencesEndpoint+Stubbing.swift"; sourceTree = "<group>"; };
|
||||
|
@ -545,6 +551,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D0DB6EF324C5228A00D965FE /* AddIdentityView.swift */,
|
||||
D075817B24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift */,
|
||||
D0091B6724DC10B30040E8D2 /* PostingReadingPreferencesView.swift */,
|
||||
D0091B6D24DD68090040E8D2 /* PreferencesView.swift */,
|
||||
D0BEC93A24C96FD500E864C4 /* RootView.swift */,
|
||||
|
@ -568,6 +575,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
D0DB6F0824C65AC000D965FE /* AddIdentityViewModel.swift */,
|
||||
D075817824E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift */,
|
||||
D0091B6A24DC10CE0040E8D2 /* PostingReadingPreferencesViewModel.swift */,
|
||||
D0091B7024DD68220040E8D2 /* PreferencesViewModel.swift */,
|
||||
D0BEC93724C9632800E864C4 /* RootViewModel.swift */,
|
||||
|
@ -884,6 +892,7 @@
|
|||
D04FD73924D4A7B4007D572D /* AccountEndpoint+Stubbing.swift in Sources */,
|
||||
D0DB6F0924C65AC000D965FE /* AddIdentityViewModel.swift in Sources */,
|
||||
D0CD847324DBDEC700CF380C /* MastodonPreferences.swift in Sources */,
|
||||
D075817924E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift in Sources */,
|
||||
D0ED1BD724CF94B200B4899C /* Application.swift in Sources */,
|
||||
D047FAAE24C3E21200AF17C5 /* MetatextApp.swift in Sources */,
|
||||
D0BEC94724CA22C400E864C4 /* TimelineViewModel.swift in Sources */,
|
||||
|
@ -893,6 +902,7 @@
|
|||
D0EC8DE824E21FEC00A08489 /* Data+Extensions.swift in Sources */,
|
||||
D0666A6324C6DC6C00F3F04B /* AppAuthorization.swift in Sources */,
|
||||
D019E6E524DF72E700697C7D /* AccountEndpoint.swift in Sources */,
|
||||
D075817C24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift in Sources */,
|
||||
D065F53B24D3B33A00741304 /* View+Extensions.swift in Sources */,
|
||||
D0DC174A24CFF15F00A75C65 /* AppAuthorizationEndpoint+Stubbing.swift in Sources */,
|
||||
D0159F8A24DE742F00E78478 /* IdentitiesViewModel.swift in Sources */,
|
||||
|
@ -1029,6 +1039,7 @@
|
|||
D0A1CA7524DAC2F1003063E9 /* KingfisherOptionsInfo+Extensions.swift in Sources */,
|
||||
D0ED1BC524CED54D00B4899C /* HTTPTarget.swift in Sources */,
|
||||
D0C963FF24CC3812003BD330 /* Publisher+Extensions.swift in Sources */,
|
||||
D075817D24E6659A0081F6A3 /* NotificationTypesPreferencesView.swift in Sources */,
|
||||
D019E6E824DF72E700697C7D /* AccessTokenEndpoint.swift in Sources */,
|
||||
D04FD73D24D4A83A007D572D /* InstanceEndpoint+Stubbing.swift in Sources */,
|
||||
D0DC175C24D0154F00A75C65 /* MastodonAPI.swift in Sources */,
|
||||
|
@ -1038,6 +1049,7 @@
|
|||
D0666A7024C6DFB300F3F04B /* AccessToken.swift in Sources */,
|
||||
D0ED1BCC24CF744200B4899C /* MastodonClient.swift in Sources */,
|
||||
D0091B6924DC10B30040E8D2 /* PostingReadingPreferencesView.swift in Sources */,
|
||||
D075817A24E6657B0081F6A3 /* NotificationTypesPreferencesViewModel.swift in Sources */,
|
||||
D019E6E624DF72E700697C7D /* AccountEndpoint.swift in Sources */,
|
||||
D0CD847724DBDF3C00CF380C /* Status.swift in Sources */,
|
||||
D0EC8DEF24E2704D00A08489 /* PushSubscriptionEndpoint.swift in Sources */,
|
||||
|
|
|
@ -103,8 +103,8 @@ extension IdentityDatabase {
|
|||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func updatePushSubscription(deviceToken: String,
|
||||
alerts: PushSubscription.Alerts,
|
||||
func updatePushSubscription(alerts: PushSubscription.Alerts,
|
||||
deviceToken: String? = nil,
|
||||
forIdentityID identityID: UUID) -> AnyPublisher<Void, Error> {
|
||||
databaseQueue.writePublisher {
|
||||
let data = try StoredIdentity.databaseJSONEncoder(for: "pushSubscriptionAlerts").encode(alerts)
|
||||
|
@ -113,9 +113,11 @@ extension IdentityDatabase {
|
|||
.filter(Column("id") == identityID)
|
||||
.updateAll($0, Column("pushSubscriptionAlerts").set(to: data))
|
||||
|
||||
try StoredIdentity
|
||||
.filter(Column("id") == identityID)
|
||||
.updateAll($0, Column("lastRegisteredDeviceToken").set(to: deviceToken))
|
||||
if let deviceToken = deviceToken {
|
||||
try StoredIdentity
|
||||
.filter(Column("id") == identityID)
|
||||
.updateAll($0, Column("lastRegisteredDeviceToken").set(to: deviceToken))
|
||||
}
|
||||
}
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
|
|
@ -20,6 +20,12 @@
|
|||
"preferences.expand-media.show-all" = "Show all";
|
||||
"preferences.expand-media.hide-all" = "Hide all";
|
||||
"preferences.reading-expand-spoilers" = "Always expand content warnings";
|
||||
"preferences.notification-types" = "Notification Types";
|
||||
"preferences.notification-types.follow" = "Follow";
|
||||
"preferences.notification-types.favourite" = "Favorite";
|
||||
"preferences.notification-types.reblog" = "Reblog";
|
||||
"preferences.notification-types.mention" = "Mention";
|
||||
"preferences.notification-types.poll" = "Poll";
|
||||
"status.visibility.public" = "Public";
|
||||
"status.visibility.unlisted" = "Unlisted";
|
||||
"status.visibility.private" = "Private";
|
||||
|
|
|
@ -4,11 +4,11 @@ import Foundation
|
|||
|
||||
struct PushSubscription: Codable {
|
||||
struct Alerts: Codable, Hashable {
|
||||
let follow: Bool
|
||||
let favourite: Bool
|
||||
let reblog: Bool
|
||||
let mention: Bool
|
||||
let poll: Bool
|
||||
var follow: Bool
|
||||
var favourite: Bool
|
||||
var reblog: Bool
|
||||
var mention: Bool
|
||||
var poll: Bool
|
||||
}
|
||||
|
||||
let endpoint: URL
|
||||
|
|
|
@ -109,8 +109,17 @@ extension IdentityService {
|
|||
publicKey: publicKey,
|
||||
auth: auth,
|
||||
alerts: alerts))
|
||||
.map { (deviceToken, $0.alerts, identityID) }
|
||||
.flatMap(identityDatabase.updatePushSubscription(deviceToken:alerts:forIdentityID:))
|
||||
.map { ($0.alerts, deviceToken, identityID) }
|
||||
.flatMap(identityDatabase.updatePushSubscription(alerts:deviceToken:forIdentityID:))
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func updatePushSubscription(alerts: PushSubscription.Alerts) -> AnyPublisher<Void, Error> {
|
||||
let identityID = identity.id
|
||||
|
||||
return networkClient.request(PushSubscriptionEndpoint.update(alerts: alerts))
|
||||
.map { ($0.alerts, nil, identityID) }
|
||||
.flatMap(identityDatabase.updatePushSubscription(alerts:deviceToken:forIdentityID:))
|
||||
.eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
class NotificationTypesPreferencesViewModel: ObservableObject {
|
||||
@Published var pushSubscriptionAlerts: PushSubscription.Alerts
|
||||
@Published var alertItem: AlertItem?
|
||||
|
||||
private let identityService: IdentityService
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init(identityService: IdentityService) {
|
||||
self.identityService = identityService
|
||||
pushSubscriptionAlerts = identityService.identity.pushSubscriptionAlerts
|
||||
|
||||
identityService.$identity
|
||||
.map(\.pushSubscriptionAlerts)
|
||||
.dropFirst()
|
||||
.removeDuplicates()
|
||||
.assign(to: &$pushSubscriptionAlerts)
|
||||
|
||||
$pushSubscriptionAlerts
|
||||
.dropFirst()
|
||||
.removeDuplicates()
|
||||
.sink(receiveValue: update(alerts:))
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
||||
|
||||
private extension NotificationTypesPreferencesViewModel {
|
||||
func update(alerts: PushSubscription.Alerts) {
|
||||
guard alerts != identityService.identity.pushSubscriptionAlerts else { return }
|
||||
|
||||
identityService.updatePushSubscription(alerts: alerts)
|
||||
.sink { [weak self] in
|
||||
guard let self = self, case let .failure(error) = $0 else { return }
|
||||
|
||||
self.alertItem = AlertItem(error: error)
|
||||
self.pushSubscriptionAlerts = self.identityService.identity.pushSubscriptionAlerts
|
||||
} receiveValue: {}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
}
|
|
@ -17,4 +17,8 @@ extension PreferencesViewModel {
|
|||
func postingReadingPreferencesViewModel() -> PostingReadingPreferencesViewModel {
|
||||
PostingReadingPreferencesViewModel(identityService: identityService)
|
||||
}
|
||||
|
||||
func notificationTypesPreferencesViewModel() -> NotificationTypesPreferencesViewModel {
|
||||
NotificationTypesPreferencesViewModel(identityService: identityService)
|
||||
}
|
||||
}
|
||||
|
|
32
Shared/Views/NotificationTypesPreferencesView.swift
Normal file
32
Shared/Views/NotificationTypesPreferencesView.swift
Normal file
|
@ -0,0 +1,32 @@
|
|||
// Copyright © 2020 Metabolist. All rights reserved.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NotificationTypesPreferencesView: View {
|
||||
@StateObject var viewModel: NotificationTypesPreferencesViewModel
|
||||
|
||||
var body: some View {
|
||||
Form {
|
||||
Toggle("preferences.notification-types.follow",
|
||||
isOn: $viewModel.pushSubscriptionAlerts.follow)
|
||||
Toggle("preferences.notification-types.favourite",
|
||||
isOn: $viewModel.pushSubscriptionAlerts.favourite)
|
||||
Toggle("preferences.notification-types.reblog",
|
||||
isOn: $viewModel.pushSubscriptionAlerts.reblog)
|
||||
Toggle("preferences.notification-types.mention",
|
||||
isOn: $viewModel.pushSubscriptionAlerts.mention)
|
||||
Toggle("preferences.notification-types.poll",
|
||||
isOn: $viewModel.pushSubscriptionAlerts.poll)
|
||||
}
|
||||
.navigationTitle("preferences.notification-types")
|
||||
.alertItem($viewModel.alertItem)
|
||||
}
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
struct NotificationTypesPreferencesView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
NotificationTypesPreferencesView(viewModel: .development)
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -11,6 +11,9 @@ struct PreferencesView: View {
|
|||
NavigationLink("preferences.posting-reading",
|
||||
destination: PostingReadingPreferencesView(
|
||||
viewModel: viewModel.postingReadingPreferencesViewModel()))
|
||||
NavigationLink("preferences.notification-types",
|
||||
destination: NotificationTypesPreferencesView(
|
||||
viewModel: viewModel.notificationTypesPreferencesViewModel()))
|
||||
}
|
||||
}
|
||||
.navigationTitle("preferences")
|
||||
|
|
Loading…
Reference in a new issue