mana-swift-ui/Sources/ManaFeedbackUI/ManaFeedbackButton.swift
Till JS 9844759e86 feat(ManaFeedbackUI): natives Feedback-Sheet + Button (F-4.1)
Neues Library-Produkt ManaFeedbackUI: ManaFeedbackSheet (Kind-Picker/
Titel/Beschreibung, anon + Kontakt-Mail), ManaFeedbackButton +
.manaFeedbackSheet()-Modifier. Postet via ManaCore.FeedbackClient.
Theming via \.manaTheme. swift build grün.
mana/docs/FEEDBACK_NATIVE_PLAN.md.

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

65 lines
2.1 KiB
Swift

import ManaCore
import SwiftUI
/// Knopf, der das ``ManaFeedbackSheet`` präsentiert. Für Apps, die kein
/// eigenes Trigger-Element haben sonst lieber der
/// `.manaFeedbackSheet(...)`-Modifier mit eigenem Button (HIG: kein
/// schwebendes Bubble-UI auf iOS, Platzierung in Settings/Konto/Toolbar).
///
/// ```swift
/// // eingeloggte App:
/// ManaFeedbackButton(
/// client: FeedbackClient(appId: "memoro") { try? await auth.freshAccessToken() },
/// isLoggedIn: session.isLoggedIn
/// )
/// // mit eigenem Label:
/// ManaFeedbackButton(client: client, isLoggedIn: false) {
/// Label("Feedback geben", systemImage: "bubble.left.and.bubble.right")
/// }
/// ```
public struct ManaFeedbackButton<Label: View>: View {
private let client: FeedbackClient
private let isLoggedIn: Bool
private let label: () -> Label
@State private var isPresented = false
public init(
client: FeedbackClient,
isLoggedIn: Bool,
@ViewBuilder label: @escaping () -> Label
) {
self.client = client
self.isLoggedIn = isLoggedIn
self.label = label
}
public var body: some View {
Button { isPresented = true } label: { label() }
.manaFeedbackSheet(isPresented: $isPresented, client: client, isLoggedIn: isLoggedIn)
}
}
extension ManaFeedbackButton where Label == SwiftUI.Label<Text, Image> {
/// Standard-Label Feedback" mit Sprechblasen-Icon.
public init(client: FeedbackClient, isLoggedIn: Bool, title: String = "Feedback") {
self.init(client: client, isLoggedIn: isLoggedIn) {
SwiftUI.Label(title, systemImage: "bubble.left.and.bubble.right")
}
}
}
extension View {
/// Hängt das ``ManaFeedbackSheet`` an einen Binding-gesteuerten
/// Präsentations-Zustand für Apps mit eigenem Trigger (z.B. ein
/// Nav-Pill oder Settings-Row).
public func manaFeedbackSheet(
isPresented: Binding<Bool>,
client: FeedbackClient,
isLoggedIn: Bool
) -> some View {
sheet(isPresented: isPresented) {
ManaFeedbackSheet(client: client, isLoggedIn: isLoggedIn)
}
}
}