mirror of
https://github.com/Novattz/creamlinux-installer.git
synced 2026-08-01 19:18:25 -04:00
new spinner
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
import { FC, ButtonHTMLAttributes } from 'react'
|
||||
import Spinner from '@/components/common/Spinner'
|
||||
|
||||
export type ButtonVariant = 'primary' | 'secondary' | 'danger' | 'success' | 'warning'
|
||||
export type ButtonSize = 'small' | 'medium' | 'large'
|
||||
@@ -58,7 +59,7 @@ const Button: FC<ButtonProps> = ({
|
||||
>
|
||||
{isLoading && (
|
||||
<span className="btn-spinner">
|
||||
<span className="spinner"></span>
|
||||
<Spinner />
|
||||
</span>
|
||||
)}
|
||||
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
import { ReactNode } from 'react'
|
||||
import Spinner from './Spinner'
|
||||
|
||||
export type LoadingType = 'spinner' | 'dots' | 'progress'
|
||||
export type LoadingType = 'spinner' | 'dots'
|
||||
export type LoadingSize = 'small' | 'medium' | 'large'
|
||||
|
||||
interface LoadingIndicatorProps {
|
||||
size?: LoadingSize
|
||||
type?: LoadingType
|
||||
message?: string
|
||||
progress?: number
|
||||
className?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Versatile loading indicator component
|
||||
* Supports multiple visual styles and sizes
|
||||
* Supports multiple visual styles and sizes.
|
||||
* For a progress bar, use ProgressBar or ProgressDialog's progress bar instead.
|
||||
*/
|
||||
const LoadingIndicator = ({
|
||||
size = 'medium',
|
||||
type = 'spinner',
|
||||
message,
|
||||
progress = 0,
|
||||
className = '',
|
||||
}: LoadingIndicatorProps) => {
|
||||
// Size class mapping
|
||||
@@ -33,7 +33,7 @@ const LoadingIndicator = ({
|
||||
const renderLoadingIndicator = (): ReactNode => {
|
||||
switch (type) {
|
||||
case 'spinner':
|
||||
return <div className="loading-spinner"></div>
|
||||
return <Spinner />
|
||||
|
||||
case 'dots':
|
||||
return (
|
||||
@@ -44,21 +44,8 @@ const LoadingIndicator = ({
|
||||
</div>
|
||||
)
|
||||
|
||||
case 'progress':
|
||||
return (
|
||||
<div className="loading-progress">
|
||||
<div className="progress-bar-container">
|
||||
<div
|
||||
className="progress-bar"
|
||||
style={{ width: `${Math.min(Math.max(progress, 0), 100)}%` }}
|
||||
></div>
|
||||
</div>
|
||||
{progress > 0 && <div className="progress-percentage">{Math.round(progress)}%</div>}
|
||||
</div>
|
||||
)
|
||||
|
||||
default:
|
||||
return <div className="loading-spinner"></div>
|
||||
return <Spinner />
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
interface SpinnerProps {
|
||||
className?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Windows/Fluent-style indeterminate ring spinner an SVG circle whose
|
||||
* stroke-dasharray and rotation are animated (see .spinner-ring in
|
||||
* _loading.scss), rather than a CSS conic-gradient mask. Size and color
|
||||
* come from whatever wrapping className/context is passed in.
|
||||
*/
|
||||
const Spinner = ({ className = '' }: SpinnerProps) => (
|
||||
<svg viewBox="0 0 16 16" className={`spinner-ring ${className}`}>
|
||||
<circle cx="8" cy="8" r="7" />
|
||||
</svg>
|
||||
)
|
||||
|
||||
export default Spinner
|
||||
@@ -2,7 +2,10 @@ export { default as LoadingIndicator } from './LoadingIndicator'
|
||||
export { default as ProgressBar } from './ProgressBar'
|
||||
export { default as Dropdown } from './Dropdown'
|
||||
export { default as VotesDisplay } from './VotesDisplay'
|
||||
export { default as EntryList } from './EntryList'
|
||||
export { default as Spinner } from './Spinner'
|
||||
|
||||
export type { LoadingSize, LoadingType } from './LoadingIndicator'
|
||||
export type { DropdownOption } from './Dropdown'
|
||||
export type { GameVotes } from './VotesDisplay'
|
||||
export type { GameVotes } from './VotesDisplay'
|
||||
export type { EntryListProps } from './EntryList'
|
||||
@@ -6,6 +6,7 @@ import DialogFooter from './DialogFooter'
|
||||
import DialogActions from './DialogActions'
|
||||
import AddDlcDialog from './AddDlcDialog'
|
||||
import { Button, AnimatedCheckbox } from '@/components/buttons'
|
||||
import { Spinner } from '@/components/common'
|
||||
import { DlcInfo } from '@/types'
|
||||
import { Icon, check, info } from '@/components/icons'
|
||||
|
||||
@@ -223,7 +224,7 @@ const DlcSelectionDialog = ({
|
||||
</ul>
|
||||
) : (
|
||||
<div className="dlc-loading">
|
||||
<div className="loading-spinner"></div>
|
||||
<Spinner />
|
||||
<p>Loading DLC information...</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { Spinner } from '@/components/common'
|
||||
|
||||
interface InitialLoadingScreenProps {
|
||||
message: string
|
||||
@@ -38,8 +39,7 @@ const InitialLoadingScreen = ({ message, progress }: InitialLoadingScreenProps)
|
||||
<h1>CreamLinux</h1>
|
||||
|
||||
<div className="loading-animation">
|
||||
{/* Spinner animation */}
|
||||
<div className="loading-spinner"></div>
|
||||
<Spinner />
|
||||
</div>
|
||||
|
||||
<p className="loading-message">{message}</p>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useState, useEffect, useCallback } from 'react'
|
||||
import { useState, useEffect, useCallback, useRef } from 'react'
|
||||
import { check } from '@tauri-apps/plugin-updater'
|
||||
import { relaunch } from '@tauri-apps/plugin-process'
|
||||
import { ProgressBar } from '@/components/common'
|
||||
import { ProgressBar, Spinner } from '@/components/common'
|
||||
|
||||
interface UpdateScreenProps {
|
||||
onComplete: () => void
|
||||
@@ -16,6 +16,8 @@ const UpdateScreen = ({ onComplete }: UpdateScreenProps) => {
|
||||
const [downloading, setDownloading] = useState(false)
|
||||
const [progress, setProgress] = useState(0)
|
||||
const [version, setVersion] = useState('')
|
||||
const totalBytesRef = useRef(0)
|
||||
const downloadedBytesRef = useRef(0)
|
||||
|
||||
const checkForUpdates = useCallback(async () => {
|
||||
try {
|
||||
@@ -29,20 +31,22 @@ const UpdateScreen = ({ onComplete }: UpdateScreenProps) => {
|
||||
setVersion(update.version)
|
||||
|
||||
// Download and install the update
|
||||
totalBytesRef.current = 0
|
||||
downloadedBytesRef.current = 0
|
||||
|
||||
await update.downloadAndInstall((event) => {
|
||||
switch (event.event) {
|
||||
case 'Started': {
|
||||
const contentLength = event.data.contentLength
|
||||
console.log(`Started downloading ${contentLength} bytes`)
|
||||
totalBytesRef.current = event.data.contentLength ?? 0
|
||||
console.log(`Started downloading ${totalBytesRef.current} bytes`)
|
||||
break
|
||||
}
|
||||
case 'Progress': {
|
||||
const { chunkLength } = event.data
|
||||
// Calculate cumulative progress
|
||||
setProgress((prev) => {
|
||||
const newProgress = prev + chunkLength
|
||||
return Math.min(newProgress, 100)
|
||||
})
|
||||
downloadedBytesRef.current += event.data.chunkLength
|
||||
// Percentage of total bytes downloaded so far (0 if the server
|
||||
// didn't report a content length)
|
||||
const total = totalBytesRef.current
|
||||
setProgress(total > 0 ? Math.min((downloadedBytesRef.current / total) * 100, 100) : 0)
|
||||
break
|
||||
}
|
||||
case 'Finished':
|
||||
@@ -77,7 +81,7 @@ const UpdateScreen = ({ onComplete }: UpdateScreenProps) => {
|
||||
<h1>CreamLinux</h1>
|
||||
|
||||
<div className="loading-animation">
|
||||
{checking && <div className="loading-spinner"></div>}
|
||||
{checking && <Spinner />}
|
||||
</div>
|
||||
|
||||
<p className="loading-message">
|
||||
|
||||
Reference in New Issue
Block a user