Default `--self remove` strippt `self.` aus @autoclosure-Calls (Logger.info) und Closure-Captures, was Swift-6-strict-concurrency dann als "implicit use of self in closure" rejected. Default `redundantSendable` strippt `Sendable` von Codable-DTOs, die über actor-Grenzen wandern müssen. Beide Regeln aus. Zusätzlich Lauf über alle Files: harmlose Whitespace-/ Trailing-Comma-/Optional-Init-Normalisierung in 5 Files. `self.` und `Sendable` bleiben überall erhalten. Build grün. Hintergrund: η-0-Lauf hat das aktiv gemacht und Submit-DTOs zerschossen, die ich dann von Hand revertieren musste. Dieser Commit verhindert die Wiederholung in η-1+. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
84 lines
2.9 KiB
Swift
84 lines
2.9 KiB
Swift
import Foundation
|
|
import SwiftData
|
|
|
|
/// Pending Quote-Submission, die wegen Network-Fehler nicht durchging.
|
|
/// Wird beim nächsten Foreground/Reconnect via `SubmissionQueue.tryFlush`
|
|
/// nachgereicht.
|
|
///
|
|
/// Eigener Store (`submissions.store`) im App-Group-Container, damit
|
|
/// Snapshot-Sync und Pending-Submissions sich nicht in den Quere kommen.
|
|
@Model
|
|
final class PendingSubmission {
|
|
@Attribute(.unique) var id: UUID
|
|
var createdAt: Date
|
|
var lastTriedAt: Date?
|
|
var retryCount: Int
|
|
var lastError: String?
|
|
|
|
// QuoteDraft-Felder, flach gespeichert für SwiftData-Kompatibilität.
|
|
var text: String
|
|
var language: String
|
|
var authorName: String?
|
|
var authorSlug: String?
|
|
var sourceTitle: String?
|
|
var sourceKindRaw: String?
|
|
var sourceYear: Int?
|
|
var editReason: String?
|
|
var acceptedTos: Bool
|
|
|
|
init(draft: QuoteDraft, id: UUID = UUID(), createdAt: Date = Date()) {
|
|
self.id = id
|
|
self.createdAt = createdAt
|
|
self.retryCount = 0
|
|
self.text = draft.text
|
|
self.language = draft.language
|
|
self.authorName = draft.authorName
|
|
self.authorSlug = draft.authorSlug
|
|
self.sourceTitle = draft.sourceTitle
|
|
self.sourceKindRaw = draft.sourceKind?.rawValue
|
|
self.sourceYear = draft.sourceYear
|
|
self.editReason = draft.editReason
|
|
self.acceptedTos = draft.acceptedTos
|
|
}
|
|
|
|
func toDraft() -> QuoteDraft {
|
|
QuoteDraft(
|
|
text: text,
|
|
language: language,
|
|
authorName: authorName,
|
|
authorSlug: authorSlug,
|
|
sourceTitle: sourceTitle,
|
|
sourceKind: sourceKindRaw.flatMap(QuoteDraft.SourceKind.init(rawValue:)),
|
|
sourceYear: sourceYear,
|
|
editReason: editReason,
|
|
acceptedTos: acceptedTos
|
|
)
|
|
}
|
|
}
|
|
|
|
/// Helper für den ModelContainer. Eigener Store, damit das
|
|
/// Snapshot-Schema nicht mit-migriert wird, wenn wir Submission-
|
|
/// Felder ändern.
|
|
enum PendingSubmissionContainer {
|
|
static let appGroup = "group.ev.mana.zitare"
|
|
|
|
static func defaultStoreURL() -> URL {
|
|
let fm = FileManager.default
|
|
if let groupURL = fm.containerURL(forSecurityApplicationGroupIdentifier: appGroup) {
|
|
return groupURL.appendingPathComponent("submissions.store")
|
|
}
|
|
let docs = fm.urls(for: .documentDirectory, in: .userDomainMask).first
|
|
?? URL(fileURLWithPath: NSTemporaryDirectory())
|
|
return docs.appendingPathComponent("submissions.store")
|
|
}
|
|
|
|
static func make(inMemory: Bool = false) throws -> ModelContainer {
|
|
let schema = Schema([PendingSubmission.self])
|
|
let config = if inMemory {
|
|
ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
|
|
} else {
|
|
ModelConfiguration("submissions", schema: schema, url: defaultStoreURL())
|
|
}
|
|
return try ModelContainer(for: schema, configurations: [config])
|
|
}
|
|
}
|