cfa3959fb3
Add TipTap editing in the editor and an Electron window on the control panel to read the current scene description. Co-authored-by: Cursor <cursoragent@cursor.com>
51 lines
1.6 KiB
TypeScript
51 lines
1.6 KiB
TypeScript
import React, { useEffect, useMemo, useState } from 'react';
|
|
|
|
import { ipcChannels } from '../../shared/ipc/contracts';
|
|
import { useEditorI18n } from '../editor/i18n/EditorI18nContext';
|
|
import { isSceneDescriptionEmpty, sanitizeSceneDescriptionHtml } from '../editor/sceneDescriptionHtml';
|
|
import proseStyles from '../editor/SceneDescriptionModal.module.css';
|
|
import { getDndApi } from '../shared/dndApi';
|
|
|
|
import styles from './SceneDescriptionApp.module.css';
|
|
|
|
export function SceneDescriptionApp() {
|
|
const { t } = useEditorI18n();
|
|
const [html, setHtml] = useState('');
|
|
|
|
useEffect(() => {
|
|
const api = getDndApi();
|
|
void api.invoke(ipcChannels.windows.getSceneDescriptionContent, {}).then(({ html: next }) => {
|
|
setHtml(next);
|
|
});
|
|
return api.on(ipcChannels.windows.sceneDescriptionContent, ({ html: next }) => {
|
|
setHtml(next);
|
|
});
|
|
}, []);
|
|
|
|
useEffect(() => {
|
|
const onKey = (e: KeyboardEvent) => {
|
|
if (e.key === 'Escape') window.close();
|
|
};
|
|
window.addEventListener('keydown', onKey);
|
|
return () => window.removeEventListener('keydown', onKey);
|
|
}, []);
|
|
|
|
const safeHtml = useMemo(() => sanitizeSceneDescriptionHtml(html), [html]);
|
|
const empty = isSceneDescriptionEmpty(html);
|
|
|
|
return (
|
|
<div className={styles.page}>
|
|
<div className={styles.body}>
|
|
{empty ? (
|
|
<div className={styles.empty}>{t('scene.descriptionEmpty')}</div>
|
|
) : (
|
|
<div
|
|
className={[proseStyles.prose, styles.proseText].join(' ')}
|
|
dangerouslySetInnerHTML={{ __html: safeHtml }}
|
|
/>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|