fix: track_tile active and blacklist color, playbutton card action positioning

This commit is contained in:
Kingkor Roy Tirtho 2023-03-23 21:29:20 +06:00
parent 20c424c77f
commit 3f5a1b9587
8 changed files with 254 additions and 185 deletions

View File

@ -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,

View File

@ -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),
],
),
),
),
);
}
}

View File

@ -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,

View File

@ -51,7 +51,7 @@ class SortTracksDropdown extends StatelessWidget {
},
onSelected: onChanged,
tooltip: "Sort tracks",
child: const Icon(SpotubeIcons.sort),
icon: const Icon(SpotubeIcons.sort),
);
}
}

View File

@ -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),
];

View File

@ -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(

View File

@ -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(),
];

View File

@ -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;
}
}
}