// lib/pages/playlists_page.dart import 'package:flutter/material.dart'; import '../models/playlist_summary.dart'; import '../repositories/playlist_repository.dart'; import '../widgets/song_artwork.dart'; import 'playlist_detail_page.dart'; /// 歌单集合页:展示所有歌单,支持新建 / 重命名 / 删除 class PlaylistsPage extends StatefulWidget { const PlaylistsPage({super.key}); @override State createState() => _PlaylistsPageState(); } class _PlaylistsPageState extends State { final PlaylistRepository _repo = PlaylistRepository(); List _playlists = []; bool _loading = true; @override void initState() { super.initState(); _load(); } Future _load() async { setState(() => _loading = true); try { final list = await _repo.getSummaries(); if (!mounted) return; setState(() { _playlists = list; _loading = false; }); } catch (e) { if (!mounted) return; setState(() => _loading = false); ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('读取歌单失败: $e')), ); } } Future _create() async { final name = await _promptName('新建歌单'); if (name == null || name.isEmpty) return; try { await _repo.createPlaylist(name); await _load(); } catch (e) { if (!mounted) return; ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text('新建失败: $e'))); } } Future _rename(PlaylistSummary playlist) async { final name = await _promptName('重命名歌单', initial: playlist.name); if (name == null || name.isEmpty) return; await _repo.updatePlaylistName(playlist.id, name); await _load(); } Future _delete(PlaylistSummary playlist) async { final ok = await showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: const Color(0xFF1A1F1E), title: const Text('删除歌单', style: TextStyle(color: Colors.white)), content: Text( '删除「${playlist.name}」?歌单内的歌曲不会从网盘删除。', style: const TextStyle(color: Colors.grey), ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, true), child: const Text('删除', style: TextStyle(color: Colors.redAccent)), ), ], ), ); if (ok == true) { await _repo.deletePlaylist(playlist.id); await _load(); } } Future _promptName(String title, {String initial = ''}) async { final controller = TextEditingController(text: initial); return showDialog( context: context, builder: (context) => AlertDialog( backgroundColor: const Color(0xFF1A1F1E), title: Text(title, style: const TextStyle(color: Colors.white)), content: TextField( controller: controller, autofocus: true, style: const TextStyle(color: Colors.white), decoration: const InputDecoration(hintText: '歌单名称'), ), actions: [ TextButton( onPressed: () => Navigator.pop(context), child: const Text('取消'), ), TextButton( onPressed: () => Navigator.pop(context, controller.text.trim()), child: const Text('确定'), ), ], ), ); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xFF0E1211), appBar: AppBar( backgroundColor: Colors.transparent, elevation: 0, title: const Text('歌单'), actions: [ IconButton( icon: const Icon(Icons.add, color: Color(0xFFB8D4D0)), tooltip: '新建歌单', onPressed: _create, ), ], ), body: _loading ? const Center(child: CircularProgressIndicator()) : _playlists.isEmpty ? _buildEmpty() : RefreshIndicator( onRefresh: _load, child: ListView.builder( padding: const EdgeInsets.symmetric( horizontal: 16, vertical: 8), itemCount: _playlists.length, itemBuilder: (context, index) { final playlist = _playlists[index]; return ListTile( contentPadding: const EdgeInsets.symmetric(horizontal: 4), visualDensity: VisualDensity.compact, leading: SongArtwork( filePath: playlist.coverPath, size: 52, fallbackIcon: Icons.queue_music, ), title: Text( playlist.name, style: const TextStyle( color: Colors.white, fontSize: 16), maxLines: 1, overflow: TextOverflow.ellipsis, ), subtitle: Text( '${playlist.songCount} 首', style: const TextStyle( color: Colors.grey, fontSize: 12), ), trailing: PopupMenuButton( icon: const Icon(Icons.more_vert, color: Colors.white38, size: 20), onSelected: (value) { if (value == 'rename') _rename(playlist); if (value == 'delete') _delete(playlist); }, itemBuilder: (context) => const [ PopupMenuItem( value: 'rename', child: Row( children: [ Icon(Icons.edit_outlined, color: Color(0xFFB8D4D0), size: 18), SizedBox(width: 10), Text('重命名'), ], ), ), PopupMenuItem( value: 'delete', child: Row( children: [ Icon(Icons.delete_outline, color: Colors.redAccent, size: 18), SizedBox(width: 10), Text('删除'), ], ), ), ], ), onTap: () async { await Navigator.push( context, MaterialPageRoute( builder: (_) => PlaylistDetailPage( playlistId: playlist.id, playlistName: playlist.name, ), ), ); await _load(); }, ); }, ), ), ); } Widget _buildEmpty() { return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Icon(Icons.queue_music, size: 48, color: Colors.grey[700]), const SizedBox(height: 14), Text( '还没有歌单', style: TextStyle(color: Colors.grey[500], fontSize: 15), ), const SizedBox(height: 6), Text( '点右上角 + 新建一个', style: TextStyle(color: Colors.grey[700], fontSize: 12), ), ], ), ); } }