forked from zelo72/mastodon-ios
fix: server-side data is inconsistent with local
This commit is contained in:
parent
e42af11bf7
commit
8c7149af89
|
@ -155,13 +155,14 @@
|
|||
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser"/>
|
||||
<relationship name="hashtag" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Tag"/>
|
||||
</entity>
|
||||
<entity name="Setting" representedClassName="Setting" syncable="YES">
|
||||
<entity name="Setting" representedClassName=".Setting" syncable="YES">
|
||||
<attribute name="appearance" optional="YES" attributeType="String"/>
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="domain" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" optional="YES" attributeType="UUID" usesScalarValueType="NO"/>
|
||||
<attribute name="triggerBy" optional="YES" attributeType="String"/>
|
||||
<attribute name="updatedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="userID" optional="YES" attributeType="String"/>
|
||||
<relationship name="subscription" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Subscription" inverseName="setting" inverseEntity="Subscription"/>
|
||||
</entity>
|
||||
<entity name="Status" representedClassName=".Status" syncable="YES">
|
||||
|
@ -202,7 +203,7 @@
|
|||
<relationship name="replyTo" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="replyFrom" inverseEntity="Status"/>
|
||||
<relationship name="tags" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Tag" inverseName="statuses" inverseEntity="Tag"/>
|
||||
</entity>
|
||||
<entity name="Subscription" representedClassName="Subscription" syncable="YES">
|
||||
<entity name="Subscription" representedClassName=".Subscription" syncable="YES">
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="endpoint" optional="YES" attributeType="String"/>
|
||||
<attribute name="id" optional="YES" attributeType="String"/>
|
||||
|
@ -212,7 +213,7 @@
|
|||
<relationship name="alert" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="SubscriptionAlerts" inverseName="subscription" inverseEntity="SubscriptionAlerts"/>
|
||||
<relationship name="setting" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Setting" inverseName="subscription" inverseEntity="Setting"/>
|
||||
</entity>
|
||||
<entity name="SubscriptionAlerts" representedClassName="SubscriptionAlerts" syncable="YES">
|
||||
<entity name="SubscriptionAlerts" representedClassName=".SubscriptionAlerts" syncable="YES">
|
||||
<attribute name="createdAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="favourite" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
<attribute name="follow" optional="YES" attributeType="Boolean" usesScalarValueType="YES"/>
|
||||
|
@ -244,10 +245,10 @@
|
|||
<element name="PollOption" positionX="0" positionY="0" width="128" height="134"/>
|
||||
<element name="PrivateNote" positionX="0" positionY="0" width="128" height="89"/>
|
||||
<element name="SearchHistory" positionX="0" positionY="0" width="128" height="104"/>
|
||||
<element name="Setting" positionX="72" positionY="162" width="128" height="149"/>
|
||||
<element name="Status" positionX="0" positionY="0" width="128" height="569"/>
|
||||
<element name="Tag" positionX="0" positionY="0" width="128" height="134"/>
|
||||
<element name="Setting" positionX="72" positionY="162" width="128" height="134"/>
|
||||
<element name="Subscription" positionX="81" positionY="171" width="128" height="149"/>
|
||||
<element name="SubscriptionAlerts" positionX="72" positionY="162" width="128" height="149"/>
|
||||
<element name="Tag" positionX="0" positionY="0" width="128" height="134"/>
|
||||
</elements>
|
||||
</model>
|
|
@ -8,11 +8,11 @@
|
|||
import CoreData
|
||||
import Foundation
|
||||
|
||||
@objc(Setting)
|
||||
public final class Setting: NSManagedObject {
|
||||
@NSManaged public var appearance: String?
|
||||
@NSManaged public var triggerBy: String?
|
||||
@NSManaged public var domain: String?
|
||||
@NSManaged public var userID: String?
|
||||
|
||||
@NSManaged public private(set) var createdAt: Date
|
||||
@NSManaged public private(set) var updatedAt: Date
|
||||
|
@ -40,6 +40,7 @@ public extension Setting {
|
|||
setting.appearance = property.appearance
|
||||
setting.triggerBy = property.triggerBy
|
||||
setting.domain = property.domain
|
||||
setting.userID = property.userID
|
||||
return setting
|
||||
}
|
||||
|
||||
|
@ -61,11 +62,13 @@ public extension Setting {
|
|||
public let appearance: String
|
||||
public let triggerBy: String
|
||||
public let domain: String
|
||||
public let userID: String
|
||||
|
||||
public init(appearance: String, triggerBy: String, domain: String) {
|
||||
public init(appearance: String, triggerBy: String, domain: String, userID: String) {
|
||||
self.appearance = appearance
|
||||
self.triggerBy = triggerBy
|
||||
self.domain = domain
|
||||
self.userID = userID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -77,8 +80,11 @@ extension Setting: Managed {
|
|||
}
|
||||
|
||||
extension Setting {
|
||||
public static func predicate(domain: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Setting.domain), domain)
|
||||
public static func predicate(domain: String, userID: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@ AND %K == %@",
|
||||
#keyPath(Setting.domain), domain,
|
||||
#keyPath(Setting.userID), userID
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import Foundation
|
||||
import CoreData
|
||||
|
||||
@objc(Subscription)
|
||||
public final class Subscription: NSManagedObject {
|
||||
@NSManaged public var id: String
|
||||
@NSManaged public var endpoint: String
|
||||
|
@ -95,8 +94,8 @@ extension Subscription: Managed {
|
|||
|
||||
extension Subscription {
|
||||
|
||||
public static func predicate(id: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Subscription.id), id)
|
||||
public static func predicate(type: String) -> NSPredicate {
|
||||
return NSPredicate(format: "%K == %@", #keyPath(Subscription.type), type)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ public final class SubscriptionAlerts: NSManagedObject {
|
|||
@NSManaged public private(set) var updatedAt: Date
|
||||
|
||||
// MARK: - relationships
|
||||
@NSManaged public var pushSubscription: Subscription?
|
||||
@NSManaged public var subscription: Subscription?
|
||||
}
|
||||
|
||||
public extension SubscriptionAlerts {
|
||||
|
|
|
@ -46,7 +46,7 @@ class SettingsViewController: UIViewController, NeedsDependency {
|
|||
UIAction(title: noOne, image: UIImage(systemName: "nosign"), attributes: []) { [weak self] action in
|
||||
self?.updateTrigger(by: noOne)
|
||||
},
|
||||
].reversed()
|
||||
]
|
||||
)
|
||||
return menu
|
||||
}
|
||||
|
@ -344,10 +344,15 @@ extension SettingsViewController: UITableViewDelegate {
|
|||
// Update setting into core data
|
||||
extension SettingsViewController {
|
||||
func updateTrigger(by who: String) {
|
||||
guard self.viewModel.triggerBy != who else { return }
|
||||
guard let setting = self.viewModel.setting.value else { return }
|
||||
|
||||
_ = context.managedObjectContext.performChanges {
|
||||
setting.update(triggerBy: who)
|
||||
setting.update(triggerBy: who)
|
||||
// trigger to call `subscription` API with POST method
|
||||
// confirm the local data is correct even if request failed
|
||||
// The asynchronous execution is to solve the problem of dropped frames for animations.
|
||||
DispatchQueue.main.async { [weak self] in
|
||||
self?.viewModel.setting.value = setting
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,34 +361,35 @@ extension SettingsViewController {
|
|||
guard let settings = self.viewModel.setting.value else { return }
|
||||
guard let triggerBy = settings.triggerBy else { return }
|
||||
|
||||
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
|
||||
})?.alert else {
|
||||
return
|
||||
})?.alert {
|
||||
var alertValues = [Bool?]()
|
||||
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 {
|
||||
case L10n.Scene.Settings.Section.Notifications.favorites:
|
||||
alertValues[0] = isOn
|
||||
alerts.favourite = NSNumber(booleanLiteral: isOn)
|
||||
case L10n.Scene.Settings.Section.Notifications.follows:
|
||||
alertValues[1] = isOn
|
||||
alerts.follow = NSNumber(booleanLiteral: isOn)
|
||||
case L10n.Scene.Settings.Section.Notifications.boosts:
|
||||
alertValues[2] = isOn
|
||||
alerts.reblog = NSNumber(booleanLiteral: isOn)
|
||||
case L10n.Scene.Settings.Section.Notifications.mentions:
|
||||
alertValues[3] = isOn
|
||||
alerts.mention = NSNumber(booleanLiteral: isOn)
|
||||
default: break
|
||||
}
|
||||
self.viewModel.updateSubscriptionSubject.send((triggerBy: triggerBy, values: alertValues))
|
||||
} else if let alertValues = self.viewModel.notificationDefaultValue[triggerBy] {
|
||||
self.viewModel.updateSubscriptionSubject.send((triggerBy: triggerBy, values: alertValues))
|
||||
}
|
||||
var alertValues = [Bool?]()
|
||||
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 {
|
||||
case L10n.Scene.Settings.Section.Notifications.favorites:
|
||||
alertValues[0] = isOn
|
||||
alerts.favourite = NSNumber(booleanLiteral: isOn)
|
||||
case L10n.Scene.Settings.Section.Notifications.follows:
|
||||
alertValues[1] = isOn
|
||||
alerts.follow = NSNumber(booleanLiteral: isOn)
|
||||
case L10n.Scene.Settings.Section.Notifications.boosts:
|
||||
alertValues[2] = isOn
|
||||
alerts.reblog = NSNumber(booleanLiteral: isOn)
|
||||
case L10n.Scene.Settings.Section.Notifications.mentions:
|
||||
alertValues[3] = isOn
|
||||
alerts.mention = NSNumber(booleanLiteral: isOn)
|
||||
default: break
|
||||
}
|
||||
self.viewModel.updateSubscriptionSubject.send((triggerBy: triggerBy, values: alertValues))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -435,7 +441,7 @@ extension SettingsViewController {
|
|||
guard let setting: Setting? = {
|
||||
let domain = box.domain
|
||||
let request = Setting.sortedFetchRequest
|
||||
request.predicate = Setting.predicate(domain: domain)
|
||||
request.predicate = Setting.predicate(domain: domain, userID: box.userID)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
|
|
|
@ -29,7 +29,7 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
if let box =
|
||||
self.context.authenticationService.activeMastodonAuthenticationBox.value {
|
||||
let domain = box.domain
|
||||
fetchRequest.predicate = Setting.predicate(domain: domain)
|
||||
fetchRequest.predicate = Setting.predicate(domain: domain, userID: box.userID)
|
||||
}
|
||||
|
||||
fetchRequest.fetchLimit = 1
|
||||
|
@ -78,6 +78,9 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
return Mastodon.API.privacyURL(domain: box.domain)
|
||||
}()
|
||||
|
||||
/// to store who trigger the notification.
|
||||
var triggerBy: String?
|
||||
|
||||
struct Input {
|
||||
}
|
||||
|
||||
|
@ -121,12 +124,14 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
follow: values[1],
|
||||
reblog: values[2],
|
||||
mention: values[3],
|
||||
poll: nil)
|
||||
poll: nil
|
||||
)
|
||||
self.context.apiService.changeSubscription(
|
||||
domain: domain,
|
||||
mastodonAuthenticationBox: activeMastodonAuthenticationBox,
|
||||
query: query,
|
||||
triggerBy: triggerBy
|
||||
triggerBy: triggerBy,
|
||||
userID: activeMastodonAuthenticationBox.userID
|
||||
)
|
||||
.sink { (_) in
|
||||
} receiveValue: { (_) in
|
||||
|
@ -164,7 +169,8 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
domain: domain,
|
||||
mastodonAuthenticationBox: activeMastodonAuthenticationBox,
|
||||
query: query,
|
||||
triggerBy: triggerBy
|
||||
triggerBy: triggerBy,
|
||||
userID: activeMastodonAuthenticationBox.userID
|
||||
)
|
||||
.sink { (_) in
|
||||
} receiveValue: { (_) in
|
||||
|
@ -178,13 +184,6 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
|
||||
// request subsription data for updating or initialization
|
||||
requestSubscription()
|
||||
|
||||
do {
|
||||
try fetchResultsController.performFetch()
|
||||
setting.value = fetchResultsController.fetchedObjects?.first
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -213,12 +212,12 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
} else if let triggerBy = settings?.triggerBy,
|
||||
let values = self.notificationDefaultValue[triggerBy] {
|
||||
switches = values
|
||||
self.createSubscriptionSubject.send((triggerBy: triggerBy, values: values))
|
||||
} else {
|
||||
// fallback a default value
|
||||
let anyone = L10n.Scene.Settings.Section.Notifications.Trigger.anyone
|
||||
switches = self.notificationDefaultValue[anyone]
|
||||
}
|
||||
|
||||
let notifications = [L10n.Scene.Settings.Section.Notifications.favorites,
|
||||
L10n.Scene.Settings.Section.Notifications.follows,
|
||||
L10n.Scene.Settings.Section.Notifications.boosts,
|
||||
|
@ -273,31 +272,61 @@ class SettingsViewModel: NSObject, NeedsDependency {
|
|||
}
|
||||
|
||||
private func requestSubscription() {
|
||||
// request subscription of notifications
|
||||
typealias SubscriptionResponse = Mastodon.Response.Content<Mastodon.Entity.Subscription>
|
||||
viewDidLoad.flatMap { [weak self] (_) -> AnyPublisher<SubscriptionResponse, Error> in
|
||||
guard let self = self,
|
||||
let activeMastodonAuthenticationBox =
|
||||
self.context.authenticationService.activeMastodonAuthenticationBox.value else {
|
||||
return Empty<SubscriptionResponse, Error>().eraseToAnyPublisher()
|
||||
setting.sink { [weak self] (settings) in
|
||||
guard let self = self else { return }
|
||||
guard settings != nil else { return }
|
||||
guard self.triggerBy != settings?.triggerBy else { return }
|
||||
self.triggerBy = settings?.triggerBy
|
||||
|
||||
var switches: [Bool?]?
|
||||
var who: String?
|
||||
if let alerts = settings?.subscription?.first(where: { (s) -> Bool in
|
||||
return s.type == settings?.triggerBy
|
||||
})?.alert {
|
||||
var items = [Bool?]()
|
||||
items.append(alerts.favourite?.boolValue)
|
||||
items.append(alerts.follow?.boolValue)
|
||||
items.append(alerts.reblog?.boolValue)
|
||||
items.append(alerts.mention?.boolValue)
|
||||
switches = items
|
||||
who = settings?.triggerBy
|
||||
} else if let triggerBy = settings?.triggerBy,
|
||||
let values = self.notificationDefaultValue[triggerBy] {
|
||||
switches = values
|
||||
who = triggerBy
|
||||
} else {
|
||||
// fallback a default value
|
||||
let anyone = L10n.Scene.Settings.Section.Notifications.Trigger.anyone
|
||||
switches = self.notificationDefaultValue[anyone]
|
||||
who = anyone
|
||||
}
|
||||
|
||||
let domain = activeMastodonAuthenticationBox.domain
|
||||
return self.context.apiService.subscription(
|
||||
domain: domain,
|
||||
mastodonAuthenticationBox: activeMastodonAuthenticationBox)
|
||||
}
|
||||
.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))
|
||||
}
|
||||
// should create a subscription whenever change trigger
|
||||
if let values = switches, let triggerBy = who {
|
||||
self.createSubscriptionSubject.send((triggerBy: triggerBy, values: values))
|
||||
}
|
||||
} receiveValue: { (subscription) in
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
guard let activeMastodonAuthenticationBox = self.context.authenticationService.activeMastodonAuthenticationBox.value else {
|
||||
return
|
||||
}
|
||||
let domain = activeMastodonAuthenticationBox.domain
|
||||
let userId = activeMastodonAuthenticationBox.userID
|
||||
|
||||
do {
|
||||
try fetchResultsController.performFetch()
|
||||
if nil == fetchResultsController.fetchedObjects?.first {
|
||||
let anyone = L10n.Scene.Settings.Section.Notifications.Trigger.anyone
|
||||
setting.value = self.context.apiService.createSettingIfNeed(domain: domain,
|
||||
userId: userId,
|
||||
triggerBy: anyone)
|
||||
} else {
|
||||
setting.value = fetchResultsController.fetchedObjects?.first
|
||||
}
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
}
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
|
|
@ -5,44 +5,71 @@
|
|||
// Created by ihugo on 2021/4/9.
|
||||
//
|
||||
|
||||
import Combine
|
||||
import CoreData
|
||||
import CoreDataStack
|
||||
import Foundation
|
||||
import MastodonSDK
|
||||
import Combine
|
||||
|
||||
extension APIService {
|
||||
|
||||
func subscription(
|
||||
domain: String,
|
||||
userID: String,
|
||||
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox
|
||||
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Subscription>, Error> {
|
||||
let authorization = mastodonAuthenticationBox.userAuthorization
|
||||
|
||||
|
||||
let findSettings: Setting? = {
|
||||
let request = Setting.sortedFetchRequest
|
||||
request.predicate = Setting.predicate(domain: domain, userID: userID)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
return try self.backgroundManagedObjectContext.fetch(request).first
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
let triggerBy = findSettings?.triggerBy ?? "anyone"
|
||||
let setting = self.createSettingIfNeed(
|
||||
domain: domain,
|
||||
userId: userID,
|
||||
triggerBy: triggerBy
|
||||
)
|
||||
return Mastodon.API.Subscriptions.subscription(
|
||||
session: session,
|
||||
domain: domain,
|
||||
authorization: authorization)
|
||||
.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)
|
||||
}
|
||||
.setFailureType(to: Error.self)
|
||||
.map { _ in return response }
|
||||
.eraseToAnyPublisher()
|
||||
}.eraseToAnyPublisher()
|
||||
authorization: authorization
|
||||
)
|
||||
.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,
|
||||
setting: setting)
|
||||
}
|
||||
.setFailureType(to: Error.self)
|
||||
.map { _ in return response }
|
||||
.eraseToAnyPublisher()
|
||||
}.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func changeSubscription(
|
||||
domain: String,
|
||||
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox,
|
||||
query: Mastodon.API.Subscriptions.CreateSubscriptionQuery,
|
||||
triggerBy: String
|
||||
triggerBy: String,
|
||||
userID: String
|
||||
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Subscription>, Error> {
|
||||
let authorization = mastodonAuthenticationBox.userAuthorization
|
||||
|
||||
let setting = self.createSettingIfNeed(domain: domain,
|
||||
userId: userID,
|
||||
triggerBy: triggerBy)
|
||||
return Mastodon.API.Subscriptions.createSubscription(
|
||||
session: session,
|
||||
domain: domain,
|
||||
|
@ -55,7 +82,9 @@ extension APIService {
|
|||
into: self.backgroundManagedObjectContext,
|
||||
entity: response.value,
|
||||
domain: domain,
|
||||
triggerBy: triggerBy)
|
||||
triggerBy: triggerBy,
|
||||
setting: setting
|
||||
)
|
||||
}
|
||||
.setFailureType(to: Error.self)
|
||||
.map { _ in return response }
|
||||
|
@ -67,10 +96,15 @@ extension APIService {
|
|||
domain: String,
|
||||
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox,
|
||||
query: Mastodon.API.Subscriptions.UpdateSubscriptionQuery,
|
||||
triggerBy: String
|
||||
triggerBy: String,
|
||||
userID: String
|
||||
) -> AnyPublisher<Mastodon.Response.Content<Mastodon.Entity.Subscription>, Error> {
|
||||
let authorization = mastodonAuthenticationBox.userAuthorization
|
||||
|
||||
let setting = self.createSettingIfNeed(domain: domain,
|
||||
userId: userID,
|
||||
triggerBy: triggerBy)
|
||||
|
||||
return Mastodon.API.Subscriptions.updateSubscription(
|
||||
session: session,
|
||||
domain: domain,
|
||||
|
@ -83,12 +117,47 @@ extension APIService {
|
|||
into: self.backgroundManagedObjectContext,
|
||||
entity: response.value,
|
||||
domain: domain,
|
||||
triggerBy: triggerBy)
|
||||
triggerBy: triggerBy,
|
||||
setting: setting
|
||||
)
|
||||
}
|
||||
.setFailureType(to: Error.self)
|
||||
.map { _ in return response }
|
||||
.eraseToAnyPublisher()
|
||||
}.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func createSettingIfNeed(domain: String, userId: String, triggerBy: String) -> Setting {
|
||||
// create setting entity if possible
|
||||
let oldSetting: Setting? = {
|
||||
let request = Setting.sortedFetchRequest
|
||||
request.predicate = Setting.predicate(domain: domain, userID: userId)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
return try backgroundManagedObjectContext.fetch(request).first
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
var setting: Setting!
|
||||
if let oldSetting = oldSetting {
|
||||
setting = oldSetting
|
||||
} else {
|
||||
let property = Setting.Property(
|
||||
appearance: "automatic",
|
||||
triggerBy: triggerBy,
|
||||
domain: domain,
|
||||
userID: userId)
|
||||
(setting, _) = APIService.CoreData.createOrMergeSetting(
|
||||
into: backgroundManagedObjectContext,
|
||||
domain: domain,
|
||||
userID: userId,
|
||||
property: property
|
||||
)
|
||||
}
|
||||
return setting
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,11 +16,12 @@ extension APIService.CoreData {
|
|||
static func createOrMergeSetting(
|
||||
into managedObjectContext: NSManagedObjectContext,
|
||||
domain: String,
|
||||
userID: String,
|
||||
property: Setting.Property
|
||||
) -> (Subscription: Setting, isCreated: Bool) {
|
||||
let oldSetting: Setting? = {
|
||||
let request = Setting.sortedFetchRequest
|
||||
request.predicate = Setting.predicate(domain: property.domain)
|
||||
request.predicate = Setting.predicate(domain: property.domain, userID: userID)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
|
@ -45,38 +46,12 @@ extension APIService.CoreData {
|
|||
into managedObjectContext: NSManagedObjectContext,
|
||||
entity: Mastodon.Entity.Subscription,
|
||||
domain: String,
|
||||
triggerBy: String? = nil
|
||||
triggerBy: String,
|
||||
setting: Setting
|
||||
) -> (Subscription: Subscription, isCreated: Bool) {
|
||||
// create setting entity if possible
|
||||
let oldSetting: Setting? = {
|
||||
let request = Setting.sortedFetchRequest
|
||||
request.predicate = Setting.predicate(domain: domain)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
return try managedObjectContext.fetch(request).first
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
var setting: Setting!
|
||||
if let oldSetting = oldSetting {
|
||||
setting = oldSetting
|
||||
} else {
|
||||
let property = Setting.Property(
|
||||
appearance: "automatic",
|
||||
triggerBy: "anyone",
|
||||
domain: domain)
|
||||
(setting, _) = createOrMergeSetting(
|
||||
into: managedObjectContext,
|
||||
domain: domain,
|
||||
property: property)
|
||||
}
|
||||
|
||||
let oldSubscription: Subscription? = {
|
||||
let request = Subscription.sortedFetchRequest
|
||||
request.predicate = Subscription.predicate(id: entity.id)
|
||||
request.predicate = Subscription.predicate(type: triggerBy)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
|
@ -91,7 +66,8 @@ extension APIService.CoreData {
|
|||
endpoint: entity.endpoint,
|
||||
id: entity.id,
|
||||
serverKey: entity.serverKey,
|
||||
type: triggerBy ?? setting.triggerBy ?? "")
|
||||
type: triggerBy
|
||||
)
|
||||
let alertEntity = entity.alerts
|
||||
let alert = SubscriptionAlerts.Property(
|
||||
favourite: alertEntity.favouriteNumber,
|
||||
|
@ -105,7 +81,8 @@ extension APIService.CoreData {
|
|||
if nil == oldSubscription.alert {
|
||||
oldSubscription.alert = SubscriptionAlerts.insert(
|
||||
into: managedObjectContext,
|
||||
property: alert)
|
||||
property: alert
|
||||
)
|
||||
} else {
|
||||
oldSubscription.alert?.updateIfNeed(property: alert)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue