fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

fix(mobile): replace Callstack glass with Expo glass - #224

Merged
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass
Sep 1, 2026
Merged

fix(mobile): replace Callstack glass with Expo glass#224
rynfar merged 2 commits into
pylonfrom
upstream/2026-08-31-expo-glass

Conversation

@rynfar

@rynfarrynfar commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Second of the mobile batch. Adopted from upstream pingdotgg/t3code#8862 (9b2d04317). Depends on #223, which created floating-working-control.tsx.

What this does

Consolidates onto the glass library the app was already standardised on.
expo-glass-effect was the primary — both GlassSurface and native-glass are
built on it — while @callstack/liquid-glass survived in only two files. This
removes the second library and its native pod.

Upstream's stated reason for the switch: Expo reapplies glass after native layout
and window reattachment, where UIKit can otherwise leave the label visible but
lose the material behind it.

The rest is API renames — effectglassEffectStyle, interactive
isInteractive, and isLiquidGlassSupported → Pylon's existing
NATIVE_LIQUID_GLASS_SUPPORTED.

Port fidelity

The cherry-pick applied with no conflicts, so I checked for silent drops rather
than trusting that. For both changed components, diff(upstreamParent, upstream)
and diff(pylon, HEAD) are line-for-line identical — no Pylon divergence was
present in these files and none was lost.

Two things verified rather than assumed:

  • The support predicate is close but NOT identical, correcting an earlier
    version of this description. @callstack checks @available(iOS 26) AND the
    absence of UIDesignRequiresCompatibility; Expo's isGlassEffectAPIAvailable
    checks @available(iOS 26) AND a runtime UIGlassEffect probe. Neither
    implies the other, and Expo's other export isLiquidGlassAvailable is the
    closer analogue. This is latent rather than active: app.config.ts does not
    set UIDesignRequiresCompatibility, so today the two agree. If it were ever
    set as an iOS 26 escape hatch, headers and tab bars would go legacy while
    these two components kept rendering glass. Timing is genuinely equivalent —
    both are import-time module constants over OS/build-fixed values.
  • The removal is complete. No @callstack/liquid-glass consumers remain
    anywhere in apps/ or packages/.

The docs edit stays Pylon-voiced and only widens the sentence to cover the
working timer and scroll-to-end button.

Verification

@t3tools/mobile typecheck clean, lint clean, 194 mobile thread tests passing.

Because this drops a native dependency and CI does not build iOS on this PR,
I regenerated the native project rather than relying on the JS bundle: expo prebuild --platform ios plus CocoaPods. Confirmed by inspecting the output, not
the exit code — PylonDev.xcworkspace exists, Podfile.lock has zero
liquid-glass references and still carries expo-glass-effect. A full simulator
build against the regenerated project follows.

Worth noting the regenerated workspace is PylonDev.xcworkspace; the checkout
had a stale T3CodeDev.xcworkspace left from before the Pylon rename.

Native build: ** BUILD SUCCEEDED **, zero errors and zero liquid-glass
references anywhere in the build log. Read from the log, not the exit code.

Simulator pass (iOS 26.3)

Adversarial review raised a blocking concern worth recording, because it was
specific and testable: the library being removed ships an explicit UIKit
workaround (contentView.isUserInteractionEnabled = true) for a bug where
UIGlassEffect can leave a glass view's content non-interactive when children
mount after setupView(). Expo's GlassView.swift has no such line, and
isInteractive — which this PR introduces to Pylon for the first time — wraps
the only tappable control inside a glass view. Predicted symptom: a dead
scroll-to-end button.

It does not reproduce. Tested on a fresh native build against real seeded
threads, in both code paths:

  • standalone UniwindGlassView with isInteractive (no work running) — tap
    scrolled the feed to the end and the button correctly disappeared;
  • merged GlassContainer with the working timer — same result.

