Files
OSGKeyboard/OSGKeyboardMac/MacSupportDeveloperTipRows.swift
T
Rocky 39002336c0
CI / Validate manifests (push) Has been cancelled
CI / SwiftLint (push) Has been cancelled
CI / iOS / Extension (push) Has been cancelled
CI / macOS (push) Has been cancelled
feat(app): add flow diagnostics and refine interface
Improve failure recovery visibility, strengthen account-session handling, and make the cross-platform interface more consistent.
2026-08-26 14:40:06 +08:00

92 lines
3.0 KiB
Swift

// MacSupportDeveloperTipRows.swift
// OSGKeyboard · Mac
//
// Optional consumable tip rows for macOS Settings.
import SwiftUI
struct MacSupportDeveloperTipRows: View {
@ObservedObject private var tipManager = TipPurchaseManager.shared
@Environment(\.themePalette) private var palette
let language: AppUILanguage
@State private var showThankYouAlert = false
@State private var showErrorAlert = false
@State private var errorMessage = ""
var body: some View {
VStack(alignment: .leading, spacing: MacMetrics.settingsRowGap) {
SupportDeveloperTipBody(language: language)
.padding(.horizontal, MacMetrics.settingsCardInset)
if tipManager.supportCount > 0 {
Text(
SharedL10n.format(
"tip.thankYou.past",
language: language,
tipManager.supportCount
)
)
.font(TypeStyle.caption)
.foregroundStyle(palette.accent)
.padding(.horizontal, MacMetrics.settingsCardInset)
}
MacSettingsToolButton(title: tipButtonTitle, disabled: isPurchaseInFlight) {
Task { await tipManager.purchase() }
}
.padding(.horizontal, MacMetrics.settingsCardInset)
}
.onChange(of: tipManager.purchaseState) { _, newValue in
switch newValue {
case .succeeded:
showThankYouAlert = true
case .failed(let message):
errorMessage = message
showErrorAlert = true
default:
break
}
}
.alert(
SharedL10n.string("tip.thankYou.title", language: language),
isPresented: $showThankYouAlert
) {
Button(SharedL10n.string("tip.alert.dismiss", language: language)) {
tipManager.acknowledgePurchaseState()
}
.tint(palette.textPrimary)
} message: {
Text(SharedL10n.string("tip.thankYou.message", language: language))
}
.alert(
SharedL10n.string("tip.error.title", language: language),
isPresented: $showErrorAlert
) {
Button(SharedL10n.string("tip.alert.dismiss", language: language)) {
tipManager.acknowledgePurchaseState()
}
.tint(palette.textPrimary)
} message: {
Text(errorMessage)
}
}
private var isPurchaseInFlight: Bool {
switch tipManager.purchaseState {
case .loading, .purchasing:
return true
default:
return false
}
}
private var tipButtonTitle: String {
if let product = tipManager.product {
return SharedL10n.format("tip.button", language: language, product.displayPrice)
}
return SharedL10n.string("tip.buttonFallback", language: language)
}
}