fix: playlist generate slider shape

This commit is contained in:
Kingkor Roy Tirtho 2023-06-15 13:00:49 +06:00
parent ce38233de8
commit 2b35c044ad
3 changed files with 249 additions and 244 deletions

View File

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

View File

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

View File

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