fixed offline mode preparation UX issue

This commit is contained in:
Dmitri 2026-04-30 10:27:40 +02:00
parent 99f126396f
commit 2bc7b64707

View File

@ -15,6 +15,7 @@ import {
mdiCloudDownload,
mdiCloudCheck,
mdiCloudOff,
mdiLoading,
mdiFullscreen,
mdiFullscreenExit,
mdiDelete,
@ -61,6 +62,27 @@ const buttonColors = {
},
};
/**
* Keyframes for spin animation (injected once)
*/
const spinKeyframes = `
@keyframes runtime-controls-spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`;
// Inject keyframes into document head (only once)
if (typeof document !== 'undefined') {
const styleId = 'runtime-controls-spin-style';
if (!document.getElementById(styleId)) {
const style = document.createElement('style');
style.id = styleId;
style.textContent = spinKeyframes;
document.head.appendChild(style);
}
}
/**
* Icon component using fixed pixel sizes
*/
@ -68,10 +90,12 @@ function ControlIcon({
path,
size = 20,
fill = 'currentColor',
spinning = false,
}: {
path: string;
size?: number;
fill?: string;
spinning?: boolean;
}) {
return (
<svg
@ -81,6 +105,7 @@ function ControlIcon({
style={{
display: 'inline-block',
flexShrink: 0,
animation: spinning ? 'runtime-controls-spin 1s linear infinite' : undefined,
}}
>
<path fill={fill} d={path} />
@ -97,12 +122,14 @@ function ControlButton({
onClick,
disabled = false,
title,
spinning = false,
}: {
icon: string;
color?: 'info' | 'success' | 'danger' | 'warning';
onClick: () => void;
disabled?: boolean;
title?: string;
spinning?: boolean;
}) {
const colors = buttonColors[color];
@ -140,7 +167,7 @@ function ControlButton({
e.currentTarget.style.borderColor = colors.border;
}}
>
<ControlIcon path={icon} size={20} />
<ControlIcon path={icon} size={20} spinning={spinning} />
</button>
);
}
@ -267,19 +294,21 @@ function OfflineControl({
}
};
// Determine icon and color
// Determine icon, color, and spinning state
let icon = mdiCloudDownload;
let color: 'info' | 'success' | 'danger' | 'warning' = 'info';
let title = 'Download for offline';
let spinning = false;
if (isDownloaded) {
icon = mdiCloudCheck;
color = 'success';
title = 'Available offline';
} else if (isDownloading) {
icon = mdiCloudDownload;
icon = mdiLoading;
color = 'info';
title = `Downloading ${progress}%`;
spinning = true;
} else if (status === 'error') {
icon = mdiCloudOff;
color = 'danger';
@ -304,6 +333,7 @@ function OfflineControl({
onClick={handleClick}
disabled={!canStore(estimatedSize) && !isDownloaded}
title={title}
spinning={spinning}
/>
{isDownloaded && (
<DeleteButton