From 53a395fe0798f538772566ddd452da4d7c2eb7ce Mon Sep 17 00:00:00 2001 From: Coki <92775570+HashCookie@users.noreply.github.com> Date: Sun, 15 Sep 2024 14:00:09 +0800 Subject: [PATCH] fix: simplify ModelEditor component and improve message handling (#154) * refactor: simplify ModelEditor component and improve message handling * chore: update GitHub actions to use v4 for various steps in release workflow --- .github/workflows/release.yml | 26 +++++++------- app/components/ModelEditor.tsx | 64 +++++++++++++++++++++++----------- app/model-editor/page.tsx | 14 ++------ 3 files changed, 59 insertions(+), 45 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 368f26a..bae0788 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,9 +13,9 @@ jobs: runs-on: macos-latest steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: '20.8.1' - name: Install dependencies @@ -25,7 +25,7 @@ jobs: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: yarn dist --mac - name: Upload macOS build artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: electron-app-macos path: dist/*.dmg @@ -34,9 +34,9 @@ jobs: runs-on: windows-latest steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: '20.8.1' - name: Install dependencies @@ -46,7 +46,7 @@ jobs: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: yarn dist --win - name: Upload Windows build artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: electron-app-windows path: dist/*.exe @@ -55,9 +55,9 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Node.js - uses: actions/setup-node@v2 + uses: actions/setup-node@v4 with: node-version: '20.8.1' - name: Install dependencies @@ -67,7 +67,7 @@ jobs: GH_TOKEN: ${{ secrets.GH_TOKEN }} run: yarn dist --linux - name: Upload Linux build artifacts - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v4 with: name: electron-app-linux path: dist/*.AppImage @@ -77,7 +77,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Set up Node.js uses: actions/setup-node@v3 with: @@ -85,17 +85,17 @@ jobs: - name: Clear npm cache run: npm cache clean --force - name: Download macOS build artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: electron-app-macos path: dist/macos - name: Download Windows build artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: electron-app-windows path: dist/windows - name: Download Linux build artifacts - uses: actions/download-artifact@v2 + uses: actions/download-artifact@v4 with: name: electron-app-linux path: dist/linux diff --git a/app/components/ModelEditor.tsx b/app/components/ModelEditor.tsx index 88f92c7..e88d0d5 100644 --- a/app/components/ModelEditor.tsx +++ b/app/components/ModelEditor.tsx @@ -1,5 +1,5 @@ 'use client'; -import React, { useState, useEffect, useCallback } from 'react'; +import React, { useState, useEffect, useCallback, useRef } from 'react'; import CodeMirror from '@uiw/react-codemirror'; import { monokai } from '@uiw/codemirror-theme-monokai'; import { basicSetup } from 'codemirror'; @@ -11,14 +11,10 @@ import { casbinLinter } from '@/app/utils/casbinLinter'; import { newModel } from 'casbin'; import { setError } from '@/app/utils/errorManager'; -export const ModelEditor = ({ initialValue = '' }: { initialValue: string }) => { +export const ModelEditor = () => { const [modelText, setModelText] = useState(''); - - useEffect(() => { - if (initialValue) { - setModelText(initialValue); - } - }, [initialValue]); + const editorRef = useRef(null); + const cursorPosRef = useRef<{ from: number; to: number } | null>(null); const validateModel = useCallback(async (text: string) => { try { @@ -33,26 +29,49 @@ export const ModelEditor = ({ initialValue = '' }: { initialValue: string }) => validateModel(modelText); }, [modelText, validateModel]); - useEffect(() => { - const handleMessage = (event: MessageEvent) => { - if (event.data.type === 'getModelText') { - window.parent.postMessage({ - type: 'modelUpdate', - modelText: modelText - }, '*'); - } - }; + const handleMessage = useCallback((event: MessageEvent) => { + if (event.data.type === 'initializeModel') { + setModelText(event.data.modelText); + } else if (event.data.type === 'getModelText') { + window.parent.postMessage({ + type: 'modelUpdate', + modelText: modelText + }, '*'); + } else if (event.data.type === 'updateModelText') { + setModelText(event.data.modelText); + } + }, [modelText]); + useEffect(() => { window.addEventListener('message', handleMessage); + window.parent.postMessage({ type: 'iframeReady' }, '*'); return () => { window.removeEventListener('message', handleMessage); }; - }, [modelText]); + }, [handleMessage]); - const handleModelTextChange = (value: string) => { + const handleModelTextChange = useCallback((value: string, viewUpdate: any) => { setModelText(value); - }; + cursorPosRef.current = viewUpdate.state.selection.main; + window.parent.postMessage({ + type: 'modelUpdate', + modelText: value + }, '*'); + }, []); + + useEffect(() => { + if (editorRef.current && cursorPosRef.current) { + const { from, to } = cursorPosRef.current; + const docLength = editorRef.current.state.doc.length; + editorRef.current.dispatch({ + selection: { + anchor: Math.min(from, docLength), + head: Math.min(to, docLength) + } + }); + } + }, [modelText]); return (
@@ -73,6 +92,11 @@ export const ModelEditor = ({ initialValue = '' }: { initialValue: string }) => indentUnit.of(' '), EditorView.lineWrapping, linter(casbinLinter), + EditorView.updateListener.of((update) => { + if (update.docChanged) { + editorRef.current = update.view; + } + }), ]} className={'function flex-grow h-[300px]'} value={modelText} diff --git a/app/model-editor/page.tsx b/app/model-editor/page.tsx index cd562d5..732b3a2 100644 --- a/app/model-editor/page.tsx +++ b/app/model-editor/page.tsx @@ -1,22 +1,12 @@ 'use client'; -import React, { useEffect, useState } from 'react'; +import React from 'react'; import { ModelEditor } from '../components/ModelEditor'; export default function ModelEditorPage() { - const [initialValue, setInitialValue] = useState(''); - - useEffect(() => { - const params = new URLSearchParams(window.location.search); - const modelParam = params.get('model'); - if (modelParam) { - setInitialValue(decodeURIComponent(modelParam)); - } - }, []); - return (
- +
); }