All files / src/entities/history/model thunk.ts

6.89% Statements 2/29
0% Branches 0/8
0% Functions 0/2
7.4% Lines 2/27

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79                  30x                                                       30x                                                                                  
import { nanoid } from 'nanoid';
import { createAsyncThunk } from '@reduxjs/toolkit';
import type { HistoryEntry } from '@/shared/types';
import type { AppDispatch, RootState } from '@/store';
import { applySnapshot } from '@/entities/history/lib';
import { historyService } from '@/entities/history/model';
import { pushState, resetHistory, setPreview } from './slice';
import { HISTORY_SLICE_ACTIONS, ICON_KEYS, UI_LABELS } from '@/shared/constants';
 
export const loadHistoryFromDB = createAsyncThunk<void, string, { state: RootState }>(
	`${HISTORY_SLICE_ACTIONS.LOAD_HISTORY_FROM_DB}`,
	async (_, { dispatch, getState }) => {
		const state = getState() as RootState;
		const projectId = state.projects.activeId;
		if (!projectId) return;
 
		const entries = await historyService.loadByProject(projectId);
 
		dispatch(resetHistory());
 
		for (const entry of entries as HistoryEntry[]) {
			const isDrawAction = !!entry.toolType; // brush/line/shape/eraser
 
			const normalizedIcon = isDrawAction
				? entry.icon
				: (entry.icon ?? ICON_KEYS.EDIT);
 
			const normalized: HistoryEntry = {
				...entry,
				icon: normalizedIcon,
			};
 
			dispatch(pushState(normalized));
		}
	},
);
 
export const applyCurrentSnapshot = createAsyncThunk<
	void,
	void,
	{ state: RootState; dispatch: AppDispatch }
>(`${HISTORY_SLICE_ACTIONS.APPLY_SNAPSHOT}`, async (_, { dispatch, getState }) => {
	const { history } = getState();
	const entry = history.stack[history.currentIndex];
	if (!entry) return;
 
	const projectId = entry.state.projectId;
 
	//  apply snapshot (Redux + Dexie + Canvas)
	await applySnapshot(entry.state, { dispatch, getState });
 
	// remove history after a chosen step
	await historyService.deleteAfterIndex(projectId, history.currentIndex);
 
	// recollect history
	dispatch(resetHistory());
	const newHistory = history.stack.slice(0, history.currentIndex + 1);
 
	for (const e of newHistory) {
		dispatch(pushState(e));
		await historyService.saveEntry(e);
	}
 
	// add final step "Apply snapshot"
	const appliedEntry = {
		id: nanoid(),
		label: UI_LABELS.APPLY_SNAPSHOT,
		state: entry.state,
		timestamp: Date.now(),
		icon: 'edit',
	};
 
	dispatch(pushState(appliedEntry));
	await historyService.saveEntry(appliedEntry);
 
	// exit from preview mode
	dispatch(setPreview(false));
});