siyuan/app/electron/init.html
Vanessa c311e3dee3 🎨
2024-02-05 12:25:12 +08:00

499 lines
17 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<title>SiYuan</title>
<meta charset="UTF-8">
<style>
body {
margin: 0;
background-color: #fff;
text-align: center;
color: #202124;
user-select: none;
font-family: "Helvetica Neue", "Luxi Sans", "DejaVu Sans", "Hiragino Sans GB", "Microsoft Yahei", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Noto Color Emoji", "Segoe UI Symbol", "Android Emoji", "EmojiSymbols";
}
.fn__flex-column {
display: flex;
flex-direction: column;
width: 100%;
margin: 0 auto;
border: 1px solid rgba(0, 0, 0, .06);
min-height: 100vh;
box-sizing: border-box;
padding: 0 calc((100vw - 608px) * 0.3);
}
.fn__flex-1 {
flex: 1;
min-height: 16px;
flex-shrink: 0;
}
h2 {
margin: 0 0 12px 0;
line-height: 24px;
}
.b3-select {
border: 1px solid rgba(0, 0, 0, .06);
border-radius: 6px;
padding: 4px 8px;
line-height: 20px;
box-sizing: border-box;
color: #202124;
transition: box-shadow 120ms 0ms cubic-bezier(0, 0, 0.2, 1);
background-color: #fff;
height: 28px;
font-size: 14px;
width: 96px;
}
.b3-select:focus {
border: 1px solid #218bff;
outline: none;
}
.b3-button {
cursor: pointer;
color: #fff;
border-radius: 6px;
line-height: 20px;
padding: 4px 8px;
background-color: #218bff;
white-space: nowrap;
display: inline-flex;
align-items: center;
justify-content: center;
transition: box-shadow 280ms cubic-bezier(0.4, 0, 0.2, 1);
border: 0;
box-sizing: border-box;
text-align: center;
width: 96px;
}
.b3-button:hover, .b3-button:focus {
text-decoration: none;
background-color: #0969da;
box-shadow: 0px 2px 4px -1px rgba(0, 0, 0, 0.2), 0px 4px 5px 0px rgba(0, 0, 0, 0.14), 0px 1px 10px 0px rgba(0, 0, 0, 0.12)
}
.b3-button:active {
box-shadow: 0px 5px 5px -3px rgba(0, 0, 0, 0.2), 0px 8px 10px 1px rgba(0, 0, 0, 0.14), 0px 3px 14px 2px rgba(0, 0, 0, 0.12)
}
.b3-label {
padding: 12px 24px;
line-height: 20px;
display: flex;
text-align: left;
border-bottom: 1px solid rgba(0, 0, 0, .06);
}
.b3-label__text {
color: #5f6368;
font-size: 14px;
margin-top: 4px;
}
.fn__space {
width: 8px;
flex-shrink: 0;
}
.fn__flex-center {
align-self: center;
}
.svg {
position: fixed;
right: 32px;
top: 0;
width: 13px;
fill: #5f6368;
padding: 9.5px;
cursor: pointer;
z-index: 1;
}
.svg:hover {
background: #dfe0e1;
fill: #202124;
}
#close {
right: 0;
width: 10px;
padding: 11px 11px;
}
#close:hover {
background-color: #d23f31;
fill: #fff;
}
a {
text-decoration: none;
color: #218bff;
}
a:hover {
text-decoration: underline;
color: #0969da;
}
.fn__none {
display: none !important;
}
.slogan {
color: #5f6368;
font-size: 15px;
}
.notice {
font-size: 14px;
color: #5f6368;
}
.icon {
width: 88px;
margin: 0 auto
}
kbd {
padding: 2px 4px;
font: 75% Consolas, "Liberation Mono", Menlo, Courier, monospace;
line-height: 1;
color: #5f6368;
vertical-align: middle;
background-color: #f3f3f3;
border: solid 1px rgba(0, 0, 0, .06);
border-radius: 6px;
box-shadow: inset 0 -1px 0 rgba(0, 0, 0, .06);
}
.feedback {
display: flex;
justify-content: space-around;
font-size: 14px
}
.drag {
-webkit-app-region: drag;
height: 22px;
cursor: pointer;
position: fixed;
top: 0;
left: 0;
right: 44px;
}
</style>
</head>
<body>
<div id="zhCN" class="fn__flex-column">
<div class="fn__flex-1"></div>
<img class="icon">
<h2>思源笔记</h2>
<div class="slogan">重构你的思维</div>
<div class="fn__flex-1"></div>
<label class="b3-label">
<div>
🌐 外观语言
<div class="b3-label__text">用户界面语言,后续可以在 <kbd>设置</kbd> - <kbd>外观</kbd> 中进行切换</div>
</div>
<div class="fn__space"></div>
<div class="fn__flex-1"></div>
<select class="b3-select lang">
<option value="en_US">English</option>
<option value="es_ES">Español</option>
<option value="fr_FR">Français</option>
<option value="zh_CN">简体中文</option>
<option value="zh_CHT">繁體中文</option>
</select>
</label>
<label class="b3-label">
<div>
🗂️ 工作空间
<div class="b3-label__text"> 工作空间用于存放数据,后续可以在顶栏左上角的主菜单中进行切换</div>
</div>
<div class="fn__space"></div>
<div class="fn__flex-1"></div>
<button class="b3-button fn__flex-center choosePath">选择</button>
</label>
<div class="fn__flex-1"></div>
<div class="fn__flex-1 notice">
<span>⚠️ 请勿使用第三方同步盘同步数据,否则会导致运行异常和数据损坏</span>
</div>
<div class="feedback">
<span>❤️ <a href="https://ld246.com/article/1649901726096" target="_blank">求助反馈建议</a></span>
<span>🏘️ <a href="https://ld246.com/article/1640266171309" target="_blank">用户社区汇总</a></span>
<span>🔖 <a href="https://b3log.org/siyuan/download.html" target="_blank" class="version"></a></span>
</div>
<div class="fn__flex-1"></div>
</div>
<div class="fn__none fn__flex-column" id="enUS">
<div class="fn__flex-1"></div>
<img class="icon">
<h2>SiYuan</h2>
<div class="slogan">Refactor your thinking</div>
<div class="fn__flex-1"></div>
<label class="b3-label">
<div>
🌐 Language
<div class="b3-label__text">User interface language, which can be switched later in <kbd>Settings</kbd> -
<kbd>Appearance</kbd>
</div>
</div>
<div class="fn__space"></div>
<div class="fn__flex-1"></div>
<select class="b3-select lang">
<option value="en_US">English</option>
<option value="es_ES">Español</option>
<option value="fr_FR">Français</option>
<option value="zh_CN">简体中文</option>
<option value="zh_CHT">繁體中文</option>
</select>
</label>
<label class="b3-label">
<div>
🗂️ Workspace
<div class="b3-label__text">The workspace is used to store data, which can be switched later in the top bar
menu later
</div>
</div>
<div class="fn__space"></div>
<div class="fn__flex-1"></div>
<button class="b3-button fn__flex-center choosePath">Select</button>
</label>
<div class="fn__flex-1"></div>
<div class="fn__flex-1 notice">
<span>⚠️ Do not use a third-party sync disk to sync data, otherwise it will cause abnormal operation and data damage</span>
</div>
<div class="feedback">
<span>❤️ <a href="https://liuyun.io/article/1686530886208" target="_blank">Support and Feedback</a></span>
<span>🏘️ <a href="https://liuyun.io/article/1687779743723" target="_blank">User community summary</a></span>
<span>🔖 <a href="https://b3log.org/siyuan/en/download.html" target="_blank" class="version"></a></span>
</div>
<div class="fn__flex-1"></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>
const isChinese = (lang) => {
return 'zh_CN' === lang || 'zh_CHT' === lang
}
const getSearch = (key) => {
if (window.location.search.indexOf('?') === -1) {
return ''
}
let value = ''
const data = window.location.search.split('?')[1].split('&')
data.find(item => {
const keyValue = item.split('=')
if (keyValue[0] === key) {
value = keyValue[1]
return true
}
})
return value
}
let currentLang = decodeURIComponent(getSearch('lang'))
const setLang = (lang) => {
if (isChinese(lang)) {
document.title = `思源笔记 v${getSearch('v')}`
document.getElementById('zhCN').classList.remove('fn__none')
document.getElementById('enUS').classList.add('fn__none')
} else {
document.title = `SiYuan v${getSearch('v')}`
document.getElementById('zhCN').classList.add('fn__none')
document.getElementById('enUS').classList.remove('fn__none')
}
currentLang = lang
}
setLang(currentLang)
document.querySelectorAll('.version').forEach(item => {
item.textContent = `v${getSearch('v')}`
})
document.querySelectorAll('.icon').forEach(item => {
item.src = decodeURIComponent(`${getSearch('icon')}`)
})
document.querySelectorAll('.lang').forEach(item => {
item.value = currentLang
item.addEventListener('change', () => {
document.querySelectorAll('.lang').forEach(item1 => {
item1.value = item.value
})
setLang(item.value)
})
})
document.getElementById('close').addEventListener('click', () => {
const {ipcRenderer} = require('electron')
ipcRenderer.send('siyuan-first-quit')
})
document.getElementById('min').addEventListener('click', () => {
const {ipcRenderer} = require('electron')
ipcRenderer.send("siyuan-cmd", "minimize");
})
document.querySelectorAll('.choosePath').forEach((item) => {
item.addEventListener('click', async () => {
const path = require('path')
const fs = require('fs')
const defaultWorkspace = path.join(decodeURIComponent(getSearch('home')), "SiYuan")
if (!fs.existsSync(defaultWorkspace)) {
fs.mkdirSync(defaultWorkspace, {mode: 0o755, recursive: true})
}
const {ipcRenderer} = require('electron')
const result = await ipcRenderer.invoke("siyuan-get", {
cmd: "showOpenDialog",
defaultPath: defaultWorkspace,
properties: ['openDirectory', 'createDirectory'],
});
if (result.canceled) {
return
}
const initPath = result.filePaths[0]
if (isICloudPath(initPath)) {
let msg = '⚠️ This folder is under the iCloud sync path, please change another path'
if (isChinese(currentLang)) {
msg = '⚠️ 该文件夹位于 iCloud 同步路径下,请更换其他路径'
}
alert(msg)
return
}
if (isCloudDrivePath(initPath)) {
let msg = '⚠️ The folder path can not contain onedrive, dropbox, google drive, pcloud and 坚果云, please change another path'
if (isChinese(currentLang)) {
msg = '⚠️ 文件夹路径不能包含 onedrive、dropbox、google drive、pcloud 和 坚果云,请更换其他路径'
}
alert(msg)
return
}
let msg = '⚠️ Do not set the workspace under the path of a third-party sync disk, otherwise the data will be damaged (iCloud/OneDrive/Dropbox/Google Drive/Nutstore/Baidu Netdisk/Tencent Weiyun, etc.), continue?'
if (isChinese(currentLang)) {
msg = '⚠️ 请勿将工作空间设置在第三方同步盘路径下否则数据会被损坏iCloud/OneDrive/Dropbox/Google Drive/坚果云/百度网盘/腾讯微云等),是否继续?'
}
if (!confirm(msg)) {
return
}
if (!fs.existsSync(initPath)) {
fs.mkdirSync(initPath, {mode: 0o755, recursive: true})
}
ipcRenderer.send('siyuan-first-init', {
workspace: initPath,
lang: document.querySelector('.lang').value
})
})
})
const isCloudDrivePath = (absPath) => {
const absPathLower = absPath.toLowerCase()
return -1 < absPathLower.indexOf("onedrive") || -1 < absPathLower.indexOf("dropbox") ||
-1 < absPathLower.indexOf("google drive") || -1 < absPathLower.indexOf("pcloud") ||
-1 < absPathLower.indexOf("坚果云")
}
const isICloudPath = (absPath) => {
const os = require('os')
if ('darwin' !== os.platform()) {
return false
}
// macOS 端对工作空间放置在 iCloud 路径下做检查 https://github.com/siyuan-note/siyuan/issues/7747
const path = require('path')
const homePath = decodeURIComponent(getSearch('home'))
const absPathLower = absPath.toLowerCase()
const iCloudRoot = path.join(homePath, 'Library', 'Mobile Documents')
if (!simpleCheckIcloudPath(absPath, homePath)) {
// 简单判断无法通过则复杂验证
const allFiles = walk(iCloudRoot)
for (const file of allFiles) {
if (-1 < absPathLower.indexOf(file.toLowerCase())) {
return true
}
}
}
return false
}
// 简单判断 iCloud 同步目录
// 不允许 为桌面 文档 和 iCloud 文件夹 和软链接
const simpleCheckIcloudPath = (absPath, homePath) => {
const fs = require('fs')
let stat = fs.lstatSync(absPath)
if (stat.isSymbolicLink()) {
return false
}
const path = require('path')
const absPathLower = absPath.toLowerCase()
const iCloudRoot = path.join(homePath, 'Library', 'Mobile Documents')
if (absPathLower.startsWith(iCloudRoot.toLowerCase())) {
return false
}
const documentsRoot = path.join(homePath, 'Documents')
if (absPathLower.startsWith(documentsRoot.toLowerCase())) {
return false
}
const desktopRoot = path.join(homePath, 'Desktop')
if (absPathLower.startsWith(desktopRoot.toLowerCase())) {
return false
}
return true
}
const walk = (dir, files = []) => {
let dirFiles;
const fs = require('fs')
try {
if (!fs.existsSync(dir)) {
console.log("dir [" + dir + "] not exists")
return files
}
dirFiles = fs.readdirSync(dir)
} catch (e) {
console.error("read dir [" + dir + "] failed: ", e)
return files
}
const path = require('path')
for (const f of dirFiles) {
let stat = fs.lstatSync(dir + path.sep + f)
if (stat.isSymbolicLink()) {
files.push(fs.readlinkSync(dir + path.sep + f))
continue
}
if (stat.isDirectory()) {
// 如果已经遍历过则不再遍历
if (files.includes(dir + path.sep + f)) {
continue
}
files.push(dir + path.sep + f)
walk(dir + path.sep + f, files)
}
}
return files
}
</script>
</body>
</html>