diff --git a/lib/api/authenticated_users_provider.dart b/lib/api/authenticated_users_provider.dart index c203d32..d4bb46f 100644 --- a/lib/api/authenticated_users_provider.dart +++ b/lib/api/authenticated_users_provider.dart @@ -11,7 +11,7 @@ import 'package:vaani/shared/extensions/obfuscation.dart'; part 'authenticated_users_provider.g.dart'; -final _box = AvailableHiveBoxes.authenticatedUserBox; +final _box = HiveBoxes.authenticatedUserBox; final _logger = Logger('authenticated_users_provider'); diff --git a/lib/api/server_provider.dart b/lib/api/server_provider.dart index 169b918..bfe59c4 100644 --- a/lib/api/server_provider.dart +++ b/lib/api/server_provider.dart @@ -9,7 +9,7 @@ import 'package:vaani/shared/extensions/obfuscation.dart'; part 'server_provider.g.dart'; -final _box = AvailableHiveBoxes.serverBox; +final _box = HiveBoxes.serverBox; final _logger = Logger('AudiobookShelfServerProvider'); diff --git a/lib/db/available_boxes.dart b/lib/db/available_boxes.dart index b523346..2d6f4c3 100644 --- a/lib/db/available_boxes.dart +++ b/lib/db/available_boxes.dart @@ -4,48 +4,34 @@ import 'package:vaani/features/per_book_settings/models/book_settings.dart'; import 'package:vaani/features/settings/models/models.dart'; @immutable -class AvailableHiveBoxes { - const AvailableHiveBoxes._(); - - static Future init() async { - await Hive.openBox('basicTypes'); - - /// Box for storing user preferences as [AppSettings] - await Hive.openBox('userPrefs'); - - /// Box for storing [ApiSettings] - await Hive.openBox('apiSettings'); - - /// stores the a list of [AudiobookShelfServer] - - await Hive.openBox('audiobookShelfServer'); - - /// stores the a list of [AuthenticatedUser] - - await Hive.openBox('authenticatedUser'); - - /// stores the a list of [BookSettings] - - await Hive.openBox('bookSettings'); - } - - static final basicBox = Hive.box('basicTypes'); +class HiveBoxes { + const HiveBoxes._(); + static late final Box basicBox; /// Box for storing user preferences as [AppSettings] - static final userPrefsBox = Hive.box('userPrefs'); + static late final Box userPrefsBox; /// Box for storing [ApiSettings] - static final apiSettingsBox = Hive.box('apiSettings'); + static late final Box apiSettingsBox; /// stores the a list of [AudiobookShelfServer] - static final serverBox = - Hive.box('audiobookShelfServer'); + static late final Box serverBox; /// stores the a list of [AuthenticatedUser] - static final authenticatedUserBox = - Hive.box('authenticatedUser'); + static late final Box authenticatedUserBox; /// stores the a list of [BookSettings] - static final individualBookSettingsBox = - Hive.box('bookSettings'); + static late final Box individualBookSettingsBox; + + static Future init() async { + basicBox = await Hive.openBox('basicTypes'); + userPrefsBox = await Hive.openBox('userPrefs'); + apiSettingsBox = await Hive.openBox('apiSettings'); + serverBox = + await Hive.openBox('audiobookShelfServer'); + authenticatedUserBox = + await Hive.openBox('authenticatedUser'); + individualBookSettingsBox = + await Hive.openBox('bookSettings'); + } } diff --git a/lib/db/init.dart b/lib/db/init.dart index 472c76f..9c41094 100644 --- a/lib/db/init.dart +++ b/lib/db/init.dart @@ -18,6 +18,6 @@ Future initStorage() async { // Hive.defaultDirectory = appDocumentsDir.path; // appLogger.config('Hive storage directory init: ${Hive.defaultDirectory}'); - await registerModels(); - await AvailableHiveBoxes.init(); + registerModels(); + await HiveBoxes.init(); } diff --git a/lib/db/register_models.dart b/lib/db/register_models.dart index 2c4d01b..8a687ad 100644 --- a/lib/db/register_models.dart +++ b/lib/db/register_models.dart @@ -5,7 +5,7 @@ import 'package:vaani/features/per_book_settings/models/book_settings.dart'; import 'package:vaani/features/settings/models/models.dart'; // register all models to Hive for serialization -Future registerModels() async { +void registerModels() { Hive.registerAdapter( JsonAdapter( id: 1, diff --git a/lib/features/per_book_settings/providers/book_settings_provider.dart b/lib/features/per_book_settings/providers/book_settings_provider.dart index c9b7312..f508fe5 100644 --- a/lib/features/per_book_settings/providers/book_settings_provider.dart +++ b/lib/features/per_book_settings/providers/book_settings_provider.dart @@ -7,7 +7,7 @@ import 'package:vaani/features/per_book_settings/models/nullable_player_settings part 'book_settings_provider.g.dart'; -final _box = AvailableHiveBoxes.individualBookSettingsBox; +final _box = HiveBoxes.individualBookSettingsBox; final _logger = Logger('BookSettingsProvider'); diff --git a/lib/features/player/core/abs_audio_player.dart b/lib/features/player/core/abs_audio_player.dart index 3381528..2e0c423 100644 --- a/lib/features/player/core/abs_audio_player.dart +++ b/lib/features/player/core/abs_audio_player.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:collection/collection.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:just_audio/just_audio.dart'; import 'package:just_audio_background/just_audio_background.dart'; import 'package:logging/logging.dart'; @@ -18,8 +19,9 @@ final offset = Duration(milliseconds: 10); final _logger = Logger('AbsAudioPlayer'); class AbsAudioPlayer { + final Ref ref; late final AudioPlayer _player; - AbsAudioPlayer(AudioPlayer player) : _player = player { + AbsAudioPlayer(AudioPlayer player, this.ref) : _player = player { _player.positionStream.listen((position) { final chapter = currentChapter; if (positionInBook <= (chapter?.start ?? Duration.zero) || @@ -53,34 +55,23 @@ class AbsAudioPlayer { List? downloadedUris, Duration? start, Duration? end, + bool force = false, }) async { - if (_bookStreamController.nvalue == book) { + if (!force && _bookStreamController.nvalue == book) { _logger.info('Book is the same, doing nothing'); return; } _bookStreamController.add(book); - final appSettings = loadOrCreateAppSettings(); final currentTrack = book.findTrackAtTime(initialPosition ?? Duration.zero); final indexTrack = book.tracks.indexOf(currentTrack); final positionInTrack = initialPosition != null ? initialPosition - currentTrack.startOffset : null; - final title = appSettings.notificationSettings.primaryTitle - .formatNotificationTitle(book); - final artist = appSettings.notificationSettings.secondaryTitle - .formatNotificationTitle(book); chapterStreamController .add(book.findChapterAtTime(initialPosition ?? Duration.zero)); - // final item = MediaItem( - // id: book.libraryItemId, - // title: title, - // artist: artist, - // duration: currentChapter?.duration ?? book.duration, - // artUri: Uri.parse( - // '$baseUrl/api/items/${book.libraryItemId}/cover?token=$token', - // ), - // ); + final title = primaryTitle(); + final artist = secondaryTitle(); mediaItem(track) => MediaItem( id: book.libraryItemId + track.index.toString(), @@ -91,6 +82,13 @@ class AbsAudioPlayer { '$baseUrl/api/items/${book.libraryItemId}/cover?token=$token', ), ); + if (start != null && start > Duration.zero || + end != null && end > Duration.zero) { + _logger.info( + 'Skip the opening ${start?.inSeconds} seconds, end ${end?.inSeconds} seconds', + ); + } + List audioSources = start != null && start > Duration.zero || end != null && end > Duration.zero ? book.tracks @@ -270,6 +268,26 @@ class AbsAudioPlayer { _bookStreamController.close(); chapterStreamController.close(); } + + String primaryTitle() { + final appSettings = ref.read(appSettingsProvider); + final currentBook = book; + if (currentBook != null) { + return appSettings.notificationSettings.primaryTitle + .formatNotificationTitle(currentBook, chapter: currentChapter); + } + return ""; + } + + String secondaryTitle() { + final appSettings = ref.read(appSettingsProvider); + final currentBook = book; + if (currentBook != null) { + return appSettings.notificationSettings.secondaryTitle + .formatNotificationTitle(currentBook, chapter: currentChapter); + } + return ""; + } } Uri _getUri( @@ -328,14 +346,14 @@ extension BookExpandedExtension on BookExpanded { } extension FormatNotificationTitle on String { - String formatNotificationTitle(BookExpanded book) { + String formatNotificationTitle(BookExpanded book, {BookChapter? chapter}) { return replaceAllMapped( RegExp(r'\$(\w+)'), (match) { final type = match.group(1); return NotificationTitleType.values .firstWhere((element) => element.name == type) - .extractFrom(book) ?? + .extractFrom(book, chapter: chapter) ?? match.group(0) ?? ''; }, @@ -344,13 +362,16 @@ extension FormatNotificationTitle on String { } extension NotificationTitleUtils on NotificationTitleType { - String? extractFrom(BookExpanded book) { + String? extractFrom(BookExpanded book, {BookChapter? chapter}) { var bookMetadataExpanded = book.metadata.asBookMetadataExpanded; switch (this) { case NotificationTitleType.bookTitle: return bookMetadataExpanded.title; case NotificationTitleType.chapterTitle: // TODO: implement chapter title; depends on https://github.com/Dr-Blank/Vaani/issues/2 + if (chapter != null) { + return chapter.title; + } return bookMetadataExpanded.title; case NotificationTitleType.author: return bookMetadataExpanded.authorName; diff --git a/lib/features/player/providers/abs_provider.dart b/lib/features/player/providers/abs_provider.dart index 0c81aeb..0e4b3f5 100644 --- a/lib/features/player/providers/abs_provider.dart +++ b/lib/features/player/providers/abs_provider.dart @@ -2,64 +2,24 @@ import 'package:collection/collection.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:just_audio/just_audio.dart' as audio; import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:shelfsdk/audiobookshelf_api.dart' as api; +import 'package:shelfsdk/audiobookshelf_api.dart' as shelfsdk; import 'package:vaani/api/api_provider.dart'; import 'package:vaani/api/library_item_provider.dart'; import 'package:vaani/db/available_boxes.dart'; import 'package:vaani/db/cache/cache_key.dart'; import 'package:vaani/features/downloads/providers/download_manager.dart'; import 'package:vaani/features/per_book_settings/providers/book_settings_provider.dart'; -import 'package:vaani/features/player/core/abs_audio_player.dart' - show AbsAudioPlayer; +import 'package:vaani/features/player/core/abs_audio_player.dart'; import 'package:vaani/features/settings/app_settings_provider.dart'; import 'package:vaani/shared/extensions/box.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; part 'abs_provider.g.dart'; -/// 音频播放器 配置 -// @Riverpod(keepAlive: true) -// Future configurePlayer(Ref ref) async { -// final player = ref.read(absPlayerProvider); -// // for playing audio on windows, linux - -// // for configuring how this app will interact with other audio apps -// final session = await AudioSession.instance; -// await session.configure(const AudioSessionConfiguration.speech()); - -// final audioService = await AudioService.init( -// builder: () => 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), -// ), -// ); - -// _logger.finer('created simple player'); -// return audioService; -// } - -// just_audio 播放器 -// @Riverpod(keepAlive: true) -// core.AbsAudioPlayer audioPlayer(Ref ref) { -// final player = AbsPlatformAudioPlayer(); -// // final player = AbsMpvAudioPlayer(); -// ref.onDispose(player.dispose); -// return player; -// } - // 播放器激活状态 @riverpod bool playerActive(Ref ref) { - return false; + return ref.watch(currentBookProvider) != null; } @Riverpod(keepAlive: true) @@ -76,23 +36,23 @@ class AbsPlayer extends _$AbsPlayer { @override AbsAudioPlayer build() { final audioPlayer = ref.watch(simpleAudioPlayerProvider); - return AbsAudioPlayer(audioPlayer); + return AbsAudioPlayer(audioPlayer, ref); } Future load( - api.BookExpanded book, { + shelfsdk.BookExpanded book, { Duration? initialPosition, bool play = true, + bool force = false, }) async { - if (state.book == book || state.book?.libraryItemId == book.libraryItemId) { + if (!force && + (state.book == book || + state.book?.libraryItemId == book.libraryItemId)) { state.playOrPause(); return; } final api = ref.read(authenticatedApiProvider); - final downloadManager = ref.read(simpleDownloadManagerProvider); - print(downloadManager.basePath); - final libItem = await ref.read(libraryItemProvider(book.libraryItemId).future); final downloadedUris = await downloadManager.getDownloadedFilesUri(libItem); @@ -112,6 +72,7 @@ class AbsPlayer extends _$AbsPlayer { downloadedUris: downloadedUris, start: bookSettings.playerSettings.skipChapterStart, end: bookSettings.playerSettings.skipChapterEnd, + force: force, ); // set the volume await state.setVolume( @@ -131,67 +92,6 @@ class AbsPlayer extends _$AbsPlayer { } } -/// 音频播放器 riverpod状态 -// @Riverpod(keepAlive: true) -// class AbsPlayer extends _$AbsPlayer { -// @override -// core.AbsAudioPlayer build() { -// final audioPlayer = ref.watch(audioPlayerProvider); -// return audioPlayer; -// } - -// Future load( -// api.BookExpanded book, { -// Duration? initialPosition, -// bool play = true, -// }) async { -// if (state.book == book || state.book?.libraryItemId == book.libraryItemId) { -// state.playOrPause(); -// return; -// } -// final api = ref.read(authenticatedApiProvider); - -// final downloadManager = ref.read(simpleDownloadManagerProvider); -// print(downloadManager.basePath); - -// final libItem = -// await ref.read(libraryItemProvider(book.libraryItemId).future); -// final downloadedUris = await downloadManager.getDownloadedFilesUri(libItem); - -// final bookSettings = ref.read(bookSettingsProvider(book.libraryItemId)); -// var bookPlayerSettings = bookSettings.playerSettings; -// var appPlayerSettings = ref.read(appSettingsProvider).playerSettings; - -// var configurePlayerForEveryBook = -// appPlayerSettings.configurePlayerForEveryBook; - -// await state.load( -// book, -// baseUrl: api.baseUrl, -// token: api.token!, -// initialPosition: initialPosition, -// downloadedUris: downloadedUris, -// start: bookSettings.playerSettings.skipChapterStart, -// end: bookSettings.playerSettings.skipChapterEnd, -// ); -// // set the volume -// await state.setVolume( -// configurePlayerForEveryBook -// ? bookPlayerSettings.preferredDefaultVolume ?? -// appPlayerSettings.preferredDefaultVolume -// : appPlayerSettings.preferredDefaultVolume, -// ); -// // set the speed -// await state.setSpeed( -// configurePlayerForEveryBook -// ? bookPlayerSettings.preferredDefaultSpeed ?? -// appPlayerSettings.preferredDefaultSpeed -// : appPlayerSettings.preferredDefaultSpeed, -// ); -// if (play) await state.play(); -// } -// } - @riverpod class PlayerState extends _$PlayerState { @override @@ -218,21 +118,24 @@ class PlayerState extends _$PlayerState { } @riverpod -Future currentTime(Ref ref, String libraryItemId) async { - final me = await ref.watch(meProvider.future); - final userProgress = me.mediaProgress - ?.firstWhereOrNull((element) => element.libraryItemId == libraryItemId); - return userProgress?.currentTime; +class CurrentTime extends _$CurrentTime { + @override + Future build(String libraryItemId) async { + final me = await ref.watch(meProvider.future); + final userProgress = me.mediaProgress + ?.firstWhereOrNull((element) => element.libraryItemId == libraryItemId); + return userProgress; + } } @riverpod class CurrentBook extends _$CurrentBook { @override - api.BookExpanded? build() { + shelfsdk.BookExpanded? build() { listenSelf((previous, next) { if (previous == null && next == null) { - final activeLibraryItemId = AvailableHiveBoxes.basicBox - .getAs(CacheKey.activeLibraryItemId); + final activeLibraryItemId = + HiveBoxes.basicBox.getAs(CacheKey.activeLibraryItemId); if (activeLibraryItemId != null) { update(activeLibraryItemId, play: false); } @@ -240,31 +143,29 @@ class CurrentBook extends _$CurrentBook { }); return null; } - // @override - // api.BookExpanded? build() { - // final player = ref.read(absPlayerProvider); - // player.bookStream.listen((book) { - // if (book != state) { - // state = book; - // } - // }); - // return player.book; - // } - Future update(String libraryItemId, {bool play = true}) async { - if (state?.libraryItemId == libraryItemId) { + Future update( + String libraryItemId, { + bool play = true, + bool force = false, + Duration? currentTime, + }) async { + if (!force && (state?.libraryItemId == libraryItemId)) { ref.read(absPlayerProvider).playOrPause(); return; } final book = await ref.read(libraryItemProvider(libraryItemId).future); state = book.media.asBookExpanded; - final currentTime = + final mediaProgress = await ref.read(currentTimeProvider(libraryItemId).future); - await ref - .read(absPlayerProvider.notifier) - .load(state!, initialPosition: currentTime, play: play); + await ref.read(absPlayerProvider.notifier).load( + state!, + initialPosition: currentTime ?? mediaProgress?.currentTime, + play: play, + force: force, + ); if (play) { - AvailableHiveBoxes.basicBox.put( + HiveBoxes.basicBox.put( CacheKey.activeLibraryItemId, libraryItemId, ); @@ -275,7 +176,7 @@ class CurrentBook extends _$CurrentBook { @riverpod class CurrentChapter extends _$CurrentChapter { @override - api.BookChapter? build() { + shelfsdk.BookChapter? build() { final player = ref.read(absPlayerProvider); player.chapterStream.listen((chapter) { if (chapter != state) { @@ -286,7 +187,48 @@ class CurrentChapter extends _$CurrentChapter { } } +/// 进度条显示 +// 进度条总时长 @riverpod -Stream positionChapter(Ref ref) { - return ref.read(absPlayerProvider).positionInChapterStream; +Duration total(Ref ref) { + final currentBook = ref.watch(currentBookProvider); + final currentChapter = ref.watch(currentChapterProvider); + final playerSettings = + ref.watch(appSettingsProvider.select((v) => v.playerSettings)); + final showChapterProgress = + playerSettings.expandedPlayerSettings.showChapterProgress; + return showChapterProgress + ? ((currentChapter?.end ?? Duration.zero) - + (currentChapter?.start ?? Duration.zero)) + : currentBook?.duration ?? Duration.zero; +} + +// 进度条当前时长 +@riverpod +Stream progress(Ref ref) { + final player = ref.read(absPlayerProvider); + final playerSettings = + ref.watch(appSettingsProvider.select((v) => v.playerSettings)); + final showChapterProgress = + playerSettings.expandedPlayerSettings.showChapterProgress; + return player.positionStream.map((position) { + return showChapterProgress + ? player.getPositionInChapter(position) + : player.getPositionInBook(position); + }); +} + +// 进度条已加载时长 +@riverpod +Stream progressBuffered(Ref ref) { + final player = ref.read(absPlayerProvider); + final playerSettings = + ref.watch(appSettingsProvider.select((v) => v.playerSettings)); + final showChapterProgress = + playerSettings.expandedPlayerSettings.showChapterProgress; + return player.bufferedPositionStream.map((position) { + return showChapterProgress + ? player.getPositionInChapter(position) + : player.getPositionInBook(position); + }); } diff --git a/lib/features/player/providers/abs_provider.g.dart b/lib/features/player/providers/abs_provider.g.dart index 02cc90a..86e8cdf 100644 --- a/lib/features/player/providers/abs_provider.g.dart +++ b/lib/features/player/providers/abs_provider.g.dart @@ -6,11 +6,9 @@ part of 'abs_provider.dart'; // RiverpodGenerator // ************************************************************************** -String _$playerActiveHash() => r'86831758035aa69d74f42ebde0a19bf7ef830910'; +String _$playerActiveHash() => r'4d3e7181cf66bfdb46d5caaece56cde07f610cc4'; -/// 音频播放器 配置 -/// -/// Copied from [playerActive]. +/// See also [playerActive]. @ProviderFor(playerActive) final playerActiveProvider = AutoDisposeProvider.internal( playerActive, @@ -41,7 +39,87 @@ final simpleAudioPlayerProvider = Provider.internal( @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element typedef SimpleAudioPlayerRef = ProviderRef; -String _$currentTimeHash() => r'3e7f99dbf48242a5fa0a4239a0f696535d0b4ac9'; +String _$totalHash() => r'2d01953862a875f6e66fe3af56868e819e33fcc8'; + +/// 进度条显示 +/// +/// Copied from [total]. +@ProviderFor(total) +final totalProvider = AutoDisposeProvider.internal( + total, + name: r'totalProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$totalHash, + dependencies: null, + allTransitiveDependencies: null, +); + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +typedef TotalRef = AutoDisposeProviderRef; +String _$progressHash() => r'7ed041be2d26a437becc9ab624322b47efbee06e'; + +/// See also [progress]. +@ProviderFor(progress) +final progressProvider = AutoDisposeStreamProvider.internal( + progress, + name: r'progressProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$progressHash, + dependencies: null, + allTransitiveDependencies: null, +); + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +typedef ProgressRef = AutoDisposeStreamProviderRef; +String _$progressBufferedHash() => r'20f886a5ad8bd4eb031eceb845201dc61dfd5fca'; + +/// See also [progressBuffered]. +@ProviderFor(progressBuffered) +final progressBufferedProvider = AutoDisposeStreamProvider.internal( + progressBuffered, + name: r'progressBufferedProvider', + debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') + ? null + : _$progressBufferedHash, + dependencies: null, + allTransitiveDependencies: null, +); + +@Deprecated('Will be removed in 3.0. Use Ref instead') +// ignore: unused_element +typedef ProgressBufferedRef = AutoDisposeStreamProviderRef; +String _$absPlayerHash() => r'c43c02b600326c2d47b900cb3977cd9fae201463'; + +/// See also [AbsPlayer]. +@ProviderFor(AbsPlayer) +final absPlayerProvider = NotifierProvider.internal( + AbsPlayer.new, + name: r'absPlayerProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$absPlayerHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$AbsPlayer = Notifier; +String _$playerStateHash() => r'eb79bd816714f721da1c4226d4447de5dc55fc5c'; + +/// See also [PlayerState]. +@ProviderFor(PlayerState) +final playerStateProvider = + AutoDisposeNotifierProvider.internal( + PlayerState.new, + name: r'playerStateProvider', + debugGetCreateSourceHash: + const bool.fromEnvironment('dart.vm.product') ? null : _$playerStateHash, + dependencies: null, + allTransitiveDependencies: null, +); + +typedef _$PlayerState = AutoDisposeNotifier; +String _$currentTimeHash() => r'e2cf66f5f04cd51f5ddafd64ace395ec3bf0ede2'; /// Copied from Dart SDK class _SystemHash { @@ -64,16 +142,25 @@ class _SystemHash { } } -/// See also [currentTime]. -@ProviderFor(currentTime) +abstract class _$CurrentTime + extends BuildlessAutoDisposeAsyncNotifier { + late final String libraryItemId; + + FutureOr build( + String libraryItemId, + ); +} + +/// See also [CurrentTime]. +@ProviderFor(CurrentTime) const currentTimeProvider = CurrentTimeFamily(); -/// See also [currentTime]. -class CurrentTimeFamily extends Family> { - /// See also [currentTime]. +/// See also [CurrentTime]. +class CurrentTimeFamily extends Family> { + /// See also [CurrentTime]. const CurrentTimeFamily(); - /// See also [currentTime]. + /// See also [CurrentTime]. CurrentTimeProvider call( String libraryItemId, ) { @@ -106,16 +193,14 @@ class CurrentTimeFamily extends Family> { String? get name => r'currentTimeProvider'; } -/// See also [currentTime]. -class CurrentTimeProvider extends AutoDisposeFutureProvider { - /// See also [currentTime]. +/// See also [CurrentTime]. +class CurrentTimeProvider extends AutoDisposeAsyncNotifierProviderImpl< + CurrentTime, shelfsdk.MediaProgress?> { + /// See also [CurrentTime]. CurrentTimeProvider( String libraryItemId, ) : this._internal( - (ref) => currentTime( - ref as CurrentTimeRef, - libraryItemId, - ), + () => CurrentTime()..libraryItemId = libraryItemId, from: currentTimeProvider, name: r'currentTimeProvider', debugGetCreateSourceHash: @@ -141,13 +226,20 @@ class CurrentTimeProvider extends AutoDisposeFutureProvider { final String libraryItemId; @override - Override overrideWith( - FutureOr Function(CurrentTimeRef provider) create, + FutureOr runNotifierBuild( + covariant CurrentTime notifier, ) { + return notifier.build( + libraryItemId, + ); + } + + @override + Override overrideWith(CurrentTime Function() create) { return ProviderOverride( origin: this, override: CurrentTimeProvider._internal( - (ref) => create(ref as CurrentTimeRef), + () => create()..libraryItemId = libraryItemId, from: from, name: null, dependencies: null, @@ -159,7 +251,8 @@ class CurrentTimeProvider extends AutoDisposeFutureProvider { } @override - AutoDisposeFutureProviderElement createElement() { + AutoDisposeAsyncNotifierProviderElement + createElement() { return _CurrentTimeProviderElement(this); } @@ -179,73 +272,27 @@ class CurrentTimeProvider extends AutoDisposeFutureProvider { @Deprecated('Will be removed in 3.0. Use Ref instead') // ignore: unused_element -mixin CurrentTimeRef on AutoDisposeFutureProviderRef { +mixin CurrentTimeRef + on AutoDisposeAsyncNotifierProviderRef { /// The parameter `libraryItemId` of this provider. String get libraryItemId; } class _CurrentTimeProviderElement - extends AutoDisposeFutureProviderElement with CurrentTimeRef { + extends AutoDisposeAsyncNotifierProviderElement with CurrentTimeRef { _CurrentTimeProviderElement(super.provider); @override String get libraryItemId => (origin as CurrentTimeProvider).libraryItemId; } -String _$positionChapterHash() => r'ac6148e92363fad849713c07045503653dcaa7e8'; - -/// See also [positionChapter]. -@ProviderFor(positionChapter) -final positionChapterProvider = AutoDisposeStreamProvider.internal( - positionChapter, - name: r'positionChapterProvider', - debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') - ? null - : _$positionChapterHash, - dependencies: null, - allTransitiveDependencies: null, -); - -@Deprecated('Will be removed in 3.0. Use Ref instead') -// ignore: unused_element -typedef PositionChapterRef = AutoDisposeStreamProviderRef; -String _$absPlayerHash() => r'370f576d3d3a2196d1a93f2046005c1a3298d994'; - -/// See also [AbsPlayer]. -@ProviderFor(AbsPlayer) -final absPlayerProvider = NotifierProvider.internal( - AbsPlayer.new, - name: r'absPlayerProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$absPlayerHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$AbsPlayer = Notifier; -String _$playerStateHash() => r'eb79bd816714f721da1c4226d4447de5dc55fc5c'; - -/// 音频播放器 riverpod状态 -/// -/// Copied from [PlayerState]. -@ProviderFor(PlayerState) -final playerStateProvider = - AutoDisposeNotifierProvider.internal( - PlayerState.new, - name: r'playerStateProvider', - debugGetCreateSourceHash: - const bool.fromEnvironment('dart.vm.product') ? null : _$playerStateHash, - dependencies: null, - allTransitiveDependencies: null, -); - -typedef _$PlayerState = AutoDisposeNotifier; -String _$currentBookHash() => r'85de9041d356e214761b65bd1b7b74321d5a9221'; +String _$currentBookHash() => r'f13ba110d104be8bae48972d6fd266d461d30898'; /// See also [CurrentBook]. @ProviderFor(CurrentBook) final currentBookProvider = - AutoDisposeNotifierProvider.internal( + AutoDisposeNotifierProvider.internal( CurrentBook.new, name: r'currentBookProvider', debugGetCreateSourceHash: @@ -254,13 +301,13 @@ final currentBookProvider = allTransitiveDependencies: null, ); -typedef _$CurrentBook = AutoDisposeNotifier; -String _$currentChapterHash() => r'aff83aed7d098099805ec7d72ea84fff3a298522'; +typedef _$CurrentBook = AutoDisposeNotifier; +String _$currentChapterHash() => r'e8d867067f383372afd758186f13950a6746ba85'; /// See also [CurrentChapter]. @ProviderFor(CurrentChapter) final currentChapterProvider = - AutoDisposeNotifierProvider.internal( + AutoDisposeNotifierProvider.internal( CurrentChapter.new, name: r'currentChapterProvider', debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product') @@ -270,6 +317,6 @@ final currentChapterProvider = allTransitiveDependencies: null, ); -typedef _$CurrentChapter = AutoDisposeNotifier; +typedef _$CurrentChapter = 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/view/player_expanded.dart b/lib/features/player/view/player_expanded.dart index b62ecd6..1640044 100644 --- a/lib/features/player/view/player_expanded.dart +++ b/lib/features/player/view/player_expanded.dart @@ -105,22 +105,11 @@ class PlayerExpanded extends HookConsumerWidget { left: AppElementSizes.paddingRegular, right: AppElementSizes.paddingRegular, ), - child: const AudiobookChapterProgressBar(), + child: const AbsDesktopProgressBar(), ), ), ), - SizedBox( - width: imageSize, - child: Padding( - padding: EdgeInsets.only( - left: AppElementSizes.paddingRegular, - right: AppElementSizes.paddingRegular, - ), - child: const AudiobookProgressBar(), - ), - ), - // the chapter skip buttons, seek 30 seconds back and forward, and play/pause button Expanded( flex: 2, diff --git a/lib/features/player/view/player_expanded_desktop.dart b/lib/features/player/view/player_expanded_desktop.dart index 894ae34..dc9ae29 100644 --- a/lib/features/player/view/player_expanded_desktop.dart +++ b/lib/features/player/view/player_expanded_desktop.dart @@ -110,9 +110,9 @@ class PlayerExpandedDesktop extends HookConsumerWidget { children: [ Padding( padding: EdgeInsets.symmetric( - horizontal: AppElementSizes.paddingRegular, + horizontal: AppElementSizes.paddingLarge, ), - child: const AudiobookChapterProgressBar( + child: const AbsDesktopProgressBar( timeLabelLocation: TimeLabelLocation.sides, ), ), @@ -140,10 +140,10 @@ class PlayerExpandedDesktop extends HookConsumerWidget { // mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( - flex: 1, child: Row(), ), Expanded( + flex: 1, child: Hero( tag: HeroTagPrefixes.controlsCenter, child: const PlayerControlsDesktopCenter(), diff --git a/lib/features/player/view/player_minimized.dart b/lib/features/player/view/player_minimized.dart index 42696c5..1398168 100644 --- a/lib/features/player/view/player_minimized.dart +++ b/lib/features/player/view/player_minimized.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/constants/hero_tag_conventions.dart'; @@ -8,12 +7,12 @@ import 'package:vaani/features/player/providers/abs_provider.dart'; import 'package:vaani/features/player/view/widgets/audiobook_player_seek_button.dart'; import 'package:vaani/features/player/view/widgets/audiobook_player_seek_chapter_button.dart'; import 'package:vaani/features/player/view/widgets/player_player_pause_button.dart'; +import 'package:vaani/features/player/view/widgets/player_progress_bar.dart'; import 'package:vaani/features/player/view/widgets/player_speed_adjust_button.dart'; import 'package:vaani/features/skip_start_end/view/skip_start_end_button.dart'; import 'package:vaani/features/sleep_timer/view/sleep_timer_button.dart'; import 'package:vaani/globals.dart'; import 'package:vaani/router/router.dart'; -import 'package:vaani/shared/extensions/chapter.dart'; import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/widgets/shelves/book_shelf.dart'; @@ -29,16 +28,16 @@ class PlayerMinimized extends HookConsumerWidget { final size = MediaQuery.of(context).size; // 竖屏 final isVertical = size.height > size.width; - return Container( + return SizedBox( height: playerMinHeight, - color: Theme.of(context).colorScheme.surface, + // color: Theme.of(context).colorScheme.surface, child: Stack( alignment: Alignment.topCenter, children: [ isVertical ? const PlayerMinimizedControls() : const PlayerMinimizedControlsDesktop(), - const PlayerMinimizedProgress(), + const AbsMinimizedProgress(), ], ), ); @@ -145,36 +144,14 @@ class PlayerMinimizedControls extends HookConsumerWidget { } } -class PlayerMinimizedProgress extends HookConsumerWidget { - const PlayerMinimizedProgress({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final currentChapter = ref.watch(currentChapterProvider); - - final progress = useStream( - ref.read(absPlayerProvider).positionInChapterStream, - initialData: Duration.zero, - ); - return SizedBox( - height: AppElementSizes.barHeight, - child: LinearProgressIndicator( - value: (progress.data ?? Duration.zero).inSeconds / - (currentChapter?.duration.inSeconds ?? 1), - // color: Theme.of(context).colorScheme.onPrimaryContainer, - // backgroundColor: Theme.of(context).colorScheme.primaryContainer, - ), - ); - } -} - class PlayerMinimizedControlsDesktop extends HookConsumerWidget { const PlayerMinimizedControlsDesktop({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { final currentBook = ref.watch(currentBookProvider); - final currentChapter = ref.watch(currentChapterProvider); + final absPlayer = ref.watch(absPlayerProvider); + ref.watch(currentChapterProvider); return MouseRegion( cursor: SystemMouseCursors.click, // 桌面端显示手型光标 @@ -210,7 +187,8 @@ class PlayerMinimizedControlsDesktop extends HookConsumerWidget { }, child: Hero( tag: HeroTagPrefixes.bookCoverWith( - currentBook?.libraryItemId), + currentBook?.libraryItemId, + ), child: BookCoverWidget( playerMinHeight, itemId: currentBook?.libraryItemId, @@ -231,18 +209,14 @@ class PlayerMinimizedControlsDesktop extends HookConsumerWidget { children: [ // AutoScrollText( Text( - currentChapter?.title ?? - currentBook?.metadata.title ?? - '', + absPlayer.primaryTitle(), maxLines: 1, overflow: TextOverflow.ellipsis, // velocity: // const Velocity(pixelsPerSecond: Offset(16, 0)), style: Theme.of(context).textTheme.bodyLarge, ), Text( - currentBook?.metadata.asBookMetadataExpanded - .authorName ?? - '', + absPlayer.secondaryTitle(), maxLines: 1, overflow: TextOverflow.ellipsis, style: Theme.of(context) @@ -263,6 +237,7 @@ class PlayerMinimizedControlsDesktop extends HookConsumerWidget { ), ), Expanded( + flex: 1, child: Hero( tag: HeroTagPrefixes.controlsCenter, child: const PlayerControlsDesktopCenter(), diff --git a/lib/features/player/view/widgets/player_progress_bar.dart b/lib/features/player/view/widgets/player_progress_bar.dart index f4419da..44cec52 100644 --- a/lib/features/player/view/widgets/player_progress_bar.dart +++ b/lib/features/player/view/widgets/player_progress_bar.dart @@ -1,60 +1,44 @@ import 'package:audio_video_progress_bar/audio_video_progress_bar.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:vaani/constants/sizes.dart'; import 'package:vaani/features/player/providers/abs_provider.dart'; +import 'package:vaani/features/settings/app_settings_provider.dart'; -// 章节进度 -class AudiobookChapterProgressBar extends HookConsumerWidget { +/// 进度条展示 根据设置显示章节进度或整本书的进度 +class AbsDesktopProgressBar extends HookConsumerWidget { final TimeLabelLocation timeLabelLocation; - const AudiobookChapterProgressBar({ + const AbsDesktopProgressBar({ super.key, this.timeLabelLocation = TimeLabelLocation.below, }); @override Widget build(BuildContext context, WidgetRef ref) { - final book = ref.watch(currentBookProvider); final player = ref.watch(absPlayerProvider); final currentChapter = ref.watch(currentChapterProvider); - final position = useStream( - player.positionInBookStream, - initialData: const Duration(seconds: 0), - ); - final buffered = useStream( - player.bufferedPositionInBookStream, - initialData: const Duration(seconds: 0), - ); + final playerSettings = + ref.watch(appSettingsProvider.select((v) => v.playerSettings)); + final showChapterProgress = + playerSettings.expandedPlayerSettings.showChapterProgress; - // now find the chapter that corresponds to the current time - // and calculate the progress of the current chapter - final currentChapterProgress = currentChapter == null - ? null - : (player.positionInBook - currentChapter.start); + final position = ref.watch(progressProvider); + final buffered = ref.watch(progressBufferedProvider); - final currentChapterBuffered = currentChapter == null - ? null - : (player.bufferedPositionInBook - currentChapter.start); - - final progress = - currentChapterProgress ?? position.data ?? const Duration(seconds: 0); - final total = currentChapter == null - ? book?.duration ?? const Duration(seconds: 0) - : currentChapter.end - currentChapter.start; + final total = ref.watch(totalProvider); return ProgressBar( - progress: progress, + progress: position.requireValue, total: total, - // ! TODO add onSeek onSeek: (duration) { player.seekInBook( - duration + (currentChapter?.start ?? const Duration(seconds: 0)), + duration + + (showChapterProgress + ? (currentChapter?.start ?? Duration.zero) + : Duration.zero), ); - // player.seek(duration); }, thumbRadius: 8, - buffered: - currentChapterBuffered ?? buffered.data ?? const Duration(seconds: 0), + buffered: buffered.requireValue, bufferedBarColor: Theme.of(context).colorScheme.secondary, timeLabelType: TimeLabelType.remainingTime, timeLabelLocation: timeLabelLocation, @@ -63,26 +47,19 @@ class AudiobookChapterProgressBar extends HookConsumerWidget { } // 书籍进度 简化版 -class AudiobookProgressBar extends HookConsumerWidget { - const AudiobookProgressBar({ - super.key, - }); +class AbsMinimizedProgress extends HookConsumerWidget { + const AbsMinimizedProgress({super.key}); @override Widget build(BuildContext context, WidgetRef ref) { - final book = ref.watch(currentBookProvider); - final player = ref.read(absPlayerProvider); - final position = useStream( - player.positionInBookStream, - initialData: const Duration(seconds: 0), - ); - + final position = ref.watch(progressProvider); + final total = ref.watch(totalProvider); return SizedBox( - height: AppElementSizes.barHeightLarge, + height: AppElementSizes.barHeight, child: LinearProgressIndicator( - value: (position.data ?? const Duration(seconds: 0)).inSeconds / - (book?.duration ?? const Duration(seconds: 0)).inSeconds, - borderRadius: BorderRadiusGeometry.all(Radius.circular(10)), + value: total > Duration.zero + ? ((position.value ?? Duration.zero).inSeconds / total.inSeconds) + : 0, ), ); } diff --git a/lib/features/settings/api_settings_provider.dart b/lib/features/settings/api_settings_provider.dart index 2767909..d6ef6dc 100644 --- a/lib/features/settings/api_settings_provider.dart +++ b/lib/features/settings/api_settings_provider.dart @@ -8,7 +8,7 @@ import 'package:vaani/shared/extensions/obfuscation.dart'; part 'api_settings_provider.g.dart'; -final _box = AvailableHiveBoxes.apiSettingsBox; +final _box = HiveBoxes.apiSettingsBox; final _logger = Logger('ApiSettingsProvider'); diff --git a/lib/features/settings/app_settings_provider.dart b/lib/features/settings/app_settings_provider.dart index 05509ed..63f8ea7 100644 --- a/lib/features/settings/app_settings_provider.dart +++ b/lib/features/settings/app_settings_provider.dart @@ -7,7 +7,7 @@ import 'package:vaani/features/settings/models/app_settings.dart' as model; part 'app_settings_provider.g.dart'; -final _box = AvailableHiveBoxes.userPrefsBox; +final _box = HiveBoxes.userPrefsBox; final _logger = Logger('AppSettingsProvider'); diff --git a/lib/features/settings/view/shake_detector_settings_page.dart b/lib/features/settings/view/shake_detector_settings_page.dart index 4896485..7ed12bb 100644 --- a/lib/features/settings/view/shake_detector_settings_page.dart +++ b/lib/features/settings/view/shake_detector_settings_page.dart @@ -1,3 +1,5 @@ +// ignore_for_file: unreachable_switch_default + import 'package:flutter/material.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_settings_ui/flutter_settings_ui.dart'; diff --git a/lib/features/shake_detector/shake_detector_provider.dart b/lib/features/shake_detector/shake_detector_provider.dart index 5b8c540..992d4e4 100644 --- a/lib/features/shake_detector/shake_detector_provider.dart +++ b/lib/features/shake_detector/shake_detector_provider.dart @@ -1,9 +1,10 @@ +// ignore_for_file: unreachable_switch_default, unused_element + import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:just_audio/just_audio.dart'; import 'package:logging/logging.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart'; -import 'package:vaani/features/player/providers/abs_provider.dart' - hide AudioPlayer; +import 'package:vaani/features/player/providers/abs_provider.dart'; import 'package:vaani/features/settings/app_settings_provider.dart' show appSettingsProvider; import 'package:vaani/features/settings/models/app_settings.dart'; diff --git a/lib/features/skip_start_end/view/skip_start_end_button.dart b/lib/features/skip_start_end/view/skip_start_end_button.dart index a0eea44..17530e5 100644 --- a/lib/features/skip_start_end/view/skip_start_end_button.dart +++ b/lib/features/skip_start_end/view/skip_start_end_button.dart @@ -73,6 +73,7 @@ class PlayerSkipChapterStartEnd extends HookConsumerWidget { bookSettings.copyWith .playerSettings(skipChapterStart: interval), ); + reloadPlayer(ref); }, ), ), @@ -97,6 +98,7 @@ class PlayerSkipChapterStartEnd extends HookConsumerWidget { bookSettings.copyWith .playerSettings(skipChapterEnd: interval), ); + reloadPlayer(ref); }, ), ), @@ -104,4 +106,15 @@ class PlayerSkipChapterStartEnd extends HookConsumerWidget { ), ); } + + void reloadPlayer(WidgetRef ref) { + final currentBook = ref.watch(currentBookProvider); + if (currentBook == null) { + return; + } + final absPlayer = ref.read(absPlayerProvider); + final positionInBook = absPlayer.positionInBook; + ref.read(currentBookProvider.notifier).update(currentBook.libraryItemId, + force: true, currentTime: positionInBook); + } } diff --git a/lib/features/statistics/abs_statistics.dart b/lib/features/statistics/abs_statistics.dart new file mode 100644 index 0000000..b05b12a --- /dev/null +++ b/lib/features/statistics/abs_statistics.dart @@ -0,0 +1,16 @@ +import 'package:flutter/material.dart'; +import 'package:hooks_riverpod/hooks_riverpod.dart'; + +class LibraryStatisticsPage extends HookConsumerWidget { + const LibraryStatisticsPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Scaffold( + appBar: AppBar( + title: Text('统计'), + ), + // body: Text('统计'), + ); + } +} diff --git a/lib/generated/intl/messages_en.dart b/lib/generated/intl/messages_en.dart index 3db6b53..a643ef8 100644 --- a/lib/generated/intl/messages_en.dart +++ b/lib/generated/intl/messages_en.dart @@ -38,500 +38,476 @@ 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, - "downloadSettings": MessageLookupByLibrary.simpleMessage( - "Download Settings", - ), - "downloadSettingsDescription": MessageLookupByLibrary.simpleMessage( - "Customize download settings", - ), - "erArmedText": MessageLookupByLibrary.simpleMessage("Release ready"), - "erDragText": MessageLookupByLibrary.simpleMessage("Pull to refresh"), - "erDragTextUp": MessageLookupByLibrary.simpleMessage("Pull to refresh"), - "erFailedText": MessageLookupByLibrary.simpleMessage("Failed"), - "erMessageText": - MessageLookupByLibrary.simpleMessage("Last updated at %T"), - "erNoMoreText": MessageLookupByLibrary.simpleMessage("No more"), - "erProcessedText": MessageLookupByLibrary.simpleMessage("Succeeded"), - "erProcessingText": - MessageLookupByLibrary.simpleMessage("Refreshing..."), - "erReadyText": MessageLookupByLibrary.simpleMessage("Refreshing..."), - "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, + "downloadSettings": MessageLookupByLibrary.simpleMessage( + "Download Settings", + ), + "downloadSettingsDescription": MessageLookupByLibrary.simpleMessage( + "Customize download settings", + ), + "erArmedText": MessageLookupByLibrary.simpleMessage("Release ready"), + "erDragText": MessageLookupByLibrary.simpleMessage("Pull to refresh"), + "erDragTextUp": MessageLookupByLibrary.simpleMessage("Pull to refresh"), + "erFailedText": MessageLookupByLibrary.simpleMessage("Failed"), + "erMessageText": MessageLookupByLibrary.simpleMessage("Last updated at %T"), + "erNoMoreText": MessageLookupByLibrary.simpleMessage("No more"), + "erProcessedText": MessageLookupByLibrary.simpleMessage("Succeeded"), + "erProcessingText": MessageLookupByLibrary.simpleMessage("Refreshing..."), + "erReadyText": MessageLookupByLibrary.simpleMessage("Refreshing..."), + "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 09f44b3..a3a79d2 100644 --- a/lib/generated/intl/messages_zh.dart +++ b/lib/generated/intl/messages_zh.dart @@ -38,367 +38,338 @@ 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, - "downloadSettings": MessageLookupByLibrary.simpleMessage("下载设置"), - "downloadSettingsDescription": MessageLookupByLibrary.simpleMessage( - "自定义下载设置", - ), - "erArmedText": MessageLookupByLibrary.simpleMessage("准备就绪"), - "erDragText": MessageLookupByLibrary.simpleMessage("下拉刷新"), - "erDragTextUp": MessageLookupByLibrary.simpleMessage("上拉加载"), - "erFailedText": MessageLookupByLibrary.simpleMessage("失败"), - "erMessageText": MessageLookupByLibrary.simpleMessage("最后更新于 %T"), - "erNoMoreText": MessageLookupByLibrary.simpleMessage("没有更多"), - "erProcessedText": MessageLookupByLibrary.simpleMessage("成功"), - "erProcessingText": MessageLookupByLibrary.simpleMessage("刷新..."), - "erReadyText": MessageLookupByLibrary.simpleMessage("刷新..."), - "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, + "downloadSettings": MessageLookupByLibrary.simpleMessage("下载设置"), + "downloadSettingsDescription": MessageLookupByLibrary.simpleMessage( + "自定义下载设置", + ), + "erArmedText": MessageLookupByLibrary.simpleMessage("准备就绪"), + "erDragText": MessageLookupByLibrary.simpleMessage("下拉刷新"), + "erDragTextUp": MessageLookupByLibrary.simpleMessage("上拉加载"), + "erFailedText": MessageLookupByLibrary.simpleMessage("失败"), + "erMessageText": MessageLookupByLibrary.simpleMessage("最后更新于 %T"), + "erNoMoreText": MessageLookupByLibrary.simpleMessage("没有更多"), + "erProcessedText": MessageLookupByLibrary.simpleMessage("成功"), + "erProcessingText": MessageLookupByLibrary.simpleMessage("刷新..."), + "erReadyText": MessageLookupByLibrary.simpleMessage("刷新..."), + "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/pages/library_page.dart b/lib/pages/library_page.dart index 553351f..90b7c33 100644 --- a/lib/pages/library_page.dart +++ b/lib/pages/library_page.dart @@ -20,7 +20,6 @@ import 'package:vaani/shared/extensions/model_conversions.dart'; import 'package:vaani/shared/extensions/style.dart'; import 'package:vaani/shared/icons/abs_icons.dart'; import 'package:vaani/shared/utils/components.dart'; -import 'package:vaani/shared/widgets/custom_dropdown.dart'; import 'package:vaani/shared/widgets/skeletons.dart'; class LibraryPage extends HookConsumerWidget { @@ -83,21 +82,21 @@ class LibraryPage extends HookConsumerWidget { // ), const LibraryItemsSort(), IconButton( - icon: Icon(Icons.next_plan), - tooltip: '加载下一页', // Helpful tooltip for users - onPressed: () => ref.read(libraryItemsProvider.notifier).loadMore(), - ), - IconButton( - icon: Icon(Icons.refresh), - tooltip: '刷新', // Helpful tooltip for users - onPressed: () => ref.read(libraryItemsProvider.notifier).refresh(), + icon: Icon(Icons.bar_chart), + tooltip: '统计', + onPressed: () => + GoRouter.of(context).pushNamed(Routes.libraryStatistics.name), ), + // IconButton( + // icon: Icon(Icons.refresh), + // tooltip: '刷新', // Helpful tooltip for users + // onPressed: () => ref.read(libraryItemsProvider.notifier).refresh(), + // ), IconButton( icon: Icon(Icons.download), tooltip: S.of(context).bookDownloads, // Helpful tooltip for users - onPressed: () { - GoRouter.of(context).pushNamed(Routes.downloads.name); - }, + onPressed: () => + GoRouter.of(context).pushNamed(Routes.downloads.name), ), ], ), diff --git a/lib/router/constants.dart b/lib/router/constants.dart index 0891987..fd8db7d 100644 --- a/lib/router/constants.dart +++ b/lib/router/constants.dart @@ -21,6 +21,11 @@ class Routes { pathParamName: 'itemId', name: 'libraryItem', ); + static const libraryStatistics = _SimpleRoute( + pathName: 'statistics', + // pathParamName: 'statistics', + name: 'libraryStatistics', + ); // Local settings static const settings = _SimpleRoute( diff --git a/lib/router/router.dart b/lib/router/router.dart index a49f246..50ac597 100644 --- a/lib/router/router.dart +++ b/lib/router/router.dart @@ -15,6 +15,7 @@ import 'package:vaani/features/settings/view/notification_settings_page.dart'; import 'package:vaani/features/settings/view/player_settings_page.dart'; import 'package:vaani/features/settings/view/shake_detector_settings_page.dart'; import 'package:vaani/features/settings/view/theme_settings_page.dart'; +import 'package:vaani/features/statistics/abs_statistics.dart'; import 'package:vaani/features/you/view/server_manager.dart'; import 'package:vaani/features/you/view/you_page.dart'; import 'package:vaani/globals.dart'; @@ -125,10 +126,18 @@ class MyAppRouter { // pageBuilder: defaultPageBuilder(const LibraryBrowserPage()), // ), GoRoute( - path: Routes.library.localPath, - name: Routes.library.name, - pageBuilder: defaultPageBuilder(LibraryPage()), - ), + path: Routes.library.localPath, + name: Routes.library.name, + pageBuilder: defaultPageBuilder(LibraryPage()), + routes: [ + GoRoute( + path: Routes.libraryStatistics.pathName, + name: Routes.libraryStatistics.name, + pageBuilder: defaultPageBuilder( + const LibraryStatisticsPage(), + ), + ), + ]), ], ), // search/explore page diff --git a/lib/router/scaffold_with_nav_bar.dart b/lib/router/scaffold_with_nav_bar.dart index a0a5df1..932466c 100644 --- a/lib/router/scaffold_with_nav_bar.dart +++ b/lib/router/scaffold_with_nav_bar.dart @@ -35,12 +35,18 @@ class ScaffoldWithNavBar extends HookConsumerWidget { final size = MediaQuery.of(context).size; // 竖屏 final isVertical = size.height > size.width; + final currentBook = ref.watch(currentBookProvider); return Scaffold( body: Stack( alignment: Alignment.bottomCenter, children: [ - isVertical ? navigationShell : buildNavLeft(context, ref), + Padding( + padding: EdgeInsets.only( + bottom: currentBook != null ? playerMinHeight : 0, + ), + child: isVertical ? navigationShell : buildNavLeft(context, ref), + ), const PlayerMinimized(), ], ), @@ -49,67 +55,62 @@ class ScaffoldWithNavBar extends HookConsumerWidget { } Widget buildNavLeft(BuildContext context, WidgetRef ref) { - final currentBook = ref.watch(currentBookProvider); - return Padding( - padding: - EdgeInsets.only(bottom: currentBook != null ? playerMinHeight : 0), - child: Row( - children: [ - SafeArea( - child: NavigationRail( - minWidth: 60, - minExtendedWidth: 180, - extended: MediaQuery.of(context).size.width > 640, - // extended: false, - destinations: _navigationItems(context).map((item) { - final isDestinationLibrary = item.name == S.of(context).library; - var currentLibrary = - ref.watch(currentLibraryProvider).valueOrNull; - final libraryIcon = AbsIcons.getIconByName( - currentLibrary?.icon, - ); - final destinationWidget = NavigationRailDestination( - icon: Icon( - isDestinationLibrary ? libraryIcon ?? item.icon : item.icon, - ), - selectedIcon: Icon( - isDestinationLibrary - ? libraryIcon ?? item.activeIcon - : item.activeIcon, - ), - label: Text( - isDestinationLibrary - ? currentLibrary?.name ?? item.name - : item.name, - ), - // tooltip: item.tooltip, - ); - // if (isDestinationLibrary) { - // return GestureDetector( - // onSecondaryTap: () => showLibrarySwitcher(context, ref), - // onDoubleTap: () => showLibrarySwitcher(context, ref), - // child: - // destinationWidget, // Wrap the actual NavigationDestination - // ); - // } else { - // // Return the unwrapped destination for other items - // return destinationWidget; - // } - return destinationWidget; - // return NavigationRailDestination(icon: Icon(nav.icon), label: Text(nav.name)); - }).toList(), - selectedIndex: navigationShell.currentIndex, - onDestinationSelected: (int index) { - _onTap(context, index, ref); - }, - ), + return Row( + children: [ + SafeArea( + child: NavigationRail( + minWidth: 60, + minExtendedWidth: 180, + extended: MediaQuery.of(context).size.width > 640, + // extended: false, + destinations: _navigationItems(context).map((item) { + final isDestinationLibrary = item.name == S.of(context).library; + var currentLibrary = + ref.watch(currentLibraryProvider).valueOrNull; + final libraryIcon = AbsIcons.getIconByName( + currentLibrary?.icon, + ); + final destinationWidget = NavigationRailDestination( + icon: Icon( + isDestinationLibrary ? libraryIcon ?? item.icon : item.icon, + ), + selectedIcon: Icon( + isDestinationLibrary + ? libraryIcon ?? item.activeIcon + : item.activeIcon, + ), + label: Text( + isDestinationLibrary + ? currentLibrary?.name ?? item.name + : item.name, + ), + // tooltip: item.tooltip, + ); + // if (isDestinationLibrary) { + // return GestureDetector( + // onSecondaryTap: () => showLibrarySwitcher(context, ref), + // onDoubleTap: () => showLibrarySwitcher(context, ref), + // child: + // destinationWidget, // Wrap the actual NavigationDestination + // ); + // } else { + // // Return the unwrapped destination for other items + // return destinationWidget; + // } + return destinationWidget; + // return NavigationRailDestination(icon: Icon(nav.icon), label: Text(nav.name)); + }).toList(), + selectedIndex: navigationShell.currentIndex, + onDestinationSelected: (int index) { + _onTap(context, index, ref); + }, ), - VerticalDivider(width: 0.5, thickness: 0.5), - Expanded( - child: navigationShell, - ), - ], - ), + ), + VerticalDivider(width: 0.5, thickness: 0.5), + Expanded( + child: navigationShell, + ), + ], ); } diff --git a/pubspec.lock b/pubspec.lock index 806d8a7..186178d 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -626,14 +626,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.3" - hive_ce_generator: - dependency: "direct dev" - description: - name: hive_ce_generator - sha256: "182fb88273055e05ef0e630b5e32e5a30268722ed3bf46fdf5986792862975af" - url: "https://pub.dev" - source: hosted - version: "1.8.1" hooks_riverpod: dependency: "direct main" description: @@ -1711,14 +1703,6 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.3" - yaml_writer: - dependency: transitive - description: - name: yaml_writer - sha256: "69651cd7238411179ac32079937d4aa9a2970150d6b2ae2c6fe6de09402a5dc5" - url: "https://pub.dev" - source: hosted - version: "2.1.0" sdks: dart: ">=3.8.0 <4.0.0" flutter: ">=3.32.0" diff --git a/pubspec.yaml b/pubspec.yaml index 00fbb84..ca9a70c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -41,6 +41,8 @@ dependencies: # 图标 icons_plus: ^5.0.0 + # 自动适配Material和Cupertino + #flutter_platform_widgets: ^9.0.0 # hooks flutter_hooks: ^0.21.2 @@ -143,6 +145,8 @@ dependencies: # 分享插件 share_plus: ^10.0.2 + # chart + # fl_chart: ^1.1.1 # AudiobookShelf SDK shelfsdk: @@ -174,7 +178,7 @@ dev_dependencies: freezed: ^2.5.2 json_serializable: ^6.8.0 - hive_ce_generator: ^1.8.1 + # hive_ce_generator: ^1.8.1 # 启动图标 flutter_launcher_icons: "^0.14.4"