feat(playlist): 歌单变更与歌单内元数据实时刷新
两个边界场景: 1) 新建/重命名/删除歌单、加入/移除歌曲后,主页歌单页不刷新 2) 歌单详情页里歌曲补全元数据后,标题/封面不更新 - 新增 PlaylistEvents(void 事件) - PlaylistRepository 的创建/重命名/删除/批量加入/移除后 publish - 主页订阅后重新拉取歌单摘要 - 歌单详情页订阅 MetadataEvents,按 path 就地更新行
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import 'dart:async';
|
||||
// lib/pages/playlist_detail_page.dart
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
@@ -5,6 +6,7 @@ import 'package:provider/provider.dart';
|
||||
import '../database/song_database.dart';
|
||||
import '../repositories/playlist_repository.dart';
|
||||
import '../services/audio_service.dart';
|
||||
import '../services/metadata_events.dart';
|
||||
import '../widgets/song_artwork.dart';
|
||||
|
||||
/// 歌单详情:展示歌单内歌曲,支持播放全部 / 单曲播放 / 移除
|
||||
@@ -41,14 +43,40 @@ class _PlaylistDetailPageState extends State<PlaylistDetailPage> {
|
||||
final SongDatabase _db = SongDatabase();
|
||||
|
||||
List<_SongRow> _songs = [];
|
||||
StreamSubscription<MetadataUpdate>? _metaSub;
|
||||
bool _loading = true;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_metaSub = MetadataEvents().stream.listen(_onMetadataUpdate);
|
||||
_load();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_metaSub?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
/// 歌单里的歌补全元数据后,就地更新对应行
|
||||
void _onMetadataUpdate(MetadataUpdate update) {
|
||||
final index = _songs.indexWhere((item) => item.path == update.path);
|
||||
if (index < 0 || !mounted) return;
|
||||
final row = update.row;
|
||||
final title = (row['title'] as String?)?.trim() ?? '';
|
||||
final artist = (row['artist'] as String?)?.trim() ?? '';
|
||||
final artwork = (row['artwork_path'] as String?)?.trim() ?? '';
|
||||
final old = _songs[index];
|
||||
setState(() {
|
||||
_songs[index] = _SongRow(
|
||||
path: old.path,
|
||||
title: title.isNotEmpty ? title : old.title,
|
||||
artist: artist.isNotEmpty ? artist : old.artist,
|
||||
artworkPath: artwork.isNotEmpty ? artwork : old.artworkPath,
|
||||
);
|
||||
});
|
||||
}
|
||||
Future<void> _load() async {
|
||||
setState(() => _loading = true);
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user