Repository navigation
Expand file tree
/
Copy pathindex.html
More file actions
142 lines (132 loc) · 4.74 KB
/
Copy pathindex.html
File metadata and controls
142 lines (132 loc) · 4.74 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/png" href="/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>CodeMUX</title>
<!--
首帧前主题引导(必须在任何绘制之前同步执行,所以是经典内联脚本而不是
module —— module 会被 defer 到解析之后,那时首帧可能已经画完)。
主题真值在 daemon 配置里,要等 fetchConfig 往返才拿得到;没有这一步,
深色用户会先看到一帧亮色界面(白闪)再整体翻暗。
源码见 src/lib/themeBoot.ts 的 THEME_BOOT_SCRIPT:两处不一致时
src/lib/themeBoot.test.ts 的「逐字包含」断言会失败。
-->
<script>(function(){try{var r=document.documentElement;var s=null;try{s=window.localStorage.getItem('codemux:theme')}catch(e){}var q=!!(window.matchMedia&&window.matchMedia('(prefers-color-scheme: dark)').matches);var d=s==='Dark'?true:s==='Light'?false:q;r.classList.toggle('dark',d);r.style.colorScheme=d?'dark':'light';r.style.backgroundColor=d?'#111111':'#fcfcfc';r.style.setProperty('--boot-bg',d?'#111111':'#fcfcfc');var h=null;try{h=window.localStorage.getItem('codemux:host')}catch(e){}if(h==='desktop'||h==='browser'||h==='mobile'){r.dataset.host=h}}catch(e){}})();</script>
<style>
/* 启动加载态(与 Electron 主窗口同窗):JS bundle 解析期间 #root 为空,
先展示 logo 扫光加载画面,React 挂载后由选择器自动隐藏并淡出。
不再使用独立 splash 窗口 —— 任务栏/层级/焦点与真实窗口完全一致。 */
/* 底色跟随主题(--boot-bg 由上面的首帧引导脚本按深浅写入,失败时兜底深色):
固定深底会让浅色主题用户看到「深底 → 浅底」的一次跳色,与白闪同源。 */
#boot {
position: fixed;
inset: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
background: var(--boot-bg, #111111);
transition: opacity 0.2s ease-out;
}
/* React 已提交 DOM:自动开始隐藏(双保险,JS 也会切 boot-hidden)。 */
#root:not(:empty) ~ #boot,
#boot.boot-hidden {
opacity: 0;
pointer-events: none;
}
/* 纯 CSS 兜底:JS 半路失败(脚本错误)时,10s 后无论如何让出画面,
避免加载态永动盖住错误信息。 */
#boot {
animation: boot-failsafe 0s linear 10s forwards;
}
@keyframes boot-failsafe {
to {
opacity: 0;
visibility: hidden;
}
}
/* logo 呼吸 + 匀速循环扫光(与产品视觉约定一致;transform 位移,
合成器执行,首启高负载下不掉帧)。 */
.boot-logo-wrap {
position: relative;
width: 96px;
height: 96px;
animation: boot-breathe 3s ease-in-out infinite;
}
@keyframes boot-breathe {
0%,
100% {
opacity: 0.85;
}
50% {
opacity: 1;
}
}
.boot-logo-wrap img {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
user-select: none;
-webkit-user-drag: none;
}
.boot-sweep {
position: absolute;
inset: 0;
overflow: hidden;
-webkit-mask-image: url('/favicon.png');
mask-image: url('/favicon.png');
-webkit-mask-size: cover;
mask-size: cover;
pointer-events: none;
}
.boot-sweep-bar {
position: absolute;
top: 0;
left: -100%;
width: 300%;
height: 100%;
background: linear-gradient(
115deg,
transparent 40%,
rgba(255, 255, 255, 0.16) 47%,
rgba(255, 255, 255, 0.3) 50%,
rgba(255, 255, 255, 0.16) 53%,
transparent 60%
);
animation: boot-sweep 3.2s linear infinite;
will-change: transform;
}
@keyframes boot-sweep {
from {
transform: translateX(66.7%);
}
to {
transform: translateX(-66.7%);
}
}
@media (prefers-reduced-motion: reduce) {
.boot-logo-wrap {
animation: none;
opacity: 0.9;
}
.boot-sweep-bar {
animation: none;
visibility: hidden;
}
}
</style>
</head>
<body>
<div id="root"></div>
<div id="boot" aria-hidden="true">
<div class="boot-logo-wrap">
<img src="/favicon.png" alt="" draggable="false" />
<div class="boot-sweep"><div class="boot-sweep-bar"></div></div>
</div>
</div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>