feat(devtool): 脚本录制器自动载入上次打开文件夹、代码
This commit is contained in:
parent
7d32c43051
commit
5fad34bd6f
|
@ -17,6 +17,7 @@ import useHotkey from '../../hooks/useHotkey';
|
|||
import { useFormModal } from '../../hooks/useFormModal';
|
||||
import { openDirectory } from '../../utils/fileUtils';
|
||||
import { useToast } from '../../components/ToastMessage';
|
||||
import { ScriptRecorderStorage } from '../../utils/storageUtils';
|
||||
|
||||
// 引入 ace 编辑器的主题和语言模式
|
||||
import 'ace-builds/src-noconflict/mode-python';
|
||||
|
@ -77,10 +78,11 @@ ContextStackVars.screenshot_mode = 'manual'
|
|||
|
||||
device.screenshot()
|
||||
`
|
||||
|
||||
console.log('ScriptRecorderStorage.load()', ScriptRecorderStorage.loadCode());
|
||||
const useScriptRecorderStore = create<ScriptRecorderState>((set) => ({
|
||||
code: DEFAULT_CODE,
|
||||
code: ScriptRecorderStorage.loadCode() || DEFAULT_CODE,
|
||||
tool: 'drag',
|
||||
|
||||
autoScreenshot: true,
|
||||
connected: false,
|
||||
imageUrl: '',
|
||||
|
@ -92,7 +94,11 @@ const useScriptRecorderStore = create<ScriptRecorderState>((set) => ({
|
|||
imageMetaDataObject: null,
|
||||
setImageMetaDataObject: (imageMetaData) => set({ imageMetaDataObject: imageMetaData }),
|
||||
|
||||
setCode: (code) => set({ code }),
|
||||
setCode: (code) => {
|
||||
ScriptRecorderStorage.saveCode(code);
|
||||
console.log('setCode', code);
|
||||
set({ code });
|
||||
},
|
||||
setTool: (tool) => set({ tool }),
|
||||
setAutoScreenshot: (auto) => set({ autoScreenshot: auto }),
|
||||
setConnected: (connected) => set({ connected }),
|
||||
|
@ -395,6 +401,7 @@ function useStoreImageMetaData() {
|
|||
|
||||
const ScriptRecorder: React.FC = () => {
|
||||
const client = useDebugClient();
|
||||
const { showToast, ToastComponent } = useToast();
|
||||
|
||||
const editorRef = useRef<any>(null);
|
||||
const { imageMetaData, Definitions, Annotations, clear } = useStoreImageMetaData();
|
||||
|
@ -580,11 +587,35 @@ const ScriptRecorder: React.FC = () => {
|
|||
|
||||
const handleOpenDirectory = async () => {
|
||||
const handle = await openDirectory();
|
||||
setDirectoryHandle(handle);
|
||||
if (handle) {
|
||||
setDirectoryHandle(handle);
|
||||
await ScriptRecorderStorage.saveDirectoryHandle(handle);
|
||||
showToast('success', '', `已载入上次打开文件夹 ${handle.name}`);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const loadSavedDirectoryHandle = async () => {
|
||||
try {
|
||||
const handle = await ScriptRecorderStorage.loadDirectoryHandle();
|
||||
if (handle) {
|
||||
const hasPermission = await ScriptRecorderStorage.verifyDirectoryHandlePermission(handle);
|
||||
if (hasPermission) {
|
||||
setDirectoryHandle(handle);
|
||||
showToast('success', '已载入文件夹', `已载入上次打开文件夹 ${handle.name}`);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('Failed to load saved directory handle:', e);
|
||||
}
|
||||
};
|
||||
|
||||
loadSavedDirectoryHandle();
|
||||
}, [showToast]);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
{ToastComponent}
|
||||
{formModal}
|
||||
{inEditMode ? (
|
||||
<EditToolBar
|
||||
|
|
|
@ -0,0 +1,91 @@
|
|||
interface ScriptRecorderData {
|
||||
code: string;
|
||||
directoryHandle?: FileSystemDirectoryHandle;
|
||||
}
|
||||
|
||||
interface StorageData {
|
||||
last: ScriptRecorderData;
|
||||
}
|
||||
|
||||
export class ScriptRecorderStorage {
|
||||
private static readonly STORAGE_KEY = 'scriptRecorder';
|
||||
private static readonly DB_NAME = 'scriptRecorderDB';
|
||||
private static readonly STORE_NAME = 'fileHandles';
|
||||
private static readonly DB_VERSION = 1;
|
||||
|
||||
static saveCode(code: string): void {
|
||||
const data: StorageData = {
|
||||
last: { code }
|
||||
};
|
||||
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(data));
|
||||
}
|
||||
|
||||
static loadCode(): string | null {
|
||||
const dataStr = localStorage.getItem(this.STORAGE_KEY);
|
||||
if (!dataStr) return null;
|
||||
|
||||
try {
|
||||
const data = JSON.parse(dataStr) as StorageData;
|
||||
return data.last.code;
|
||||
} catch (e) {
|
||||
console.error('Failed to parse script recorder data:', e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static clearCode(): void {
|
||||
localStorage.removeItem(this.STORAGE_KEY);
|
||||
}
|
||||
|
||||
private static async getDB(): Promise<IDBDatabase> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const request = indexedDB.open(this.DB_NAME, this.DB_VERSION);
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result);
|
||||
|
||||
request.onupgradeneeded = (event) => {
|
||||
const db = (event.target as IDBOpenDBRequest).result;
|
||||
if (!db.objectStoreNames.contains(this.STORE_NAME)) {
|
||||
db.createObjectStore(this.STORE_NAME);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
static async saveDirectoryHandle(handle: FileSystemDirectoryHandle): Promise<void> {
|
||||
const db = await this.getDB();
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(this.STORE_NAME, 'readwrite');
|
||||
const store = transaction.objectStore(this.STORE_NAME);
|
||||
const request = store.put(handle, 'directoryHandle');
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve();
|
||||
});
|
||||
}
|
||||
|
||||
static async loadDirectoryHandle(): Promise<FileSystemDirectoryHandle | null> {
|
||||
const db = await this.getDB();
|
||||
return new Promise((resolve, reject) => {
|
||||
const transaction = db.transaction(this.STORE_NAME, 'readonly');
|
||||
const store = transaction.objectStore(this.STORE_NAME);
|
||||
const request = store.get('directoryHandle');
|
||||
|
||||
request.onerror = () => reject(request.error);
|
||||
request.onsuccess = () => resolve(request.result || null);
|
||||
});
|
||||
}
|
||||
|
||||
static async verifyDirectoryHandlePermission(handle: FileSystemDirectoryHandle): Promise<boolean> {
|
||||
try {
|
||||
const options = { mode: 'readwrite' } as const;
|
||||
// @ts-ignore
|
||||
const permission = await handle.requestPermission(options);
|
||||
return permission === 'granted';
|
||||
} catch (e) {
|
||||
console.error('Failed to verify directory handle permission:', e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue