66 lines
2.1 KiB
TypeScript
66 lines
2.1 KiB
TypeScript
import React, { createContext, useContext, useReducer, useEffect, type ReactNode } from 'react';
|
|
import { Store } from '@tauri-apps/plugin-store';
|
|
import type { QrState, QrAction, HistoryEntry } from '../types';
|
|
|
|
const initialState: QrState = {
|
|
mode: 'text',
|
|
formData: {},
|
|
config: { level: 'M', margin: 4, moduleSize: 8 },
|
|
preview: null,
|
|
history: [],
|
|
loading: false,
|
|
};
|
|
|
|
function qrReducer(state: QrState, action: QrAction): QrState {
|
|
switch (action.type) {
|
|
case 'SET_MODE':
|
|
return { ...state, mode: action.payload, formData: {}, preview: null };
|
|
case 'SET_FORM_DATA':
|
|
return { ...state, formData: action.payload };
|
|
case 'SET_CONFIG':
|
|
return { ...state, config: { ...state.config, ...action.payload } };
|
|
case 'SET_PREVIEW':
|
|
return { ...state, preview: action.payload, loading: false };
|
|
case 'SET_LOADING':
|
|
return { ...state, loading: action.payload };
|
|
case 'SET_HISTORY':
|
|
return { ...state, history: action.payload };
|
|
case 'ADD_HISTORY':
|
|
return { ...state, history: [action.payload, ...state.history].slice(0, 50) };
|
|
case 'REMOVE_HISTORY':
|
|
return { ...state, history: state.history.filter(h => h.id !== action.payload) };
|
|
case 'RESET':
|
|
return { ...initialState, history: state.history };
|
|
default:
|
|
return state;
|
|
}
|
|
}
|
|
|
|
const QrContext = createContext<{
|
|
state: QrState;
|
|
dispatch: React.Dispatch<QrAction>;
|
|
} | null>(null);
|
|
|
|
export function QrProvider({ children }: { children: ReactNode }) {
|
|
const [state, dispatch] = useReducer(qrReducer, initialState);
|
|
|
|
// 启动时从 store 加载持久化的历史记录
|
|
useEffect(() => {
|
|
(async () => {
|
|
try {
|
|
const store = await Store.load('history.json');
|
|
const history = await store.get<HistoryEntry[]>('qr-history') || [];
|
|
dispatch({ type: 'SET_HISTORY', payload: history });
|
|
} catch { /* store 不可用时忽略 */ }
|
|
})();
|
|
}, []);
|
|
|
|
return <QrContext.Provider value={{ state, dispatch }}>{children}</QrContext.Provider>;
|
|
}
|
|
|
|
export function useQrState() {
|
|
const ctx = useContext(QrContext);
|
|
if (!ctx) throw new Error('useQrState must be inside QrProvider');
|
|
return ctx;
|
|
}
|