feat(editor): highlight edges and show preview import loader
- Highlight all edges connected to selected scene - Show overlay spinner while uploading/optimizing preview image - macOS: keep control window independent from presentation Made-with: Cursor
This commit is contained in:
@@ -64,6 +64,7 @@ export function EditorApp() {
|
||||
const [settingsMenuOpen, setSettingsMenuOpen] = useState(false);
|
||||
const [renameOpen, setRenameOpen] = useState(false);
|
||||
const [exportModalOpen, setExportModalOpen] = useState(false);
|
||||
const [previewBusy, setPreviewBusy] = useState(false);
|
||||
const [licenseSnap, setLicenseSnap] = useState<LicenseSnapshot | null>(null);
|
||||
const [licenseKeyModalOpen, setLicenseKeyModalOpen] = useState(false);
|
||||
const [eulaModalOpen, setEulaModalOpen] = useState(false);
|
||||
@@ -480,6 +481,7 @@ export function EditorApp() {
|
||||
previewAssetType={sc?.previewAssetType ?? null}
|
||||
previewVideoAutostart={sc?.previewVideoAutostart ?? false}
|
||||
previewRotationDeg={sc?.previewRotationDeg ?? 0}
|
||||
previewBusy={previewBusy}
|
||||
mediaAssets={sceneMediaAssets}
|
||||
audioRefs={sceneAudioRefs}
|
||||
onAudioRefsChange={(next) =>
|
||||
@@ -492,7 +494,18 @@ export function EditorApp() {
|
||||
onDescriptionChange={(description) =>
|
||||
void actions.updateScene(sid, { description })
|
||||
}
|
||||
onImportPreview={() => void actions.importScenePreview(sid)}
|
||||
onImportPreview={() => {
|
||||
setPreviewBusy(true);
|
||||
void (async () => {
|
||||
try {
|
||||
await actions.importScenePreview(sid);
|
||||
} catch (e) {
|
||||
window.alert(e instanceof Error ? e.message : String(e));
|
||||
} finally {
|
||||
setPreviewBusy(false);
|
||||
}
|
||||
})();
|
||||
}}
|
||||
onClearPreview={() => void actions.clearScenePreview(sid)}
|
||||
onRotatePreview={(previewRotationDeg) =>
|
||||
void actions.updateScene(sid, { previewRotationDeg })
|
||||
@@ -1040,6 +1053,7 @@ type SceneInspectorProps = {
|
||||
previewAssetType: 'image' | 'video' | null;
|
||||
previewVideoAutostart: boolean;
|
||||
previewRotationDeg: 0 | 90 | 180 | 270;
|
||||
previewBusy: boolean;
|
||||
mediaAssets: MediaAsset[];
|
||||
audioRefs: SceneAudioRef[];
|
||||
onAudioRefsChange: (next: SceneAudioRef[]) => void;
|
||||
@@ -1145,6 +1159,7 @@ function SceneInspector({
|
||||
previewAssetType,
|
||||
previewVideoAutostart,
|
||||
previewRotationDeg,
|
||||
previewBusy,
|
||||
mediaAssets,
|
||||
audioRefs,
|
||||
onAudioRefsChange,
|
||||
@@ -1188,6 +1203,14 @@ function SceneInspector({
|
||||
) : (
|
||||
<div className={styles.previewEmpty}>Превью не задано</div>
|
||||
)}
|
||||
{previewBusy ? (
|
||||
<div className={styles.previewBusyOverlay} aria-live="polite">
|
||||
<div className={styles.previewBusyModal}>
|
||||
<div className={styles.previewSpinner} aria-hidden />
|
||||
<div className={styles.previewBusyText}>Загрузка и оптимизация изображения…</div>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
</div>
|
||||
<div className={styles.actionsRow}>
|
||||
<Button variant="primary" onClick={onImportPreview}>
|
||||
|
||||
Reference in New Issue
Block a user