refactor: use CustomScrollView in player queue

This commit is contained in:
Kingkor Roy Tirtho 2024-03-28 22:49:40 +06:00
parent ee97aedcfc
commit 044d3b4820

View File

@ -3,11 +3,15 @@ import 'dart:ui';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:fuzzywuzzy/fuzzywuzzy.dart'; import 'package:fuzzywuzzy/fuzzywuzzy.dart';
import 'package:gap/gap.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:scroll_to_index/scroll_to_index.dart';
import 'package:sliver_tools/sliver_tools.dart';
import 'package:spotube/collections/fake.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/shared/fallbacks/not_found.dart'; import 'package:spotube/components/shared/fallbacks/not_found.dart';
import 'package:spotube/components/shared/inter_scrollbar/inter_scrollbar.dart'; import 'package:spotube/components/shared/inter_scrollbar/inter_scrollbar.dart';
@ -109,10 +113,15 @@ class PlayerQueue extends HookConsumerWidget {
searchText.value = ''; searchText.value = '';
} }
}, },
child: Column( child: InterScrollbar(
children: [ controller: controller,
child: CustomScrollView(
controller: controller,
slivers: [
if (!floating) if (!floating)
Container( SliverToBoxAdapter(
child: Center(
child: Container(
height: 5, height: 5,
width: 100, width: 100,
margin: const EdgeInsets.only(bottom: 5, top: 2), margin: const EdgeInsets.only(bottom: 5, top: 2),
@ -121,13 +130,26 @@ class PlayerQueue extends HookConsumerWidget {
borderRadius: BorderRadius.circular(20), borderRadius: BorderRadius.circular(20),
), ),
), ),
Row( ),
crossAxisAlignment: CrossAxisAlignment.center, ),
mainAxisAlignment: MainAxisAlignment.center, SliverAppBar(
children: [ floating: true,
if (mediaQuery.mdAndUp || !isSearching.value) ...[ pinned: false,
const SizedBox(width: 10), snap: false,
Text( backgroundColor: Colors.transparent,
elevation: 0,
automaticallyImplyLeading: !isSearching.value,
title: BackdropFilter(
filter: ImageFilter.blur(
sigmaX: 10,
sigmaY: 10,
),
child: SizedBox(
height: kToolbarHeight,
child: mediaQuery.mdAndUp || !isSearching.value
? Align(
alignment: Alignment.centerLeft,
child: Text(
context.l10n.tracks_in_queue(tracks.length), context.l10n.tracks_in_queue(tracks.length),
style: TextStyle( style: TextStyle(
color: headlineColor, color: headlineColor,
@ -135,8 +157,11 @@ class PlayerQueue extends HookConsumerWidget {
fontSize: 18, fontSize: 18,
), ),
), ),
const Spacer(), )
], : null,
),
),
actions: [
if (mediaQuery.mdAndUp || isSearching.value) if (mediaQuery.mdAndUp || isSearching.value)
TextField( TextField(
onChanged: (value) { onChanged: (value) {
@ -181,7 +206,8 @@ class PlayerQueue extends HookConsumerWidget {
style: FilledButton.styleFrom( style: FilledButton.styleFrom(
backgroundColor: backgroundColor:
theme.scaffoldBackgroundColor.withOpacity(0.5), theme.scaffoldBackgroundColor.withOpacity(0.5),
foregroundColor: theme.textTheme.headlineSmall?.color, foregroundColor:
theme.textTheme.headlineSmall?.color,
), ),
child: Row( child: Row(
children: [ children: [
@ -199,17 +225,12 @@ class PlayerQueue extends HookConsumerWidget {
], ],
], ],
), ),
const SizedBox(height: 10), const SliverGap(10),
if (!isSearching.value && searchText.value.isEmpty) SliverReorderableList(
Flexible(
child: ReorderableListView.builder(
onReorder: (oldIndex, newIndex) { onReorder: (oldIndex, newIndex) {
playlistNotifier.moveTrack(oldIndex, newIndex); playlistNotifier.moveTrack(oldIndex, newIndex);
}, },
scrollController: controller, itemCount: filteredTracks.length,
itemCount: tracks.length,
shrinkWrap: true,
buildDefaultDragHandles: false,
onReorderStart: (index) { onReorderStart: (index) {
HapticFeedback.selectionClick(); HapticFeedback.selectionClick();
}, },
@ -217,14 +238,13 @@ class PlayerQueue extends HookConsumerWidget {
HapticFeedback.selectionClick(); HapticFeedback.selectionClick();
}, },
itemBuilder: (context, i) { itemBuilder: (context, i) {
final track = tracks.elementAt(i); final track = filteredTracks.elementAt(i);
return AutoScrollTag( return AutoScrollTag(
key: ValueKey(i), key: ValueKey<int>(i),
controller: controller, controller: controller,
index: i, index: i,
child: Padding( child: Material(
padding: color: Colors.transparent,
const EdgeInsets.symmetric(horizontal: 8.0),
child: TrackTile( child: TrackTile(
index: i, index: i,
track: track, track: track,
@ -235,9 +255,16 @@ class PlayerQueue extends HookConsumerWidget {
await playlistNotifier.jumpToTrack(track); await playlistNotifier.jumpToTrack(track);
}, },
leadingActions: [ leadingActions: [
ReorderableDragStartListener( if (!isSearching.value &&
searchText.value.isEmpty)
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: ReorderableDragStartListener(
index: i, index: i,
child: const Icon(SpotubeIcons.dragHandle), child: const Icon(
SpotubeIcons.dragHandle,
),
),
), ),
], ],
), ),
@ -245,39 +272,13 @@ class PlayerQueue extends HookConsumerWidget {
); );
}, },
), ),
) const SliverGap(100),
else
Flexible(
child: InterScrollbar(
controller: controller,
child: ListView.builder(
controller: controller,
itemCount: filteredTracks.length,
itemBuilder: (context, i) {
final track = filteredTracks.elementAt(i);
return Padding(
padding:
const EdgeInsets.symmetric(horizontal: 8.0),
child: TrackTile(
index: i,
track: track,
onTap: () async {
if (playlist.activeTrack?.id == track.id) {
return;
}
await playlistNotifier.jumpToTrack(track);
},
),
);
},
),
),
),
], ],
), ),
), ),
), ),
), ),
),
); );
} }
} }