diff --git a/bitchat/Localizable.xcstrings b/bitchat/Localizable.xcstrings index ae8335a5..739c9d8e 100644 --- a/bitchat/Localizable.xcstrings +++ b/bitchat/Localizable.xcstrings @@ -32410,7 +32410,7 @@ "fil" : { "stringUnit" : { "state" : "translated", - "value" : "settings" + "value" : "mga setting" } }, "fr" : { @@ -56149,7 +56149,7 @@ "en" : { "stringUnit" : { "state" : "translated", "value" : "settings" } }, "es" : { "stringUnit" : { "state" : "translated", "value" : "ajustes" } }, "fa" : { "stringUnit" : { "state" : "translated", "value" : "تنظیمات" } }, - "fil" : { "stringUnit" : { "state" : "translated", "value" : "settings" } }, + "fil" : { "stringUnit" : { "state" : "translated", "value" : "mga setting" } }, "fr" : { "stringUnit" : { "state" : "translated", "value" : "réglages" } }, "he" : { "stringUnit" : { "state" : "translated", "value" : "הגדרות" } }, "hi" : { "stringUnit" : { "state" : "translated", "value" : "सेटिंग्स" } }, diff --git a/bitchat/Views/ContentHeaderView.swift b/bitchat/Views/ContentHeaderView.swift index 1e465be7..6988c9b3 100644 --- a/bitchat/Views/ContentHeaderView.swift +++ b/bitchat/Views/ContentHeaderView.swift @@ -129,7 +129,7 @@ struct ContentHeaderView: View { if locationChannelsModel.gatewayEnabled { // The gateway toggle lives in the App Info settings pane // now, so the indicator deep-links there. - Button(action: { appChromeModel.presentAppInfo() }) { + Button(action: { appChromeModel.presentAppInfo(pane: .settings) }) { Image(systemName: "globe") .font(.bitchatSystem(size: 12)) .foregroundColor(palette.secondary.opacity(0.8)) diff --git a/bitchatTests/AppArchitectureTests.swift b/bitchatTests/AppArchitectureTests.swift index 747e737b..222794e8 100644 --- a/bitchatTests/AppArchitectureTests.swift +++ b/bitchatTests/AppArchitectureTests.swift @@ -462,6 +462,49 @@ struct AppArchitectureTests { #expect(chromeModel.showingFingerprintFor == nil) } + @Test("App Info pane routing: a promised pane overrides the sticky memory, a plain present never touches it") + @MainActor + func presentAppInfoPaneRouting() { + let viewModel = makeArchitectureViewModel() + let privateInboxModel = PrivateInboxModel(conversations: ConversationStore()) + let chromeModel = AppChromeModel(chatViewModel: viewModel, privateInboxModel: privateInboxModel) + + // The sticky pane lives in standard defaults (@AppStorage's store); + // restore whatever was there so this test can't leak state. + let key = "appInfo.selectedPane" + let defaults = UserDefaults.standard + let original = defaults.string(forKey: key) + defer { + if let original { + defaults.set(original, forKey: key) + } else { + defaults.removeObject(forKey: key) + } + } + + // First-ever open: the logo tap passes no pane, and the absent key is + // what lands new users on the gentler Info default — a plain present + // must not create it. + defaults.removeObject(forKey: key) + chromeModel.presentAppInfo() + #expect(defaults.string(forKey: key) == nil) + #expect(chromeModel.isAppInfoPresented) + + // Later opens: the logo tap keeps whatever pane the sheet was left on. + chromeModel.isAppInfoPresented = false + defaults.set(AppInfoView.Pane.info.rawValue, forKey: key) + chromeModel.presentAppInfo() + #expect(defaults.string(forKey: key) == AppInfoView.Pane.info.rawValue) + #expect(chromeModel.isAppInfoPresented) + + // Controls that promise a pane (the header gear and the gateway globe + // both say "settings") must land there even against sticky memory. + chromeModel.isAppInfoPresented = false + chromeModel.presentAppInfo(pane: .settings) + #expect(defaults.string(forKey: key) == AppInfoView.Pane.settings.rawValue) + #expect(chromeModel.isAppInfoPresented) + } + @Test("Triple-tap panic entry point only raises the confirmation dialog") @MainActor func requestPanicWipeAsksBeforeDestroying() {