mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-05-20 15:15:33 +02:00
123 lines
3.7 KiB
Dart
123 lines
3.7 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
import 'package:path/path.dart' as p;
|
|
|
|
/// Persistent cache manager for album/track cover images.
|
|
///
|
|
/// Unlike the default cache manager which stores in temp directory
|
|
/// (can be cleared by system anytime), this stores in app support
|
|
/// directory which persists across app restarts.
|
|
class CoverCacheManager {
|
|
static const String _cacheKey = 'coverImageCache';
|
|
static const int _maxCacheObjects = 1000;
|
|
static const Duration _maxCacheAge = Duration(days: 365);
|
|
|
|
static CacheManager? _instance;
|
|
static bool _initialized = false;
|
|
static String? _cachePath;
|
|
|
|
static CacheManager get instance {
|
|
if (!_initialized || _instance == null) {
|
|
// Fallback to default cache manager if not initialized
|
|
debugPrint('CoverCacheManager: Not initialized, using DefaultCacheManager');
|
|
return DefaultCacheManager();
|
|
}
|
|
return _instance!;
|
|
}
|
|
|
|
/// Check if cache manager is initialized
|
|
static bool get isInitialized => _initialized && _instance != null;
|
|
|
|
static Future<void> initialize() async {
|
|
if (_initialized) return;
|
|
|
|
try {
|
|
final appDir = await getApplicationSupportDirectory();
|
|
_cachePath = p.join(appDir.path, 'cover_cache');
|
|
|
|
// Ensure cache directory exists
|
|
await Directory(_cachePath!).create(recursive: true);
|
|
|
|
debugPrint('CoverCacheManager: Initializing at $_cachePath');
|
|
|
|
_instance = CacheManager(
|
|
Config(
|
|
_cacheKey,
|
|
stalePeriod: _maxCacheAge,
|
|
maxNrOfCacheObjects: _maxCacheObjects,
|
|
// Use path only (not databaseName) to store database in persistent directory
|
|
repo: JsonCacheInfoRepository(path: _cachePath),
|
|
fileSystem: IOFileSystem(_cachePath!),
|
|
fileService: HttpFileService(),
|
|
),
|
|
);
|
|
|
|
_initialized = true;
|
|
debugPrint('CoverCacheManager: Initialized successfully');
|
|
} catch (e) {
|
|
debugPrint('CoverCacheManager: Failed to initialize: $e');
|
|
// Will fallback to DefaultCacheManager
|
|
}
|
|
}
|
|
|
|
/// Clear all cached cover images.
|
|
/// Returns the number of files deleted.
|
|
static Future<void> clearCache() async {
|
|
if (!_initialized || _instance == null) return;
|
|
await _instance!.emptyCache();
|
|
}
|
|
|
|
static Future<CacheStats> getStats() async {
|
|
if (!_initialized || _cachePath == null) {
|
|
return const CacheStats(fileCount: 0, totalSizeBytes: 0);
|
|
}
|
|
|
|
final cacheDir = Directory(_cachePath!);
|
|
|
|
if (!await cacheDir.exists()) {
|
|
return const CacheStats(fileCount: 0, totalSizeBytes: 0);
|
|
}
|
|
|
|
int fileCount = 0;
|
|
int totalSize = 0;
|
|
|
|
try {
|
|
await for (final entity in cacheDir.list(recursive: true)) {
|
|
if (entity is File) {
|
|
fileCount++;
|
|
totalSize += await entity.length();
|
|
}
|
|
}
|
|
} catch (e) {
|
|
debugPrint('CoverCacheManager: Error getting stats: $e');
|
|
}
|
|
|
|
return CacheStats(fileCount: fileCount, totalSizeBytes: totalSize);
|
|
}
|
|
}
|
|
|
|
/// Statistics about the cover image cache
|
|
class CacheStats {
|
|
final int fileCount;
|
|
final int totalSizeBytes;
|
|
|
|
const CacheStats({
|
|
required this.fileCount,
|
|
required this.totalSizeBytes,
|
|
});
|
|
|
|
String get formattedSize {
|
|
if (totalSizeBytes < 1024) {
|
|
return '$totalSizeBytes B';
|
|
} else if (totalSizeBytes < 1024 * 1024) {
|
|
return '${(totalSizeBytes / 1024).toStringAsFixed(1)} KB';
|
|
} else if (totalSizeBytes < 1024 * 1024 * 1024) {
|
|
return '${(totalSizeBytes / (1024 * 1024)).toStringAsFixed(1)} MB';
|
|
} else {
|
|
return '${(totalSizeBytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB';
|
|
}
|
|
}
|
|
}
|