fix(mobile): dialogs in bottom sheet are not opening

This commit is contained in:
Kingkor Roy Tirtho 2025-04-07 14:53:05 +06:00
parent e986baa0aa
commit 8fc319d980
7 changed files with 64 additions and 51 deletions

View File

@ -3,4 +3,17 @@
to allow setting breakpoints, to provide hot reload, etc. to allow setting breakpoints, to provide hot reload, etc.
--> -->
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application
android:name="${applicationName}"
android:allowBackup="false"
android:fullBackupContent="false"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name_en"
android:requestLegacyExternalStorage="true"
android:usesCleartextTraffic="true">
<!-- Disable Impeller -->
<meta-data
android:name="io.flutter.embedding.android.EnableImpeller"
android:value="false" />
</application>
</manifest> </manifest>

View File

@ -1,4 +1,3 @@
import 'package:flutter/material.dart' show showModalBottomSheet;
import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart'; import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
@ -26,7 +25,7 @@ class AdaptiveMenuButton<T> extends MenuButton {
/// An adaptive widget that shows a [PopupMenuButton] when screen size is above /// An adaptive widget that shows a [PopupMenuButton] when screen size is above
/// or equal to 640px /// or equal to 640px
/// In smaller screen, a [IconButton] with a [showModalBottomSheet] is shown /// In smaller screen, a [IconButton] with a [openDrawer] is shown
class AdaptivePopSheetList<T> extends StatelessWidget { class AdaptivePopSheetList<T> extends StatelessWidget {
final List<AdaptiveMenuButton<T>> Function(BuildContext context) items; final List<AdaptiveMenuButton<T>> Function(BuildContext context) items;
final Widget? icon; final Widget? icon;
@ -102,15 +101,13 @@ class AdaptivePopSheetList<T> extends StatelessWidget {
return; return;
} }
showModalBottomSheet( await openDrawer(
context: context, context: context,
enableDrag: true, draggable: true,
showDragHandle: true, showDragHandle: true,
useRootNavigator: true, position: OverlayPosition.bottom,
shape: RoundedRectangleBorder( borderRadius: context.theme.borderRadiusMd,
borderRadius: context.theme.borderRadiusMd, transformBackdrop: false,
),
backgroundColor: context.theme.colorScheme.card,
builder: (context) { builder: (context) {
final children = childrenModified(context); final children = childrenModified(context);
return ListView.builder( return ListView.builder(
@ -127,7 +124,7 @@ class AdaptivePopSheetList<T> extends StatelessWidget {
onPressed: () { onPressed: () {
data.onPressed?.call(context); data.onPressed?.call(context);
if (data.autoClose) { if (data.autoClose) {
Navigator.of(context).pop(); closeDrawer(context);
} }
}, },
leading: data.leading, leading: data.leading,

View File

@ -74,6 +74,26 @@ class TrackPresentationActionsSection extends HookConsumerWidget {
ref.watch(presentationStateProvider(options.collection).notifier); ref.watch(presentationStateProvider(options.collection).notifier);
final selectedTracks = state.selectedTracks; final selectedTracks = state.selectedTracks;
Future<void> actionDownloadTracks({
required BuildContext context,
required List<Track> tracks,
required String action,
}) async {
final confirmed = audioSource == AudioSource.piped ||
(await showDialog<bool>(
context: context,
builder: (context) {
return const ConfirmDownloadDialog();
},
) ??
false);
if (confirmed != true) return;
downloader.batchAddToQueue(tracks);
notifier.deselectAllTracks();
if (!context.mounted) return;
showToastForAction(context, action, tracks.length);
}
return AdaptivePopSheetList( return AdaptivePopSheetList(
tooltip: context.l10n.more_actions, tooltip: context.l10n.more_actions,
headings: [ headings: [
@ -95,22 +115,12 @@ class TrackPresentationActionsSection extends HookConsumerWidget {
switch (action) { switch (action) {
case "download": case "download":
{ await actionDownloadTracks(
final confirmed = audioSource == AudioSource.piped || context: context,
(await showDialog<bool?>( tracks: tracks,
context: context, action: action,
builder: (context) { );
return const ConfirmDownloadDialog(); break;
},
) ??
false);
if (confirmed != true) return;
downloader.batchAddToQueue(tracks);
notifier.deselectAllTracks();
if (!context.mounted) return;
showToastForAction(context, action, tracks.length);
break;
}
case "add-to-playlist": case "add-to-playlist":
{ {
if (context.mounted) { if (context.mounted) {

View File

@ -57,7 +57,7 @@ class TrackPresentationTopSection extends HookConsumerWidget {
Tooltip( Tooltip(
tooltip: TooltipContainer( tooltip: TooltipContainer(
child: Text(context.l10n.shuffle_playlist), child: Text(context.l10n.shuffle_playlist),
), ).call,
child: IconButton.secondary( child: IconButton.secondary(
icon: isLoading icon: isLoading
? const Center( ? const Center(
@ -73,7 +73,7 @@ class TrackPresentationTopSection extends HookConsumerWidget {
Tooltip( Tooltip(
tooltip: TooltipContainer( tooltip: TooltipContainer(
child: Text(context.l10n.add_to_queue), child: Text(context.l10n.add_to_queue),
), ).call,
child: IconButton.secondary( child: IconButton.secondary(
icon: const Icon(SpotubeIcons.queueAdd), icon: const Icon(SpotubeIcons.queueAdd),
enabled: !isLoading && !isActive, enabled: !isLoading && !isActive,
@ -126,7 +126,7 @@ class TrackPresentationTopSection extends HookConsumerWidget {
Tooltip( Tooltip(
tooltip: TooltipContainer( tooltip: TooltipContainer(
child: Text(context.l10n.share), child: Text(context.l10n.share),
), ).call,
child: IconButton.outline( child: IconButton.outline(
icon: const Icon(SpotubeIcons.share), icon: const Icon(SpotubeIcons.share),
size: ButtonSize.small, size: ButtonSize.small,

View File

@ -91,24 +91,14 @@ class TrackOptions extends HookConsumerWidget {
) { ) {
/// showDialog doesn't work for some reason. So we have to /// showDialog doesn't work for some reason. So we have to
/// manually push a Dialog Route in the Navigator to get it working /// manually push a Dialog Route in the Navigator to get it working
Navigator.push( showDialog(
context, context: context,
DialogRoute( builder: (context) {
alignment: Alignment.bottomCenter, return PlaylistAddTrackDialog(
transitionBuilder: (context, animation, secondaryAnimation, child) { tracks: [track],
return FadeTransition(opacity: animation, child: child); openFromPlaylist: playlistId,
}, );
context: context, },
barrierColor: Colors.black.withValues(alpha: 0.5),
builder: (context) {
return Center(
child: PlaylistAddTrackDialog(
tracks: [track],
openFromPlaylist: playlistId,
),
);
},
),
); );
} }
@ -338,6 +328,7 @@ class TrackOptions extends HookConsumerWidget {
} }
}, },
icon: icon ?? const Icon(SpotubeIcons.moreHorizontal), icon: icon ?? const Icon(SpotubeIcons.moreHorizontal),
variance: ButtonVariance.outline,
headings: [ headings: [
Basic( Basic(
leading: AspectRatio( leading: AspectRatio(

View File

@ -132,7 +132,7 @@ class PlayerView extends HookConsumerWidget {
Tooltip( Tooltip(
tooltip: TooltipContainer( tooltip: TooltipContainer(
child: Text(context.l10n.details), child: Text(context.l10n.details),
), ).call,
child: IconButton.ghost( child: IconButton.ghost(
icon: const Icon(SpotubeIcons.info, size: 18), icon: const Icon(SpotubeIcons.info, size: 18),
onPressed: currentTrack == null onPressed: currentTrack == null

View File

@ -82,7 +82,7 @@ class PlayerActions extends HookConsumerWidget {
children: [ children: [
if (showQueue) if (showQueue)
Tooltip( Tooltip(
tooltip: TooltipContainer(child: Text(context.l10n.queue)), tooltip: TooltipContainer(child: Text(context.l10n.queue)).call,
child: IconButton.ghost( child: IconButton.ghost(
icon: const Icon(SpotubeIcons.queue), icon: const Icon(SpotubeIcons.queue),
enabled: playlist.activeTrack != null, enabled: playlist.activeTrack != null,
@ -119,7 +119,8 @@ class PlayerActions extends HookConsumerWidget {
if (!isLocalTrack) if (!isLocalTrack)
Tooltip( Tooltip(
tooltip: TooltipContainer( tooltip: TooltipContainer(
child: Text(context.l10n.alternative_track_sources)), child: Text(context.l10n.alternative_track_sources),
).call,
child: IconButton.ghost( child: IconButton.ghost(
enabled: playlist.activeTrack != null, enabled: playlist.activeTrack != null,
icon: const Icon(SpotubeIcons.alternativeRoute), icon: const Icon(SpotubeIcons.alternativeRoute),
@ -160,7 +161,8 @@ class PlayerActions extends HookConsumerWidget {
else else
Tooltip( Tooltip(
tooltip: tooltip:
TooltipContainer(child: Text(context.l10n.download_track)), TooltipContainer(child: Text(context.l10n.download_track))
.call,
child: IconButton.ghost( child: IconButton.ghost(
icon: Icon( icon: Icon(
isDownloaded ? SpotubeIcons.done : SpotubeIcons.download, isDownloaded ? SpotubeIcons.done : SpotubeIcons.download,