diff --git a/Frameworks/Resources/Localizable.xcstrings b/Frameworks/Resources/Localizable.xcstrings index 315c4709..642619f8 100644 --- a/Frameworks/Resources/Localizable.xcstrings +++ b/Frameworks/Resources/Localizable.xcstrings @@ -10387,53 +10387,6 @@ } } }, - "Authentication and host-key approval are used only for this lookup. The host draft is not saved." : { - "extractionState" : "manual", - "localizations" : { - "de" : { - "stringUnit" : { - "state" : "translated", - "value" : "Authentifizierung und Hostschlüsselbestätigung gelten nur für diese Abfrage. Der Hostentwurf wird nicht gespeichert." - } - }, - "en" : { - "stringUnit" : { - "state" : "translated", - "value" : "Authentication and host-key approval are used only for this lookup. The host draft is not saved." - } - }, - "fr" : { - "stringUnit" : { - "state" : "translated", - "value" : "L’authentification et l’approbation de la clé d’hôte ne servent qu’à cette recherche. Le brouillon de l’hôte n’est pas enregistré." - } - }, - "ja" : { - "stringUnit" : { - "state" : "translated", - "value" : "認証とホスト鍵の承認は、この検索にのみ使用されます。ホストの下書きは保存されません。" - } - }, - "ko" : { - "stringUnit" : { - "state" : "translated", - "value" : "인증 및 호스트 키 승인은 이번 조회에만 사용됩니다. 호스트 초안은 저장되지 않습니다." - } - }, - "zh-Hans" : { - "stringUnit" : { - "state" : "translated", - "value" : "身份验证和主机密钥确认仅用于此次查询,不会保存主机草稿。" - } - }, - "zh-Hant" : { - "stringUnit" : { - "state" : "translated", - "value" : "驗證和主機金鑰確認僅用於此次查詢,不會儲存主機草稿。" - } - } - } - }, "Authentication required" : { "extractionState" : "manual", "localizations" : { diff --git a/Frameworks/TermindPresentation/Strings/LocalNetwork.swift b/Frameworks/TermindPresentation/Strings/LocalNetwork.swift index ec5c160a..192d918c 100644 --- a/Frameworks/TermindPresentation/Strings/LocalNetwork.swift +++ b/Frameworks/TermindPresentation/Strings/LocalNetwork.swift @@ -71,8 +71,5 @@ extension AppStrings { public static var selectAdapter: LocalizedStringResource { "Choose the network adapter to wake." } - public static var temporaryAuthentication: LocalizedStringResource { - "Authentication and host-key approval are used only for this lookup. The host draft is not saved." - } } } diff --git a/TFI/Features/HostEditor/MobileHostMACAddressView.swift b/TFI/Features/HostEditor/MobileHostMACAddressView.swift index 3abe5fa4..c5cc26e3 100644 --- a/TFI/Features/HostEditor/MobileHostMACAddressView.swift +++ b/TFI/Features/HostEditor/MobileHostMACAddressView.swift @@ -11,7 +11,6 @@ struct MobileHostMACAddressView: View { var body: some View { NavigationStack { VStack(spacing: 12) { - Text(AppStrings.LocalNetwork.temporaryAuthentication).font(.caption).foregroundStyle(.secondary) if model.isFinished { HostMACAddressCandidatesView(candidates: model.candidates) { select($0.address.rawValue) @@ -39,7 +38,8 @@ struct MobileHostMACAddressView: View { .navigationTitle(AppStrings.LocalNetwork.fetchMAC.swiftUIKey) .toolbar { ToolbarItem(placement: .cancellationAction) { - Button(AppStrings.Common.cancel.swiftUIKey) { dismiss() } + Button(AppStrings.Common.cancel.swiftUIKey, systemImage: "xmark") { dismiss() } + .labelStyle(.iconOnly) } } } diff --git a/TFITests/Screenshots/MobileLocalDiscoveryRenderingTests.swift b/TFITests/Screenshots/MobileLocalDiscoveryRenderingTests.swift index 5082d3c9..ad5ea059 100644 --- a/TFITests/Screenshots/MobileLocalDiscoveryRenderingTests.swift +++ b/TFITests/Screenshots/MobileLocalDiscoveryRenderingTests.swift @@ -109,6 +109,64 @@ struct MobileLocalDiscoveryRenderingTests { print("Local discovery screenshot: \(output.path)") } + @Test(arguments: ["en", "zh-Hans"]) + func macLookupUsesCompactDismissalWithoutDescription(language: String) async throws { + let scene = try #require(UIApplication.shared.connectedScenes.compactMap { $0 as? UIWindowScene }.first) + let previous = scene.keyWindow + let library = HostLibraryModel() + let model = HostMACAddressModel( + host: .init(name: "Example", host: "preview.invalid"), library: library, resolver: PreviewMACResolver()) + let window = UIWindow(windowScene: scene) + window.overrideUserInterfaceStyle = .light + window.rootViewController = UIHostingController( + rootView: MACLookupSheetPreview(model: model, library: library) + .environment(\.locale, Locale(identifier: language))) + window.makeKeyAndVisible() + defer { + model.cancel() + window.isHidden = true + window.rootViewController = nil + previous?.makeKey() + } + for _ in 0..<100 { + if model.authenticationPrompt != nil { break } + try await Task.sleep(for: .milliseconds(20)) + } + try #require(model.authenticationPrompt != nil) + try await Task.sleep(for: .milliseconds(700)) + window.layoutIfNeeded() + let labels = accessibilityLabels(in: window) + let locale = Locale(identifier: language) + let title = AppLocalization.resolve(AppStrings.LocalNetwork.fetchMAC, locale: locale) + let cancel = AppLocalization.resolve(AppStrings.Common.cancel, locale: locale) + #expect(labels.contains { $0.contains(title) }) + #expect(labels.contains { $0.contains(cancel) }) + for description in [ + "Authentication and host-key approval are used only for this lookup. The host draft is not saved.", + "身份验证和主机密钥确认仅用于此次查询,不会保存主机草稿。", + ] { + #expect(!labels.contains { $0.contains(description) }) + } + let data = UIGraphicsImageRenderer(bounds: window.bounds).pngData { _ in + window.drawHierarchy(in: window.bounds, afterScreenUpdates: true) + } + Attachment.record(data, named: "iphone-\(language)-mac-lookup.png") + } + + private struct MACLookupSheetPreview: View { + let model: HostMACAddressModel + let library: HostLibraryModel + @State private var presented = false + + var body: some View { + Color(uiColor: .systemGroupedBackground) + .sheet(isPresented: $presented) { + MobileHostMACAddressView(model: model, library: library, select: { _ in }) + } + .onAppear { presented = true } + } + } + private struct DiscoverySheetPreview: View { let model: LocalDiscoveryModel @State private var presented = false @@ -137,6 +195,14 @@ struct MobileLocalDiscoveryRenderingTests { } } +private struct PreviewMACResolver: HostMACAddressResolving { + func resolve(_ request: SSHConnectionRequest, progress: SSHRouteProgressHandler?) async throws + -> [HostMACAddressCandidate] + { + [] + } +} + @MainActor private final class PreviewDiscovery: LocalHostDiscovering { let connectionProtocol = LocalDiscoveryProtocol.ssh diff --git a/TFM/Features/HostEditor/HostMACAddressView.swift b/TFM/Features/HostEditor/HostMACAddressView.swift index b0f38244..2f1612e6 100644 --- a/TFM/Features/HostEditor/HostMACAddressView.swift +++ b/TFM/Features/HostEditor/HostMACAddressView.swift @@ -14,7 +14,6 @@ struct HostMACAddressView: View { closeLabel: AppStrings.Common.back, closeSymbol: "chevron.backward" ) { VStack(spacing: 12) { - Text(AppStrings.LocalNetwork.temporaryAuthentication).font(.caption).foregroundStyle(.secondary) if model.isFinished { HostMACAddressCandidatesView(candidates: model.candidates) { select($0.address.rawValue)