fix(desktop): place private lake modules and sleep idle layers

This commit is contained in:
冰朔 2026-08-16 23:39:52 +08:00
commit e6d45eaea8
4 changed files with 36 additions and 10 deletions

View file

@ -7,6 +7,8 @@ const styles = fs.readFileSync(new URL('../src/styles.css', import.meta.url), 'u
test('ambient lake motion sleeps by default and wakes only after human interaction', () => {
assert.match(source, /const \[motionAwake, setMotionAwake\] = useState\(false\)/)
assert.match(source, /function LakeAtmosphere\(\{ awake \}: \{ awake: boolean \}\)/)
assert.match(source, /\{awake && <div className="world-shimmer"/)
assert.match(source, /onPointerMove=\{wakeAmbientMotion\}/)
assert.match(source, /onPointerDown=\{wakeAmbientMotion\}/)
assert.match(source, /onKeyDown=\{wakeAmbientMotion\}/)

View file

@ -21,10 +21,23 @@ test('the verified Zhizhi route unfolds through her exact private nesting', () =
test('the Eternal Lake Heart system body exposes both owned branches before channel tools', () => {
assert.match(source, /title="心跳核心频道" meta="冰朔 · 私人频道"/)
assert.match(source, /title="爱之核心子系统" meta="责任主体 · 之之"/)
assert.match(source, /title="光之湖" meta="人格体居所"/)
assert.match(source, /worldStage === 'heartbeat'/)
assert.match(source, /<h1>心跳核心频道<\/h1>/)
})
test('knowledge belongs to Heartbeat Core while persona repositories belong to Light Lake', () => {
const heartbeatStart = source.indexOf("worldStage === 'heartbeat'")
const lightLakeStart = source.indexOf("worldStage === 'lightLake'", heartbeatStart)
const toolStart = source.indexOf("worldStage === 'tool'", lightLakeStart)
const heartbeat = source.slice(heartbeatStart, lightLakeStart)
const lightLake = source.slice(lightLakeStart, toolStart)
assert.match(heartbeat, /title="知识空间"/)
assert.doesNotMatch(heartbeat, /人格体代码仓库|title="光之湖"/)
assert.match(lightLake, /<h1>光之湖<\/h1>/)
assert.match(lightLake, /title="人格体代码仓库"/)
})
test('Fifth Domain human numbers are paired with their own login account', () => {
assert.match(source, /'ICE-GL∞': 'bingshuo'/)
assert.match(source, /'ICE-GL-ZHI∞': 'zhizhi'/)

View file

@ -49,7 +49,7 @@ import './styles.css'
type ThemeId = 'night' | 'dawn' | 'nebula' | 'candle' | 'clear'
type ViewId = 'overview' | 'knowledge' | 'code' | 'receipts' | 'system'
type WorldStage = 'domain' | 'heart' | 'heartbeat' | 'love' | 'tomorrow' | 'bottle' | 'channel' | 'tool'
type WorldStage = 'domain' | 'heart' | 'heartbeat' | 'lightLake' | 'love' | 'tomorrow' | 'bottle' | 'channel' | 'tool'
type KnowledgeSource = 'native' | 'legacy'
interface HomeStatus {
@ -278,17 +278,17 @@ const glintPoints = Array.from({ length: 58 }, (_, index) => ({
delay: (index % 11) * .43,
}))
function LakeAtmosphere() {
function LakeAtmosphere({ awake }: { awake: boolean }) {
return <>
<div className="world-sky" aria-hidden="true">
<i className="world-nebula"/>
{starPoints.map(([left, top, size, duration], index) => <i className="world-star" key={index} style={{ left: `${left}%`, top: `${top}%`, width: size, height: size, '--star-duration': `${duration}s`, '--star-delay': `${index * .37}s` } as React.CSSProperties}/>) }
</div>
<div className="world-mist" aria-hidden="true"/>
<div className="world-shimmer" aria-hidden="true">
{awake && <div className="world-shimmer" aria-hidden="true">
<i className="world-shine cool"/><i className="world-shine warm"/>
{glintPoints.map((point, index) => <i className={`world-glint ${point.warm ? 'warm' : 'cool'}`} key={index} style={{ left: `${point.left}%`, top: `${point.top}%`, width: point.size, height: point.size, '--glint-duration': `${point.duration}s`, '--glint-delay': `${point.delay}s` } as React.CSSProperties}/>) }
</div>
</div>}
</>
}
@ -424,6 +424,7 @@ function HoloLakeApp() {
const [theme, setTheme] = useState<ThemeId>(() => (window.localStorage.getItem('hololake-theme') as ThemeId) || 'night')
const [view, setView] = useState<ViewId>('overview')
const [worldStage, setWorldStage] = useState<WorldStage>('domain')
const [toolReturnStage, setToolReturnStage] = useState<WorldStage>('channel')
const [status, setStatus] = useState<HomeStatus>(previewStatus)
const [personal, setPersonal] = useState<PersonalChannelSnapshot>(previewPersonal)
const [knowledge, setKnowledge] = useState<KnowledgeSnapshot>(previewKnowledge)
@ -1239,6 +1240,7 @@ function HoloLakeApp() {
const openWorldTool = (nextView: ViewId) => {
setView(nextView)
setToolReturnStage(worldStage === 'tool' ? 'channel' : worldStage)
setWorldStage('tool')
}
@ -1249,7 +1251,7 @@ function HoloLakeApp() {
const resolvedDomain = zeroPoint?.resolvedDomain || ''
const activeGate = domainGates.find((gate) => gate.domain === activeDomainInfo)
return <div className={`official-world${motionAwake ? ' motion-awake' : ''}${loginRising ? ' sinking' : ''}`} onPointerMove={wakeAmbientMotion} onPointerDown={wakeAmbientMotion} onKeyDown={wakeAmbientMotion}>
<LakeAtmosphere/>
<LakeAtmosphere awake={motionAwake}/>
<header className="world-titlebar"><b>HoloLake</b><button type="button" aria-label="显示主题" onClick={() => setTheme(themes[(themes.findIndex((item) => item.id === theme) + 1) % themes.length].id)}></button></header>
<main className={`world-scene${gateRising ? ' resolving' : ''}${gateStage === 'key' ? ' resolved' : ''}`}>
<div className="official-hero"><h1> · </h1><p>GH-AIOS · GUANGHU AI OPERATING SYSTEM</p></div>
@ -1308,10 +1310,8 @@ function HoloLakeApp() {
}
const isZhizhi = repoLogin.domain === 'FIFTH_DOMAIN' && zeroPoint?.userNumber === 'ICE-GL-ZHI∞'
const toolReturnStage: WorldStage = isZhizhi ? 'tomorrow' : repoLogin.domain === 'FIFTH_DOMAIN' ? 'heartbeat' : 'channel'
return <div className={`official-world signed-in-world${motionAwake ? ' motion-awake' : ''}`} onPointerMove={wakeAmbientMotion} onPointerDown={wakeAmbientMotion} onKeyDown={wakeAmbientMotion}>
<LakeAtmosphere/>
<LakeAtmosphere awake={motionAwake}/>
<header className="world-titlebar"><b>HoloLake</b><div className="world-title-actions"><span>{repoLogin.username} · {domainDisplayName(repoLogin.domain)}</span><button type="button" onClick={() => setTheme(themes[(themes.findIndex((item) => item.id === theme) + 1) % themes.length].id)}></button><button type="button" onClick={() => void signOutRepo()}>退</button></div></header>
<main className="world-scene signed-in-scene">
{worldStage === 'domain' && <section className="domain-home">
@ -1352,6 +1352,7 @@ function HoloLakeApp() {
{repoLogin.domain === 'FIFTH_DOMAIN' ? <>
<LakePool className="channel-main" title="奶瓶频道" meta="光湖奶瓶小宝宝系统 · 私人" open onClick={() => setWorldStage('bottle')}/>
<LakePool className="channel-knowledge system-branch-heartbeat" title="心跳核心频道" meta="冰朔 · 私人频道" open onClick={() => setWorldStage('heartbeat')}/>
<LakePool className="channel-code system-branch-light-lake" title="光之湖" meta="人格体居所" onClick={() => setWorldStage('lightLake')}/>
<LakePool className="channel-light system-branch-love" title="爱之核心子系统" meta="责任主体 · 之之" onClick={() => setWorldStage('love')}/>
<LakePool className="channel-status" title="湖面天气" meta={connectionLabel} onClick={() => openWorldTool('system')}/>
</> : <>
@ -1367,8 +1368,13 @@ function HoloLakeApp() {
<div className="world-location"><h1></h1><p> · ICE-GL · </p></div>
<LakePool className="channel-main" title="频道全景" meta="心跳核心频道" open onClick={() => openWorldTool('overview')}/>
<LakePool className="channel-knowledge" title="知识空间" meta={`${knowledge.uniqueDocumentCount} 唯一页`} onClick={() => openWorldTool('knowledge')}/>
<LakePool className="channel-code" title="人格代码频道" meta={`${codeChannels.channels.length} 个仓库`} onClick={() => openWorldTool('code')}/>
<LakePool className="channel-light" title="光之湖" meta="人格体居所" onClick={() => openWorldTool('receipts')}/>
<LakePool className="channel-status" title="湖面天气" meta={connectionLabel} onClick={() => openWorldTool('system')}/>
</section>}
{worldStage === 'lightLake' && repoLogin.domain === 'FIFTH_DOMAIN' && <section className="channel-world light-lake-world">
<button className="world-back" type="button" onClick={() => setWorldStage('channel')}> 退</button>
<div className="world-location"><h1></h1><p> · AGE </p></div>
<LakePool className="channel-main" title="人格体居所" meta="光之湖" open onClick={() => openWorldTool('receipts')}/>
<LakePool className="channel-code" title="人格体代码仓库" meta={`${codeChannels.channels.length} 个仓库`} onClick={() => openWorldTool('code')}/>
<LakePool className="channel-status" title="湖面天气" meta={connectionLabel} onClick={() => openWorldTool('system')}/>
</section>}
{worldStage === 'tool' && <section className={`world-tool world-tool-${view}`}>

View file

@ -589,6 +589,11 @@ svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-lineca
.official-world.motion-awake .pool-halo { animation: world-pool-breathe 5.8s ease-in-out infinite; }
.official-world.motion-awake .pool-ring { animation: world-ripple 5.5s ease-out infinite; }
.official-world.motion-awake .nucleus-locus i { animation: world-pool-breathe 5.2s ease-in-out infinite; }
.official-world:not(.motion-awake) .world-nebula,
.official-world:not(.motion-awake) .world-mist,
.official-world:not(.motion-awake) .pool-halo,
.official-world:not(.motion-awake) .nucleus-locus i { filter: none; }
.official-world:not(.motion-awake) .world-titlebar { backdrop-filter: none; -webkit-backdrop-filter: none; background: color-mix(in srgb, var(--surface-sky) 92%, transparent); }
.official-hero { position: absolute; z-index: 10; top: 26px; left: 0; right: 0; text-align: center; }
.official-hero h1 { margin: 0; color: var(--content-primary); font-size: clamp(24px, 3vw, 34px); font-weight: 700; letter-spacing: .09em; }