Repository navigation
fix(shell): restore the native iOS glass host with Telegram's tint - #278
TiaraBasori wants to merge 2 commits into
Conversation
iOS showed no liquid glass because the native surface had been retired for a Flutter BackdropFilter bar, and before that its tint was derived from the bar's own surface colour: in the light palette navBar equals the background white, so any alpha either composites to nothing or, pushed high enough to see, becomes a fill that hides the material's refraction — the exact 'still no glass' report. The tint now follows Telegram iOS (GlassBackgroundComponent): plain white at 0.10 in light and 0.025 in dark, strictly a whisper so the material stays visible. The capsule's edge, which Telegram derives by clamping backdrop luminance through a private UIKit class, is drawn instead by the same Flutter hairline contour and shadow the Flutter glass bar uses, so no private API or swizzle ships. The surface host is the reviewed public-API NativeGlassSurface (UIGlassEffect on iOS 26+, UIBlurEffect before), with the documented no-op fixed: a tint change installs a fresh effect because UIGlassEffect resolves its tint when the material is built. Geometry, tabs, pill, and gestures stay app-owned in Flutter, so the compact phone bar and the tablet sidebar column share one layout in either host; the restored native geometry suite pins the split column, home-indicator containment, RTL, and the host-mirror rect.
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
Automated PR reviewHead: Review unavailable: Free OpenRouter review unavailable (HTTP 429); no paid fallback and no merge. Remaining gates
No PR code runs with the model key or write token. Free-only routing; provider/rate-limit failures never authorize a merge. Existing review findings must be resolved, not hidden by a new recommendation. |
The pressed-tab mask, ripple, and the selection pill were 9px rounded rectangles inside a stadium capsule — two different shapes at the same place, visibly mismatched at both ends. The 9px radius came from iebb#193, where a stadium indicator clipped the label row's lower corners; the glass row has been icon-only since iebb#261, so nothing clips anymore. The row sits a 5px inset inside the capsule's stadium, so a stadium of the row's own height has its end arcs on the same centres as the capsule's — the shapes are concentric and their edges parallel everywhere. The icon block clears the arc even in the narrowest tablet slot (365px squared against the 31px arc disc). The coverage test now measures containment through the clamped RRect (the real stadium geometry) with the bar's real fixed row height, and the capsule probes pick the outermost stadium now that slot ripples share the pill radius.
iebb
left a comment
There was a problem hiding this comment.
Reviewed exact head cfed7d630e4a0952fbabba8f51d5da98e8b69588. Changes requested before publication.
Please do not treat this PR as a substitute for the owner's separately requested historical native-glass revert. That separate work is not validation of this unchanged PR.
The recorded Quality and Apple checks both stop at formatting test/glass_bottom_bar_geometry_test.dart, before build/test execution. Fix formatting and obtain fresh actual execution results. Two [P2] runtime-behavior gaps also remain: lib/app/main_tab_view.dart:2497–2504 selects the native glass host without the explicit high-contrast opaque fallback used in lib/app/liquid_glass_bottom_bar.dart:127–134; lib/app/native_glass_surface.dart:51–58 derives dark appearance from background, not the independently configurable navigation-bar token. Preserve high-contrast behavior and navigation-token ownership, and add differing-background/nav-token and high-contrast regressions.
Real UIKit backdrop, tint and corner behavior needs native evidence; mocked platform-view captures cannot prove it. No claim is made that this PR was tested by the maintainer's separate revert/compatibility work, or that a new runtime failure was reproduced here.
No approval is granted. Current-base merged-result Quality is not yet fresh in the reviewed evidence; before publication require fresh ordinary PR Quality on this exact head merged with live master, applicable platform checks, resolved findings and genuine exact-head owner approval. No incoming PR code was executed for this review.
|
Closed as superseded by the owner's own native-glass restoration that landed on master ( This PR's two remaining review findings are both covered there with a different mechanism: master's No further work is planned on this branch. Thank you for the review — the tick-tock between the two implementations is exactly why the owner-side revert was the right call. |
Change
Enabling the liquid-glass bottom bar on iOS still showed no glass. The root cause had two layers:
UIGlassEffectwith the bar's own surface colour (navBar). In the light palettenavBar == background == 0xFFFFFF, so that tint is white over white — any low alpha composites to no pixel, and pushing the alpha high enough to see (0.56/0.72, tried in fix(shell): make the iOS glass bottom bar visibly glass #253) turns the tint into a fill that hides the material's refraction. The bar reads as a flat translucent slab either way: "完全没有液态玻璃效果".BackdropFilterbar on iOS too. That bar is a credible frosted capsule, but it is not the system Liquid Glass material — no refraction, no specular response, and its tint problem is the same white-on-white one.What Telegram iOS actually does (read from
GlassBackgroundComponentin TelegramMessenger/Telegram-iOS, first-party code): its glass surfaces tintUIGlassEffectwith plain white at 0.10 in light and 0.025 in dark — never the panel's surface colour. The visible edge of iOS 26 glass comes from clamping the backdrop's sampled luminance into a narrow band (lumaMin/lumaMax = 0.8/0.801light,0/0.15dark), which Telegram implements by swizzling the private_UISDFBackdropViewclass (backdropLayer:didChangeLuma:) behind obfuscated class-name strings. That path is not shippable here (App Store Guideline 2.5.1 binary scans; the class name embeds a UIKit build hash that breaks silently on OS updates). The public-API alternative this PR uses: keep the tint a whisper, and draw the edge — the same Flutter hairline contour + drop shadow #259 added, now wrapping the native surface.This PR restores the reviewed public-API host (#216 architecture) with Telegram's tint:
NativeGlassSurfacereturns (Swift + Dart wrapper):UIGlassEffect(style: .regular)in a non-interactiveUIVisualEffectViewon iOS 26+,UIBlurEffect(systemMaterial)before,overrideUserInterfaceStylefrom the effective app palette, re-registered inAppDelegateand the fourproject.pbxprojentries.nativeGlassTint(): white ARGB0x1AFFFFFFlight /0x06FFFFFFdark, with a source-pinned policy test (red-verified against the old surface-colour tint).UIGlassEffect(mutating the installed effect is a no-op assignment — the effect resolves its tint when the material is built)._GlassCapsuleFramedraws the capsule's silhouette (0.6pt contour at 5.5%/34% black + the shared drop shadow) around the native surface, so the bar keeps a visible edge on white without any private UIKit.UITabBaraway is untouched: nothing system-drawn positions against tab slots).glass_bottom_bar_geometry_test.dartis now the non-iOS host suite (onAndroid); the restorednative_glass_bar_geometry_test.dartpins the iOS native host: split column, home-indicator containment, narrow phone, RTL channel flag, and the host-mirror rect (native surface == Flutter capsule).Affected platform: iOS with the liquid-glass setting on. Every other target is byte-identical (same Flutter bar, same code path).
Telegram API Terms classification
allowTelegramTosViolations(I_DONT_FUCKING_CARE_ABOUT_TOS), disabled in official builds, and available only in an explicitly enabled self-build.Reason and affected Telegram behavior:
Presentation only. No message data is read, no request changes, no status Telegram shows is altered. The change swaps how the already-existing opt-in bottom bar renders its background on iOS; with the setting off the classic bar is unchanged.
Basic checks (every PR)
dart format --output=none --set-exit-if-changed lib test integration_test test_driver— the touched Dart files report 0 changed after formatting.flutter analyze— only the pre-existingconfig/secrets.dartenv-file errors remain (uncommitted env file, copied fromsecrets_example.dartlocally); zero issues in the touched files.flutter test --concurrency=4.Commands, results, platform/build/UI evidence, and reasons for inapplicable checks:
Flutter 3.44.2 (
/tmp/flutter-3.44.2), serial (--no-pub -j 1):test/native_glass_surface_test.dart→ 2/2 (channel contract + tint policy; red-verified: injecting the old surface-colour tint fails both tests exactly).test/native_glass_bar_geometry_test.dart→ 7/7 (native host mount, home-indicator containment, split column, narrow phone, RTL, host-mirror rect; red-verified: disabling the iOS native branch fails 3+ tests).test/glass_bottom_bar_geometry_test.dart+test/liquid_glass_bottom_bar_test.dart→ 16 pass, 2 conditional skips (visual captures,captureGlassReviewnot set).test/main_tab_motion_test.dart+test/bottom_bar_layout_test.dart+test/bottom_bar_tap_target_test.dart→ 30/30.test/topic_split_navigation_test.dart+test/appearance_theming_test.dart+test/music_mini_player_tablet_test.dart→ 42/42 (neighbouring split-shell surfaces).Expected: <452984831>); host-branch kill → native suite fails ("exactly one matching candidate"); restored → green.Not verifiable on this machine: no Xcode/macOS host here, so the Swift file is compile-checked by inspection and source-pinned tests only. The construct set is unchanged from #216 (which compiled on a hosted
macos-26/Xcode 26.6 runner in fork run 39688921371); the only Swift-side deltas are the fresh-effect-instead-of-mutate branch and no new API. No localization or generated file is touched (python3 translations/tools/check.pynot re-run: no string or asset changes).Line counts (
git show --numstat HEAD):118 0 ios/Runner/NativeGlassSurface.swift(new),106 0 lib/app/native_glass_surface.dart(new),92 5 lib/app/main_tab_view.dart,69 58 test/glass_bottom_bar_geometry_test.dart(host split),427 0 test/native_glass_bar_geometry_test.dart(restored),188 0 test/native_glass_surface_test.dart(restored + policy),3 0 ios/Runner/AppDelegate.swift,4 0 ios/Runner.xcodeproj/project.pbxproj.Device check for this change (glass on, iOS 26): the capsule under the tab row reads as system Liquid Glass — content scrolling behind it refracts/bends at the capsule edges, with a faint white brightening and the drawn hairline edge; in dark mode the material is near-clear with the heavier contour. On iOS 25 the capsule is a system material blur with the same tint and edge. Flipping the app appearance repaints through the same surface (no re-create). Tabs, badges, and long-press clear-unread stay tappable in both the compact bar and the tablet sidebar column.
Section 1.4 exception checks
Complete every item for an exception. For a compliant/unchanged PR, write
Not applicablehere.Not applicable.
--dart-define=I_DONT_FUCKING_CARE_ABOUT_TOS=false, the feature is absent and ordinary Telegram behavior remains intact.--dart-define=I_DONT_FUCKING_CARE_ABOUT_TOS=true, the feature works through the guarded entry points in a self-build; I included relevant test and build/UI evidence.falseand have no option that enables it. All store versions remain compliant with applicable Telegram API Terms.Guard locations and evidence for each flag variant:
Not applicable.
Agentic reviewer confirmation
Agentic code reviewer only: record this confirmation in the PR review or check these boxes before approval.
Follow-up (cfed7d6)
The pressed-tab mask, ripple, and selection pill were 9px rounded rectangles inside the stadium capsule — a visible shape mismatch at both ends. #193 chose 9px to keep a stadium indicator from clipping the label row's corners; the glass row has been icon-only since #261, so the constraint is gone and the shapes are now concentric stadiums (row inset 5px, arcs on the same centres; icon block clears the arc in the narrowest tablet slot). Coverage/geometry tests updated accordingly (containment measured through the clamped RRect at the bar's real fixed row height; capsule probes pick the outermost stadium now that slot ripples share the pill radius). Red-verified: reverting the indicator to 9px fails the stadium assertion (Expected 999.0, Actual 9.0).
Re-run at this head: liquid_glass + glass geometry + native suites + motion + tap-target = 52 passed, 2 conditional skips; flutter analyze clean; dart format 0 changed.