Files
boundless/index.html
吴璨 fad9760265 自部署多端同步:服务端、实时协作、口令登录与油画加载动画
- 新增 Node 服务端(Hono + Hocuspocus + node:sqlite),数据保存在服务器
- 基于 Yjs 的多端实时同步,本机 IndexedDB 离线缓存,撤销只针对本机操作
- 空间(标签)有独立地址,增删改通过接口同步到所有设备
- 口令登录(签名 Cookie 会话、登录限流、同源校验)
- 图片上传到服务器,过大照片上传前自动压缩
- 历史版本(自动/手动保存、一键恢复)、跨空间搜索、在线设备
- 随机油画加载动画(Painting Loaders,本地收录 p5 / p5.brush)
- 选中样式与拖拽性能优化:拖动结束后才同步位置
- Docker / docker-compose 部署,README 与 CLAUDE.md 更新
2026-10-21 18:09:03 +08:00

100 lines
3.1 KiB
HTML

<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<link rel="icon" href="/icon.svg" type="image/svg+xml">
<link rel="apple-touch-icon" href="/icon.svg">
<link rel="manifest" href="/manifest.webmanifest">
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover">
<meta name="theme-color" content="#f4f3ee">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-title" content="无界笺">
<meta name="description" content="无界笺是一张可以无限延伸、在所有设备间同步的灵感平面。">
<title>无界笺 · Boundless</title>
<style>
/* 启动画面:在主程序下载完成之前就显示,样式内联避免闪烁 */
#boot {
position: fixed;
inset: 0;
z-index: 1000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 22px;
background: #f4f3ee;
color: #7b7b73;
font-family: Georgia, 'Songti SC', 'STSong', serif;
transition: opacity 480ms ease;
}
#boot.boot--gone {
opacity: 0;
pointer-events: none;
}
#boot .boot__tile {
position: relative;
width: min(232px, 58vw);
aspect-ratio: 1;
overflow: hidden;
border: 1px solid rgba(29, 30, 29, 0.08);
border-radius: 14px;
background: #efebe2;
box-shadow: 0 1px 2px rgba(27, 26, 23, 0.04), 0 18px 40px -22px rgba(27, 26, 23, 0.32);
transition: background 600ms ease;
}
#boot iframe {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
border: 0;
opacity: 0;
transition: opacity 600ms ease;
}
#boot.boot--painting iframe {
opacity: 1;
}
#boot .boot__text {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
font-size: 13px;
letter-spacing: 0.06em;
}
#boot .boot__caption {
min-height: 1.2em;
color: #a3a39a;
font-size: 11px;
font-style: italic;
letter-spacing: 0.04em;
opacity: 0;
transition: opacity 600ms ease;
}
#boot.boot--painting .boot__caption {
opacity: 1;
}
</style>
</head>
<body>
<div id="boot" role="status" aria-live="polite">
<div class="boot__tile" aria-hidden="true">
<iframe src="/painterly/index.html" title="加载动画" tabindex="-1"></iframe>
</div>
<div class="boot__text">
<span class="boot__status">正在展开你的平面…</span>
<span class="boot__caption"></span>
</div>
</div>
<script>
// 保护:页面被嵌进 iframe 时不再嵌套加载动画,避免无限递归
if (window.top !== window.self) {
document.querySelector('#boot iframe')?.remove()
}
</script>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>