Vaani/lib/features/player/view/player_expanded_desktop.dart
2026-01-09 17:58:36 +08:00

191 lines
6.4 KiB
Dart

import 'dart:math';
import 'package:audio_video_progress_bar/audio_video_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shelfsdk/audiobookshelf_api.dart';
import 'package:vaani/constants/hero_tag_conventions.dart';
import 'package:vaani/constants/sizes.dart';
import 'package:vaani/features/item_viewer/view/library_item_hero_section.dart';
import 'package:vaani/features/player/providers/abs_provider.dart';
import 'package:vaani/features/player/view/player_expanded.dart'
show PlayerExpandedImage;
import 'package:vaani/features/player/view/player_minimized.dart';
import 'package:vaani/features/player/view/widgets/chapter_selection_button.dart';
import 'package:vaani/features/player/view/widgets/player_progress_bar.dart';
import 'package:vaani/globals.dart';
import 'package:vaani/shared/extensions/model_conversions.dart';
var pendingPlayerModals = 0;
class PlayerExpandedDesktop extends HookConsumerWidget {
const PlayerExpandedDesktop({
super.key,
});
@override
Widget build(BuildContext context, WidgetRef ref) {
final currentBook = ref.watch(currentBookProvider);
if (currentBook == null) {
return SizedBox.shrink();
}
/// all the properties that help in building the widget are calculated from the [percentageExpandedPlayer]
/// however, some properties need to start later than 0% and end before 100%
final currentChapter = ref.watch(currentChapterProvider);
// final currentBookMetadata = ref.watch(currentBookMetadataProvider);
// max height of the player is the height of the screen
final playerMaxHeight = MediaQuery.of(context).size.height;
final availWidth = MediaQuery.of(context).size.width;
// the image width when the player is expanded
final imageSize = min(playerMaxHeight * 0.5, availWidth * 0.9);
final itemBookMetadata = currentBook.metadata.asBookMetadataExpanded;
return Stack(
alignment: Alignment.bottomCenter,
children: [
Scaffold(
body: Padding(
padding: EdgeInsets.only(
top: AppElementSizes.paddingLarge,
right: AppElementSizes.paddingRegular,
bottom: playerMinHeight + 40,
),
child: Row(
children: [
Expanded(
flex: 45,
child: Column(
children: [
Align(
alignment: Alignment.topCenter,
// add a shadow to the image elevation hovering effect
child: PlayerExpandedImage(
imageSize,
itemId: currentBook.libraryItemId,
),
),
_buildBookDetails(imageSize, itemBookMetadata),
],
),
),
Expanded(
flex: 65,
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
currentChapter == null
? SizedBox.shrink()
: Text(
currentChapter.title,
style: Theme.of(context).textTheme.titleLarge,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
Expanded(
child: DecoratedBox(
decoration: BoxDecoration(
border: Border(
right: BorderSide(
color: Theme.of(context).focusColor,
width: 1.0,
style: BorderStyle.solid, // 可以设置为 dashed 虚线
),
),
),
child: ChapterSelectionModal(
back: false,
),
),
),
],
),
),
],
),
),
),
Column(
mainAxisAlignment: MainAxisAlignment.end,
children: [
Padding(
padding: EdgeInsets.symmetric(
horizontal: AppElementSizes.paddingRegular,
),
child: const AudiobookChapterProgressBar(
timeLabelLocation: TimeLabelLocation.sides,
),
),
SizedBox(
height: playerMinHeight,
child: MouseRegion(
cursor: SystemMouseCursors.click, // 桌面端显示手型光标
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
context.pop();
},
child: _buildBottom(),
),
),
),
],
),
],
);
}
Widget _buildBottom() {
return Row(
// mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
flex: 1,
child: Row(),
),
Expanded(
child: Hero(
tag: HeroTagPrefixes.controlsCenter,
child: const PlayerControlsDesktopCenter(),
),
),
Expanded(
flex: 1,
child: Hero(
tag: HeroTagPrefixes.controlsRight,
child: const PlayerControlsDesktopRight(),
),
),
],
);
}
Widget _buildBookDetails(
double width,
BookMetadataExpanded? itemBookMetadata,
) {
return Container(
padding: EdgeInsets.all(AppElementSizes.paddingLarge),
width: width,
child: Column(
children: [
// authors info if available
BookAuthors(
itemBookMetadata: itemBookMetadata,
bookDetailsCached: null,
),
// narrators info if available
BookNarrators(
itemBookMetadata: itemBookMetadata,
bookDetailsCached: null,
),
// series info if available
BookSeries(
itemBookMetadata: itemBookMetadata,
bookDetailsCached: null,
),
],
),
);
}
}