mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 10:29:58 +02:00
Replaces every stringly-typed localization key in the Apple app with compile-time-checked accessors generated from localization/strings.json. A mistyped key is now a build error instead of a silent fallback to the raw key at runtime. The runtime path is unchanged: plain keys are String.LocalizationValue constants resolved with String(localized:) and Apple's String Catalog still does the lookup; keys with arguments become typed, named functions applying args through String(format:). Generator: new renderSwiftAccessors emits apple/VniDrop/Generated/L10n.swift, wired into generate. Renamed generic arg1/arg2 tokens on four keys to semantic names (receiver, transferName, deviceId) and updated their context notes; positional output is unchanged so .xcstrings (bar the 4 comments) and the Android XML regenerate identical. Migration: every key-carrying value flipped to String.LocalizationValue end to end, resolved only at the leaf. Zero key literals and zero LocalizedStringKey remain in app or test code. macOS build passes; iOS test run pending.
62 lines
2.3 KiB
Swift
62 lines
2.3 KiB
Swift
import SwiftUI
|
|
|
|
enum NfcShareAvailability { case available, unavailable, hidden }
|
|
|
|
/// Invitation delivery actions, ported from `TransferShareActions` (iosMain).
|
|
/// Platform implementations perform export, native share, and NFC write.
|
|
@MainActor
|
|
protocol TransferShareActions: AnyObject {
|
|
var canUseNativeShare: Bool { get }
|
|
var nfcAvailability: NfcShareAvailability { get }
|
|
|
|
func exportInvitation(ticket: String, transferName: String, onResult: @escaping (Result<Void, Error>) -> Void)
|
|
func shareInvitation(ticket: String, transferName: String, onResult: @escaping (Result<Void, Error>) -> Void)
|
|
func writeInvitationToNfc(ticket: String, onResult: @escaping (Result<Void, Error>) -> Void)
|
|
func cancelNfcWrite()
|
|
}
|
|
|
|
/// The QR + delivery buttons for a transfer's share panel, ported from the button
|
|
/// stack in `TransferSharePanel` (`TransferDetails.kt`).
|
|
struct ShareActionsView: View {
|
|
@Environment(\.vniColors) private var colors
|
|
@ObservedObject var model: SendModel
|
|
let transfer: Transfer
|
|
let ticket: String
|
|
|
|
@State private var actions: TransferShareActions = makePlatformShareActions()
|
|
@State private var writingNfc = false
|
|
|
|
var body: some View {
|
|
VStack(spacing: 12) {
|
|
if actions.nfcAvailability != .hidden {
|
|
SecondaryButton(
|
|
title: writingNfc ? String(localized: L10n.Transfer.nfcWaiting) : String(localized: L10n.Button.writeNfc),
|
|
action: {
|
|
writingNfc = true
|
|
actions.writeInvitationToNfc(ticket: ticket) { result in
|
|
writingNfc = false
|
|
model.onInvitationResult(.nfc, result)
|
|
}
|
|
},
|
|
enabled: actions.nfcAvailability == .available && !writingNfc
|
|
)
|
|
if actions.nfcAvailability == .unavailable {
|
|
Text(String(localized: L10n.Transfer.nfcUnavailable))
|
|
.font(VniType.bodySmall).foregroundStyle(colors.foregroundLighter)
|
|
}
|
|
}
|
|
SecondaryButton(title: String(localized: L10n.Button.downloadInvitation), action: {
|
|
actions.exportInvitation(ticket: ticket, transferName: transfer.transferName ?? "") {
|
|
model.onInvitationResult(.export, $0)
|
|
}
|
|
})
|
|
PrimaryButton(title: String(localized: L10n.Button.nativeShare), action: {
|
|
actions.shareInvitation(ticket: ticket, transferName: transfer.transferName ?? "") {
|
|
model.onInvitationResult(.share, $0)
|
|
}
|
|
}, enabled: actions.canUseNativeShare)
|
|
}
|
|
.onDisappear { actions.cancelNfcWrite() }
|
|
}
|
|
}
|