🐛 Fix update app color fail sometimes

This commit is contained in:
2025-12-16 23:54:33 +08:00
parent c0a495484c
commit bdc277a2e3
3 changed files with 25 additions and 38 deletions

View File

@@ -1,8 +1,9 @@
import 'package:audio_service/audio_service.dart'; import 'package:audio_service/audio_service.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:media_kit/media_kit.dart' as media_kit; import 'package:media_kit/media_kit.dart' as media_kit;
import 'package:groovybox/data/db.dart'; import 'package:groovybox/data/db.dart';
import 'package:groovybox/providers/theme_provider.dart'; import 'package:groovybox/providers/theme_provider.dart';
import 'package:groovybox/logic/metadata_service.dart';
class AudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler { class AudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler {
final media_kit.Player _player; final media_kit.Player _player;
@@ -46,23 +47,18 @@ class AudioHandler extends BaseAudioHandler with QueueHandler, SeekHandler {
} }
// Update theme color based on current track's album art // Update theme color based on current track's album art
void _updateThemeFromCurrentTrack(MediaItem mediaItem) { void _updateThemeFromCurrentTrack(MediaItem mediaItem) async {
if (_container == null) return; if (_container == null) return;
final artUri = mediaItem.artUri; try {
if (artUri != null && // Get metadata for the current track to access artBytes
artUri.scheme == 'file' && final metadataService = _container!.read(metadataServiceProvider);
artUri.path.isNotEmpty && final metadata = await metadataService.getMetadata(mediaItem.id);
!artUri.path.contains('..') && // Prevent directory traversal
(artUri.path.endsWith('.jpg') ||
artUri.path.endsWith('.jpeg') ||
artUri.path.endsWith('.png') ||
artUri.path.endsWith('.bmp') ||
artUri.path.endsWith('.webp'))) {
final seedColorNotifier = _container!.read(seedColorProvider.notifier); final seedColorNotifier = _container!.read(seedColorProvider.notifier);
seedColorNotifier.updateFromAlbumArt(artUri.path); seedColorNotifier.updateFromAlbumArtBytes(metadata.artBytes);
} else { } catch (e) {
// Reset to default color if no valid album art // If metadata retrieval fails, reset to default color
final seedColorNotifier = _container!.read(seedColorProvider.notifier); final seedColorNotifier = _container!.read(seedColorProvider.notifier);
seedColorNotifier.resetToDefault(); seedColorNotifier.resetToDefault();
} }

View File

@@ -1,7 +1,6 @@
import 'dart:io'; import 'dart:io';
import 'dart:typed_data'; import 'dart:typed_data';
import 'package:flutter_media_metadata/flutter_media_metadata.dart'; import 'package:flutter_media_metadata/flutter_media_metadata.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:riverpod_annotation/riverpod_annotation.dart'; import 'package:riverpod_annotation/riverpod_annotation.dart';
part 'metadata_service.g.dart'; part 'metadata_service.g.dart';

View File

@@ -1,4 +1,4 @@
import 'dart:io'; import 'dart:typed_data';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:palette_generator/palette_generator.dart'; import 'package:palette_generator/palette_generator.dart';
@@ -94,32 +94,16 @@ class SeedColorNotifier extends _$SeedColorNotifier {
state = color; state = color;
} }
void updateFromAlbumArt(String? imagePath) async { void updateFromAlbumArtBytes(Uint8List? artBytes) async {
if (imagePath == null || imagePath.isEmpty) { if (artBytes == null || artBytes.isEmpty) {
// Reset to default color if no album art // Reset to default color if no album art
state = defaultSeedColor; state = defaultSeedColor;
return; return;
} }
try { try {
// Validate that the file exists before attempting to load it
final file = File(imagePath);
if (!await file.exists()) {
// File doesn't exist, reset to default color
state = defaultSeedColor;
return;
}
// Additional validation: check if file is readable and not empty
final fileStat = await file.stat();
if (fileStat.size == 0) {
// Empty file, reset to default color
state = defaultSeedColor;
return;
}
final paletteGenerator = await PaletteGenerator.fromImageProvider( final paletteGenerator = await PaletteGenerator.fromImageProvider(
FileImage(file), MemoryImage(artBytes),
size: const Size(200, 200), size: const Size(200, 200),
maximumColorCount: 20, // Increase color count for better extraction maximumColorCount: 20, // Increase color count for better extraction
); );
@@ -140,13 +124,21 @@ class SeedColorNotifier extends _$SeedColorNotifier {
// Ensure we have a valid color, otherwise use default // Ensure we have a valid color, otherwise use default
state = extractedColor ?? defaultSeedColor; state = extractedColor ?? defaultSeedColor;
} catch (e) { } catch (e) {
// Log the error for debugging (in a real app, you'd use proper logging)
// debugPrint('Failed to extract color from album art: $e');
// If color extraction fails, reset to default color // If color extraction fails, reset to default color
state = defaultSeedColor; state = defaultSeedColor;
} }
} }
// Keep the old method for backward compatibility, but mark as deprecated
@Deprecated(
'Use updateFromAlbumArtBytes instead. File path based color extraction is unreliable.',
)
void updateFromAlbumArt(String? imagePath) async {
// This method is deprecated, but kept for compatibility
// It will always reset to default since we now use artBytes
state = defaultSeedColor;
}
void resetToDefault() { void resetToDefault() {
state = defaultSeedColor; state = defaultSeedColor;
} }