Версия 3.2.0: контракт v2, оформление «Лес» #2
No files matched your search
@@ -20,7 +20,7 @@ extension EnvironmentValues {
|
||||
struct CurrencyContextProvider<Content: View>: View {
|
||||
@Query private var accounts: [FinanceAccount]
|
||||
@Query private var rates: [ExchangeRate]
|
||||
@Query(filter: #Predicate<SyncRecord> { $0.entity == "setting" && $0.recordID == "baseCurrency" })
|
||||
@Query(filter: #Predicate<SyncRecord> { $0.entityName == "setting" && $0.recordID == "baseCurrency" })
|
||||
private var baseSetting: [SyncRecord]
|
||||
@AppStorage("currencyCode") private var currencyCode = SupportedCurrency.RUB.rawValue
|
||||
@ViewBuilder let content: Content
|
||||
|
||||
@@ -489,7 +489,7 @@ struct WatchSettingsView: View {
|
||||
@StateObject private var account = ServerAccountStore.shared
|
||||
@AppStorage("currencyCode") private var currencyCode = SupportedCurrency.RUB.rawValue
|
||||
@AppStorage("appTheme") private var appTheme = AppTheme.system.rawValue
|
||||
@Query(filter: #Predicate<SyncRecord> { $0.entity == "setting" && $0.recordID == "baseCurrency" })
|
||||
@Query(filter: #Predicate<SyncRecord> { $0.entityName == "setting" && $0.recordID == "baseCurrency" })
|
||||
private var baseSetting: [SyncRecord]
|
||||
|
||||
private var currencyCodes: [String] {
|
||||
@@ -508,7 +508,7 @@ struct WatchSettingsView: View {
|
||||
record.payload = payload
|
||||
record.syncUpdatedAt = .now
|
||||
} else {
|
||||
modelContext.insert(SyncRecord(entity: "setting", recordID: SyncRecord.baseCurrencyKey, payload: payload, syncUpdatedAt: .now))
|
||||
modelContext.insert(SyncRecord(entityName: "setting", recordID: SyncRecord.baseCurrencyKey, payload: payload, syncUpdatedAt: .now))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -70,13 +70,15 @@ final class ExchangeRate {
|
||||
/// `attachment`, `setting`. Payload хранится целиком, поэтому все поля сохраняются.
|
||||
@Model
|
||||
final class SyncRecord {
|
||||
var entity: String = ""
|
||||
/// Не `entity`: так называется встроенное свойство CoreData, и предикат
|
||||
/// по нему ломает SQL-запрос SwiftData.
|
||||
var entityName: String = ""
|
||||
var recordID: String = ""
|
||||
var payload: Data = Data()
|
||||
var syncUpdatedAt: Date = Date.now
|
||||
|
||||
init(entity: String, recordID: String, payload: Data, syncUpdatedAt: Date) {
|
||||
self.entity = entity
|
||||
init(entityName: String, recordID: String, payload: Data, syncUpdatedAt: Date) {
|
||||
self.entityName = entityName
|
||||
self.recordID = recordID
|
||||
self.payload = payload
|
||||
self.syncUpdatedAt = syncUpdatedAt
|
||||
|
||||
@@ -498,9 +498,9 @@ final class ServerAccountStore: ObservableObject {
|
||||
private func pushSettings(context: ModelContext, after threshold: Date, through cutoff: Date, cursor: Int64) async throws {
|
||||
let lowerBound = threshold, upperBound = cutoff
|
||||
let items = try context.fetch(FetchDescriptor<SyncRecord>(predicate: #Predicate { item in
|
||||
item.entity == "setting" && item.syncUpdatedAt >= lowerBound && item.syncUpdatedAt <= upperBound
|
||||
item.entityName == "setting" && item.syncUpdatedAt >= lowerBound && item.syncUpdatedAt <= upperBound
|
||||
}))
|
||||
try await sendPush(items.map { SyncChange(entity:$0.entity, id:$0.recordID, deleted:false, updatedAt:$0.syncUpdatedAt, payload:$0.payload) }, cursor:cursor)
|
||||
try await sendPush(items.map { SyncChange(entity:$0.entityName, id:$0.recordID, deleted:false, updatedAt:$0.syncUpdatedAt, payload:$0.payload) }, cursor:cursor)
|
||||
}
|
||||
|
||||
private func pushTombstones(through cutoff: Date, cursor: Int64) async throws {
|
||||
@@ -660,12 +660,12 @@ final class ServerAccountStore: ObservableObject {
|
||||
/// Регулярные операции часы не исполняют (§4).
|
||||
private func applyRecord(_ change: SyncChange, context: ModelContext) throws {
|
||||
let entity = change.entity, recordID = change.id
|
||||
let existing = try context.fetch(FetchDescriptor<SyncRecord>(predicate:#Predicate { $0.entity == entity && $0.recordID == recordID })).first
|
||||
let existing = try context.fetch(FetchDescriptor<SyncRecord>(predicate:#Predicate { $0.entityName == entity && $0.recordID == recordID })).first
|
||||
if let existing, existing.syncUpdatedAt > change.updatedAt { return }
|
||||
if change.deleted { if let existing { context.delete(existing) }; return }
|
||||
guard let data = change.payload else { return }
|
||||
if let existing { existing.payload = data; existing.syncUpdatedAt = change.updatedAt }
|
||||
else { context.insert(SyncRecord(entity:entity, recordID:recordID, payload:data, syncUpdatedAt:change.updatedAt)) }
|
||||
else { context.insert(SyncRecord(entityName:entity, recordID:recordID, payload:data, syncUpdatedAt:change.updatedAt)) }
|
||||
}
|
||||
|
||||
private func transaction(id: UUID, context: ModelContext) throws -> FinanceTransaction? {
|
||||
|
||||
Reference in new issue
Block a user