mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
112 lines
3.9 KiB
Dart
112 lines
3.9 KiB
Dart
import 'package:flutter/services.dart';
|
|
import 'package:flutter_undraw/flutter_undraw.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
|
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
|
|
import 'package:skeletonizer/skeletonizer.dart';
|
|
import 'package:spotube/collections/fake.dart';
|
|
import 'package:spotube/components/track_presentation/presentation_props.dart';
|
|
import 'package:spotube/components/track_presentation/presentation_state.dart';
|
|
import 'package:spotube/components/track_presentation/use_track_tile_play_callback.dart';
|
|
import 'package:spotube/components/track_tile/track_tile.dart';
|
|
import 'package:spotube/components/track_presentation/use_is_user_playlist.dart';
|
|
import 'package:spotube/extensions/context.dart';
|
|
import 'package:spotube/provider/audio_player/audio_player.dart';
|
|
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
|
|
|
class PresentationListSection extends HookConsumerWidget {
|
|
const PresentationListSection({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, ref) {
|
|
final options = TrackPresentationOptions.of(context);
|
|
final playlist = ref.watch(audioPlayerProvider);
|
|
final state = ref.watch(presentationStateProvider(options.collection));
|
|
final notifier =
|
|
ref.read(presentationStateProvider(options.collection).notifier);
|
|
final isUserPlaylist = useIsUserPlaylist(ref, options.collectionId);
|
|
|
|
final onTileTap = useTrackTilePlayCallback(ref);
|
|
|
|
if (state.presentationTracks.isEmpty && !options.pagination.isLoading) {
|
|
return SliverToBoxAdapter(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
Undraw(
|
|
illustration: UndrawIllustration.dreamer,
|
|
color: context.theme.colorScheme.primary,
|
|
height: 200 * context.theme.scaling,
|
|
),
|
|
Text(
|
|
isUserPlaylist
|
|
? context.l10n.no_tracks_added_yet
|
|
: context.l10n.no_tracks,
|
|
textAlign: TextAlign.center,
|
|
).muted().small(),
|
|
],
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
return SliverInfiniteList(
|
|
isLoading: options.pagination.isLoading,
|
|
onFetchData: options.pagination.onFetchMore,
|
|
itemCount: state.presentationTracks.length,
|
|
hasReachedMax: !options.pagination.hasNextPage,
|
|
loadingBuilder: (context) {
|
|
return Skeletonizer(
|
|
enabled: true,
|
|
child: TrackTile(
|
|
index: 0,
|
|
playlist: playlist,
|
|
track: FakeData.track,
|
|
),
|
|
);
|
|
},
|
|
emptyBuilder: (context) => Skeletonizer(
|
|
enabled: true,
|
|
child: Column(
|
|
children: List.generate(
|
|
10,
|
|
(index) => TrackTile(
|
|
track: FakeData.track,
|
|
index: index,
|
|
playlist: playlist,
|
|
),
|
|
),
|
|
),
|
|
),
|
|
itemBuilder: (context, index) {
|
|
final track = state.presentationTracks[index];
|
|
final isSelected = state.selectedTracks.any((e) => e.id == track.id);
|
|
return TrackTile(
|
|
userPlaylist: isUserPlaylist,
|
|
playlistId: options.collectionId,
|
|
index: index,
|
|
playlist: playlist,
|
|
track: track,
|
|
selected: isSelected,
|
|
onTap: () => onTileTap(track, index),
|
|
onChanged: state.selectedTracks.isEmpty
|
|
? null
|
|
: (isSelected) {
|
|
if (isSelected == true) {
|
|
notifier.selectTrack(track);
|
|
} else {
|
|
notifier.deselectTrack(track);
|
|
}
|
|
},
|
|
onLongPress: () {
|
|
notifier.selectTrack(track);
|
|
HapticFeedback.selectionClick();
|
|
},
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|