diff --git a/.github/workflows/flutter-ci.yaml b/.github/workflows/flutter-ci.yaml index 4f1c06b..4bc0d59 100644 --- a/.github/workflows/flutter-ci.yaml +++ b/.github/workflows/flutter-ci.yaml @@ -87,7 +87,11 @@ jobs: run: flutter build apk --release - name: Rename Universal APK - run: mv build/app/outputs/flutter-apk/{app-release,app-universal-release}.apk + run: | + APP_NAME=$(grep '^name:' pubspec.yaml | sed 's/name: //') + APP_VERSION=$(grep '^version:' pubspec.yaml | sed 's/version: //') + + mv build/app/outputs/flutter-apk/{app-release,$APP_NAME-$APP_VERSION-app-universal}.apk - name: Build App Bundle run: flutter build appbundle --release diff --git a/lib/api/library_provider.dart b/lib/api/library_provider.dart index c5403ae..7db659a 100644 --- a/lib/api/library_provider.dart +++ b/lib/api/library_provider.dart @@ -2,7 +2,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart' show Ref; import 'package:logging/logging.dart' show Logger; import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:shelfsdk/audiobookshelf_api.dart' - show GetLibrarysItemsReqParams, Library, LibraryItemMinified; + show GetLibrarysItemsReqParams, Library, LibraryItemMinified, LibraryItem; import 'package:vaani/api/api_provider.dart' show authenticatedApiProvider; import 'package:vaani/features/settings/api_settings_provider.dart' show apiSettingsProvider; @@ -59,9 +59,21 @@ class Libraries extends _$Libraries { } } +@riverpod +class LibraryItemsParams extends _$LibraryItemsParams { + @override + GetLibrarysItemsReqParams build() { + return const GetLibrarysItemsReqParams( + limit: 18, + page: 0, + minified: true, + ); + } +} + // 查询库下所有项目 @riverpod -Future> currentLibraryItems(Ref ref) async { +Future> currentLibraryItems(Ref ref) async { final api = ref.watch(authenticatedApiProvider); final libraryId = ref.watch(apiSettingsProvider.select((s) => s.activeLibraryId)); @@ -73,12 +85,12 @@ Future> currentLibraryItems(Ref ref) async { libraryId: libraryId, parameters: const GetLibrarysItemsReqParams( limit: 18, - page: 1, + page: 0, minified: true, ), ); if (items == null) { return []; } - return items.results.map((v) => v.asMinified).toList(); + return items.results; } diff --git a/lib/api/library_provider.g.dart b/lib/api/library_provider.g.dart index 8bcaf44..0abdc83 100644 --- a/lib/api/library_provider.g.dart +++ b/lib/api/library_provider.g.dart @@ -174,12 +174,12 @@ final currentLibraryProvider = AutoDisposeFutureProvider.internal( // ignore: unused_element typedef CurrentLibraryRef = AutoDisposeFutureProviderRef; String _$currentLibraryItemsHash() => - r'2e2ce270c46bedf0b779399772df89a23803fe50'; + r'b0d0dcca86e760ee08f327c06b5ad5deaf7852e1'; /// See also [currentLibraryItems]. @ProviderFor(currentLibraryItems) final currentLibraryItemsProvider = - AutoDisposeFutureProvider>.internal( + AutoDisposeFutureProvider>.internal( currentLibraryItems, name: r'currentLibraryItemsProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') @@ -192,7 +192,7 @@ final currentLibraryItemsProvider = @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element typedef CurrentLibraryItemsRef - = AutoDisposeFutureProviderRef>; + = AutoDisposeFutureProviderRef>; String _$librariesHash() => r'95ebd4d1ac0cc2acf7617dc22895eff0ca30600f'; /// See also [Libraries]. @@ -208,5 +208,22 @@ final librariesProvider = ); typedef _$Libraries = AutoDisposeAsyncNotifier>; +String _$libraryItemsParamsHash() => + r'9e7f11ab185eb99e926ae87e06466fc12aee7f72'; + +/// See also [LibraryItemsParams]. +@ProviderFor(LibraryItemsParams) +final libraryItemsParamsProvider = AutoDisposeNotifierProvider< + LibraryItemsParams, GetLibrarysItemsReqParams>.internal( + LibraryItemsParams.new, + name: r'libraryItemsParamsProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$libraryItemsParamsHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$LibraryItemsParams = AutoDisposeNotifier; // ignore_for_file: type=lint // ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/features/player/core/abs_audio_handler.dart b/lib/features/player/core/abs_audio_handler.dart new file mode 100644 index 0000000..c3f04db --- /dev/null +++ b/lib/features/player/core/abs_audio_handler.dart @@ -0,0 +1,39 @@ +import 'package:audio_service/audio_service.dart'; +import 'package:just_audio/just_audio.dart'; + +class AbsAudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler { + final AudioPlayer player; + + AbsAudioHandler(this.player); + + // 播放控制方法重写 + @override + Future play() async { + await player.play(); + } + + @override + Future pause() async { + await player.pause(); + } + + @override + Future skipToNext() async { + await player.seekToNext(); + } + + @override + Future skipToPrevious() async { + await player.seekToPrevious(); + } + + @override + Future seek(Duration position) async { + await player.seek(position); + } + + @override + Future setSpeed(double speed) async { + await player.setSpeed(speed); + } +} diff --git a/lib/features/player/core/abs_audio_player.dart b/lib/features/player/core/abs_audio_player.dart new file mode 100644 index 0000000..3475a3a --- /dev/null +++ b/lib/features/player/core/abs_audio_player.dart @@ -0,0 +1,5 @@ +// ignore_for_file: public_member_api_docs, sort_constructors_first +import 'package:just_audio/just_audio.dart'; +import 'package:shelfsdk/audiobookshelf_api.dart'; + +class AbsAudioPlayer extends AudioPlayer {} diff --git a/lib/features/player/core/audiobook_player.dart b/lib/features/player/core/audiobook_player.dart index 0faecf5..da6e0c6 100644 --- a/lib/features/player/core/audiobook_player.dart +++ b/lib/features/player/core/audiobook_player.dart @@ -32,6 +32,7 @@ class AbsAudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler { final _currentChapterObject = BehaviorSubject.seeded(null); AbsAudioHandler(this.ref) { + notificationSettings = ref.read(appSettingsProvider).notificationSettings; ref.listen(appSettingsProvider, (a, b) { if (a?.notificationSettings != b.notificationSettings) { notificationSettings = b.notificationSettings; @@ -52,12 +53,12 @@ class AbsAudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler { final chapter = _book?.findChapterAtTime(positionInBook); if (chapter != currentChapter) { if (mediaItem.hasValue && chapter != null) { - updateMediaItem( - mediaItem.value!.copyWith( - duration: chapter.duration, - displayTitle: chapter.title, - ), - ); + // updateMediaItem( + // mediaItem.value!.copyWith( + // duration: chapter.duration, + // displayTitle: chapter.title, + // ), + // ); } _currentChapterObject.sink.add(chapter); } diff --git a/lib/features/player/providers/abs_provider.dart b/lib/features/player/providers/abs_provider.dart new file mode 100644 index 0000000..c9cfd46 --- /dev/null +++ b/lib/features/player/providers/abs_provider.dart @@ -0,0 +1,56 @@ +import 'package:audio_service/audio_service.dart'; +import 'package:audio_session/audio_session.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:just_audio_media_kit/just_audio_media_kit.dart'; +import 'package:logging/logging.dart'; +import 'package:riverpod_annotation/riverpod_annotation.dart'; +import 'package:shelfsdk/audiobookshelf_api.dart'; +import 'package:vaani/features/player/core/abs_audio_handler.dart' as core; +import 'package:vaani/features/player/core/abs_audio_player.dart' as core; + +part 'abs_provider.g.dart'; + +final _logger = Logger('AbsPlayerProvider'); + +@Riverpod(keepAlive: true) +Future absAudioHandler(Ref ref) async { + // for playing audio on windows, linux + JustAudioMediaKit.ensureInitialized(); + + // for configuring how this app will interact with other audio apps + final session = await AudioSession.instance; + await session.configure(const AudioSessionConfiguration.speech()); + + final player = ref.read(absAudioPlayerProvider); + + final audioService = await AudioService.init( + builder: () => core.AbsAudioHandler(player), + config: const AudioServiceConfig( + androidNotificationChannelId: 'dr.blank.vaani.channel.audio', + androidNotificationChannelName: 'ABSPlayback', + androidNotificationChannelDescription: + 'Needed to control audio from lock screen', + androidNotificationOngoing: false, + androidStopForegroundOnPause: false, + androidNotificationIcon: 'drawable/ic_stat_logo', + preloadArtwork: true, + // fastForwardInterval: Duration(seconds: 20), + // rewindInterval: Duration(seconds: 20), + ), + ); + + return audioService; +} + +@Riverpod(keepAlive: true) +class AbsAudioPlayer extends _$AbsAudioPlayer { + @override + core.AbsAudioPlayer build() { + final player = core.AbsAudioPlayer(); + + ref.onDispose(player.dispose); + _logger.finer('created simple player'); + + return player; + } +} diff --git a/lib/features/player/providers/abs_provider.g.dart b/lib/features/player/providers/abs_provider.g.dart new file mode 100644 index 0000000..6bd8866 --- /dev/null +++ b/lib/features/player/providers/abs_provider.g.dart @@ -0,0 +1,43 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'abs_provider.dart'; + +// ************************************************************************** +// RiverpodGenerator +// ************************************************************************** + +String _$absAudioHandlerHash() => r'f4ef20cc3e244d5d37354ef38a1e0fdbd89412f4'; + +/// See also [absAudioHandler]. +@ProviderFor(absAudioHandler) +final absAudioHandlerProvider = FutureProvider.internal( + absAudioHandler, + name: r'absAudioHandlerProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$absAudioHandlerHash, + dependencies: null, + allTransitiveDependencies: null, +); + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +typedef AbsAudioHandlerRef = FutureProviderRef; +String _$absAudioPlayerHash() => r'68a56d45a9f165d257c23f81d9bf7d0930425464'; + +/// See also [AbsAudioPlayer]. +@ProviderFor(AbsAudioPlayer) +final absAudioPlayerProvider = + NotifierProvider.internal( + AbsAudioPlayer.new, + name: r'absAudioPlayerProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$absAudioPlayerHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$AbsAudioPlayer = Notifier; +// ignore_for_file: type=lint +// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package diff --git a/lib/features/player/providers/currently_playing_provider.dart b/lib/features/player/providers/currently_playing_provider.dart index bdd0fc8..3cebfbe 100644 --- a/lib/features/player/providers/currently_playing_provider.dart +++ b/lib/features/player/providers/currently_playing_provider.dart @@ -99,6 +99,7 @@ List currentChapters(Ref ref) { } final index = book.chapters.indexOf(currentChapter); final total = book.chapters.length; - return book.chapters - .sublist(index - 3, (total - 3) <= (index + 17) ? total : index + 17); + final start = index - 3 >= 0 ? index - 3 : 0; + final end = start + 20 <= total ? start + 20 : total; + return book.chapters.sublist(start, end); } diff --git a/lib/features/player/providers/currently_playing_provider.g.dart b/lib/features/player/providers/currently_playing_provider.g.dart index b353d18..67ad4a8 100644 --- a/lib/features/player/providers/currently_playing_provider.g.dart +++ b/lib/features/player/providers/currently_playing_provider.g.dart @@ -6,7 +6,7 @@ part of 'currently_playing_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$currentChaptersHash() => r'a25733d8085a2ce7dbc16fa2bf14f00ab8e2a623'; +String _$currentChaptersHash() => r'6574b3f4ee0af8006f233aaf76cc507d188c6305'; /// See also [currentChapters]. @ProviderFor(currentChapters) diff --git a/lib/features/player/view/player_expanded_desktop.dart b/lib/features/player/view/player_expanded_desktop.dart index f0dafda..94e68e5 100644 --- a/lib/features/player/view/player_expanded_desktop.dart +++ b/lib/features/player/view/player_expanded_desktop.dart @@ -1,7 +1,9 @@ import 'dart:math'; import 'package:flutter/material.dart'; +import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/constants/sizes.dart'; import 'package:vaani/features/player/providers/audiobook_player.dart'; import 'package:vaani/features/player/providers/currently_playing_provider.dart'; @@ -137,22 +139,45 @@ class PlayerExpandedDesktop extends HookConsumerWidget { class ChapterSelection extends HookConsumerWidget { const ChapterSelection({super.key}); - @override Widget build(BuildContext context, WidgetRef ref) { final currentChapter = ref.watch(currentChapterProvider); if (currentChapter == null) { return SizedBox.shrink(); } + final chapters = useState([]); + final scrollController = useScrollController(); + useEffect( + () { + int page = 0; + void load(page) { + chapters.value.addAll(ref.watch(currentChaptersProvider)); + } - final currentChapters = ref.watch(currentChaptersProvider); - final currentChapterIndex = currentChapters.indexOf(currentChapter); + load(page); + void listener() { + if (scrollController.position.pixels / + scrollController.position.maxScrollExtent > + 0.8) { + print('滚动到底部'); + } + } + + scrollController.addListener(listener); + return () => scrollController.removeListener(listener); + }, + [scrollController], + ); + + final currentChapterIndex = chapters.value.indexOf(currentChapter); final theme = Theme.of(context); return Scrollbar( + controller: scrollController, child: ListView.builder( - itemCount: currentChapters.length, + controller: scrollController, + itemCount: chapters.value.length, itemBuilder: (context, index) { - final chapter = currentChapters[index]; + final chapter = chapters.value[index]; final isCurrent = currentChapterIndex == index; final isPlayed = index < currentChapterIndex; return ListTile( diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 331e549..fd01b59 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -38,461 +38,483 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "account": MessageLookupByLibrary.simpleMessage("Account"), - "accountAddNewServer": MessageLookupByLibrary.simpleMessage( - "Add New Server", - ), - "accountAddUser": MessageLookupByLibrary.simpleMessage("Add User"), - "accountAddUserDialog": m0, - "accountAddUserSuccessDialog": MessageLookupByLibrary.simpleMessage( - "User added successfully! Switch?", - ), - "accountAddUserTooltip": MessageLookupByLibrary.simpleMessage( - "Add new server", - ), - "accountAnonymous": MessageLookupByLibrary.simpleMessage("Anonymous"), - "accountDeleteServer": MessageLookupByLibrary.simpleMessage( - "Delete Server", - ), - "accountInvalidURL": MessageLookupByLibrary.simpleMessage("Invalid URL"), - "accountManage": MessageLookupByLibrary.simpleMessage("Manage Accounts"), - "accountRegisteredServers": MessageLookupByLibrary.simpleMessage( - "Registered Servers", - ), - "accountRemoveServerAndUsers": MessageLookupByLibrary.simpleMessage( - "Remove Server and Users", - ), - "accountRemoveServerAndUsersHead": MessageLookupByLibrary.simpleMessage( - "This will remove the server ", - ), - "accountRemoveServerAndUsersTail": MessageLookupByLibrary.simpleMessage( - " and all its users\' login info from this app.", - ), - "accountRemoveUserLogin": MessageLookupByLibrary.simpleMessage( - "Remove User Login", - ), - "accountRemoveUserLoginHead": MessageLookupByLibrary.simpleMessage( - "This will remove login details of the user ", - ), - "accountRemoveUserLoginTail": MessageLookupByLibrary.simpleMessage( - " from this app.", - ), - "accountServerURI": MessageLookupByLibrary.simpleMessage("Server URI"), - "accountSwitch": MessageLookupByLibrary.simpleMessage("Switch Account"), - "accountUsersCount": m1, - "appSettings": MessageLookupByLibrary.simpleMessage("App Settings"), - "appearance": MessageLookupByLibrary.simpleMessage("Appearance"), - "autoSleepTimerSettings": MessageLookupByLibrary.simpleMessage( - "Auto Sleep Timer Settings", - ), - "autoTurnOnSleepTimer": MessageLookupByLibrary.simpleMessage( - "Auto Turn On Sleep Timer", - ), - "autoTurnOnTimer": MessageLookupByLibrary.simpleMessage( - "Auto Turn On Timer", - ), - "autoTurnOnTimerAlways": MessageLookupByLibrary.simpleMessage( - "Always Auto Turn On Timer", - ), - "autoTurnOnTimerAlwaysDescription": MessageLookupByLibrary.simpleMessage( - "Always turn on the sleep timer, no matter what", - ), - "autoTurnOnTimerDescription": MessageLookupByLibrary.simpleMessage( - "Automatically turn on the sleep timer based on the time of day", - ), - "autoTurnOnTimerFrom": MessageLookupByLibrary.simpleMessage("From"), - "autoTurnOnTimerFromDescription": MessageLookupByLibrary.simpleMessage( - "Turn on the sleep timer at the specified time", - ), - "autoTurnOnTimerUntil": MessageLookupByLibrary.simpleMessage("Until"), - "autoTurnOnTimerUntilDescription": MessageLookupByLibrary.simpleMessage( - "Turn off the sleep timer at the specified time", - ), - "automaticallyDescription": MessageLookupByLibrary.simpleMessage( - "Automatically turn on the sleep timer based on the time of day", - ), - "backup": MessageLookupByLibrary.simpleMessage("Backup"), - "backupAndRestore": MessageLookupByLibrary.simpleMessage( - "Backup and Restore", - ), - "bookAbout": MessageLookupByLibrary.simpleMessage("About the Book"), - "bookAboutDefault": MessageLookupByLibrary.simpleMessage( - "Sorry, no description found", - ), - "bookAuthors": MessageLookupByLibrary.simpleMessage("Authors"), - "bookDownloads": MessageLookupByLibrary.simpleMessage("Downloads"), - "bookGenres": MessageLookupByLibrary.simpleMessage("Genres"), - "bookMetadataAbridged": MessageLookupByLibrary.simpleMessage("Abridged"), - "bookMetadataLength": MessageLookupByLibrary.simpleMessage("Length"), - "bookMetadataPublished": MessageLookupByLibrary.simpleMessage("Published"), - "bookMetadataUnabridged": MessageLookupByLibrary.simpleMessage( - "Unabridged", - ), - "bookSeries": MessageLookupByLibrary.simpleMessage("Series"), - "bookShelveEmpty": MessageLookupByLibrary.simpleMessage("Try again"), - "bookShelveEmptyText": MessageLookupByLibrary.simpleMessage( - "No shelves to display", - ), - "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), - "chapterNotFound": MessageLookupByLibrary.simpleMessage("Chapters"), - "chapterSelect": MessageLookupByLibrary.simpleMessage("Select Chapter"), - "chapterSkip": MessageLookupByLibrary.simpleMessage( - "Skip chapter opening and ending", - ), - "chapterSkipEnd": MessageLookupByLibrary.simpleMessage( - "Skip chapter opening for ", - ), - "chapterSkipOpen": MessageLookupByLibrary.simpleMessage( - "Skip chapter opening for ", - ), - "chapters": MessageLookupByLibrary.simpleMessage("Chapters"), - "copyToClipboard": MessageLookupByLibrary.simpleMessage( - "Copy to Clipboard", - ), - "copyToClipboardDescription": MessageLookupByLibrary.simpleMessage( - "Copy the app settings to the clipboard", - ), - "copyToClipboardToast": MessageLookupByLibrary.simpleMessage( - "Settings copied to clipboard", - ), - "delete": MessageLookupByLibrary.simpleMessage("Delete"), - "deleteDialog": m2, - "deleted": m3, - "explore": MessageLookupByLibrary.simpleMessage("explore"), - "exploreHint": MessageLookupByLibrary.simpleMessage( - "Seek and you shall discover...", - ), - "exploreTooltip": MessageLookupByLibrary.simpleMessage( - "Search and Explore", - ), - "general": MessageLookupByLibrary.simpleMessage("General"), - "help": MessageLookupByLibrary.simpleMessage("Help"), - "home": MessageLookupByLibrary.simpleMessage("Home"), - "homeBookContinueListening": MessageLookupByLibrary.simpleMessage( - "Continue Listening", - ), - "homeBookContinueListeningDescription": - MessageLookupByLibrary.simpleMessage( + "account": MessageLookupByLibrary.simpleMessage("Account"), + "accountAddNewServer": MessageLookupByLibrary.simpleMessage( + "Add New Server", + ), + "accountAddUser": MessageLookupByLibrary.simpleMessage("Add User"), + "accountAddUserDialog": m0, + "accountAddUserSuccessDialog": MessageLookupByLibrary.simpleMessage( + "User added successfully! Switch?", + ), + "accountAddUserTooltip": MessageLookupByLibrary.simpleMessage( + "Add new server", + ), + "accountAnonymous": MessageLookupByLibrary.simpleMessage("Anonymous"), + "accountDeleteServer": MessageLookupByLibrary.simpleMessage( + "Delete Server", + ), + "accountInvalidURL": + MessageLookupByLibrary.simpleMessage("Invalid URL"), + "accountManage": + MessageLookupByLibrary.simpleMessage("Manage Accounts"), + "accountRegisteredServers": MessageLookupByLibrary.simpleMessage( + "Registered Servers", + ), + "accountRemoveServerAndUsers": MessageLookupByLibrary.simpleMessage( + "Remove Server and Users", + ), + "accountRemoveServerAndUsersHead": MessageLookupByLibrary.simpleMessage( + "This will remove the server ", + ), + "accountRemoveServerAndUsersTail": MessageLookupByLibrary.simpleMessage( + " and all its users\' login info from this app.", + ), + "accountRemoveUserLogin": MessageLookupByLibrary.simpleMessage( + "Remove User Login", + ), + "accountRemoveUserLoginHead": MessageLookupByLibrary.simpleMessage( + "This will remove login details of the user ", + ), + "accountRemoveUserLoginTail": MessageLookupByLibrary.simpleMessage( + " from this app.", + ), + "accountServerURI": MessageLookupByLibrary.simpleMessage("Server URI"), + "accountSwitch": MessageLookupByLibrary.simpleMessage("Switch Account"), + "accountUsersCount": m1, + "appSettings": MessageLookupByLibrary.simpleMessage("App Settings"), + "appearance": MessageLookupByLibrary.simpleMessage("Appearance"), + "autoSleepTimerSettings": MessageLookupByLibrary.simpleMessage( + "Auto Sleep Timer Settings", + ), + "autoTurnOnSleepTimer": MessageLookupByLibrary.simpleMessage( + "Auto Turn On Sleep Timer", + ), + "autoTurnOnTimer": MessageLookupByLibrary.simpleMessage( + "Auto Turn On Timer", + ), + "autoTurnOnTimerAlways": MessageLookupByLibrary.simpleMessage( + "Always Auto Turn On Timer", + ), + "autoTurnOnTimerAlwaysDescription": + MessageLookupByLibrary.simpleMessage( + "Always turn on the sleep timer, no matter what", + ), + "autoTurnOnTimerDescription": MessageLookupByLibrary.simpleMessage( + "Automatically turn on the sleep timer based on the time of day", + ), + "autoTurnOnTimerFrom": MessageLookupByLibrary.simpleMessage("From"), + "autoTurnOnTimerFromDescription": MessageLookupByLibrary.simpleMessage( + "Turn on the sleep timer at the specified time", + ), + "autoTurnOnTimerUntil": MessageLookupByLibrary.simpleMessage("Until"), + "autoTurnOnTimerUntilDescription": MessageLookupByLibrary.simpleMessage( + "Turn off the sleep timer at the specified time", + ), + "automaticallyDescription": MessageLookupByLibrary.simpleMessage( + "Automatically turn on the sleep timer based on the time of day", + ), + "backup": MessageLookupByLibrary.simpleMessage("Backup"), + "backupAndRestore": MessageLookupByLibrary.simpleMessage( + "Backup and Restore", + ), + "bookAbout": MessageLookupByLibrary.simpleMessage("About the Book"), + "bookAboutDefault": MessageLookupByLibrary.simpleMessage( + "Sorry, no description found", + ), + "bookAuthors": MessageLookupByLibrary.simpleMessage("Authors"), + "bookDownloads": MessageLookupByLibrary.simpleMessage("Downloads"), + "bookGenres": MessageLookupByLibrary.simpleMessage("Genres"), + "bookMetadataAbridged": + MessageLookupByLibrary.simpleMessage("Abridged"), + "bookMetadataLength": MessageLookupByLibrary.simpleMessage("Length"), + "bookMetadataPublished": + MessageLookupByLibrary.simpleMessage("Published"), + "bookMetadataUnabridged": MessageLookupByLibrary.simpleMessage( + "Unabridged", + ), + "bookSeries": MessageLookupByLibrary.simpleMessage("Series"), + "bookShelveEmpty": MessageLookupByLibrary.simpleMessage("Try again"), + "bookShelveEmptyText": MessageLookupByLibrary.simpleMessage( + "No shelves to display", + ), + "cancel": MessageLookupByLibrary.simpleMessage("Cancel"), + "chapterNotFound": MessageLookupByLibrary.simpleMessage("Chapters"), + "chapterSelect": MessageLookupByLibrary.simpleMessage("Select Chapter"), + "chapterSkip": MessageLookupByLibrary.simpleMessage( + "Skip chapter opening and ending", + ), + "chapterSkipEnd": MessageLookupByLibrary.simpleMessage( + "Skip chapter opening for ", + ), + "chapterSkipOpen": MessageLookupByLibrary.simpleMessage( + "Skip chapter opening for ", + ), + "chapters": MessageLookupByLibrary.simpleMessage("Chapters"), + "copyToClipboard": MessageLookupByLibrary.simpleMessage( + "Copy to Clipboard", + ), + "copyToClipboardDescription": MessageLookupByLibrary.simpleMessage( + "Copy the app settings to the clipboard", + ), + "copyToClipboardToast": MessageLookupByLibrary.simpleMessage( + "Settings copied to clipboard", + ), + "delete": MessageLookupByLibrary.simpleMessage("Delete"), + "deleteDialog": m2, + "deleted": m3, + "explore": MessageLookupByLibrary.simpleMessage("explore"), + "exploreHint": MessageLookupByLibrary.simpleMessage( + "Seek and you shall discover...", + ), + "exploreTooltip": MessageLookupByLibrary.simpleMessage( + "Search and Explore", + ), + "general": MessageLookupByLibrary.simpleMessage("General"), + "help": MessageLookupByLibrary.simpleMessage("Help"), + "home": MessageLookupByLibrary.simpleMessage("Home"), + "homeBookContinueListening": MessageLookupByLibrary.simpleMessage( + "Continue Listening", + ), + "homeBookContinueListeningDescription": + MessageLookupByLibrary.simpleMessage( "Show play button for books in currently listening shelf", ), - "homeBookContinueSeries": MessageLookupByLibrary.simpleMessage( - "Continue Series", - ), - "homeBookContinueSeriesDescription": MessageLookupByLibrary.simpleMessage( - "Show play button for books in continue series shelf", - ), - "homeBookDiscover": MessageLookupByLibrary.simpleMessage("Discover"), - "homeBookListenAgain": MessageLookupByLibrary.simpleMessage("Listen Again"), - "homeBookListenAgainDescription": MessageLookupByLibrary.simpleMessage( - "Show play button for all books in listen again shelf", - ), - "homeBookNewestAuthors": MessageLookupByLibrary.simpleMessage( - "Newest Authors", - ), - "homeBookRecentlyAdded": MessageLookupByLibrary.simpleMessage( - "Recently Added", - ), - "homeBookRecommended": MessageLookupByLibrary.simpleMessage("Recommended"), - "homeContinueListening": MessageLookupByLibrary.simpleMessage( - "Continue Listening", - ), - "homeListenAgain": MessageLookupByLibrary.simpleMessage("Listen Again"), - "homePageSettings": MessageLookupByLibrary.simpleMessage( - "Home Page Settings", - ), - "homePageSettingsDescription": MessageLookupByLibrary.simpleMessage( - "Customize the home page", - ), - "homePageSettingsOtherShelves": MessageLookupByLibrary.simpleMessage( - "Other shelves", - ), - "homePageSettingsOtherShelvesDescription": - MessageLookupByLibrary.simpleMessage( + "homeBookContinueSeries": MessageLookupByLibrary.simpleMessage( + "Continue Series", + ), + "homeBookContinueSeriesDescription": + MessageLookupByLibrary.simpleMessage( + "Show play button for books in continue series shelf", + ), + "homeBookDiscover": MessageLookupByLibrary.simpleMessage("Discover"), + "homeBookListenAgain": + MessageLookupByLibrary.simpleMessage("Listen Again"), + "homeBookListenAgainDescription": MessageLookupByLibrary.simpleMessage( + "Show play button for all books in listen again shelf", + ), + "homeBookNewestAuthors": MessageLookupByLibrary.simpleMessage( + "Newest Authors", + ), + "homeBookRecentlyAdded": MessageLookupByLibrary.simpleMessage( + "Recently Added", + ), + "homeBookRecommended": + MessageLookupByLibrary.simpleMessage("Recommended"), + "homeContinueListening": MessageLookupByLibrary.simpleMessage( + "Continue Listening", + ), + "homeListenAgain": MessageLookupByLibrary.simpleMessage("Listen Again"), + "homePageSettings": MessageLookupByLibrary.simpleMessage( + "Home Page Settings", + ), + "homePageSettingsDescription": MessageLookupByLibrary.simpleMessage( + "Customize the home page", + ), + "homePageSettingsOtherShelves": MessageLookupByLibrary.simpleMessage( + "Other shelves", + ), + "homePageSettingsOtherShelvesDescription": + MessageLookupByLibrary.simpleMessage( "Show play button for all books in all remaining shelves", ), - "homePageSettingsQuickPlay": MessageLookupByLibrary.simpleMessage( - "Quick Play", - ), - "homeStartListening": MessageLookupByLibrary.simpleMessage( - "Start Listening", - ), - "language": MessageLookupByLibrary.simpleMessage("Language"), - "languageDescription": MessageLookupByLibrary.simpleMessage( - "Language switch", - ), - "library": MessageLookupByLibrary.simpleMessage("Library"), - "libraryChange": MessageLookupByLibrary.simpleMessage("Change Library"), - "libraryEmpty": MessageLookupByLibrary.simpleMessage( - "No libraries available.", - ), - "libraryLoadError": m4, - "librarySelect": MessageLookupByLibrary.simpleMessage("Select Library"), - "librarySwitchTooltip": MessageLookupByLibrary.simpleMessage( - "Switch Library", - ), - "libraryTooltip": MessageLookupByLibrary.simpleMessage( - "Browse your library", - ), - "loading": MessageLookupByLibrary.simpleMessage("Loading..."), - "loginLocal": MessageLookupByLibrary.simpleMessage("Local"), - "loginLogin": MessageLookupByLibrary.simpleMessage("Login"), - "loginOpenID": MessageLookupByLibrary.simpleMessage("OpenID"), - "loginPassword": MessageLookupByLibrary.simpleMessage("Password"), - "loginServerClick": MessageLookupByLibrary.simpleMessage("Click here"), - "loginServerConnected": MessageLookupByLibrary.simpleMessage( - "Server connected, please login", - ), - "loginServerNo": MessageLookupByLibrary.simpleMessage( - "Do not have a server? ", - ), - "loginServerNoConnected": MessageLookupByLibrary.simpleMessage( - "Please enter the URL of your AudiobookShelf Server", - ), - "loginServerNot": m5, - "loginServerTo": MessageLookupByLibrary.simpleMessage( - " to know how to setup a server.", - ), - "loginTitle": m6, - "loginToken": MessageLookupByLibrary.simpleMessage("Token"), - "loginUsername": MessageLookupByLibrary.simpleMessage("Username"), - "logs": MessageLookupByLibrary.simpleMessage("Logs"), - "nmpSettingsBackward": MessageLookupByLibrary.simpleMessage( - "Backward Interval", - ), - "nmpSettingsForward": MessageLookupByLibrary.simpleMessage( - "Forward Interval", - ), - "nmpSettingsMediaControls": MessageLookupByLibrary.simpleMessage( - "Media Controls", - ), - "nmpSettingsMediaControlsDescription": MessageLookupByLibrary.simpleMessage( - "Select the media controls to display", - ), - "nmpSettingsSelectOne": MessageLookupByLibrary.simpleMessage( - "Select a field below to insert it", - ), - "nmpSettingsShowChapterProgress": MessageLookupByLibrary.simpleMessage( - "Show Chapter Progress", - ), - "nmpSettingsShowChapterProgressDescription": - MessageLookupByLibrary.simpleMessage( + "homePageSettingsQuickPlay": MessageLookupByLibrary.simpleMessage( + "Quick Play", + ), + "homeStartListening": MessageLookupByLibrary.simpleMessage( + "Start Listening", + ), + "language": MessageLookupByLibrary.simpleMessage("Language"), + "languageDescription": MessageLookupByLibrary.simpleMessage( + "Language switch", + ), + "library": MessageLookupByLibrary.simpleMessage("Library"), + "libraryChange": MessageLookupByLibrary.simpleMessage("Change Library"), + "libraryEmpty": MessageLookupByLibrary.simpleMessage( + "No libraries available.", + ), + "libraryLoadError": m4, + "librarySelect": MessageLookupByLibrary.simpleMessage("Select Library"), + "librarySwitchTooltip": MessageLookupByLibrary.simpleMessage( + "Switch Library", + ), + "libraryTooltip": MessageLookupByLibrary.simpleMessage( + "Browse your library", + ), + "loading": MessageLookupByLibrary.simpleMessage("Loading..."), + "loginLocal": MessageLookupByLibrary.simpleMessage("Local"), + "loginLogin": MessageLookupByLibrary.simpleMessage("Login"), + "loginOpenID": MessageLookupByLibrary.simpleMessage("OpenID"), + "loginPassword": MessageLookupByLibrary.simpleMessage("Password"), + "loginServerClick": MessageLookupByLibrary.simpleMessage("Click here"), + "loginServerConnected": MessageLookupByLibrary.simpleMessage( + "Server connected, please login", + ), + "loginServerNo": MessageLookupByLibrary.simpleMessage( + "Do not have a server? ", + ), + "loginServerNoConnected": MessageLookupByLibrary.simpleMessage( + "Please enter the URL of your AudiobookShelf Server", + ), + "loginServerNot": m5, + "loginServerTo": MessageLookupByLibrary.simpleMessage( + " to know how to setup a server.", + ), + "loginTitle": m6, + "loginToken": MessageLookupByLibrary.simpleMessage("Token"), + "loginUsername": MessageLookupByLibrary.simpleMessage("Username"), + "logs": MessageLookupByLibrary.simpleMessage("Logs"), + "nmpSettingsBackward": MessageLookupByLibrary.simpleMessage( + "Backward Interval", + ), + "nmpSettingsForward": MessageLookupByLibrary.simpleMessage( + "Forward Interval", + ), + "nmpSettingsMediaControls": MessageLookupByLibrary.simpleMessage( + "Media Controls", + ), + "nmpSettingsMediaControlsDescription": + MessageLookupByLibrary.simpleMessage( + "Select the media controls to display", + ), + "nmpSettingsSelectOne": MessageLookupByLibrary.simpleMessage( + "Select a field below to insert it", + ), + "nmpSettingsShowChapterProgress": MessageLookupByLibrary.simpleMessage( + "Show Chapter Progress", + ), + "nmpSettingsShowChapterProgressDescription": + MessageLookupByLibrary.simpleMessage( "Instead of the overall progress of the book", ), - "nmpSettingsSubTitle": MessageLookupByLibrary.simpleMessage( - "Secondary Title", - ), - "nmpSettingsSubTitleDescription": MessageLookupByLibrary.simpleMessage( - "The subtitle of the notification\n", - ), - "nmpSettingsTitle": MessageLookupByLibrary.simpleMessage("Primary Title"), - "nmpSettingsTitleDescription": MessageLookupByLibrary.simpleMessage( - "The title of the notification\n", - ), - "no": MessageLookupByLibrary.simpleMessage("No"), - "notImplemented": MessageLookupByLibrary.simpleMessage("Not implemented"), - "notificationMediaPlayer": MessageLookupByLibrary.simpleMessage( - "Notification Media Player", - ), - "notificationMediaPlayerDescription": MessageLookupByLibrary.simpleMessage( - "Customize the media player in notifications", - ), - "ok": MessageLookupByLibrary.simpleMessage("OK"), - "pause": MessageLookupByLibrary.simpleMessage("Pause"), - "play": MessageLookupByLibrary.simpleMessage("Play"), - "playerSettings": MessageLookupByLibrary.simpleMessage("Player Settings"), - "playerSettingsCompleteTime": MessageLookupByLibrary.simpleMessage( - "Mark Complete When Time Left", - ), - "playerSettingsCompleteTimeDescriptionHead": - MessageLookupByLibrary.simpleMessage("Mark complete when less than "), - "playerSettingsCompleteTimeDescriptionTail": - MessageLookupByLibrary.simpleMessage(" left in the book"), - "playerSettingsDescription": MessageLookupByLibrary.simpleMessage( - "Customize the player settings", - ), - "playerSettingsDisplay": MessageLookupByLibrary.simpleMessage( - "Display Settings", - ), - "playerSettingsDisplayChapterProgress": - MessageLookupByLibrary.simpleMessage("Show Chapter Progress"), - "playerSettingsDisplayChapterProgressDescription": - MessageLookupByLibrary.simpleMessage( + "nmpSettingsSubTitle": MessageLookupByLibrary.simpleMessage( + "Secondary Title", + ), + "nmpSettingsSubTitleDescription": MessageLookupByLibrary.simpleMessage( + "The subtitle of the notification\n", + ), + "nmpSettingsTitle": + MessageLookupByLibrary.simpleMessage("Primary Title"), + "nmpSettingsTitleDescription": MessageLookupByLibrary.simpleMessage( + "The title of the notification\n", + ), + "no": MessageLookupByLibrary.simpleMessage("No"), + "notImplemented": + MessageLookupByLibrary.simpleMessage("Not implemented"), + "notificationMediaPlayer": MessageLookupByLibrary.simpleMessage( + "Notification Media Player", + ), + "notificationMediaPlayerDescription": + MessageLookupByLibrary.simpleMessage( + "Customize the media player in notifications", + ), + "ok": MessageLookupByLibrary.simpleMessage("OK"), + "pause": MessageLookupByLibrary.simpleMessage("Pause"), + "play": MessageLookupByLibrary.simpleMessage("Play"), + "playerSettings": + MessageLookupByLibrary.simpleMessage("Player Settings"), + "playerSettingsCompleteTime": MessageLookupByLibrary.simpleMessage( + "Mark Complete When Time Left", + ), + "playerSettingsCompleteTimeDescriptionHead": + MessageLookupByLibrary.simpleMessage( + "Mark complete when less than "), + "playerSettingsCompleteTimeDescriptionTail": + MessageLookupByLibrary.simpleMessage(" left in the book"), + "playerSettingsDescription": MessageLookupByLibrary.simpleMessage( + "Customize the player settings", + ), + "playerSettingsDisplay": MessageLookupByLibrary.simpleMessage( + "Display Settings", + ), + "playerSettingsDisplayChapterProgress": + MessageLookupByLibrary.simpleMessage("Show Chapter Progress"), + "playerSettingsDisplayChapterProgressDescription": + MessageLookupByLibrary.simpleMessage( "Show the progress of the current chapter in the player", ), - "playerSettingsDisplayTotalProgress": MessageLookupByLibrary.simpleMessage( - "Show Total Progress", - ), - "playerSettingsDisplayTotalProgressDescription": - MessageLookupByLibrary.simpleMessage( + "playerSettingsDisplayTotalProgress": + MessageLookupByLibrary.simpleMessage( + "Show Total Progress", + ), + "playerSettingsDisplayTotalProgressDescription": + MessageLookupByLibrary.simpleMessage( "Show the total progress of the book in the player", ), - "playerSettingsPlaybackInterval": MessageLookupByLibrary.simpleMessage( - "Playback Report Interval", - ), - "playerSettingsPlaybackIntervalDescriptionHead": - MessageLookupByLibrary.simpleMessage("Report progress every "), - "playerSettingsPlaybackIntervalDescriptionTail": - MessageLookupByLibrary.simpleMessage(" to the server"), - "playerSettingsPlaybackReporting": MessageLookupByLibrary.simpleMessage( - "Playback Reporting", - ), - "playerSettingsPlaybackReportingIgnore": - MessageLookupByLibrary.simpleMessage( + "playerSettingsPlaybackInterval": MessageLookupByLibrary.simpleMessage( + "Playback Report Interval", + ), + "playerSettingsPlaybackIntervalDescriptionHead": + MessageLookupByLibrary.simpleMessage("Report progress every "), + "playerSettingsPlaybackIntervalDescriptionTail": + MessageLookupByLibrary.simpleMessage(" to the server"), + "playerSettingsPlaybackReporting": MessageLookupByLibrary.simpleMessage( + "Playback Reporting", + ), + "playerSettingsPlaybackReportingIgnore": + MessageLookupByLibrary.simpleMessage( "Ignore Playback Position Less Than", ), - "playerSettingsPlaybackReportingMinimum": - MessageLookupByLibrary.simpleMessage("Minimum Position to Report"), - "playerSettingsPlaybackReportingMinimumDescriptionHead": - MessageLookupByLibrary.simpleMessage( + "playerSettingsPlaybackReportingMinimum": + MessageLookupByLibrary.simpleMessage("Minimum Position to Report"), + "playerSettingsPlaybackReportingMinimumDescriptionHead": + MessageLookupByLibrary.simpleMessage( "Do not report playback for the first ", ), - "playerSettingsPlaybackReportingMinimumDescriptionTail": - MessageLookupByLibrary.simpleMessage("of the book"), - "playerSettingsRememberForEveryBook": MessageLookupByLibrary.simpleMessage( - "Remember Player Settings for Every Book", - ), - "playerSettingsRememberForEveryBookDescription": - MessageLookupByLibrary.simpleMessage( + "playerSettingsPlaybackReportingMinimumDescriptionTail": + MessageLookupByLibrary.simpleMessage("of the book"), + "playerSettingsRememberForEveryBook": + MessageLookupByLibrary.simpleMessage( + "Remember Player Settings for Every Book", + ), + "playerSettingsRememberForEveryBookDescription": + MessageLookupByLibrary.simpleMessage( "Settings like speed, loudness, etc. will be remembered for every book", ), - "playerSettingsSpeed": MessageLookupByLibrary.simpleMessage("Speed"), - "playerSettingsSpeedDefault": MessageLookupByLibrary.simpleMessage( - "Default Speed", - ), - "playerSettingsSpeedOptions": MessageLookupByLibrary.simpleMessage( - "Speed Options", - ), - "playerSettingsSpeedOptionsSelect": MessageLookupByLibrary.simpleMessage( - "Select Speed Options", - ), - "playerSettingsSpeedOptionsSelectAdd": MessageLookupByLibrary.simpleMessage( - "Add Speed Option", - ), - "playerSettingsSpeedOptionsSelectAddHelper": - MessageLookupByLibrary.simpleMessage("Enter a new speed option to add"), - "playerSettingsSpeedSelect": MessageLookupByLibrary.simpleMessage( - "Select Speed", - ), - "playerSettingsSpeedSelectHelper": MessageLookupByLibrary.simpleMessage( - "Enter the speed you want to set when playing for the first time", - ), - "playlistsMine": MessageLookupByLibrary.simpleMessage("My Playlists"), - "readLess": MessageLookupByLibrary.simpleMessage("Read Less"), - "readMore": MessageLookupByLibrary.simpleMessage("Read More"), - "refresh": MessageLookupByLibrary.simpleMessage("Refresh"), - "reset": MessageLookupByLibrary.simpleMessage("Reset"), - "resetAppSettings": MessageLookupByLibrary.simpleMessage( - "Reset App Settings", - ), - "resetAppSettingsDescription": MessageLookupByLibrary.simpleMessage( - "Reset the app settings to the default values", - ), - "resetAppSettingsDialog": MessageLookupByLibrary.simpleMessage( - "Are you sure you want to reset the app settings?", - ), - "restore": MessageLookupByLibrary.simpleMessage("Restore"), - "restoreBackup": MessageLookupByLibrary.simpleMessage("Restore Backup"), - "restoreBackupHint": MessageLookupByLibrary.simpleMessage( - "Paste the backup here", - ), - "restoreBackupInvalid": MessageLookupByLibrary.simpleMessage( - "Invalid backup", - ), - "restoreBackupSuccess": MessageLookupByLibrary.simpleMessage( - "Settings restored", - ), - "restoreBackupValidator": MessageLookupByLibrary.simpleMessage( - "Please paste the backup here", - ), - "restoreDescription": MessageLookupByLibrary.simpleMessage( - "Restore the app settings from the backup", - ), - "resume": MessageLookupByLibrary.simpleMessage("Resume"), - "retry": MessageLookupByLibrary.simpleMessage("Retry"), - "settings": MessageLookupByLibrary.simpleMessage("Settings"), - "shakeAction": MessageLookupByLibrary.simpleMessage("Shake Action"), - "shakeActionDescription": MessageLookupByLibrary.simpleMessage( - "The action to perform when a shake is detected", - ), - "shakeActivationThreshold": MessageLookupByLibrary.simpleMessage( - "Shake Activation Threshold", - ), - "shakeActivationThresholdDescription": MessageLookupByLibrary.simpleMessage( - "The higher the threshold, the harder you need to shake", - ), - "shakeDetector": MessageLookupByLibrary.simpleMessage("Shake Detector"), - "shakeDetectorDescription": MessageLookupByLibrary.simpleMessage( - "Customize the shake detector settings", - ), - "shakeDetectorEnable": MessageLookupByLibrary.simpleMessage( - "Enable Shake Detection", - ), - "shakeDetectorEnableDescription": MessageLookupByLibrary.simpleMessage( - "Enable shake detection to do various actions", - ), - "shakeDetectorSettings": MessageLookupByLibrary.simpleMessage( - "Shake Detector Settings", - ), - "shakeFeedback": MessageLookupByLibrary.simpleMessage("Shake Feedback"), - "shakeFeedbackDescription": MessageLookupByLibrary.simpleMessage( - "The feedback to give when a shake is detected", - ), - "shakeSelectAction": MessageLookupByLibrary.simpleMessage( - "Select Shake Action", - ), - "shakeSelectActivationThreshold": MessageLookupByLibrary.simpleMessage( - "Select Shake Activation Threshold", - ), - "shakeSelectActivationThresholdHelper": - MessageLookupByLibrary.simpleMessage( + "playerSettingsSpeed": MessageLookupByLibrary.simpleMessage("Speed"), + "playerSettingsSpeedDefault": MessageLookupByLibrary.simpleMessage( + "Default Speed", + ), + "playerSettingsSpeedOptions": MessageLookupByLibrary.simpleMessage( + "Speed Options", + ), + "playerSettingsSpeedOptionsSelect": + MessageLookupByLibrary.simpleMessage( + "Select Speed Options", + ), + "playerSettingsSpeedOptionsSelectAdd": + MessageLookupByLibrary.simpleMessage( + "Add Speed Option", + ), + "playerSettingsSpeedOptionsSelectAddHelper": + MessageLookupByLibrary.simpleMessage( + "Enter a new speed option to add"), + "playerSettingsSpeedSelect": MessageLookupByLibrary.simpleMessage( + "Select Speed", + ), + "playerSettingsSpeedSelectHelper": MessageLookupByLibrary.simpleMessage( + "Enter the speed you want to set when playing for the first time", + ), + "playlistsMine": MessageLookupByLibrary.simpleMessage("My Playlists"), + "readLess": MessageLookupByLibrary.simpleMessage("Read Less"), + "readMore": MessageLookupByLibrary.simpleMessage("Read More"), + "refresh": MessageLookupByLibrary.simpleMessage("Refresh"), + "reset": MessageLookupByLibrary.simpleMessage("Reset"), + "resetAppSettings": MessageLookupByLibrary.simpleMessage( + "Reset App Settings", + ), + "resetAppSettingsDescription": MessageLookupByLibrary.simpleMessage( + "Reset the app settings to the default values", + ), + "resetAppSettingsDialog": MessageLookupByLibrary.simpleMessage( + "Are you sure you want to reset the app settings?", + ), + "restore": MessageLookupByLibrary.simpleMessage("Restore"), + "restoreBackup": MessageLookupByLibrary.simpleMessage("Restore Backup"), + "restoreBackupHint": MessageLookupByLibrary.simpleMessage( + "Paste the backup here", + ), + "restoreBackupInvalid": MessageLookupByLibrary.simpleMessage( + "Invalid backup", + ), + "restoreBackupSuccess": MessageLookupByLibrary.simpleMessage( + "Settings restored", + ), + "restoreBackupValidator": MessageLookupByLibrary.simpleMessage( + "Please paste the backup here", + ), + "restoreDescription": MessageLookupByLibrary.simpleMessage( + "Restore the app settings from the backup", + ), + "resume": MessageLookupByLibrary.simpleMessage("Resume"), + "retry": MessageLookupByLibrary.simpleMessage("Retry"), + "settings": MessageLookupByLibrary.simpleMessage("Settings"), + "shakeAction": MessageLookupByLibrary.simpleMessage("Shake Action"), + "shakeActionDescription": MessageLookupByLibrary.simpleMessage( + "The action to perform when a shake is detected", + ), + "shakeActivationThreshold": MessageLookupByLibrary.simpleMessage( + "Shake Activation Threshold", + ), + "shakeActivationThresholdDescription": + MessageLookupByLibrary.simpleMessage( + "The higher the threshold, the harder you need to shake", + ), + "shakeDetector": MessageLookupByLibrary.simpleMessage("Shake Detector"), + "shakeDetectorDescription": MessageLookupByLibrary.simpleMessage( + "Customize the shake detector settings", + ), + "shakeDetectorEnable": MessageLookupByLibrary.simpleMessage( + "Enable Shake Detection", + ), + "shakeDetectorEnableDescription": MessageLookupByLibrary.simpleMessage( + "Enable shake detection to do various actions", + ), + "shakeDetectorSettings": MessageLookupByLibrary.simpleMessage( + "Shake Detector Settings", + ), + "shakeFeedback": MessageLookupByLibrary.simpleMessage("Shake Feedback"), + "shakeFeedbackDescription": MessageLookupByLibrary.simpleMessage( + "The feedback to give when a shake is detected", + ), + "shakeSelectAction": MessageLookupByLibrary.simpleMessage( + "Select Shake Action", + ), + "shakeSelectActivationThreshold": MessageLookupByLibrary.simpleMessage( + "Select Shake Activation Threshold", + ), + "shakeSelectActivationThresholdHelper": + MessageLookupByLibrary.simpleMessage( "Enter a number to set the threshold in m/s²", ), - "shakeSelectFeedback": MessageLookupByLibrary.simpleMessage( - "Select Shake Feedback", - ), - "themeMode": MessageLookupByLibrary.simpleMessage("Theme Mode"), - "themeModeDark": MessageLookupByLibrary.simpleMessage("Dark"), - "themeModeHighContrast": MessageLookupByLibrary.simpleMessage( - "High Contrast Mode", - ), - "themeModeHighContrastDescription": MessageLookupByLibrary.simpleMessage( - "Increase the contrast between the background and the text", - ), - "themeModeLight": MessageLookupByLibrary.simpleMessage("Light"), - "themeModeSystem": MessageLookupByLibrary.simpleMessage("System"), - "themeSettings": MessageLookupByLibrary.simpleMessage("Theme Settings"), - "themeSettingsColors": MessageLookupByLibrary.simpleMessage( - "Material Theme from System", - ), - "themeSettingsColorsAndroid": MessageLookupByLibrary.simpleMessage( - "Use Material You", - ), - "themeSettingsColorsBook": MessageLookupByLibrary.simpleMessage( - "Adaptive Theme on Item Page", - ), - "themeSettingsColorsBookDescription": MessageLookupByLibrary.simpleMessage( - "Get fancy with the colors on the item page at the cost of some performance", - ), - "themeSettingsColorsCurrent": MessageLookupByLibrary.simpleMessage( - "Adapt theme from currently playing item", - ), - "themeSettingsColorsCurrentDescription": - MessageLookupByLibrary.simpleMessage( + "shakeSelectFeedback": MessageLookupByLibrary.simpleMessage( + "Select Shake Feedback", + ), + "themeMode": MessageLookupByLibrary.simpleMessage("Theme Mode"), + "themeModeDark": MessageLookupByLibrary.simpleMessage("Dark"), + "themeModeHighContrast": MessageLookupByLibrary.simpleMessage( + "High Contrast Mode", + ), + "themeModeHighContrastDescription": + MessageLookupByLibrary.simpleMessage( + "Increase the contrast between the background and the text", + ), + "themeModeLight": MessageLookupByLibrary.simpleMessage("Light"), + "themeModeSystem": MessageLookupByLibrary.simpleMessage("System"), + "themeSettings": MessageLookupByLibrary.simpleMessage("Theme Settings"), + "themeSettingsColors": MessageLookupByLibrary.simpleMessage( + "Material Theme from System", + ), + "themeSettingsColorsAndroid": MessageLookupByLibrary.simpleMessage( + "Use Material You", + ), + "themeSettingsColorsBook": MessageLookupByLibrary.simpleMessage( + "Adaptive Theme on Item Page", + ), + "themeSettingsColorsBookDescription": + MessageLookupByLibrary.simpleMessage( + "Get fancy with the colors on the item page at the cost of some performance", + ), + "themeSettingsColorsCurrent": MessageLookupByLibrary.simpleMessage( + "Adapt theme from currently playing item", + ), + "themeSettingsColorsCurrentDescription": + MessageLookupByLibrary.simpleMessage( "Use the theme colors from the currently playing item for the app", ), - "themeSettingsColorsDescription": MessageLookupByLibrary.simpleMessage( - "Use the system theme colors for the app", - ), - "themeSettingsDescription": MessageLookupByLibrary.simpleMessage( - "Customize the app theme", - ), - "timeSecond": m7, - "unknown": MessageLookupByLibrary.simpleMessage("Unknown"), - "webVersion": MessageLookupByLibrary.simpleMessage("Web Version"), - "yes": MessageLookupByLibrary.simpleMessage("Yes"), - "you": MessageLookupByLibrary.simpleMessage("You"), - "youTooltip": MessageLookupByLibrary.simpleMessage( - "Your Profile and Settings", - ), - }; + "themeSettingsColorsDescription": MessageLookupByLibrary.simpleMessage( + "Use the system theme colors for the app", + ), + "themeSettingsDescription": MessageLookupByLibrary.simpleMessage( + "Customize the app theme", + ), + "timeSecond": m7, + "unknown": MessageLookupByLibrary.simpleMessage("Unknown"), + "webVersion": MessageLookupByLibrary.simpleMessage("Web Version"), + "yes": MessageLookupByLibrary.simpleMessage("Yes"), + "you": MessageLookupByLibrary.simpleMessage("You"), + "youTooltip": MessageLookupByLibrary.simpleMessage( + "Your Profile and Settings", + ), + }; } diff --git a/lib/generated/intl/messages_zh.dart b/lib/generated/intl/messages_zh.dart index 5de2d92..480a87b 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -38,325 +38,354 @@ class MessageLookup extends MessageLookupByLibrary { final messages = _notInlinedMessages(_notInlinedMessages); static Map _notInlinedMessages(_) => { - "account": MessageLookupByLibrary.simpleMessage("账户"), - "accountAddNewServer": MessageLookupByLibrary.simpleMessage("添加新服务器"), - "accountAddUser": MessageLookupByLibrary.simpleMessage("添加用户"), - "accountAddUserDialog": m0, - "accountAddUserSuccessDialog": MessageLookupByLibrary.simpleMessage( - "用户添加成功!切换?", - ), - "accountAddUserTooltip": MessageLookupByLibrary.simpleMessage("添加新服务器"), - "accountAnonymous": MessageLookupByLibrary.simpleMessage("匿名"), - "accountDeleteServer": MessageLookupByLibrary.simpleMessage("删除服务器"), - "accountInvalidURL": MessageLookupByLibrary.simpleMessage("无效网址"), - "accountManage": MessageLookupByLibrary.simpleMessage("帐户管理"), - "accountRegisteredServers": MessageLookupByLibrary.simpleMessage("已注册服务器"), - "accountRemoveServerAndUsers": MessageLookupByLibrary.simpleMessage( - "删除服务器和用户", - ), - "accountRemoveServerAndUsersHead": MessageLookupByLibrary.simpleMessage( - "这将删除服务器 ", - ), - "accountRemoveServerAndUsersTail": MessageLookupByLibrary.simpleMessage( - " 以及该应用程序中所有用户的登录信息。", - ), - "accountRemoveUserLogin": MessageLookupByLibrary.simpleMessage("删除用户登录"), - "accountRemoveUserLoginHead": MessageLookupByLibrary.simpleMessage( - "这将删除用户 ", - ), - "accountRemoveUserLoginTail": MessageLookupByLibrary.simpleMessage( - " 的登录详细信息。", - ), - "accountServerURI": MessageLookupByLibrary.simpleMessage("服务器地址"), - "accountSwitch": MessageLookupByLibrary.simpleMessage("切换账户"), - "accountUsersCount": m1, - "appSettings": MessageLookupByLibrary.simpleMessage("应用设置"), - "appearance": MessageLookupByLibrary.simpleMessage("外观"), - "autoSleepTimerSettings": MessageLookupByLibrary.simpleMessage("自动睡眠定时器设置"), - "autoTurnOnSleepTimer": MessageLookupByLibrary.simpleMessage("自动开启睡眠定时器"), - "autoTurnOnTimer": MessageLookupByLibrary.simpleMessage("自动开启定时器"), - "autoTurnOnTimerAlways": MessageLookupByLibrary.simpleMessage("始终自动开启定时器"), - "autoTurnOnTimerAlwaysDescription": MessageLookupByLibrary.simpleMessage( - "总是打开睡眠定时器", - ), - "autoTurnOnTimerDescription": MessageLookupByLibrary.simpleMessage( - "根据一天中的时间自动打开睡眠定时器", - ), - "autoTurnOnTimerFrom": MessageLookupByLibrary.simpleMessage("从"), - "autoTurnOnTimerFromDescription": MessageLookupByLibrary.simpleMessage( - "在指定时间打开睡眠定时器", - ), - "autoTurnOnTimerUntil": MessageLookupByLibrary.simpleMessage("直到"), - "autoTurnOnTimerUntilDescription": MessageLookupByLibrary.simpleMessage( - "在指定时间关闭睡眠定时器", - ), - "automaticallyDescription": MessageLookupByLibrary.simpleMessage( - "根据一天中的时间自动打开睡眠定时器", - ), - "backup": MessageLookupByLibrary.simpleMessage("备份"), - "backupAndRestore": MessageLookupByLibrary.simpleMessage("备份与恢复"), - "bookAbout": MessageLookupByLibrary.simpleMessage("关于本书"), - "bookAboutDefault": MessageLookupByLibrary.simpleMessage("抱歉,找不到描述"), - "bookAuthors": MessageLookupByLibrary.simpleMessage("作者"), - "bookDownloads": MessageLookupByLibrary.simpleMessage("下载"), - "bookGenres": MessageLookupByLibrary.simpleMessage("风格"), - "bookMetadataAbridged": MessageLookupByLibrary.simpleMessage("删节版"), - "bookMetadataLength": MessageLookupByLibrary.simpleMessage("持续时间"), - "bookMetadataPublished": MessageLookupByLibrary.simpleMessage("发布年份"), - "bookMetadataUnabridged": MessageLookupByLibrary.simpleMessage("未删节版"), - "bookSeries": MessageLookupByLibrary.simpleMessage("系列"), - "bookShelveEmpty": MessageLookupByLibrary.simpleMessage("重试"), - "bookShelveEmptyText": MessageLookupByLibrary.simpleMessage("未查询到书架"), - "cancel": MessageLookupByLibrary.simpleMessage("取消"), - "chapterNotFound": MessageLookupByLibrary.simpleMessage("未找到章节"), - "chapterSelect": MessageLookupByLibrary.simpleMessage("选择章节"), - "chapterSkip": MessageLookupByLibrary.simpleMessage("跳过章节片头片尾"), - "chapterSkipEnd": MessageLookupByLibrary.simpleMessage("跳过章节片尾 "), - "chapterSkipOpen": MessageLookupByLibrary.simpleMessage("跳过章节片头 "), - "chapters": MessageLookupByLibrary.simpleMessage("章节列表"), - "copyToClipboard": MessageLookupByLibrary.simpleMessage("复制到剪贴板"), - "copyToClipboardDescription": MessageLookupByLibrary.simpleMessage( - "将应用程序设置复制到剪贴板", - ), - "copyToClipboardToast": MessageLookupByLibrary.simpleMessage("设置已复制到剪贴板"), - "delete": MessageLookupByLibrary.simpleMessage("删除"), - "deleteDialog": m2, - "deleted": m3, - "explore": MessageLookupByLibrary.simpleMessage("探索"), - "exploreHint": MessageLookupByLibrary.simpleMessage("搜索与探索..."), - "exploreTooltip": MessageLookupByLibrary.simpleMessage("搜索和探索"), - "general": MessageLookupByLibrary.simpleMessage("通用"), - "help": MessageLookupByLibrary.simpleMessage("Help"), - "home": MessageLookupByLibrary.simpleMessage("首页"), - "homeBookContinueListening": MessageLookupByLibrary.simpleMessage("继续收听"), - "homeBookContinueListeningDescription": - MessageLookupByLibrary.simpleMessage("继续收听书架上显示播放按钮"), - "homeBookContinueSeries": MessageLookupByLibrary.simpleMessage("继续系列"), - "homeBookContinueSeriesDescription": MessageLookupByLibrary.simpleMessage( - "继续系列书架上显示播放按钮", - ), - "homeBookDiscover": MessageLookupByLibrary.simpleMessage("发现"), - "homeBookListenAgain": MessageLookupByLibrary.simpleMessage("再听一遍"), - "homeBookListenAgainDescription": MessageLookupByLibrary.simpleMessage( - "再听一遍书架上显示播放按钮", - ), - "homeBookNewestAuthors": MessageLookupByLibrary.simpleMessage("最新作者"), - "homeBookRecentlyAdded": MessageLookupByLibrary.simpleMessage("最近添加"), - "homeBookRecommended": MessageLookupByLibrary.simpleMessage("推荐"), - "homeContinueListening": MessageLookupByLibrary.simpleMessage("继续收听"), - "homeListenAgain": MessageLookupByLibrary.simpleMessage("再听一遍"), - "homePageSettings": MessageLookupByLibrary.simpleMessage("主页设置"), - "homePageSettingsDescription": MessageLookupByLibrary.simpleMessage( - "自定义主页", - ), - "homePageSettingsOtherShelves": MessageLookupByLibrary.simpleMessage( - "其他书架", - ), - "homePageSettingsOtherShelvesDescription": - MessageLookupByLibrary.simpleMessage("显示所有剩余书架上所有书籍的播放按钮"), - "homePageSettingsQuickPlay": MessageLookupByLibrary.simpleMessage("继续播放"), - "homeStartListening": MessageLookupByLibrary.simpleMessage("开始收听"), - "language": MessageLookupByLibrary.simpleMessage("语言"), - "languageDescription": MessageLookupByLibrary.simpleMessage("语言切换"), - "library": MessageLookupByLibrary.simpleMessage("媒体库"), - "libraryChange": MessageLookupByLibrary.simpleMessage("更改媒体库"), - "libraryEmpty": MessageLookupByLibrary.simpleMessage("没有可用的库。"), - "libraryLoadError": m4, - "librarySelect": MessageLookupByLibrary.simpleMessage("选择媒体库"), - "librarySwitchTooltip": MessageLookupByLibrary.simpleMessage("切换媒体库"), - "libraryTooltip": MessageLookupByLibrary.simpleMessage("浏览您的媒体库"), - "loading": MessageLookupByLibrary.simpleMessage("加载中..."), - "loginLocal": MessageLookupByLibrary.simpleMessage("Local"), - "loginLogin": MessageLookupByLibrary.simpleMessage("登录"), - "loginOpenID": MessageLookupByLibrary.simpleMessage("OpenID"), - "loginPassword": MessageLookupByLibrary.simpleMessage("密码"), - "loginServerClick": MessageLookupByLibrary.simpleMessage("单击此处"), - "loginServerConnected": MessageLookupByLibrary.simpleMessage("服务器已连接,请登录"), - "loginServerNo": MessageLookupByLibrary.simpleMessage("没有服务器? "), - "loginServerNoConnected": MessageLookupByLibrary.simpleMessage( - "请输入您的AudiobookShelf服务器的URL", - ), - "loginServerNot": m5, - "loginServerTo": MessageLookupByLibrary.simpleMessage(" 了解如何设置服务器。"), - "loginTitle": m6, - "loginToken": MessageLookupByLibrary.simpleMessage("Token"), - "loginUsername": MessageLookupByLibrary.simpleMessage("用户名"), - "logs": MessageLookupByLibrary.simpleMessage("日志"), - "nmpSettingsBackward": MessageLookupByLibrary.simpleMessage("快退间隔"), - "nmpSettingsForward": MessageLookupByLibrary.simpleMessage("快进间隔"), - "nmpSettingsMediaControls": MessageLookupByLibrary.simpleMessage("媒体控制"), - "nmpSettingsMediaControlsDescription": MessageLookupByLibrary.simpleMessage( - "选择要显示的媒体控件", - ), - "nmpSettingsSelectOne": MessageLookupByLibrary.simpleMessage( - "在下面选择一个字段进行插入", - ), - "nmpSettingsShowChapterProgress": MessageLookupByLibrary.simpleMessage( - "显示章节进度", - ), - "nmpSettingsShowChapterProgressDescription": - MessageLookupByLibrary.simpleMessage("而不是本书的整体进展"), - "nmpSettingsSubTitle": MessageLookupByLibrary.simpleMessage("副标题"), - "nmpSettingsSubTitleDescription": MessageLookupByLibrary.simpleMessage( - "通知的副标题\n", - ), - "nmpSettingsTitle": MessageLookupByLibrary.simpleMessage("主标题"), - "nmpSettingsTitleDescription": MessageLookupByLibrary.simpleMessage( - "通知的标题\n", - ), - "no": MessageLookupByLibrary.simpleMessage("否"), - "notImplemented": MessageLookupByLibrary.simpleMessage("未实现"), - "notificationMediaPlayer": MessageLookupByLibrary.simpleMessage("通知媒体播放器"), - "notificationMediaPlayerDescription": MessageLookupByLibrary.simpleMessage( - "在通知中自定义媒体播放器", - ), - "ok": MessageLookupByLibrary.simpleMessage("确定"), - "pause": MessageLookupByLibrary.simpleMessage("暂停"), - "play": MessageLookupByLibrary.simpleMessage("播放"), - "playerSettings": MessageLookupByLibrary.simpleMessage("播放器设置"), - "playerSettingsCompleteTime": MessageLookupByLibrary.simpleMessage( - "剩余时间标记完成", - ), - "playerSettingsCompleteTimeDescriptionHead": - MessageLookupByLibrary.simpleMessage("当书中剩余时间少于 "), - "playerSettingsCompleteTimeDescriptionTail": - MessageLookupByLibrary.simpleMessage(" 时,标记完成"), - "playerSettingsDescription": MessageLookupByLibrary.simpleMessage( - "自定义播放器设置", - ), - "playerSettingsDisplay": MessageLookupByLibrary.simpleMessage("显示设置"), - "playerSettingsDisplayChapterProgress": - MessageLookupByLibrary.simpleMessage("显示章节进度"), - "playerSettingsDisplayChapterProgressDescription": - MessageLookupByLibrary.simpleMessage("在播放器中显示当前章节的进度"), - "playerSettingsDisplayTotalProgress": MessageLookupByLibrary.simpleMessage( - "显示总进度", - ), - "playerSettingsDisplayTotalProgressDescription": - MessageLookupByLibrary.simpleMessage("在播放器中显示当前书籍的总进度"), - "playerSettingsPlaybackInterval": MessageLookupByLibrary.simpleMessage( - "播放报告间隔", - ), - "playerSettingsPlaybackIntervalDescriptionHead": - MessageLookupByLibrary.simpleMessage("每 "), - "playerSettingsPlaybackIntervalDescriptionTail": - MessageLookupByLibrary.simpleMessage(" 向服务器报告一次进度"), - "playerSettingsPlaybackReporting": MessageLookupByLibrary.simpleMessage( - "回放报告", - ), - "playerSettingsPlaybackReportingIgnore": - MessageLookupByLibrary.simpleMessage("忽略播放位置小于"), - "playerSettingsPlaybackReportingMinimum": - MessageLookupByLibrary.simpleMessage("回放报告最小位置"), - "playerSettingsPlaybackReportingMinimumDescriptionHead": - MessageLookupByLibrary.simpleMessage("不要报告本书前 "), - "playerSettingsPlaybackReportingMinimumDescriptionTail": - MessageLookupByLibrary.simpleMessage(" 的播放"), - "playerSettingsRememberForEveryBook": MessageLookupByLibrary.simpleMessage( - "记住每本书的播放器设置", - ), - "playerSettingsRememberForEveryBookDescription": - MessageLookupByLibrary.simpleMessage("每本书都会记住播放速度、音量等设置"), - "playerSettingsSpeed": MessageLookupByLibrary.simpleMessage("播放速度"), - "playerSettingsSpeedDefault": MessageLookupByLibrary.simpleMessage( - "默认播放速度", - ), - "playerSettingsSpeedOptions": MessageLookupByLibrary.simpleMessage( - "播放速度选项", - ), - "playerSettingsSpeedOptionsSelect": MessageLookupByLibrary.simpleMessage( - "播放速度选项", - ), - "playerSettingsSpeedOptionsSelectAdd": MessageLookupByLibrary.simpleMessage( - "添加一个速度选项", - ), - "playerSettingsSpeedOptionsSelectAddHelper": - MessageLookupByLibrary.simpleMessage("输入一个新的速度选项"), - "playerSettingsSpeedSelect": MessageLookupByLibrary.simpleMessage("选择播放速度"), - "playerSettingsSpeedSelectHelper": MessageLookupByLibrary.simpleMessage( - "输入默认的播放速度", - ), - "playlistsMine": MessageLookupByLibrary.simpleMessage("播放列表"), - "readLess": MessageLookupByLibrary.simpleMessage("折叠"), - "readMore": MessageLookupByLibrary.simpleMessage("展开"), - "refresh": MessageLookupByLibrary.simpleMessage("刷新"), - "reset": MessageLookupByLibrary.simpleMessage("重置"), - "resetAppSettings": MessageLookupByLibrary.simpleMessage("重置应用程序设置"), - "resetAppSettingsDescription": MessageLookupByLibrary.simpleMessage( - "将应用程序设置重置为默认值", - ), - "resetAppSettingsDialog": MessageLookupByLibrary.simpleMessage( - "您确定要重置应用程序设置吗?", - ), - "restore": MessageLookupByLibrary.simpleMessage("恢复"), - "restoreBackup": MessageLookupByLibrary.simpleMessage("恢复备份"), - "restoreBackupHint": MessageLookupByLibrary.simpleMessage("将备份粘贴到此处"), - "restoreBackupInvalid": MessageLookupByLibrary.simpleMessage("无效备份"), - "restoreBackupSuccess": MessageLookupByLibrary.simpleMessage("设置已恢复"), - "restoreBackupValidator": MessageLookupByLibrary.simpleMessage("请将备份粘贴到此处"), - "restoreDescription": MessageLookupByLibrary.simpleMessage("从备份中还原应用程序设置"), - "resume": MessageLookupByLibrary.simpleMessage("继续"), - "retry": MessageLookupByLibrary.simpleMessage("重试"), - "settings": MessageLookupByLibrary.simpleMessage("设置"), - "shakeAction": MessageLookupByLibrary.simpleMessage("抖动操作"), - "shakeActionDescription": MessageLookupByLibrary.simpleMessage( - "检测到抖动时要执行的操作", - ), - "shakeActivationThreshold": MessageLookupByLibrary.simpleMessage("抖动激活阈值"), - "shakeActivationThresholdDescription": MessageLookupByLibrary.simpleMessage( - "门槛越高,你就越难摇晃", - ), - "shakeDetector": MessageLookupByLibrary.simpleMessage("抖动检测器"), - "shakeDetectorDescription": MessageLookupByLibrary.simpleMessage( - "自定义抖动检测器设置", - ), - "shakeDetectorEnable": MessageLookupByLibrary.simpleMessage("启用抖动检测"), - "shakeDetectorEnableDescription": MessageLookupByLibrary.simpleMessage( - "启用抖动检测以执行各种操作", - ), - "shakeDetectorSettings": MessageLookupByLibrary.simpleMessage("抖动检测器设置"), - "shakeFeedback": MessageLookupByLibrary.simpleMessage("抖动反馈"), - "shakeFeedbackDescription": MessageLookupByLibrary.simpleMessage( - "检测到抖动时给出的反馈", - ), - "shakeSelectAction": MessageLookupByLibrary.simpleMessage("选择抖动动作"), - "shakeSelectActivationThreshold": MessageLookupByLibrary.simpleMessage( - "选择抖动激活阈值", - ), - "shakeSelectActivationThresholdHelper": - MessageLookupByLibrary.simpleMessage("输入一个数字以m/s²为单位设置阈值"), - "shakeSelectFeedback": MessageLookupByLibrary.simpleMessage("选择抖动反馈"), - "themeMode": MessageLookupByLibrary.simpleMessage("主题模式"), - "themeModeDark": MessageLookupByLibrary.simpleMessage("深色"), - "themeModeHighContrast": MessageLookupByLibrary.simpleMessage("高对比度模式"), - "themeModeHighContrastDescription": MessageLookupByLibrary.simpleMessage( - "增加背景和文本之间的对比度", - ), - "themeModeLight": MessageLookupByLibrary.simpleMessage("浅色"), - "themeModeSystem": MessageLookupByLibrary.simpleMessage("跟随系统"), - "themeSettings": MessageLookupByLibrary.simpleMessage("主题设置"), - "themeSettingsColors": MessageLookupByLibrary.simpleMessage("主题色"), - "themeSettingsColorsAndroid": MessageLookupByLibrary.simpleMessage("主题色"), - "themeSettingsColorsBook": MessageLookupByLibrary.simpleMessage( - "书籍详情页自适应主题", - ), - "themeSettingsColorsBookDescription": MessageLookupByLibrary.simpleMessage( - "以牺牲一些性能为代价,对书籍详情页的颜色进行美化", - ), - "themeSettingsColorsCurrent": MessageLookupByLibrary.simpleMessage( - "根据当前播放的书籍调整主题", - ), - "themeSettingsColorsCurrentDescription": - MessageLookupByLibrary.simpleMessage("使用当前播放书籍的主题颜色"), - "themeSettingsColorsDescription": MessageLookupByLibrary.simpleMessage( - "使用应用程序的系统主题色", - ), - "themeSettingsDescription": MessageLookupByLibrary.simpleMessage("自定义应用主题"), - "timeSecond": m7, - "unknown": MessageLookupByLibrary.simpleMessage("未知"), - "webVersion": MessageLookupByLibrary.simpleMessage("Web版本"), - "yes": MessageLookupByLibrary.simpleMessage("是"), - "you": MessageLookupByLibrary.simpleMessage("我的"), - "youTooltip": MessageLookupByLibrary.simpleMessage("您的个人资料和设置"), - }; + "account": MessageLookupByLibrary.simpleMessage("账户"), + "accountAddNewServer": MessageLookupByLibrary.simpleMessage("添加新服务器"), + "accountAddUser": MessageLookupByLibrary.simpleMessage("添加用户"), + "accountAddUserDialog": m0, + "accountAddUserSuccessDialog": MessageLookupByLibrary.simpleMessage( + "用户添加成功!切换?", + ), + "accountAddUserTooltip": MessageLookupByLibrary.simpleMessage("添加新服务器"), + "accountAnonymous": MessageLookupByLibrary.simpleMessage("匿名"), + "accountDeleteServer": MessageLookupByLibrary.simpleMessage("删除服务器"), + "accountInvalidURL": MessageLookupByLibrary.simpleMessage("无效网址"), + "accountManage": MessageLookupByLibrary.simpleMessage("帐户管理"), + "accountRegisteredServers": + MessageLookupByLibrary.simpleMessage("已注册服务器"), + "accountRemoveServerAndUsers": MessageLookupByLibrary.simpleMessage( + "删除服务器和用户", + ), + "accountRemoveServerAndUsersHead": MessageLookupByLibrary.simpleMessage( + "这将删除服务器 ", + ), + "accountRemoveServerAndUsersTail": MessageLookupByLibrary.simpleMessage( + " 以及该应用程序中所有用户的登录信息。", + ), + "accountRemoveUserLogin": + MessageLookupByLibrary.simpleMessage("删除用户登录"), + "accountRemoveUserLoginHead": MessageLookupByLibrary.simpleMessage( + "这将删除用户 ", + ), + "accountRemoveUserLoginTail": MessageLookupByLibrary.simpleMessage( + " 的登录详细信息。", + ), + "accountServerURI": MessageLookupByLibrary.simpleMessage("服务器地址"), + "accountSwitch": MessageLookupByLibrary.simpleMessage("切换账户"), + "accountUsersCount": m1, + "appSettings": MessageLookupByLibrary.simpleMessage("应用设置"), + "appearance": MessageLookupByLibrary.simpleMessage("外观"), + "autoSleepTimerSettings": + MessageLookupByLibrary.simpleMessage("自动睡眠定时器设置"), + "autoTurnOnSleepTimer": + MessageLookupByLibrary.simpleMessage("自动开启睡眠定时器"), + "autoTurnOnTimer": MessageLookupByLibrary.simpleMessage("自动开启定时器"), + "autoTurnOnTimerAlways": + MessageLookupByLibrary.simpleMessage("始终自动开启定时器"), + "autoTurnOnTimerAlwaysDescription": + MessageLookupByLibrary.simpleMessage( + "总是打开睡眠定时器", + ), + "autoTurnOnTimerDescription": MessageLookupByLibrary.simpleMessage( + "根据一天中的时间自动打开睡眠定时器", + ), + "autoTurnOnTimerFrom": MessageLookupByLibrary.simpleMessage("从"), + "autoTurnOnTimerFromDescription": MessageLookupByLibrary.simpleMessage( + "在指定时间打开睡眠定时器", + ), + "autoTurnOnTimerUntil": MessageLookupByLibrary.simpleMessage("直到"), + "autoTurnOnTimerUntilDescription": MessageLookupByLibrary.simpleMessage( + "在指定时间关闭睡眠定时器", + ), + "automaticallyDescription": MessageLookupByLibrary.simpleMessage( + "根据一天中的时间自动打开睡眠定时器", + ), + "backup": MessageLookupByLibrary.simpleMessage("备份"), + "backupAndRestore": MessageLookupByLibrary.simpleMessage("备份与恢复"), + "bookAbout": MessageLookupByLibrary.simpleMessage("关于本书"), + "bookAboutDefault": MessageLookupByLibrary.simpleMessage("抱歉,找不到描述"), + "bookAuthors": MessageLookupByLibrary.simpleMessage("作者"), + "bookDownloads": MessageLookupByLibrary.simpleMessage("下载"), + "bookGenres": MessageLookupByLibrary.simpleMessage("风格"), + "bookMetadataAbridged": MessageLookupByLibrary.simpleMessage("删节版"), + "bookMetadataLength": MessageLookupByLibrary.simpleMessage("持续时间"), + "bookMetadataPublished": MessageLookupByLibrary.simpleMessage("发布年份"), + "bookMetadataUnabridged": MessageLookupByLibrary.simpleMessage("未删节版"), + "bookSeries": MessageLookupByLibrary.simpleMessage("系列"), + "bookShelveEmpty": MessageLookupByLibrary.simpleMessage("重试"), + "bookShelveEmptyText": MessageLookupByLibrary.simpleMessage("未查询到书架"), + "cancel": MessageLookupByLibrary.simpleMessage("取消"), + "chapterNotFound": MessageLookupByLibrary.simpleMessage("未找到章节"), + "chapterSelect": MessageLookupByLibrary.simpleMessage("选择章节"), + "chapterSkip": MessageLookupByLibrary.simpleMessage("跳过章节片头片尾"), + "chapterSkipEnd": MessageLookupByLibrary.simpleMessage("跳过章节片尾 "), + "chapterSkipOpen": MessageLookupByLibrary.simpleMessage("跳过章节片头 "), + "chapters": MessageLookupByLibrary.simpleMessage("章节列表"), + "copyToClipboard": MessageLookupByLibrary.simpleMessage("复制到剪贴板"), + "copyToClipboardDescription": MessageLookupByLibrary.simpleMessage( + "将应用程序设置复制到剪贴板", + ), + "copyToClipboardToast": + MessageLookupByLibrary.simpleMessage("设置已复制到剪贴板"), + "delete": MessageLookupByLibrary.simpleMessage("删除"), + "deleteDialog": m2, + "deleted": m3, + "explore": MessageLookupByLibrary.simpleMessage("探索"), + "exploreHint": MessageLookupByLibrary.simpleMessage("搜索与探索..."), + "exploreTooltip": MessageLookupByLibrary.simpleMessage("搜索和探索"), + "general": MessageLookupByLibrary.simpleMessage("通用"), + "help": MessageLookupByLibrary.simpleMessage("Help"), + "home": MessageLookupByLibrary.simpleMessage("首页"), + "homeBookContinueListening": + MessageLookupByLibrary.simpleMessage("继续收听"), + "homeBookContinueListeningDescription": + MessageLookupByLibrary.simpleMessage("继续收听书架上显示播放按钮"), + "homeBookContinueSeries": MessageLookupByLibrary.simpleMessage("继续系列"), + "homeBookContinueSeriesDescription": + MessageLookupByLibrary.simpleMessage( + "继续系列书架上显示播放按钮", + ), + "homeBookDiscover": MessageLookupByLibrary.simpleMessage("发现"), + "homeBookListenAgain": MessageLookupByLibrary.simpleMessage("再听一遍"), + "homeBookListenAgainDescription": MessageLookupByLibrary.simpleMessage( + "再听一遍书架上显示播放按钮", + ), + "homeBookNewestAuthors": MessageLookupByLibrary.simpleMessage("最新作者"), + "homeBookRecentlyAdded": MessageLookupByLibrary.simpleMessage("最近添加"), + "homeBookRecommended": MessageLookupByLibrary.simpleMessage("推荐"), + "homeContinueListening": MessageLookupByLibrary.simpleMessage("继续收听"), + "homeListenAgain": MessageLookupByLibrary.simpleMessage("再听一遍"), + "homePageSettings": MessageLookupByLibrary.simpleMessage("主页设置"), + "homePageSettingsDescription": MessageLookupByLibrary.simpleMessage( + "自定义主页", + ), + "homePageSettingsOtherShelves": MessageLookupByLibrary.simpleMessage( + "其他书架", + ), + "homePageSettingsOtherShelvesDescription": + MessageLookupByLibrary.simpleMessage("显示所有剩余书架上所有书籍的播放按钮"), + "homePageSettingsQuickPlay": + MessageLookupByLibrary.simpleMessage("继续播放"), + "homeStartListening": MessageLookupByLibrary.simpleMessage("开始收听"), + "language": MessageLookupByLibrary.simpleMessage("语言"), + "languageDescription": MessageLookupByLibrary.simpleMessage("语言切换"), + "library": MessageLookupByLibrary.simpleMessage("媒体库"), + "libraryChange": MessageLookupByLibrary.simpleMessage("更改媒体库"), + "libraryEmpty": MessageLookupByLibrary.simpleMessage("没有可用的库。"), + "libraryLoadError": m4, + "librarySelect": MessageLookupByLibrary.simpleMessage("选择媒体库"), + "librarySwitchTooltip": MessageLookupByLibrary.simpleMessage("切换媒体库"), + "libraryTooltip": MessageLookupByLibrary.simpleMessage("浏览您的媒体库"), + "loading": MessageLookupByLibrary.simpleMessage("加载中..."), + "loginLocal": MessageLookupByLibrary.simpleMessage("Local"), + "loginLogin": MessageLookupByLibrary.simpleMessage("登录"), + "loginOpenID": MessageLookupByLibrary.simpleMessage("OpenID"), + "loginPassword": MessageLookupByLibrary.simpleMessage("密码"), + "loginServerClick": MessageLookupByLibrary.simpleMessage("单击此处"), + "loginServerConnected": + MessageLookupByLibrary.simpleMessage("服务器已连接,请登录"), + "loginServerNo": MessageLookupByLibrary.simpleMessage("没有服务器? "), + "loginServerNoConnected": MessageLookupByLibrary.simpleMessage( + "请输入您的AudiobookShelf服务器的URL", + ), + "loginServerNot": m5, + "loginServerTo": MessageLookupByLibrary.simpleMessage(" 了解如何设置服务器。"), + "loginTitle": m6, + "loginToken": MessageLookupByLibrary.simpleMessage("Token"), + "loginUsername": MessageLookupByLibrary.simpleMessage("用户名"), + "logs": MessageLookupByLibrary.simpleMessage("日志"), + "nmpSettingsBackward": MessageLookupByLibrary.simpleMessage("快退间隔"), + "nmpSettingsForward": MessageLookupByLibrary.simpleMessage("快进间隔"), + "nmpSettingsMediaControls": + MessageLookupByLibrary.simpleMessage("媒体控制"), + "nmpSettingsMediaControlsDescription": + MessageLookupByLibrary.simpleMessage( + "选择要显示的媒体控件", + ), + "nmpSettingsSelectOne": MessageLookupByLibrary.simpleMessage( + "在下面选择一个字段进行插入", + ), + "nmpSettingsShowChapterProgress": MessageLookupByLibrary.simpleMessage( + "显示章节进度", + ), + "nmpSettingsShowChapterProgressDescription": + MessageLookupByLibrary.simpleMessage("而不是本书的整体进展"), + "nmpSettingsSubTitle": MessageLookupByLibrary.simpleMessage("副标题"), + "nmpSettingsSubTitleDescription": MessageLookupByLibrary.simpleMessage( + "通知的副标题\n", + ), + "nmpSettingsTitle": MessageLookupByLibrary.simpleMessage("主标题"), + "nmpSettingsTitleDescription": MessageLookupByLibrary.simpleMessage( + "通知的标题\n", + ), + "no": MessageLookupByLibrary.simpleMessage("否"), + "notImplemented": MessageLookupByLibrary.simpleMessage("未实现"), + "notificationMediaPlayer": + MessageLookupByLibrary.simpleMessage("通知媒体播放器"), + "notificationMediaPlayerDescription": + MessageLookupByLibrary.simpleMessage( + "在通知中自定义媒体播放器", + ), + "ok": MessageLookupByLibrary.simpleMessage("确定"), + "pause": MessageLookupByLibrary.simpleMessage("暂停"), + "play": MessageLookupByLibrary.simpleMessage("播放"), + "playerSettings": MessageLookupByLibrary.simpleMessage("播放器设置"), + "playerSettingsCompleteTime": MessageLookupByLibrary.simpleMessage( + "剩余时间标记完成", + ), + "playerSettingsCompleteTimeDescriptionHead": + MessageLookupByLibrary.simpleMessage("当书中剩余时间少于 "), + "playerSettingsCompleteTimeDescriptionTail": + MessageLookupByLibrary.simpleMessage(" 时,标记完成"), + "playerSettingsDescription": MessageLookupByLibrary.simpleMessage( + "自定义播放器设置", + ), + "playerSettingsDisplay": MessageLookupByLibrary.simpleMessage("显示设置"), + "playerSettingsDisplayChapterProgress": + MessageLookupByLibrary.simpleMessage("显示章节进度"), + "playerSettingsDisplayChapterProgressDescription": + MessageLookupByLibrary.simpleMessage("在播放器中显示当前章节的进度"), + "playerSettingsDisplayTotalProgress": + MessageLookupByLibrary.simpleMessage( + "显示总进度", + ), + "playerSettingsDisplayTotalProgressDescription": + MessageLookupByLibrary.simpleMessage("在播放器中显示当前书籍的总进度"), + "playerSettingsPlaybackInterval": MessageLookupByLibrary.simpleMessage( + "播放报告间隔", + ), + "playerSettingsPlaybackIntervalDescriptionHead": + MessageLookupByLibrary.simpleMessage("每 "), + "playerSettingsPlaybackIntervalDescriptionTail": + MessageLookupByLibrary.simpleMessage(" 向服务器报告一次进度"), + "playerSettingsPlaybackReporting": MessageLookupByLibrary.simpleMessage( + "回放报告", + ), + "playerSettingsPlaybackReportingIgnore": + MessageLookupByLibrary.simpleMessage("忽略播放位置小于"), + "playerSettingsPlaybackReportingMinimum": + MessageLookupByLibrary.simpleMessage("回放报告最小位置"), + "playerSettingsPlaybackReportingMinimumDescriptionHead": + MessageLookupByLibrary.simpleMessage("不要报告本书前 "), + "playerSettingsPlaybackReportingMinimumDescriptionTail": + MessageLookupByLibrary.simpleMessage(" 的播放"), + "playerSettingsRememberForEveryBook": + MessageLookupByLibrary.simpleMessage( + "记住每本书的播放器设置", + ), + "playerSettingsRememberForEveryBookDescription": + MessageLookupByLibrary.simpleMessage("每本书都会记住播放速度、音量等设置"), + "playerSettingsSpeed": MessageLookupByLibrary.simpleMessage("播放速度"), + "playerSettingsSpeedDefault": MessageLookupByLibrary.simpleMessage( + "默认播放速度", + ), + "playerSettingsSpeedOptions": MessageLookupByLibrary.simpleMessage( + "播放速度选项", + ), + "playerSettingsSpeedOptionsSelect": + MessageLookupByLibrary.simpleMessage( + "播放速度选项", + ), + "playerSettingsSpeedOptionsSelectAdd": + MessageLookupByLibrary.simpleMessage( + "添加一个速度选项", + ), + "playerSettingsSpeedOptionsSelectAddHelper": + MessageLookupByLibrary.simpleMessage("输入一个新的速度选项"), + "playerSettingsSpeedSelect": + MessageLookupByLibrary.simpleMessage("选择播放速度"), + "playerSettingsSpeedSelectHelper": MessageLookupByLibrary.simpleMessage( + "输入默认的播放速度", + ), + "playlistsMine": MessageLookupByLibrary.simpleMessage("播放列表"), + "readLess": MessageLookupByLibrary.simpleMessage("折叠"), + "readMore": MessageLookupByLibrary.simpleMessage("展开"), + "refresh": MessageLookupByLibrary.simpleMessage("刷新"), + "reset": MessageLookupByLibrary.simpleMessage("重置"), + "resetAppSettings": MessageLookupByLibrary.simpleMessage("重置应用程序设置"), + "resetAppSettingsDescription": MessageLookupByLibrary.simpleMessage( + "将应用程序设置重置为默认值", + ), + "resetAppSettingsDialog": MessageLookupByLibrary.simpleMessage( + "您确定要重置应用程序设置吗?", + ), + "restore": MessageLookupByLibrary.simpleMessage("恢复"), + "restoreBackup": MessageLookupByLibrary.simpleMessage("恢复备份"), + "restoreBackupHint": MessageLookupByLibrary.simpleMessage("将备份粘贴到此处"), + "restoreBackupInvalid": MessageLookupByLibrary.simpleMessage("无效备份"), + "restoreBackupSuccess": MessageLookupByLibrary.simpleMessage("设置已恢复"), + "restoreBackupValidator": + MessageLookupByLibrary.simpleMessage("请将备份粘贴到此处"), + "restoreDescription": + MessageLookupByLibrary.simpleMessage("从备份中还原应用程序设置"), + "resume": MessageLookupByLibrary.simpleMessage("继续"), + "retry": MessageLookupByLibrary.simpleMessage("重试"), + "settings": MessageLookupByLibrary.simpleMessage("设置"), + "shakeAction": MessageLookupByLibrary.simpleMessage("抖动操作"), + "shakeActionDescription": MessageLookupByLibrary.simpleMessage( + "检测到抖动时要执行的操作", + ), + "shakeActivationThreshold": + MessageLookupByLibrary.simpleMessage("抖动激活阈值"), + "shakeActivationThresholdDescription": + MessageLookupByLibrary.simpleMessage( + "门槛越高,你就越难摇晃", + ), + "shakeDetector": MessageLookupByLibrary.simpleMessage("抖动检测器"), + "shakeDetectorDescription": MessageLookupByLibrary.simpleMessage( + "自定义抖动检测器设置", + ), + "shakeDetectorEnable": MessageLookupByLibrary.simpleMessage("启用抖动检测"), + "shakeDetectorEnableDescription": MessageLookupByLibrary.simpleMessage( + "启用抖动检测以执行各种操作", + ), + "shakeDetectorSettings": + MessageLookupByLibrary.simpleMessage("抖动检测器设置"), + "shakeFeedback": MessageLookupByLibrary.simpleMessage("抖动反馈"), + "shakeFeedbackDescription": MessageLookupByLibrary.simpleMessage( + "检测到抖动时给出的反馈", + ), + "shakeSelectAction": MessageLookupByLibrary.simpleMessage("选择抖动动作"), + "shakeSelectActivationThreshold": MessageLookupByLibrary.simpleMessage( + "选择抖动激活阈值", + ), + "shakeSelectActivationThresholdHelper": + MessageLookupByLibrary.simpleMessage("输入一个数字以m/s²为单位设置阈值"), + "shakeSelectFeedback": MessageLookupByLibrary.simpleMessage("选择抖动反馈"), + "themeMode": MessageLookupByLibrary.simpleMessage("主题模式"), + "themeModeDark": MessageLookupByLibrary.simpleMessage("深色"), + "themeModeHighContrast": MessageLookupByLibrary.simpleMessage("高对比度模式"), + "themeModeHighContrastDescription": + MessageLookupByLibrary.simpleMessage( + "增加背景和文本之间的对比度", + ), + "themeModeLight": MessageLookupByLibrary.simpleMessage("浅色"), + "themeModeSystem": MessageLookupByLibrary.simpleMessage("跟随系统"), + "themeSettings": MessageLookupByLibrary.simpleMessage("主题设置"), + "themeSettingsColors": MessageLookupByLibrary.simpleMessage("主题色"), + "themeSettingsColorsAndroid": + MessageLookupByLibrary.simpleMessage("主题色"), + "themeSettingsColorsBook": MessageLookupByLibrary.simpleMessage( + "书籍详情页自适应主题", + ), + "themeSettingsColorsBookDescription": + MessageLookupByLibrary.simpleMessage( + "以牺牲一些性能为代价,对书籍详情页的颜色进行美化", + ), + "themeSettingsColorsCurrent": MessageLookupByLibrary.simpleMessage( + "根据当前播放的书籍调整主题", + ), + "themeSettingsColorsCurrentDescription": + MessageLookupByLibrary.simpleMessage("使用当前播放书籍的主题颜色"), + "themeSettingsColorsDescription": MessageLookupByLibrary.simpleMessage( + "使用应用程序的系统主题色", + ), + "themeSettingsDescription": + MessageLookupByLibrary.simpleMessage("自定义应用主题"), + "timeSecond": m7, + "unknown": MessageLookupByLibrary.simpleMessage("未知"), + "webVersion": MessageLookupByLibrary.simpleMessage("Web版本"), + "yes": MessageLookupByLibrary.simpleMessage("是"), + "you": MessageLookupByLibrary.simpleMessage("我的"), + "youTooltip": MessageLookupByLibrary.simpleMessage("您的个人资料和设置"), + }; } diff --git a/lib/main.dart b/lib/main.dart index e25224a..bcc3cbf 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -160,7 +160,6 @@ class AbsApp extends ConsumerWidget { ); try { return MaterialApp.router( - // debugShowCheckedModeBanner: false, locale: Locale(appSettings.language), localizationsDelegates: [ // 以下是其他代理 @@ -175,6 +174,7 @@ class AbsApp extends ConsumerWidget { themeMode: themeSettings.themeMode, routerConfig: routerConfig, themeAnimationCurve: Curves.easeInOut, + debugShowCheckedModeBanner: false, ); } catch (e) { debugPrintStack(stackTrace: StackTrace.current, label: e.toString()); diff --git a/lib/pages/library_page.dart b/lib/pages/library_page.dart index 89c3780..bb4d627 100644 --- a/lib/pages/library_page.dart +++ b/lib/pages/library_page.dart @@ -1,12 +1,20 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; +import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; +import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; +import 'package:shelfsdk/audiobookshelf_api.dart'; import 'package:vaani/api/api_provider.dart'; -import 'package:vaani/globals.dart'; -import 'package:vaani/features/settings/api_settings_provider.dart'; - -import '../shared/widgets/drawer.dart'; -import '../shared/widgets/shelves/home_shelf.dart'; +import 'package:vaani/api/image_provider.dart'; +import 'package:vaani/api/library_provider.dart'; +import 'package:vaani/features/you/view/widgets/library_switch_chip.dart'; +import 'package:vaani/generated/l10n.dart'; +import 'package:vaani/router/router.dart'; +import 'package:vaani/shared/extensions/model_conversions.dart'; +import 'package:vaani/shared/icons/abs_icons.dart'; +import 'package:vaani/shared/widgets/shelves/book_shelf.dart'; // TODO: implement the library page class LibraryPage extends HookConsumerWidget { @@ -15,20 +23,28 @@ class LibraryPage extends HookConsumerWidget { final String? libraryId; @override Widget build(BuildContext context, WidgetRef ref) { - // set the library id as the active library - if (libraryId != null) { - ref.read(apiSettingsProvider.notifier).updateState( - ref.watch(apiSettingsProvider).copyWith(activeLibraryId: libraryId), - ); - } + final currentLibrary = ref.watch(currentLibraryProvider).valueOrNull; - final views = ref.watch(personalizedViewProvider); + // Determine the icon to use, with a fallback + final IconData libraryIconData = + AbsIcons.getIconByName(currentLibrary?.icon) ?? Icons.library_books; + + // Determine the title text + final String appBarTitle = currentLibrary?.name ?? S.of(context).library; + // set the library id as the active library + // if (libraryId != null) { + // ref.read(apiSettingsProvider.notifier).updateState( + // ref.watch(apiSettingsProvider).copyWith(activeLibraryId: libraryId), + // ); + // } + + final views = ref.watch(currentLibraryItemsProvider); final scrollController = useScrollController(); return Scaffold( appBar: AppBar( title: GestureDetector( - child: const Text('Vaani'), + child: Text(appBarTitle), onTap: () { // scroll to the top of the page scrollController.animateTo( @@ -40,34 +56,57 @@ class LibraryPage extends HookConsumerWidget { ref.invalidate(personalizedViewProvider); }, ), + leading: IconButton( + icon: Icon(libraryIconData), + tooltip: + S.of(context).librarySwitchTooltip, // Helpful tooltip for users + onPressed: () { + showLibrarySwitcher(context, ref); + }, + ), + actions: [ + IconButton( + icon: Icon(Icons.refresh), + tooltip: '刷新', // Helpful tooltip for users + onPressed: () { + return ref.refresh(currentLibraryItemsProvider); + }, + ), + IconButton( + icon: Icon(Icons.download), + tooltip: S.of(context).bookDownloads, // Helpful tooltip for users + onPressed: () { + GoRouter.of(context).pushNamed(Routes.downloads.name); + }, + ), + ], ), - drawer: const MyDrawer(), - body: Container( + // drawer: const MyDrawer(), + body: RefreshIndicator( + onRefresh: () async { + return ref.refresh(currentLibraryItemsProvider); + }, child: views.when( data: (data) { - final shelvesToDisplay = data - // .where((element) => !element.id.contains('discover')) - .map((shelf) { - appLogger.fine('building shelf ${shelf.label}'); - return HomeShelf( - title: shelf.label, - shelf: shelf, - ); - }).toList(); - return RefreshIndicator( - onRefresh: () async { - return ref.refresh(personalizedViewProvider); + return LayoutBuilder( + builder: (context, constraints) { + final height = getDefaultHeight(context); + // final height = min(constraints.maxHeight, 500.0); + final width = height * 0.75; + return AlignedGridView.count( + crossAxisCount: constraints.maxWidth ~/ width, + mainAxisSpacing: 12, + crossAxisSpacing: 12, + padding: EdgeInsets.only(top: 0, left: 8, right: 8), + itemCount: data.length, + controller: scrollController, + itemBuilder: (context, index) { + return LibraryPageItem( + item: data[index], + ); + }, + ); }, - child: ListView.separated( - itemBuilder: (context, index) => shelvesToDisplay[index], - separatorBuilder: (context, index) => Divider( - color: Theme.of(context).dividerColor.withValues(alpha: 0.1), - indent: 16, - endIndent: 16, - ), - itemCount: shelvesToDisplay.length, - controller: scrollController, - ), ); }, loading: () => const LibraryPageSkeleton(), @@ -78,8 +117,27 @@ class LibraryPage extends HookConsumerWidget { ), ); } + + double getDefaultHeight( + BuildContext context, { + bool ignoreWidth = false, + atMin = 150.0, + perCent = 0.3, + }) { + double referenceSide; + if (ignoreWidth) { + referenceSide = MediaQuery.of(context).size.height; + } else { + referenceSide = min( + MediaQuery.of(context).size.width, + MediaQuery.of(context).size.height, + ); + } + return max(atMin, referenceSide * perCent); + } } +// 加载 class LibraryPageSkeleton extends StatelessWidget { const LibraryPageSkeleton({super.key}); @@ -92,3 +150,72 @@ class LibraryPageSkeleton extends StatelessWidget { ); } } + +class LibraryPageItem extends HookConsumerWidget { + const LibraryPageItem({ + super.key, + required this.item, + }); + final LibraryItem item; + @override + Widget build(BuildContext context, WidgetRef ref) { + final book = item.media.asBookMinified; + final metadata = book.metadata.asBookMetadataMinified; + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + BookCoverWidget(itemId: item.id), + const SizedBox(height: 3), + Text( + metadata.title ?? '', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodyLarge, + ), + const SizedBox(height: 3), + Text( + metadata.authorName ?? '', + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.bodySmall, + ), + ], + ); + } +} + +class BookCoverWidget extends HookConsumerWidget { + const BookCoverWidget({ + super.key, + required this.itemId, + }); + + final String itemId; + + @override + Widget build(BuildContext context, WidgetRef ref) { + final coverImage = ref.watch(coverImageProvider(itemId)); + + return coverImage.when( + data: (image) { + // return const BookCoverSkeleton(); + if (image.isEmpty) { + return const Icon(Icons.error); + } + + return Image.memory( + image, + fit: BoxFit.cover, + ); + }, + loading: () { + return const Center( + child: BookCoverSkeleton(), + ); + }, + error: (error, stack) { + return const Center(child: Icon(Icons.error)); + }, + ); + } +} diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 7c71855..3e25577 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -13,7 +13,7 @@ class Routes { ); static const library = _SimpleRoute( pathName: 'library', - pathParamName: 'libraryId', + // pathParamName: 'libraryId', name: 'library', ); static const libraryItem = _SimpleRoute( diff --git a/lib/router/router.dart b/lib/router/router.dart index 7397f05..188ec72 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -19,6 +19,7 @@ import 'package:vaani/features/you/view/server_manager.dart'; import 'package:vaani/features/you/view/you_page.dart'; import 'package:vaani/globals.dart'; import 'package:vaani/pages/home_page.dart'; +import 'package:vaani/pages/library_page.dart'; import 'package:vaani/pages/player_page.dart'; import 'scaffold_with_nav_bar.dart'; @@ -118,10 +119,15 @@ class MyAppRouter { // Library page StatefulShellBranch( routes: [ + // GoRoute( + // path: Routes.libraryBrowser.localPath, + // name: Routes.libraryBrowser.name, + // pageBuilder: defaultPageBuilder(const LibraryBrowserPage()), + // ), GoRoute( - path: Routes.libraryBrowser.localPath, - name: Routes.libraryBrowser.name, - pageBuilder: defaultPageBuilder(const LibraryBrowserPage()), + path: Routes.library.localPath, + name: Routes.library.name, + pageBuilder: defaultPageBuilder(const LibraryPage()), ), ], ), diff --git a/pubspec.lock b/pubspec.lock index 4555c30..6a85a28 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -568,6 +568,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.1.3" + flutter_staggered_grid_view: + dependency: "direct main" + description: + name: flutter_staggered_grid_view + sha256: "19e7abb550c96fbfeb546b23f3ff356ee7c59a019a651f8f102a4ba9b7349395" + url: "https://pub.dev" + source: hosted + version: "0.7.0" flutter_svg: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 5d8e57c..d82c7b3 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -44,6 +44,7 @@ dependencies: collection: ^1.18.0 cupertino_icons: ^1.0.6 flutter_platform_widgets: ^9.0.0 + flutter_staggered_grid_view: ^0.7.0 device_info_plus: ^11.3.3 duration_picker: ^1.2.0 dynamic_color: ^1.7.0