|
|
@@ -731,118 +731,72 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
|
|
|
// 播放列表控制方法
|
|
|
async playNext(): Promise<void> {
|
|
|
- try {
|
|
|
- // 设置手动歌曲切换标志,防止自动播放干扰
|
|
|
- this.isManualSongChange = true;
|
|
|
-
|
|
|
- // 首先检查服务是否已准备就绪
|
|
|
- if (!this.isAllServicesReady()) {
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: playNext - 服务未就绪,等待服务初始化完成');
|
|
|
- // 在自动播放场景下,减少等待时间避免阻塞
|
|
|
- const isReady = await this.waitForAllServicesReady(500, false);
|
|
|
- if (!isReady) {
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: Services not ready for playNext, skipping');
|
|
|
- this.isManualSongChange = false;
|
|
|
- return; // 直接返回,不抛出错误
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- const playMode = this.stateModel.getState().playMode;
|
|
|
-
|
|
|
- if (!this.playlistModel.hasNext(playMode)) {
|
|
|
- this.isManualSongChange = false;
|
|
|
- return;
|
|
|
- }
|
|
|
- const moved = this.playlistModel.moveToNext(playMode);
|
|
|
- if (!moved) {
|
|
|
- this.isManualSongChange = false;
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- // 更新状态模型的索引
|
|
|
- const newIndex = this.playlistModel.getCurrentIndex();
|
|
|
- const newSong = this.playlistModel.getCurrentSong();
|
|
|
- this.stateModel.updateCurrentIndex(newIndex);
|
|
|
-
|
|
|
- if (newSong) {
|
|
|
- this.stateModel.updateCurrentSong(newSong);
|
|
|
- }
|
|
|
-
|
|
|
- // 静默停止当前播放(不触发状态变化通知)
|
|
|
- await this.stopSilently();
|
|
|
-
|
|
|
- // 直接播放新歌曲,不调用通用的恢复逻辑
|
|
|
- await this.playNewSongDirectly(newSong);
|
|
|
-
|
|
|
- // 更新状态模型中的播放列表状态
|
|
|
- this.updatePlaylistStateInModel();
|
|
|
-
|
|
|
- // 强制更新卡片显示新歌曲(重要事件)
|
|
|
- if (newSong) {
|
|
|
- await this.updateWidgetsForSongChange(newSong, true);
|
|
|
- }
|
|
|
-
|
|
|
- } catch (error) {
|
|
|
- await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
|
|
|
- } finally {
|
|
|
- // 确保在任何情况下都清除手动切换标志
|
|
|
- setTimeout(() => {
|
|
|
- this.isManualSongChange = false;
|
|
|
- }, 1000); // 延迟1秒清除,确保播放器状态稳定
|
|
|
- }
|
|
|
+ return this.changeTrack('next');
|
|
|
}
|
|
|
|
|
|
async playPrevious(): Promise<void> {
|
|
|
+ return this.changeTrack('previous');
|
|
|
+ }
|
|
|
+ /**
|
|
|
+ * 切换歌曲(下一首或上一首)
|
|
|
+ * @param direction - 切换方向,'next' 或 'previous'
|
|
|
+ */
|
|
|
+ async changeTrack(direction: 'next' | 'previous'): Promise<void> {
|
|
|
try {
|
|
|
- // 设置手动歌曲切换标志,防止自动播放干扰
|
|
|
+ // 1. 设置手动歌曲切换标志,防止自动播放等逻辑干扰
|
|
|
this.isManualSongChange = true;
|
|
|
-
|
|
|
- // 首先检查服务是否已准备就绪
|
|
|
+
|
|
|
+ // 2. 检查服务是否已准备就绪
|
|
|
if (!this.isAllServicesReady()) {
|
|
|
- LogUtils.getInstance().LOGI('UnifiedPlayerService: playPrevious - 服务未就绪,等待服务初始化完成');
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: ${direction} - 服务未就绪,等待服务初始化完成`);
|
|
|
const isReady = await this.waitForAllServicesReady(500, false);
|
|
|
if (!isReady) {
|
|
|
- const error = new Error('Services not ready for playPrevious');
|
|
|
- await this.handlePlaybackError(error, PlayerErrorType.INITIALIZATION_ERROR);
|
|
|
+ LogUtils.getInstance().LOGI(`UnifiedPlayerService: Services not ready for ${direction}, skipping`);
|
|
|
+ // 统一处理方式:在服务未就绪时直接返回,避免抛出错误中断用户体验
|
|
|
this.isManualSongChange = false;
|
|
|
return;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const playMode = this.stateModel.getState().playMode;
|
|
|
+ let moved = false;
|
|
|
|
|
|
- if (!(await this.playlistModel.hasPrevious(playMode))) {
|
|
|
- this.isManualSongChange = false;
|
|
|
- return;
|
|
|
+ // 3. 根据 direction 参数执行不同的逻辑
|
|
|
+ if (direction === 'next') {
|
|
|
+ if (this.playlistModel.hasNext(playMode)) {
|
|
|
+ moved = this.playlistModel.moveToNext(playMode);
|
|
|
+ }
|
|
|
+ } else { // direction === 'previous'
|
|
|
+ if (await this.playlistModel.hasPrevious(playMode)) {
|
|
|
+ // 注意:'previous' 相关的操作是异步的,需要 await
|
|
|
+ moved = await this.playlistModel.moveToPrevious(playMode);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- // 先获取当前歌曲信息用于日志
|
|
|
-
|
|
|
- const moved = await this.playlistModel.moveToPrevious(playMode);
|
|
|
+ // 如果没有成功移动(列表到头/尾,或移动失败),则直接返回
|
|
|
if (!moved) {
|
|
|
this.isManualSongChange = false;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // 更新状态模型的索引
|
|
|
const newIndex = this.playlistModel.getCurrentIndex();
|
|
|
const newSong = this.playlistModel.getCurrentSong();
|
|
|
- this.stateModel.updateCurrentIndex(newIndex);
|
|
|
|
|
|
+ this.stateModel.updateCurrentIndex(newIndex);
|
|
|
if (newSong) {
|
|
|
this.stateModel.updateCurrentSong(newSong);
|
|
|
}
|
|
|
|
|
|
- // 静默停止当前播放(不触发状态变化通知)
|
|
|
+ // 静默停止当前播放
|
|
|
await this.stopSilently();
|
|
|
|
|
|
- // 直接播放新歌曲,不调用通用的恢复逻辑
|
|
|
+ // 直接播放新歌曲
|
|
|
await this.playNewSongDirectly(newSong);
|
|
|
|
|
|
- // 更新状态模型中的播放列表状态
|
|
|
+ // 更新播放列表状态
|
|
|
this.updatePlaylistStateInModel();
|
|
|
|
|
|
- // 强制更新卡片显示新歌曲(重要事件)
|
|
|
+ // 强制更新UI(如卡片)
|
|
|
if (newSong) {
|
|
|
await this.updateWidgetsForSongChange(newSong, true);
|
|
|
}
|
|
|
@@ -850,7 +804,7 @@ export class UnifiedPlayerService implements IPlayerService, PlaylistSyncListene
|
|
|
} catch (error) {
|
|
|
await this.handlePlaybackError(error as Error, PlayerErrorType.PLAYBACK_ERROR);
|
|
|
} finally {
|
|
|
- // 确保在任何情况下都清除手动切换标志
|
|
|
+ // 5. 在任何情况下都清除手动切换标志
|
|
|
setTimeout(() => {
|
|
|
this.isManualSongChange = false;
|
|
|
}, 1000); // 延迟1秒清除,确保播放器状态稳定
|