媒体库上拉刷新,下拉加载

This commit is contained in:
rang 2025-12-30 17:02:28 +08:00
parent bdd85efcd8
commit ebcbe1774a
20 changed files with 351 additions and 126 deletions

View file

@ -52,6 +52,20 @@ extension UserConversion on User {
User get asUser => User.fromJson(toJson());
}
extension ContentUrlExtension on AudioFile {
Uri url(String baseUrl, String itemId, String token) {
// /api/items/{itemId}/file/{ino}?{token}
// return Uri.parse('$baseUrl/api/items/$itemId/file/$ino?token=$token');
var baseUri = Uri.parse(baseUrl);
return Uri(
scheme: baseUri.scheme,
host: baseUri.host,
path: '/api/items/$itemId/file/$ino',
queryParameters: {'token': token},
);
}
}
extension ContentUrl on LibraryFile {
Uri url(String baseUrl, String itemId, String token) {
// /api/items/{itemId}/file/{ino}?{token}

View file

@ -0,0 +1,33 @@
import 'package:easy_refresh/easy_refresh.dart';
import 'package:flutter/widgets.dart';
import 'package:vaani/generated/l10n.dart';
class Components {
Components._();
static ClassicHeader easyRefreshHeader(BuildContext context) {
return ClassicHeader(
dragText: S.of(context).erDragText,
armedText: S.of(context).erArmedText,
readyText: S.of(context).erReadyText,
processingText: S.of(context).erProcessingText,
processedText: S.of(context).erProcessedText,
noMoreText: S.of(context).erNoMoreText,
failedText: S.of(context).erFailedText,
messageText: S.of(context).erMessageText,
);
}
static ClassicFooter easyRefreshFooter(BuildContext context) {
return ClassicFooter(
dragText: S.of(context).erDragTextUp,
armedText: S.of(context).erArmedText,
readyText: S.of(context).erReadyText,
processingText: S.of(context).erProcessingText,
processedText: S.of(context).erProcessedText,
noMoreText: S.of(context).erNoMoreText,
failedText: S.of(context).erFailedText,
messageText: S.of(context).erMessageText,
infiniteOffset: 0,
);
}
}

View file

@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:vaani/generated/l10n.dart';
class DialogUtils {
DialogUtils._();
// dialog
static deleteDialog(
BuildContext context, {
String? name,
required Function() onPressed,
}) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(S.of(context).delete),
content: Text(S.of(context).deleteDialog(name ?? '')),
actions: [
TextButton(
onPressed: () {
onPressed();
Navigator.pop(context);
},
child: Text(S.of(context).yes),
),
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text(S.of(context).no),
),
],
);
},
);
}
}

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shelfsdk/audiobookshelf_api.dart';
import 'package:vaani/api/image_provider.dart';
import 'package:vaani/shared/extensions/model_conversions.dart';
import 'package:vaani/shared/widgets/shelves/home_shelf.dart';
@ -40,7 +41,7 @@ class AuthorOnShelf extends HookConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
final author = item.asMinified;
// final coverImage = ref.watch(coverImageProvider(item));
final coverImage = ref.watch(coverImageProvider(item.id));
return Container(
margin: const EdgeInsets.only(right: 10, bottom: 10),
@ -53,17 +54,17 @@ class AuthorOnShelf extends HookConsumerWidget {
aspectRatio: 1,
child: Container(
constraints: const BoxConstraints(maxWidth: 50),
// child: coverImage.when(
// data: (image) {
// return Image.memory(image, fit: BoxFit.cover);
// },
// loading: () {
// return const Center(child: CircularProgressIndicator());
// },
// error: (error, stack) {
// return const Icon(Icons.error);
// },
// ),
child: coverImage.when(
data: (image) {
return Image.memory(image, fit: BoxFit.cover);
},
loading: () {
return const Center(child: CircularProgressIndicator());
},
error: (error, stack) {
return const Icon(Icons.error);
},
),
),
),
),

View file

@ -213,12 +213,12 @@ class _BookOnShelfPlayButton extends HookConsumerWidget {
Widget build(BuildContext context, WidgetRef ref) {
final me = ref.watch(meProvider);
final currentBook = ref.watch(currentBookProvider);
final playerStateNotifier = ref.watch(playerStateProvider.notifier);
final playing = ref.watch(playerStateProvider.select((v) => v.playing));
final playerStateNotifier = ref.read(playerStateProvider.notifier);
final isLoading = playerStateNotifier.isLoading(libraryItemId);
final isCurrentBookSetInPlayer =
currentBook?.libraryItemId == libraryItemId;
final isPlayingThisBook =
playerStateNotifier.isPlaying() && isCurrentBookSetInPlayer;
final isPlayingThisBook = playing && isCurrentBookSetInPlayer;
final userProgress = me.valueOrNull?.mediaProgress
?.firstWhereOrNull((element) => element.libraryItemId == libraryItemId);