fix(mobile): pin CJK fonts so iOS WKWebView doesn't render ? boxes#92
Merged
Conversation
3345e5c to
2c9df9f
Compare
2c9df9f to
ad82de1
Compare
iOS 26 WebKit regresses `-apple-system` / `system-ui`: the composite font reports full Unicode coverage but doesn't actually render CJK glyphs, AND WebKit refuses to fall through to later families in the font-family list. Stacks that start with `-apple-system, ..., "PingFang SC", ...` show every CJK character as a missing-glyph box even though PingFang SC is present and works when referenced directly. Verified via tmp-font-probe.html on iPhone 17 Pro / iOS 26.3 simulator: - `-apple-system` alone → ? boxes - `system-ui` alone → ? boxes - `"PingFang SC"` direct → renders fine - `document.fonts.check` reports all CJK families OK Workaround: - Put PingFang SC FIRST in --font-sans / --font-mono (CSS vars in style.css) so per-glyph fallback finds it before WebKit short-circuits on the broken -apple-system entry. - Drop -apple-system / BlinkMacSystemFont from the stack — too risky given the iOS 26 bug; Helvetica Neue is iOS's normal Latin fallback. - Inline the same stack in index.capacitor.html so WKWebView's parse-time font-selection has the correct chain before style.css loads. - Component-level styles (MobileSetup, MobileSessionList, MobileTerminal, PairingConsume) all reference var(--font-sans|mono) so future components inherit the fix automatically.
ad82de1 to
e066ddf
Compare
attson
added a commit
that referenced
this pull request
Jun 2, 2026
Follow-up to #92. Three leftover [?] boxes on iOS 26 MobileSetup: 1. Language <select> showed "跟随系统" as four boxes. The control inherited --font-mono which had ui-monospace first — same iOS 26 short-circuit bug as -apple-system. 2. The "⚠" warning icon in the insecure-mode hint rendered as a box because no font in our stack covers U+26A0 in text presentation, and we never explicitly requested emoji presentation. 3. Same ⚠ in InsecureBanner header. Changes: - Reorder --font-mono to put PingFang SC first (mirrors --font-sans). - Add --font-mono-strict for ASCII-only URL/token inputs that want a real monospace look. - MobileSetup: <input> on mono-strict, <select> on sans. - Add "Apple Color Emoji" to --font-sans + index.capacitor.html. - Append U+FE0F (variation selector-16) to the two ⚠ icons so iOS picks the emoji glyph rather than missing text-style.
attson
added a commit
that referenced
this pull request
Jun 2, 2026
Follow-up to #92. Two leftover [?] boxes on iOS 26 MobileSetup: 1. Language <select> showed "跟随系统" as four boxes. The control inherited --font-mono which had ui-monospace first — same iOS 26 short-circuit-on-claim bug as -apple-system. 2. The "⚠" warning icon rendered as a box, in both MobileSetup's warn-hint and InsecureBanner's header. Adding U+FE0F (variation selector-16) to request emoji presentation did not help — iOS 26 simulator's Apple Color Emoji still produced a missing-glyph box. Changes: - Reorder --font-mono to put PingFang SC first (mirrors --font-sans). - Add --font-mono-strict for ASCII-only URL/token inputs that want a real monospace look. - MobileSetup: <input> uses mono-strict, <select> uses sans. - Add "Apple Color Emoji" to --font-sans + index.capacitor.html inline stack — helps in environments where emoji rendering works. - Replace the U+26A0 emoji in MobileSetup's warn-hint and the InsecureBanner head with a lucide-style inline SVG. Removes the font-dependency entirely; icon now renders on any platform.
attson
added a commit
that referenced
this pull request
Jun 2, 2026
Follow-up to #92. Two leftover [?] boxes on iOS 26 MobileSetup: 1. Language <select> showed "跟随系统" as four boxes. The control inherited --font-mono which had ui-monospace first — same iOS 26 short-circuit-on-claim bug as -apple-system. 2. The "⚠" warning icon rendered as a box, in both MobileSetup's warn-hint and InsecureBanner's header. Adding U+FE0F (variation selector-16) to request emoji presentation did not help — iOS 26 simulator's Apple Color Emoji still produced a missing-glyph box. Changes: - Reorder --font-mono to put PingFang SC first (mirrors --font-sans). - Add --font-mono-strict for ASCII-only URL/token inputs that want a real monospace look. - MobileSetup: <input> uses mono-strict, <select> uses sans. - Add "Apple Color Emoji" to --font-sans + index.capacitor.html inline stack — helps in environments where emoji rendering works. - Replace the U+26A0 emoji in MobileSetup's warn-hint and the InsecureBanner head with a lucide-style inline SVG. Removes the font-dependency entirely; icon now renders on any platform.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Repro
On iOS 26 Capacitor build (verified iPhone 17 Pro / iOS 26.3 simulator), all Chinese-locale i18n strings render as missing-glyph `[?]` boxes — `mobile.relayDisconnected` = "Relay 已断开" shows as "Relay [?] [?] [?]", same for `mobile.setupSubtitle`, all the insecure-HTTP warning text, etc. English text renders fine.
Root cause
iOS 26 WebKit regression. `-apple-system` (and `system-ui`) declares full Unicode coverage but doesn't actually render CJK glyphs, AND WebKit refuses to fall through to later families in the font-family list. Stacks that start with `-apple-system, ..., "PingFang SC", ...` fail every CJK glyph even with PingFang SC explicitly in the list.
Verified via a font-probe page hitting the live WKWebView:
`document.fonts.check` reports all CJK families as present — so the fonts are installed, WebKit just won't reach them when `-apple-system` sits in front.
Fix
Test plan
Out of scope