fixed: subscription API call

This commit is contained in:
ihugo 2021-04-12 21:42:43 +08:00
parent b2b8b70707
commit 23a06f04ab
9 changed files with 320 additions and 124 deletions

View File

@ -50,6 +50,7 @@ public extension Subscription {
setting.id = property.id setting.id = property.id
setting.endpoint = property.endpoint setting.endpoint = property.endpoint
setting.serverKey = property.serverKey setting.serverKey = property.serverKey
setting.type = property.type
return setting return setting
} }

View File

@ -12,6 +12,8 @@ import ActiveLabel
import CoreData import CoreData
import CoreDataStack import CoreDataStack
// iTODO: when to ask permission to Use Notifications
class SettingsViewController: UIViewController, NeedsDependency { class SettingsViewController: UIViewController, NeedsDependency {
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } } weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
@ -26,7 +28,7 @@ class SettingsViewController: UIViewController, NeedsDependency {
let follow = L10n.Scene.Settings.Section.Notifications.Trigger.follow let follow = L10n.Scene.Settings.Section.Notifications.Trigger.follow
let noOne = L10n.Scene.Settings.Section.Notifications.Trigger.noOne let noOne = L10n.Scene.Settings.Section.Notifications.Trigger.noOne
let menu = UIMenu( let menu = UIMenu(
image: UIImage(systemName: "escape"), image: nil,
identifier: nil, identifier: nil,
options: .displayInline, options: .displayInline,
children: [ children: [
@ -173,7 +175,9 @@ class SettingsViewController: UIViewController, NeedsDependency {
} }
private func setupTableView() { private func setupTableView() {
viewModel.dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { (tableView, indexPath, item) -> UITableViewCell? in viewModel.dataSource = UITableViewDiffableDataSource(tableView: tableView, cellProvider: { [weak self] (tableView, indexPath, item) -> UITableViewCell? in
guard let self = self else { return nil }
switch item { switch item {
case .apperance(let item): case .apperance(let item):
guard let cell = tableView.dequeueReusableCell(withIdentifier: "SettingsAppearanceTableViewCell") as? SettingsAppearanceTableViewCell else { guard let cell = tableView.dequeueReusableCell(withIdentifier: "SettingsAppearanceTableViewCell") as? SettingsAppearanceTableViewCell else {
@ -227,6 +231,10 @@ class SettingsViewController: UIViewController, NeedsDependency {
.store(in: &disposeBag) .store(in: &disposeBag)
} }
deinit {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function)
}
// Mark: - Actions // Mark: - Actions
@objc func doneButtonDidClick() { @objc func doneButtonDidClick() {
dismiss(animated: true, completion: nil) dismiss(animated: true, completion: nil)
@ -306,38 +314,39 @@ extension SettingsViewController {
guard let settings = self.viewModel.setting.value else { return } guard let settings = self.viewModel.setting.value else { return }
guard let triggerBy = settings.triggerBy else { return } guard let triggerBy = settings.triggerBy else { return }
var values: [Bool?]? guard let alerts = settings.subscription?.first(where: { (s) -> Bool in
if let alerts = settings.subscription?.first(where: { (s) -> Bool in
return s.type == settings.triggerBy return s.type == settings.triggerBy
})?.alert { })?.alert else {
var items = [Bool?]() return
items.append(alerts.favourite)
items.append(alerts.follow)
items.append(alerts.reblog)
items.append(alerts.mention)
values = items
} }
guard var alertValues = values else { return } var alertValues = [Bool?]()
guard alertValues.count >= 4 else { return } alertValues.append(alerts.favourite?.boolValue)
alertValues.append(alerts.follow?.boolValue)
alertValues.append(alerts.reblog?.boolValue)
alertValues.append(alerts.mention?.boolValue)
// need to update `alerts` to make update API with correct parameter
switch title { switch title {
case L10n.Scene.Settings.Section.Notifications.favorites: case L10n.Scene.Settings.Section.Notifications.favorites:
alertValues[0] = isOn alertValues[0] = isOn
alerts.favourite = NSNumber(booleanLiteral: isOn)
case L10n.Scene.Settings.Section.Notifications.follows: case L10n.Scene.Settings.Section.Notifications.follows:
alertValues[1] = isOn alertValues[1] = isOn
alerts.follow = NSNumber(booleanLiteral: isOn)
case L10n.Scene.Settings.Section.Notifications.boosts: case L10n.Scene.Settings.Section.Notifications.boosts:
alertValues[2] = isOn alertValues[2] = isOn
alerts.reblog = NSNumber(booleanLiteral: isOn)
case L10n.Scene.Settings.Section.Notifications.mentions: case L10n.Scene.Settings.Section.Notifications.mentions:
alertValues[3] = isOn alertValues[3] = isOn
alerts.mention = NSNumber(booleanLiteral: isOn)
default: break default: break
} }
self.viewModel.alertUpdate.send((triggerBy: triggerBy, values: alertValues)) self.viewModel.updateSubscriptionSubject.send((triggerBy: triggerBy, values: alertValues))
} }
} }
extension SettingsViewController: SettingsAppearanceTableViewCellDelegate { extension SettingsViewController: SettingsAppearanceTableViewCellDelegate {
func settingsAppearanceCell(_ view: SettingsAppearanceTableViewCell, didSelect: SettingsItem.AppearanceMode) { func settingsAppearanceCell(_ view: SettingsAppearanceTableViewCell, didSelect: SettingsItem.AppearanceMode) {
print("[SettingsViewController]: didSelect \(didSelect)")
guard let setting = self.viewModel.setting.value else { return } guard let setting = self.viewModel.setting.value else { return }
context.managedObjectContext.performChanges { context.managedObjectContext.performChanges {

View File

@ -20,6 +20,9 @@ class SettingsViewModel: NSObject, NeedsDependency {
var dataSource: UITableViewDiffableDataSource<SettingsSection, SettingsItem>! var dataSource: UITableViewDiffableDataSource<SettingsSection, SettingsItem>!
var disposeBag = Set<AnyCancellable>() var disposeBag = Set<AnyCancellable>()
var updateDisposeBag = Set<AnyCancellable>()
var createDisposeBag = Set<AnyCancellable>()
let viewDidLoad = PassthroughSubject<Void, Never>() let viewDidLoad = PassthroughSubject<Void, Never>()
lazy var fetchResultsController: NSFetchedResultsController<Setting> = { lazy var fetchResultsController: NSFetchedResultsController<Setting> = {
let fetchRequest = Setting.sortedFetchRequest let fetchRequest = Setting.sortedFetchRequest
@ -42,10 +45,14 @@ class SettingsViewModel: NSObject, NeedsDependency {
}() }()
let setting = CurrentValueSubject<Setting?, Never>(nil) let setting = CurrentValueSubject<Setting?, Never>(nil)
/// trigger when /// create a subscription when:
/// - init alerts /// - does not has one
/// - change subscription status everytime /// - does not find subscription for selected trigger when change trigger
let alertUpdate = PassthroughSubject<(triggerBy: String, values: [Bool?]), Never>() let createSubscriptionSubject = PassthroughSubject<(triggerBy: String, values: [Bool?]), Never>()
/// update a subscription when:
/// - change switch for specified alerts
let updateSubscriptionSubject = PassthroughSubject<(triggerBy: String, values: [Bool?]), Never>()
lazy var notificationDefaultValue: [String: [Bool?]] = { lazy var notificationDefaultValue: [String: [Bool?]] = {
let followerSwitchItems: [Bool?] = [true, nil, true, true] let followerSwitchItems: [Bool?] = [true, nil, true, true]
@ -77,7 +84,85 @@ class SettingsViewModel: NSObject, NeedsDependency {
} }
func transform(input: Input?) -> Output? { func transform(input: Input?) -> Output? {
//guard let input = input else { return nil } typealias SubscriptionResponse = Mastodon.Response.Content<Mastodon.Entity.Subscription>
createSubscriptionSubject
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
.sink { _ in
} receiveValue: { [weak self] (arg) in
let (triggerBy, values) = arg
guard let self = self else {
return
}
guard let activeMastodonAuthenticationBox =
self.context.authenticationService.activeMastodonAuthenticationBox.value else {
return
}
guard values.count >= 4 else {
return
}
self.createDisposeBag.removeAll()
typealias Query = Mastodon.API.Notification.CreateSubscriptionQuery
let domain = activeMastodonAuthenticationBox.domain
let query = Query(
endpoint: "http://www.google.com",
p256dh: "BLQELIDm-6b9Bl07YrEuXJ4BL_YBVQ0dvt9NQGGJxIQidJWHPNa9YrouvcQ9d7_MqzvGS9Alz60SZNCG3qfpk=",
auth: "4vQK-SvRAN5eo-8ASlrwA==",
favourite: values[0],
follow: values[1],
reblog: values[2],
mention: values[3],
poll: nil)
self.context.apiService.changeSubscription(
domain: domain,
mastodonAuthenticationBox: activeMastodonAuthenticationBox,
query: query,
triggerBy: triggerBy
)
.sink { (_) in
} receiveValue: { (_) in
}
.store(in: &self.createDisposeBag)
}
.store(in: &disposeBag)
updateSubscriptionSubject
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
.sink { _ in
} receiveValue: { [weak self] (arg) in
let (triggerBy, values) = arg
guard let self = self else {
return
}
guard let activeMastodonAuthenticationBox =
self.context.authenticationService.activeMastodonAuthenticationBox.value else {
return
}
guard values.count >= 4 else {
return
}
self.updateDisposeBag.removeAll()
typealias Query = Mastodon.API.Notification.UpdateSubscriptionQuery
let domain = activeMastodonAuthenticationBox.domain
let query = Query(
favourite: values[0],
follow: values[1],
reblog: values[2],
mention: values[3],
poll: nil)
self.context.apiService.updateSubscription(
domain: domain,
mastodonAuthenticationBox: activeMastodonAuthenticationBox,
query: query,
triggerBy: triggerBy
)
.sink { (_) in
} receiveValue: { (_) in
}
.store(in: &self.updateDisposeBag)
}
.store(in: &disposeBag)
// build data for table view // build data for table view
buildDataSource() buildDataSource()
@ -85,36 +170,6 @@ class SettingsViewModel: NSObject, NeedsDependency {
// request subsription data for updating or initialization // request subsription data for updating or initialization
requestSubscription() requestSubscription()
typealias SubscriptionResponse = Mastodon.Response.Content<Mastodon.Entity.Subscription>
alertUpdate
.debounce(for: .milliseconds(300), scheduler: DispatchQueue.main)
.flatMap { [weak self] (arg) -> AnyPublisher<SubscriptionResponse, Error> in
let (triggerBy, values) = arg
guard let self = self else {
return Empty<SubscriptionResponse, Error>().eraseToAnyPublisher()
}
guard let activeMastodonAuthenticationBox =
self.context.authenticationService.activeMastodonAuthenticationBox.value else {
return Empty<SubscriptionResponse, Error>().eraseToAnyPublisher()
}
guard values.count >= 4 else {
return Empty<SubscriptionResponse, Error>().eraseToAnyPublisher()
}
typealias Query = Mastodon.API.Notification.CreateSubscriptionQuery
let domain = activeMastodonAuthenticationBox.domain
return self.context.apiService.changeSubscription(
domain: domain,
mastodonAuthenticationBox: activeMastodonAuthenticationBox,
query: Query(favourite: values[0], follow: values[1], reblog: values[2], mention: values[3], poll: nil),
triggerBy: triggerBy)
}
.sink { _ in
} receiveValue: { (subscription) in
}
.store(in: &disposeBag)
do { do {
try fetchResultsController.performFetch() try fetchResultsController.performFetch()
setting.value = fetchResultsController.fetchedObjects?.first setting.value = fetchResultsController.fetchedObjects?.first
@ -141,15 +196,15 @@ class SettingsViewModel: NSObject, NeedsDependency {
return s.type == settings?.triggerBy return s.type == settings?.triggerBy
})?.alert { })?.alert {
var items = [Bool?]() var items = [Bool?]()
items.append(alerts.favourite) items.append(alerts.favourite?.boolValue)
items.append(alerts.follow) items.append(alerts.follow?.boolValue)
items.append(alerts.reblog) items.append(alerts.reblog?.boolValue)
items.append(alerts.mention) items.append(alerts.mention?.boolValue)
switches = items switches = items
} else if let triggerBy = settings?.triggerBy, } else if let triggerBy = settings?.triggerBy,
let values = self.notificationDefaultValue[triggerBy] { let values = self.notificationDefaultValue[triggerBy] {
switches = values switches = values
self.alertUpdate.send((triggerBy: triggerBy, values: values)) self.createSubscriptionSubject.send((triggerBy: triggerBy, values: values))
} else { } else {
// fallback a default value // fallback a default value
let anyone = L10n.Scene.Settings.Section.Notifications.Trigger.anyone let anyone = L10n.Scene.Settings.Section.Notifications.Trigger.anyone
@ -178,7 +233,6 @@ class SettingsViewModel: NSObject, NeedsDependency {
L10n.Scene.Settings.Section.BoringZone.privacy] L10n.Scene.Settings.Section.BoringZone.privacy]
var boringLinkItems = [SettingsItem]() var boringLinkItems = [SettingsItem]()
for l in boringLinks { for l in boringLinks {
// FIXME: update color in both light and dark mode
let item = SettingsItem.boringZone(item: SettingsItem.Link(title: l, color: .systemBlue)) let item = SettingsItem.boringZone(item: SettingsItem.Link(title: l, color: .systemBlue))
boringLinkItems.append(item) boringLinkItems.append(item)
} }
@ -191,7 +245,6 @@ class SettingsViewModel: NSObject, NeedsDependency {
L10n.Scene.Settings.Section.SpicyZone.signOut] L10n.Scene.Settings.Section.SpicyZone.signOut]
var spicyLinkItems = [SettingsItem]() var spicyLinkItems = [SettingsItem]()
for l in spicyLinks { for l in spicyLinks {
// FIXME: update color in both light and dark mode
let item = SettingsItem.boringZone(item: SettingsItem.Link(title: l, color: .systemRed)) let item = SettingsItem.boringZone(item: SettingsItem.Link(title: l, color: .systemRed))
spicyLinkItems.append(item) spicyLinkItems.append(item)
} }
@ -203,15 +256,11 @@ class SettingsViewModel: NSObject, NeedsDependency {
} }
private func buildDataSource() { private func buildDataSource() {
setting.filter({ $0 != nil }).sink { [weak self] (settings) in setting.sink { [weak self] (settings) in
guard let self = self else { return } guard let self = self else { return }
self.processDataSource(settings) self.processDataSource(settings)
} }
.store(in: &disposeBag) .store(in: &disposeBag)
// init with no subscription for notification
let settings: Setting? = nil
self.processDataSource(settings)
} }
private func requestSubscription() { private func requestSubscription() {
@ -229,11 +278,22 @@ class SettingsViewModel: NSObject, NeedsDependency {
domain: domain, domain: domain,
mastodonAuthenticationBox: activeMastodonAuthenticationBox) mastodonAuthenticationBox: activeMastodonAuthenticationBox)
} }
.sink { _ in .sink { [weak self] competion in
if case .failure(_) = competion {
// create a subscription when doesn't has one
let anyone = L10n.Scene.Settings.Section.Notifications.Trigger.anyone
if let values = self?.notificationDefaultValue[anyone] {
self?.createSubscriptionSubject.send((triggerBy: anyone, values: values))
}
}
} receiveValue: { (subscription) in } receiveValue: { (subscription) in
} }
.store(in: &disposeBag) .store(in: &disposeBag)
} }
deinit {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s:", ((#file as NSString).lastPathComponent), #line, #function)
}
} }
// MARK: - NSFetchedResultsControllerDelegate // MARK: - NSFetchedResultsControllerDelegate

View File

@ -86,12 +86,7 @@ class AppearanceView: UIView {
class SettingsAppearanceTableViewCell: UITableViewCell { class SettingsAppearanceTableViewCell: UITableViewCell {
weak var delegate: SettingsAppearanceTableViewCellDelegate? weak var delegate: SettingsAppearanceTableViewCellDelegate?
var appearance: SettingsItem.AppearanceMode = .automatic { var appearance: SettingsItem.AppearanceMode = .automatic
didSet {
guard let delegate = self.delegate else { return }
delegate.settingsAppearanceCell(self, didSelect: appearance)
}
}
lazy var stackView: UIStackView = { lazy var stackView: UIStackView = {
let view = UIStackView() let view = UIStackView()
@ -203,5 +198,8 @@ class SettingsAppearanceTableViewCell: UITableViewCell {
if sender == darkTap { if sender == darkTap {
appearance = .dark appearance = .dark
} }
guard let delegate = self.delegate else { return }
delegate.settingsAppearanceCell(self, didSelect: appearance)
} }
} }

View File

@ -62,5 +62,33 @@ extension APIService {
.eraseToAnyPublisher() .eraseToAnyPublisher()
}.eraseToAnyPublisher() }.eraseToAnyPublisher()
} }
func updateSubscription(
domain: String,
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox,
query: Mastodon.API.Notification.UpdateSubscriptionQuery,
triggerBy: String
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Subscription>, Error> {
let authorization = mastodonAuthenticationBox.userAuthorization
return Mastodon.API.Notification.updateSubscription(
session: session,
domain: domain,
authorization: authorization,
query: query
)
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Subscription>, Error> in
return self.backgroundManagedObjectContext.performChanges {
_ = APIService.CoreData.createOrMergeSubscription(
into: self.backgroundManagedObjectContext,
entity: response.value,
domain: domain,
triggerBy: triggerBy)
}
.setFailureType(to: Error.self)
.map { _ in return response }
.eraseToAnyPublisher()
}.eraseToAnyPublisher()
}
} }

View File

@ -94,11 +94,12 @@ extension APIService.CoreData {
type: triggerBy ?? setting.triggerBy ?? "") type: triggerBy ?? setting.triggerBy ?? "")
let alertEntity = entity.alerts let alertEntity = entity.alerts
let alert = SubscriptionAlerts.Property( let alert = SubscriptionAlerts.Property(
favourite: alertEntity.favourite, favourite: alertEntity.favouriteNumber,
follow: alertEntity.follow, follow: alertEntity.followNumber,
mention: alertEntity.mention, mention: alertEntity.mentionNumber,
poll: alertEntity.poll, poll: alertEntity.pollNumber,
reblog: alertEntity.reblog) reblog: alertEntity.reblogNumber
)
if let oldSubscription = oldSubscription { if let oldSubscription = oldSubscription {
oldSubscription.updateIfNeed(property: property) oldSubscription.updateIfNeed(property: property)
if nil == oldSubscription.alert { if nil == oldSubscription.alert {
@ -109,9 +110,10 @@ extension APIService.CoreData {
oldSubscription.alert?.updateIfNeed(property: alert) oldSubscription.alert?.updateIfNeed(property: alert)
} }
if oldSubscription.alert?.hasChanges == true { if oldSubscription.alert?.hasChanges == true || oldSubscription.hasChanges {
// don't expand subscription if add existed subscription // don't expand subscription if add existed subscription
setting.mutableSetValue(forKey: #keyPath(Setting.subscription)).add(oldSubscription) //setting.mutableSetValue(forKey: #keyPath(Setting.subscription)).add(oldSubscription)
oldSubscription.didUpdate(at: Date())
} }
return (oldSubscription, false) return (oldSubscription, false)
} else { } else {

View File

@ -47,9 +47,9 @@ extension Mastodon.API.Notification {
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
/// Change types of notifications /// Subscribe to push notifications
/// ///
/// Using this endpoint to change types of notifications /// Add a Web Push API subscription to receive notifications. Each access token can have one push subscription. If you create a new subscription, the old subscription is deleted.
/// ///
/// - Since: 2.4.0 /// - Since: 2.4.0
/// - Version: 3.3.0 /// - Version: 3.3.0
@ -80,6 +80,40 @@ extension Mastodon.API.Notification {
} }
.eraseToAnyPublisher() .eraseToAnyPublisher()
} }
/// Change types of notifications
///
/// Updates the current push subscription. Only the data part can be updated. To change fundamentals, a new subscription must be created instead.
///
/// - Since: 2.4.0
/// - Version: 3.3.0
/// # Last Update
/// 2021/4/9
/// # Reference
/// [Document](https://docs.joinmastodon.org/methods/notifications/push/)
/// - Parameters:
/// - session: `URLSession`
/// - domain: Mastodon instance domain. e.g. "example.com"
/// - authorization: User token. Could be nil if status is public
/// - Returns: `AnyPublisher` contains `Poll` nested in the response
public static func updateSubscription(
session: URLSession,
domain: String,
authorization: Mastodon.API.OAuth.Authorization?,
query: UpdateSubscriptionQuery
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Subscription>, Error> {
let request = Mastodon.API.put(
url: pushEndpointURL(domain: domain),
query: query,
authorization: authorization
)
return session.dataTaskPublisher(for: request)
.tryMap { data, response in
let value = try Mastodon.API.decode(type: Mastodon.Entity.Subscription.self, from: data, response: response)
return Mastodon.Response.Content(value: value, response: response)
}
.eraseToAnyPublisher()
}
} }
extension Mastodon.API.Notification { extension Mastodon.API.Notification {
@ -88,27 +122,56 @@ extension Mastodon.API.Notification {
var contentType: String? var contentType: String?
var body: Data? var body: Data?
let follow: Bool? public init(
let favourite: Bool? endpoint: String,
let reblog: Bool? p256dh: String,
let mention: Bool? auth: String,
let poll: Bool? favourite: Bool?,
follow: Bool?,
// iTODO: missing parameters reblog: Bool?,
// subscription[endpoint] mention: Bool?,
// subscription[keys][p256dh] poll: Bool?
// subscription[keys][auth] ) {
public init(favourite: Bool?, queryItems = [URLQueryItem]()
follow: Bool?,
reblog: Bool?,
mention: Bool?,
poll: Bool?) {
self.follow = follow
self.favourite = favourite
self.reblog = reblog
self.mention = mention
self.poll = poll
queryItems?.append(URLQueryItem(name: "subscription[endpoint]", value: endpoint))
queryItems?.append(URLQueryItem(name: "subscription[keys][p256dh]", value: p256dh))
queryItems?.append(URLQueryItem(name: "subscription[keys][auth]", value: auth))
if let followValue = follow?.queryItemValue {
let followItem = URLQueryItem(name: "data[alerts][follow]", value: followValue)
queryItems?.append(followItem)
}
if let favouriteValue = favourite?.queryItemValue {
let favouriteItem = URLQueryItem(name: "data[alerts][favourite]", value: favouriteValue)
queryItems?.append(favouriteItem)
}
if let reblogValue = reblog?.queryItemValue {
let reblogItem = URLQueryItem(name: "data[alerts][reblog]", value: reblogValue)
queryItems?.append(reblogItem)
}
if let mentionValue = mention?.queryItemValue {
let mentionItem = URLQueryItem(name: "data[alerts][mention]", value: mentionValue)
queryItems?.append(mentionItem)
}
}
}
public struct UpdateSubscriptionQuery: PutQuery {
var queryItems: [URLQueryItem]?
var contentType: String?
var body: Data?
public init(
favourite: Bool?,
follow: Bool?,
reblog: Bool?,
mention: Bool?,
poll: Bool?
) {
queryItems = [URLQueryItem]() queryItems = [URLQueryItem]()
if let followValue = follow?.queryItemValue { if let followValue = follow?.queryItemValue {

View File

@ -32,11 +32,46 @@ extension Mastodon.Entity {
} }
public struct Alerts: Codable { public struct Alerts: Codable {
public let follow: Bool public let follow: Bool?
public let favourite: Bool public let favourite: Bool?
public let reblog: Bool public let reblog: Bool?
public let mention: Bool public let mention: Bool?
public let poll: Bool public let poll: Bool?
public var followNumber: NSNumber? {
guard let value = follow else { return nil }
return NSNumber(booleanLiteral: value)
}
public var favouriteNumber: NSNumber? {
guard let value = favourite else { return nil }
return NSNumber(booleanLiteral: value)
}
public var reblogNumber: NSNumber? {
guard let value = reblog else { return nil }
return NSNumber(booleanLiteral: value)
}
public var mentionNumber: NSNumber? {
guard let value = mention else { return nil }
return NSNumber(booleanLiteral: value)
}
public var pollNumber: NSNumber? {
guard let value = poll else { return nil }
return NSNumber(booleanLiteral: value)
}
}
public init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
var id = try? container.decode(String.self, forKey: .id)
if nil == id, let numId = try? container.decode(Int.self, forKey: .id) {
id = String(numId)
}
self.id = id ?? ""
endpoint = try container.decode(String.self, forKey: .endpoint)
alerts = try container.decode(Alerts.self, forKey: .alerts)
serverKey = try container.decode(String.self, forKey: .serverKey)
} }
} }
} }

View File

@ -11,11 +11,11 @@ import CoreData
@objc(SubscriptionAlerts) @objc(SubscriptionAlerts)
public final class SubscriptionAlerts: NSManagedObject { public final class SubscriptionAlerts: NSManagedObject {
@NSManaged public var follow: Bool @NSManaged public var follow: NSNumber?
@NSManaged public var favourite: Bool @NSManaged public var favourite: NSNumber?
@NSManaged public var reblog: Bool @NSManaged public var reblog: NSNumber?
@NSManaged public var mention: Bool @NSManaged public var mention: NSNumber?
@NSManaged public var poll: Bool @NSManaged public var poll: NSNumber?
@NSManaged public private(set) var createdAt: Date @NSManaged public private(set) var createdAt: Date
@NSManaged public private(set) var updatedAt: Date @NSManaged public private(set) var updatedAt: Date
@ -48,35 +48,35 @@ public extension SubscriptionAlerts {
return alerts return alerts
} }
func update(favourite: Bool) { func update(favourite: NSNumber?) {
guard self.favourite != favourite else { return } guard self.favourite != favourite else { return }
self.favourite = favourite self.favourite = favourite
didUpdate(at: Date()) didUpdate(at: Date())
} }
func update(follow: Bool) { func update(follow: NSNumber?) {
guard self.follow != follow else { return } guard self.follow != follow else { return }
self.follow = follow self.follow = follow
didUpdate(at: Date()) didUpdate(at: Date())
} }
func update(mention: Bool) { func update(mention: NSNumber?) {
guard self.mention != mention else { return } guard self.mention != mention else { return }
self.mention = mention self.mention = mention
didUpdate(at: Date()) didUpdate(at: Date())
} }
func update(poll: Bool) { func update(poll: NSNumber?) {
guard self.poll != poll else { return } guard self.poll != poll else { return }
self.poll = poll self.poll = poll
didUpdate(at: Date()) didUpdate(at: Date())
} }
func update(reblog: Bool) { func update(reblog: NSNumber?) {
guard self.reblog != reblog else { return } guard self.reblog != reblog else { return }
self.reblog = reblog self.reblog = reblog
@ -86,18 +86,18 @@ public extension SubscriptionAlerts {
public extension SubscriptionAlerts { public extension SubscriptionAlerts {
struct Property { struct Property {
public let favourite: Bool public let favourite: NSNumber?
public let follow: Bool public let follow: NSNumber?
public let mention: Bool public let mention: NSNumber?
public let poll: Bool public let poll: NSNumber?
public let reblog: Bool public let reblog: NSNumber?
public init(favourite: Bool?, follow: Bool?, mention: Bool?, poll: Bool?, reblog: Bool?) { public init(favourite: NSNumber?, follow: NSNumber?, mention: NSNumber?, poll: NSNumber?, reblog: NSNumber?) {
self.favourite = favourite ?? true self.favourite = favourite
self.follow = follow ?? true self.follow = follow
self.mention = mention ?? true self.mention = mention
self.poll = poll ?? true self.poll = poll
self.reblog = reblog ?? true self.reblog = reblog
} }
} }