Skip to content

Commit

Permalink
Merge pull request #399 from KRTirtho/feat-server
Browse files Browse the repository at this point in the history
Playback Manager Rewrite and Custom Server
  • Loading branch information
KRTirtho committed Feb 3, 2023
2 parents 84d94b0 + 1956692 commit 0104362
Show file tree
Hide file tree
Showing 59 changed files with 1,918 additions and 1,411 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/spotube-nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ jobs:
curl -sS https://webi.sh/yq | sh
yq -i '.version |= sub("\+\d+", "-nightly-")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
flutter config --enable-linux-desktop
flutter pub get
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
Expand Down Expand Up @@ -63,6 +64,7 @@ jobs:
curl -sS https://webi.sh/yq | sh
yq -i '.version |= sub("\+\d+", "-nightly-")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
flutter pub get
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
echo '${{ secrets.KEYSTORE }}' | base64 --decode > android/app/upload-keystore.jks
Expand Down Expand Up @@ -93,6 +95,7 @@ jobs:
yq -i '.version |= sub("\+\d+", "-nightly-")' pubspec.yaml
yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
sed -i "s/%{{SPOTUBE_VERSION}}%/${{ env.GITHUB_RUN_NUMBER }}/" windows/runner/Runner.rc
echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
flutter config --enable-windows-desktop
flutter pub get
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
Expand Down Expand Up @@ -120,6 +123,7 @@ jobs:
- run: brew install yq
- run: yq -i '.version |= sub("\+\d+", "-nightly-")' pubspec.yaml
- run: yq -i '.version += strenv(GITHUB_RUN_NUMBER)' pubspec.yaml
- run: echo '${{ secrets.DOTENV_NIGHTLY }}' > .env
- run: flutter config --enable-macos-desktop
- run: flutter pub get
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/spotube-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ jobs:
with:
cache: true
- run: |
echo '${{ secrets.DOTENV_RELEASE }}' > .env
flutter config --enable-windows-desktop
flutter pub get
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
Expand Down Expand Up @@ -72,6 +73,7 @@ jobs:
- uses: subosito/[email protected]
with:
cache: true
- run: echo '${{ secrets.DOTENV_RELEASE }}' > .env
- run: flutter config --enable-macos-desktop
- run: flutter pub get
- run: dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
Expand Down Expand Up @@ -112,6 +114,7 @@ jobs:
# replacing & adding new release version with older version
- run: |
sed -i 's|%{{APPDATA_RELEASE}}%|<release version="${{ steps.tag.outputs.tag }}" date="${{ steps.date.outputs.date }}" />|' linux/com.github.KRTirtho.Spotube.appdata.xml
echo '${{ secrets.DOTENV_RELEASE }}' > .env
- run: |
flutter config --enable-linux-desktop
Expand Down Expand Up @@ -146,6 +149,7 @@ jobs:
sudo apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev make python3-pip python3-setuptools patchelf desktop-file-utils libgdk-pixbuf2.0-dev fakeroot strace fuse
- run: |
echo '${{ secrets.DOTENV_RELEASE }}' > .env
flutter pub get
dart bin/create-secrets.dart '${{ secrets.LYRICS_SECRET }}' '${{ secrets.SPOTIFY_SECRET }}'
echo '${{ secrets.KEYSTORE }}' | base64 --decode > android/app/upload-keystore.jks
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,5 @@ appimage-build

android/key.properties
.fvm/flutter_sdk

