mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
fix: track_tile active and blacklist color, playbutton card action positioning
This commit is contained in:
parent
20c424c77f
commit
3f5a1b9587
@ -50,7 +50,11 @@ class UserAlbums extends HookConsumerWidget {
|
||||
return const AnonymousFallback();
|
||||
}
|
||||
if (albumsQuery.isLoading || !albumsQuery.hasData) {
|
||||
return const Center(child: ShimmerPlaybuttonCard(count: 7));
|
||||
return Container(
|
||||
alignment: Alignment.topLeft,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: const ShimmerPlaybuttonCard(count: 7),
|
||||
);
|
||||
}
|
||||
|
||||
return RefreshIndicator(
|
||||
@ -63,6 +67,7 @@ class UserAlbums extends HookConsumerWidget {
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: SafeArea(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextField(
|
||||
onChanged: (value) => searchText.value = value,
|
||||
|
@ -7,6 +7,7 @@ import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/shared/image/universal_image.dart';
|
||||
import 'package:spotube/hooks/use_breakpoint_value.dart';
|
||||
import 'package:spotube/hooks/use_brightness_value.dart';
|
||||
import 'package:spotube/utils/platform.dart';
|
||||
|
||||
class PlaybuttonCard extends HookWidget {
|
||||
final void Function()? onTap;
|
||||
@ -34,6 +35,7 @@ class PlaybuttonCard extends HookWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final textsKey = useMemoized(() => GlobalKey(), []);
|
||||
final theme = Theme.of(context);
|
||||
final radius = BorderRadius.circular(15);
|
||||
|
||||
@ -41,15 +43,36 @@ class PlaybuttonCard extends HookWidget {
|
||||
sm: 130,
|
||||
md: 150,
|
||||
others: 170,
|
||||
);
|
||||
) ??
|
||||
170;
|
||||
|
||||
final end = useBreakpointValue<double>(
|
||||
sm: 5,
|
||||
md: 7,
|
||||
others: 10,
|
||||
sm: 15,
|
||||
others: 20,
|
||||
) ??
|
||||
20;
|
||||
|
||||
final textsHeight = useState(
|
||||
(textsKey.currentContext?.findRenderObject() as RenderBox?)
|
||||
?.size
|
||||
.height ??
|
||||
110.00,
|
||||
);
|
||||
|
||||
return Container(
|
||||
useEffect(() {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
textsHeight.value =
|
||||
(textsKey.currentContext?.findRenderObject() as RenderBox?)
|
||||
?.size
|
||||
.height ??
|
||||
textsHeight.value;
|
||||
});
|
||||
return null;
|
||||
}, [textsKey]);
|
||||
|
||||
return Stack(
|
||||
children: [
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: size),
|
||||
margin: margin,
|
||||
child: Material(
|
||||
@ -70,16 +93,12 @@ class PlaybuttonCard extends HookWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Stack(
|
||||
clipBehavior: Clip.none,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.only(
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 8,
|
||||
right: 8,
|
||||
top: 8,
|
||||
),
|
||||
constraints: BoxConstraints(maxHeight: size),
|
||||
child: ClipRRect(
|
||||
borderRadius: radius,
|
||||
child: UniversalImage(
|
||||
@ -88,10 +107,45 @@ class PlaybuttonCard extends HookWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Positioned.directional(
|
||||
textDirection: TextDirection.ltr,
|
||||
end: end,
|
||||
bottom: -size * .15,
|
||||
Column(
|
||||
key: textsKey,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 15),
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: AutoSizeText(
|
||||
title,
|
||||
maxLines: 1,
|
||||
minFontSize: theme.textTheme.bodyMedium!.fontSize!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
if (description != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: AutoSizeText(
|
||||
description!,
|
||||
maxLines: 2,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color:
|
||||
theme.colorScheme.onSurface.withOpacity(.5),
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
AnimatedPositioned(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
right: end,
|
||||
bottom: textsHeight.value - (kIsMobile ? 5 : 10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
@ -115,8 +169,7 @@ class PlaybuttonCard extends HookWidget {
|
||||
icon: isLoading
|
||||
? SizedBox.fromSize(
|
||||
size: const Size.square(15),
|
||||
child: const CircularProgressIndicator(
|
||||
strokeWidth: 2),
|
||||
child: const CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: isPlaying
|
||||
? const Icon(SpotubeIcons.pause)
|
||||
@ -127,38 +180,6 @@ class PlaybuttonCard extends HookWidget {
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 15),
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: AutoSizeText(
|
||||
title,
|
||||
maxLines: 1,
|
||||
minFontSize: theme.textTheme.bodyMedium!.fontSize!,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
if (description != null)
|
||||
Flexible(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12.0),
|
||||
child: AutoSizeText(
|
||||
description!,
|
||||
maxLines: 2,
|
||||
style: theme.textTheme.bodySmall?.copyWith(
|
||||
color: theme.colorScheme.onSurface.withOpacity(.5),
|
||||
),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -26,7 +26,8 @@ class ShimmerArtistProfile extends HookWidget {
|
||||
lg: MediaQuery.of(context).size.width * 0.30,
|
||||
xl: MediaQuery.of(context).size.width * 0.30,
|
||||
xxl: MediaQuery.of(context).size.width * 0.30,
|
||||
);
|
||||
) ??
|
||||
0;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
@ -51,7 +51,7 @@ class SortTracksDropdown extends StatelessWidget {
|
||||
},
|
||||
onSelected: onChanged,
|
||||
tooltip: "Sort tracks",
|
||||
child: const Icon(SpotubeIcons.sort),
|
||||
icon: const Icon(SpotubeIcons.sort),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -100,12 +100,13 @@ class TrackCollectionView<T> extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
// play playlist
|
||||
IconButton(
|
||||
style: IconButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.primary,
|
||||
ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const CircleBorder(),
|
||||
backgroundColor: theme.colorScheme.inversePrimary,
|
||||
),
|
||||
onPressed: tracksSnapshot.data != null ? onPlay : null,
|
||||
icon: Icon(isPlaying ? SpotubeIcons.stop : SpotubeIcons.play),
|
||||
child: Icon(isPlaying ? SpotubeIcons.stop : SpotubeIcons.play),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
];
|
||||
|
@ -179,18 +179,16 @@ class TrackTile extends HookConsumerWidget {
|
||||
return AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 500),
|
||||
decoration: BoxDecoration(
|
||||
color: isBlackListed
|
||||
? Colors.red[100]
|
||||
: isActive
|
||||
? theme.popupMenuTheme.color
|
||||
color: isActive
|
||||
? theme.colorScheme.surfaceVariant.withOpacity(0.5)
|
||||
: Colors.transparent,
|
||||
borderRadius: BorderRadius.circular(isActive ? 10 : 0),
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
child: Row(
|
||||
children: [
|
||||
if (showCheck)
|
||||
if (showCheck && !isBlackListed)
|
||||
Checkbox(
|
||||
value: isChecked,
|
||||
onChanged: (s) => onCheckChange?.call(s),
|
||||
@ -222,22 +220,21 @@ class TrackTile extends HookConsumerWidget {
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: IconButton(
|
||||
icon: Icon(
|
||||
playlist?.activeTrack.id == track.value.id
|
||||
? SpotubeIcons.pause
|
||||
: SpotubeIcons.play,
|
||||
color: Colors.white,
|
||||
),
|
||||
style: IconButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.primary,
|
||||
hoverColor: theme.colorScheme.primary.withOpacity(0.5),
|
||||
child: ElevatedButton(
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: theme.colorScheme.inversePrimary,
|
||||
shape: const CircleBorder(),
|
||||
),
|
||||
onPressed: !isBlackListed
|
||||
? () => onTrackPlayButtonPressed?.call(
|
||||
track.value,
|
||||
)
|
||||
: null,
|
||||
child: Icon(
|
||||
playlist?.activeTrack.id == track.value.id
|
||||
? SpotubeIcons.pause
|
||||
: SpotubeIcons.play,
|
||||
),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
|
@ -197,7 +197,7 @@ class TracksTableView extends HookConsumerWidget {
|
||||
default:
|
||||
}
|
||||
},
|
||||
child: const Icon(SpotubeIcons.moreVertical),
|
||||
icon: const Icon(SpotubeIcons.moreVertical),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
],
|
||||
@ -205,12 +205,31 @@ class TracksTableView extends HookConsumerWidget {
|
||||
...sortedTracks.asMap().entries.map((track) {
|
||||
String duration =
|
||||
"${track.value.duration?.inMinutes.remainder(60)}:${PrimitiveUtils.zeroPadNumStr(track.value.duration?.inSeconds.remainder(60) ?? 0)}";
|
||||
return InkWell(
|
||||
onLongPress: () {
|
||||
return Consumer(builder: (context, ref, _) {
|
||||
final isBlackListed = ref.watch(
|
||||
BlackListNotifier.provider.select(
|
||||
(blacklist) => blacklist.contains(
|
||||
BlacklistedElement.track(
|
||||
track.value.id!, track.value.name!),
|
||||
),
|
||||
),
|
||||
);
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
onLongPress: isBlackListed
|
||||
? null
|
||||
: () {
|
||||
showCheck.value = true;
|
||||
selected.value = [...selected.value, track.value.id!];
|
||||
selected.value = [
|
||||
...selected.value,
|
||||
track.value.id!
|
||||
];
|
||||
},
|
||||
onTap: () {
|
||||
onTap: isBlackListed
|
||||
? null
|
||||
: () {
|
||||
if (showCheck.value) {
|
||||
final alreadyChecked =
|
||||
selected.value.contains(track.value.id);
|
||||
@ -219,7 +238,10 @@ class TracksTableView extends HookConsumerWidget {
|
||||
.where((id) => id != track.value.id)
|
||||
.toList();
|
||||
} else {
|
||||
selected.value = [...selected.value, track.value.id!];
|
||||
selected.value = [
|
||||
...selected.value,
|
||||
track.value.id!
|
||||
];
|
||||
}
|
||||
} else {
|
||||
final isBlackListed = ref.read(
|
||||
@ -255,7 +277,9 @@ class TracksTableView extends HookConsumerWidget {
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
}).toList(),
|
||||
];
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import 'package:spotube/hooks/use_breakpoints.dart';
|
||||
|
||||
useBreakpointValue<T>({
|
||||
T useBreakpointValue<T>({
|
||||
T? sm,
|
||||
T? md,
|
||||
T? lg,
|
||||
@ -8,17 +8,37 @@ useBreakpointValue<T>({
|
||||
T? xxl,
|
||||
T? others,
|
||||
}) {
|
||||
final isSomeNull =
|
||||
sm == null || md == null || lg == null || xl == null || xxl == null;
|
||||
assert(
|
||||
(isSomeNull && others != null) || (!isSomeNull && others == null),
|
||||
'You must provide a value for all breakpoints or a default value for others',
|
||||
);
|
||||
final breakpoint = useBreakpoints();
|
||||
|
||||
if (isSomeNull) {
|
||||
if (breakpoint.isSm) {
|
||||
return sm ?? others;
|
||||
return sm ?? others!;
|
||||
} else if (breakpoint.isMd) {
|
||||
return md ?? others;
|
||||
return md ?? others!;
|
||||
} else if (breakpoint.isXl) {
|
||||
return xl ?? others;
|
||||
return xl ?? others!;
|
||||
} else if (breakpoint.isXxl) {
|
||||
return xxl ?? others;
|
||||
return xxl ?? others!;
|
||||
} else {
|
||||
return lg ?? others;
|
||||
return lg ?? others!;
|
||||
}
|
||||
} else {
|
||||
if (breakpoint.isSm) {
|
||||
return sm;
|
||||
} else if (breakpoint.isMd) {
|
||||
return md;
|
||||
} else if (breakpoint.isXl) {
|
||||
return xl;
|
||||
} else if (breakpoint.isXxl) {
|
||||
return xxl;
|
||||
} else {
|
||||
return lg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user