Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qjclaw-dmg
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
AI-甘富林
qjclaw-dmg
Commits
763794d2
Commit
763794d2
authored
May 22, 2026
by
edy
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix(ui): smooth startup curtain progress
parent
2d5b1d70
Pipeline
#18479
failed
Changes
4
Pipelines
1
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
59 additions
and
15 deletions
+59
-15
App.tsx
apps/ui/src/App.tsx
+12
-3
startupStatus.ts
apps/ui/src/features/shell/startupStatus.ts
+11
-9
shell.css
apps/ui/src/styles/shell.css
+8
-3
startupStatus.test.ts
apps/ui/test/startupStatus.test.ts
+28
-0
No files found.
apps/ui/src/App.tsx
View file @
763794d2
...
...
@@ -65,6 +65,7 @@ import { useHomeNavigation } from "./features/shell/useHomeNavigation";
import
{
TopBar
}
from
"./features/shell/TopBar"
;
import
{
useSidebarModel
}
from
"./features/shell/useSidebarModel"
;
import
{
getNextStartupVisualProgress
,
getStartupCurtainFootnote
,
getStartupCurtainStatus
,
getStartupProgress
,
...
...
@@ -641,7 +642,15 @@ export default function App() {
setVectcutFileBaseUrlDraft
(
drafts
.
vectcutFileBaseUrl
);
setVectcutApiKeyDraft
(
drafts
.
vectcutApiKey
);
},
[
config
]);
const
startupProgress
=
getStartupProgress
(
startupPhase
);
const
startupProgressTarget
=
chatLaunchState
===
"ready"
?
1
:
getStartupProgress
(
startupPhase
);
const
[
visualStartupProgress
,
setVisualStartupProgress
]
=
useState
(
startupProgressTarget
);
useEffect
(()
=>
{
if
(
chatLaunchState
===
"error"
)
{
return
;
}
setVisualStartupProgress
((
currentProgress
)
=>
getNextStartupVisualProgress
(
currentProgress
,
startupProgressTarget
));
},
[
chatLaunchState
,
startupProgressTarget
]);
const
startupCurtainStatus
=
getStartupCurtainStatus
(
startupPhase
,
chatLaunchState
);
const
startupCurtainFootnote
=
getStartupCurtainFootnote
(
chatLaunchState
);
const
{
...
...
@@ -1639,12 +1648,12 @@ export default function App() {
<
div
className=
"startup-overlay-body"
>
{
chatLaunchState
!==
"error"
?
(
<
div
className=
"startup-overlay-progress"
aria
-
hidden=
"true"
>
<
span
style=
{
{
width
:
String
(
Math
.
round
(
s
tartupProgress
*
100
))
+
"%"
}
}
/>
<
span
style=
{
{
width
:
String
(
Math
.
round
(
visualS
tartupProgress
*
100
))
+
"%"
}
}
/>
</
div
>
)
:
null
}
<
div
className=
"startup-overlay-status"
>
<
strong
>
{
startupCurtainStatus
}
</
strong
>
<
span
>
{
startupCurtainFootnote
}
</
span
>
{
startupCurtainFootnote
?
<
span
>
{
startupCurtainFootnote
}
</
span
>
:
null
}
{
chatLaunchState
===
"error"
&&
startupMessage
?
(
<
p
className=
"startup-overlay-detail"
>
{
startupMessage
}
</
p
>
)
:
null
}
...
...
apps/ui/src/features/shell/startupStatus.ts
View file @
763794d2
...
...
@@ -5,12 +5,12 @@ export type WorkspaceStatusTone = "positive" | "warning" | "info"
export
const
startupCurtainCopy
=
{
brandTitle
:
"
\
u5343
\
u5320
\
u00b7
\
u95ee
\
u5929"
,
brandTagline
:
"START YOUR IDEAS"
,
loadingLabel
:
"
\
u6b63
\
u5728
\
u4e3a
\
u60a8
\
u51c6
\
u5907
\
u5bf9
\
u8bdd
\
u73af
\
u5883
"
,
syncingConfig
:
"
\
u6b63
\
u5728
\
u540c
\
u6b65
\
u5de5
\
u4f5c
\
u914d
\
u7f6e
"
,
syncingProjects
:
"
\
u6b63
\
u5728
\
u540c
\
u6b65
\
u9879
\
u76ee
\
u914d
\
u7f6e
"
,
startingRuntime
:
"
\
u6b63
\
u5728
\
u5524
\
u8d77
\
u672c
\
u5730
\
u52a9
\
u624b
"
,
connectingGateway
:
"
\
u6b63
\
u5728
\
u5efa
\
u7acb
\
u5bf9
\
u8bdd
\
u8fde
\
u63a5
"
,
ready
:
"
\
u51c6
\
u5907
\
u5b8c
\
u6210
\
uff0c
\
u6b63
\
u5728
\
u8fdb
\
u5165
\
u5bf9
\
u8bdd
"
,
loadingLabel
:
"
准备中
"
,
syncingConfig
:
"
准备配置
"
,
syncingProjects
:
"
同步项目
"
,
startingRuntime
:
"
启动助手
"
,
connectingGateway
:
"
连接服务
"
,
ready
:
"
即将进入
"
,
errorTitle
:
"
\
u542f
\
u52a8
\
u73af
\
u5883
\
u6682
\
u672a
\
u5c31
\
u7eea"
,
errorFootnote
:
"
\
u8bf7
\
u91cd
\
u65b0
\
u51c6
\
u5907
\
uff1b
\
u5982
\
u4ecd
\
u5931
\
u8d25
\
uff0c
\
u53ef
\
u524d
\
u5f80
\
u8bbe
\
u7f6e
\
u6216
\
u5bfc
\
u51fa
\
u8bca
\
u65ad
\
u7ee7
\
u7eed
\
u6392
\
u67e5
\
u3002"
,
retryHint
:
"
\
u51c6
\
u5907
\
u5931
\
u8d25
\
u540e
\
u53ef
\
u91cd
\
u65b0
\
u5c1d
\
u8bd5
\
uff0c
\
u6216
\
u524d
\
u5f80
\
u8bbe
\
u7f6e
\
u68c0
\
u67e5
\
u5bc6
\
u94a5
\
u4e0e
\
u7f51
\
u7edc
\
u3002"
...
...
@@ -61,6 +61,10 @@ export function getStartupProgress(phase: WorkspaceSummary["startupPhase"] | und
}
}
export
function
getNextStartupVisualProgress
(
currentProgress
:
number
,
targetProgress
:
number
):
number
{
return
Math
.
max
(
currentProgress
,
targetProgress
)
}
export
function
getStartupCurtainStatus
(
phase
:
WorkspaceSummary
[
"startupPhase"
]
|
undefined
,
launchState
:
ChatLaunchState
...
...
@@ -86,7 +90,5 @@ export function getStartupCurtainStatus(
}
export
function
getStartupCurtainFootnote
(
launchState
:
ChatLaunchState
):
string
{
return
launchState
===
"error"
?
startupCurtainCopy
.
errorFootnote
:
startupCurtainCopy
.
loadingLabel
return
launchState
===
"error"
?
startupCurtainCopy
.
errorFootnote
:
""
}
apps/ui/src/styles/shell.css
View file @
763794d2
...
...
@@ -532,7 +532,7 @@
width
:
min
(
500px
,
100%
);
display
:
grid
;
justify-items
:
center
;
gap
:
1
6
px
;
gap
:
1
4
px
;
margin-top
:
34px
;
}
...
...
@@ -550,15 +550,20 @@
border-radius
:
inherit
;
background
:
linear-gradient
(
90deg
,
#69bcff
0%
,
#3f8cff
100%
);
box-shadow
:
0
0
18px
rgba
(
63
,
140
,
255
,
0.28
);
transition
:
width
240ms
ease
;
transition
:
width
1600ms
cubic-bezier
(
0.22
,
1
,
0.36
,
1
)
;
}
.startup-overlay-status
{
min-height
:
24px
;
display
:
grid
;
gap
:
8
px
;
gap
:
6
px
;
justify-items
:
center
;
}
.startup-overlay.error
.startup-overlay-status
{
min-height
:
auto
;
}
.startup-overlay-status
strong
{
color
:
#1f426d
;
font-size
:
16px
;
...
...
apps/ui/test/startupStatus.test.ts
0 → 100644
View file @
763794d2
import
test
from
"node:test"
import
assert
from
"node:assert/strict"
import
{
getNextStartupVisualProgress
,
getStartupCurtainFootnote
,
getStartupCurtainStatus
}
from
"../src/features/shell/startupStatus.ts"
test
(
"startup curtain uses concise one-line loading statuses"
,
()
=>
{
assert
.
equal
(
getStartupCurtainStatus
(
"syncing-config"
,
"starting"
),
"准备配置"
)
assert
.
equal
(
getStartupCurtainStatus
(
"syncing-projects"
,
"starting"
),
"同步项目"
)
assert
.
equal
(
getStartupCurtainStatus
(
"starting-runtime"
,
"starting"
),
"启动助手"
)
assert
.
equal
(
getStartupCurtainStatus
(
"connecting-gateway"
,
"starting"
),
"连接服务"
)
assert
.
equal
(
getStartupCurtainStatus
(
"ready"
,
"ready"
),
"即将进入"
)
assert
.
equal
(
getStartupCurtainStatus
(
undefined
,
"starting"
),
"准备中"
)
})
test
(
"startup curtain only keeps footnote text for errors"
,
()
=>
{
assert
.
equal
(
getStartupCurtainFootnote
(
"starting"
),
""
)
assert
.
equal
(
getStartupCurtainFootnote
(
"error"
).
length
>
0
,
true
)
})
test
(
"visual startup progress advances without retreating"
,
()
=>
{
assert
.
equal
(
getNextStartupVisualProgress
(
0.56
,
0.82
),
0.82
)
assert
.
equal
(
getNextStartupVisualProgress
(
0.82
,
0.24
),
0.82
)
})
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment