mirror of
https://github.com/venera-app/venera.git
synced 2025-12-16 07:01:16 +00:00
Optimize favorite page.
This commit is contained in:
@@ -753,9 +753,9 @@ class SliverGridComics extends StatefulWidget {
|
|||||||
|
|
||||||
final List<MenuEntry> Function(Comic)? menuBuilder;
|
final List<MenuEntry> Function(Comic)? menuBuilder;
|
||||||
|
|
||||||
final void Function(Comic)? onTap;
|
final void Function(Comic, int heroID)? onTap;
|
||||||
|
|
||||||
final void Function(Comic)? onLongPressed;
|
final void Function(Comic, int heroID)? onLongPressed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SliverGridComics> createState() => _SliverGridComicsState();
|
State<SliverGridComics> createState() => _SliverGridComicsState();
|
||||||
@@ -856,28 +856,30 @@ class _SliverGridComics extends StatelessWidget {
|
|||||||
|
|
||||||
final List<MenuEntry> Function(Comic)? menuBuilder;
|
final List<MenuEntry> Function(Comic)? menuBuilder;
|
||||||
|
|
||||||
final void Function(Comic)? onTap;
|
final void Function(Comic, int heroID)? onTap;
|
||||||
|
|
||||||
final void Function(Comic)? onLongPressed;
|
final void Function(Comic, int heroID)? onLongPressed;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SliverGrid(
|
return SliverGrid(
|
||||||
delegate: SliverChildBuilderDelegate(
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
(context, index) {
|
|
||||||
if (index == comics.length - 1) {
|
if (index == comics.length - 1) {
|
||||||
onLastItemBuild?.call();
|
onLastItemBuild?.call();
|
||||||
}
|
}
|
||||||
var badge = badgeBuilder?.call(comics[index]);
|
var badge = badgeBuilder?.call(comics[index]);
|
||||||
var isSelected =
|
var isSelected = selection == null
|
||||||
selection == null ? false : selection![comics[index]] ?? false;
|
? false
|
||||||
|
: selection![comics[index]] ?? false;
|
||||||
var comic = ComicTile(
|
var comic = ComicTile(
|
||||||
comic: comics[index],
|
comic: comics[index],
|
||||||
badge: badge,
|
badge: badge,
|
||||||
menuOptions: menuBuilder?.call(comics[index]),
|
menuOptions: menuBuilder?.call(comics[index]),
|
||||||
onTap: onTap != null ? () => onTap!(comics[index]) : null,
|
onTap: onTap != null
|
||||||
|
? () => onTap!(comics[index], heroIDs[index])
|
||||||
|
: null,
|
||||||
onLongPressed: onLongPressed != null
|
onLongPressed: onLongPressed != null
|
||||||
? () => onLongPressed!(comics[index])
|
? () => onLongPressed!(comics[index], heroIDs[index])
|
||||||
: null,
|
: null,
|
||||||
heroID: heroIDs[index],
|
heroID: heroIDs[index],
|
||||||
);
|
);
|
||||||
@@ -889,19 +891,16 @@ class _SliverGridComics extends StatelessWidget {
|
|||||||
duration: const Duration(milliseconds: 150),
|
duration: const Duration(milliseconds: 150),
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: isSelected
|
color: isSelected
|
||||||
? Theme.of(context)
|
? Theme.of(
|
||||||
.colorScheme
|
context,
|
||||||
.secondaryContainer
|
).colorScheme.secondaryContainer.toOpacity(0.72)
|
||||||
.toOpacity(0.72)
|
|
||||||
: null,
|
: null,
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
),
|
),
|
||||||
margin: const EdgeInsets.all(4),
|
margin: const EdgeInsets.all(4),
|
||||||
child: comic,
|
child: comic,
|
||||||
);
|
);
|
||||||
},
|
}, childCount: comics.length),
|
||||||
childCount: comics.length,
|
|
||||||
),
|
|
||||||
gridDelegate: SliverGridDelegateWithComics(),
|
gridDelegate: SliverGridDelegateWithComics(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -241,6 +241,10 @@ class _AppScrollBarState extends State<AppScrollBar> {
|
|||||||
|
|
||||||
late final VerticalDragGestureRecognizer _dragGestureRecognizer;
|
late final VerticalDragGestureRecognizer _dragGestureRecognizer;
|
||||||
|
|
||||||
|
bool _isVisible = false;
|
||||||
|
Timer? _hideTimer;
|
||||||
|
static const _hideDuration = Duration(seconds: 2);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -248,7 +252,41 @@ class _AppScrollBarState extends State<AppScrollBar> {
|
|||||||
_scrollController.addListener(onChanged);
|
_scrollController.addListener(onChanged);
|
||||||
Future.microtask(onChanged);
|
Future.microtask(onChanged);
|
||||||
_dragGestureRecognizer = VerticalDragGestureRecognizer()
|
_dragGestureRecognizer = VerticalDragGestureRecognizer()
|
||||||
..onUpdate = onUpdate;
|
..onUpdate = onUpdate
|
||||||
|
..onStart = (_) {
|
||||||
|
_showScrollbar();
|
||||||
|
}
|
||||||
|
..onEnd = (_) {
|
||||||
|
_scheduleHide();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_hideTimer?.cancel();
|
||||||
|
_scrollController.removeListener(onChanged);
|
||||||
|
_dragGestureRecognizer.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showScrollbar() {
|
||||||
|
if (!_isVisible && mounted) {
|
||||||
|
setState(() {
|
||||||
|
_isVisible = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
_hideTimer?.cancel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _scheduleHide() {
|
||||||
|
_hideTimer?.cancel();
|
||||||
|
_hideTimer = Timer(_hideDuration, () {
|
||||||
|
if (mounted && _isVisible) {
|
||||||
|
setState(() {
|
||||||
|
_isVisible = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void onUpdate(DragUpdateDetails details) {
|
void onUpdate(DragUpdateDetails details) {
|
||||||
@@ -269,14 +307,24 @@ class _AppScrollBarState extends State<AppScrollBar> {
|
|||||||
void onChanged() {
|
void onChanged() {
|
||||||
if (_scrollController.positions.isEmpty) return;
|
if (_scrollController.positions.isEmpty) return;
|
||||||
var position = _scrollController.position;
|
var position = _scrollController.position;
|
||||||
|
|
||||||
|
bool hasChanged = false;
|
||||||
if (position.minScrollExtent != minExtent ||
|
if (position.minScrollExtent != minExtent ||
|
||||||
position.maxScrollExtent != maxExtent ||
|
position.maxScrollExtent != maxExtent ||
|
||||||
position.pixels != this.position) {
|
position.pixels != this.position) {
|
||||||
setState(() {
|
hasChanged = true;
|
||||||
minExtent = position.minScrollExtent;
|
minExtent = position.minScrollExtent;
|
||||||
maxExtent = position.maxScrollExtent;
|
maxExtent = position.maxScrollExtent;
|
||||||
this.position = position.pixels;
|
this.position = position.pixels;
|
||||||
});
|
}
|
||||||
|
|
||||||
|
if (hasChanged) {
|
||||||
|
_showScrollbar();
|
||||||
|
_scheduleHide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hasChanged && mounted) {
|
||||||
|
setState(() {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,15 +348,20 @@ class _AppScrollBarState extends State<AppScrollBar> {
|
|||||||
Positioned(
|
Positioned(
|
||||||
top: top + widget.topPadding,
|
top: top + widget.topPadding,
|
||||||
right: 0,
|
right: 0,
|
||||||
|
child: AnimatedOpacity(
|
||||||
|
opacity: _isVisible ? 1.0 : 0.0,
|
||||||
|
duration: const Duration(milliseconds: 200),
|
||||||
child: MouseRegion(
|
child: MouseRegion(
|
||||||
cursor: SystemMouseCursors.click,
|
cursor: SystemMouseCursors.click,
|
||||||
|
onEnter: (_) => _showScrollbar(),
|
||||||
|
onExit: (_) => _scheduleHide(),
|
||||||
child: Listener(
|
child: Listener(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onPointerDown: (event) {
|
onPointerDown: (event) {
|
||||||
_dragGestureRecognizer.addPointer(event);
|
_dragGestureRecognizer.addPointer(event);
|
||||||
},
|
},
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: _scrollIndicatorSize/2,
|
width: _scrollIndicatorSize / 2,
|
||||||
height: _scrollIndicatorSize,
|
height: _scrollIndicatorSize,
|
||||||
child: CustomPaint(
|
child: CustomPaint(
|
||||||
painter: _ScrollIndicatorPainter(
|
painter: _ScrollIndicatorPainter(
|
||||||
@@ -328,6 +381,7 @@ class _AppScrollBarState extends State<AppScrollBar> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -627,7 +627,7 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
},
|
},
|
||||||
onTap: (c) {
|
onTap: (c, heroID) {
|
||||||
if (multiSelectMode) {
|
if (multiSelectMode) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selectedComics.containsKey(c as FavoriteItem)) {
|
if (selectedComics.containsKey(c as FavoriteItem)) {
|
||||||
@@ -639,18 +639,22 @@ class _LocalFavoritesPageState extends State<_LocalFavoritesPage> {
|
|||||||
lastSelectedIndex = comics.indexOf(c);
|
lastSelectedIndex = comics.indexOf(c);
|
||||||
});
|
});
|
||||||
} else if (appdata.settings["onClickFavorite"] == "viewDetail") {
|
} else if (appdata.settings["onClickFavorite"] == "viewDetail") {
|
||||||
App.mainNavigatorKey?.currentContext
|
|
||||||
?.to(() => ComicPage(id: c.id, sourceKey: c.sourceKey));
|
|
||||||
} else {
|
|
||||||
App.mainNavigatorKey?.currentContext?.to(
|
App.mainNavigatorKey?.currentContext?.to(
|
||||||
() => ReaderWithLoading(
|
() => ComicPage(
|
||||||
id: c.id,
|
id: c.id,
|
||||||
sourceKey: c.sourceKey,
|
sourceKey: c.sourceKey,
|
||||||
|
cover: c.cover,
|
||||||
|
title: c.title,
|
||||||
|
heroID: heroID,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
} else {
|
||||||
|
App.mainNavigatorKey?.currentContext?.to(
|
||||||
|
() => ReaderWithLoading(id: c.id, sourceKey: c.sourceKey),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onLongPressed: (c) {
|
onLongPressed: (c, heroID) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (!multiSelectMode) {
|
if (!multiSelectMode) {
|
||||||
multiSelectMode = true;
|
multiSelectMode = true;
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ class _HistoryPageState extends State<HistoryPage> {
|
|||||||
selections: selectedComics,
|
selections: selectedComics,
|
||||||
onLongPressed: null,
|
onLongPressed: null,
|
||||||
onTap: multiSelectMode
|
onTap: multiSelectMode
|
||||||
? (c) {
|
? (c, heroID) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selectedComics.containsKey(c as History)) {
|
if (selectedComics.containsKey(c as History)) {
|
||||||
selectedComics.remove(c);
|
selectedComics.remove(c);
|
||||||
|
|||||||
@@ -285,13 +285,13 @@ class _LocalComicsPageState extends State<LocalComicsPage> {
|
|||||||
SliverGridComics(
|
SliverGridComics(
|
||||||
comics: comics,
|
comics: comics,
|
||||||
selections: selectedComics,
|
selections: selectedComics,
|
||||||
onLongPressed: (c) {
|
onLongPressed: (c, heroID) {
|
||||||
setState(() {
|
setState(() {
|
||||||
multiSelectMode = true;
|
multiSelectMode = true;
|
||||||
selectedComics[c as LocalComic] = true;
|
selectedComics[c as LocalComic] = true;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onTap: (c) {
|
onTap: (c, heroID) {
|
||||||
if (multiSelectMode) {
|
if (multiSelectMode) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (selectedComics.containsKey(c as LocalComic)) {
|
if (selectedComics.containsKey(c as LocalComic)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user