mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
Play playlist from PlaylistCard support
Login page tuned Replace loading texts with Circular progress bar Sidebar icons are rounded now New Icon & banner
This commit is contained in:
parent
0ef44709fa
commit
db42e81501
68
assets/spotube-logo.svg
Normal file
68
assets/spotube-logo.svg
Normal file
@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<svg viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:bx="https://boxy-svg.com">
|
||||
<defs>
|
||||
<filter id="inner-shadow-filter-1" x="-500%" y="-500%" width="1000%" height="1000%" bx:preset="inner-shadow 1 0 0 9 0.5 rgba(0,0,0,0.7)">
|
||||
<feOffset dx="0" dy="0"/>
|
||||
<feGaussianBlur stdDeviation="9"/>
|
||||
<feComposite operator="out" in="SourceGraphic"/>
|
||||
<feComponentTransfer result="choke">
|
||||
<feFuncA type="linear" slope="1"/>
|
||||
</feComponentTransfer>
|
||||
<feFlood flood-color="rgba(0,0,0,0.7)" result="color"/>
|
||||
<feComposite operator="in" in="color" in2="choke" result="shadow"/>
|
||||
<feComposite operator="over" in="shadow" in2="SourceGraphic"/>
|
||||
</filter>
|
||||
<linearGradient id="gradient-0-0" gradientUnits="userSpaceOnUse" x1="47.146" y1="18.044" x2="47.146" y2="75.354" xlink:href="#gradient-0"/>
|
||||
<linearGradient id="gradient-0">
|
||||
<stop offset="0.031" style="stop-color: rgb(255, 115, 0);"/>
|
||||
<stop offset="1" style="stop-color: rgb(1, 107, 255);"/>
|
||||
</linearGradient>
|
||||
<filter id="inner-shadow-filter-0" x="-500%" y="-500%" width="1000%" height="1000%" bx:preset="inner-shadow 1 0 0 3 0.5 rgba(0,0,0,0.7)">
|
||||
<feOffset dx="0" dy="0"/>
|
||||
<feGaussianBlur stdDeviation="3"/>
|
||||
<feComposite operator="out" in="SourceGraphic"/>
|
||||
<feComponentTransfer result="choke">
|
||||
<feFuncA type="linear" slope="1"/>
|
||||
</feComponentTransfer>
|
||||
<feFlood flood-color="rgba(0,0,0,0.7)" result="color"/>
|
||||
<feComposite operator="in" in="color" in2="choke" result="shadow"/>
|
||||
<feComposite operator="over" in="shadow" in2="SourceGraphic"/>
|
||||
</filter>
|
||||
<linearGradient id="gradient-4-1" gradientUnits="userSpaceOnUse" x1="82.026" y1="144.832" x2="82.026" y2="264.462" xlink:href="#gradient-4"/>
|
||||
<linearGradient id="gradient-4">
|
||||
<stop offset="0.04" style="stop-color: rgb(255, 107, 1);"/>
|
||||
<stop offset="0.598" style="stop-color: rgb(0, 234, 255);"/>
|
||||
<stop offset="0.909" style="stop-color: rgb(8, 85, 140);"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="gradient-4-2" gradientUnits="userSpaceOnUse" x1="143.693" y1="22.804" x2="143.693" y2="264.582" xlink:href="#gradient-4"/>
|
||||
<linearGradient id="gradient-4-0" gradientUnits="userSpaceOnUse" x1="205.862" y1="146.28" x2="205.862" y2="265.91" xlink:href="#gradient-4"/>
|
||||
</defs>
|
||||
<ellipse style="paint-order: fill; fill: rgb(255, 255, 255); filter: url(#inner-shadow-filter-1);" cx="249.704" cy="250.295" rx="241.45" ry="241.45"/>
|
||||
<g transform="matrix(0.372585, 0, 0, 0.376313, 245.872849, 308.773438)" style="">
|
||||
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(-175.05 -175.05000000000004) scale(3.89 3.89)">
|
||||
<path d="M 91.835 18.32 C 91.637 18.132 91.374 18.036 91.096 18.046 C 84.617 18.367 77.578 19.444 68.948 21.435 C 68.677 21.498 68.444 21.67 68.305 21.911 C 68.166 22.152 68.135 22.44 68.217 22.705 L 69.055 25.409 C 62.692 22.996 53.742 21.607 45.995 21.912 C 43.155 21.912 39.913 23.321 36.95 25.412 L 25.235 25.412 L 26.074 22.704 C 26.157 22.438 26.124 22.151 25.986 21.91 C 25.848 21.669 25.615 21.496 25.344 21.434 C 16.714 19.443 9.676 18.366 3.196 18.045 C 2.927 18.033 2.656 18.13 2.457 18.319 C 2.258 18.509 2.146 18.771 2.146 19.045 L 2.146 53.387 C 2.146 53.94 2.594 54.387 3.146 54.387 L 15.524 54.387 C 15.962 54.387 16.35 54.102 16.479 53.683 L 16.951 52.16 C 27.138 64.032 37.497 74.935 45.585 74.935 C 47.142 74.935 48.614 74.524 49.986 73.645 L 50.197 73.859 C 51.141 74.815 52.406 75.346 53.758 75.354 C 53.769 75.354 53.779 75.354 53.79 75.354 C 55.129 75.354 56.387 74.839 57.336 73.903 C 58.17 73.078 58.635 72.03 58.772 70.947 C 59.702 71.718 60.833 72.127 61.978 72.127 C 63.259 72.126 64.542 71.643 65.525 70.673 C 66.634 69.577 67.105 68.092 66.981 66.648 C 67.427 66.758 67.878 66.833 68.331 66.833 C 69.614 66.833 70.869 66.39 71.779 65.491 C 72.735 64.547 73.266 63.282 73.274 61.93 C 73.282 60.578 72.767 59.308 71.887 58.423 C 71.519 57.97 71.139 57.535 70.766 57.089 L 77.582 52.94 L 77.812 53.682 C 77.942 54.101 78.329 54.386 78.767 54.386 L 91.146 54.386 C 91.699 54.386 92.146 53.939 92.146 53.386 L 92.146 19.045 C 92.146 18.771 92.034 18.509 91.835 18.32 Z M 14.787 52.387 L 4.146 52.387 L 4.146 20.102 C 9.952 20.461 16.268 21.437 23.845 23.145 L 14.787 52.387 Z M 70.373 64.067 C 69.234 65.193 67.063 65.072 65.817 63.809 C 65.8 63.792 65.778 63.786 65.76 63.771 C 65.693 63.694 65.642 63.608 65.569 63.534 L 54.619 52.448 C 54.229 52.056 53.598 52.052 53.204 52.439 C 52.811 52.828 52.808 53.46 53.195 53.854 L 64.145 64.94 C 64.714 65.515 65.025 66.283 65.02 67.1 C 65.015 67.916 64.695 68.68 64.119 69.248 C 62.924 70.431 60.991 70.416 59.809 69.222 L 57.384 66.767 C 57.382 66.765 57.381 66.763 57.38 66.762 L 46.43 55.677 C 46.041 55.286 45.408 55.281 45.016 55.668 C 44.623 56.057 44.619 56.689 45.007 57.083 L 55.956 68.169 C 57.138 69.364 57.126 71.298 55.93 72.479 C 54.734 73.661 52.8 73.647 51.62 72.453 L 38.24 58.908 C 37.851 58.516 37.218 58.51 36.826 58.9 C 36.433 59.288 36.429 59.921 36.817 60.314 L 48.528 72.169 C 41.093 76.143 28.778 62.93 17.651 49.901 L 24.616 27.414 L 34.431 27.414 C 31.69 29.846 29.43 32.75 28.339 35.397 C 26.943 38.783 27.852 40.687 28.86 41.688 C 28.886 41.714 28.914 41.739 28.943 41.762 C 32.786 44.809 36.571 45.577 42.466 39.479 C 44.467 39.601 46.171 39.254 47.65 38.415 C 55.956 44.222 63.587 51.376 70.399 59.758 C 71.581 60.953 71.569 62.887 70.373 64.067 Z M 69.464 55.541 C 63.058 48.131 55.937 41.698 48.248 36.395 C 47.907 36.159 47.455 36.159 47.114 36.394 C 45.792 37.301 44.175 37.645 42.17 37.449 C 41.859 37.415 41.556 37.533 41.343 37.759 C 35.758 43.702 32.999 42.415 30.234 40.232 C 29.238 39.193 29.657 37.448 30.188 36.159 C 32.412 30.761 40.301 23.913 46.034 23.912 C 54.206 23.599 63.683 25.188 69.82 27.879 L 76.972 50.97 L 69.464 55.541 Z M 90.146 52.387 L 79.504 52.387 L 70.446 23.145 C 78.023 21.437 84.34 20.461 90.145 20.102 L 90.145 52.387 Z" style="stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill-rule: nonzero; opacity: 1; stroke: url(#gradient-0-0); fill: rgb(28, 28, 29); stroke-width: 3.33887px; paint-order: stroke;" stroke-linecap="round"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(1.289989, 0, 0, 1.28817, 62.9105, 31.643152)" style="filter: url(#inner-shadow-filter-0);">
|
||||
<g>
|
||||
<path d="M 71.421 155.437 L 71.421 253.857 C 71.421 259.724 76.162 264.462 82.026 264.462 C 87.88 264.462 92.631 259.724 92.631 253.857 L 92.631 155.437 C 92.631 149.581 87.88 144.832 82.026 144.832 C 76.162 144.832 71.421 149.576 71.421 155.437 Z" style="stroke-width: 9.80924px; stroke: url(#gradient-4-1); fill: rgb(29, 29, 29); stroke-linecap: round; stroke-linejoin: round;"/>
|
||||
<path d="M29.456,264.582h23.351v-116.85c0.064-0.56,0.166-1.119,0.166-1.693c0-50.412,40.69-91.42,90.698-91.42 c50.002,0,90.692,41.008,90.692,91.42c0,0.771,0.113,1.518,0.228,2.263v116.28h23.354c16.254,0,29.442-13.64,29.442-30.469 v-60.936c0-13.878-8.989-25.57-21.261-29.249c-1.129-66.971-55.608-121.124-122.45-121.124 c-66.86,0-121.347,54.158-122.465,121.15C8.956,147.638,0,159.32,0,173.187v60.926C0,250.932,13.187,264.582,29.456,264.582z" style="stroke-width: 11.3184px; stroke: url(#gradient-4-2); fill: rgb(29, 29, 29); stroke-linecap: round; stroke-linejoin: round;"/>
|
||||
<path d="M 195.258 156.885 L 195.258 255.305 C 195.258 261.172 200.006 265.91 205.862 265.91 C 211.718 265.91 216.466 261.172 216.466 255.305 L 216.466 156.885 C 216.466 151.029 211.718 146.28 205.862 146.28 C 199.995 146.28 195.258 151.024 195.258 156.885 Z" style="stroke-width: 9.80924px; stroke: url(#gradient-4-0); fill: rgb(29, 29, 29); stroke-linecap: round; stroke-linejoin: round;"/>
|
||||
</g>
|
||||
</g>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
<g transform="matrix(0.972684, 0, 0, 0.972684, 62.9105, 10.735223)" style=""/>
|
||||
</svg>
|
After Width: | Height: | Size: 9.0 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 736 KiB After Width: | Height: | Size: 9.3 KiB |
@ -33,8 +33,13 @@ class _HomeState extends State<Home> {
|
||||
|
||||
if (clientId != null && clientSecret != null) {
|
||||
SpotifyApi spotifyApi = SpotifyApi(
|
||||
SpotifyApiCredentials(clientId, clientSecret,
|
||||
scopes: ["user-library-read", "user-library-modify"]),
|
||||
SpotifyApiCredentials(clientId, clientSecret, scopes: [
|
||||
"user-library-read",
|
||||
"user-library-modify",
|
||||
"user-read-private",
|
||||
"user-read-email",
|
||||
"playlist-read-collaborative"
|
||||
]),
|
||||
);
|
||||
SpotifyApiCredentials credentials = await spotifyApi.getCredentials();
|
||||
if (credentials.accessToken?.isNotEmpty ?? false) {
|
||||
@ -89,7 +94,7 @@ class _HomeState extends State<Home> {
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
color: Colors.grey.shade100,
|
||||
color: Colors.blueGrey[50],
|
||||
constraints: const BoxConstraints(maxWidth: 230),
|
||||
child: Material(
|
||||
type: MaterialType.transparency,
|
||||
@ -121,39 +126,50 @@ class _HomeState extends State<Home> {
|
||||
),
|
||||
),
|
||||
// user name & settings
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
"User's name",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.settings_outlined),
|
||||
onPressed: () {}),
|
||||
],
|
||||
),
|
||||
)
|
||||
Consumer<SpotifyDI>(builder: (context, data, widget) {
|
||||
return FutureBuilder<User>(
|
||||
future: data.spotifyApi.me.get(),
|
||||
builder: (context, snapshot) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
snapshot.data?.displayName ??
|
||||
"User's name",
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon:
|
||||
const Icon(Icons.settings_outlined),
|
||||
onPressed: () {}),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
})
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
// contents of the spotify
|
||||
Consumer<SpotifyDI>(builder: (_, data, __) {
|
||||
return Expanded(
|
||||
child: Scrollbar(
|
||||
child: PagedListView(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Category>(
|
||||
itemBuilder: (context, item, index) {
|
||||
return CategoryCard(item);
|
||||
},
|
||||
)),
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
child: PagedListView(
|
||||
pagingController: _pagingController,
|
||||
builderDelegate: PagedChildBuilderDelegate<Category>(
|
||||
itemBuilder: (context, item, index) {
|
||||
return CategoryCard(item);
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,3 +1,4 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
@ -51,43 +52,61 @@ class _LoginState extends State<Login> {
|
||||
return Consumer<Auth>(
|
||||
builder: (context, authState, child) {
|
||||
return Scaffold(
|
||||
body: Container(
|
||||
padding: EdgeInsets.all(8.0),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text("Add your spotify credentials to get started",
|
||||
style: Theme.of(context).textTheme.headline3),
|
||||
Text(
|
||||
style: Theme.of(context).textTheme.headline4),
|
||||
const Text(
|
||||
"Don't worry, any of your credentials won't be collected or shared with anyone"),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Spotify Client ID", labelText: "ClientId"),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
client_id = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
TextField(
|
||||
decoration: InputDecoration(
|
||||
hintText: "Spotify Client Secret",
|
||||
labelText: "ClientSecret"),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
client_secret = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
SizedBox(
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
MaterialButton(
|
||||
color: Theme.of(context).buttonColor,
|
||||
onPressed: () {
|
||||
handleLogin(authState);
|
||||
},
|
||||
child: Text("Submit"),
|
||||
)
|
||||
Container(
|
||||
constraints: const BoxConstraints(
|
||||
maxWidth: 400,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
hintText: "Spotify Client ID",
|
||||
label: Text("ClientID"),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
client_id = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
TextField(
|
||||
decoration: const InputDecoration(
|
||||
hintText: "Spotify Client Secret",
|
||||
label: Text("Client Secret"),
|
||||
),
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
client_secret = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
height: 10,
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
handleLogin(authState);
|
||||
},
|
||||
child: const Text("Submit"),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -115,22 +115,27 @@ class _PlayerState extends State<Player> {
|
||||
}
|
||||
|
||||
Future playPlaylist(CurrentPlaylist playlist) async {
|
||||
if (player.isRunning() && playlist.id != _currentPlaylistId) {
|
||||
var playlistPath = "/tmp/playlist-${playlist.id}.txt";
|
||||
File file = File(playlistPath);
|
||||
var newPlaylist = playlistToStr(playlist);
|
||||
try {
|
||||
if (player.isRunning() && playlist.id != _currentPlaylistId) {
|
||||
var playlistPath = "/tmp/playlist-${playlist.id}.txt";
|
||||
File file = File(playlistPath);
|
||||
var newPlaylist = playlistToStr(playlist);
|
||||
|
||||
if (!await file.exists()) {
|
||||
await file.create();
|
||||
if (!await file.exists()) {
|
||||
await file.create();
|
||||
}
|
||||
|
||||
await file.writeAsString(newPlaylist);
|
||||
|
||||
await player.loadPlaylist(playlistPath);
|
||||
setState(() {
|
||||
_currentPlaylistId = playlist.id;
|
||||
_shuffled = false;
|
||||
});
|
||||
}
|
||||
|
||||
await file.writeAsString(newPlaylist);
|
||||
|
||||
await player.loadPlaylist(playlistPath);
|
||||
setState(() {
|
||||
_currentPlaylistId = playlist.id;
|
||||
_shuffled = false;
|
||||
});
|
||||
} catch (e, stackTrace) {
|
||||
print("[Player]: $e");
|
||||
print(stackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,11 +1,14 @@
|
||||
import 'package:cached_network_image/cached_network_image.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:spotify/spotify.dart';
|
||||
import 'package:spotube/components/PlaylistView.dart';
|
||||
import 'package:spotube/provider/Playback.dart';
|
||||
import 'package:spotube/provider/SpotifyDI.dart';
|
||||
|
||||
class PlaylistCard extends StatefulWidget {
|
||||
PlaylistSimple playlist;
|
||||
PlaylistCard(this.playlist);
|
||||
final PlaylistSimple playlist;
|
||||
const PlaylistCard(this.playlist, {Key? key}) : super(key: key);
|
||||
@override
|
||||
_PlaylistCardState createState() => _PlaylistCardState();
|
||||
}
|
||||
@ -22,7 +25,7 @@ class _PlaylistCardState extends State<PlaylistCard> {
|
||||
));
|
||||
},
|
||||
child: ConstrainedBox(
|
||||
constraints: BoxConstraints(maxWidth: 200),
|
||||
constraints: const BoxConstraints(maxWidth: 200),
|
||||
child: Ink(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
@ -30,7 +33,7 @@ class _PlaylistCardState extends State<PlaylistCard> {
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
blurRadius: 10,
|
||||
offset: Offset(0, 3),
|
||||
offset: const Offset(0, 3),
|
||||
spreadRadius: 5,
|
||||
color: Colors.grey.shade300,
|
||||
)
|
||||
@ -40,21 +43,66 @@ class _PlaylistCardState extends State<PlaylistCard> {
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
// thumbnail of the playlist
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: widget.playlist.images![0].url!),
|
||||
Stack(
|
||||
children: [
|
||||
ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: CachedNetworkImage(
|
||||
imageUrl: widget.playlist.images![0].url!),
|
||||
),
|
||||
Positioned.directional(
|
||||
textDirection: TextDirection.ltr,
|
||||
bottom: 10,
|
||||
end: 5,
|
||||
child: Builder(builder: (context) {
|
||||
Playback playback = context.watch<Playback>();
|
||||
SpotifyDI data = context.watch<SpotifyDI>();
|
||||
bool isPlaylistPlaying = playback.currentPlaylist !=
|
||||
null &&
|
||||
playback.currentPlaylist!.id == widget.playlist.id;
|
||||
return ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (isPlaylistPlaying) return;
|
||||
|
||||
List<Track> tracks = (await data.spotifyApi.playlists
|
||||
.getTracksByPlaylistId(widget.playlist.id!)
|
||||
.all())
|
||||
.toList();
|
||||
|
||||
playback.setCurrentPlaylist = CurrentPlaylist(
|
||||
tracks: tracks,
|
||||
id: widget.playlist.id!,
|
||||
name: widget.playlist.name!,
|
||||
thumbnail: widget.playlist.images!.first.url!,
|
||||
);
|
||||
},
|
||||
child: Icon(
|
||||
isPlaylistPlaying
|
||||
? Icons.pause_rounded
|
||||
: Icons.play_arrow_rounded,
|
||||
),
|
||||
style: ButtonStyle(
|
||||
shape: MaterialStateProperty.all(
|
||||
const CircleBorder(),
|
||||
),
|
||||
padding: MaterialStateProperty.all(
|
||||
const EdgeInsets.all(16),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(height: 5),
|
||||
const SizedBox(height: 5),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
widget.playlist.name!,
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -45,7 +45,7 @@ class _PlaylistGenreViewState extends State<PlaylistGenreView> {
|
||||
return const Center(child: Text("Error occurred"));
|
||||
}
|
||||
if (!snapshot.hasData) {
|
||||
return const Center(child: Text("Loading.."));
|
||||
return const CircularProgressIndicator.adaptive();
|
||||
}
|
||||
return Wrap(
|
||||
children: snapshot.data!
|
||||
|
@ -15,7 +15,6 @@ class PlaylistView extends StatefulWidget {
|
||||
class _PlaylistViewState extends State<PlaylistView> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Playback playback = context.read<Playback>();
|
||||
return Consumer<SpotifyDI>(builder: (_, data, __) {
|
||||
return Scaffold(
|
||||
body: FutureBuilder<Iterable<Track>>(
|
||||
@ -70,7 +69,7 @@ class _PlaylistViewState extends State<PlaylistView> {
|
||||
snapshot.hasError
|
||||
? const Center(child: Text("Error occurred"))
|
||||
: !snapshot.hasData
|
||||
? const Center(child: Text("Loading.."))
|
||||
? const CircularProgressIndicator.adaptive()
|
||||
: Expanded(
|
||||
child: Scrollbar(
|
||||
isAlwaysShown: true,
|
||||
|
@ -27,13 +27,38 @@ class MyApp extends StatelessWidget {
|
||||
debugShowCheckedModeBanner: false,
|
||||
title: 'Flutter Demo',
|
||||
theme: ThemeData(
|
||||
primaryColor: Colors.greenAccent[400],
|
||||
primarySwatch: Colors.green,
|
||||
buttonTheme: const ButtonThemeData(
|
||||
buttonColor: Colors.green,
|
||||
),
|
||||
),
|
||||
home: Home(),
|
||||
primaryColor: Colors.greenAccent[400],
|
||||
primarySwatch: Colors.green,
|
||||
buttonTheme: const ButtonThemeData(
|
||||
buttonColor: Colors.green,
|
||||
),
|
||||
textTheme: TextTheme(
|
||||
bodyText1: TextStyle(color: Colors.grey[850]),
|
||||
headline1: TextStyle(color: Colors.grey[850]),
|
||||
headline2: TextStyle(color: Colors.grey[850]),
|
||||
headline3: TextStyle(color: Colors.grey[850]),
|
||||
headline4: TextStyle(color: Colors.grey[850]),
|
||||
headline5: TextStyle(color: Colors.grey[850]),
|
||||
headline6: TextStyle(color: Colors.grey[850]),
|
||||
),
|
||||
listTileTheme: ListTileThemeData(
|
||||
iconColor: Colors.grey[850],
|
||||
horizontalTitleGap: 0,
|
||||
),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.green[400]!,
|
||||
width: 2.0,
|
||||
),
|
||||
),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Colors.grey[800]!,
|
||||
),
|
||||
),
|
||||
)),
|
||||
home: const Home(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ class SideBarTiles {
|
||||
}
|
||||
|
||||
List<SideBarTiles> sidebarTileList = [
|
||||
SideBarTiles(icon: Icons.home_filled, title: "Browse"),
|
||||
SideBarTiles(icon: Icons.search, title: "Search"),
|
||||
SideBarTiles(icon: Icons.home_rounded, title: "Browse"),
|
||||
SideBarTiles(icon: Icons.search_rounded, title: "Search"),
|
||||
SideBarTiles(icon: Icons.library_books_rounded, title: "Library"),
|
||||
];
|
||||
|
Loading…
Reference in New Issue
Block a user