import 'dart:convert'; import 'dart:io'; import 'package:get/get.dart'; import 'package:shared_preferences/shared_preferences.dart'; import '../api/api_download.dart'; import '../common_widget/Song_widegt.dart'; import 'package:path/path.dart' as path; class DownloadItem { final Song song; double progress; bool isCompleted; bool isDownloading; DownloadItem({ required this.song, this.progress = 0.0, this.isCompleted = false, this.isDownloading = false, }); Map toJson() { return { 'song': { 'pic': song.pic, 'artistPic': song.artistPic, 'title': song.title, 'artist': song.artist, 'musicurl': song.musicurl, 'id': song.id, 'likes': song.likes, 'collection': song.collection }, 'progress': progress, 'isCompleted': isCompleted, 'isDownloading': isDownloading, }; } // 从JSON创建DownloadItem factory DownloadItem.fromJson(Map json) { return DownloadItem( song: Song( pic: json['song']['pic'], artistPic: json['song']['artistPic'], title: json['song']['title'], artist: json['song']['artist'], musicurl: json['song']['musicurl'], id: json['song']['id'], likes: json['song']['likes'], collection: json['song']['collection'], ), progress: json['progress'], isCompleted: json['isCompleted'], isDownloading: json['isDownloading'], ); } } class DownloadManager extends GetxController { static const String PREFS_KEY = 'downloads_data'; final _downloads = {}.obs; final downloadApi = DownloadApi(); late SharedPreferences _prefs; @override void onInit() async { super.onInit(); await _initPrefs(); } Future _initPrefs() async { _prefs = await SharedPreferences.getInstance(); await _loadDownloadsFromPrefs(); } // 从SharedPreferences加载数据 Future _loadDownloadsFromPrefs() async { final String? downloadsJson = _prefs.getString(PREFS_KEY); if (downloadsJson != null) { final Map downloadsMap = json.decode(downloadsJson); downloadsMap.forEach((key, value) { _downloads[key] = DownloadItem.fromJson(value); }); } } // 保存数据到SharedPreferences Future _saveDownloadsToPrefs() async { final Map downloadsMap = {}; _downloads.forEach((key, value) { downloadsMap[key] = value.toJson(); }); await _prefs.setString(PREFS_KEY, json.encode(downloadsMap)); } List getLocalSongs() { final localSongs = []; _downloads.forEach((key, value) { if (value.isCompleted) { localSongs.add(value.song); } }); return localSongs; } Map get downloads => _downloads; bool isDownloading(int id) => _downloads[id.toString()]?.isDownloading ?? false; bool isCompleted(int id) => _downloads[id.toString()]?.isCompleted ?? false; double getProgress(int id) => _downloads[id.toString()]?.progress ?? 0.0; Song? getLocalSong(int id) { final downloadItem = _downloads[id.toString()]; if (downloadItem?.isCompleted ?? false) { return downloadItem!.song; } return null; } bool removeSong(int id) { if (_downloads[id.toString()]?.isCompleted ?? false) { File file = File.fromUri(Uri.parse(_downloads[id.toString()]!.song.musicurl)); file.deleteSync(); _downloads.remove(id.toString()); _saveDownloadsToPrefs(); return true; } return false; } int completedNumber() { int count = 0; _downloads.forEach((key, value) { if (value.isCompleted) { count++; } }); return count; } Future startDownload({ required Song song, required context, }) async { if (_downloads[song.id.toString()]?.isDownloading ?? false) return; final fileName = '${song.id}_${song.title}_${song.artist}'; final downloadItem = DownloadItem( song: song, isDownloading: true, ); _downloads[song.id.toString()] = downloadItem; try { final filePath = await downloadApi.downloadMusic( musicUrl: song.musicurl, name: fileName, context: context, onProgress: (progress) { downloadItem.progress = progress; _downloads[song.id.toString()] = downloadItem; }, ); if (filePath != null) { downloadItem.isCompleted = true; downloadItem.isDownloading = false; downloadItem.progress = 1.0; song.musicurl = _getLocalAudioPath(fileName, song.musicurl); print(song.musicurl); } else { downloadItem.isDownloading = false; downloadItem.progress = 0.0; } } catch (e) { print('Download error: $e'); downloadItem.isDownloading = false; downloadItem.progress = 0.0; } _downloads[song.id.toString()] = downloadItem; await _saveDownloadsToPrefs(); } bool updateSongInfo(int id, bool isCollected, bool isLiked) { final downloadItem = _downloads[id.toString()]; if (downloadItem != null) { downloadItem.song.collection = isCollected; downloadItem.song.likes = isLiked; _downloads[id.toString()] = downloadItem; _saveDownloadsToPrefs(); return true; } return false; } String _getFileExtension(String url) { // Remove query parameters final urlWithoutQuery = url.split('?').first; // Get the extension including the dot final extension = path.extension(urlWithoutQuery); return extension.isNotEmpty ? extension : '.mp3'; // Default to .mp3 if no extension found } String _getLocalAudioPath(String fileName, String url) { final extension = _getFileExtension(url); final fullFileName = '$fileName$extension'; return path.join('/storage/emulated/0/MTMusic', fullFileName); } }