Rebrand as TPSchedule and refine clear liquid glass dock

This commit is contained in:
Codex
2026-10-13 22:08:20 +08:00
parent 50fcc70e8e
commit 204e945b2e
45 changed files with 1155 additions and 103 deletions
+43 -11
View File
@@ -8,9 +8,13 @@ class GlassRefraction extends StatefulWidget {
const GlassRefraction({
super.key,
required this.strength,
this.blurSigma = 2,
required this.child,
});
final double strength;
/// Optical softness in logical pixels, independent of display density.
final double blurSigma;
final Widget child;
@override
State<GlassRefraction> createState() => _GlassRefractionState();
@@ -18,6 +22,7 @@ class GlassRefraction extends StatefulWidget {
class _GlassRefractionState extends State<GlassRefraction> {
static Future<ui.FragmentProgram>? _program;
static ui.FragmentProgram? _loadedProgram;
ui.FragmentShader? _shader;
@override
void initState() {
@@ -27,12 +32,12 @@ class _GlassRefractionState extends State<GlassRefraction> {
Future<void> _load() async {
try {
final program = await (_program ??= ui.FragmentProgram.fromAsset(
'shaders/liquid_glass.frag',
));
final program = _loadedProgram ??= await (_program ??=
ui.FragmentProgram.fromAsset('shaders/liquid_glass.frag'));
if (mounted) setState(() => _shader = program.fragmentShader());
} catch (error) {
_program = null;
_loadedProgram = null;
debugPrint('Glass refraction unavailable: $error');
}
}
@@ -46,12 +51,17 @@ class _GlassRefractionState extends State<GlassRefraction> {
@override
Widget build(BuildContext context) => _shader == null
? BackdropFilter(
filter: ui.ImageFilter.blur(sigmaX: 0.6, sigmaY: 0.6),
filter: ui.ImageFilter.blur(
sigmaX: widget.blurSigma,
sigmaY: widget.blurSigma,
tileMode: TileMode.clamp,
),
child: widget.child,
)
: _LiveGlassFilter(
shader: _shader!,
strength: widget.strength,
blurSigma: widget.blurSigma,
pixelRatio: MediaQuery.devicePixelRatioOf(context),
child: widget.child,
);
@@ -61,29 +71,41 @@ class _LiveGlassFilter extends SingleChildRenderObjectWidget {
const _LiveGlassFilter({
required this.shader,
required this.strength,
required this.blurSigma,
required this.pixelRatio,
required super.child,
});
final ui.FragmentShader shader;
final double strength, pixelRatio;
final double strength, blurSigma, pixelRatio;
@override
_RenderLiveGlass createRenderObject(BuildContext context) =>
_RenderLiveGlass(shader, strength, pixelRatio);
_RenderLiveGlass(shader, strength, blurSigma, pixelRatio);
@override
void updateRenderObject(
BuildContext context,
_RenderLiveGlass renderObject,
) => renderObject.update(shader, strength, pixelRatio);
) => renderObject.update(shader, strength, blurSigma, pixelRatio);
}
class _RenderLiveGlass extends RenderProxyBox {
_RenderLiveGlass(this._shader, this._strength, this._pixelRatio);
_RenderLiveGlass(
this._shader,
this._strength,
this._blurSigma,
this._pixelRatio,
);
ui.FragmentShader _shader;
double _strength, _pixelRatio;
double _strength, _blurSigma, _pixelRatio;
final _layer = LayerHandle<BackdropFilterLayer>();
void update(ui.FragmentShader shader, double strength, double pixelRatio) {
void update(
ui.FragmentShader shader,
double strength,
double blurSigma,
double pixelRatio,
) {
_shader = shader;
_strength = strength;
_blurSigma = blurSigma;
_pixelRatio = pixelRatio;
markNeedsPaint();
}
@@ -103,7 +125,17 @@ class _RenderLiveGlass extends RenderProxyBox {
..setFloat(5, size.height * _pixelRatio)
..setFloat(6, _strength);
_layer.layer ??= BackdropFilterLayer();
_layer.layer!.filter = ui.ImageFilter.shader(_shader);
// Refract the original backdrop first, then diffuse it with the engine's
// separable Gaussian blur. Keeping the shader inside the composition also
// keeps its source texture coordinates independent of blur padding.
_layer.layer!.filter = ui.ImageFilter.compose(
outer: ui.ImageFilter.blur(
sigmaX: _blurSigma,
sigmaY: _blurSigma,
tileMode: TileMode.clamp,
),
inner: ui.ImageFilter.shader(_shader),
);
context.pushLayer(_layer.layer!, super.paint, offset);
}