import {createSlice, PayloadAction} from '@reduxjs/toolkit' import {find, findIndex} from 'lodash-es' import {DEFAULT_SERVER_URL_OPENAI, TOTAL_HEIGHT_DEF} from '../consts/const' interface EnvState { envData: EnvData envReady: boolean tempData: TempData tempReady: boolean path?: 'app' | 'options' fold: boolean // fold app foldAll?: boolean // fold all segments autoTranslate?: boolean autoScroll?: boolean checkAutoScroll?: boolean curOffsetTop?: number floatKeyPointsSegIdx?: number // segment的startIdx noVideo?: boolean totalHeight: number curIdx?: number // 从0开始 needScroll?: boolean currentTime?: number infos?: any[] curInfo?: any curFetched?: boolean data?: Transcript uploadedTranscript?: Transcript segments?: Segment[] url?: string title?: string ctime?: number | null author?: string taskIds?: string[] transResults: { [key: number]: TransResult } lastTransTime?: number lastSummarizeTime?: number // ask asks: AskInfo[] /** * 是否输入中(中文) */ inputting: boolean searchText: string searchResult: Record // 当前视频是否计算过操作 reviewAction: boolean } const initialState: EnvState = { envData: { serverUrl: DEFAULT_SERVER_URL_OPENAI, translateEnable: true, summarizeEnable: true, autoExpand: true, theme: 'light', searchEnabled: true, }, tempData: { curSummaryType: 'overview', }, totalHeight: TOTAL_HEIGHT_DEF, autoScroll: true, envReady: false, tempReady: false, fold: true, transResults: {}, inputting: false, searchText: '', searchResult: {}, asks: [], reviewAction: false, } export const slice = createSlice({ name: 'env', initialState, reducers: { setEnvData: (state, action: PayloadAction) => { state.envData = { ...state.envData, ...action.payload, } }, setEnvReady: (state) => { state.envReady = true }, setTempData: (state, action: PayloadAction>) => { state.tempData = { ...state.tempData, ...action.payload, } }, setReviewAction: (state, action: PayloadAction) => { state.reviewAction = action.payload }, setPath: (state, action: PayloadAction<'app' | 'options' | undefined>) => { state.path = action.payload }, setTempReady: (state) => { state.tempReady = true }, setSearchText: (state, action: PayloadAction) => { state.searchText = action.payload }, setSearchResult: (state, action: PayloadAction>) => { state.searchResult = action.payload }, setFloatKeyPointsSegIdx: (state, action: PayloadAction) => { state.floatKeyPointsSegIdx = action.payload }, setFoldAll: (state, action: PayloadAction) => { state.foldAll = action.payload }, setTotalHeight: (state, action: PayloadAction) => { state.totalHeight = action.payload }, setTaskIds: (state, action: PayloadAction) => { state.taskIds = action.payload }, setLastTransTime: (state, action: PayloadAction) => { state.lastTransTime = action.payload }, setLastSummarizeTime: (state, action: PayloadAction) => { state.lastSummarizeTime = action.payload }, addTaskId: (state, action: PayloadAction) => { state.taskIds = [...(state.taskIds ?? []), action.payload] }, delTaskId: (state, action: PayloadAction) => { state.taskIds = state.taskIds?.filter(id => id !== action.payload) }, addTransResults: (state, action: PayloadAction<{ [key: number]: TransResult }>) => { // 不要覆盖TransResult里code为200的 for (const payloadKey in action.payload) { const payloadItem = action.payload[payloadKey] const stateItem = state.transResults[payloadKey] if (!stateItem || stateItem.code !== '200') { state.transResults[payloadKey] = payloadItem } else if (stateItem.code === '200') { // 保留data state.transResults[payloadKey] = { ...payloadItem, data: stateItem.data, } } } }, setSummaryContent: (state, action: PayloadAction<{ segmentStartIdx: number type: SummaryType content?: any }>) => { const segment = find(state.segments, {startIdx: action.payload.segmentStartIdx}) if (segment != null) { let summary = segment.summaries[action.payload.type] if (!summary) { summary = { type: action.payload.type, status: 'done', content: action.payload.content, } segment.summaries[action.payload.type] = summary } else { summary.content = action.payload.content } } }, setSummaryStatus: (state, action: PayloadAction<{ segmentStartIdx: number type: SummaryType status: SummaryStatus }>) => { const segment = find(state.segments, {startIdx: action.payload.segmentStartIdx}) if (segment != null) { let summary = segment.summaries[action.payload.type] if (summary) { summary.status = action.payload.status } else { summary = { type: action.payload.type, status: action.payload.status, } segment.summaries[action.payload.type] = summary } } }, setSummaryError: (state, action: PayloadAction<{ segmentStartIdx: number type: SummaryType error?: string }>) => { const segment = find(state.segments, {startIdx: action.payload.segmentStartIdx}) if (segment != null) { let summary = segment.summaries[action.payload.type] if (summary) { summary.error = action.payload.error } else { summary = { type: action.payload.type, status: 'done', error: action.payload.error, } segment.summaries[action.payload.type] = summary } } }, addAskInfo: (state, action: PayloadAction) => { state.asks.push(action.payload) }, delAskInfo: (state, action: PayloadAction) => { state.asks = state.asks.filter(ask => ask.id !== action.payload) }, mergeAskInfo: (state, action: PayloadAction) => { const idx = findIndex(state.asks, {id: action.payload.id}) if (idx >= 0) { state.asks[idx] = { ...state.asks[idx], ...action.payload, } } }, setSegmentFold: (state, action: PayloadAction<{ segmentStartIdx: number fold: boolean }>) => { const segment = find(state.segments, {startIdx: action.payload.segmentStartIdx}) if (segment != null) { segment.fold = action.payload.fold } }, clearTransResults: (state) => { state.transResults = {} }, setCurIdx: (state, action: PayloadAction) => { state.curIdx = action.payload }, setAutoTranslate: (state, action: PayloadAction) => { state.autoTranslate = action.payload }, setAutoScroll: (state, action: PayloadAction) => { state.autoScroll = action.payload }, setCheckAutoScroll: (state, action: PayloadAction) => { state.checkAutoScroll = action.payload }, setCurOffsetTop: (state, action: PayloadAction) => { state.curOffsetTop = action.payload }, setNoVideo: (state, action: PayloadAction) => { state.noVideo = action.payload }, setNeedScroll: (state, action: PayloadAction) => { state.needScroll = action.payload }, setCurrentTime: (state, action: PayloadAction) => { state.currentTime = action.payload }, setUrl: (state, action: PayloadAction) => { state.url = action.payload }, setTitle: (state, action: PayloadAction) => { state.title = action.payload }, setCtime: (state, action: PayloadAction) => { state.ctime = action.payload }, setAuthor: (state, action: PayloadAction) => { state.author = action.payload }, setInfos: (state, action: PayloadAction) => { state.infos = action.payload }, setCurInfo: (state, action: PayloadAction) => { state.curInfo = action.payload }, setCurFetched: (state, action: PayloadAction) => { state.curFetched = action.payload }, setData: (state, action: PayloadAction) => { state.data = action.payload }, setUploadedTranscript: (state, action: PayloadAction) => { state.uploadedTranscript = action.payload }, setSegments: (state, action: PayloadAction) => { state.segments = action.payload }, setFold: (state, action: PayloadAction) => { state.fold = action.payload }, setInputting: (state, action: PayloadAction) => { state.inputting = action.payload }, }, }) export const { setPath, setUrl, setTempReady, setTempData, setUploadedTranscript, setTotalHeight, setCheckAutoScroll, setCurOffsetTop, setFloatKeyPointsSegIdx, setFoldAll, setSegmentFold, setSummaryContent, setSummaryStatus, setSummaryError, setTitle, setSegments, setLastSummarizeTime, setLastTransTime, clearTransResults, addTransResults, addTaskId, delTaskId, setTaskIds, setAutoTranslate, setAutoScroll, setNoVideo, setReviewAction, setNeedScroll, setCurIdx, setEnvData, setEnvReady, setCurrentTime, setInfos, setCurInfo, setCurFetched, setData, setFold, setSearchText, setSearchResult, setInputting, addAskInfo, delAskInfo, mergeAskInfo, setCtime, setAuthor, } = slice.actions export default slice.reducer