fixed offline mode preparation UX issue
This commit is contained in:
parent
99f126396f
commit
2bc7b64707
@ -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
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user