diff --git a/assets/spotube-logo.svg b/assets/spotube-logo.svg
new file mode 100644
index 00000000..54cbb448
--- /dev/null
+++ b/assets/spotube-logo.svg
@@ -0,0 +1,68 @@
+
+
\ No newline at end of file
diff --git a/assets/spotube_banner.svg b/assets/spotube_banner.svg
index 76f4a7f8..040487e7 100644
--- a/assets/spotube_banner.svg
+++ b/assets/spotube_banner.svg
@@ -1,9 +1,70 @@
-
-
-
\ No newline at end of file
+
+
\ No newline at end of file
diff --git a/lib/components/Home.dart b/lib/components/Home.dart
index bd2b2ea2..463c76ba 100644
--- a/lib/components/Home.dart
+++ b/lib/components/Home.dart
@@ -33,8 +33,13 @@ class _HomeState extends State {
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 {
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 {
),
),
// 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(builder: (context, data, widget) {
+ return FutureBuilder(
+ 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(builder: (_, data, __) {
- return Expanded(
- child: Scrollbar(
- child: PagedListView(
- pagingController: _pagingController,
- builderDelegate: PagedChildBuilderDelegate(
- itemBuilder: (context, item, index) {
- return CategoryCard(item);
- },
- )),
+ Expanded(
+ child: Scrollbar(
+ child: PagedListView(
+ pagingController: _pagingController,
+ builderDelegate: PagedChildBuilderDelegate(
+ itemBuilder: (context, item, index) {
+ return CategoryCard(item);
+ },
+ ),
),
- );
- }),
+ ),
+ ),
],
),
),
diff --git a/lib/components/Login.dart b/lib/components/Login.dart
index 19ba4255..88eb2a1b 100644
--- a/lib/components/Login.dart
+++ b/lib/components/Login.dart
@@ -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 {
return Consumer(
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"),
+ )
+ ],
+ ),
+ ),
],
),
),
diff --git a/lib/components/Player.dart b/lib/components/Player.dart
index b4161e1e..44585420 100644
--- a/lib/components/Player.dart
+++ b/lib/components/Player.dart
@@ -115,22 +115,27 @@ class _PlayerState extends State {
}
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);
}
}
diff --git a/lib/components/PlaylistCard.dart b/lib/components/PlaylistCard.dart
index fc0ef33c..fbd1ea20 100644
--- a/lib/components/PlaylistCard.dart
+++ b/lib/components/PlaylistCard.dart
@@ -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 {
));
},
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 {
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 {
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();
+ SpotifyDI data = context.watch();
+ bool isPlaylistPlaying = playback.currentPlaylist !=
+ null &&
+ playback.currentPlaylist!.id == widget.playlist.id;
+ return ElevatedButton(
+ onPressed: () async {
+ if (isPlaylistPlaying) return;
+
+ List