Header: globe opens channel sheet; deterministic crowding cascade (#1400)

The gateway globe indicator was a plain Image with a tooltip but no tap
handler. Wrap it in a Button that opens the location channels sheet,
where the gateway toggle lives, so tapping it lets people turn the
gateway on or off. Adds an accessibility hint localized into all 29
locales.

When the header got crowded with indicator icons, the bitchat/ logo and
the nickname field both sat at layout priority 0, so compression was
split arbitrarily between them — and the logo, lacking a lineLimit,
wrapped to two lines inside the fixed-height bar. Make the degradation
order explicit: the nickname shrinks first, the logo holds full width
until the name is gone and then truncates on one line, and the icon
cluster (priority 3) never compresses.

Render-verified with an offscreen ImageRenderer harness at 320/375/500pt
with the maximum icon load (globe, courier, envelope, pin, bookmark).

Co-authored-by: jack <jackjackbits@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jack
2026-07-08 08:46:40 +02:00
committed by GitHub
co-authored by jack Claude Fable 5
parent 3f677776bb
commit e642f696cb
2 changed files with 203 additions and 10 deletions
+180
View File
@@ -13457,6 +13457,186 @@
}
}
},
"content.accessibility.gateway_hint" : {
"comment" : "Accessibility hint for the internet gateway indicator explaining a tap opens the channel sheet",
"extractionState" : "manual",
"localizations" : {
"ar" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "يفتح إعدادات القنوات لتشغيل البوابة أو إيقافها"
}
},
"bn" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "গেটওয়ে চালু বা বন্ধ করতে চ্যানেল সেটিংস খোলে"
}
},
"de" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Öffnet die kanaleinstellungen, um das gateway ein- oder auszuschalten"
}
},
"en" : {
"stringUnit" : {
"state" : "translated",
"value" : "Opens channel settings to turn the gateway on or off"
}
},
"es" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Abre los ajustes de canales para activar o desactivar la puerta de enlace"
}
},
"fil" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Binubuksan ang mga setting ng channel para i-on o i-off ang gateway"
}
},
"fr" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Ouvre les réglages des canaux pour activer ou désactiver la passerelle"
}
},
"he" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "פותח את הגדרות הערוצים כדי להפעיל או לכבות את השער"
}
},
"hi" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "गेटवे चालू या बंद करने के लिए चैनल सेटिंग्स खोलता है"
}
},
"id" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Membuka pengaturan kanal untuk menyalakan atau mematikan gateway"
}
},
"it" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Apre le impostazioni dei canali per attivare o disattivare il gateway"
}
},
"ja" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "チャンネル設定を開いてゲートウェイのオン/オフを切り替えます"
}
},
"ko" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "채널 설정을 열어 게이트웨이를 켜거나 끕니다"
}
},
"ms" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Membuka tetapan saluran untuk menghidupkan atau mematikan gateway"
}
},
"ne" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "गेटवे खोल्न वा बन्द गर्न च्यानल सेटिङहरू खोल्छ"
}
},
"nl" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Opent kanaalinstellingen om de gateway aan of uit te zetten"
}
},
"pl" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Otwiera ustawienia kanałów, aby włączyć lub wyłączyć bramę"
}
},
"pt" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Abre as definições de canais para ligar ou desligar o gateway"
}
},
"pt-BR" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Abre as configurações de canais para ligar ou desligar o gateway"
}
},
"ru" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Открывает настройки каналов, чтобы включить или выключить шлюз"
}
},
"sv" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Öppnar kanalinställningar för att slå på eller av gatewayen"
}
},
"ta" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "கேட்வேயை இயக்க அல்லது அணைக்க சேனல் அமைப்புகளைத் திறக்கிறது"
}
},
"th" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "เปิดการตั้งค่าช่องเพื่อเปิดหรือปิดเกตเวย์"
}
},
"tr" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Ağ geçidini açmak veya kapatmak için kanal ayarlarını açar"
}
},
"uk" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Відкриває налаштування каналів, щоб увімкнути або вимкнути шлюз"
}
},
"ur" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "گیٹ وے کو آن یا آف کرنے کے لیے چینل کی ترتیبات کھولتا ہے"
}
},
"vi" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "Mở cài đặt kênh để bật hoặc tắt gateway"
}
},
"zh-Hans" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "打开频道设置以开启或关闭网关"
}
},
"zh-Hant" : {
"stringUnit" : {
"state" : "needs_review",
"value" : "開啟頻道設定以開啟或關閉閘道"
}
}
}
},
"content.accessibility.group_chat" : {
"extractionState" : "manual",
"localizations" : {
+13
View File
@@ -33,7 +33,12 @@ struct ContentHeaderView: View {
HStack(spacing: 0) {
Text(verbatim: "bitchat/")
.bitchatFont(size: 18, weight: .medium)
.lineLimit(1)
.foregroundColor(palette.primary)
// When icons crowd the header, squeeze the nickname first
// (priority 0) and the logo only as a last resort; the icon
// cluster at priority 3 never gives up width.
.layoutPriority(2)
.onTapGesture(count: 3) {
appChromeModel.panicClearAllData()
}
@@ -55,6 +60,8 @@ struct ContentHeaderView: View {
Text(verbatim: "@")
.bitchatFont(size: 14)
.foregroundColor(palette.secondary)
// Keep the sigil whole while the field beside it shrinks.
.fixedSize()
TextField(
"content.input.nickname_placeholder",
@@ -96,13 +103,19 @@ struct ContentHeaderView: View {
HStack(spacing: 2) {
if locationChannelsModel.gatewayEnabled {
Button(action: { appChromeModel.isLocationChannelsSheetPresented = true }) {
Image(systemName: "globe")
.font(.bitchatSystem(size: 12))
.foregroundColor(palette.secondary.opacity(0.8))
.headerTapTarget()
}
.buttonStyle(.plain)
.accessibilityLabel(
String(localized: "content.accessibility.gateway_active", defaultValue: "Internet gateway active, sharing your connection with the mesh", comment: "Accessibility label for the internet gateway indicator")
)
.accessibilityHint(
String(localized: "content.accessibility.gateway_hint", defaultValue: "Opens channel settings to turn the gateway on or off", comment: "Accessibility hint for the internet gateway indicator explaining a tap opens the channel sheet")
)
.help(
String(localized: "content.header.gateway_active", defaultValue: "Sharing your internet connection with nearby mesh peers", comment: "Tooltip for the internet gateway indicator")
)