Skip to content

Commit 14aa35d

Browse files
committed
fix: stop composer blur bleeding over messages on iOS 26
UIVisualEffectView's gaussian blur spreads ~one blur radius beyond its bounds. After 6423056 removed the outer clip (required to fix the iOS 26 first-mount blur failure), that bleed escapes above the composer's top edge and frosts the last line of the agent reply — RN-level clipping cannot contain it since clipping the effect view's host is documented undefined behavior. Switch Glass to expo-glass-effect's GlassView (system UIGlassEffect) on iOS 26+, which renders strictly within its corner-configured shape, and keep the BlurView path as fallback for older iOS / non-liquid-glass builds. The module is lazy-required with a try/catch so OTA bundles running on binaries without the native module fall back instead of crashing. colorScheme follows the in-app theme toggle rather than the system appearance.
1 parent 2edbae9 commit 14aa35d

3 files changed

Lines changed: 35 additions & 43 deletions

File tree

mobile/package-lock.json

Lines changed: 1 addition & 42 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mobile/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"expo-document-picker": "~55.0.14",
2727
"expo-file-system": "~55.0.23",
2828
"expo-font": "~55.0.8",
29+
"expo-glass-effect": "~55.0.11",
2930
"expo-image-manipulator": "~55.0.18",
3031
"expo-image-picker": "~55.0.21",
3132
"expo-linking": "~55.0.16",

mobile/src/components/glass.tsx

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,30 @@
11
/**
22
* 液态玻璃容器。
3-
* 用 expo-blur 实现真实毛玻璃(模糊层 + 薄边 + 顶部高光)。
3+
* iOS 26+ 用 expo-glass-effect(系统 UIGlassEffect);旧 iOS 回退 expo-blur 毛玻璃。
4+
* 换掉 UIVisualEffectView 方案的原因:它的高斯模糊会越过 bounds 向外渗出约一个
5+
* blur radius,iOS 26 上 RN 层的裁剪约束不住(Apple 标注裁剪其宿主为未定义行为),
6+
* composer 顶边上方会浮出一条把消息糊住的毛玻璃光晕。UIGlassEffect 严格按 bounds 渲染。
47
*/
58
import { BlurView } from 'expo-blur';
69
import React from 'react';
710
import { Platform, StyleSheet, View, type StyleProp, type ViewStyle } from 'react-native';
811
import { useTheme } from '@/theme';
912

13+
// 懒加载 + 容错:OTA 包可能跑在还没编入 ExpoGlassEffect 原生模块的旧安装包上,
14+
// 顶层 import 触发 requireNativeModule 抛错会直接崩 App;失败则永远走 BlurView 回退。
15+
let glassEffectMod: typeof import('expo-glass-effect') | null | undefined;
16+
function liquidGlassModule(): typeof import('expo-glass-effect') | null {
17+
if (glassEffectMod === undefined) {
18+
try {
19+
const mod = require('expo-glass-effect') as typeof import('expo-glass-effect');
20+
glassEffectMod = mod.isLiquidGlassAvailable() ? mod : null;
21+
} catch {
22+
glassEffectMod = null;
23+
}
24+
}
25+
return glassEffectMod;
26+
}
27+
1028
interface GlassProps {
1129
children?: React.ReactNode;
1230
style?: StyleProp<ViewStyle>;
@@ -42,6 +60,20 @@ export function Glass({ children, style, radius = 0, intensity = 36, border = tr
4260
);
4361
}
4462

63+
// iOS 26+:系统液态玻璃。intensity 在此路径无效(材质强度由系统定),观感靠 veil 统一;
64+
// colorScheme 跟随 App 内主题开关而非系统外观,避免强制深/浅色时玻璃底色错位。
65+
const glassEffect = liquidGlassModule();
66+
if (glassEffect) {
67+
const { GlassView } = glassEffect;
68+
return (
69+
<View style={[radiusStyle, shadow && t.shLift, style]}>
70+
<GlassView glassEffectStyle="regular" colorScheme={t.glassTint} style={[StyleSheet.absoluteFill, radiusStyle]} />
71+
<View style={[StyleSheet.absoluteFill, radiusStyle, { backgroundColor: t.glassVeil }, borderStyle]} />
72+
{children}
73+
</View>
74+
);
75+
}
76+
4577
return (
4678
<View style={[radiusStyle, shadow && t.shLift, style]}>
4779
<BlurView

0 commit comments

Comments
 (0)