mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-14 00:15:17 +00:00
feat: right click to open track option
This commit is contained in:
parent
d4f99ec899
commit
1540999f50
@ -78,6 +78,31 @@ class AdaptivePopSheetList<T> extends StatelessWidget {
|
|||||||
'Either icon or child must be provided',
|
'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
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final mediaQuery = MediaQuery.of(context);
|
final mediaQuery = MediaQuery.of(context);
|
||||||
|
@ -14,7 +14,6 @@ import 'package:spotube/components/shared/heart_button.dart';
|
|||||||
import 'package:spotube/components/shared/image/universal_image.dart';
|
import 'package:spotube/components/shared/image/universal_image.dart';
|
||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/models/local_track.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/authentication_provider.dart';
|
||||||
import 'package:spotube/provider/blacklist_provider.dart';
|
import 'package:spotube/provider/blacklist_provider.dart';
|
||||||
import 'package:spotube/provider/download_manager_provider.dart';
|
import 'package:spotube/provider/download_manager_provider.dart';
|
||||||
@ -40,9 +39,11 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
final Track track;
|
final Track track;
|
||||||
final bool userPlaylist;
|
final bool userPlaylist;
|
||||||
final String? playlistId;
|
final String? playlistId;
|
||||||
|
final ObjectRef<ValueChanged<RelativeRect>?>? showMenuCbRef;
|
||||||
const TrackOptions({
|
const TrackOptions({
|
||||||
Key? key,
|
Key? key,
|
||||||
required this.track,
|
required this.track,
|
||||||
|
this.showMenuCbRef,
|
||||||
this.userPlaylist = false,
|
this.userPlaylist = false,
|
||||||
this.playlistId,
|
this.playlistId,
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
@ -114,11 +115,7 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
return downloadManager.getProgressNotifier(spotubeTrack);
|
return downloadManager.getProgressNotifier(spotubeTrack);
|
||||||
});
|
});
|
||||||
|
|
||||||
return ListTileTheme(
|
final adaptivePopSheetList = AdaptivePopSheetList<TrackOptionValue>(
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
child: AdaptivePopSheetList<TrackOptionValue>(
|
|
||||||
onSelected: (value) async {
|
onSelected: (value) async {
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case TrackOptionValue.delete:
|
case TrackOptionValue.delete:
|
||||||
@ -203,8 +200,7 @@ class TrackOptions extends HookConsumerWidget {
|
|||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(10),
|
borderRadius: BorderRadius.circular(10),
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
path: TypeConversionUtils.image_X_UrlString(
|
path: TypeConversionUtils.image_X_UrlString(track.album!.images,
|
||||||
track.album!.images,
|
|
||||||
placeholder: ImagePlaceholder.albumArt),
|
placeholder: ImagePlaceholder.albumArt),
|
||||||
fit: BoxFit.cover,
|
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,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:flutter/gestures.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@ -57,10 +58,24 @@ class TrackTile extends HookConsumerWidget {
|
|||||||
[blacklist, track],
|
[blacklist, track],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final showOptionCbRef = useRef<ValueChanged<RelativeRect>?>(null);
|
||||||
|
|
||||||
final isPlaying = track.id == playlist.activeTrack?.id;
|
final isPlaying = track.id == playlist.activeTrack?.id;
|
||||||
|
|
||||||
return LayoutBuilder(builder: (context, constrains) {
|
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,
|
permanentState: isPlaying || constrains.smAndDown ? true : null,
|
||||||
builder: (context, isHovering) {
|
builder: (context, isHovering) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
@ -69,7 +84,8 @@ class TrackTile extends HookConsumerWidget {
|
|||||||
onLongPress: onLongPress,
|
onLongPress: onLongPress,
|
||||||
enabled: !isBlackListed,
|
enabled: !isBlackListed,
|
||||||
contentPadding: EdgeInsets.zero,
|
contentPadding: EdgeInsets.zero,
|
||||||
tileColor: isBlackListed ? theme.colorScheme.errorContainer : null,
|
tileColor:
|
||||||
|
isBlackListed ? theme.colorScheme.errorContainer : null,
|
||||||
horizontalTitleGap: 12,
|
horizontalTitleGap: 12,
|
||||||
leadingAndTrailingTextStyle: theme.textTheme.bodyMedium,
|
leadingAndTrailingTextStyle: theme.textTheme.bodyMedium,
|
||||||
leading: Row(
|
leading: Row(
|
||||||
@ -220,11 +236,13 @@ class TrackTile extends HookConsumerWidget {
|
|||||||
track: track,
|
track: track,
|
||||||
playlistId: playlistId,
|
playlistId: playlistId,
|
||||||
userPlaylist: userPlaylist,
|
userPlaylist: userPlaylist,
|
||||||
|
showMenuCbRef: showOptionCbRef,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user