mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-12 23:45:18 +00:00
Compare commits
6 Commits
9dc3658455
...
e27f58666e
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e27f58666e | ||
![]() |
151a440e7e | ||
![]() |
9471e008e3 | ||
![]() |
ff252d6b14 | ||
![]() |
195cad8f39 | ||
![]() |
19f525fa3c |
63
CHANGELOG.md
63
CHANGELOG.md
@ -1,5 +1,68 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## [5.0.0](https://github.com/KRTirtho/spotube/compare/v4.0.2...v5.0.0) (2025-09-08)
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
- Add ISRC track search for YouTube ([#2594](https://github.com/KRTirtho/spotube/issues/2594))
|
||||||
|
- Add new icons #2676 by @alexio-dev ([#2678](https://github.com/KRTirtho/spotube/issues/2678))
|
||||||
|
- Add connect confirmation dialog
|
||||||
|
- Add metadata api service and models
|
||||||
|
- **metadata-plugin**: Add pagination support, feed and playlist CRUD endpoints
|
||||||
|
- **metadata-plugin**: Add local storage api
|
||||||
|
- Add webview, totp and setInterval apis for plugins
|
||||||
|
- Enhance local storage and webview APIs with improved error handling and resource management
|
||||||
|
- **metadata_plugin**: Add logout method
|
||||||
|
- Update plugin configuration with more fields
|
||||||
|
- Implement metadata plugins based on hetu
|
||||||
|
- Update models to match hetu_spotube_plugin signature
|
||||||
|
- Add user endpoint calls in metadata and paginated async notifiers
|
||||||
|
- Add playlist endpoint and providers
|
||||||
|
- Add albums metadata endpoint and provider
|
||||||
|
- Add artist and album providers
|
||||||
|
- Add track endpoint for metadata service
|
||||||
|
- Remove green corp names formally
|
||||||
|
- **metadata**: Add plugin form
|
||||||
|
- Add support for entity specific search
|
||||||
|
- Enhance image handling
|
||||||
|
- Add support for automatic plugin repository from github and codeberg
|
||||||
|
- Use isolate for youtube_explode engine
|
||||||
|
- Add repository and plugin API version fields to metadata plugins
|
||||||
|
- Update new pipe version
|
||||||
|
- **metadata**: Add plugin update checker and dialog for available updates
|
||||||
|
- Optimize track options and related artists
|
||||||
|
- Add plugin scrobbling support and support button
|
||||||
|
- Add ErrorBox and NoDefaultMetadataPlugin components
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
- Calling /track/:streamId endpoint causes active sourced track to be anything
|
||||||
|
- **mobile**: Dialogs in bottom sheet are not opening
|
||||||
|
- Default accent color is orange but it shows blue in settings
|
||||||
|
- Artist images are not loading up
|
||||||
|
- CVE: Remote path traversal through websocket when devices are on same network
|
||||||
|
- Endless playback not working
|
||||||
|
- **android**: NewPipe invalid search content filters
|
||||||
|
- Make YoutubeExplode engine faster
|
||||||
|
- Create and delete playlist not working
|
||||||
|
- Local track not working and images of local not showing up
|
||||||
|
- Local playback not working for tracks with special # (hashtag) characters
|
||||||
|
- Inaccessible streaming url causing rapid skips
|
||||||
|
- **yt**: Fallback to different search result if all streaming url is inaccessible
|
||||||
|
- **playback**: Skip network requests if cached file already exists
|
||||||
|
- Yt-dlp playback not working and add partial support for HLS streaming
|
||||||
|
- Windows webview2 environment permission issue
|
||||||
|
- **playback**: Play not fetching full playlist if playlist is too long
|
||||||
|
- **track_options**: Tapping on option doesn't close the menu
|
||||||
|
- **playback**: Alternative track sources switch not working
|
||||||
|
- **ui**: Lyrics white text in white background and small player buttons
|
||||||
|
|
||||||
|
### Translation
|
||||||
|
|
||||||
|
- Add Traditional Chinese translation ([#2762](https://github.com/KRTirtho/spotube/issues/2762))
|
||||||
|
- Fix Japanese translations ([#2732](https://github.com/KRTirtho/spotube/issues/2732))
|
||||||
|
- Correction of the dutch language ([#1306](https://github.com/KRTirtho/spotube/issues/1306))
|
||||||
|
|
||||||
## [4.0.2](https://github.com/krtirtho/spotube/compare/v4.0.1...v4.0.2) (2025-03-16)
|
## [4.0.2](https://github.com/krtirtho/spotube/compare/v4.0.1...v4.0.2) (2025-03-16)
|
||||||
|
|
||||||
### Bug Fixes
|
### Bug Fixes
|
||||||
|
@ -13,7 +13,7 @@ class BackButton extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return IconButton.ghost(
|
return IconButton.ghost(
|
||||||
size: const ButtonSize(.9),
|
size: const ButtonSize(1.2),
|
||||||
icon: Icon(icon, color: color),
|
icon: Icon(icon, color: color),
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
);
|
);
|
||||||
|
@ -137,16 +137,16 @@
|
|||||||
"pre_download_play_description": "Anzi che effettuare lo stream dell'audio, scarica invece i byte e li riproduce (raccomandato per gli utenti con banda più alta)",
|
"pre_download_play_description": "Anzi che effettuare lo stream dell'audio, scarica invece i byte e li riproduce (raccomandato per gli utenti con banda più alta)",
|
||||||
"skip_non_music": "Salta i segmenti non di musica (SponsorBlock)",
|
"skip_non_music": "Salta i segmenti non di musica (SponsorBlock)",
|
||||||
"blacklist_description": "Tracce e artisti in blacklist",
|
"blacklist_description": "Tracce e artisti in blacklist",
|
||||||
"wait_for_download_to_finish": "Prego attendere che lo scaricamento corrente finisca",
|
"wait_for_download_to_finish": "Prego attendere che il download corrente finisca",
|
||||||
"desktop": "Desktop",
|
"desktop": "Desktop",
|
||||||
"close_behavior": "Comportamento Chiusura",
|
"close_behavior": "Comportamento Chiusura",
|
||||||
"close": "Chiudi",
|
"close": "Chiudi",
|
||||||
"minimize_to_tray": "Minimizza in tray",
|
"minimize_to_tray": "Minimizza in tray",
|
||||||
"show_tray_icon": "Mostra icona in tray di sistema",
|
"show_tray_icon": "Mostra icona in tray di sistema",
|
||||||
"about": "A proposito di",
|
"about": "Informazioni su",
|
||||||
"u_love_spotube": "Sappiamo che ami Spotube",
|
"u_love_spotube": "Sappiamo che ami Spotube",
|
||||||
"check_for_updates": "Controlla aggiornamenti",
|
"check_for_updates": "Controlla aggiornamenti",
|
||||||
"about_spotube": "A proposito di Spotube",
|
"about_spotube": "Informazioni su Spotube",
|
||||||
"blacklist": "Blacklist",
|
"blacklist": "Blacklist",
|
||||||
"please_sponsor": "Per favore sponsorizza/dona",
|
"please_sponsor": "Per favore sponsorizza/dona",
|
||||||
"spotube_description": "Spotube, un client spotify gratis per tutti, multipiattaforma e leggero",
|
"spotube_description": "Spotube, un client spotify gratis per tutti, multipiattaforma e leggero",
|
||||||
@ -187,7 +187,7 @@
|
|||||||
"generate_playlist": "Genera Playlist",
|
"generate_playlist": "Genera Playlist",
|
||||||
"track_exists": "La traccia {track} esiste già",
|
"track_exists": "La traccia {track} esiste già",
|
||||||
"replace_downloaded_tracks": "Sostituisci tutte le tracce scaricate",
|
"replace_downloaded_tracks": "Sostituisci tutte le tracce scaricate",
|
||||||
"skip_download_tracks": "Salta lo scaricamento di tutte le tracce scaricate",
|
"skip_download_tracks": "Salta il download di tutte le tracce scaricate",
|
||||||
"do_you_want_to_replace": "Vuoi sovrascrivere la traccia esistente??",
|
"do_you_want_to_replace": "Vuoi sovrascrivere la traccia esistente??",
|
||||||
"replace": "Sovrascrivi",
|
"replace": "Sovrascrivi",
|
||||||
"skip": "Salta",
|
"skip": "Salta",
|
||||||
@ -256,7 +256,7 @@
|
|||||||
"querying_info": "Richiesta informazioni...",
|
"querying_info": "Richiesta informazioni...",
|
||||||
"piped_api_down": "Le Piped API non funzionano",
|
"piped_api_down": "Le Piped API non funzionano",
|
||||||
"piped_down_error_instructions": "L'istanza di Piped {pipedInstance} è correntemente offline\n\nCambia istanza o cambia 'Tipo API' alle API ufficiali YouTube\n\nAssicurati di riavviare l'app dopo il cambio",
|
"piped_down_error_instructions": "L'istanza di Piped {pipedInstance} è correntemente offline\n\nCambia istanza o cambia 'Tipo API' alle API ufficiali YouTube\n\nAssicurati di riavviare l'app dopo il cambio",
|
||||||
"you_are_offline": "Sei correntemente offline",
|
"you_are_offline": "Al momento sei offline",
|
||||||
"connection_restored": "Connessione ad internet ripristinata",
|
"connection_restored": "Connessione ad internet ripristinata",
|
||||||
"use_system_title_bar": "Usa la barra del titolo di sistema",
|
"use_system_title_bar": "Usa la barra del titolo di sistema",
|
||||||
"crunching_results": "Elaborazione risultati...",
|
"crunching_results": "Elaborazione risultati...",
|
||||||
@ -267,15 +267,15 @@
|
|||||||
"change_cover": "Cambia copertina",
|
"change_cover": "Cambia copertina",
|
||||||
"add_cover": "Aggiungi copertina",
|
"add_cover": "Aggiungi copertina",
|
||||||
"restore_defaults": "Ripristina default",
|
"restore_defaults": "Ripristina default",
|
||||||
"download_music_codec": "Codec musicale scaricamento",
|
"download_music_codec": "Codec download musica",
|
||||||
"streaming_music_codec": "Codec musicale streaming",
|
"streaming_music_codec": "Codec streaming musica",
|
||||||
"login_with_lastfm": "Accesso a Last.fm",
|
"login_with_lastfm": "Accedi con Last.fm",
|
||||||
"connect": "Connetti",
|
"connect": "Connettiti",
|
||||||
"disconnect_lastfm": "Disconnetti Last.fm",
|
"disconnect_lastfm": "Disconnettiti da Last.fm",
|
||||||
"disconnect": "Disconnetti",
|
"disconnect": "Disconnetti",
|
||||||
"username": "Nome utente",
|
"username": "Nome utente",
|
||||||
"password": "Password",
|
"password": "Password",
|
||||||
"login": "Accesso",
|
"login": "Accedi",
|
||||||
"login_with_your_lastfm": "Accedi con il tuo account Last.fm",
|
"login_with_your_lastfm": "Accedi con il tuo account Last.fm",
|
||||||
"scrobble_to_lastfm": "Invia a Last.fm",
|
"scrobble_to_lastfm": "Invia a Last.fm",
|
||||||
"audio_source": "Fonte audio",
|
"audio_source": "Fonte audio",
|
||||||
@ -299,7 +299,7 @@
|
|||||||
"song_link": "Link della Canzone",
|
"song_link": "Link della Canzone",
|
||||||
"skip_this_nonsense": "Salta questa sciocchezza",
|
"skip_this_nonsense": "Salta questa sciocchezza",
|
||||||
"freedom_of_music": "“Libertà della Musica”",
|
"freedom_of_music": "“Libertà della Musica”",
|
||||||
"freedom_of_music_palm": "“Libertà della Musica nel palmo della tua mano”",
|
"freedom_of_music_palm": "“Libertà della Musica nelle tue mani”",
|
||||||
"get_started": "Cominciamo",
|
"get_started": "Cominciamo",
|
||||||
"youtube_source_description": "Consigliato e funziona meglio.",
|
"youtube_source_description": "Consigliato e funziona meglio.",
|
||||||
"piped_source_description": "Ti senti libero? Come YouTube ma molto più gratuito.",
|
"piped_source_description": "Ti senti libero? Come YouTube ma molto più gratuito.",
|
||||||
|
@ -21,7 +21,6 @@ import 'package:spotube/extensions/constrains.dart';
|
|||||||
import 'package:spotube/extensions/context.dart';
|
import 'package:spotube/extensions/context.dart';
|
||||||
import 'package:spotube/modules/root/spotube_navigation_bar.dart';
|
import 'package:spotube/modules/root/spotube_navigation_bar.dart';
|
||||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/provider/metadata_plugin/core/auth.dart';
|
|
||||||
import 'package:spotube/provider/server/active_track_sources.dart';
|
import 'package:spotube/provider/server/active_track_sources.dart';
|
||||||
import 'package:spotube/provider/volume_provider.dart';
|
import 'package:spotube/provider/volume_provider.dart';
|
||||||
import 'package:spotube/services/sourced_track/sources/youtube.dart';
|
import 'package:spotube/services/sourced_track/sources/youtube.dart';
|
||||||
@ -40,7 +39,6 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, ref) {
|
Widget build(BuildContext context, ref) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final authenticated = ref.watch(metadataPluginAuthenticatedProvider);
|
|
||||||
final sourcedCurrentTrack = ref.watch(activeTrackSourcesProvider);
|
final sourcedCurrentTrack = ref.watch(activeTrackSourcesProvider);
|
||||||
final currentActiveTrack =
|
final currentActiveTrack =
|
||||||
ref.watch(audioPlayerProvider.select((s) => s.activeTrack));
|
ref.watch(audioPlayerProvider.select((s) => s.activeTrack));
|
||||||
@ -105,13 +103,15 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
surfaceBlur: 0,
|
surfaceBlur: 0,
|
||||||
leading: [
|
leading: [
|
||||||
IconButton.ghost(
|
IconButton.ghost(
|
||||||
icon: const Icon(SpotubeIcons.angleDown, size: 18),
|
size: const ButtonSize(1.2),
|
||||||
|
icon: const Icon(SpotubeIcons.angleDown),
|
||||||
onPressed: panelController.close,
|
onPressed: panelController.close,
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
trailing: [
|
trailing: [
|
||||||
if (currentActiveTrackSource is YoutubeSourcedTrack)
|
if (currentActiveTrackSource is YoutubeSourcedTrack)
|
||||||
TextButton(
|
TextButton(
|
||||||
|
size: const ButtonSize(1.2),
|
||||||
leading: Assets.images.logos.songlinkTransparent.image(
|
leading: Assets.images.logos.songlinkTransparent.image(
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
@ -131,7 +131,8 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
child: Text(context.l10n.details),
|
child: Text(context.l10n.details),
|
||||||
).call,
|
).call,
|
||||||
child: IconButton.ghost(
|
child: IconButton.ghost(
|
||||||
icon: const Icon(SpotubeIcons.info, size: 18),
|
size: const ButtonSize(1.2),
|
||||||
|
icon: const Icon(SpotubeIcons.info),
|
||||||
onPressed: currentActiveTrackSource == null
|
onPressed: currentActiveTrackSource == null
|
||||||
? null
|
? null
|
||||||
: () {
|
: () {
|
||||||
@ -239,9 +240,7 @@ class PlayerView extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (authenticated.asData?.value == true)
|
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
if (authenticated.asData?.value == true)
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: OutlineButton(
|
child: OutlineButton(
|
||||||
leading: const Icon(SpotubeIcons.music),
|
leading: const Icon(SpotubeIcons.music),
|
||||||
|
@ -3,7 +3,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:media_kit/media_kit.dart';
|
import 'package:media_kit/media_kit.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:shadcn_flutter/shadcn_flutter.dart' hide Consumer;
|
import 'package:shadcn_flutter/shadcn_flutter.dart';
|
||||||
|
|
||||||
import 'package:spotube/collections/spotube_icons.dart';
|
import 'package:spotube/collections/spotube_icons.dart';
|
||||||
import 'package:spotube/collections/intents.dart';
|
import 'package:spotube/collections/intents.dart';
|
||||||
@ -14,6 +14,7 @@ import 'package:spotube/modules/player/use_progress.dart';
|
|||||||
import 'package:spotube/provider/audio_player/audio_player.dart';
|
import 'package:spotube/provider/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/provider/audio_player/querying_track_info.dart';
|
import 'package:spotube/provider/audio_player/querying_track_info.dart';
|
||||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||||
|
import 'package:spotube/utils/platform.dart';
|
||||||
|
|
||||||
class PlayerControls extends HookConsumerWidget {
|
class PlayerControls extends HookConsumerWidget {
|
||||||
final PaletteGenerator? palette;
|
final PaletteGenerator? palette;
|
||||||
@ -48,6 +49,9 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
useStream(audioPlayer.playingStream).data ?? audioPlayer.isPlaying;
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
|
final buttonSize =
|
||||||
|
kIsMobile ? const ButtonSize(1.5) : const ButtonSize(1.2);
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
behavior: HitTestBehavior.translucent,
|
behavior: HitTestBehavior.translucent,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@ -149,9 +153,11 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
).call,
|
).call,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
|
size: buttonSize,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
SpotubeIcons.shuffle,
|
SpotubeIcons.shuffle,
|
||||||
color: shuffled ? theme.colorScheme.primary : null,
|
color: shuffled ? theme.colorScheme.primary : null,
|
||||||
|
size: 22,
|
||||||
),
|
),
|
||||||
variance: shuffled
|
variance: shuffled
|
||||||
? ButtonVariance.secondary
|
? ButtonVariance.secondary
|
||||||
@ -170,8 +176,10 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
}),
|
}),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
tooltip: TooltipContainer(
|
tooltip: TooltipContainer(
|
||||||
child: Text(context.l10n.previous_track)).call,
|
child: Text(context.l10n.previous_track),
|
||||||
|
).call,
|
||||||
child: IconButton.ghost(
|
child: IconButton.ghost(
|
||||||
|
size: buttonSize,
|
||||||
enabled: !isFetchingActiveTrack,
|
enabled: !isFetchingActiveTrack,
|
||||||
icon: const Icon(SpotubeIcons.skipBack),
|
icon: const Icon(SpotubeIcons.skipBack),
|
||||||
onPressed: audioPlayer.skipToPrevious,
|
onPressed: audioPlayer.skipToPrevious,
|
||||||
@ -186,6 +194,7 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
).call,
|
).call,
|
||||||
child: IconButton.primary(
|
child: IconButton.primary(
|
||||||
|
size: buttonSize,
|
||||||
shape: ButtonShape.circle,
|
shape: ButtonShape.circle,
|
||||||
icon: isFetchingActiveTrack
|
icon: isFetchingActiveTrack
|
||||||
? const SizedBox(
|
? const SizedBox(
|
||||||
@ -206,8 +215,10 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
Tooltip(
|
Tooltip(
|
||||||
tooltip:
|
tooltip:
|
||||||
TooltipContainer(child: Text(context.l10n.next_track)).call,
|
TooltipContainer(child: Text(context.l10n.next_track))
|
||||||
|
.call,
|
||||||
child: IconButton.ghost(
|
child: IconButton.ghost(
|
||||||
|
size: buttonSize,
|
||||||
icon: const Icon(SpotubeIcons.skipForward),
|
icon: const Icon(SpotubeIcons.skipForward),
|
||||||
onPressed:
|
onPressed:
|
||||||
isFetchingActiveTrack ? null : audioPlayer.skipToNext,
|
isFetchingActiveTrack ? null : audioPlayer.skipToNext,
|
||||||
@ -228,6 +239,7 @@ class PlayerControls extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
).call,
|
).call,
|
||||||
child: IconButton(
|
child: IconButton(
|
||||||
|
size: buttonSize,
|
||||||
icon: Icon(
|
icon: Icon(
|
||||||
loopMode == PlaylistMode.single
|
loopMode == PlaylistMode.single
|
||||||
? SpotubeIcons.repeatOne
|
? SpotubeIcons.repeatOne
|
||||||
|
@ -47,10 +47,8 @@ class PlayerTrackDetails extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
LinkText(
|
Text(
|
||||||
playback.activeTrack?.name ?? "",
|
playback.activeTrack?.name ?? "",
|
||||||
TrackRoute(trackId: playback.activeTrack?.id ?? ""),
|
|
||||||
push: true,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: theme.typography.normal.copyWith(
|
style: theme.typography.normal.copyWith(
|
||||||
color: color,
|
color: color,
|
||||||
|
@ -18,8 +18,6 @@ import 'package:spotube/provider/lyrics/synced.dart';
|
|||||||
import 'package:spotube/services/audio_player/audio_player.dart';
|
import 'package:spotube/services/audio_player/audio_player.dart';
|
||||||
import 'package:spotube/services/logger/logger.dart';
|
import 'package:spotube/services/logger/logger.dart';
|
||||||
|
|
||||||
import 'package:stroke_text/stroke_text.dart';
|
|
||||||
|
|
||||||
class SyncedLyrics extends HookConsumerWidget {
|
class SyncedLyrics extends HookConsumerWidget {
|
||||||
final PaletteColor palette;
|
final PaletteColor palette;
|
||||||
final bool? isModal;
|
final bool? isModal;
|
||||||
@ -160,6 +158,9 @@ class SyncedLyrics extends HookConsumerWidget {
|
|||||||
child: AnimatedDefaultTextStyle(
|
child: AnimatedDefaultTextStyle(
|
||||||
duration: const Duration(milliseconds: 250),
|
duration: const Duration(milliseconds: 250),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
|
color: isActive
|
||||||
|
? theme.colorScheme.foreground
|
||||||
|
: theme.colorScheme.mutedForeground,
|
||||||
fontWeight: isActive
|
fontWeight: isActive
|
||||||
? FontWeight.w500
|
? FontWeight.w500
|
||||||
: FontWeight.normal,
|
: FontWeight.normal,
|
||||||
@ -181,25 +182,7 @@ class SyncedLyrics extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
audioPlayer.seek(time);
|
audioPlayer.seek(time);
|
||||||
},
|
},
|
||||||
child: Builder(builder: (context) {
|
child: Text(lyricSlice.text),
|
||||||
return StrokeText(
|
|
||||||
text: lyricSlice.text,
|
|
||||||
textStyle:
|
|
||||||
DefaultTextStyle.of(context).style,
|
|
||||||
textColor: switch ((
|
|
||||||
isActive,
|
|
||||||
isModal == true
|
|
||||||
)) {
|
|
||||||
(true, _) => Colors.white,
|
|
||||||
(_, true) =>
|
|
||||||
theme.colorScheme.mutedForeground,
|
|
||||||
(_, _) => palette.bodyTextColor,
|
|
||||||
},
|
|
||||||
strokeColor: isActive
|
|
||||||
? Colors.black
|
|
||||||
: Colors.transparent,
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -28,9 +28,7 @@ class PlayerLyricsPage extends HookConsumerWidget {
|
|||||||
final selectedIndex = useState(0);
|
final selectedIndex = useState(0);
|
||||||
final palette = usePaletteColor(albumArt, ref);
|
final palette = usePaletteColor(albumArt, ref);
|
||||||
|
|
||||||
final tabbar = Padding(
|
final tabbar = TabList(
|
||||||
padding: const EdgeInsets.all(10),
|
|
||||||
child: TabList(
|
|
||||||
index: selectedIndex.value,
|
index: selectedIndex.value,
|
||||||
onChanged: (index) => selectedIndex.value = index,
|
onChanged: (index) => selectedIndex.value = index,
|
||||||
children: [
|
children: [
|
||||||
@ -41,7 +39,7 @@ class PlayerLyricsPage extends HookConsumerWidget {
|
|||||||
child: Text(context.l10n.plain),
|
child: Text(context.l10n.plain),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
));
|
);
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
headers: [
|
headers: [
|
||||||
|
@ -3,7 +3,7 @@ description: Open source extensible music streaming platform and app, based on B
|
|||||||
|
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
|
|
||||||
version: 4.0.2+41
|
version: 5.0.0+42
|
||||||
|
|
||||||
homepage: https://spotube.krtirtho.dev
|
homepage: https://spotube.krtirtho.dev
|
||||||
repository: https://github.com/KRTirtho/spotube
|
repository: https://github.com/KRTirtho/spotube
|
||||||
|
Loading…
Reference in New Issue
Block a user