mana-swift-core/Sources/ManaCore/Feedback/FeedbackSubmission.swift
Till JS 8cb6fdc945 feat(feedback): FeedbackImage + images im Submit (v2.2.0)
FeedbackSubmission.images (base64, ohne data:-Praefix, 1:1 zum Web- und
Android-Vertrag); FeedbackClient-Payload sendet images:[{mime,b64}].
Additiv. Test deckt Bild-Payload ab.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-12 19:56:08 +02:00

79 lines
2.6 KiB
Swift

import Foundation
/// Eine vom Nutzer ausgefüllte Feedback-Einreichung. Technischer Kontext
/// (App-Version, OS, Locale, Gerät) ergänzt der ``FeedbackClient``
/// automatisch — er ist im Backend nur der Vorstand-Sicht sichtbar
/// (Feld-Redaktion, siehe `FEEDBACK_STRATEGIE.md`).
public struct FeedbackSubmission: Sendable {
public var kind: FeedbackKind
public var title: String
public var description: String
/// Nur bei anonymer Einreichung (kein Token) relevant: Rückfrage-Adresse.
public var contactEmail: String?
/// Nur bei anonymer Einreichung relevant: Anzeigename / Kürzel.
public var guestName: String?
/// Optionale Screenshot-Anhänge (bereits herunterskaliert + EXIF-frei).
public var images: [FeedbackImage]
public init(
kind: FeedbackKind,
title: String,
description: String,
contactEmail: String? = nil,
guestName: String? = nil,
images: [FeedbackImage] = []
) {
self.kind = kind
self.title = title
self.description = description
self.contactEmail = contactEmail
self.guestName = guestName
self.images = images
}
}
/// Ein base64-kodierter Bild-Anhang. ``b64`` ist **reines** base64 der Bytes —
/// **ohne** `data:`-Präfix, exakt wie der Web-`FeedbackImage`-Vertrag
/// (`@mana/shared-feedback`). Das Backend lädt es nach mana-media und hängt
/// nur die Media-ID an die Einreichung (Vorstand-only).
public struct FeedbackImage: Sendable {
/// MIME-Typ, z.B. `"image/jpeg"`.
public var mime: String
/// Reines base64 der Bytes (kein `data:…;base64,`-Präfix).
public var b64: String
public init(mime: String, b64: String) {
self.mime = mime
self.b64 = b64
}
}
/// Antwort des Backends auf eine Einreichung.
public struct FeedbackResult: Sendable, Decodable {
public let id: String?
public let status: String
public let kind: String?
public let message: String?
public init(id: String?, status: String, kind: String?, message: String?) {
self.id = id
self.status = status
self.kind = kind
self.message = message
}
}
/// Fehler bei der Einreichung.
public enum FeedbackError: Error, Sendable, LocalizedError {
case network(String)
case server(status: Int, message: String?)
public var errorDescription: String? {
switch self {
case .network(let message):
return message
case .server(_, let message):
return message ?? "Senden fehlgeschlagen. Bitte später erneut versuchen."
}
}
}