mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
refactor: genres section
This commit is contained in:
parent
6dd9b753b0
commit
bf94a490bb
@ -408,5 +408,6 @@
|
||||
"add_all_to_playlist": "Add all to playlist",
|
||||
"add_all_to_queue": "Add all to queue",
|
||||
"play_all_next": "Play all next",
|
||||
"pause": "Pause"
|
||||
"pause": "Pause",
|
||||
"view_all": "View all"
|
||||
}
|
@ -4,14 +4,16 @@ 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:spotify/spotify.dart';
|
||||
import 'package:spotube/collections/fake.dart';
|
||||
import 'package:spotube/collections/spotube_icons.dart';
|
||||
import 'package:spotube/components/image/universal_image.dart';
|
||||
import 'package:spotube/extensions/constrains.dart';
|
||||
import 'package:spotube/extensions/context.dart';
|
||||
import 'package:spotube/extensions/image.dart';
|
||||
import 'package:spotube/extensions/string.dart';
|
||||
import 'package:spotube/pages/home/genres/genre_playlists.dart';
|
||||
import 'package:spotube/pages/home/genres/genres.dart';
|
||||
import 'package:spotube/pages/playlist/playlist.dart';
|
||||
import 'package:spotube/provider/spotify/spotify.dart';
|
||||
|
||||
class HomeGenresSection extends HookConsumerWidget {
|
||||
@ -19,7 +21,8 @@ class HomeGenresSection extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, ref) {
|
||||
final mediaQuery = MediaQuery.of(context);
|
||||
final theme = context.theme;
|
||||
final mediaQuery = MediaQuery.sizeOf(context);
|
||||
|
||||
final categoriesQuery = ref.watch(categoriesProvider);
|
||||
final categories = useMemoized(
|
||||
@ -28,7 +31,9 @@ class HomeGenresSection extends HookConsumerWidget {
|
||||
.where((c) => (c.icons?.length ?? 0) > 0)
|
||||
.take(mediaQuery.mdAndDown ? 6 : 10)
|
||||
.toList() ??
|
||||
<Category>[],
|
||||
[
|
||||
FakeData.category,
|
||||
],
|
||||
[mediaQuery.mdAndDown, categoriesQuery.asData?.value],
|
||||
);
|
||||
|
||||
@ -61,51 +66,175 @@ class HomeGenresSection extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
const SliverGap(8),
|
||||
SliverPadding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||
sliver: Skeletonizer.sliver(
|
||||
enabled: categoriesQuery.isLoading,
|
||||
child: SliverGrid.builder(
|
||||
gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
|
||||
maxCrossAxisExtent: mediaQuery.mdAndDown ? 200 : 250,
|
||||
mainAxisExtent: 50,
|
||||
crossAxisSpacing: 16,
|
||||
mainAxisSpacing: 16,
|
||||
SliverToBoxAdapter(
|
||||
child: SizedBox(
|
||||
height: 280 * theme.scaling,
|
||||
child: Carousel(
|
||||
transition: const CarouselTransition.sliding(gap: 24),
|
||||
sizeConstraint: CarouselSizeConstraint.fixed(
|
||||
mediaQuery.mdAndUp
|
||||
? mediaQuery.width * .6
|
||||
: mediaQuery.width * .95,
|
||||
),
|
||||
itemCount: categoriesQuery.isLoading
|
||||
? mediaQuery.mdAndDown
|
||||
? 6
|
||||
: 10
|
||||
: categories.length,
|
||||
itemCount: categories.length,
|
||||
autoplaySpeed: const Duration(seconds: 2),
|
||||
duration: const Duration(seconds: 5),
|
||||
pauseOnHover: true,
|
||||
direction: Axis.horizontal,
|
||||
itemBuilder: (context, index) {
|
||||
final category =
|
||||
categories.elementAtOrNull(index) ?? FakeData.category;
|
||||
final category = categories[index];
|
||||
final playlists =
|
||||
ref.watch(categoryPlaylistsProvider(category.id!));
|
||||
final playlistsData = playlists.asData?.value.items.take(8) ??
|
||||
List.generate(5, (index) => FakeData.playlistSimple);
|
||||
|
||||
return Button(
|
||||
style: ButtonVariance.secondary.copyWith(
|
||||
padding: (context, states, value) {
|
||||
return EdgeInsets.zero;
|
||||
},
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 8),
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: theme.borderRadiusXxl,
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.border,
|
||||
width: 1,
|
||||
),
|
||||
onPressed: () {},
|
||||
child: CardImage(
|
||||
image: DecorationImage(
|
||||
image: UniversalImage.imageProvider(
|
||||
category.icons!.first.url!,
|
||||
),
|
||||
colorFilter: ColorFilter.mode(
|
||||
theme.colorScheme.background.withAlpha(125),
|
||||
BlendMode.darken,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
spacing: 16,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
category.name!,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
).h3(),
|
||||
Button.link(
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
GenrePlaylistsPage.name,
|
||||
pathParameters: {
|
||||
"categoryId": category.id!,
|
||||
},
|
||||
pathParameters: {'categoryId': category.id!},
|
||||
extra: category,
|
||||
);
|
||||
},
|
||||
direction: Axis.horizontal,
|
||||
image: UniversalImage(
|
||||
path: category.icons!.first.url!,
|
||||
fit: BoxFit.cover,
|
||||
height: 50,
|
||||
width: 50,
|
||||
child: Text(
|
||||
context.l10n.view_all,
|
||||
style: const TextStyle(color: Colors.white),
|
||||
).muted(),
|
||||
),
|
||||
title: Text(category.name!),
|
||||
],
|
||||
),
|
||||
Expanded(
|
||||
child: Skeleton.ignore(
|
||||
child: Skeletonizer(
|
||||
enabled: playlists.isLoading,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
spacing: 12,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
for (final playlist in playlistsData)
|
||||
Container(
|
||||
width: 115 * theme.scaling,
|
||||
decoration: BoxDecoration(
|
||||
color: theme.colorScheme.background
|
||||
.withAlpha(75),
|
||||
borderRadius: theme.borderRadiusMd,
|
||||
),
|
||||
child: SurfaceBlur(
|
||||
borderRadius: theme.borderRadiusMd,
|
||||
surfaceBlur: theme.surfaceBlur,
|
||||
child: Button(
|
||||
style:
|
||||
ButtonVariance.secondary.copyWith(
|
||||
padding: (context, states, value) =>
|
||||
const EdgeInsets.all(8),
|
||||
decoration:
|
||||
(context, states, value) {
|
||||
final decoration = ButtonVariance
|
||||
.secondary
|
||||
.decoration(
|
||||
context, states)
|
||||
as BoxDecoration;
|
||||
|
||||
if (states.isNotEmpty) {
|
||||
return decoration;
|
||||
}
|
||||
|
||||
return decoration.copyWith(
|
||||
color: decoration.color
|
||||
?.withAlpha(180),
|
||||
);
|
||||
},
|
||||
),
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
PlaylistPage.name,
|
||||
pathParameters: {
|
||||
"id": playlist.id!,
|
||||
},
|
||||
extra: playlist,
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
crossAxisAlignment:
|
||||
CrossAxisAlignment.start,
|
||||
spacing: 5,
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius:
|
||||
theme.borderRadiusSm,
|
||||
child: UniversalImage(
|
||||
path: (playlist.images)!
|
||||
.asUrlString(
|
||||
placeholder:
|
||||
ImagePlaceholder
|
||||
.collection,
|
||||
index: 1,
|
||||
),
|
||||
fit: BoxFit.cover,
|
||||
height: 100 * theme.scaling,
|
||||
width: 100 * theme.scaling,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
playlist.name!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
).semiBold().small(),
|
||||
if (playlist.description != null)
|
||||
Text(
|
||||
playlist.description
|
||||
?.unescapeHtml()
|
||||
.cleanHtml() ??
|
||||
"",
|
||||
maxLines: 2,
|
||||
overflow:
|
||||
TextOverflow.ellipsis,
|
||||
).xSmall().muted(),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
|
@ -4,6 +4,7 @@ import 'package:dio/dio.dart';
|
||||
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:html/dom.dart' hide Text;
|
||||
import 'package:shadcn_flutter/shadcn_flutter.dart' hide Element;
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/modules/library/user_local_tracks.dart';
|
||||
import 'package:spotube/modules/root/update_dialog.dart';
|
||||
@ -20,7 +21,6 @@ import 'package:html/parser.dart' as parser;
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart' hide Element;
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:spotube/collections/env.dart';
|
||||
@ -304,7 +304,9 @@ abstract class ServiceUtils {
|
||||
.map((e) => e.matchedLocation);
|
||||
|
||||
if (routerState.matchedLocation == location ||
|
||||
routerStack.contains(location)) return;
|
||||
routerStack.contains(location)) {
|
||||
return;
|
||||
}
|
||||
router.push(location, extra: extra);
|
||||
}
|
||||
|
||||
@ -418,7 +420,7 @@ abstract class ServiceUtils {
|
||||
await showDialog(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
barrierColor: Colors.black26,
|
||||
barrierColor: Colors.black.withAlpha(66),
|
||||
builder: (context) {
|
||||
return RootAppUpdateDialog.nightly(nightlyBuildNum: buildNum);
|
||||
},
|
||||
@ -439,14 +441,16 @@ abstract class ServiceUtils {
|
||||
if (currentVersion == null ||
|
||||
latestVersion == null ||
|
||||
(latestVersion.isPreRelease && !currentVersion.isPreRelease) ||
|
||||
(!latestVersion.isPreRelease && currentVersion.isPreRelease)) return;
|
||||
(!latestVersion.isPreRelease && currentVersion.isPreRelease)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (latestVersion <= currentVersion || !context.mounted) return;
|
||||
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: true,
|
||||
barrierColor: Colors.black26,
|
||||
barrierColor: Colors.black.withAlpha(66),
|
||||
builder: (context) {
|
||||
return RootAppUpdateDialog(version: latestVersion);
|
||||
},
|
||||
|
@ -8,7 +8,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"bn": [
|
||||
@ -20,7 +21,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"ca": [
|
||||
@ -32,7 +34,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"cs": [
|
||||
@ -44,7 +47,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"de": [
|
||||
@ -56,7 +60,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"es": [
|
||||
@ -68,7 +73,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"eu": [
|
||||
@ -80,7 +86,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"fa": [
|
||||
@ -92,7 +99,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"fi": [
|
||||
@ -104,7 +112,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"fr": [
|
||||
@ -116,7 +125,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"hi": [
|
||||
@ -128,7 +138,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"id": [
|
||||
@ -140,7 +151,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"it": [
|
||||
@ -152,7 +164,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"ja": [
|
||||
@ -164,7 +177,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"ka": [
|
||||
@ -176,7 +190,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"ko": [
|
||||
@ -188,7 +203,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"ne": [
|
||||
@ -200,7 +216,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"nl": [
|
||||
@ -212,7 +229,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"pl": [
|
||||
@ -224,7 +242,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"pt": [
|
||||
@ -236,7 +255,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"ru": [
|
||||
@ -248,7 +268,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"th": [
|
||||
@ -260,7 +281,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"tr": [
|
||||
@ -272,7 +294,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"uk": [
|
||||
@ -284,7 +307,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"vi": [
|
||||
@ -296,7 +320,8 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
],
|
||||
|
||||
"zh": [
|
||||
@ -308,6 +333,7 @@
|
||||
"add_all_to_playlist",
|
||||
"add_all_to_queue",
|
||||
"play_all_next",
|
||||
"pause"
|
||||
"pause",
|
||||
"view_all"
|
||||
]
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user