mirror of
https://github.com/venera-app/venera.git
synced 2025-09-26 23:47:23 +00:00

* feat: 增加图片收藏 * feat: 主体图片收藏页面实现 * feat: 点击打开大图浏览 * feat: 数据结构变更 * feat: 基本完成 * feat: 翻译与bug修复 * feat: 实机测试和问题修复 * feat: jm导入, pica历史记录nhentai有问题, 一键反转 * fix: 大小写不一致, 一个htManga, 一个htmanga * feat: 拉取收藏优化 * feat: 改成以ep为准 * feat: 兜底一些可能报错场景 * chore: 没有用到 * feat: 尽量保证和网络收藏顺序一致 * feat: 支持显示热点tag * feat: 支持双击收藏, 不过此时禁止放大图片 * fix: 自动塞封面逻辑完善, 切换快速收藏图片立刻生效 * Refactor * fix updateValue * feat: 双击功能提示 * fix: 被确定取消收藏的才删除 * Refactor ImageFavoritesPage * translate author * feat: 功能提示改到dialog中 * fix text editing * fix text editing * feat: 功能提示放到邮件或长按菜单中 * fix: 修复tag过滤不生效问题 * Improve image loading * The default value of quickCollectImage should be false. * Refactor DragListener * Refactor ImageFavoriteItem & ImageFavoritePhotoView * Refactor * Fix `ImageFavoriteManager.has` * Fix UI * Improve UI --------- Co-authored-by: nyne <me@nyne.dev>
138 lines
3.8 KiB
Dart
138 lines
3.8 KiB
Dart
part of 'components.dart';
|
|
|
|
class SmoothCustomScrollView extends StatelessWidget {
|
|
const SmoothCustomScrollView(
|
|
{super.key, required this.slivers, this.controller});
|
|
|
|
final ScrollController? controller;
|
|
|
|
final List<Widget> slivers;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return SmoothScrollProvider(
|
|
controller: controller,
|
|
builder: (context, controller, physics) {
|
|
return CustomScrollView(
|
|
controller: controller,
|
|
physics: physics,
|
|
slivers: [
|
|
...slivers,
|
|
SliverPadding(
|
|
padding: EdgeInsets.only(
|
|
bottom: context.padding.bottom,
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|
|
|
|
class SmoothScrollProvider extends StatefulWidget {
|
|
const SmoothScrollProvider(
|
|
{super.key, this.controller, required this.builder});
|
|
|
|
final ScrollController? controller;
|
|
|
|
final Widget Function(BuildContext, ScrollController, ScrollPhysics) builder;
|
|
|
|
static bool get isMouseScroll => _SmoothScrollProviderState._isMouseScroll;
|
|
|
|
@override
|
|
State<SmoothScrollProvider> createState() => _SmoothScrollProviderState();
|
|
}
|
|
|
|
class _SmoothScrollProviderState extends State<SmoothScrollProvider> {
|
|
late final ScrollController _controller;
|
|
|
|
double? _futurePosition;
|
|
|
|
static bool _isMouseScroll = App.isDesktop;
|
|
|
|
@override
|
|
void initState() {
|
|
_controller = widget.controller ?? ScrollController();
|
|
super.initState();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
if (App.isMacOS) {
|
|
return widget.builder(
|
|
context,
|
|
_controller,
|
|
const BouncingScrollPhysics(),
|
|
);
|
|
}
|
|
return Listener(
|
|
behavior: HitTestBehavior.translucent,
|
|
onPointerDown: (event) {
|
|
_futurePosition = null;
|
|
if (_isMouseScroll) {
|
|
setState(() {
|
|
_isMouseScroll = false;
|
|
});
|
|
}
|
|
},
|
|
onPointerSignal: (pointerSignal) {
|
|
if (pointerSignal is PointerScrollEvent) {
|
|
if (HardwareKeyboard.instance.isShiftPressed) {
|
|
return;
|
|
}
|
|
if (pointerSignal.kind == PointerDeviceKind.mouse &&
|
|
!_isMouseScroll) {
|
|
setState(() {
|
|
_isMouseScroll = true;
|
|
});
|
|
}
|
|
if (!_isMouseScroll) return;
|
|
var currentLocation = _controller.position.pixels;
|
|
var old = _futurePosition;
|
|
_futurePosition ??= currentLocation;
|
|
double k = (_futurePosition! - currentLocation).abs() / 1600 + 1;
|
|
_futurePosition = _futurePosition! + pointerSignal.scrollDelta.dy * k;
|
|
_futurePosition = _futurePosition!.clamp(
|
|
_controller.position.minScrollExtent,
|
|
_controller.position.maxScrollExtent,
|
|
);
|
|
if (_futurePosition == old) return;
|
|
_controller.animateTo(_futurePosition!,
|
|
duration: _fastAnimationDuration, curve: Curves.linear);
|
|
}
|
|
},
|
|
child: ScrollControllerProvider._(
|
|
controller: _controller,
|
|
child: widget.builder(
|
|
context,
|
|
_controller,
|
|
_isMouseScroll
|
|
? const NeverScrollableScrollPhysics()
|
|
: const BouncingScrollPhysics(),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class ScrollControllerProvider extends InheritedWidget {
|
|
const ScrollControllerProvider._({
|
|
required this.controller,
|
|
required super.child,
|
|
});
|
|
|
|
final ScrollController controller;
|
|
|
|
static ScrollController of(BuildContext context) {
|
|
final ScrollControllerProvider? provider =
|
|
context.dependOnInheritedWidgetOfExactType<ScrollControllerProvider>();
|
|
return provider!.controller;
|
|
}
|
|
|
|
@override
|
|
bool updateShouldNotify(ScrollControllerProvider oldWidget) {
|
|
return oldWidget.controller != controller;
|
|
}
|
|
}
|