Download app/src/load-dialog.mjs from Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP: direct link, hf CLI and curl.
- Browser
- Download file 3.65 kB
-
https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/app/src/load-dialog.mjs
- Command line
-
hf download hf://spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/app/src/load-dialog.mjs
-
curl -L -o load-dialog.mjs https://huggingface.co/spaces/Mike0021/MiniCPM5-2B-WebGPU-Pi-HTTP/resolve/main/app/src/load-dialog.mjs
3.65 kB
| import { playCatSound } from './cat-sound.mjs'; | |
| // Native modal dialog provides focus trapping, background inertness and Escape. | |
| export function createLoadDialog(dialog, { onClose }) { | |
| const find = selector => dialog.querySelector(selector); | |
| const confirm = find('#model-confirm'), cancel = find('#model-cancel'); | |
| const error = find('#model-error'); | |
| const cat = find('.setup-cat img'); | |
| const figure = cat.parentElement, tail = find('.setup-cat-tail'); | |
| const reducedMotion = matchMedia('(prefers-reduced-motion: reduce)'); | |
| let tailReaction; | |
| function stopCatReaction() { tailReaction?.cancel(); tailReaction = undefined; } | |
| figure.onpointerdown = event => event.preventDefault(); | |
| figure.onmousedown = event => event.preventDefault(); | |
| figure.onclick = () => { | |
| playCatSound(); | |
| if (!dialog.open || document.hidden || reducedMotion.matches || !figure.classList.contains('is-ready')) return; | |
| const pose = getComputedStyle(tail).transform; | |
| stopCatReaction(); | |
| // Restart the idle rest period so it meets the click animation at neutral. | |
| const idle = tail.getAnimations().find(animation => animation.animationName === 'setup-tail-swish'); | |
| if (idle) idle.currentTime = 0; | |
| tailReaction = tail.animate([ | |
| { transform: pose }, | |
| { transform: 'rotate(-7deg)', offset: .3 }, | |
| { transform: 'rotate(4deg)', offset: .6 }, | |
| { transform: 'rotate(-1deg)', offset: .82 }, | |
| { transform: 'rotate(0deg)' }, | |
| ], { id: 'cat-tail-reaction', duration: 1200, easing: 'ease-in-out' }); | |
| tailReaction.onfinish = () => { tailReaction = undefined; }; | |
| }; | |
| dialog.addEventListener('close', stopCatReaction); | |
| // The HTML preloads the sprite; decode it now, including on a warm cache hit. | |
| // A slow or failed image must never hold up model setup. | |
| void cat.decode().then(() => { | |
| // Both layers reuse the decoded, preloaded sprite; no second asset download. | |
| cat.parentElement.style.setProperty('--cat-sprite', `url("${cat.currentSrc || cat.src}")`); | |
| cat.parentElement.classList.add('is-ready'); | |
| }).catch(() => {}); | |
| const syncCatMotion = () => { | |
| dialog.style.setProperty('--cat-play-state', document.hidden ? 'paused' : 'running'); | |
| if (document.hidden || reducedMotion.matches) stopCatReaction(); | |
| }; | |
| document.addEventListener('visibilitychange', syncCatMotion); | |
| reducedMotion.addEventListener('change', syncCatMotion); | |
| syncCatMotion(); | |
| let resolveRequest; | |
| function finish(send) { | |
| if (!resolveRequest) return; | |
| stopCatReaction(); | |
| const resolve = resolveRequest; resolveRequest = undefined; | |
| dialog.close(); onClose(); resolve(send); | |
| } | |
| cancel.onclick = () => finish(false); | |
| dialog.addEventListener('cancel', event => { event.preventDefault(); finish(false); }); | |
| confirm.onclick = () => finish(true); | |
| return { | |
| request(text, { errorMessage } = {}) { | |
| if (resolveRequest) throw Error('Finish the current model setup before sending another message.'); | |
| confirm.textContent = errorMessage ? 'Try again' : 'Load model & send'; | |
| find('#model-title').textContent = errorMessage ? 'Load model' : 'Download model weights'; | |
| find('#model-preview').textContent = text; | |
| error.textContent = errorMessage ?? ''; error.hidden = !errorMessage; | |
| const storageLink = document.querySelector('#open-tab'); | |
| find('#model-open-tab').hidden = !errorMessage || storageLink.hidden; | |
| find('#model-open-tab').href = storageLink.href; | |
| const request = new Promise(resolve => { resolveRequest = resolve; }); | |
| dialog.showModal(); find('.setup-body').scrollTop = 0; confirm.focus(); | |
| return request; | |
| }, | |
| }; | |
| } | |