mirror of
https://github.com/zimplexing/OrionTV.git
synced 2026-05-18 23:07:31 +08:00
Enhance video playback features by adding playTime and initialPosition handling, and update PlayerControls for better focus management
This commit is contained in:
@@ -8,6 +8,7 @@ export type RowItem = (SearchResult | PlayRecord) & {
|
||||
title: string;
|
||||
poster: string;
|
||||
progress?: number;
|
||||
play_time?: number;
|
||||
lastPlayed?: number;
|
||||
episodeIndex?: number;
|
||||
sourceName?: string;
|
||||
@@ -61,48 +62,48 @@ const useHomeStore = create<HomeState>((set, get) => ({
|
||||
error: null,
|
||||
|
||||
fetchInitialData: async () => {
|
||||
const { selectedCategory } = get();
|
||||
set({ loading: true, contentData: [], pageStart: 0, hasMore: true, error: null });
|
||||
await get().loadMoreData();
|
||||
set({ loading: false });
|
||||
},
|
||||
|
||||
loadMoreData: async () => {
|
||||
const { selectedCategory, pageStart, loading, loadingMore, hasMore } = get();
|
||||
if (loading || loadingMore || !hasMore) return;
|
||||
const { selectedCategory, pageStart, loadingMore, hasMore } = get();
|
||||
if (loadingMore || !hasMore) return;
|
||||
|
||||
if (selectedCategory.type === 'record') {
|
||||
const records = await PlayRecordManager.getAll();
|
||||
const rowItems = Object.entries(records)
|
||||
.map(([key, record]) => {
|
||||
const [source, id] = key.split('+');
|
||||
return { ...record, id, source, progress: record.play_time / record.total_time, poster: record.cover, sourceName: record.source_name, episodeIndex: record.index, totalEpisodes: record.total_episodes, lastPlayed: record.save_time };
|
||||
})
|
||||
.filter(record => record.progress !== undefined && record.progress > 0 && record.progress < 1)
|
||||
.sort((a, b) => (b.lastPlayed || 0) - (a.lastPlayed || 0));
|
||||
|
||||
set({ contentData: rowItems, hasMore: false });
|
||||
return;
|
||||
if (pageStart > 0) {
|
||||
set({ loadingMore: true });
|
||||
}
|
||||
|
||||
if (!selectedCategory.type || !selectedCategory.tag) return;
|
||||
|
||||
set({ loadingMore: true });
|
||||
try {
|
||||
const result = await api.getDoubanData(selectedCategory.type, selectedCategory.tag, 20, pageStart);
|
||||
if (result.list.length === 0) {
|
||||
set({ hasMore: false });
|
||||
if (selectedCategory.type === 'record') {
|
||||
const records = await PlayRecordManager.getAll();
|
||||
const rowItems = Object.entries(records)
|
||||
.map(([key, record]) => {
|
||||
const [source, id] = key.split('+');
|
||||
return { ...record, id, source, progress: record.play_time / record.total_time, poster: record.cover, sourceName: record.source_name, episodeIndex: record.index, totalEpisodes: record.total_episodes, lastPlayed: record.save_time, play_time: record.play_time };
|
||||
})
|
||||
.filter(record => record.progress !== undefined && record.progress > 0 && record.progress < 1)
|
||||
.sort((a, b) => (b.lastPlayed || 0) - (a.lastPlayed || 0));
|
||||
|
||||
set({ contentData: rowItems, hasMore: false });
|
||||
} else if (selectedCategory.type && selectedCategory.tag) {
|
||||
const result = await api.getDoubanData(selectedCategory.type, selectedCategory.tag, 20, pageStart);
|
||||
if (result.list.length === 0) {
|
||||
set({ hasMore: false });
|
||||
} else {
|
||||
const newItems = result.list.map(item => ({
|
||||
...item,
|
||||
id: item.title,
|
||||
source: 'douban',
|
||||
})) as RowItem[];
|
||||
set(state => ({
|
||||
contentData: pageStart === 0 ? newItems : [...state.contentData, ...newItems],
|
||||
pageStart: state.pageStart + result.list.length,
|
||||
hasMore: true,
|
||||
}));
|
||||
}
|
||||
} else {
|
||||
const newItems = result.list.map(item => ({
|
||||
...item,
|
||||
id: item.title,
|
||||
source: 'douban',
|
||||
})) as RowItem[];
|
||||
set(state => ({
|
||||
contentData: pageStart === 0 ? newItems : [...state.contentData, ...newItems],
|
||||
pageStart: state.pageStart + result.list.length,
|
||||
hasMore: true,
|
||||
}));
|
||||
set({ hasMore: false });
|
||||
}
|
||||
} catch (err: any) {
|
||||
if (err.message === 'API_URL_NOT_SET') {
|
||||
@@ -111,7 +112,7 @@ const useHomeStore = create<HomeState>((set, get) => ({
|
||||
set({ error: '加载失败,请重试' });
|
||||
}
|
||||
} finally {
|
||||
set({ loadingMore: false });
|
||||
set({ loading: false, loadingMore: false });
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -27,8 +27,9 @@ interface PlayerState {
|
||||
isSeeking: boolean;
|
||||
seekPosition: number;
|
||||
progressPosition: number;
|
||||
initialPosition: number;
|
||||
setVideoRef: (ref: RefObject<Video>) => void;
|
||||
loadVideo: (source: string, id: string, episodeIndex: number) => Promise<void>;
|
||||
loadVideo: (source: string, id: string, episodeIndex: number, position?: number) => Promise<void>;
|
||||
playEpisode: (index: number) => void;
|
||||
togglePlayPause: () => void;
|
||||
seek: (forward: boolean) => void;
|
||||
@@ -53,11 +54,18 @@ const usePlayerStore = create<PlayerState>((set, get) => ({
|
||||
isSeeking: false,
|
||||
seekPosition: 0,
|
||||
progressPosition: 0,
|
||||
initialPosition: 0,
|
||||
|
||||
setVideoRef: (ref) => set({ videoRef: ref }),
|
||||
|
||||
loadVideo: async (source, id, episodeIndex) => {
|
||||
set({ isLoading: true, detail: null, episodes: [], currentEpisodeIndex: 0 });
|
||||
loadVideo: async (source, id, episodeIndex, position) => {
|
||||
set({
|
||||
isLoading: true,
|
||||
detail: null,
|
||||
episodes: [],
|
||||
currentEpisodeIndex: 0,
|
||||
initialPosition: position || 0,
|
||||
});
|
||||
try {
|
||||
const videoDetail = await api.getVideoDetail(source, id);
|
||||
const episodes = videoDetail.episodes.map((ep, index) => ({ url: ep, title: `第 ${index + 1} 集` }));
|
||||
@@ -76,7 +84,7 @@ const usePlayerStore = create<PlayerState>((set, get) => ({
|
||||
playEpisode: (index) => {
|
||||
const { episodes, videoRef } = get();
|
||||
if (index >= 0 && index < episodes.length) {
|
||||
set({ currentEpisodeIndex: index, showNextEpisodeOverlay: false });
|
||||
set({ currentEpisodeIndex: index, showNextEpisodeOverlay: false, initialPosition: 0 });
|
||||
videoRef?.current?.replayAsync();
|
||||
}
|
||||
},
|
||||
@@ -156,6 +164,7 @@ const usePlayerStore = create<PlayerState>((set, get) => ({
|
||||
showControls: true,
|
||||
showEpisodeModal: false,
|
||||
showNextEpisodeOverlay: false,
|
||||
initialPosition: 0,
|
||||
});
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { create } from 'zustand';
|
||||
import { SettingsManager } from '@/services/storage';
|
||||
import { api } from '@/services/api';
|
||||
import useHomeStore from './homeStore';
|
||||
|
||||
interface SettingsState {
|
||||
apiBaseUrl: string;
|
||||
@@ -26,6 +27,7 @@ export const useSettingsStore = create<SettingsState>((set, get) => ({
|
||||
await SettingsManager.save({ apiBaseUrl });
|
||||
api.setBaseUrl(apiBaseUrl);
|
||||
set({ isModalVisible: false });
|
||||
useHomeStore.getState().fetchInitialData();
|
||||
},
|
||||
showModal: () => set({ isModalVisible: true }),
|
||||
hideModal: () => set({ isModalVisible: false }),
|
||||
|
||||
Reference in New Issue
Block a user