The likely reason: Expo's GlassView.swift carries 7 layoutSubviews /
didMoveToWindow hooks that re-run setup, whereas GlassContainer.swift has
none. Also verified visually: both pills render with correct rounded-full
geometry, so the unclamped-borderRadius concern does not manifest either.

The working-timer branch needs a live turn, so it was exercised by temporarily
forcing showWorkingControl on and then reverting — no such change is in the
diff, and all six gating conditions are intact on the branch.

Reviewed and integrated with Claude Opus 5 in Claude Code.


View with [code]smithAutofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Adopted from upstream `pingdotgg/t3code#8862` (`9b2d04317`).
Consolidates onto the glass library the app already uses. `expo-glass-effect`
was the primary — `GlassSurface` and `native-glass` were built on it — while
`@callstack/liquid-glass` survived in only two files. Expo reapplies glass after
native layout and window reattachment, where UIKit can otherwise leave the label
visible but lose the material behind it.
The support predicate swaps to Pylon's existing `NATIVE_LIQUID_GLASS_SUPPORTED`,
which is semantically identical: both resolve to "iOS and the native glass API
is available". Remaining changes are API renames (`effect` to `glassEffectStyle`,
`interactive` to `isInteractive`).
Drops the `@callstack/liquid-glass` dependency; no consumers remain.
@github-actionsgithub-actionsBot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:M labels Sep 1, 2026
@github-actions

github-actionsBot commented Sep 1, 2026

Copy link
Copy Markdown

Thread transfer impact

✅ Thread transfer remains within every enforced ceiling.

ProviderMetricMain baselineThis PRImpactPR ceiling
CodexTotal thread wire13.6 KiB13.7 KiB+176 B (+1.3%)15.1 KiB
CodexThread snapshot wire6.9 KiB6.9 KiB+7 B (+0.1%)7.3 KiB
CodexLive turn WebSocket wire6.6 KiB6.8 KiB+169 B (+2.5%)7.8 KiB
CodexLive turn WebSocket decoded57.2 KiB58.7 KiB+1.5 KiB (+2.6%)66.4 KiB
CodexLive turn messages1011+1 (+10.0%)21
ClaudeTotal thread wire13.5 KiB13.5 KiB+2 B (+0.0%)15.1 KiB
ClaudeThread snapshot wire6.9 KiB6.9 KiB+3 B (+0.0%)7.3 KiB
ClaudeLive turn WebSocket wire6.6 KiB6.6 KiB−1 B (−0.0%)7.8 KiB
ClaudeLive turn WebSocket decoded58.0 KiB58.0 KiB0 B (0.0%)66.4 KiB
ClaudeLive turn messages990 (0.0%)21

Baseline: 2d168f2 · PR result: 6950c6c · Source CI: success

Scenario and decoded snapshot size

10 historical turns, 5 command tools per turn, 878.9 KiB retained MCP result per historical turn, and a 1.05 MiB retained result in the measured turn.

  • Codex decoded thread snapshot: 109.5 KiB
  • Claude decoded thread snapshot: 110.2 KiB

Updated in place by a trusted workflow. PR artifacts are strictly validated and never executed.

The comment carried over from upstream described GlassView's window
handling while sitting above the withUniwind call, where it reads as if it
justifies the options object. It does not, and the options object is
load-bearing: uniwind treats any prop ending in "Style" as a style prop, so
auto mode would pass glassEffectStyle={[undefined, "regular"]} into a native
enum and lose the effect. The old `effect` prop did not end in "Style",
which is why auto mode was safe before the rename.
Uses the wording Pylon already records at GlassSurface.tsx, so a future
simplification does not drop the options object and silently lose the glass
style.
@rynfar
rynfar merged commit 9d82e68 into pylonSep 1, 2026
19 checks passed
@rynfar
rynfar deleted the upstream/2026-08-31-expo-glass branch September 1, 2026 05:33
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:Mvouch:trustedPR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@rynfar