feat: right click to open track option

This commit is contained in:
Kingkor Roy Tirtho 2023-09-10 22:50:44 +06:00
parent d4f99ec899
commit 1540999f50
3 changed files with 413 additions and 363 deletions

View File

@ -78,6 +78,31 @@ class AdaptivePopSheetList<T> extends StatelessWidget {
'Either icon or child must be provided',
);
Future<T?> showPopupMenu(BuildContext context, RelativeRect position) {
final mediaQuery = MediaQuery.of(context);
return showMenu<T>(
context: context,
useRootNavigator: useRootNavigator,
constraints: BoxConstraints(
maxHeight: mediaQuery.size.height * 0.6,
),
position: position,
items: children
.map(
(item) => PopupMenuItem<T>(
padding: EdgeInsets.zero,
enabled: false,
child: _AdaptivePopSheetListItem<T>(
item: item,
onSelected: onSelected,
),
),
)
.toList(),
);
}
@override
Widget build(BuildContext context) {
final mediaQuery = MediaQuery.of(context);

View File

@ -14,7 +14,6 @@ import 'package:spotube/components/shared/heart_button.dart';
import 'package:spotube/components/shared/image/universal_image.dart';
import 'package:spotube/extensions/context.dart';
import 'package:spotube/models/local_track.dart';
import 'package:spotube/models/spotube_track.dart';
import 'package:spotube/provider/authentication_provider.dart';
import 'package:spotube/provider/blacklist_provider.dart';
import 'package:spotube/provider/download_manager_provider.dart';
@ -40,9 +39,11 @@ class TrackOptions extends HookConsumerWidget {
final Track track;
final bool userPlaylist;
final String? playlistId;
final ObjectRef<ValueChanged<RelativeRect>?>? showMenuCbRef;
const TrackOptions({
Key? key,
required this.track,
this.showMenuCbRef,
this.userPlaylist = false,
this.playlistId,
}) : super(key: key);
@ -114,11 +115,7 @@ class TrackOptions extends HookConsumerWidget {
return downloadManager.getProgressNotifier(spotubeTrack);
});
return ListTileTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: AdaptivePopSheetList<TrackOptionValue>(
final adaptivePopSheetList = AdaptivePopSheetList<TrackOptionValue>(
onSelected: (value) async {
switch (value) {
case TrackOptionValue.delete:
@ -203,8 +200,7 @@ class TrackOptions extends HookConsumerWidget {
child: ClipRRect(
borderRadius: BorderRadius.circular(10),
child: UniversalImage(
path: TypeConversionUtils.image_X_UrlString(
track.album!.images,
path: TypeConversionUtils.image_X_UrlString(track.album!.images,
placeholder: ImagePlaceholder.albumArt),
fit: BoxFit.cover,
),
@ -317,7 +313,18 @@ class TrackOptions extends HookConsumerWidget {
),
]
},
);
//! This is the most ANTI pattern I've ever done, but it works
showMenuCbRef?.value = (relativeRect) {
adaptivePopSheetList.showPopupMenu(context, relativeRect);
};
return ListTileTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
child: adaptivePopSheetList,
);
}
}

View File

@ -1,3 +1,4 @@
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -57,10 +58,24 @@ class TrackTile extends HookConsumerWidget {
[blacklist, track],
);
final showOptionCbRef = useRef<ValueChanged<RelativeRect>?>(null);
final isPlaying = track.id == playlist.activeTrack?.id;
return LayoutBuilder(builder: (context, constrains) {
return HoverBuilder(
return Listener(
onPointerDown: (event) {
if (event.buttons != kSecondaryMouseButton) return;
showOptionCbRef.value?.call(
RelativeRect.fromLTRB(
event.position.dx,
event.position.dy,
constrains.maxWidth - event.position.dx,
constrains.maxHeight - event.position.dy,
),
);
},
child: HoverBuilder(
permanentState: isPlaying || constrains.smAndDown ? true : null,
builder: (context, isHovering) {
return ListTile(
@ -69,7 +84,8 @@ class TrackTile extends HookConsumerWidget {
onLongPress: onLongPress,
enabled: !isBlackListed,
contentPadding: EdgeInsets.zero,
tileColor: isBlackListed ? theme.colorScheme.errorContainer : null,
tileColor:
isBlackListed ? theme.colorScheme.errorContainer : null,
horizontalTitleGap: 12,
leadingAndTrailingTextStyle: theme.textTheme.bodyMedium,
leading: Row(
@ -220,11 +236,13 @@ class TrackTile extends HookConsumerWidget {
track: track,
playlistId: playlistId,
userPlaylist: userPlaylist,
showMenuCbRef: showOptionCbRef,
),
],
),
);
},
),
);
});
}