Skip to content

Commit

Permalink
feat: Implement playback controller buttons for the Zune view
Browse files Browse the repository at this point in the history
  • Loading branch information
Losses committed Oct 20, 2024
1 parent a28a059 commit f4595d5
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 55 deletions.
183 changes: 132 additions & 51 deletions lib/screens/cover_wall/widgets/small_screen_playing_track.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import 'package:material_symbols_icons/symbols.dart';
import 'package:provider/provider.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:rune/providers/playback_controller.dart';
import 'package:rune/providers/volume.dart';
import 'package:rune/widgets/playback_controller/constants/controller_items.dart';

import '../../../utils/ax_shadow.dart';
import '../../../utils/format_time.dart';
Expand Down Expand Up @@ -27,14 +31,17 @@ class SmallScreenPlayingTrack extends StatelessWidget {

final width = MediaQuery.of(context).size.width;

Provider.of<VolumeProvider>(context);

return Selector<PlaybackStatusProvider,
(String?, String?, String?, String?, double?)>(
(String?, String?, String?, String?, double?, String?)>(
selector: (context, playbackStatusProvider) => (
playbackStatusProvider.playbackStatus?.coverArtPath,
playbackStatusProvider.playbackStatus?.artist,
playbackStatusProvider.playbackStatus?.album,
playbackStatusProvider.playbackStatus?.title,
playbackStatusProvider.playbackStatus?.duration,
playbackStatusProvider.playbackStatus?.state,
),
builder: (context, p, child) {
if (p.$1 == null) return Container();
Expand All @@ -50,68 +57,142 @@ class SmallScreenPlayingTrack extends StatelessWidget {
playbackControllerHeight + 12,
),
constraints: const BoxConstraints(maxWidth: 240),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
SmallerOrEqualTo(
breakpoint: DeviceType.zune,
builder: (context, isSmaller) {
if (isSmaller) return Container();
return Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 4),
boxShadow: axShadow(9),
),
child: AspectRatio(
aspectRatio: 1,
child: CoverArt(
hint: (
p.$3 ?? "",
p.$2 ?? "",
'Total Time ${formatTime(p.$5 ?? 0)}'
child: SmallerOrEqualTo(
breakpoint: DeviceType.zune,
builder: (context, isZune) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
if (!isZune)
Container(
padding: const EdgeInsets.symmetric(horizontal: 10),
child: Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.white, width: 4),
boxShadow: axShadow(9),
),
child: AspectRatio(
aspectRatio: 1,
child: CoverArt(
hint: (
p.$3 ?? "",
p.$2 ?? "",
'Total Time ${formatTime(p.$5 ?? 0)}'
),
key: p.$1 != null ? Key(p.$1.toString()) : null,
path: p.$1,
size: (width - 20).clamp(0, 240),
),
key: p.$1 != null ? Key(p.$1.toString()) : null,
path: p.$1,
size: (width - 20).clamp(0, 240),
),
),
),
);
},
),
SmallerOrEqualTo(
breakpoint: DeviceType.zune,
builder: (context, isSmaller) {
if (isSmaller) return Container();

return Transform.translate(
if (!isZune)
Transform.translate(
offset: const Offset(0, -16),
child: SizedBox(
height: 80,
child: CoverArtPageProgressBar(shadows: shadows),
),
);
}),
const SizedBox(height: 8),
Text(
p.$4 ?? "Unknown Track",
style: typography.subtitle?.apply(shadows: shadows),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
'$artist · $album',
style:
typography.body?.apply(shadows: shadows, heightFactor: 2),
textAlign: TextAlign.center,
),
],
),
const SizedBox(height: 8),
Text(
p.$4 ?? "Unknown Track",
style: typography.subtitle?.apply(shadows: shadows),
textAlign: TextAlign.center,
),
const SizedBox(height: 12),
Text(
'$artist · $album',
style: typography.body
?.apply(shadows: shadows, heightFactor: 2),
textAlign: TextAlign.center,
),
if (isZune) const SizedBox(height: 12),
if (isZune)
Selector<PlaybackControllerProvider,
(List<ControllerEntry>, List<ControllerEntry>)>(
selector: (context, controllerProvider) {
final entries = controllerProvider.entries;
final hiddenIndex =
entries.indexWhere((entry) => entry.id == 'hidden');
final List<ControllerEntry> visibleEntries =
hiddenIndex != -1
? entries.sublist(0, hiddenIndex)
: entries;
final List<ControllerEntry> hiddenEntries =
hiddenIndex != -1
? entries.sublist(hiddenIndex + 1)
: [];

return (visibleEntries, hiddenEntries);
},
builder: (context, entries, child) {
return CommandBar(
isCompact: true,
overflowMenuItemBuilder: (context, entry) {
if (entry is PrimaryCommandBarItem) {
return entry.entry.flyoutEntryBuilder(context);
}

throw "Unacceptable entry type";
},
overflowItemBuilder: (onPressed) {
return OverflowCommandBarItem(
key: const ValueKey("Overflow Item"),
onPressed: onPressed,
);
},
primaryItems: entries.$1
.map(
(x) => PrimaryCommandBarItem(
key: ValueKey(x.id),
entry: x,
),
)
.toList(),
secondaryItems: entries.$2
.map(
(x) => PrimaryCommandBarItem(
key: ValueKey(x.id),
entry: x,
),
)
.toList(),
);
},
)
],
);
},
),
);
},
);
}
}

class PrimaryCommandBarItem extends CommandBarItem {
PrimaryCommandBarItem({required super.key, required this.entry});

final ControllerEntry entry;

@override
Widget build(BuildContext context, CommandBarItemDisplayMode displayMode) {
return entry.controllerButtonBuilder(context);
}
}

class OverflowCommandBarItem extends CommandBarItem {
OverflowCommandBarItem({required super.key, required this.onPressed});

final VoidCallback onPressed;

@override
Widget build(BuildContext context, CommandBarItemDisplayMode displayMode) {
return IconButton(
icon: const Icon(Symbols.more_vert),
onPressed: onPressed,
);
}
}
2 changes: 1 addition & 1 deletion lib/widgets/playback_controller/controller_buttons.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import 'package:provider/provider.dart';
import 'package:go_router/go_router.dart';
import 'package:fluent_ui/fluent_ui.dart';
import 'package:material_symbols_icons/symbols.dart';
import 'package:rune/providers/status.dart';

import '../../widgets/playback_controller/constants/controller_items.dart';
import '../../providers/status.dart';
import '../../providers/playback_controller.dart';
import '../../providers/responsive_providers.dart';

Expand Down
4 changes: 2 additions & 2 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -338,8 +338,8 @@ packages:
dependency: "direct main"
description:
path: "."
ref: "6f3e1695a43ceb5b7d9c14e7563a0d1eaf303814"
resolved-ref: "6f3e1695a43ceb5b7d9c14e7563a0d1eaf303814"
ref: "2186f815de5d6b461775938eb2484d9a3f4162ee"
resolved-ref: "2186f815de5d6b461775938eb2484d9a3f4162ee"
url: "https://github.com/Losses/fluent_ui.git"
source: git
version: "4.9.1"
Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ dependencies:
fluent_ui:
git:
url: https://github.com/Losses/fluent_ui.git
ref: 6f3e1695a43ceb5b7d9c14e7563a0d1eaf303814
ref: 2186f815de5d6b461775938eb2484d9a3f4162ee
flutter_acrylic: ^1.1.4
system_theme: ^3.0.0
go_router: ^14.2.1
Expand Down

0 comments on commit f4595d5

Please sign in to comment.