mirror of
https://github.com/Dr-Blank/Vaani.git
synced 2026-02-16 14:29:35 +00:00
测试安卓修改app名称
This commit is contained in:
parent
6b1edcb475
commit
6ceeb99d20
19 changed files with 1218 additions and 822 deletions
39
lib/features/player/core/abs_audio_handler.dart
Normal file
39
lib/features/player/core/abs_audio_handler.dart
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
|
||||
class AbsAudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler {
|
||||
final AudioPlayer player;
|
||||
|
||||
AbsAudioHandler(this.player);
|
||||
|
||||
// 播放控制方法重写
|
||||
@override
|
||||
Future<void> play() async {
|
||||
await player.play();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> pause() async {
|
||||
await player.pause();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> skipToNext() async {
|
||||
await player.seekToNext();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> skipToPrevious() async {
|
||||
await player.seekToPrevious();
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> seek(Duration position) async {
|
||||
await player.seek(position);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> setSpeed(double speed) async {
|
||||
await player.setSpeed(speed);
|
||||
}
|
||||
}
|
||||
5
lib/features/player/core/abs_audio_player.dart
Normal file
5
lib/features/player/core/abs_audio_player.dart
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
// ignore_for_file: public_member_api_docs, sort_constructors_first
|
||||
import 'package:just_audio/just_audio.dart';
|
||||
import 'package:shelfsdk/audiobookshelf_api.dart';
|
||||
|
||||
class AbsAudioPlayer extends AudioPlayer {}
|
||||
|
|
@ -32,6 +32,7 @@ class AbsAudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler {
|
|||
|
||||
final _currentChapterObject = BehaviorSubject<BookChapter?>.seeded(null);
|
||||
AbsAudioHandler(this.ref) {
|
||||
notificationSettings = ref.read(appSettingsProvider).notificationSettings;
|
||||
ref.listen(appSettingsProvider, (a, b) {
|
||||
if (a?.notificationSettings != b.notificationSettings) {
|
||||
notificationSettings = b.notificationSettings;
|
||||
|
|
@ -52,12 +53,12 @@ class AbsAudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler {
|
|||
final chapter = _book?.findChapterAtTime(positionInBook);
|
||||
if (chapter != currentChapter) {
|
||||
if (mediaItem.hasValue && chapter != null) {
|
||||
updateMediaItem(
|
||||
mediaItem.value!.copyWith(
|
||||
duration: chapter.duration,
|
||||
displayTitle: chapter.title,
|
||||
),
|
||||
);
|
||||
// updateMediaItem(
|
||||
// mediaItem.value!.copyWith(
|
||||
// duration: chapter.duration,
|
||||
// displayTitle: chapter.title,
|
||||
// ),
|
||||
// );
|
||||
}
|
||||
_currentChapterObject.sink.add(chapter);
|
||||
}
|
||||
|
|
|
|||
56
lib/features/player/providers/abs_provider.dart
Normal file
56
lib/features/player/providers/abs_provider.dart
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
import 'package:audio_service/audio_service.dart';
|
||||
import 'package:audio_session/audio_session.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:just_audio_media_kit/just_audio_media_kit.dart';
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:shelfsdk/audiobookshelf_api.dart';
|
||||
import 'package:vaani/features/player/core/abs_audio_handler.dart' as core;
|
||||
import 'package:vaani/features/player/core/abs_audio_player.dart' as core;
|
||||
|
||||
part 'abs_provider.g.dart';
|
||||
|
||||
final _logger = Logger('AbsPlayerProvider');
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
Future<core.AbsAudioHandler> absAudioHandler(Ref ref) async {
|
||||
// for playing audio on windows, linux
|
||||
JustAudioMediaKit.ensureInitialized();
|
||||
|
||||
// for configuring how this app will interact with other audio apps
|
||||
final session = await AudioSession.instance;
|
||||
await session.configure(const AudioSessionConfiguration.speech());
|
||||
|
||||
final player = ref.read(absAudioPlayerProvider);
|
||||
|
||||
final audioService = await AudioService.init(
|
||||
builder: () => core.AbsAudioHandler(player),
|
||||
config: const AudioServiceConfig(
|
||||
androidNotificationChannelId: 'dr.blank.vaani.channel.audio',
|
||||
androidNotificationChannelName: 'ABSPlayback',
|
||||
androidNotificationChannelDescription:
|
||||
'Needed to control audio from lock screen',
|
||||
androidNotificationOngoing: false,
|
||||
androidStopForegroundOnPause: false,
|
||||
androidNotificationIcon: 'drawable/ic_stat_logo',
|
||||
preloadArtwork: true,
|
||||
// fastForwardInterval: Duration(seconds: 20),
|
||||
// rewindInterval: Duration(seconds: 20),
|
||||
),
|
||||
);
|
||||
|
||||
return audioService;
|
||||
}
|
||||
|
||||
@Riverpod(keepAlive: true)
|
||||
class AbsAudioPlayer extends _$AbsAudioPlayer {
|
||||
@override
|
||||
core.AbsAudioPlayer build() {
|
||||
final player = core.AbsAudioPlayer();
|
||||
|
||||
ref.onDispose(player.dispose);
|
||||
_logger.finer('created simple player');
|
||||
|
||||
return player;
|
||||
}
|
||||
}
|
||||
43
lib/features/player/providers/abs_provider.g.dart
Normal file
43
lib/features/player/providers/abs_provider.g.dart
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'abs_provider.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$absAudioHandlerHash() => r'f4ef20cc3e244d5d37354ef38a1e0fdbd89412f4';
|
||||
|
||||
/// See also [absAudioHandler].
|
||||
@ProviderFor(absAudioHandler)
|
||||
final absAudioHandlerProvider = FutureProvider<core.AbsAudioHandler>.internal(
|
||||
absAudioHandler,
|
||||
name: r'absAudioHandlerProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$absAudioHandlerHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef AbsAudioHandlerRef = FutureProviderRef<core.AbsAudioHandler>;
|
||||
String _$absAudioPlayerHash() => r'68a56d45a9f165d257c23f81d9bf7d0930425464';
|
||||
|
||||
/// See also [AbsAudioPlayer].
|
||||
@ProviderFor(AbsAudioPlayer)
|
||||
final absAudioPlayerProvider =
|
||||
NotifierProvider<AbsAudioPlayer, core.AbsAudioPlayer>.internal(
|
||||
AbsAudioPlayer.new,
|
||||
name: r'absAudioPlayerProvider',
|
||||
debugGetCreateSourceHash: const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$absAudioPlayerHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$AbsAudioPlayer = Notifier<core.AbsAudioPlayer>;
|
||||
// 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
|
||||
|
|
@ -99,6 +99,7 @@ List<core.BookChapter> currentChapters(Ref ref) {
|
|||
}
|
||||
final index = book.chapters.indexOf(currentChapter);
|
||||
final total = book.chapters.length;
|
||||
return book.chapters
|
||||
.sublist(index - 3, (total - 3) <= (index + 17) ? total : index + 17);
|
||||
final start = index - 3 >= 0 ? index - 3 : 0;
|
||||
final end = start + 20 <= total ? start + 20 : total;
|
||||
return book.chapters.sublist(start, end);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ part of 'currently_playing_provider.dart';
|
|||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$currentChaptersHash() => r'a25733d8085a2ce7dbc16fa2bf14f00ab8e2a623';
|
||||
String _$currentChaptersHash() => r'6574b3f4ee0af8006f233aaf76cc507d188c6305';
|
||||
|
||||
/// See also [currentChapters].
|
||||
@ProviderFor(currentChapters)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:shelfsdk/audiobookshelf_api.dart';
|
||||
import 'package:vaani/constants/sizes.dart';
|
||||
import 'package:vaani/features/player/providers/audiobook_player.dart';
|
||||
import 'package:vaani/features/player/providers/currently_playing_provider.dart';
|
||||
|
|
@ -137,22 +139,45 @@ class PlayerExpandedDesktop extends HookConsumerWidget {
|
|||
|
||||
class ChapterSelection extends HookConsumerWidget {
|
||||
const ChapterSelection({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final currentChapter = ref.watch(currentChapterProvider);
|
||||
if (currentChapter == null) {
|
||||
return SizedBox.shrink();
|
||||
}
|
||||
final chapters = useState(<BookChapter>[]);
|
||||
final scrollController = useScrollController();
|
||||
useEffect(
|
||||
() {
|
||||
int page = 0;
|
||||
void load(page) {
|
||||
chapters.value.addAll(ref.watch(currentChaptersProvider));
|
||||
}
|
||||
|
||||
final currentChapters = ref.watch(currentChaptersProvider);
|
||||
final currentChapterIndex = currentChapters.indexOf(currentChapter);
|
||||
load(page);
|
||||
void listener() {
|
||||
if (scrollController.position.pixels /
|
||||
scrollController.position.maxScrollExtent >
|
||||
0.8) {
|
||||
print('滚动到底部');
|
||||
}
|
||||
}
|
||||
|
||||
scrollController.addListener(listener);
|
||||
return () => scrollController.removeListener(listener);
|
||||
},
|
||||
[scrollController],
|
||||
);
|
||||
|
||||
final currentChapterIndex = chapters.value.indexOf(currentChapter);
|
||||
final theme = Theme.of(context);
|
||||
return Scrollbar(
|
||||
controller: scrollController,
|
||||
child: ListView.builder(
|
||||
itemCount: currentChapters.length,
|
||||
controller: scrollController,
|
||||
itemCount: chapters.value.length,
|
||||
itemBuilder: (context, index) {
|
||||
final chapter = currentChapters[index];
|
||||
final chapter = chapters.value[index];
|
||||
final isCurrent = currentChapterIndex == index;
|
||||
final isPlayed = index < currentChapterIndex;
|
||||
return ListTile(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue