import 'package:flutter/material.dart'; import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:provider/provider.dart'; import 'package:yumi/modules/room/music/room_music_texts.dart'; import 'package:yumi/services/music/room_music_manager.dart'; import 'package:yumi/shared/data_sources/models/sc_music_folder_mode.dart'; import 'package:yumi/shared/data_sources/models/sc_music_mode.dart'; class RoomMusicSelectPage extends StatefulWidget { const RoomMusicSelectPage({super.key, required this.folder}); final SCMusicFolderMode folder; @override State createState() => _RoomMusicSelectPageState(); } class _RoomMusicSelectPageState extends State { late Set _initialSelectedIds; late Set _selectedIds; bool get _hasChanged => !_setEquals(_initialSelectedIds, _selectedIds); bool get _allSelected => _selectedIds.length == widget.folder.songs.length; @override void initState() { super.initState(); final currentIds = context .read() .playlist .map((item) => item.id) .toSet(); _initialSelectedIds = widget.folder.songs .where((item) => currentIds.contains(item.id)) .map((item) => item.id) .toSet(); _selectedIds = {..._initialSelectedIds}; } @override Widget build(BuildContext context) { return Theme( data: Theme.of(context).copyWith( splashFactory: NoSplash.splashFactory, splashColor: Colors.transparent, highlightColor: Colors.transparent, ), child: Scaffold( backgroundColor: const Color(0xFF071F1B), appBar: AppBar( backgroundColor: const Color(0xFF071F1B), elevation: 0, title: Text( RoomMusicTexts.t(context, "roomMusicAddMusic", "添加音乐"), style: TextStyle(fontSize: 17.sp, fontWeight: FontWeight.w700), ), ), body: Column( children: [ Expanded( child: ListView.separated( padding: EdgeInsets.fromLTRB(16.w, 8.w, 16.w, 16.w), itemCount: widget.folder.songs.length, separatorBuilder: (_, __) => Divider( color: Colors.white.withValues(alpha: 0.08), height: 1, ), itemBuilder: (context, index) { return _buildSongItem(widget.folder.songs[index]); }, ), ), _buildBottomBar(context), ], ), ), ); } Widget _buildSongItem(SCMusicMode item) { final selected = _selectedIds.contains(item.id); final alreadyAdded = _initialSelectedIds.contains(item.id); final checkColor = !selected ? Colors.transparent : alreadyAdded ? Colors.white.withValues(alpha: 0.34) : const Color(0xFF33E6A2); return GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { if (selected) { _selectedIds.remove(item.id); } else { _selectedIds.add(item.id); } }); }, child: SizedBox( height: 64.w, child: Row( children: [ Expanded( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( item.title, maxLines: 1, overflow: TextOverflow.ellipsis, style: TextStyle( color: Colors.white, fontSize: 14.sp, fontWeight: FontWeight.w600, ), ), SizedBox(height: 5.w), Text( _formatDuration(item.durationMs), style: TextStyle( color: Colors.white.withValues(alpha: 0.52), fontSize: 11.sp, ), ), ], ), ), Container( width: 22.w, height: 22.w, decoration: BoxDecoration( shape: BoxShape.circle, color: checkColor, border: Border.all( color: selected ? checkColor : Colors.white.withValues(alpha: 0.28), ), ), child: selected ? Icon(Icons.check, size: 15.w, color: Colors.white) : null, ), ], ), ), ); } Widget _buildBottomBar(BuildContext context) { return SafeArea( top: false, child: Container( padding: EdgeInsets.fromLTRB(16.w, 12.w, 16.w, 12.w), decoration: BoxDecoration( color: const Color(0xFF082820), border: Border( top: BorderSide(color: Colors.white.withValues(alpha: 0.08)), ), ), child: Row( children: [ GestureDetector( behavior: HitTestBehavior.opaque, onTap: () { setState(() { if (_allSelected) { _selectedIds.clear(); } else { _selectedIds = widget.folder.songs.map((item) => item.id).toSet(); } }); }, child: Row( children: [ Icon( _allSelected ? Icons.check_circle : Icons.radio_button_unchecked, color: _allSelected ? const Color(0xFF33E6A2) : Colors.white.withValues(alpha: 0.55), size: 22.w, ), SizedBox(width: 8.w), Text( RoomMusicTexts.t(context, "roomMusicSelectAll", "全选"), style: TextStyle(color: Colors.white, fontSize: 14.sp), ), ], ), ), const Spacer(), GestureDetector( behavior: HitTestBehavior.opaque, onTap: _hasChanged ? _submit : null, child: Container( width: 104.w, height: 40.w, alignment: Alignment.center, decoration: BoxDecoration( color: _hasChanged ? const Color(0xFF33E6A2) : Colors.white.withValues(alpha: 0.18), borderRadius: BorderRadius.circular(20.w), ), child: Text( RoomMusicTexts.t(context, "add", "添加"), style: TextStyle( color: _hasChanged ? const Color(0xFF06251F) : Colors.white.withValues(alpha: 0.38), fontSize: 14.sp, fontWeight: FontWeight.w700, ), ), ), ), ], ), ), ); } Future _submit() async { await context.read().applyFolderSelection( folder: widget.folder, selectedIds: _selectedIds, ); if (!mounted) { return; } Navigator.pop(context, true); } bool _setEquals(Set a, Set b) { return a.length == b.length && a.containsAll(b); } String _formatDuration(int milliseconds) { final seconds = (milliseconds / 1000).floor(); final minutes = seconds ~/ 60; final rest = seconds % 60; return "$minutes:${rest.toString().padLeft(2, '0')}"; } }