You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
MTMusic/lib/view/user/my_music_view.dart

738 lines
29 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:music_player_miao/api/api_music_mymusic.dart';
import '../../common_widget/app_data.dart';
import '../../models/getAllSongs_bean.dart';
import '../../view_model/home_view_model.dart';
import '../../api/api_songlist.dart';
import '../../api/api_songlist.dart';
import '../../models/universal_bean.dart';
import '../music_view.dart';
import '../../common_widget/Song_widegt.dart';
import '../../common/download_manager.dart';
List<T> flatten<T>(Iterable<Iterable<T>> iterable) {
return iterable.expand((inner) => inner).toList();
}
class MyMusicView extends StatefulWidget {
final int? songlistIdd;
const MyMusicView({Key? key, this.songlistIdd}) : super(key: key);
@override
State<MyMusicView> createState() => _MyMusicViewState();
}
class _MyMusicViewState extends State<MyMusicView> {
int songsNum = 0;
List songlistId = [];
List musicDetail = [];
List name = [];
List coverPath = [];
List musicPath = [];
List singerName = [];
List uploadUserName = [];
List mid = [];
final listVM = Get.put(HomeViewModel());
bool _isSelectMode = false;
final List<bool> _mySongListSelections = List.generate(2, (index) => false);
List<bool> _selectedItems = List.generate(10, (index) => false);
final downloadManager = Get.put(DownloadManager());
//修改从这开始
@override
void initState() {
super.initState();
if (widget.songlistIdd != null) {
_fetchMyWorksData();
} else {
// 处理 songlistIdd 为 null 的情况,例如显示错误消息或不执行数据获取
print('Songlist ID is null, cannot fetch data.');
}
}
///获取我的作品
Future<void> _fetchMyWorksData() async {
try {
MyMusicListBean bean2 = await SonglistApi().getAllSongs(
id: widget.songlistIdd!,
Authorization: AppData().currentToken,
);
setState(() {
// 初始化列表
name = [];
coverPath = [];
musicPath = [];
singerName = [];
songlistId = [];
mid = [];
// 遍历每个DataBean对象
bean2.data?.forEach((dataBean) {
// 提取songlistId
songlistId.add(dataBean.songlistId);
// 提取musicDetail对象
SongDetails songDetails = dataBean.musicDetail!;
// 添加歌曲信息到列表
name.add(songDetails.name);
coverPath.add(songDetails.coverPath);
musicPath.add(songDetails.musicPath);
singerName.add(songDetails.singerName);
mid.add(songDetails.mid);
});
songsNum = name.length; // 歌曲数量
});
} catch (error) {
print('Error fetching myworks data: $error');
}
}
Future<void> _deleteSong(int songId) async {
try {
List<int> songIds = [songId];
print(songIds);
// 先调用API
UniversalBean response = await MymusicsApiMusic().mymusicsMusic(
songlistMusicIds: songIds,
Authorization: AppData().currentToken,
);
if (response.code != 200) {
throw Exception('Failed to delete song');
}
// API调用成功后再刷新列表
await _fetchMyWorksData();
} catch (error) {
print('Error deleting song: $error');
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('删除失败,请稍后重试')),
);
}
}
//在这里结束
void _toggleSelectMode() {
setState(() {
_isSelectMode = !_isSelectMode;
if (!_isSelectMode) {
_selectedItems = List.generate(10, (index) => false);
}
});
}
void _selectAll() {
setState(() {
_selectedItems = List.generate(10, (index) => true);
});
}
void _showSelectionDialog() {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
title: Row(
children: [
const Text(
"添加到",
),
Text(
'(${_selectedItems.where((item) => item).length} 首)',
style: const TextStyle(color: Color(0xff429482), fontSize: 16),
)
],
),
content: SingleChildScrollView(
physics: const BouncingScrollPhysics(),
child: Column(
children: [
for (int i = 0; i < _mySongListSelections.length; i++)
_buildSongListTile(i),
],
),
),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
style: TextButton.styleFrom(
backgroundColor: const Color(0xff429482),
minimumSize: const Size(130, 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
child: const Text(
"取消",
style: TextStyle(color: Colors.white),
),
),
TextButton(
onPressed: () {},
style: TextButton.styleFrom(
backgroundColor: const Color(0xff429482),
minimumSize: const Size(130, 50),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(5.0),
),
),
child: const Text(
"保存",
style: TextStyle(color: Colors.white),
),
),
],
);
},
);
}
Widget _buildSongListTile(int index) {
return ListTile(
title: Text("我的歌单 $index"),
trailing: Checkbox(
value: _mySongListSelections[index],
onChanged: (value) {
setState(() {
_mySongListSelections[index] = value ?? false;
});
},
shape: const CircleBorder(),
activeColor: const Color(0xff429482),
),
onTap: () {
setState(() {
_mySongListSelections[index] = !_mySongListSelections[index];
});
},
);
}
@override
Widget build(BuildContext context) {
return Container(
decoration: const BoxDecoration(
image: DecorationImage(
image: AssetImage("assets/img/app_bg.png"),
fit: BoxFit.cover,
),
),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
backgroundColor: Colors.transparent,
centerTitle: true,
elevation: 0,
leading: !_isSelectMode
? IconButton(
onPressed: () {
Get.back(result: true);
},
icon: Image.asset(
"assets/img/back.png",
width: 25,
height: 25,
fit: BoxFit.contain,
),
)
: TextButton(
onPressed: _selectAll,
style: TextButton.styleFrom(
foregroundColor: Colors.black,
minimumSize: const Size(50, 40), // 设置小宽度,确保文字有足够空间
padding:
const EdgeInsets.symmetric(horizontal: 8), // 添加水平内边距
),
child: const Text(
'全选',
style: TextStyle(fontSize: 18),
),
),
title: _isSelectMode
? Text(
'已选中 ${_selectedItems.where((item) => item).length} 首歌曲',
style: const TextStyle(
color: Colors.black,
),
)
: const Text(
'我的歌单',
style: TextStyle(color: Colors.black),
),
actions: [
if (_isSelectMode)
TextButton(
onPressed: () {
setState(() {
_isSelectMode = false;
_selectedItems = List.generate(10, (index) => false);
});
},
child: const Text(
"完成",
style: TextStyle(color: Colors.black, fontSize: 18),
))
],
),
body: Container(
padding: const EdgeInsets.only(left: 10),
decoration: const BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(top: Radius.circular(30)),
),
child: Column(
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
// 播放全部按钮
Row(
children: [
IconButton(
onPressed: songsNum == 0
? null
: () async {
List<Song> songList = List.generate(
songsNum,
(i) => Song(
id: songlistId[i] ?? 0,
title: name[i] ?? '未知歌曲',
artist: singerName[i] ?? '未知歌手',
artistPic: coverPath[i],
pic: coverPath[i],
musicurl: musicPath[i],
likes: false,
collection: false,
mid: mid[i],
),
);
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MusicView(
songList: songList,
initialSongIndex: 0,
onSongStatusChanged: (index, isCollected, isLiked) {
setState(() {
songList[index].collection = isCollected;
songList[index].likes = isLiked;
downloadManager.updateSongInfo(
songList[index].id,
isCollected,
isLiked,
);
});
},
),
),
);
if (result != null) {
_fetchMyWorksData();
}
},
icon: Image.asset(
"assets/img/button_play.png",
width: 20,
height: 20,
),
),
const Text(
'播放全部',
style: TextStyle(fontSize: 16),
),
const SizedBox(width: 5),
Text(
'(${songsNum})', // 使用实际的歌曲数量
style: const TextStyle(fontSize: 16),
),
],
),
// 删除右边的三个杠按钮
// IconButton(
// onPressed: () {...},
// icon: Image.asset("assets/img/list_op.png",...),
// ),
],
),
),
Expanded(
child: songsNum == 0
? const Center(child: Text('该歌单为空'))
: ListView.builder(
itemCount: songsNum,
padding: EdgeInsets.zero,
itemBuilder: (context, index) {
return Dismissible(
key: Key(songlistId[index].toString()),
direction: DismissDirection.endToStart,
background: Container(
color: Colors.red,
padding: const EdgeInsets.only(right: 16.0),
alignment: Alignment.centerRight,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
"assets/img/delete.png",
width: 24,
height: 24,
color: Colors.white,
),
const SizedBox(height: 4),
const Text(
'删除',
style: TextStyle(
color: Colors.white,
fontSize: 12,
),
),
],
),
),
confirmDismiss: (direction) async {
return await showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('确认删除'),
content: Text('确定要删除 ${name[index] ?? "这首歌"} 吗?'),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.of(context).pop(false),
child: const Text(
'取消',
style: TextStyle(color: Color(0xff429482)),
),
),
TextButton(
onPressed: () => Navigator.of(context).pop(true),
child: const Text(
'确定',
style: TextStyle(color: Colors.red),
),
),
],
);
},
);
},
onDismissed: (direction) {
if (songlistId[index] != null) {
final currentSongId = songlistId[index];
// 先调用API成功后会自动刷新列表
_deleteSong(currentSongId);
}
},
child: ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 16.0),
onTap: _isSelectMode
? () {
setState(() {
_selectedItems[index] = !_selectedItems[index];
});
}
: () async {
// 创建当前播放列表
List<Song> songList = List.generate(
songsNum,
(i) => Song(
id: songlistId[i],
title: name[i] ?? '未知歌曲',
artist: singerName[i] ?? '未知歌手',
artistPic: coverPath[i] ?? 'https://api.aspark.cc/image/1/6759856d288fd.jpg',
pic: coverPath[i] ?? 'https://api.aspark.cc/image/1/6759856d288fd.jpg',
musicurl: musicPath[i] ?? '',
likes: false,
collection: false,
mid: mid[i],
),
);
// 导航到音乐播放页面
final result = await Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MusicView(
songList: songList,
initialSongIndex: index,
onSongStatusChanged: (index, isCollected, isLiked) {
setState(() {
songList[index].collection = isCollected;
songList[index].likes = isLiked;
downloadManager.updateSongInfo(
songList[index].id,
isCollected,
isLiked,
);
});
},
),
),
);
// 从播放页面返回时刷新列表
if (result != null) {
_fetchMyWorksData();
}
},
title: Row(
children: [
if (_isSelectMode)
Checkbox(
value: _selectedItems[index],
onChanged: (value) {
setState(() {
_selectedItems[index] = value!;
});
},
shape: const CircleBorder(),
activeColor: const Color(0xff429482),
),
ClipRRect(
borderRadius: BorderRadius.circular(10),
child: Image.network(
coverPath[index],
width: 60,
height: 60,
fit: BoxFit.cover,
errorBuilder: (context, error, stackTrace) {
return Image.asset(
"assets/img/artist_pic.png",
width: 60,
height: 60,
);
},
),
),
const SizedBox(width: 12),
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
name[index] ?? '未知歌曲',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 16,
color: Colors.black,
),
),
Text(
singerName[index] ?? '未知歌手',
maxLines: 1,
overflow: TextOverflow.ellipsis,
style: const TextStyle(
fontSize: 14,
color: Colors.black54,
),
),
],
),
),
],
),
),
);
},
),
),
],
),
),
bottomNavigationBar: _isSelectMode
? BottomAppBar(
child: SizedBox(
height: 127.0,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
Row(
children: [
IconButton(
onPressed: () {
_showSelectionDialog();
},
icon: Image.asset("assets/img/list_add.png"),
iconSize: 60,
),
const Text("添加到"),
],
),
Container(
height: 50,
width: 2,
color: const Color(0xff429482),
),
Row(
children: [
IconButton(
onPressed: () {},
icon:
Image.asset("assets/img/list_download.png"),
iconSize: 60,
),
const Text("下载"),
],
),
],
),
ElevatedButton(
onPressed: () {
setState(() {
_isSelectMode = false;
_selectedItems =
List.generate(10, (index) => false);
});
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xff429482),
padding: const EdgeInsets.symmetric(vertical: 14),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
),
child: const Text(
'取消',
style: TextStyle(color: Colors.black, fontSize: 16),
),
),
],
),
),
)
: null,
),
);
}
Future _bottomSheet(BuildContext context) {
return showModalBottomSheet(
context: context,
backgroundColor: Colors.white,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(top: Radius.circular(30))),
builder: (context) => Container(
height: 210,
padding: const EdgeInsets.only(top: 20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Column(
children: [
IconButton(
onPressed: () {},
icon: Image.asset("assets/img/list_remove.png"),
iconSize: 60,
),
const Text("从歌单移除")
],
),
Column(
children: [
IconButton(
onPressed: () {},
icon: Image.asset("assets/img/list_download.png"),
iconSize: 60,
),
const Text("下载")
],
),
Column(
children: [
IconButton(
onPressed: () {},
icon: Image.asset("assets/img/list_collection.png"),
iconSize: 60,
),
const Text("收藏")
],
),
Column(
children: [
IconButton(
onPressed: () {},
icon: Image.asset("assets/img/list_good.png"),
iconSize: 60,
),
const Text("点赞")
],
),
Column(
children: [
IconButton(
onPressed: () {},
icon: Image.asset("assets/img/list_comment.png"),
iconSize: 60,
),
const Text("评论")
],
),
],
),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: () {
// Get.to(()=>const MusicView());
},
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xffE6F4F1),
padding: const EdgeInsets.symmetric(vertical: 8),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
),
child: const Text(
"查看详情页",
style: TextStyle(color: Colors.black, fontSize: 18),
),
),
ElevatedButton(
onPressed: () => Navigator.pop(context),
style: ElevatedButton.styleFrom(
backgroundColor: const Color(0xff429482),
padding: const EdgeInsets.symmetric(vertical: 8),
tapTargetSize: MaterialTapTargetSize.shrinkWrap,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.zero,
),
),
child: const Text(
"取消",
style: TextStyle(color: Colors.black, fontSize: 18),
),
),
],
),
));
}
}