mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
User Library added
Liked Song Playlist support Screenshot changed
This commit is contained in:
parent
76d0538f96
commit
96629f6a83
@ -1,6 +1,6 @@
|
|||||||

|

|
||||||
|
|
||||||
Spotube is a [qt](https://qt.io) based lightweight spotify client which uses [nodegui/react-nodegui](https://github.com/nodegui/react-nodegui) as frontend & nodejs as backend. It utilizes the power of Spotify & Youtube's public API & creates a hazardless, performant & resource friendly User Experience
|
Spotube is a [Flutter](https://flutter.dev) based lightweight spotify client. It utilizes the power of Spotify & Youtube's public API & creates a hazardless, performant & resource friendly User Experience
|
||||||

|

|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
@ -10,11 +10,11 @@ Following are the features that currently spotube offers:
|
|||||||
- Open Source
|
- Open Source
|
||||||
- No telementry, diagnostics or user data collection
|
- No telementry, diagnostics or user data collection
|
||||||
- Lightweight & resource friendly
|
- Lightweight & resource friendly
|
||||||
- Near native performance & seemless with default desktop themes (Win10, Win7, OSX, QT-default)
|
- Near native performance (Thanks to Flutter+Skia)
|
||||||
- Playback control is on user's machine instead of server based
|
- Playback control is on user's machine instead of server based
|
||||||
- Small size & less data hungry
|
- Small size & less data hungry
|
||||||
- No spotify or youtube ads since it uses all public & free APIs (But it's recommended to support the creators by watching/liking/subscribing to the artists youtube channel or add as favourite track in spotify. Mostly buying spotify premium is the best way to support their valuable creations)
|
- No spotify or youtube ads since it uses all public & free APIs (But it's recommended to support the creators by watching/liking/subscribing to the artists youtube channel or add as favourite track in spotify. Mostly buying spotify premium is the best way to support their valuable creations)
|
||||||
- Lyrics
|
- Lyrics (WIP)
|
||||||
- Downloadable track
|
- Downloadable track
|
||||||
|
|
||||||
## Requirements (Linux🐧 only)
|
## Requirements (Linux🐧 only)
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 380 KiB After Width: | Height: | Size: 920 KiB |
@ -8,6 +8,7 @@ import 'package:spotube/components/CategoryCard.dart';
|
|||||||
import 'package:spotube/components/Login.dart';
|
import 'package:spotube/components/Login.dart';
|
||||||
import 'package:spotube/components/Player.dart' as player;
|
import 'package:spotube/components/Player.dart' as player;
|
||||||
import 'package:spotube/components/Settings.dart';
|
import 'package:spotube/components/Settings.dart';
|
||||||
|
import 'package:spotube/components/UserLibrary.dart';
|
||||||
import 'package:spotube/models/LocalStorageKeys.dart';
|
import 'package:spotube/models/LocalStorageKeys.dart';
|
||||||
import 'package:spotube/models/sideBarTiles.dart';
|
import 'package:spotube/models/sideBarTiles.dart';
|
||||||
import 'package:spotube/provider/Auth.dart';
|
import 'package:spotube/provider/Auth.dart';
|
||||||
@ -205,6 +206,7 @@ class _HomeState extends State<Home> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (_selectedIndex == 2) const UserLibrary(),
|
||||||
// player itself
|
// player itself
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -64,9 +64,16 @@ class _PlaylistCardState extends State<PlaylistCard> {
|
|||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (isPlaylistPlaying) return;
|
if (isPlaylistPlaying) return;
|
||||||
|
|
||||||
List<Track> tracks = (await data.spotifyApi.playlists
|
List<Track> tracks =
|
||||||
.getTracksByPlaylistId(widget.playlist.id!)
|
(widget.playlist.id != "user-liked-tracks"
|
||||||
.all())
|
? await data.spotifyApi.playlists
|
||||||
|
.getTracksByPlaylistId(
|
||||||
|
widget.playlist.id!)
|
||||||
|
.all()
|
||||||
|
: await data.spotifyApi.tracks.me.saved
|
||||||
|
.all()
|
||||||
|
.then((tracks) =>
|
||||||
|
tracks.map((e) => e.track!)))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
playback.setCurrentPlaylist = CurrentPlaylist(
|
playback.setCurrentPlaylist = CurrentPlaylist(
|
||||||
|
@ -25,7 +25,7 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
children: [
|
children: [
|
||||||
TableCell(
|
TableCell(
|
||||||
child: Text(
|
child: Text(
|
||||||
track.key.toString(),
|
(track.key + 1).toString(),
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
)),
|
)),
|
||||||
TableCell(
|
TableCell(
|
||||||
@ -85,9 +85,13 @@ class _PlaylistViewState extends State<PlaylistView> {
|
|||||||
return Consumer<SpotifyDI>(builder: (_, data, __) {
|
return Consumer<SpotifyDI>(builder: (_, data, __) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: FutureBuilder<Iterable<Track>>(
|
body: FutureBuilder<Iterable<Track>>(
|
||||||
future: data.spotifyApi.playlists
|
future: widget.playlist.id != "user-liked-tracks"
|
||||||
|
? data.spotifyApi.playlists
|
||||||
.getTracksByPlaylistId(widget.playlist.id)
|
.getTracksByPlaylistId(widget.playlist.id)
|
||||||
.all(),
|
.all()
|
||||||
|
: data.spotifyApi.tracks.me.saved
|
||||||
|
.all()
|
||||||
|
.then((tracks) => tracks.map((e) => e.track!)),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
List<Track> tracks = snapshot.data?.toList() ?? [];
|
List<Track> tracks = snapshot.data?.toList() ?? [];
|
||||||
TextStyle tableHeadStyle =
|
TextStyle tableHeadStyle =
|
||||||
|
60
lib/components/UserLibrary.dart
Normal file
60
lib/components/UserLibrary.dart
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import 'package:flutter/material.dart' hide Image;
|
||||||
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:spotify/spotify.dart';
|
||||||
|
import 'package:spotube/components/PlaylistCard.dart';
|
||||||
|
import 'package:spotube/provider/SpotifyDI.dart';
|
||||||
|
|
||||||
|
class UserLibrary extends StatefulWidget {
|
||||||
|
const UserLibrary({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_UserLibraryState createState() => _UserLibraryState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UserLibraryState extends State<UserLibrary> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
SpotifyDI data = context.watch<SpotifyDI>();
|
||||||
|
|
||||||
|
return FutureBuilder<Iterable<PlaylistSimple>>(
|
||||||
|
future: data.spotifyApi.playlists.me.all(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const CircularProgressIndicator.adaptive();
|
||||||
|
}
|
||||||
|
Image image = Image();
|
||||||
|
image.height = 300;
|
||||||
|
image.width = 300;
|
||||||
|
PlaylistSimple likedTracksPlaylist = PlaylistSimple();
|
||||||
|
likedTracksPlaylist.name = "Liked Tracks";
|
||||||
|
likedTracksPlaylist.type = "playlist";
|
||||||
|
likedTracksPlaylist.collaborative = false;
|
||||||
|
likedTracksPlaylist.public = false;
|
||||||
|
likedTracksPlaylist.id = "user-liked-tracks";
|
||||||
|
image.url =
|
||||||
|
"https://t.scdn.co/images/3099b3803ad9496896c43f22fe9be8c4.png";
|
||||||
|
likedTracksPlaylist.images = [image];
|
||||||
|
return Expanded(
|
||||||
|
child: Scrollbar(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(8.0),
|
||||||
|
child: Wrap(
|
||||||
|
spacing: 8.0, // gap between adjacent chips
|
||||||
|
runSpacing: 8.0, // gap between lines
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
children: [
|
||||||
|
PlaylistCard(likedTracksPlaylist),
|
||||||
|
...snapshot.data!
|
||||||
|
.map((playlist) => PlaylistCard(playlist))
|
||||||
|
.toList(),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user