webdav存在自引用问题,现版本修复完成

This commit is contained in:
2026-08-17 22:24:56 +08:00
parent 457a9bf1e5
commit a6056c7f1a
5 changed files with 874 additions and 622 deletions
+150
View File
@@ -0,0 +1,150 @@
import 'package:flutter/material.dart';
/// 磁吸进度状态
class MagneticSnapState {
/// 吸附进度 0.0 ~ 1.0
final double progress;
/// 媒体库透明度
double get mediaOpacity {
// 0% ~ 70%: 1.0 → 0.45
// 70% ~ 100%: 0.45 → 0
if (progress <= 0.7) {
return 1.0 - (progress / 0.7) * 0.55;
} else {
final t = (progress - 0.7) / 0.3;
return 0.45 * (1 - t);
}
}
/// 收藏标题位移(从 +12px → 0)
double get favoriteTranslateY {
return (1 - progress) * 12;
}
/// 收藏列表展开程度 0.0 ~ 1.0
double get listReveal {
if (progress <= 0.7) return 0.0;
return (progress - 0.7) / 0.3;
}
/// 是否完全吸附
bool get isSnapped => progress >= 1.0;
/// 是否在磁吸区(进度 > 70%)
bool get isInMagneticZone => progress > 0.7;
const MagneticSnapState(this.progress);
factory MagneticSnapState.initial() => const MagneticSnapState(0.0);
MagneticSnapState copyWith({double? progress}) {
return MagneticSnapState(progress ?? this.progress);
}
}
/// 磁吸控制器
class MagneticScrollController extends ChangeNotifier {
/// 吸附进度
double _progress = 0.0;
double get progress => _progress;
/// 是否已吸附
bool _isSnapped = false;
bool get isSnapped => _isSnapped;
/// 动画控制器(用于吸附动画)
AnimationController? _animationController;
TickerProvider? _tickerProvider;
/// 状态
MagneticSnapState get state => MagneticSnapState(_progress);
void init(TickerProvider vsync) {
_animationController = AnimationController(
vsync: vsync,
duration: const Duration(milliseconds: 300),
);
}
@override
void dispose() {
_animationController?.dispose();
super.dispose();
}
/// 更新滚动进度(在滚动时调用)
void updateProgress(double newProgress) {
if (_isSnapped) return;
_progress = newProgress.clamp(0.0, 1.0);
notifyListeners();
}
/// 处理松手事件
void onDragEnd(double velocity) {
if (_isSnapped) return;
final threshold = 0.45; // 45% 触发吸附
final shouldSnap = _progress > threshold || velocity > 800;
if (shouldSnap) {
snapOpen();
} else {
snapBack();
}
}
/// 吸附展开
void snapOpen() {
if (_isSnapped) return;
_isSnapped = true;
_animationController?.reset();
_animationController
?.animateTo(
1.0,
duration: const Duration(milliseconds: 300),
curve: Curves.easeOutBack,
)
.then((_) {
_progress = 1.0;
notifyListeners();
});
// 实时更新进度
_animationController?.addListener(() {
_progress = _animationController!.value;
notifyListeners();
});
}
/// 回弹
void snapBack() {
if (_isSnapped) return;
_animationController?.reset();
_animationController
?.animateTo(
0.0,
duration: const Duration(milliseconds: 250),
curve: Curves.easeOut,
)
.then((_) {
_progress = 0.0;
notifyListeners();
});
_animationController?.addListener(() {
_progress = _animationController!.value;
notifyListeners();
});
}
/// 重置状态(退出页面时)
void reset() {
_isSnapped = false;
_progress = 0.0;
_animationController?.reset();
notifyListeners();
}
}
+74
View File
@@ -0,0 +1,74 @@
// lib/widgets/magnetic_scroll_physics.dart
import 'package:flutter/material.dart';
class MagneticScrollPhysics extends ClampingScrollPhysics {
final double snapPoint;
final double magneticZoneStart;
const MagneticScrollPhysics({
required this.snapPoint,
this.magneticZoneStart = 0.20,
super.parent,
});
@override
MagneticScrollPhysics applyTo(ScrollPhysics? ancestor) {
return MagneticScrollPhysics(
snapPoint: snapPoint,
magneticZoneStart: magneticZoneStart,
parent: buildParent(ancestor),
);
}
@override
Simulation? createBallisticSimulation(
ScrollMetrics position,
double velocity,
) {
final offset = position.pixels;
if (offset <= 0 || offset >= snapPoint) {
return super.createBallisticSimulation(position, velocity);
}
final shouldSnap = _shouldSnap(offset, velocity);
final target = shouldSnap ? snapPoint : 0.0;
if ((offset - target).abs() < 1.0) {
return null;
}
return ScrollSpringSimulation(
SpringDescription(
mass: 1.0,
stiffness: 320.0,
damping: 26.0,
),
offset,
target,
velocity,
tolerance: const Tolerance(
velocity: 0.01,
distance: 0.5,
),
);
}
bool _shouldSnap(double offset, double velocity) {
final zoneStart = snapPoint * magneticZoneStart;
// 向上滑 → 吸附展开
if (velocity > 20) {
return true;
}
// 向下滑 → 回去
if (velocity < -20) {
return false;
}
// 松手速度很小,用当前位置决定
return offset >= zoneStart;
}
}