refactor: remove more redundant comments

This commit is contained in:
zarzet
2026-02-04 10:20:04 +07:00
parent 24897e25e2
commit e20becdca7
16 changed files with 44 additions and 315 deletions
@@ -1019,10 +1019,6 @@ void removeItem(String id) {
_saveQueueToStorage();
}
/// Export failed downloads to a TXT file
/// Returns the file path if successful, null otherwise
/// Uses daily files: same day = append to existing file, new day = new file
/// Saves to 'failed_downloads' subfolder to keep organized
Future<String?> exportFailedDownloads() async {
final failedItems = state.items
.where((item) => item.status == DownloadStatus.failed)
@@ -1091,7 +1087,6 @@ void removeItem(String id) {
}
}
/// Clear all failed downloads from queue
void clearFailedDownloads() {
final items = state.items
.where((item) => item.status != DownloadStatus.failed)
-16
View File
@@ -41,25 +41,20 @@ class LocalLibraryState {
.map((item) => MapEntry(item.isrc!, item)),
);
/// Check if ISRC exists in library
bool hasIsrc(String isrc) => _isrcSet.contains(isrc);
/// Check if track exists by name and artist
bool hasTrack(String trackName, String artistName) {
final key = '${trackName.toLowerCase()}|${artistName.toLowerCase()}';
return _trackKeySet.contains(key);
}
/// Find library item by ISRC
LocalLibraryItem? getByIsrc(String isrc) => _byIsrc[isrc];
/// Find library item by track name and artist
LocalLibraryItem? findByTrackAndArtist(String trackName, String artistName) {
final key = '${trackName.toLowerCase()}|${artistName.toLowerCase()}';
return items.where((item) => item.matchKey == key).firstOrNull;
}
/// Check if a track exists in library (by ISRC or name matching)
bool existsInLibrary({String? isrc, String? trackName, String? artistName}) {
if (isrc != null && isrc.isNotEmpty && hasIsrc(isrc)) {
return true;
@@ -136,13 +131,11 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
}
}
/// Reload library from database
Future<void> reloadFromStorage() async {
_isLoaded = false;
await _loadFromDatabase();
}
/// Start scanning a folder for audio files
Future<void> startScan(String folderPath) async {
if (state.isScanning) {
_log.w('Scan already in progress');
@@ -230,7 +223,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
_progressTimer = null;
}
/// Cancel ongoing scan
Future<void> cancelScan() async {
if (!state.isScanning) return;
@@ -240,7 +232,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
_stopProgressPolling();
}
/// Clean up missing files from library
Future<int> cleanupMissingFiles() async {
final removed = await _db.cleanupMissingFiles();
if (removed > 0) {
@@ -249,7 +240,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
return removed;
}
/// Clear all library data
Future<void> clearLibrary() async {
await _db.clearAll();
@@ -264,7 +254,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
_log.i('Library cleared');
}
/// Remove a single item from library by ID
Future<void> removeItem(String id) async {
await _db.delete(id);
state = state.copyWith(
@@ -272,7 +261,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
);
}
/// Check if a track exists in library
bool existsInLibrary({String? isrc, String? trackName, String? artistName}) {
return state.existsInLibrary(
isrc: isrc,
@@ -281,12 +269,10 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
);
}
/// Get library item by ISRC
LocalLibraryItem? getByIsrc(String isrc) {
return state.getByIsrc(isrc);
}
/// Find library item for a track
LocalLibraryItem? findExisting({String? isrc, String? trackName, String? artistName}) {
if (isrc != null && isrc.isNotEmpty) {
final byIsrc = state.getByIsrc(isrc);
@@ -298,7 +284,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
return null;
}
/// Search library
Future<List<LocalLibraryItem>> search(String query) async {
if (query.isEmpty) return [];
@@ -306,7 +291,6 @@ class LocalLibraryNotifier extends Notifier<LocalLibraryState> {
return results.map((e) => LocalLibraryItem.fromJson(e)).toList();
}
/// Get library count
Future<int> getCount() async {
return await _db.getCount();
}
+10 -20
View File
@@ -45,10 +45,10 @@ class AlbumScreen extends ConsumerStatefulWidget {
final String albumId;
final String albumName;
final String? coverUrl;
final List<Track>? tracks; // Optional - will fetch if null
final String? extensionId; // If from extension
final String? artistId; // Artist ID for navigation
final String? artistName; // Artist name for navigation
final List<Track>? tracks;
final String? extensionId;
final String? artistId;
final String? artistName;
const AlbumScreen({
super.key,
@@ -93,13 +93,12 @@ class _AlbumScreenState extends ConsumerState<AlbumScreen> {
);
});
// Use provided tracks if not empty, otherwise try cache
if (widget.tracks != null && widget.tracks!.isNotEmpty) {
_tracks = widget.tracks;
} else {
_tracks = _AlbumCache.get(widget.albumId);
}
_artistId = widget.artistId; // Use provided artist ID if available
_artistId = widget.artistId;
if (_tracks == null || _tracks!.isEmpty) {
_fetchTracks();
@@ -122,7 +121,7 @@ class _AlbumScreenState extends ConsumerState<AlbumScreen> {
}
}
Future<void> _extractDominantColor() async {
Future<void> _extractDominantColor() async {
if (widget.coverUrl == null) return;
final color = await PaletteService.instance.extractDominantColor(widget.coverUrl);
if (mounted && color != null) {
@@ -131,21 +130,18 @@ Future<void> _extractDominantColor() async {
}
String _formatReleaseDate(String date) {
// Handle formats: "2024-01-15", "2024-01", "2024"
if (date.length >= 10) {
// Full date: 2024-01-15
final parts = date.substring(0, 10).split('-');
if (parts.length == 3) {
return '${parts[2]}/${parts[1]}/${parts[0]}'; // DD/MM/YYYY
return '${parts[2]}/${parts[1]}/${parts[0]}';
}
} else if (date.length >= 7) {
// Month: 2024-01
final parts = date.split('-');
if (parts.length >= 2) {
return '${parts[1]}/${parts[0]}'; // MM/YYYY
return '${parts[1]}/${parts[0]}';
}
}
return date; // Year only or unknown format
return date;
}
Future<void> _fetchTracks() async {
@@ -164,7 +160,6 @@ Future<void> _fetchTracks() async {
final trackList = metadata['track_list'] as List<dynamic>;
final tracks = trackList.map((t) => _parseTrack(t as Map<String, dynamic>)).toList();
// Extract artist ID from album_info if available
final albumInfo = metadata['album_info'] as Map<String, dynamic>?;
final artistId = albumInfo?['artist_id'] as String?;
@@ -236,7 +231,7 @@ Future<void> _fetchTracks() async {
Widget _buildAppBar(BuildContext context, ColorScheme colorScheme) {
final screenWidth = MediaQuery.of(context).size.width;
final coverSize = screenWidth * 0.5; // 50% of screen width
final coverSize = screenWidth * 0.5;
final bgColor = _dominantColor ?? colorScheme.surface;
return SliverAppBar(
@@ -269,7 +264,6 @@ Future<void> _fetchTracks() async {
background: Stack(
fit: StackFit.expand,
children: [
// Background with dominant color
AnimatedContainer(
duration: const Duration(milliseconds: 500),
decoration: BoxDecoration(
@@ -501,11 +495,9 @@ ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(context.l10n.s
}
void _navigateToArtist(BuildContext context, String artistName) {
// Use stored artist ID if available, otherwise use a placeholder
final artistId = _artistId ??
(widget.albumId.startsWith('deezer:') ? 'deezer:unknown' : 'unknown');
// Don't navigate if artist ID is unknown
if (artistId == 'unknown' || artistId == 'deezer:unknown' || artistId.isEmpty) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Artist information not available')),
@@ -513,7 +505,6 @@ ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(context.l10n.s
return;
}
// If from extension, use ExtensionArtistScreen
if (widget.extensionId != null) {
Navigator.push(
context,
@@ -621,7 +612,6 @@ class _AlbumTrackItem extends ConsumerWidget {
return state.isDownloaded(track.id);
}));
// Check local library for duplicate detection
final settings = ref.watch(settingsProvider);
final showLocalLibraryIndicator = settings.localLibraryEnabled && settings.localLibraryShowDuplicates;
final isInLocalLibrary = showLocalLibraryIndicator
+1 -1
View File
@@ -74,7 +74,7 @@ class ArtistScreen extends ConsumerStatefulWidget {
final int? monthlyListeners;
final List<ArtistAlbum>? albums;
final List<Track>? topTracks;
final String? extensionId; // If set, skip fetching from Spotify/Deezer
final String? extensionId;
const ArtistScreen({
super.key,
-9
View File
@@ -50,19 +50,10 @@ class _HomeTabState extends ConsumerState<HomeTab> with AutomaticKeepAliveClient
late final ProviderSubscription<TrackState> _trackStateSub;
late final ProviderSubscription<bool> _extensionInitSub;
/// Debounce timer for live search (extension-only feature)
Timer? _liveSearchDebounce;
/// Flag to prevent concurrent live search calls (prevents race conditions in extensions)
bool _isLiveSearchInProgress = false;
/// Pending query to execute after current search completes
String? _pendingLiveSearchQuery;
/// Minimum characters required to trigger live search
static const int _minLiveSearchChars = 3;
/// Debounce duration for live search
static const Duration _liveSearchDelay = Duration(milliseconds: 800);
List<DownloadHistoryItem>? _recentAccessHistoryCache;
+1 -1
View File
@@ -17,7 +17,7 @@ class PlaylistScreen extends ConsumerStatefulWidget {
final String playlistName;
final String? coverUrl;
final List<Track> tracks;
final String? playlistId; // Deezer playlist ID for fetching tracks
final String? playlistId;
const PlaylistScreen({
super.key,
-25
View File
@@ -567,7 +567,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
});
}
/// Exit selection mode
void _exitSelectionMode() {
setState(() {
_isSelectionMode = false;
@@ -588,25 +587,20 @@ class _QueueTabState extends ConsumerState<QueueTab> {
});
}
/// Select all visible items
void _selectAll(List<UnifiedLibraryItem> items) {
setState(() {
_selectedIds.addAll(items.map((e) => e.id));
});
}
/// Get short badge text for quality display
String _getQualityBadgeText(String quality) {
// For lossless: "24-bit/96kHz" -> "24-bit"
if (quality.contains('bit')) {
return quality.split('/').first;
}
// For lossy: "OPUS 128kbps" -> "128k", "MP3 320kbps" -> "320k"
final bitrateMatch = RegExp(r'(\d+)kbps').firstMatch(quality);
if (bitrateMatch != null) {
return '${bitrateMatch.group(1)}k';
}
// Fallback: return format name
return quality.split(' ').first;
}
@@ -725,7 +719,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
});
}
/// Count of active advanced filters
int get _activeFilterCount {
int count = 0;
if (_filterSource != null) count++;
@@ -735,7 +728,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
return count;
}
/// Reset all advanced filters
void _resetFilters() {
setState(() {
_filterSource = null;
@@ -746,12 +738,10 @@ class _QueueTabState extends ConsumerState<QueueTab> {
});
}
/// Apply advanced filters to unified items
List<UnifiedLibraryItem> _applyAdvancedFilters(List<UnifiedLibraryItem> items) {
if (_activeFilterCount == 0) return items;
return items.where((item) {
// Source filter
if (_filterSource != null) {
if (_filterSource == 'downloaded' && item.source != LibraryItemSource.downloaded) {
return false;
@@ -761,7 +751,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
}
}
// Quality filter
if (_filterQuality != null && item.quality != null) {
final quality = item.quality!.toLowerCase();
switch (_filterQuality) {
@@ -770,21 +759,17 @@ class _QueueTabState extends ConsumerState<QueueTab> {
case 'cd':
if (!quality.startsWith('16')) return false;
case 'lossy':
// Lossy formats typically don't have bit depth or are labeled differently
if (quality.startsWith('24') || quality.startsWith('16')) return false;
}
} else if (_filterQuality != null && item.quality == null) {
// If quality filter is set but item has no quality info, include only for 'lossy'
if (_filterQuality != 'lossy') return false;
}
// Format filter
if (_filterFormat != null) {
final ext = item.filePath.split('.').last.toLowerCase();
if (ext != _filterFormat) return false;
}
// Date filter
if (_filterDateRange != null) {
final now = DateTime.now();
final itemDate = item.addedAt;
@@ -808,7 +793,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
}).toList(growable: false);
}
/// Get available formats from current items
Set<String> _getAvailableFormats(List<UnifiedLibraryItem> items) {
final formats = <String>{};
for (final item in items) {
@@ -820,12 +804,10 @@ class _QueueTabState extends ConsumerState<QueueTab> {
return formats;
}
/// Show filter bottom sheet
void _showFilterSheet(BuildContext context, List<UnifiedLibraryItem> allItems) {
final colorScheme = Theme.of(context).colorScheme;
final availableFormats = _getAvailableFormats(allItems);
// Temporary filter state for the sheet
String? tempSource = _filterSource;
String? tempQuality = _filterQuality;
String? tempFormat = _filterFormat;
@@ -847,7 +829,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Handle bar
Center(
child: Container(
width: 32,
@@ -860,7 +841,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
),
),
// Title row
Row(
children: [
Text(
@@ -885,7 +865,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
),
const SizedBox(height: 16),
// Source filter
Text(
context.l10n.libraryFilterSource,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
@@ -915,7 +894,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
),
const SizedBox(height: 16),
// Quality filter
Text(
context.l10n.libraryFilterQuality,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
@@ -950,7 +928,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
),
const SizedBox(height: 16),
// Format filter
Text(
context.l10n.libraryFilterFormat,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
@@ -976,7 +953,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
),
const SizedBox(height: 16),
// Date filter
Text(
context.l10n.libraryFilterDate,
style: Theme.of(context).textTheme.titleSmall?.copyWith(
@@ -1016,7 +992,6 @@ class _QueueTabState extends ConsumerState<QueueTab> {
),
const SizedBox(height: 24),
// Apply button
SizedBox(
width: double.infinity,
child: FilledButton(
-4
View File
@@ -27,7 +27,6 @@ class CoverCacheManager {
return _instance!;
}
/// Check if cache manager is initialized
static bool get isInitialized => _initialized && _instance != null;
static Future<void> initialize() async {
@@ -62,8 +61,6 @@ class CoverCacheManager {
}
}
/// Clear all cached cover images.
/// Returns the number of files deleted.
static Future<void> clearCache() async {
if (!_initialized || _instance == null) return;
await _instance!.emptyCache();
@@ -98,7 +95,6 @@ class CoverCacheManager {
}
}
/// Statistics about the cover image cache
class CacheStats {
final int fileCount;
final int totalSizeBytes;
-1
View File
@@ -154,7 +154,6 @@ class LogBuffer extends ChangeNotifier {
return buffer.toString();
}
/// Export logs with device information for debugging
Future<String> exportWithDeviceInfo() async {
final buffer = StringBuffer();