Skip to content

Commit 11ec2c0

Browse files
authored
Update index.html
1 parent 4dbb6a4 commit 11ec2c0

1 file changed

Lines changed: 79 additions & 21 deletions

File tree

index.html

Lines changed: 79 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,21 @@
181181
#media-paths-container .media-icon-label { margin-bottom: 0; flex-shrink: 0; width: 24px; height: 24px; color: var(--secondary-color); display: inline-flex; align-items: center; justify-content: center; }
182182

183183
#scene-editor-preview-wrapper { position: relative; width: 100%; max-width: 720px; margin: 0 auto 25px auto; aspect-ratio: 16 / 9; border: 1px solid var(--border-color); border-radius: 8px; overflow: hidden; background-color: #000; }
184+
#scene-editor-preview-wrapper.is-loading::after {
185+
content: 'Loading...';
186+
position: absolute;
187+
top: 0;
188+
left: 0;
189+
width: 100%;
190+
height: 100%;
191+
display: flex;
192+
justify-content: center;
193+
align-items: center;
194+
background-color: rgba(0, 0, 0, 0.5);
195+
color: white;
196+
font-size: 1.2em;
197+
z-index: 10;
198+
}
184199
#scene-editor-preview { position: absolute; top: 0; left: 0; width: 200%; height: 200%; transform: scale(0.5); transform-origin: top left; overflow: auto; background-color: var(--bg-color); color: var(--text-color); font-family: var(--font-family); font-size: var(--font-size); display: flex; justify-content: center; align-items: center; }
185200
#scene-editor-preview.layout-image-as-bg { align-items: flex-end; }
186201
#scene-editor-preview, #scene-editor-preview #preview-player-inner-container { background-size: cover; background-position: center; }
@@ -829,6 +844,8 @@ <h2 id="about-title"></h2>
829844
currentNavView: 'tree', // 'tree' or 'list'
830845
navViewsDirty: true,
831846
missingAssetWarnings: new Set(),
847+
previewLoadId: 0,
848+
thumbnailLoadId: 0,
832849
player: {
833850
gameState: null,
834851
typewriter: { intervalId: null, skipListener: null }
@@ -930,7 +947,6 @@ <h2 id="about-title"></h2>
930947

931948
document.getElementById('select-image-btn').addEventListener('click', () => App.assets.selectFile('images', 'scene-image'));
932949
document.getElementById('select-sound-btn').addEventListener('click', () => App.assets.selectFile('sounds', 'scene-sound'));
933-
App.elements['scene-image'].addEventListener('change', (e) => App.ui.updateImageThumbnail(e.target.value));
934950
App.elements['scene-sound'].addEventListener('input', (e) => {
935951
const hasSound = !!e.target.value;
936952
const btn = App.elements['toggle-ambience-btn'];
@@ -947,8 +963,11 @@ <h2 id="about-title"></h2>
947963
App.setDirty(true);
948964
});
949965

950-
['scene-text', 'scene-image'].forEach(id => {
951-
App.elements[id].addEventListener('input', () => App.editor.renderPreview());
966+
App.elements['scene-text'].addEventListener('input', () => App.editor.renderPreview());
967+
App.elements['scene-image'].addEventListener('input', (e) => {
968+
// This now correctly triggers updates for BOTH preview and thumbnail on every input change.
969+
App.editor.renderPreview();
970+
App.ui.updateImageThumbnail(e.target.value);
952971
});
953972
App.elements['choices-container'].addEventListener('input', () => { App.editor.renderPreview(); App.setDirty(true); });
954973

@@ -1308,6 +1327,10 @@ <h2 id="about-title"></h2>
13081327
}
13091328
},
13101329
async updateImageThumbnail(path) {
1330+
// 1. Cancellation Token Logic
1331+
App.state.thumbnailLoadId++;
1332+
const currentLoadId = App.state.thumbnailLoadId;
1333+
13111334
const preview = App.elements['image-preview'];
13121335
const icon = preview.querySelector('.thumbnail-fullscreen-icon');
13131336
preview.innerHTML = '';
@@ -1318,7 +1341,15 @@ <h2 id="about-title"></h2>
13181341

13191342
if (!path) return;
13201343
try {
1344+
// Show loading state
1345+
defaultSpan.textContent = 'Loading...';
13211346
const url = await App.io.getAssetDataUrl(path);
1347+
1348+
// 2. Check if the request is still valid
1349+
if (currentLoadId !== App.state.thumbnailLoadId) {
1350+
return; // Abort if a newer request has started
1351+
}
1352+
13221353
if (url) {
13231354
preview.innerHTML = '';
13241355
if(icon) preview.appendChild(icon);
@@ -1329,7 +1360,9 @@ <h2 id="about-title"></h2>
13291360
defaultSpan.textContent = 'Invalid Path';
13301361
}
13311362
} catch (e) {
1332-
defaultSpan.textContent = 'Invalid Path';
1363+
if (currentLoadId === App.state.thumbnailLoadId) {
1364+
defaultSpan.textContent = 'Invalid Path';
1365+
}
13331366
console.warn('Thumbnail load failed:', e);
13341367
}
13351368
},
@@ -2621,31 +2654,56 @@ <h3 style="margin-top:0;">Loading Project</h3>
26212654
this.updatePreviewImage();
26222655
},
26232656
async updatePreviewImage() {
2657+
// 1. Cancellation Token Logic
2658+
App.state.previewLoadId++;
2659+
const currentLoadId = App.state.previewLoadId;
2660+
2661+
const previewWrapper = App.elements['scene-editor-preview-wrapper'];
26242662
const imageEl = document.getElementById('preview-player-image');
26252663
const imageContainerEl = document.getElementById('preview-player-image-container');
26262664
const innerContainer = document.getElementById('preview-player-inner-container');
26272665
const previewContainer = App.elements['scene-editor-preview'];
26282666

2629-
const sceneImage = App.elements['scene-image'].value;
2630-
const meta = App.state.storyData.meta;
2631-
const styles = meta.styles;
2667+
// 2. Add loading state feedback
2668+
previewWrapper.classList.add('is-loading');
26322669

2633-
const sceneImageUrl = await App.io.getAssetDataUrl(sceneImage);
2634-
const globalScreenBgUrl = await App.io.getAssetDataUrl(styles['--screen-bg-image']);
2635-
const containerBgUrl = await App.io.getAssetDataUrl(styles['--container-bg-image']);
2670+
try {
2671+
const sceneImage = App.elements['scene-image'].value;
2672+
const meta = App.state.storyData.meta;
2673+
const styles = meta.styles;
2674+
2675+
// Await all asset URLs
2676+
const [sceneImageUrl, globalScreenBgUrl, containerBgUrl] = await Promise.all([
2677+
App.io.getAssetDataUrl(sceneImage),
2678+
App.io.getAssetDataUrl(styles['--screen-bg-image']),
2679+
App.io.getAssetDataUrl(styles['--container-bg-image'])
2680+
]);
2681+
2682+
// 3. Check if the request is still valid before updating the DOM
2683+
if (currentLoadId !== App.state.previewLoadId) {
2684+
return; // Abort if a newer request has started
2685+
}
26362686

2637-
innerContainer.style.backgroundImage = containerBgUrl ? `url("${containerBgUrl}")` : 'none';
2687+
innerContainer.style.backgroundImage = containerBgUrl ? `url("${containerBgUrl}")` : 'none';
26382688

2639-
if (meta.layout === 'layout-image-as-bg') {
2640-
imageContainerEl.style.display = 'none';
2641-
previewContainer.style.backgroundImage = sceneImageUrl ? `url("${sceneImageUrl}")` : (globalScreenBgUrl ? `url("${globalScreenBgUrl}")` : 'none');
2642-
} else {
2643-
previewContainer.style.backgroundImage = globalScreenBgUrl ? `url("${globalScreenBgUrl}")` : 'none';
2644-
if (sceneImageUrl) {
2645-
imageEl.src = sceneImageUrl;
2646-
imageContainerEl.style.display = 'block';
2647-
} else {
2689+
if (meta.layout === 'layout-image-as-bg') {
26482690
imageContainerEl.style.display = 'none';
2691+
previewContainer.style.backgroundImage = sceneImageUrl ? `url("${sceneImageUrl}")` : (globalScreenBgUrl ? `url("${globalScreenBgUrl}")` : 'none');
2692+
} else {
2693+
previewContainer.style.backgroundImage = globalScreenBgUrl ? `url("${globalScreenBgUrl}")` : 'none';
2694+
if (sceneImageUrl) {
2695+
imageEl.src = sceneImageUrl;
2696+
imageContainerEl.style.display = 'block';
2697+
} else {
2698+
imageContainerEl.style.display = 'none';
2699+
}
2700+
}
2701+
} catch (error) {
2702+
console.error("Failed to update preview image:", error);
2703+
} finally {
2704+
// 4. Always remove loading state, but only if this is the latest request
2705+
if (currentLoadId === App.state.previewLoadId) {
2706+
previewWrapper.classList.remove('is-loading');
26492707
}
26502708
}
26512709
},
@@ -3117,7 +3175,7 @@ <h3 style="margin-top:0;">Loading Project</h3>
31173175
App.elements['ambience-player'].src = ''; App.elements['music-player'].src = '';
31183176
if (App.state.currentSceneId) App.editor.render();
31193177
},
3120-
async toggleAmbienceSound() {
3178+
async toggleAmbienceSound() {
31213179
const audio = App.elements['ambience-player'];
31223180
const soundPath = App.elements['scene-sound'].value;
31233181
if (!soundPath) return;

0 commit comments

Comments
 (0)