**/pb_data
4 changes: 2 additions & 2 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,6 @@ flutter {
}

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.android.support:multidex:1.0.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
implementation 'com.android.support:multidex:2.0.1'
}
2 changes: 1 addition & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
buildscript {
ext.kotlin_version = '1.6.10'
ext.kotlin_version = '1.7.21'
repositories {
google()
mavenCentral()
Expand Down
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-all.zip
15 changes: 15 additions & 0 deletions lib/collections/env.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import 'package:flutter/foundation.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

abstract class Env {
static final String pocketbaseUrl =
dotenv.get('POCKETBASE_URL', fallback: 'http://localhost:8090');
static final String username = dotenv.get('USERNAME', fallback: 'root');
static final String password = dotenv.get('PASSWORD', fallback: '12345678');

static configure() async {
if (kReleaseMode) {
await dotenv.load(fileName: ".env");
}
}
}
42 changes: 20 additions & 22 deletions lib/collections/intents.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@ import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/player/player_controls.dart';
import 'package:spotube/collections/routes.dart';
import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/playback_provider.dart';
import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/utils/platform.dart';
import 'package:window_manager/window_manager.dart';

Expand All @@ -23,23 +22,22 @@ class PlayPauseAction extends Action<PlayPauseIntent> {
if (PlayerControls.focusNode.canRequestFocus) {
PlayerControls.focusNode.requestFocus();
}
final playback = intent.ref.read(playbackProvider);
if (playback.track == null) {
final playlist = intent.ref.read(PlaylistQueueNotifier.provider);
final playlistNotifier = intent.ref.read(PlaylistQueueNotifier.notifier);
if (playlist == null) {
return null;
} else if (playback.track != null &&
playback.currentDuration == Duration.zero &&
await playback.player.getCurrentPosition() == Duration.zero) {
if (playback.track!.ytUri.startsWith("http")) {
final track = Track.fromJson(playback.track!.toJson());
playback.track = null;
await playback.play(track);
} else {
final track = playback.track;
playback.track = null;
await playback.play(track!);
}
} else if (!PlaylistQueueNotifier.isPlaying) {
// if (playlist.activeTrack is SpotubeTrack &&
// (playlist.activeTrack as SpotubeTrack).ytUri.startsWith("http")) {
// final track =
// Track.fromJson((playlist.activeTrack as SpotubeTrack).toJson());

// await playlistNotifier.play(track);
// } else {
// }
await playlistNotifier.play();
} else {
await playback.togglePlayPause();
await playlistNotifier.pause();
}
return null;
}
Expand Down Expand Up @@ -102,9 +100,9 @@ class SeekIntent extends Intent {
class SeekAction extends Action<SeekIntent> {
@override
invoke(intent) async {
final playback = intent.ref.read(playbackProvider);
if ((playback.playlist == null && playback.track == null) ||
playback.status == PlaybackStatus.loading) {
final playlist = intent.ref.read(PlaylistQueueNotifier.provider);
final playlistNotifier = intent.ref.read(PlaylistQueueNotifier.notifier);
if (playlist == null || playlist.isLoading) {
DirectionalFocusAction().invoke(
DirectionalFocusIntent(
intent.forward ? TraversalDirection.right : TraversalDirection.left,
Expand All @@ -113,8 +111,8 @@ class SeekAction extends Action<SeekIntent> {
return null;
}
final position =
(await playback.player.getCurrentPosition() ?? Duration.zero).inSeconds;
await playback.seekPosition(
(await audioPlayer.getCurrentPosition() ?? Duration.zero).inSeconds;
await playlistNotifier.seek(
Duration(
seconds: intent.forward ? position + 5 : position - 5,
),
Expand Down
31 changes: 13 additions & 18 deletions lib/components/album/album_card.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:spotify/spotify.dart';
import 'package:spotube/components/shared/playbutton_card.dart';
import 'package:spotube/hooks/use_breakpoint_value.dart';
import 'package:spotube/models/current_playlist.dart';
import 'package:spotube/provider/playback_provider.dart';
import 'package:spotube/provider/spotify_provider.dart';
import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/utils/service_utils.dart';
import 'package:spotube/utils/type_conversion_utils.dart';

Expand All @@ -20,9 +20,10 @@ class AlbumCard extends HookConsumerWidget {

@override
Widget build(BuildContext context, ref) {
Playback playback = ref.watch(playbackProvider);
bool isPlaylistPlaying =
playback.playlist != null && playback.playlist!.id == album.id;
final playlist = ref.watch(PlaylistQueueNotifier.provider);
final playing = useStream(PlaylistQueueNotifier.playing).data ?? false;
final playlistNotifier = ref.watch(PlaylistQueueNotifier.notifier);
bool isPlaylistPlaying = playlistNotifier.isPlayingPlaylist(album.tracks!);
final int marginH =
useBreakpointValue(sm: 10, md: 15, lg: 20, xl: 20, xxl: 20);
return PlaybuttonCard(
Expand All @@ -32,9 +33,8 @@ class AlbumCard extends HookConsumerWidget {
),
viewType: viewType,
margin: EdgeInsets.symmetric(horizontal: marginH.toDouble()),
isPlaying: isPlaylistPlaying && playback.isPlaying,
isLoading: playback.status == PlaybackStatus.loading &&
playback.playlist?.id == album.id,
isPlaying: isPlaylistPlaying && playing,
isLoading: isPlaylistPlaying && playlist?.isLoading == true,
title: album.name!,
description:
"Album • ${TypeConversionUtils.artists_X_String<ArtistSimple>(album.artists ?? [])}",
Expand All @@ -43,23 +43,18 @@ class AlbumCard extends HookConsumerWidget {
},
onPlaybuttonPressed: () async {
SpotifyApi spotify = ref.read(spotifyProvider);
if (isPlaylistPlaying && playback.isPlaying) {
return playback.pause();
} else if (isPlaylistPlaying && !playback.isPlaying) {
return playback.resume();
if (isPlaylistPlaying && playing) {
return playlistNotifier.pause();
} else if (isPlaylistPlaying && !playing) {
return playlistNotifier.resume();
}
List<Track> tracks = (await spotify.albums.getTracks(album.id!).all())
.map((track) =>
TypeConversionUtils.simpleTrack_X_Track(track, album))
.toList();
if (tracks.isEmpty) return;

await playback.playPlaylist(CurrentPlaylist(
tracks: tracks,
id: album.id!,
name: album.name!,
thumbnail: album.images!.first.url!,
));
await playlistNotifier.loadAndPlay(tracks);
},
);
}
Expand Down
69 changes: 34 additions & 35 deletions lib/components/library/user_local_tracks.dart
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,8 @@ import 'package:spotube/components/shared/sort_tracks_dropdown.dart';
import 'package:spotube/components/shared/track_table/track_tile.dart';
import 'package:spotube/hooks/use_async_effect.dart';
import 'package:spotube/hooks/use_breakpoints.dart';
import 'package:spotube/models/current_playlist.dart';
import 'package:spotube/models/logger.dart';
import 'package:spotube/provider/playback_provider.dart';
import 'package:spotube/models/local_track.dart';
import 'package:spotube/provider/playlist_queue_provider.dart';
import 'package:spotube/provider/user_preferences_provider.dart';
import 'package:spotube/utils/platform.dart';
import 'package:spotube/utils/primitive_utils.dart';
Expand Down Expand Up @@ -58,7 +57,7 @@ enum SortBy {
dateAdded,
}

final localTracksProvider = FutureProvider<List<Track>>((ref) async {
final localTracksProvider = FutureProvider<List<LocalTrack>>((ref) async {
try {
if (kIsWeb) return [];
final downloadLocation = ref.watch(
Expand Down Expand Up @@ -97,9 +96,8 @@ final localTracksProvider = FutureProvider<List<Track>>((ref) async {

return {"metadata": metadata, "file": f, "art": imageFile.path};
} on FfiException catch (e) {
if (e.message == "NoTag: reader does not contain an id3 tag") {
getLogger(FutureProvider<List<Track>>)
.v("[Fetching metadata]", e.message);
if (e.message != "NoTag: reader does not contain an id3 tag") {
rethrow;
}
return {};
} catch (e, stack) {
Expand All @@ -114,10 +112,13 @@ final localTracksProvider = FutureProvider<List<Track>>((ref) async {

final tracks = filesWithMetadata
.map(
(fileWithMetadata) => TypeConversionUtils.localTrack_X_Track(
fileWithMetadata["file"],
metadata: fileWithMetadata["metadata"],
art: fileWithMetadata["art"],
(fileWithMetadata) => LocalTrack.fromTrack(
track: TypeConversionUtils.localTrack_X_Track(
fileWithMetadata["file"],
metadata: fileWithMetadata["metadata"],
art: fileWithMetadata["art"],
),
path: fileWithMetadata["file"].path,
),
)
.toList();
Expand All @@ -132,37 +133,34 @@ final localTracksProvider = FutureProvider<List<Track>>((ref) async {
class UserLocalTracks extends HookConsumerWidget {
const UserLocalTracks({Key? key}) : super(key: key);

void playLocalTracks(Playback playback, List<Track> tracks,
{Track? currentTrack}) async {
void playLocalTracks(
PlaylistQueueNotifier playback,
List<LocalTrack> tracks, {
LocalTrack? currentTrack,
}) async {
currentTrack ??= tracks.first;
final isPlaylistPlaying = playback.playlist?.id == "local";
final isPlaylistPlaying = playback.isPlayingPlaylist(tracks);
if (!isPlaylistPlaying) {
await playback.playPlaylist(
CurrentPlaylist(
tracks: tracks,
id: "local",
name: "Local Tracks",
thumbnail: TypeConversionUtils.image_X_UrlString(
null,
placeholder: ImagePlaceholder.collection,
),
isLocal: true,
),
tracks.indexWhere((s) => s.id == currentTrack?.id),
await playback.loadAndPlay(
tracks,
active: tracks.indexWhere((s) => s.id == currentTrack?.id),
);
} else if (isPlaylistPlaying &&
currentTrack.id != null &&
currentTrack.id != playback.track?.id) {
await playback.play(currentTrack);
currentTrack.id != playback.state?.activeTrack.id) {
await playback.playTrack(currentTrack);
}
}

@override
Widget build(BuildContext context, ref) {
final sortBy = useState<SortBy>(SortBy.none);
final playback = ref.watch(playbackProvider);
final isPlaylistPlaying = playback.playlist?.id == "local";
final playlist = ref.watch(PlaylistQueueNotifier.provider);
final playlistNotifier = ref.watch(PlaylistQueueNotifier.notifier);
final trackSnapshot = ref.watch(localTracksProvider);
final isPlaylistPlaying = playlistNotifier.isPlayingPlaylist(
trackSnapshot.value ?? [],
);
final isMounted = useIsMounted();
final breakpoint = useBreakpoints();

Expand Down Expand Up @@ -198,9 +196,10 @@ class UserLocalTracks extends HookConsumerWidget {
? () {
if (trackSnapshot.value?.isNotEmpty == true) {
if (!isPlaylistPlaying) {
playLocalTracks(playback, trackSnapshot.value!);
playLocalTracks(
playlistNotifier, trackSnapshot.value!);
} else {
playback.stop();
playlistNotifier.stop();
}
}
}
Expand Down Expand Up @@ -267,17 +266,17 @@ class UserLocalTracks extends HookConsumerWidget {
itemBuilder: (context, index) {
final track = filteredTracks[index];
return TrackTile(
playback,
playlist,
duration:
"${track.duration?.inMinutes.remainder(60)}:${PrimitiveUtils.zeroPadNumStr(track.duration?.inSeconds.remainder(60) ?? 0)}",
track: MapEntry(index, track),
isActive: playback.track?.id == track.id,
isActive: playlist?.activeTrack.id == track.id,
isChecked: false,
showCheck: false,
isLocal: true,
onTrackPlayButtonPressed: (currentTrack) {
return playLocalTracks(
playback,
playlistNotifier,
sortedTracks,
currentTrack: track,
);
Expand Down
Loading

0 comments on commit 0104362

Please sign in to comment.