diff --git a/README.md b/README.md index f7031453a..5b51d7855 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ + +# 🚨 DO NOT INSTALL Spotube FROM `PLAY STORE` +## There's an unofficial + `illegal` clone/copycat of Spotube available on `Play Store` that is full of malware, ads and trackers. To help take down this illegal copycat/clone, please FOLLOW THIS GUIDE : [wiki/Report-Spotube-Copycat-on-PlayStore](https://github.com/KRTirtho/spotube/wiki/Report-Spotube-Copycat-on-Playstore) + +Follow this issue thread to get updates on the progress of the legal action against the illegal copycat/clone: https://github.com/KRTirtho/spotube/issues/448 + +

Spotube Logo

@@ -206,7 +213,7 @@ But why? You can learn about it [here](https://dev.to/krtirtho/choosing-open-sou - [Kingkor Roy Tirtho](https://github.com/KRTirtho) - The Founder, Maintainer and Lead Developer - [Owen Conor](https://github.com/owencz1998) - The Cool Discord Moderator - [Piotr Rogowski](https://github.com/karniv00l) - The MacOS Developer -- [RaptaG](https://github.com/raptag) - The Github Moderator and Community Manager +- [RaptaG](https://github.com/raptag) - The GitHub Moderator and Community Manager - [Rusty Apple](https://github.com/RustyApple) - The Mysterious Unknown Guy # Social platforms diff --git a/lib/pages/lyrics/lyrics.dart b/lib/pages/lyrics/lyrics.dart index a2c0c537f..d1df57b86 100644 --- a/lib/pages/lyrics/lyrics.dart +++ b/lib/pages/lyrics/lyrics.dart @@ -5,6 +5,7 @@ import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:spotube/collections/spotube_icons.dart'; +import 'package:spotube/components/shared/fallbacks/anonymous_fallback.dart'; import 'package:spotube/components/shared/page_window_title_bar.dart'; import 'package:spotube/components/shared/image/universal_image.dart'; import 'package:spotube/components/shared/themed_button_tab_bar.dart'; @@ -13,6 +14,7 @@ import 'package:spotube/hooks/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/use_palette_color.dart'; import 'package:spotube/pages/lyrics/plain_lyrics.dart'; import 'package:spotube/pages/lyrics/synced_lyrics.dart'; +import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/utils/platform.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; @@ -48,6 +50,15 @@ class LyricsPage extends HookConsumerWidget { ], ); + final auth = ref.watch(AuthenticationNotifier.provider); + + if (auth == null) { + return Scaffold( + appBar: !kIsMacOS && !isModal ? const PageWindowTitleBar() : null, + body: const AnonymousFallback(), + ); + } + if (isModal) { return DefaultTabController( length: 2, diff --git a/lib/pages/player/player.dart b/lib/pages/player/player.dart index c287a41f4..38230db3c 100644 --- a/lib/pages/player/player.dart +++ b/lib/pages/player/player.dart @@ -17,6 +17,7 @@ import 'package:spotube/hooks/use_custom_status_bar_color.dart'; import 'package:spotube/hooks/use_palette_color.dart'; import 'package:spotube/models/local_track.dart'; import 'package:spotube/pages/lyrics/lyrics.dart'; +import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/playlist_queue_provider.dart'; import 'package:spotube/provider/user_preferences_provider.dart'; import 'package:spotube/utils/type_conversion_utils.dart'; @@ -29,6 +30,7 @@ class PlayerView extends HookConsumerWidget { @override Widget build(BuildContext context, ref) { final theme = Theme.of(context); + final auth = ref.watch(AuthenticationNotifier.provider); final currentTrack = ref.watch(PlaylistQueueNotifier.provider.select( (value) => value?.activeTrack, )); @@ -180,32 +182,33 @@ class PlayerView extends HookConsumerWidget { mainAxisAlignment: MainAxisAlignment.spaceEvenly, floatingQueue: false, extraActions: [ - IconButton( - tooltip: "Open Lyrics", - icon: const Icon(SpotubeIcons.music), - onPressed: () { - showModalBottomSheet( - context: context, - isDismissible: true, - enableDrag: true, - isScrollControlled: true, - backgroundColor: Colors.black38, - barrierColor: Colors.black12, - shape: const RoundedRectangleBorder( - borderRadius: BorderRadius.only( - topLeft: Radius.circular(20), - topRight: Radius.circular(20), + if (auth != null) + IconButton( + tooltip: "Open Lyrics", + icon: const Icon(SpotubeIcons.music), + onPressed: () { + showModalBottomSheet( + context: context, + isDismissible: true, + enableDrag: true, + isScrollControlled: true, + backgroundColor: Colors.black38, + barrierColor: Colors.black12, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.only( + topLeft: Radius.circular(20), + topRight: Radius.circular(20), + ), ), - ), - constraints: BoxConstraints( - maxHeight: - MediaQuery.of(context).size.height * 0.8, - ), - builder: (context) => - const LyricsPage(isModal: true), - ); - }, - ) + constraints: BoxConstraints( + maxHeight: + MediaQuery.of(context).size.height * 0.8, + ), + builder: (context) => + const LyricsPage(isModal: true), + ); + }, + ) ], ), PlayerControls(iconColor: paletteColor.bodyTextColor), diff --git a/lib/pages/root/root_app.dart b/lib/pages/root/root_app.dart index 43620606f..672ddb715 100644 --- a/lib/pages/root/root_app.dart +++ b/lib/pages/root/root_app.dart @@ -8,6 +8,7 @@ import 'package:spotube/components/root/bottom_player.dart'; import 'package:spotube/components/root/sidebar.dart'; import 'package:spotube/components/root/spotube_navigation_bar.dart'; import 'package:spotube/hooks/use_update_checker.dart'; +import 'package:spotube/provider/authentication_provider.dart'; import 'package:spotube/provider/downloader_provider.dart'; const rootPaths = { @@ -28,6 +29,7 @@ class RootApp extends HookConsumerWidget { Widget build(BuildContext context, ref) { final index = useState(0); final isMounted = useIsMounted(); + final auth = ref.watch(AuthenticationNotifier.provider); final downloader = ref.watch(downloaderProvider); useEffect(() { diff --git a/lib/provider/playlist_queue_provider.dart b/lib/provider/playlist_queue_provider.dart index 324a41387..aee2c13bc 100644 --- a/lib/provider/playlist_queue_provider.dart +++ b/lib/provider/playlist_queue_provider.dart @@ -152,7 +152,10 @@ class PlaylistQueueNotifier extends PersistedStateNotifier { void configure() async { if (kIsMobile || kIsMacOS) { mobileService = await AudioService.init( - builder: () => MobileAudioService(this), + builder: () => MobileAudioService( + this, + ref.read(VolumeProvider.provider.notifier), + ), config: const AudioServiceConfig( androidNotificationChannelId: 'com.krtirtho.Spotube', androidNotificationChannelName: 'Spotube', diff --git a/lib/services/mobile_audio_service.dart b/lib/services/mobile_audio_service.dart index c21f0c0b7..ccc1d3d67 100644 --- a/lib/services/mobile_audio_service.dart +++ b/lib/services/mobile_audio_service.dart @@ -9,22 +9,28 @@ import 'package:spotube/services/audio_player.dart'; class MobileAudioService extends BaseAudioHandler { AudioSession? session; final PlaylistQueueNotifier playlistNotifier; + final VolumeProvider volumeNotifier; PlaylistQueue? get playlist => playlistNotifier.state; - MobileAudioService(this.playlistNotifier) { + MobileAudioService(this.playlistNotifier, this.volumeNotifier) { AudioSession.instance.then((s) { session = s; + session?.configure(const AudioSessionConfiguration.music()); s.interruptionEventStream.listen((event) async { - if (event.type != AudioInterruptionType.duck) { - await playlistNotifier.pause(); + switch (event.type) { + case AudioInterruptionType.duck: + await volumeNotifier.setVolume(event.begin ? 0.5 : 1.0); + break; + case AudioInterruptionType.pause: + case AudioInterruptionType.unknown: + await playlistNotifier.pause(); + break; } }); }); audioPlayer.onPlayerStateChanged.listen((state) async { - if (state != PlayerState.completed) { - playbackState.add(await _transformEvent()); - } + playbackState.add(await _transformEvent()); }); audioPlayer.onPositionChanged.listen((pos) async { @@ -46,6 +52,27 @@ class MobileAudioService extends BaseAudioHandler { @override Future seek(Duration position) => playlistNotifier.seek(position); + @override + Future setShuffleMode(AudioServiceShuffleMode shuffleMode) async { + await super.setShuffleMode(shuffleMode); + + if (shuffleMode == AudioServiceShuffleMode.all) { + playlistNotifier.shuffle(); + } else { + playlistNotifier.unshuffle(); + } + } + + @override + Future setRepeatMode(AudioServiceRepeatMode repeatMode) async { + super.setRepeatMode(repeatMode); + if (repeatMode == AudioServiceRepeatMode.all) { + playlistNotifier.loop(); + } else { + playlistNotifier.unloop(); + } + } + @override Future stop() async { await playlistNotifier.stop(); @@ -71,6 +98,7 @@ class MobileAudioService extends BaseAudioHandler { } Future _transformEvent() async { + final position = (await audioPlayer.getCurrentPosition()) ?? Duration.zero; return PlaybackState( controls: [ MediaControl.skipToPrevious, @@ -85,12 +113,17 @@ class MobileAudioService extends BaseAudioHandler { }, androidCompactActionIndices: const [0, 1, 2], playing: audioPlayer.state == PlayerState.playing, - updatePosition: (await audioPlayer.getCurrentPosition()) ?? Duration.zero, - processingState: audioPlayer.state == PlayerState.paused - ? AudioProcessingState.buffering - : audioPlayer.state == PlayerState.playing - ? AudioProcessingState.ready - : AudioProcessingState.idle, + updatePosition: position, + bufferedPosition: position, + shuffleMode: playlist?.isShuffled == true + ? AudioServiceShuffleMode.all + : AudioServiceShuffleMode.none, + repeatMode: playlist?.isLooping == true + ? AudioServiceRepeatMode.one + : AudioServiceRepeatMode.all, + processingState: playlist?.isLoading == true + ? AudioProcessingState.loading + : AudioProcessingState.ready, ); } } diff --git a/scripts/update_flathub_version.py b/scripts/update_flathub_version.py index 8afae00e1..27d6682d5 100644 --- a/scripts/update_flathub_version.py +++ b/scripts/update_flathub_version.py @@ -15,7 +15,7 @@ # Requires the 2nd VERSION argument to be passed version = sys.argv[1:][0] -tar_url = f"https://github.com/{REPO}/releases/download/v{version}/Spotube-linux-x86_64.tar.xz" +tar_url = f"https://github.com/{REPO}/releases/download/v{version}/spotube-linux-{version}-x86_64.tar.xz" tar_sha256 = hashlib.sha256() print(f"Downloading file {tar_url} to generete sha256 sum") tar = requests.get(tar_url)