fixed offline mode preparation UX issue
This commit is contained in:
parent
99f126396f
commit
2bc7b64707
@ -15,6 +15,7 @@ import {
|
|||||||
mdiCloudDownload,
|
mdiCloudDownload,
|
||||||
mdiCloudCheck,
|
mdiCloudCheck,
|
||||||
mdiCloudOff,
|
mdiCloudOff,
|
||||||
|
mdiLoading,
|
||||||
mdiFullscreen,
|
mdiFullscreen,
|
||||||
mdiFullscreenExit,
|
mdiFullscreenExit,
|
||||||
mdiDelete,
|
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
|
* Icon component using fixed pixel sizes
|
||||||
*/
|
*/
|
||||||
@ -68,10 +90,12 @@ function ControlIcon({
|
|||||||
path,
|
path,
|
||||||
size = 20,
|
size = 20,
|
||||||
fill = 'currentColor',
|
fill = 'currentColor',
|
||||||
|
spinning = false,
|
||||||
}: {
|
}: {
|
||||||
path: string;
|
path: string;
|
||||||
size?: number;
|
size?: number;
|
||||||
fill?: string;
|
fill?: string;
|
||||||
|
spinning?: boolean;
|
||||||
}) {
|
}) {
|
||||||
return (
|
return (
|
||||||
<svg
|
<svg
|
||||||
@ -81,6 +105,7 @@ function ControlIcon({
|
|||||||
style={{
|
style={{
|
||||||
display: 'inline-block',
|
display: 'inline-block',
|
||||||
flexShrink: 0,
|
flexShrink: 0,
|
||||||
|
animation: spinning ? 'runtime-controls-spin 1s linear infinite' : undefined,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<path fill={fill} d={path} />
|
<path fill={fill} d={path} />
|
||||||
@ -97,12 +122,14 @@ function ControlButton({
|
|||||||
onClick,
|
onClick,
|
||||||
disabled = false,
|
disabled = false,
|
||||||
title,
|
title,
|
||||||
|
spinning = false,
|
||||||
}: {
|
}: {
|
||||||
icon: string;
|
icon: string;
|
||||||
color?: 'info' | 'success' | 'danger' | 'warning';
|
color?: 'info' | 'success' | 'danger' | 'warning';
|
||||||
onClick: () => void;
|
onClick: () => void;
|
||||||
disabled?: boolean;
|
disabled?: boolean;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
spinning?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const colors = buttonColors[color];
|
const colors = buttonColors[color];
|
||||||
|
|
||||||
@ -140,7 +167,7 @@ function ControlButton({
|
|||||||
e.currentTarget.style.borderColor = colors.border;
|
e.currentTarget.style.borderColor = colors.border;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ControlIcon path={icon} size={20} />
|
<ControlIcon path={icon} size={20} spinning={spinning} />
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -267,19 +294,21 @@ function OfflineControl({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// Determine icon and color
|
// Determine icon, color, and spinning state
|
||||||
let icon = mdiCloudDownload;
|
let icon = mdiCloudDownload;
|
||||||
let color: 'info' | 'success' | 'danger' | 'warning' = 'info';
|
let color: 'info' | 'success' | 'danger' | 'warning' = 'info';
|
||||||
let title = 'Download for offline';
|
let title = 'Download for offline';
|
||||||
|
let spinning = false;
|
||||||
|
|
||||||
if (isDownloaded) {
|
if (isDownloaded) {
|
||||||
icon = mdiCloudCheck;
|
icon = mdiCloudCheck;
|
||||||
color = 'success';
|
color = 'success';
|
||||||
title = 'Available offline';
|
title = 'Available offline';
|
||||||
} else if (isDownloading) {
|
} else if (isDownloading) {
|
||||||
icon = mdiCloudDownload;
|
icon = mdiLoading;
|
||||||
color = 'info';
|
color = 'info';
|
||||||
title = `Downloading ${progress}%`;
|
title = `Downloading ${progress}%`;
|
||||||
|
spinning = true;
|
||||||
} else if (status === 'error') {
|
} else if (status === 'error') {
|
||||||
icon = mdiCloudOff;
|
icon = mdiCloudOff;
|
||||||
color = 'danger';
|
color = 'danger';
|
||||||
@ -304,6 +333,7 @@ function OfflineControl({
|
|||||||
onClick={handleClick}
|
onClick={handleClick}
|
||||||
disabled={!canStore(estimatedSize) && !isDownloaded}
|
disabled={!canStore(estimatedSize) && !isDownloaded}
|
||||||
title={title}
|
title={title}
|
||||||
|
spinning={spinning}
|
||||||
/>
|
/>
|
||||||
{isDownloaded && (
|
{isDownloaded && (
|
||||||
<DeleteButton
|
<DeleteButton
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user