Compare commits
No commits in common. "f9d4074d8535e857f57a7e4ba2b82ab284fce040" and "3caae592f191b6aeea3b056d2e139f476c510588" have entirely different histories.
f9d4074d85
...
3caae592f1
@ -971,105 +971,3 @@ span.ant-skeleton-input.ant-skeleton-input-sm.text-skeleton {
|
|||||||
.electron-body .ant-modal-mask {
|
.electron-body .ant-modal-mask {
|
||||||
top: 41px;
|
top: 41px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes h-progress-macos-wave {
|
|
||||||
0% {
|
|
||||||
transform: translateX(-120%);
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
transform: translateX(120%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress {
|
|
||||||
display: inline-block;
|
|
||||||
width: 100%;
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-outer {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-inner {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
width: 100%;
|
|
||||||
flex: 1;
|
|
||||||
overflow: hidden;
|
|
||||||
vertical-align: middle;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-bg,
|
|
||||||
.h-progress-success-bg {
|
|
||||||
position: relative;
|
|
||||||
transition: all 0.3s cubic-bezier(0.78, 0.14, 0.15, 0.86);
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-success-bg {
|
|
||||||
position: absolute;
|
|
||||||
inset-block-start: 0;
|
|
||||||
inset-inline-start: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-bg-active::after {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
border-radius: inherit;
|
|
||||||
pointer-events: none;
|
|
||||||
background: linear-gradient(
|
|
||||||
90deg,
|
|
||||||
rgba(255, 255, 255, 0) 0%,
|
|
||||||
rgba(255, 255, 255, 0.08) 18%,
|
|
||||||
rgba(255, 255, 255, 0.42) 50%,
|
|
||||||
rgba(255, 255, 255, 0.08) 82%,
|
|
||||||
rgba(255, 255, 255, 0) 100%
|
|
||||||
);
|
|
||||||
width: 55%;
|
|
||||||
animation: h-progress-macos-wave 1.6s ease-in-out infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-text {
|
|
||||||
display: inline-block;
|
|
||||||
margin-inline-start: 8px;
|
|
||||||
line-height: 1;
|
|
||||||
width: 2em;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-align: start;
|
|
||||||
vertical-align: middle;
|
|
||||||
word-break: normal;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-text-start {
|
|
||||||
width: max-content;
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-inline-end: 8px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-text-inner {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
margin-inline-start: 0;
|
|
||||||
padding: 0 4px;
|
|
||||||
color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-layout-bottom {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.h-progress-layout-bottom .h-progress-text {
|
|
||||||
width: max-content;
|
|
||||||
margin-inline-start: 0;
|
|
||||||
margin-top: 4px;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -1,11 +1,10 @@
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
import { Button, Flex, Modal, Typography, theme, Divider } from 'antd'
|
import { Button, Flex, Modal, Progress, Typography, theme, Divider } from 'antd'
|
||||||
|
|
||||||
import CloudIcon from '../../../Icons/CloudIcon'
|
import CloudIcon from '../../../Icons/CloudIcon'
|
||||||
import HostIcon from '../../../Icons/HostIcon'
|
import HostIcon from '../../../Icons/HostIcon'
|
||||||
import ReloadIcon from '../../../Icons/ReloadIcon'
|
import ReloadIcon from '../../../Icons/ReloadIcon'
|
||||||
import HProgress from '../../common/HProgress'
|
|
||||||
|
|
||||||
import CheckCircleIcon from '../../../Icons/CheckCircleIcon'
|
import CheckCircleIcon from '../../../Icons/CheckCircleIcon'
|
||||||
import XMarkCircleIcon from '../../../Icons/XMarkCircleIcon'
|
import XMarkCircleIcon from '../../../Icons/XMarkCircleIcon'
|
||||||
@ -129,7 +128,7 @@ const UpdateStage = ({ stage, status, percent, detail }) => {
|
|||||||
<Text style={{ flexShrink: 0 }}>{config.labels[resolvedStatus]}</Text>
|
<Text style={{ flexShrink: 0 }}>{config.labels[resolvedStatus]}</Text>
|
||||||
{showProgress && (
|
{showProgress && (
|
||||||
<Flex vertical gap={2} style={{ flex: 1 }}>
|
<Flex vertical gap={2} style={{ flex: 1 }}>
|
||||||
<HProgress
|
<Progress
|
||||||
percent={resolvedPercent}
|
percent={resolvedPercent}
|
||||||
status={getProgressStatus(resolvedStatus)}
|
status={getProgressStatus(resolvedStatus)}
|
||||||
showInfo={typeof resolvedPercent === 'number'}
|
showInfo={typeof resolvedPercent === 'number'}
|
||||||
|
|||||||
@ -1,284 +0,0 @@
|
|||||||
import { forwardRef, useMemo } from 'react'
|
|
||||||
import PropTypes from 'prop-types'
|
|
||||||
import { theme } from 'antd'
|
|
||||||
import CheckCircleFilled from '@ant-design/icons/CheckCircleFilled'
|
|
||||||
import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'
|
|
||||||
|
|
||||||
const validProgress = (progress) => {
|
|
||||||
if (!progress || progress < 0) return 0
|
|
||||||
if (progress > 100) return 100
|
|
||||||
return progress
|
|
||||||
}
|
|
||||||
|
|
||||||
const getSuccessPercent = ({ success, successPercent }) => {
|
|
||||||
if (success && 'progress' in success) return success.progress
|
|
||||||
if (success && 'percent' in success) return success.percent
|
|
||||||
return successPercent
|
|
||||||
}
|
|
||||||
|
|
||||||
const sortGradient = (gradients) => {
|
|
||||||
const entries = Object.keys(gradients)
|
|
||||||
.map((key) => ({
|
|
||||||
key: Number.parseFloat(key.replace(/%/g, '')),
|
|
||||||
value: gradients[key]
|
|
||||||
}))
|
|
||||||
.filter(({ key }) => !Number.isNaN(key))
|
|
||||||
.sort((a, b) => a.key - b.key)
|
|
||||||
|
|
||||||
return entries.map(({ key, value }) => `${value} ${key}%`).join(', ')
|
|
||||||
}
|
|
||||||
|
|
||||||
const resolveStrokeBackground = (strokeColor, direction = 'to right') => {
|
|
||||||
if (!strokeColor) return undefined
|
|
||||||
|
|
||||||
if (typeof strokeColor === 'string') {
|
|
||||||
return strokeColor
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Array.isArray(strokeColor)) {
|
|
||||||
return strokeColor[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
const { from, to, direction: gradientDirection, ...rest } = strokeColor
|
|
||||||
|
|
||||||
if (Object.keys(rest).length > 0) {
|
|
||||||
return `linear-gradient(${gradientDirection || direction}, ${sortGradient(rest)})`
|
|
||||||
}
|
|
||||||
|
|
||||||
return `linear-gradient(${gradientDirection || direction}, ${from}, ${to})`
|
|
||||||
}
|
|
||||||
|
|
||||||
const getBarHeight = ({ size, strokeWidth }) => {
|
|
||||||
if (typeof strokeWidth === 'number') return strokeWidth
|
|
||||||
|
|
||||||
if (size === 'small') return 6
|
|
||||||
if (typeof size === 'number') return size
|
|
||||||
if (Array.isArray(size)) return size[1] ?? 8
|
|
||||||
if (typeof size === 'object' && size?.height != null) return size.height
|
|
||||||
|
|
||||||
return 8
|
|
||||||
}
|
|
||||||
|
|
||||||
const getOuterWidth = ({ size, strokeWidth }) => {
|
|
||||||
if (typeof size === 'number') return size
|
|
||||||
if (Array.isArray(size)) return size[0] ?? -1
|
|
||||||
if (typeof size === 'object' && size?.width != null) return size.width
|
|
||||||
if (strokeWidth) return -1
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
const HProgress = forwardRef(function HProgress(
|
|
||||||
{
|
|
||||||
className,
|
|
||||||
rootClassName,
|
|
||||||
style,
|
|
||||||
percent = 0,
|
|
||||||
success,
|
|
||||||
successPercent,
|
|
||||||
status,
|
|
||||||
showInfo = true,
|
|
||||||
strokeColor,
|
|
||||||
trailColor,
|
|
||||||
strokeLinecap = 'round',
|
|
||||||
strokeWidth,
|
|
||||||
size = 'default',
|
|
||||||
format,
|
|
||||||
percentPosition = {}
|
|
||||||
},
|
|
||||||
ref
|
|
||||||
) {
|
|
||||||
const { token } = theme.useToken()
|
|
||||||
|
|
||||||
const { align: infoAlign = 'end', type: infoPosition = 'outer' } =
|
|
||||||
percentPosition
|
|
||||||
|
|
||||||
const resolvedPercent = validProgress(percent)
|
|
||||||
const resolvedSuccessPercent = getSuccessPercent({ success, successPercent })
|
|
||||||
const successValue =
|
|
||||||
resolvedSuccessPercent == null
|
|
||||||
? undefined
|
|
||||||
: validProgress(resolvedSuccessPercent)
|
|
||||||
|
|
||||||
const percentNumber = Number.parseInt(
|
|
||||||
String(successValue ?? resolvedPercent),
|
|
||||||
10
|
|
||||||
)
|
|
||||||
|
|
||||||
const progressStatus = useMemo(() => {
|
|
||||||
if (status === 'exception' || status === 'success' || status === 'active') {
|
|
||||||
return status
|
|
||||||
}
|
|
||||||
if (percentNumber >= 100) return 'success'
|
|
||||||
return status || 'normal'
|
|
||||||
}, [status, percentNumber])
|
|
||||||
|
|
||||||
const barHeight = getBarHeight({ size, strokeWidth })
|
|
||||||
const outerWidth = getOuterWidth({ size, strokeWidth })
|
|
||||||
const borderRadius =
|
|
||||||
strokeLinecap === 'square' || strokeLinecap === 'butt' ? 0 : barHeight
|
|
||||||
|
|
||||||
const trailBackground = trailColor || token.colorFillSecondary
|
|
||||||
|
|
||||||
const defaultFillColor =
|
|
||||||
progressStatus === 'exception'
|
|
||||||
? token.colorError
|
|
||||||
: progressStatus === 'success'
|
|
||||||
? token.colorSuccess
|
|
||||||
: token.colorPrimary
|
|
||||||
|
|
||||||
const fillBackground =
|
|
||||||
resolveStrokeBackground(strokeColor) || defaultFillColor
|
|
||||||
|
|
||||||
const successBackground =
|
|
||||||
success?.strokeColor || token.colorSuccess
|
|
||||||
|
|
||||||
const textFormatter = format || ((value) => `${value}%`)
|
|
||||||
const progressTextValue = textFormatter(
|
|
||||||
resolvedPercent,
|
|
||||||
successValue ?? undefined
|
|
||||||
)
|
|
||||||
|
|
||||||
const progressInfo = !showInfo ? null : (
|
|
||||||
<span
|
|
||||||
className={[
|
|
||||||
'h-progress-text',
|
|
||||||
infoPosition === 'outer' && infoAlign === 'start'
|
|
||||||
? 'h-progress-text-start'
|
|
||||||
: null
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' ')}
|
|
||||||
title={typeof progressTextValue === 'string' ? progressTextValue : undefined}
|
|
||||||
style={{ color: token.colorText }}
|
|
||||||
>
|
|
||||||
{progressStatus === 'exception' ? (
|
|
||||||
<CloseCircleFilled style={{ color: token.colorError }} />
|
|
||||||
) : progressStatus === 'success' ? (
|
|
||||||
<CheckCircleFilled style={{ color: token.colorSuccess }} />
|
|
||||||
) : (
|
|
||||||
progressTextValue
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
)
|
|
||||||
|
|
||||||
const innerInfo =
|
|
||||||
infoPosition === 'inner' && showInfo ? (
|
|
||||||
<span className='h-progress-text-inner'>{progressTextValue}</span>
|
|
||||||
) : null
|
|
||||||
|
|
||||||
const lineInner = (
|
|
||||||
<div
|
|
||||||
className='h-progress-inner'
|
|
||||||
style={{
|
|
||||||
height: barHeight,
|
|
||||||
backgroundColor: trailBackground,
|
|
||||||
borderRadius
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className={[
|
|
||||||
'h-progress-bg',
|
|
||||||
progressStatus === 'active' ? 'h-progress-bg-active' : null
|
|
||||||
]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' ')}
|
|
||||||
style={{
|
|
||||||
width: `${resolvedPercent}%`,
|
|
||||||
height: barHeight,
|
|
||||||
borderRadius,
|
|
||||||
background: fillBackground,
|
|
||||||
overflow: 'hidden'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{innerInfo}
|
|
||||||
</div>
|
|
||||||
{successValue != null && (
|
|
||||||
<div
|
|
||||||
className='h-progress-success-bg'
|
|
||||||
style={{
|
|
||||||
width: `${successValue}%`,
|
|
||||||
height: barHeight,
|
|
||||||
borderRadius,
|
|
||||||
background: successBackground
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
const isOuterStart = infoPosition === 'outer' && infoAlign === 'start'
|
|
||||||
const isOuterEnd = infoPosition === 'outer' && infoAlign === 'end'
|
|
||||||
const isLayoutBottom =
|
|
||||||
infoPosition === 'outer' && infoAlign === 'center'
|
|
||||||
|
|
||||||
const content = isLayoutBottom ? (
|
|
||||||
<div className='h-progress-layout-bottom'>
|
|
||||||
{lineInner}
|
|
||||||
{progressInfo}
|
|
||||||
</div>
|
|
||||||
) : (
|
|
||||||
<div
|
|
||||||
className='h-progress-outer'
|
|
||||||
style={{ width: outerWidth < 0 ? '100%' : outerWidth }}
|
|
||||||
>
|
|
||||||
{isOuterStart && progressInfo}
|
|
||||||
{lineInner}
|
|
||||||
{isOuterEnd && progressInfo}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className={['h-progress', className, rootClassName]
|
|
||||||
.filter(Boolean)
|
|
||||||
.join(' ')}
|
|
||||||
style={style}
|
|
||||||
role='progressbar'
|
|
||||||
aria-valuemin={0}
|
|
||||||
aria-valuemax={100}
|
|
||||||
aria-valuenow={resolvedPercent}
|
|
||||||
>
|
|
||||||
{content}
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
HProgress.propTypes = {
|
|
||||||
className: PropTypes.string,
|
|
||||||
rootClassName: PropTypes.string,
|
|
||||||
style: PropTypes.object,
|
|
||||||
percent: PropTypes.number,
|
|
||||||
success: PropTypes.shape({
|
|
||||||
percent: PropTypes.number,
|
|
||||||
progress: PropTypes.number,
|
|
||||||
strokeColor: PropTypes.string
|
|
||||||
}),
|
|
||||||
successPercent: PropTypes.number,
|
|
||||||
status: PropTypes.oneOf(['normal', 'exception', 'active', 'success']),
|
|
||||||
showInfo: PropTypes.bool,
|
|
||||||
strokeColor: PropTypes.oneOfType([
|
|
||||||
PropTypes.string,
|
|
||||||
PropTypes.arrayOf(PropTypes.string),
|
|
||||||
PropTypes.object
|
|
||||||
]),
|
|
||||||
trailColor: PropTypes.string,
|
|
||||||
strokeLinecap: PropTypes.oneOf(['butt', 'square', 'round']),
|
|
||||||
strokeWidth: PropTypes.number,
|
|
||||||
size: PropTypes.oneOfType([
|
|
||||||
PropTypes.oneOf(['default', 'small']),
|
|
||||||
PropTypes.number,
|
|
||||||
PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.number, PropTypes.string])),
|
|
||||||
PropTypes.shape({
|
|
||||||
width: PropTypes.number,
|
|
||||||
height: PropTypes.number
|
|
||||||
})
|
|
||||||
]),
|
|
||||||
format: PropTypes.func,
|
|
||||||
percentPosition: PropTypes.shape({
|
|
||||||
align: PropTypes.oneOf(['start', 'center', 'end']),
|
|
||||||
type: PropTypes.oneOf(['inner', 'outer'])
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default HProgress
|
|
||||||
@ -1,8 +1,7 @@
|
|||||||
// PrinterSelect.js
|
// PrinterSelect.js
|
||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import { Flex, Space, Modal, Button, Typography } from 'antd'
|
import { Progress, Flex, Space, Modal, Button, Typography } from 'antd'
|
||||||
import StateTag from './StateTag'
|
import StateTag from './StateTag'
|
||||||
import HProgress from './HProgress'
|
|
||||||
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
|
import InfoCircleIcon from '../../Icons/InfoCircleIcon'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
|
||||||
@ -44,7 +43,7 @@ const StateDisplay = ({
|
|||||||
currentState?.progress &&
|
currentState?.progress &&
|
||||||
progressValue !== 100 &&
|
progressValue !== 100 &&
|
||||||
currentState?.progress > 0 ? (
|
currentState?.progress > 0 ? (
|
||||||
<HProgress
|
<Progress
|
||||||
percent={progressValue}
|
percent={progressValue}
|
||||||
status={
|
status={
|
||||||
activeProgressTypes.includes(currentState.type) ? 'active' : ''
|
activeProgressTypes.includes(currentState.type) ? 'active' : ''
|
||||||
|
|||||||
@ -71,11 +71,7 @@ const formatFullAppVersion = (version, buildNumber) => {
|
|||||||
|
|
||||||
const build = String(buildNumber || '').trim()
|
const build = String(buildNumber || '').trim()
|
||||||
const buildSuffix =
|
const buildSuffix =
|
||||||
!build || build === 'dev'
|
!build || build === 'dev' ? 'dev' : build.startsWith('b') ? build : `b${build}`
|
||||||
? 'dev'
|
|
||||||
: build.startsWith('b')
|
|
||||||
? build
|
|
||||||
: `b${build}`
|
|
||||||
|
|
||||||
return `v${normalizedVersion}-${buildSuffix}`
|
return `v${normalizedVersion}-${buildSuffix}`
|
||||||
}
|
}
|
||||||
@ -490,7 +486,6 @@ export const AppUpdateProvider = ({ children }) => {
|
|||||||
style={{ maxWidth: 430 }}
|
style={{ maxWidth: 430 }}
|
||||||
centered
|
centered
|
||||||
maskClosable
|
maskClosable
|
||||||
closable={false}
|
|
||||||
onOk={() => setNoUpdateOpen(false)}
|
onOk={() => setNoUpdateOpen(false)}
|
||||||
onCancel={() => setNoUpdateOpen(false)}
|
onCancel={() => setNoUpdateOpen(false)}
|
||||||
footer={[
|
footer={[
|
||||||
@ -550,7 +545,6 @@ export const AppUpdateProvider = ({ children }) => {
|
|||||||
open={Boolean(completedUpdate)}
|
open={Boolean(completedUpdate)}
|
||||||
style={{ maxWidth: 430 }}
|
style={{ maxWidth: 430 }}
|
||||||
centered
|
centered
|
||||||
closable={false}
|
|
||||||
onCancel={() => setCompletedUpdate(null)}
|
onCancel={() => setCompletedUpdate(null)}
|
||||||
footer={[
|
footer={[
|
||||||
<Button
|
<Button
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user