mirror of
https://github.com/bggRGjQaUbCoE/PiliPlus.git
synced 2026-05-11 04:27:47 +08:00
tweaks (#2032)
* fix: 1080p * opt: import export * opt: downloader * opt: skeleton * opt: parseColor * tweak * opt: sb seek * opt: rxn
This commit is contained in:
committed by
GitHub
parent
b7b40c557e
commit
f5dbfcec79
@@ -1,188 +1,62 @@
|
||||
import 'dart:ui' as ui;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class Skeleton extends StatelessWidget {
|
||||
class Skeleton extends StatefulWidget {
|
||||
final Widget child;
|
||||
|
||||
const Skeleton({
|
||||
required this.child,
|
||||
super.key,
|
||||
});
|
||||
const Skeleton({super.key, required this.child});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final color = Theme.of(context).colorScheme.surface.withAlpha(10);
|
||||
final shimmerGradient = LinearGradient(
|
||||
colors: [
|
||||
Colors.transparent,
|
||||
color,
|
||||
color,
|
||||
Colors.transparent,
|
||||
],
|
||||
stops: const [
|
||||
0.1,
|
||||
0.3,
|
||||
0.5,
|
||||
0.7,
|
||||
],
|
||||
begin: const Alignment(-1.0, -0.3),
|
||||
end: const Alignment(1.0, 0.9),
|
||||
tileMode: TileMode.clamp,
|
||||
);
|
||||
return Shimmer(
|
||||
linearGradient: shimmerGradient,
|
||||
child: ShimmerLoading(
|
||||
isLoading: true,
|
||||
child: child,
|
||||
),
|
||||
);
|
||||
}
|
||||
State<Skeleton> createState() => _SkeletonState();
|
||||
}
|
||||
|
||||
class Shimmer extends StatefulWidget {
|
||||
static ShimmerState? of(BuildContext context) {
|
||||
return context.findAncestorStateOfType<ShimmerState>();
|
||||
}
|
||||
|
||||
const Shimmer({
|
||||
super.key,
|
||||
required this.linearGradient,
|
||||
this.child,
|
||||
});
|
||||
|
||||
final LinearGradient linearGradient;
|
||||
final Widget? child;
|
||||
|
||||
@override
|
||||
ShimmerState createState() => ShimmerState();
|
||||
}
|
||||
|
||||
class ShimmerState extends State<Shimmer> with SingleTickerProviderStateMixin {
|
||||
late AnimationController _shimmerController;
|
||||
class _SkeletonState extends State<Skeleton>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late final AnimationController _controller;
|
||||
late Color color;
|
||||
final matrix = Matrix4.identity();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_shimmerController = AnimationController.unbounded(vsync: this)
|
||||
..repeat(min: -0.5, max: 1.5, period: const Duration(milliseconds: 1000));
|
||||
_controller = AnimationController.unbounded(vsync: this)
|
||||
..repeat(min: -0.5, max: 1.5, period: const Duration(milliseconds: 1000))
|
||||
..addListener(_setState);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_shimmerController.dispose();
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
LinearGradient get gradient => LinearGradient(
|
||||
colors: widget.linearGradient.colors,
|
||||
stops: widget.linearGradient.stops,
|
||||
begin: widget.linearGradient.begin,
|
||||
end: widget.linearGradient.end,
|
||||
transform: _SlidingGradientTransform(
|
||||
slidePercent: _shimmerController.value,
|
||||
),
|
||||
);
|
||||
|
||||
bool get isSized =>
|
||||
(context.findRenderObject() as RenderBox?)?.hasSize ?? false;
|
||||
|
||||
Size get size => (context.findRenderObject() as RenderBox).size;
|
||||
|
||||
Offset getDescendantOffset({
|
||||
required RenderBox descendant,
|
||||
Offset offset = Offset.zero,
|
||||
}) {
|
||||
final shimmerBox = context.findRenderObject() as RenderBox;
|
||||
return descendant.localToGlobal(offset, ancestor: shimmerBox);
|
||||
void _setState() {
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
Listenable get shimmerChanges => _shimmerController;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return widget.child ?? const SizedBox.shrink();
|
||||
}
|
||||
}
|
||||
|
||||
class _SlidingGradientTransform extends GradientTransform {
|
||||
const _SlidingGradientTransform({
|
||||
required this.slidePercent,
|
||||
});
|
||||
|
||||
final double slidePercent;
|
||||
|
||||
@override
|
||||
Matrix4? transform(Rect bounds, {TextDirection? textDirection}) {
|
||||
return Matrix4.translationValues(bounds.width * slidePercent, 0.0, 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
class ShimmerLoading extends StatefulWidget {
|
||||
const ShimmerLoading({
|
||||
super.key,
|
||||
required this.isLoading,
|
||||
required this.child,
|
||||
});
|
||||
|
||||
final bool isLoading;
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
State<ShimmerLoading> createState() => _ShimmerLoadingState();
|
||||
}
|
||||
|
||||
class _ShimmerLoadingState extends State<ShimmerLoading> {
|
||||
Listenable? _shimmerChanges;
|
||||
|
||||
@override
|
||||
void didChangeDependencies() {
|
||||
super.didChangeDependencies();
|
||||
if (_shimmerChanges != null) {
|
||||
_shimmerChanges!.removeListener(_onShimmerChange);
|
||||
}
|
||||
_shimmerChanges = Shimmer.of(context)?.shimmerChanges;
|
||||
if (_shimmerChanges != null) {
|
||||
_shimmerChanges!.addListener(_onShimmerChange);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_shimmerChanges?.removeListener(_onShimmerChange);
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _onShimmerChange() {
|
||||
if (widget.isLoading) {
|
||||
setState(() {});
|
||||
}
|
||||
color = ColorScheme.of(context).surface.withAlpha(10);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (!widget.isLoading) {
|
||||
return widget.child;
|
||||
}
|
||||
|
||||
final shimmer = Shimmer.of(context)!;
|
||||
if (!shimmer.isSized) {
|
||||
return const SizedBox.shrink();
|
||||
}
|
||||
final shimmerSize = shimmer.size;
|
||||
final gradient = shimmer.gradient;
|
||||
final offsetWithinShimmer = shimmer.getDescendantOffset(
|
||||
descendant: context.findRenderObject() as RenderBox,
|
||||
);
|
||||
|
||||
final colors = [Colors.transparent, color, color, Colors.transparent];
|
||||
return ShaderMask(
|
||||
blendMode: BlendMode.srcATop,
|
||||
shaderCallback: (bounds) {
|
||||
return gradient.createShader(
|
||||
Rect.fromLTWH(
|
||||
-offsetWithinShimmer.dx,
|
||||
-offsetWithinShimmer.dy,
|
||||
shimmerSize.width,
|
||||
shimmerSize.height,
|
||||
),
|
||||
shaderCallback: (Rect bounds) {
|
||||
final width = bounds.width;
|
||||
final height = bounds.height;
|
||||
matrix[12] = width * _controller.value;
|
||||
return ui.Gradient.linear(
|
||||
Offset(0, 0.35 * height),
|
||||
Offset(width, 0.95 * height),
|
||||
colors,
|
||||
const [0.1, 0.3, 0.5, 0.7],
|
||||
TileMode.clamp,
|
||||
matrix.storage,
|
||||
);
|
||||
},
|
||||
child: widget.child,
|
||||
|
||||
Reference in New Issue
Block a user