mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-07-03 14:09:06 +02:00
407c9221ce
Signed-off-by: Daniel <845765@qq.com>
427 lines
14 KiB
HTML
427 lines
14 KiB
HTML
<!DOCTYPE html>
|
|
<html>
|
|
<head>
|
|
<title>SiYuan</title>
|
|
<meta charset="UTF-8">
|
|
<meta name="color-scheme" content="light dark">
|
|
<link rel="stylesheet" href="window.css">
|
|
<style>
|
|
/* workspace.html 独有样式,公共样式在 window.css 中 */
|
|
.layout {
|
|
display: flex;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.wsPanel {
|
|
flex: none;
|
|
width: 300px;
|
|
border-right: 1px solid #e0e0e0;
|
|
padding: 24px;
|
|
overflow-y: auto;
|
|
text-align: left;
|
|
box-sizing: border-box;
|
|
background-color: #f6f6f6;
|
|
}
|
|
|
|
.wsTitle {
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
color: rgba(0, 0, 0, .6);
|
|
margin-bottom: 16px;
|
|
}
|
|
|
|
.ws-item {
|
|
padding: 12px;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 12px;
|
|
border-radius: 6px;
|
|
cursor: default;
|
|
}
|
|
|
|
.ws-item:hover {
|
|
background: #dfe0e1;
|
|
}
|
|
|
|
.ws-text {
|
|
flex: 1;
|
|
min-width: 0;
|
|
}
|
|
|
|
.ws-name {
|
|
font-size: 16px;
|
|
color: #222;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.ws-path {
|
|
font-size: 12px;
|
|
color: rgba(0, 0, 0, .6);
|
|
word-break: break-all;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.right {
|
|
flex: 1;
|
|
padding: 0 32px;
|
|
}
|
|
|
|
.ws-open {
|
|
width: auto;
|
|
padding: 2px 12px;
|
|
color: rgba(0, 0, 0, .6);
|
|
background-color: transparent;
|
|
box-shadow: inset 0 0 0 0.6px rgba(0, 0, 0, .25);
|
|
opacity: 0;
|
|
pointer-events: none;
|
|
transition: opacity 120ms ease;
|
|
}
|
|
|
|
.ws-item:hover .ws-open {
|
|
opacity: 1;
|
|
pointer-events: auto;
|
|
}
|
|
|
|
.ws-open:hover, .ws-open:focus {
|
|
color: #222;
|
|
background-color: rgba(0, 0, 0, .06);
|
|
box-shadow: inset 0 0 0 0.6px rgba(0, 0, 0, .4);
|
|
}
|
|
|
|
.ws-open:active {
|
|
box-shadow: inset 0 0 0 0.6px rgba(0, 0, 0, .4);
|
|
}
|
|
|
|
.missing-tip {
|
|
font-size: 18px;
|
|
color: #222;
|
|
text-align: left;
|
|
padding: 0 24px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.missing-path {
|
|
font-size: 14px;
|
|
color: rgba(0, 0, 0, .6);
|
|
margin-top: 8px;
|
|
word-break: break-all;
|
|
}
|
|
|
|
code {
|
|
word-break: break-all;
|
|
}
|
|
|
|
/* 安全模式分支(渲染进程崩溃恢复)独有样式 */
|
|
.crash-tip {
|
|
font-size: 18px;
|
|
color: #222;
|
|
text-align: left;
|
|
padding: 0 24px;
|
|
line-height: 1.6;
|
|
}
|
|
|
|
.crash-log {
|
|
font-size: 12px;
|
|
color: rgba(0, 0, 0, .6);
|
|
background-color: rgba(0, 0, 0, .04);
|
|
border-radius: 6px;
|
|
padding: 8px 12px;
|
|
margin: 12px 0 0;
|
|
max-height: 160px;
|
|
overflow: auto;
|
|
white-space: pre-wrap;
|
|
word-break: break-all;
|
|
}
|
|
|
|
.crash-actions {
|
|
display: flex;
|
|
gap: 16px;
|
|
padding: 24px 0;
|
|
flex-wrap: wrap;
|
|
}
|
|
|
|
.crash-actions .b3-button {
|
|
flex: 1;
|
|
min-width: 180px;
|
|
}
|
|
|
|
.b3-button--safe {
|
|
color: #fff;
|
|
background-color: #3575f0;
|
|
}
|
|
|
|
.b3-button--safe:hover {
|
|
background-color: #2c66e0;
|
|
}
|
|
|
|
/* 次操作按钮:透明背景 + 描边,与主操作(安全模式)形成对比 */
|
|
.b3-button--outline {
|
|
color: rgba(0, 0, 0, .75);
|
|
background-color: transparent;
|
|
box-shadow: inset 0 0 0 0.6px rgba(0, 0, 0, .25);
|
|
}
|
|
|
|
.b3-button--outline:hover, .b3-button--outline:focus {
|
|
color: #222;
|
|
background-color: rgba(0, 0, 0, .06);
|
|
box-shadow: inset 0 0 0 0.6px rgba(0, 0, 0, .4);
|
|
}
|
|
|
|
@media (prefers-color-scheme: dark) {
|
|
.wsPanel {
|
|
background-color: #2c2c2c;
|
|
border-right: 1px solid #363636;
|
|
}
|
|
|
|
.wsTitle {
|
|
color: #9aa0a6;
|
|
}
|
|
|
|
.ws-item:hover {
|
|
background: rgba(255, 255, 255, .075);
|
|
}
|
|
|
|
.ws-name {
|
|
color: #dadada;
|
|
}
|
|
|
|
.ws-path {
|
|
color: #9aa0a6;
|
|
}
|
|
|
|
.ws-open {
|
|
color: #9aa0a6;
|
|
background-color: transparent;
|
|
box-shadow: inset 0 0 0 0.6px rgba(255, 255, 255, .25);
|
|
}
|
|
|
|
.ws-open:hover, .ws-open:focus {
|
|
color: #dadada;
|
|
background-color: rgba(255, 255, 255, .075);
|
|
box-shadow: inset 0 0 0 0.6px rgba(255, 255, 255, .4);
|
|
}
|
|
|
|
.ws-open:active {
|
|
box-shadow: inset 0 0 0 0.6px rgba(255, 255, 255, .4);
|
|
}
|
|
|
|
.missing-tip {
|
|
color: #dadada;
|
|
}
|
|
|
|
.missing-path {
|
|
color: #9aa0a6;
|
|
}
|
|
|
|
.crash-tip {
|
|
color: #dadada;
|
|
}
|
|
|
|
.crash-log {
|
|
color: #9aa0a6;
|
|
background-color: rgba(255, 255, 255, .05);
|
|
}
|
|
|
|
.b3-button--outline {
|
|
color: #9aa0a6;
|
|
background-color: transparent;
|
|
box-shadow: inset 0 0 0 0.6px rgba(255, 255, 255, .25);
|
|
}
|
|
|
|
.b3-button--outline:hover, .b3-button--outline:focus {
|
|
color: #dadada;
|
|
background-color: rgba(255, 255, 255, .075);
|
|
box-shadow: inset 0 0 0 0.6px rgba(255, 255, 255, .4);
|
|
}
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<div id="layout" class="layout">
|
|
<div class="wsPanel">
|
|
<div class="wsTitle" data-i18n="wsTitle"></div>
|
|
<div class="wsList"></div>
|
|
</div>
|
|
<div class="fn__flex-column right">
|
|
<div class="fn__flex-1"></div>
|
|
<img class="icon">
|
|
<h2 data-i18n="title"></h2>
|
|
<div class="slogan" data-i18n="slogan"></div>
|
|
<div class="fn__flex-1"></div>
|
|
<div class="missing-tip">
|
|
<div data-i18n="missingTip"></div>
|
|
<div class="missing-path"><code class="missing"></code></div>
|
|
</div>
|
|
<div class="crash-tip fn__none">
|
|
<div data-i18n="crashTip"></div>
|
|
<pre class="crash-log"></pre>
|
|
<div class="crash-actions">
|
|
<button class="b3-button b3-button--safe safeMode" data-i18n="safeModeBtn"></button>
|
|
<button class="b3-button b3-button--outline normal" data-i18n="normalBtn"></button>
|
|
</div>
|
|
</div>
|
|
<div class="fn__flex-1"></div>
|
|
<div class="notice fn__none emptyHint">
|
|
<span data-i18n="emptyHint"></span>
|
|
</div>
|
|
<label class="b3-label">
|
|
<div>
|
|
<span data-i18n="selectPath"></span>
|
|
<div class="b3-label__text" data-i18n="selectPathDesc"></div>
|
|
</div>
|
|
<div class="fn__flex-1"></div>
|
|
<button class="b3-button fn__flex-center choosePath" data-i18n="selectBtn"></button>
|
|
</label>
|
|
<label class="b3-label">
|
|
<div>
|
|
<span data-i18n="lang"></span>
|
|
<div class="b3-label__text" data-i18n-html="langDesc"></div>
|
|
</div>
|
|
<div class="fn__flex-1"></div>
|
|
<select class="b3-select lang">
|
|
<option value="ar">العربية</option>
|
|
<option value="de">Deutsch</option>
|
|
<option value="en">English</option>
|
|
<option value="es">Español</option>
|
|
<option value="fr">Français</option>
|
|
<option value="he">עברית</option>
|
|
<option value="hi">हिन्दी</option>
|
|
<option value="id">Bahasa Indonesia</option>
|
|
<option value="it">Italiano</option>
|
|
<option value="ja">日本語</option>
|
|
<option value="ko">한국어</option>
|
|
<option value="nl">Nederlands</option>
|
|
<option value="pl">Polski</option>
|
|
<option value="pt-BR">Português (Brasil)</option>
|
|
<option value="ru">Русский</option>
|
|
<option value="sk">Slovenčina</option>
|
|
<option value="th">ไทย</option>
|
|
<option value="tr">Türkçe</option>
|
|
<option value="uk">Українська</option>
|
|
<option value="zh-TW">繁體中文</option>
|
|
<option value="zh-CN">简体中文</option>
|
|
</select>
|
|
</label>
|
|
<div class="fn__flex-1"></div>
|
|
<div class="feedback">
|
|
<span>❤️ <a data-i18n-href="feedbackUrl" target="_blank" data-i18n="feedback"></a></span>
|
|
<span>🏘️ <a data-i18n-href="communityUrl" target="_blank" data-i18n="community"></a></span>
|
|
<span>🔖 <a data-i18n-href="downloadUrl" target="_blank" class="version"></a></span>
|
|
</div>
|
|
<div class="fn__flex-1"></div>
|
|
</div>
|
|
</div>
|
|
<svg class="svg" id="min" viewBox="0 0 32 32">
|
|
<path d="M1.333 14.667h29.333q1.333 0 1.333 1.333v0q0 1.333-1.333 1.333h-29.333q-1.333 0-1.333-1.333v0q0-1.333 1.333-1.333z"></path>
|
|
</svg>
|
|
<svg class="svg" id="close" viewBox="0 0 32 32">
|
|
<path d="M32 3.221l-12.779 12.779 12.779 12.779-3.221 3.221-12.779-12.779-12.779 12.779-3.221-3.221 12.779-12.779-12.779-12.779 3.221-3.221 12.779 12.779 12.779-12.779z"></path>
|
|
</svg>
|
|
<div class="drag"></div>
|
|
<script src="window.js"></script>
|
|
<script>
|
|
const path = require("path")
|
|
const {ipcRenderer} = require("electron")
|
|
|
|
// 渲染可用工作空间列表
|
|
const wsRaw = decodeURIComponent(getSearch("workspaces"))
|
|
const wsList = wsRaw.split("\n").filter(item => "" !== item.trim())
|
|
let langData = applyLang(currentLang)
|
|
const renderWsList = () => {
|
|
const root = document.querySelector(".wsList")
|
|
root.innerHTML = ""
|
|
wsList.forEach(p => {
|
|
const div = document.createElement("div")
|
|
div.className = "ws-item"
|
|
const text = document.createElement("div")
|
|
text.className = "ws-text"
|
|
const name = document.createElement("div")
|
|
name.className = "ws-name"
|
|
name.textContent = path.basename(p)
|
|
const wsPath = document.createElement("div")
|
|
wsPath.className = "ws-path"
|
|
wsPath.textContent = p
|
|
text.appendChild(name)
|
|
text.appendChild(wsPath)
|
|
const btn = document.createElement("button")
|
|
btn.className = "b3-button ws-open"
|
|
btn.textContent = langData.open
|
|
btn.dataset.path = p
|
|
btn.addEventListener("click", () => {
|
|
ipcRenderer.send("siyuan-select-workspace", {
|
|
workspace: p,
|
|
lang: currentLang,
|
|
})
|
|
})
|
|
div.appendChild(text)
|
|
div.appendChild(btn)
|
|
root.appendChild(div)
|
|
})
|
|
}
|
|
|
|
const langSelect = document.querySelector(".lang")
|
|
langSelect.value = currentLang
|
|
document.querySelector(".version").textContent = `v${getSearch("v")}`
|
|
document.querySelector(".icon").src = decodeURIComponent(`${getSearch("icon")}`)
|
|
document.querySelector(".missing").textContent = decodeURIComponent(getSearch("missing"))
|
|
|
|
langSelect.addEventListener("change", (event) => {
|
|
langData = applyLang(event.target.value)
|
|
// 重新渲染列表项按钮文案
|
|
renderWsList()
|
|
})
|
|
|
|
initWindowChrome()
|
|
|
|
// 渲染进程崩溃恢复:显示安全模式选择,隐藏工作空间选择相关 UI
|
|
const isCrash = "1" === getSearch("crash")
|
|
const crashWorkspace = decodeURIComponent(getSearch("workspace"))
|
|
if (isCrash) {
|
|
document.querySelector(".wsPanel").classList.add("fn__none")
|
|
document.querySelector(".missing-tip").classList.add("fn__none")
|
|
document.querySelectorAll(".b3-label").forEach(item => item.classList.add("fn__none"))
|
|
const crashLogEl = document.querySelector(".crash-log")
|
|
const crashInfo = decodeURIComponent(getSearch("crashInfo"))
|
|
if (crashInfo) {
|
|
crashLogEl.textContent = crashInfo
|
|
} else {
|
|
crashLogEl.classList.add("fn__none")
|
|
}
|
|
document.querySelector(".crash-tip").classList.remove("fn__none")
|
|
document.querySelector(".safeMode").addEventListener("click", () => {
|
|
ipcRenderer.send("siyuan-select-workspace", {
|
|
workspace: crashWorkspace,
|
|
lang: currentLang,
|
|
safeMode: true,
|
|
})
|
|
})
|
|
document.querySelector(".normal").addEventListener("click", () => {
|
|
ipcRenderer.send("siyuan-select-workspace", {
|
|
workspace: crashWorkspace,
|
|
lang: currentLang,
|
|
safeMode: false,
|
|
})
|
|
})
|
|
} else if (0 < wsList.length) {
|
|
// 存在可用工作空间时渲染左列列表
|
|
renderWsList()
|
|
} else {
|
|
// 没有可用工作空间时隐藏左列,显示右列空提示
|
|
document.querySelector(".wsPanel").classList.add("fn__none")
|
|
document.querySelector(".emptyHint").classList.remove("fn__none")
|
|
}
|
|
|
|
document.querySelector(".choosePath").addEventListener("click", async () => {
|
|
const initPath = await chooseWorkspacePath(langData)
|
|
if (null === initPath) {
|
|
return
|
|
}
|
|
ipcRenderer.send("siyuan-select-workspace", {
|
|
workspace: initPath,
|
|
lang: currentLang,
|
|
})
|
|
})
|
|
</script>
|
|
</body>
|
|
</html>
|