mirror of
https://github.com/sudosylabs/vnidrop.git
synced 2026-08-05 10:29:58 +02:00
refactor(apple): type the merged relay/network resources
Convert master's raw-string localization keys and SF Symbols in the new relay/network code to typed accessors, matching this branch's typed-resources convention: relay mode labels/descriptions, NetworkSettings strings, the endpoint id and relay-validation messages (now typed L10n functions), and SF Symbols via SFSafeSymbols. Retype the model's relayApplyErrorKey from a raw String key to String.LocalizationValue so no loose key literals remain in the settings layer.
This commit is contained in:
@@ -303,9 +303,9 @@ struct TransferSharePanel: View {
|
|||||||
image.interpolation(.none).resizable().scaledToFit().padding(14)
|
image.interpolation(.none).resizable().scaledToFit().padding(14)
|
||||||
} else {
|
} else {
|
||||||
VStack(spacing: 10) {
|
VStack(spacing: 10) {
|
||||||
Image(systemName: "qrcode")
|
Image(systemSymbol: .qrcode)
|
||||||
.font(.system(size: 36, weight: .medium))
|
.font(.system(size: 36, weight: .medium))
|
||||||
Text(LocalizedStringKey("transfer_qr_unavailable"))
|
Text(String(localized: L10n.Transfer.qrUnavailable))
|
||||||
.font(VniType.bodySmall)
|
.font(VniType.bodySmall)
|
||||||
.multilineTextAlignment(.center)
|
.multilineTextAlignment(.center)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ struct SettingsState: Equatable {
|
|||||||
var isApplyingRelayConfiguration = false
|
var isApplyingRelayConfiguration = false
|
||||||
var hasActiveNetworkWork = false
|
var hasActiveNetworkWork = false
|
||||||
var endpointId: String?
|
var endpointId: String?
|
||||||
var relayApplyErrorKey: String?
|
var relayApplyErrorKey: String.LocalizationValue?
|
||||||
var deviceInfo: DeviceInfo?
|
var deviceInfo: DeviceInfo?
|
||||||
var appVersion = ""
|
var appVersion = ""
|
||||||
var isLoadingDeviceInfo = false
|
var isLoadingDeviceInfo = false
|
||||||
@@ -169,7 +169,7 @@ final class SettingsModel: ObservableObject {
|
|||||||
|| coreState.transfers.contains(where: { $0.status.isActiveTransfer })
|
|| coreState.transfers.contains(where: { $0.status.isActiveTransfer })
|
||||||
self.state.hasActiveNetworkWork = hasActiveWork
|
self.state.hasActiveNetworkWork = hasActiveWork
|
||||||
self.state.endpointId = coreState.status?.endpointId
|
self.state.endpointId = coreState.status?.endpointId
|
||||||
if !hasActiveWork && self.state.relayApplyErrorKey == "relay_apply_active_transfers" {
|
if !hasActiveWork && self.state.relayApplyErrorKey == L10n.Relay.applyActiveTransfers {
|
||||||
self.state.relayApplyErrorKey = nil
|
self.state.relayApplyErrorKey = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -296,8 +296,8 @@ final class SettingsModel: ObservableObject {
|
|||||||
|| coreState.transfers.contains(where: { $0.status.isActiveTransfer })
|
|| coreState.transfers.contains(where: { $0.status.isActiveTransfer })
|
||||||
guard !hasActiveWork else {
|
guard !hasActiveWork else {
|
||||||
state.hasActiveNetworkWork = true
|
state.hasActiveNetworkWork = true
|
||||||
state.relayApplyErrorKey = "relay_apply_active_transfers"
|
state.relayApplyErrorKey = L10n.Relay.applyActiveTransfers
|
||||||
messages.show(UiMessage(text: .resource("relay_apply_active_transfers"), tone: .warning))
|
messages.show(UiMessage(text: .resource(L10n.Relay.applyActiveTransfers), tone: .warning))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -316,16 +316,16 @@ final class SettingsModel: ObservableObject {
|
|||||||
preferences.setRelayConfiguration(configuration)
|
preferences.setRelayConfiguration(configuration)
|
||||||
state.isApplyingRelayConfiguration = false
|
state.isApplyingRelayConfiguration = false
|
||||||
state.relayConfigurationIsDirty = false
|
state.relayConfigurationIsDirty = false
|
||||||
messages.show(UiMessage(text: .resource("relay_settings_applied"), tone: .success))
|
messages.show(UiMessage(text: .resource(L10n.Relay.settingsApplied), tone: .success))
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
if let lifecycleError = error as? CoreNetworkLifecycleError {
|
if let lifecycleError = error as? CoreNetworkLifecycleError {
|
||||||
state.isApplyingRelayConfiguration = false
|
state.isApplyingRelayConfiguration = false
|
||||||
switch lifecycleError {
|
switch lifecycleError {
|
||||||
case .activeNetworkWork:
|
case .activeNetworkWork:
|
||||||
state.hasActiveNetworkWork = true
|
state.hasActiveNetworkWork = true
|
||||||
state.relayApplyErrorKey = "relay_apply_active_transfers"
|
state.relayApplyErrorKey = L10n.Relay.applyActiveTransfers
|
||||||
case .transitionInProgress:
|
case .transitionInProgress:
|
||||||
state.relayApplyErrorKey = "relay_apply_failed"
|
state.relayApplyErrorKey = L10n.Relay.applyFailed
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -335,11 +335,11 @@ final class SettingsModel: ObservableObject {
|
|||||||
)
|
)
|
||||||
state.isApplyingRelayConfiguration = false
|
state.isApplyingRelayConfiguration = false
|
||||||
if case .success = rollbackResult {
|
if case .success = rollbackResult {
|
||||||
state.relayApplyErrorKey = "relay_apply_failed"
|
state.relayApplyErrorKey = L10n.Relay.applyFailed
|
||||||
messages.show(UiMessage(text: .resource("relay_apply_failed"), tone: .error))
|
messages.show(UiMessage(text: .resource(L10n.Relay.applyFailed), tone: .error))
|
||||||
} else {
|
} else {
|
||||||
state.relayApplyErrorKey = "relay_restore_failed"
|
state.relayApplyErrorKey = L10n.Relay.restoreFailed
|
||||||
messages.show(UiMessage(text: .resource("relay_restore_failed"), tone: .error))
|
messages.show(UiMessage(text: .resource(L10n.Relay.restoreFailed), tone: .error))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -125,19 +125,19 @@ private struct SettingsSectionContent: View {
|
|||||||
|
|
||||||
func relayModeLabel(_ mode: RelayPreferenceMode) -> String {
|
func relayModeLabel(_ mode: RelayPreferenceMode) -> String {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .automatic: return String(localized: "relay_mode_automatic")
|
case .automatic: return String(localized: L10n.Relay.modeAutomatic)
|
||||||
case .strictCustom: return String(localized: "relay_mode_custom")
|
case .strictCustom: return String(localized: L10n.Relay.modeCustom)
|
||||||
case .customWithDirectFallback: return String(localized: "relay_mode_custom_direct_fallback")
|
case .customWithDirectFallback: return String(localized: L10n.Relay.modeCustomDirectFallback)
|
||||||
case .localOnly: return String(localized: "relay_mode_local_only")
|
case .localOnly: return String(localized: L10n.Relay.modeLocalOnly)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func relayModeDescriptionKey(_ mode: RelayPreferenceMode) -> String {
|
func relayModeDescription(_ mode: RelayPreferenceMode) -> String.LocalizationValue {
|
||||||
switch mode {
|
switch mode {
|
||||||
case .automatic: return "relay_mode_automatic_description"
|
case .automatic: return L10n.Relay.modeAutomaticDescription
|
||||||
case .strictCustom: return "relay_mode_custom_description"
|
case .strictCustom: return L10n.Relay.modeCustomDescription
|
||||||
case .customWithDirectFallback: return "relay_mode_custom_direct_fallback_description"
|
case .customWithDirectFallback: return L10n.Relay.modeCustomDirectFallbackDescription
|
||||||
case .localOnly: return "relay_mode_local_only_description"
|
case .localOnly: return L10n.Relay.modeLocalOnlyDescription
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -93,22 +93,22 @@ struct NetworkSettings: View {
|
|||||||
} header: {
|
} header: {
|
||||||
Text(String(localized: L10n.Settings.networkTitle))
|
Text(String(localized: L10n.Settings.networkTitle))
|
||||||
} footer: {
|
} footer: {
|
||||||
Text(LocalizedStringKey(relayModeDescriptionKey(model.state.relayMode)))
|
Text(String(localized: relayModeDescription(model.state.relayMode)))
|
||||||
}
|
}
|
||||||
|
|
||||||
Section {
|
Section {
|
||||||
Label {
|
Label {
|
||||||
Text(LocalizedStringKey("relay_privacy_description"))
|
Text(String(localized: L10n.Relay.privacyDescription))
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
} icon: {
|
} icon: {
|
||||||
Image(systemName: "lock.shield")
|
Image(systemSymbol: .lockShield)
|
||||||
}
|
}
|
||||||
.foregroundStyle(.secondary)
|
.foregroundStyle(.secondary)
|
||||||
}
|
}
|
||||||
|
|
||||||
if let endpointId = model.state.endpointId, !endpointId.isEmpty {
|
if let endpointId = model.state.endpointId, !endpointId.isEmpty {
|
||||||
Section {
|
Section {
|
||||||
Text(String(format: String(localized: "approval_endpoint_id"), endpointId))
|
Text(L10n.Approval.endpointId(deviceId: endpointId))
|
||||||
.font(.footnote.monospaced())
|
.font(.footnote.monospaced())
|
||||||
.textSelection(.enabled)
|
.textSelection(.enabled)
|
||||||
}
|
}
|
||||||
@@ -118,10 +118,10 @@ struct NetworkSettings: View {
|
|||||||
Section {
|
Section {
|
||||||
if model.state.relayMode == .strictCustom {
|
if model.state.relayMode == .strictCustom {
|
||||||
Label {
|
Label {
|
||||||
Text(LocalizedStringKey("relay_strict_warning"))
|
Text(String(localized: L10n.Relay.strictWarning))
|
||||||
.fixedSize(horizontal: false, vertical: true)
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
} icon: {
|
} icon: {
|
||||||
Image(systemName: "exclamationmark.shield.fill")
|
Image(systemSymbol: .exclamationmarkShieldFill)
|
||||||
}
|
}
|
||||||
.foregroundStyle(.orange)
|
.foregroundStyle(.orange)
|
||||||
}
|
}
|
||||||
@@ -154,10 +154,10 @@ struct NetworkSettings: View {
|
|||||||
Button(role: .destructive) {
|
Button(role: .destructive) {
|
||||||
model.removeRelayURL(at: index)
|
model.removeRelayURL(at: index)
|
||||||
} label: {
|
} label: {
|
||||||
Image(systemName: "minus.circle.fill")
|
Image(systemSymbol: .minusCircleFill)
|
||||||
}
|
}
|
||||||
.buttonStyle(.borderless)
|
.buttonStyle(.borderless)
|
||||||
.accessibilityLabel(Text(LocalizedStringKey("relay_remove_url")))
|
.accessibilityLabel(Text(String(localized: L10n.Relay.removeUrl)))
|
||||||
.disabled(model.state.isApplyingRelayConfiguration)
|
.disabled(model.state.isApplyingRelayConfiguration)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -170,16 +170,16 @@ struct NetworkSettings: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Button(action: model.addRelayURL) {
|
Button(action: model.addRelayURL) {
|
||||||
Label(String(localized: "relay_add_url"), systemImage: "plus.circle")
|
Label(String(localized: L10n.Relay.addUrl), systemSymbol: .plusCircle)
|
||||||
}
|
}
|
||||||
.disabled(
|
.disabled(
|
||||||
model.state.relayURLs.count >= RelayConfigurationValidator.maximumRelayCount
|
model.state.relayURLs.count >= RelayConfigurationValidator.maximumRelayCount
|
||||||
|| model.state.isApplyingRelayConfiguration
|
|| model.state.isApplyingRelayConfiguration
|
||||||
)
|
)
|
||||||
} header: {
|
} header: {
|
||||||
Text(LocalizedStringKey("relay_custom_urls_label"))
|
Text(String(localized: L10n.Relay.customUrlsLabel))
|
||||||
} footer: {
|
} footer: {
|
||||||
Text(LocalizedStringKey("relay_custom_urls_help"))
|
Text(String(localized: L10n.Relay.customUrlsHelp))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +188,7 @@ struct NetworkSettings: View {
|
|||||||
Label {
|
Label {
|
||||||
Text(relayValidationMessage(error))
|
Text(relayValidationMessage(error))
|
||||||
} icon: {
|
} icon: {
|
||||||
Image(systemName: "exclamationmark.triangle.fill")
|
Image(systemSymbol: .exclamationmarkTriangleFill)
|
||||||
}
|
}
|
||||||
.foregroundStyle(.red)
|
.foregroundStyle(.red)
|
||||||
}
|
}
|
||||||
@@ -197,13 +197,9 @@ struct NetworkSettings: View {
|
|||||||
if model.state.hasActiveNetworkWork || model.state.relayApplyErrorKey != nil {
|
if model.state.hasActiveNetworkWork || model.state.relayApplyErrorKey != nil {
|
||||||
Section {
|
Section {
|
||||||
Label {
|
Label {
|
||||||
Text(LocalizedStringKey(
|
Text(String(localized: model.state.hasActiveNetworkWork ? L10n.Relay.applyActiveTransfers : (model.state.relayApplyErrorKey ?? L10n.Relay.applyFailed)))
|
||||||
model.state.hasActiveNetworkWork
|
|
||||||
? "relay_apply_active_transfers"
|
|
||||||
: model.state.relayApplyErrorKey ?? "relay_apply_failed"
|
|
||||||
))
|
|
||||||
} icon: {
|
} icon: {
|
||||||
Image(systemName: "exclamationmark.triangle.fill")
|
Image(systemSymbol: .exclamationmarkTriangleFill)
|
||||||
}
|
}
|
||||||
.foregroundStyle(.red)
|
.foregroundStyle(.red)
|
||||||
}
|
}
|
||||||
@@ -212,9 +208,7 @@ struct NetworkSettings: View {
|
|||||||
Section {
|
Section {
|
||||||
Button(action: model.applyRelayConfiguration) {
|
Button(action: model.applyRelayConfiguration) {
|
||||||
HStack {
|
HStack {
|
||||||
Text(LocalizedStringKey(
|
Text(String(localized: model.state.isApplyingRelayConfiguration ? L10n.Relay.applying : L10n.Relay.apply))
|
||||||
model.state.isApplyingRelayConfiguration ? "relay_applying" : "relay_apply"
|
|
||||||
))
|
|
||||||
if model.state.isApplyingRelayConfiguration {
|
if model.state.isApplyingRelayConfiguration {
|
||||||
Spacer()
|
Spacer()
|
||||||
ProgressView()
|
ProgressView()
|
||||||
@@ -227,7 +221,7 @@ struct NetworkSettings: View {
|
|||||||
|| model.state.hasActiveNetworkWork
|
|| model.state.hasActiveNetworkWork
|
||||||
)
|
)
|
||||||
} footer: {
|
} footer: {
|
||||||
Text(LocalizedStringKey("relay_apply_restart_description"))
|
Text(String(localized: L10n.Relay.applyRestartDescription))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -235,18 +229,15 @@ struct NetworkSettings: View {
|
|||||||
private func relayValidationMessage(_ error: RelayConfigurationValidationError) -> String {
|
private func relayValidationMessage(_ error: RelayConfigurationValidationError) -> String {
|
||||||
switch error {
|
switch error {
|
||||||
case .missingURL:
|
case .missingURL:
|
||||||
return String(localized: "relay_validation_missing_url")
|
return String(localized: L10n.Relay.validationMissingUrl)
|
||||||
case .tooManyURLs:
|
case .tooManyURLs:
|
||||||
return String(
|
return L10n.Relay.validationTooManyUrls(maximum: RelayConfigurationValidator.maximumRelayCount)
|
||||||
format: String(localized: "relay_validation_too_many_urls"),
|
|
||||||
RelayConfigurationValidator.maximumRelayCount
|
|
||||||
)
|
|
||||||
case .httpsRequired(let index):
|
case .httpsRequired(let index):
|
||||||
return String(format: String(localized: "relay_validation_https_required"), index + 1)
|
return L10n.Relay.validationHttpsRequired(line: index + 1)
|
||||||
case .invalidURL(let index):
|
case .invalidURL(let index):
|
||||||
return String(format: String(localized: "relay_validation_invalid_url"), index + 1)
|
return L10n.Relay.validationInvalidUrl(line: index + 1)
|
||||||
case .duplicateURL(let index):
|
case .duplicateURL(let index):
|
||||||
return String(format: String(localized: "relay_validation_duplicate_url"), index + 1)
|
return L10n.Relay.validationDuplicateUrl(line: index + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user