wordeck-native/Sources/Core/Sync/PendingShareStore.swift
Till JS 542082772a refactor(big-bang): cards-native → wordeck-native
Code + Identity-Rename zur Vorbereitung auf Apple-Dev-Portal-Aktion
(Bundle ev.mana.wordeck, App-Group group.ev.mana.wordeck, AASA
applinks:wordeck.com). Build bleibt funktional, aber gegen die
neue text-only-API können image-occlusion-Creates 422 zurückgeben —
das wird mit der Wordeck-Native v1.0-Welle (parallele Apple-Aktion)
sauber gemacht.

Umbenennung:
- 41 Files: cardecky/Cardecky → wordeck/Wordeck (Display, Strings,
  Kommentare)
- 57 Files: CardsNative → WordeckNative, CardsAPI → WordeckAPI,
  CardsTheme → WordeckTheme, CardsBrand → WordeckBrand, CardsWidget →
  WordeckWidget, CardsDueWidget → WordeckDueWidget
- Bundle-ID ev.mana.cardecky → ev.mana.wordeck (project.yml,
  Info.plist, entitlements, Keychain-Service, App-Group)
- AASA applinks:cardecky.mana.how → applinks:wordeck.com
- API-Base cardecky-api.mana.how → api.wordeck.com
- 10 Files renamed (App-Entry, API-Extensions, Theme, Widget,
  Entitlements, Tests)
- xcodeproj regenerated via xcodegen → WordeckNative.xcodeproj
- MaskRegionsTests.swift gelöscht (image-occlusion entfällt mit
  Wordeck text-only)

Forgejo-Repo git.mana.how/till/cards-native → wordeck-native umbenannt
(Auto-Redirect aktiv). Lokales Verzeichnis Code/cards-native/ bleibt
vorerst — wird beim nächsten Apple-Setup mit Bundle-Test umbenannt.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 23:10:42 +02:00

61 lines
2.1 KiB
Swift

import Foundation
/// Inbox für Share-Extension. Die Extension persistiert hier, die
/// Haupt-App liest beim Start und zeigt einen Banner mit
/// " Als Karte speichern". Shared App-Group-Container.
struct PendingShare: Codable, Identifiable, Hashable {
let id: String
let text: String
let sourceURL: String?
let capturedAt: Date
init(text: String, sourceURL: String? = nil, capturedAt: Date = .now) {
id = "\(capturedAt.timeIntervalSince1970)-\(UUID().uuidString.prefix(8))"
self.text = text
self.sourceURL = sourceURL
self.capturedAt = capturedAt
}
}
enum PendingShareStore {
static let appGroupID = "group.ev.mana.wordeck"
static let filename = "pending-shares.json"
static var url: URL? {
FileManager.default
.containerURL(forSecurityApplicationGroupIdentifier: appGroupID)?
.appendingPathComponent(filename)
}
/// FIFO-Liste aller noch nicht konsumierten Shares.
static func readAll() -> [PendingShare] {
guard let url, let data = try? Data(contentsOf: url) else { return [] }
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
return (try? decoder.decode([PendingShare].self, from: data)) ?? []
}
/// Append-only-Write. Bei Concurrent-Writes aus Extension + Haupt-App
/// kann ein Eintrag verloren gehen akzeptabel, weil Extension nur
/// schreibt wenn User aktiv "Teilen" tippt.
static func append(_ share: PendingShare) {
guard url != nil else { return }
var all = readAll()
all.append(share)
write(all)
}
/// Entfernt einen Eintrag (wenn die Haupt-App ihn als Karte gespeichert hat).
static func remove(id: String) {
let all = readAll().filter { $0.id != id }
write(all)
}
private static func write(_ shares: [PendingShare]) {
guard let url else { return }
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
guard let data = try? encoder.encode(shares) else { return }
try? data.write(to: url, options: .atomic)
}
}