Merge 8a2195449af87232d8dcfb42d0a7146b60d5ef4d into 948d6a85b9f254760c475a64f02fe8899e4f3d7f

This commit is contained in:
Rod Bahmanyari 2026-08-01 10:46:08 +02:00 committed by GitHub
commit e809dc0c7e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 229 additions and 6 deletions

View File

@ -71,7 +71,13 @@ final class AppChromeModel: ObservableObject {
showingFingerprintFor = nil
}
func presentAppInfo() {
/// Presents the App Info sheet. Pass a pane when the launching control
/// promises one (the header gear is labeled "settings"); nil keeps the
/// sheet's own sticky last-used pane.
func presentAppInfo(pane: AppInfoView.Pane? = nil) {
if let pane {
AppInfoView.setSelectedPane(pane)
}
isAppInfoPresented = true
}

View File

@ -76527,6 +76527,192 @@
"zh-Hans" : { "stringUnit" : { "state" : "needs_review", "value" : "用于草稿" } },
"zh-Hant" : { "stringUnit" : { "state" : "needs_review", "value" : "用於草稿" } }
}
},
"content.header.settings" : {
"comment" : "Accessibility label and tooltip for the header gear button that opens the settings/app info sheet",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "translated",
"value" : "الإعدادات"
}
},
"bn" : {
"stringUnit" : {
"state" : "translated",
"value" : "সেটিংস"
}
},
"de" : {
"stringUnit" : {
"state" : "translated",
"value" : "einstellungen"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "settings"
}
},
"es" : {
"stringUnit" : {
"state" : "translated",
"value" : "ajustes"
}
},
"fa" : {
"stringUnit" : {
"state" : "translated",
"value" : "تنظیمات"
}
},
"fil" : {
"stringUnit" : {
"state" : "translated",
"value" : "settings"
}
},
"fr" : {
"stringUnit" : {
"state" : "translated",
"value" : "réglages"
}
},
"he" : {
"stringUnit" : {
"state" : "translated",
"value" : "הגדרות"
}
},
"hi" : {
"stringUnit" : {
"state" : "translated",
"value" : "सेटिंग्स"
}
},
"id" : {
"stringUnit" : {
"state" : "translated",
"value" : "pengaturan"
}
},
"it" : {
"stringUnit" : {
"state" : "translated",
"value" : "impostazioni"
}
},
"ja" : {
"stringUnit" : {
"state" : "translated",
"value" : "設定"
}
},
"ko" : {
"stringUnit" : {
"state" : "translated",
"value" : "설정"
}
},
"ms" : {
"stringUnit" : {
"state" : "translated",
"value" : "tetapan"
}
},
"ne" : {
"stringUnit" : {
"state" : "translated",
"value" : "सेटिङ"
}
},
"nl" : {
"stringUnit" : {
"state" : "translated",
"value" : "instellingen"
}
},
"pl" : {
"stringUnit" : {
"state" : "translated",
"value" : "ustawienia"
}
},
"pt" : {
"stringUnit" : {
"state" : "translated",
"value" : "definições"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "translated",
"value" : "ajustes"
}
},
"ru" : {
"stringUnit" : {
"state" : "translated",
"value" : "настройки"
}
},
"sv" : {
"stringUnit" : {
"state" : "translated",
"value" : "inställningar"
}
},
"ta" : {
"stringUnit" : {
"state" : "translated",
"value" : "அமைப்புகள்"
}
},
"th" : {
"stringUnit" : {
"state" : "translated",
"value" : "ตั้งค่า"
}
},
"tr" : {
"stringUnit" : {
"state" : "translated",
"value" : "ayarlar"
}
},
"uk" : {
"stringUnit" : {
"state" : "translated",
"value" : "налаштування"
}
},
"ur" : {
"stringUnit" : {
"state" : "translated",
"value" : "سیٹنگز"
}
},
"vi" : {
"stringUnit" : {
"state" : "translated",
"value" : "cài đặt"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "translated",
"value" : "设置"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "translated",
"value" : "設定"
}
}
}
}
},
"version" : "1.1"

View File

@ -28,18 +28,28 @@ struct AppInfoView: View {
@ObservedObject private var locationManager = LocationChannelManager.shared
/// Sticky across opens: first-ever open lands on Info (the gentler
/// introduction), and afterwards the sheet reopens wherever it was left.
@AppStorage("appInfo.selectedPane") private var selectedPane: Pane = .info
@AppStorage(AppInfoView.selectedPaneStorageKey) private var selectedPane: Pane = .info
@State private var showPanicConfirmation = false
@AppStorage(AppLanguageSettings.overrideKey) private var languageOverride = ""
/// The override changed this session; localization resolves at process
/// start, so surface the restart hint.
@State private var showLanguageRestartNote = false
private enum Pane: String {
enum Pane: String {
case settings
case info
}
private static let selectedPaneStorageKey = "appInfo.selectedPane"
/// Overwrites the remembered pane so the next presentation opens there.
/// `selectedPane` is sticky by design; a caller whose control names a
/// specific pane (the header gear says "settings") uses this so the
/// sheet doesn't land first-time users on the Info default instead.
static func setSelectedPane(_ pane: Pane) {
UserDefaults.standard.set(pane.rawValue, forKey: selectedPaneStorageKey)
}
private var selectedTheme: AppTheme {
AppTheme(rawValue: appThemeRawValue) ?? .matrix
}

View File

@ -52,9 +52,10 @@ struct ContentHeaderView: View {
.onTapGesture(count: 1) {
appChromeModel.presentAppInfo()
}
// This is the only entry point to App Info, but it reads as
// static text; surface the tap. (The triple-tap panic wipe
// stays undiscoverable on purpose it's destructive.)
// The gear in the icon cluster is the discoverable entry
// point to App Info; the logo tap stays as a shortcut but
// reads as static text, so surface it. (The triple-tap panic
// wipe stays undiscoverable on purpose it's destructive.)
.accessibilityAddTraits(.isButton)
.accessibilityHint(
String(localized: "content.accessibility.app_info_hint", comment: "Accessibility hint on the bitchat/ logo explaining a tap opens app info")
@ -286,6 +287,26 @@ struct ContentHeaderView: View {
? String(localized: "content.accessibility.peers_connected", comment: "Accessibility value when peers are reachable")
: String(localized: "content.accessibility.peers_none", comment: "Accessibility value when no peers are reachable"))
)
// Settings entry point new users can actually find; the
// logo tap remains as a shortcut for those who know it.
// Opens on the settings pane explicitly: the sheet's pane
// memory defaults to info, and a button labeled "settings"
// must not land there.
Button(action: { appChromeModel.presentAppInfo(pane: .settings) }) {
Image(systemName: "gearshape")
.font(.bitchatSystem(size: 12))
.foregroundColor(palette.secondary.opacity(0.9))
.headerTapTarget()
}
.buttonStyle(.plain)
.padding(.leading, 4)
.accessibilityLabel(
String(localized: "content.header.settings", defaultValue: "settings", comment: "Accessibility label and tooltip for the header gear button that opens the settings/app info sheet")
)
.help(
String(localized: "content.header.settings", defaultValue: "settings", comment: "Accessibility label and tooltip for the header gear button that opens the settings/app info sheet")
)
}
.layoutPriority(3)
.sheet(isPresented: $showVerifySheet) {