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>
89 lines
3 KiB
Swift
89 lines
3 KiB
Swift
import ManaCore
|
|
import SwiftUI
|
|
|
|
/// Liste der vom User blockierten Marketplace-Authors. Entblock-Action
|
|
/// per Swipe — analog zur iOS-Mail-Inbox.
|
|
///
|
|
/// App-Store-Guideline 5.1.1(v) verlangt: Block-Mechanismus für UGC
|
|
/// muss verwaltbar sein. Diese View ist der Verwaltungs-Endpunkt.
|
|
struct BlockedAuthorsView: View {
|
|
@Environment(AuthClient.self) private var auth
|
|
|
|
@State private var blocks: [BlockEntry] = []
|
|
@State private var isLoading = false
|
|
@State private var errorMessage: String?
|
|
|
|
var body: some View {
|
|
ZStack {
|
|
WordeckTheme.background.ignoresSafeArea()
|
|
content
|
|
}
|
|
.navigationTitle("Blockierte Authors")
|
|
#if os(iOS)
|
|
.navigationBarTitleDisplayMode(.inline)
|
|
#endif
|
|
.task { await load() }
|
|
.refreshable { await load() }
|
|
}
|
|
|
|
@ViewBuilder
|
|
private var content: some View {
|
|
if isLoading, blocks.isEmpty {
|
|
ProgressView().tint(WordeckTheme.primary)
|
|
} else if blocks.isEmpty {
|
|
ContentUnavailableView(
|
|
"Keine blockierten Authors",
|
|
systemImage: "hand.raised.slash",
|
|
description: Text("Blockiere Authors über das Menü oben rechts auf Marketplace-Decks.")
|
|
)
|
|
.foregroundStyle(WordeckTheme.mutedForeground)
|
|
} else {
|
|
List {
|
|
ForEach(blocks) { block in
|
|
VStack(alignment: .leading, spacing: 2) {
|
|
Text(block.displayName)
|
|
.font(.subheadline.weight(.semibold))
|
|
Text("@\(block.authorSlug)")
|
|
.font(.caption)
|
|
.foregroundStyle(WordeckTheme.mutedForeground)
|
|
}
|
|
.swipeActions {
|
|
Button("Entblocken") {
|
|
Task { await unblock(block) }
|
|
}
|
|
.tint(WordeckTheme.primary)
|
|
}
|
|
}
|
|
}
|
|
.listStyle(.plain)
|
|
.scrollContentBackground(.hidden)
|
|
if let errorMessage {
|
|
Text(errorMessage)
|
|
.font(.caption)
|
|
.foregroundStyle(WordeckTheme.error)
|
|
.padding(.horizontal, 16)
|
|
}
|
|
}
|
|
}
|
|
|
|
private func load() async {
|
|
isLoading = true
|
|
defer { isLoading = false }
|
|
let api = WordeckAPI(auth: auth)
|
|
do {
|
|
blocks = try await api.myBlocks()
|
|
} catch {
|
|
errorMessage = (error as? LocalizedError)?.errorDescription ?? String(describing: error)
|
|
}
|
|
}
|
|
|
|
private func unblock(_ block: BlockEntry) async {
|
|
let api = WordeckAPI(auth: auth)
|
|
do {
|
|
try await api.unblockAuthor(slug: block.authorSlug)
|
|
blocks.removeAll { $0.id == block.id }
|
|
} catch {
|
|
errorMessage = (error as? LocalizedError)?.errorDescription ?? String(describing: error)
|
|
}
|
|
}
|
|
}
|