mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 16:05:18 +00:00
fix: playlist generate slider shape
This commit is contained in:
parent
ce38233de8
commit
2b35c044ad
@ -94,7 +94,7 @@ class RecommendationAttributeDials extends HookWidget {
|
|||||||
return Card(
|
return Card(
|
||||||
child: ExpansionTile(
|
child: ExpansionTile(
|
||||||
title: DefaultTextStyle(
|
title: DefaultTextStyle(
|
||||||
style: Theme.of(context).textTheme.titleMedium!,
|
style: Theme.of(context).textTheme.titleSmall!,
|
||||||
child: title,
|
child: title,
|
||||||
),
|
),
|
||||||
shape: const Border(),
|
shape: const Border(),
|
||||||
|
@ -93,7 +93,7 @@ class RecommendationAttributeFields extends HookWidget {
|
|||||||
return Card(
|
return Card(
|
||||||
child: ExpansionTile(
|
child: ExpansionTile(
|
||||||
title: DefaultTextStyle(
|
title: DefaultTextStyle(
|
||||||
style: Theme.of(context).textTheme.titleMedium!,
|
style: Theme.of(context).textTheme.titleSmall!,
|
||||||
child: title,
|
child: title,
|
||||||
),
|
),
|
||||||
shape: const Border(),
|
shape: const Border(),
|
||||||
|
@ -248,251 +248,256 @@ class PlaylistGeneratorPage extends HookConsumerWidget {
|
|||||||
title: Text(context.l10n.generate_playlist),
|
title: Text(context.l10n.generate_playlist),
|
||||||
centerTitle: true,
|
centerTitle: true,
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: SliderTheme(
|
||||||
child: LayoutBuilder(builder: (context, constrains) {
|
data: const SliderThemeData(
|
||||||
return ListView(
|
overlayShape: RoundSliderOverlayShape(),
|
||||||
padding: const EdgeInsets.all(16),
|
),
|
||||||
children: [
|
child: SafeArea(
|
||||||
ValueListenableBuilder(
|
child: LayoutBuilder(builder: (context, constrains) {
|
||||||
valueListenable: limit,
|
return ListView(
|
||||||
builder: (context, value, child) {
|
padding: const EdgeInsets.all(16),
|
||||||
return Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
ValueListenableBuilder(
|
||||||
children: [
|
valueListenable: limit,
|
||||||
Text(
|
builder: (context, value, child) {
|
||||||
context.l10n.number_of_tracks_generate,
|
return Column(
|
||||||
style: textTheme.titleMedium,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
Row(
|
Text(
|
||||||
children: [
|
context.l10n.number_of_tracks_generate,
|
||||||
Container(
|
style: textTheme.titleMedium,
|
||||||
width: 40,
|
),
|
||||||
height: 40,
|
Row(
|
||||||
alignment: Alignment.center,
|
children: [
|
||||||
decoration: BoxDecoration(
|
Container(
|
||||||
color: theme.colorScheme.primary,
|
width: 40,
|
||||||
shape: BoxShape.circle,
|
height: 40,
|
||||||
),
|
alignment: Alignment.center,
|
||||||
child: Text(
|
decoration: BoxDecoration(
|
||||||
value.round().toString(),
|
color: theme.colorScheme.primary,
|
||||||
style: textTheme.bodyLarge?.copyWith(
|
shape: BoxShape.circle,
|
||||||
color: theme.colorScheme.primaryContainer,
|
),
|
||||||
|
child: Text(
|
||||||
|
value.round().toString(),
|
||||||
|
style: textTheme.bodyLarge?.copyWith(
|
||||||
|
color: theme.colorScheme.primaryContainer,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
Expanded(
|
child: Slider.adaptive(
|
||||||
child: Slider.adaptive(
|
value: value.toDouble(),
|
||||||
value: value.toDouble(),
|
min: 10,
|
||||||
min: 10,
|
max: 100,
|
||||||
max: 100,
|
divisions: 9,
|
||||||
divisions: 9,
|
label: value.round().toString(),
|
||||||
label: value.round().toString(),
|
onChanged: (value) {
|
||||||
onChanged: (value) {
|
limit.value = value.round();
|
||||||
limit.value = value.round();
|
},
|
||||||
},
|
),
|
||||||
),
|
)
|
||||||
)
|
],
|
||||||
],
|
)
|
||||||
)
|
],
|
||||||
],
|
);
|
||||||
);
|
},
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
if (constrains.mdAndUp)
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: countrySelector,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: genreSelector,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else ...[
|
|
||||||
countrySelector,
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
genreSelector,
|
|
||||||
],
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
if (constrains.mdAndUp)
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: artistAutoComplete,
|
|
||||||
),
|
|
||||||
const SizedBox(width: 16),
|
|
||||||
Expanded(
|
|
||||||
child: tracksAutocomplete,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
else ...[
|
|
||||||
artistAutoComplete,
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
tracksAutocomplete,
|
|
||||||
],
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.acousticness),
|
|
||||||
values: acousticness.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
acousticness.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.danceability),
|
|
||||||
values: danceability.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
danceability.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.energy),
|
|
||||||
values: energy.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
energy.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.instrumentalness),
|
|
||||||
values: instrumentalness.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
instrumentalness.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.liveness),
|
|
||||||
values: liveness.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
liveness.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.loudness),
|
|
||||||
values: loudness.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
loudness.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.speechiness),
|
|
||||||
values: speechiness.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
speechiness.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.valence),
|
|
||||||
values: valence.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
valence.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.popularity),
|
|
||||||
values: popularity.value,
|
|
||||||
base: 100,
|
|
||||||
onChanged: (value) {
|
|
||||||
popularity.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeDials(
|
|
||||||
title: Text(context.l10n.key),
|
|
||||||
values: key.value,
|
|
||||||
base: 11,
|
|
||||||
onChanged: (value) {
|
|
||||||
key.value = value;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
RecommendationAttributeFields(
|
|
||||||
title: Text(context.l10n.duration),
|
|
||||||
values: (
|
|
||||||
max: durationMs.value.max / 1000,
|
|
||||||
target: durationMs.value.target / 1000,
|
|
||||||
min: durationMs.value.min / 1000,
|
|
||||||
),
|
),
|
||||||
onChanged: (value) {
|
const SizedBox(height: 16),
|
||||||
durationMs.value = (
|
if (constrains.mdAndUp)
|
||||||
max: value.max * 1000,
|
Row(
|
||||||
target: value.target * 1000,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
min: value.min * 1000,
|
children: [
|
||||||
);
|
Expanded(
|
||||||
},
|
child: countrySelector,
|
||||||
presets: {
|
),
|
||||||
context.l10n.short: (min: 50, target: 90, max: 120),
|
const SizedBox(width: 16),
|
||||||
context.l10n.medium: (min: 120, target: 180, max: 200),
|
Expanded(
|
||||||
context.l10n.long: (min: 480, target: 560, max: 640)
|
child: genreSelector,
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
RecommendationAttributeFields(
|
)
|
||||||
title: Text(context.l10n.tempo),
|
else ...[
|
||||||
values: tempo.value,
|
countrySelector,
|
||||||
onChanged: (value) {
|
const SizedBox(height: 16),
|
||||||
tempo.value = value;
|
genreSelector,
|
||||||
},
|
],
|
||||||
),
|
const SizedBox(height: 16),
|
||||||
RecommendationAttributeFields(
|
if (constrains.mdAndUp)
|
||||||
title: Text(context.l10n.mode),
|
Row(
|
||||||
values: mode.value,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
onChanged: (value) {
|
children: [
|
||||||
mode.value = value;
|
Expanded(
|
||||||
},
|
child: artistAutoComplete,
|
||||||
),
|
),
|
||||||
RecommendationAttributeFields(
|
const SizedBox(width: 16),
|
||||||
title: Text(context.l10n.time_signature),
|
Expanded(
|
||||||
values: timeSignature.value,
|
child: tracksAutocomplete,
|
||||||
onChanged: (value) {
|
),
|
||||||
timeSignature.value = value;
|
],
|
||||||
},
|
)
|
||||||
),
|
else ...[
|
||||||
const SizedBox(height: 20),
|
artistAutoComplete,
|
||||||
FilledButton.icon(
|
const SizedBox(height: 16),
|
||||||
icon: const Icon(SpotubeIcons.magic),
|
tracksAutocomplete,
|
||||||
label: Text(context.l10n.generate_playlist),
|
],
|
||||||
onPressed: artists.value.isEmpty &&
|
const SizedBox(height: 16),
|
||||||
tracks.value.isEmpty &&
|
RecommendationAttributeDials(
|
||||||
genres.value.isEmpty
|
title: Text(context.l10n.acousticness),
|
||||||
? null
|
values: acousticness.value,
|
||||||
: () {
|
onChanged: (value) {
|
||||||
final PlaylistGenerateResultRouteState routeState = (
|
acousticness.value = value;
|
||||||
seeds: (
|
},
|
||||||
artists: artists.value.map((a) => a.id!).toList(),
|
),
|
||||||
tracks: tracks.value.map((t) => t.id!).toList(),
|
RecommendationAttributeDials(
|
||||||
genres: genres.value
|
title: Text(context.l10n.danceability),
|
||||||
),
|
values: danceability.value,
|
||||||
market: market.value,
|
onChanged: (value) {
|
||||||
limit: limit.value,
|
danceability.value = value;
|
||||||
parameters: (
|
},
|
||||||
acousticness: acousticness.value,
|
),
|
||||||
danceability: danceability.value,
|
RecommendationAttributeDials(
|
||||||
energy: energy.value,
|
title: Text(context.l10n.energy),
|
||||||
instrumentalness: instrumentalness.value,
|
values: energy.value,
|
||||||
liveness: liveness.value,
|
onChanged: (value) {
|
||||||
loudness: loudness.value,
|
energy.value = value;
|
||||||
speechiness: speechiness.value,
|
},
|
||||||
valence: valence.value,
|
),
|
||||||
popularity: popularity.value,
|
RecommendationAttributeDials(
|
||||||
key: key.value,
|
title: Text(context.l10n.instrumentalness),
|
||||||
duration_ms: durationMs.value,
|
values: instrumentalness.value,
|
||||||
tempo: tempo.value,
|
onChanged: (value) {
|
||||||
mode: mode.value,
|
instrumentalness.value = value;
|
||||||
time_signature: timeSignature.value,
|
},
|
||||||
)
|
),
|
||||||
);
|
RecommendationAttributeDials(
|
||||||
GoRouter.of(context).push(
|
title: Text(context.l10n.liveness),
|
||||||
"/library/generate/result",
|
values: liveness.value,
|
||||||
extra: routeState,
|
onChanged: (value) {
|
||||||
);
|
liveness.value = value;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
RecommendationAttributeDials(
|
||||||
);
|
title: Text(context.l10n.loudness),
|
||||||
}),
|
values: loudness.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
loudness.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeDials(
|
||||||
|
title: Text(context.l10n.speechiness),
|
||||||
|
values: speechiness.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
speechiness.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeDials(
|
||||||
|
title: Text(context.l10n.valence),
|
||||||
|
values: valence.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
valence.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeDials(
|
||||||
|
title: Text(context.l10n.popularity),
|
||||||
|
values: popularity.value,
|
||||||
|
base: 100,
|
||||||
|
onChanged: (value) {
|
||||||
|
popularity.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeDials(
|
||||||
|
title: Text(context.l10n.key),
|
||||||
|
values: key.value,
|
||||||
|
base: 11,
|
||||||
|
onChanged: (value) {
|
||||||
|
key.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeFields(
|
||||||
|
title: Text(context.l10n.duration),
|
||||||
|
values: (
|
||||||
|
max: durationMs.value.max / 1000,
|
||||||
|
target: durationMs.value.target / 1000,
|
||||||
|
min: durationMs.value.min / 1000,
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
durationMs.value = (
|
||||||
|
max: value.max * 1000,
|
||||||
|
target: value.target * 1000,
|
||||||
|
min: value.min * 1000,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
presets: {
|
||||||
|
context.l10n.short: (min: 50, target: 90, max: 120),
|
||||||
|
context.l10n.medium: (min: 120, target: 180, max: 200),
|
||||||
|
context.l10n.long: (min: 480, target: 560, max: 640)
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeFields(
|
||||||
|
title: Text(context.l10n.tempo),
|
||||||
|
values: tempo.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
tempo.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeFields(
|
||||||
|
title: Text(context.l10n.mode),
|
||||||
|
values: mode.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
mode.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
RecommendationAttributeFields(
|
||||||
|
title: Text(context.l10n.time_signature),
|
||||||
|
values: timeSignature.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
timeSignature.value = value;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
FilledButton.icon(
|
||||||
|
icon: const Icon(SpotubeIcons.magic),
|
||||||
|
label: Text(context.l10n.generate_playlist),
|
||||||
|
onPressed: artists.value.isEmpty &&
|
||||||
|
tracks.value.isEmpty &&
|
||||||
|
genres.value.isEmpty
|
||||||
|
? null
|
||||||
|
: () {
|
||||||
|
final PlaylistGenerateResultRouteState routeState = (
|
||||||
|
seeds: (
|
||||||
|
artists: artists.value.map((a) => a.id!).toList(),
|
||||||
|
tracks: tracks.value.map((t) => t.id!).toList(),
|
||||||
|
genres: genres.value
|
||||||
|
),
|
||||||
|
market: market.value,
|
||||||
|
limit: limit.value,
|
||||||
|
parameters: (
|
||||||
|
acousticness: acousticness.value,
|
||||||
|
danceability: danceability.value,
|
||||||
|
energy: energy.value,
|
||||||
|
instrumentalness: instrumentalness.value,
|
||||||
|
liveness: liveness.value,
|
||||||
|
loudness: loudness.value,
|
||||||
|
speechiness: speechiness.value,
|
||||||
|
valence: valence.value,
|
||||||
|
popularity: popularity.value,
|
||||||
|
key: key.value,
|
||||||
|
duration_ms: durationMs.value,
|
||||||
|
tempo: tempo.value,
|
||||||
|
mode: mode.value,
|
||||||
|
time_signature: timeSignature.value,
|
||||||
|
)
|
||||||
|
);
|
||||||
|
GoRouter.of(context).push(
|
||||||
|
"/library/generate/result",
|
||||||
|
extra: routeState,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user