mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-08-23 19:32:29 +02:00
fix: service selection priority and Amazon fallback-only
- Fix service selection ignored: user's preferred service now takes priority - Add preferredService parameter to downloadWithExtensions - Gray out Amazon in service picker (fallback only) - Clean up unused code in Go backend
This commit is contained in:
@@ -43,7 +43,6 @@ class _EagerInitializationState extends ConsumerState<_EagerInitialization> {
|
||||
void initState() {
|
||||
super.initState();
|
||||
_initializeExtensions();
|
||||
// Trigger history provider initialization without subscribing to updates.
|
||||
ref.read(downloadHistoryProvider);
|
||||
}
|
||||
|
||||
|
||||
@@ -1878,7 +1878,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
'Quality: $quality${item.qualityOverride != null ? ' (override)' : ''}',
|
||||
);
|
||||
_log.d('Output dir: $outputDir');
|
||||
result = await PlatformBridge.downloadWithExtensions(
|
||||
result = await PlatformBridge.downloadWithExtensions(
|
||||
isrc: trackToDownload.isrc ?? '',
|
||||
spotifyId: trackToDownload.id,
|
||||
trackName: trackToDownload.name,
|
||||
@@ -1898,6 +1898,7 @@ class DownloadQueueNotifier extends Notifier<DownloadQueueState> {
|
||||
genre: genre,
|
||||
label: label,
|
||||
lyricsMode: settings.lyricsMode,
|
||||
preferredService: item.service,
|
||||
);
|
||||
} else if (state.autoFallback) {
|
||||
_log.d('Using auto-fallback mode');
|
||||
|
||||
@@ -323,7 +323,6 @@ class PlatformBridge {
|
||||
});
|
||||
}
|
||||
|
||||
/// Returns true if credentials are available (custom or env vars)
|
||||
static Future<bool> hasSpotifyCredentials() async {
|
||||
final result = await _channel.invokeMethod('hasSpotifyCredentials');
|
||||
return result as bool;
|
||||
@@ -410,7 +409,6 @@ class PlatformBridge {
|
||||
return logs.map((e) => e as Map<String, dynamic>).toList();
|
||||
}
|
||||
|
||||
/// Get logs since a specific index (for incremental updates)
|
||||
static Future<Map<String, dynamic>> getGoLogsSince(int index) async {
|
||||
final result = await _channel.invokeMethod('getLogsSince', {'index': index});
|
||||
return jsonDecode(result as String) as Map<String, dynamic>;
|
||||
@@ -561,7 +559,7 @@ class PlatformBridge {
|
||||
return list.map((e) => e as Map<String, dynamic>).toList();
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>> downloadWithExtensions({
|
||||
static Future<Map<String, dynamic>> downloadWithExtensions({
|
||||
required String isrc,
|
||||
required String spotifyId,
|
||||
required String trackName,
|
||||
@@ -584,8 +582,9 @@ class PlatformBridge {
|
||||
String? genre,
|
||||
String? label,
|
||||
String lyricsMode = 'embed',
|
||||
String? preferredService,
|
||||
}) async {
|
||||
_log.i('downloadWithExtensions: "$trackName" by $artistName${source != null ? ' (source: $source)' : ''}');
|
||||
_log.i('downloadWithExtensions: "$trackName" by $artistName${source != null ? ' (source: $source)' : ''}${preferredService != null ? ' (service: $preferredService)' : ''}');
|
||||
final request = jsonEncode({
|
||||
'isrc': isrc,
|
||||
'spotify_id': spotifyId,
|
||||
@@ -609,6 +608,7 @@ class PlatformBridge {
|
||||
'genre': genre ?? '',
|
||||
'label': label ?? '',
|
||||
'lyrics_mode': lyricsMode,
|
||||
'service': preferredService ?? '',
|
||||
});
|
||||
|
||||
final result = await _channel.invokeMethod('downloadWithExtensions', request);
|
||||
@@ -795,7 +795,6 @@ class PlatformBridge {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get extension home feed
|
||||
static Future<Map<String, dynamic>?> getExtensionHomeFeed(String extensionId) async {
|
||||
try {
|
||||
final result = await _channel.invokeMethod('getExtensionHomeFeed', {
|
||||
@@ -809,7 +808,6 @@ class PlatformBridge {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get extension browse categories
|
||||
static Future<Map<String, dynamic>?> getExtensionBrowseCategories(String extensionId) async {
|
||||
try {
|
||||
final result = await _channel.invokeMethod('getExtensionBrowseCategories', {
|
||||
|
||||
@@ -10,11 +10,15 @@ class BuiltInService {
|
||||
final String id;
|
||||
final String label;
|
||||
final List<QualityOption> qualityOptions;
|
||||
final bool isDisabled; // If true, service is grayed out (fallback only)
|
||||
final String? disabledReason;
|
||||
|
||||
const BuiltInService({
|
||||
required this.id,
|
||||
required this.label,
|
||||
required this.qualityOptions,
|
||||
this.isDisabled = false,
|
||||
this.disabledReason,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -47,6 +51,8 @@ const _builtInServices = [
|
||||
QualityOption(id: 'HI_RES', label: 'Hi-Res FLAC', description: '24-bit / up to 96kHz'),
|
||||
QualityOption(id: 'HI_RES_LOSSLESS', label: 'Hi-Res FLAC Max', description: '24-bit / up to 192kHz'),
|
||||
],
|
||||
isDisabled: true,
|
||||
disabledReason: 'Fallback only',
|
||||
),
|
||||
];
|
||||
|
||||
@@ -169,7 +175,7 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Wrap(
|
||||
spacing: 8,
|
||||
@@ -177,9 +183,14 @@ class _DownloadServicePickerState extends ConsumerState<DownloadServicePicker> {
|
||||
children: [
|
||||
for (final service in _builtInServices)
|
||||
_ServiceChip(
|
||||
label: service.label,
|
||||
label: service.isDisabled
|
||||
? '${service.label} (${service.disabledReason})'
|
||||
: service.label,
|
||||
isSelected: _selectedService == service.id,
|
||||
onTap: () => setState(() => _selectedService = service.id),
|
||||
isDisabled: service.isDisabled,
|
||||
onTap: service.isDisabled
|
||||
? null
|
||||
: () => setState(() => _selectedService = service.id),
|
||||
),
|
||||
for (final ext in downloadExtensions)
|
||||
_ServiceChip(
|
||||
@@ -392,26 +403,32 @@ class _QualityOption extends StatelessWidget {
|
||||
class _ServiceChip extends StatelessWidget {
|
||||
final String label;
|
||||
final bool isSelected;
|
||||
final VoidCallback onTap;
|
||||
final VoidCallback? onTap;
|
||||
final String? iconPath;
|
||||
final bool isDisabled;
|
||||
|
||||
const _ServiceChip({
|
||||
required this.label,
|
||||
required this.isSelected,
|
||||
required this.onTap,
|
||||
this.iconPath,
|
||||
this.isDisabled = false,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final colorScheme = Theme.of(context).colorScheme;
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
onTap: isDisabled ? null : onTap,
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 200),
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? colorScheme.primaryContainer : colorScheme.surfaceContainerHighest,
|
||||
color: isDisabled
|
||||
? colorScheme.surfaceContainerHighest.withValues(alpha: 0.5)
|
||||
: isSelected
|
||||
? colorScheme.primaryContainer
|
||||
: colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: isSelected ? null : Border.all(color: colorScheme.outlineVariant.withValues(alpha: 0.5)),
|
||||
),
|
||||
@@ -429,7 +446,11 @@ class _ServiceChip extends StatelessWidget {
|
||||
errorBuilder: (context, error, stackTrace) => Icon(
|
||||
Icons.extension,
|
||||
size: 18,
|
||||
color: isSelected ? colorScheme.onPrimaryContainer : colorScheme.onSurfaceVariant,
|
||||
color: isDisabled
|
||||
? colorScheme.onSurfaceVariant.withValues(alpha: 0.4)
|
||||
: isSelected
|
||||
? colorScheme.onPrimaryContainer
|
||||
: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -439,7 +460,11 @@ class _ServiceChip extends StatelessWidget {
|
||||
label,
|
||||
style: TextStyle(
|
||||
fontWeight: isSelected ? FontWeight.w600 : FontWeight.normal,
|
||||
color: isSelected ? colorScheme.onPrimaryContainer : colorScheme.onSurfaceVariant,
|
||||
color: isDisabled
|
||||
? colorScheme.onSurfaceVariant.withValues(alpha: 0.4)
|
||||
: isSelected
|
||||
? colorScheme.onPrimaryContainer
|
||||
: colorScheme.onSurfaceVariant,
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user