mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-23 01:50:12 +01:00
📱 add ai and flashcard
This commit is contained in:
parent
557781e4a1
commit
4e313b8829
11 changed files with 835 additions and 689 deletions
|
|
@ -3,52 +3,87 @@ import {fetchPost} from "../util/fetch";
|
||||||
export const ai = {
|
export const ai = {
|
||||||
element: undefined as Element,
|
element: undefined as Element,
|
||||||
genHTML: () => {
|
genHTML: () => {
|
||||||
|
let responsiveHTML = ""
|
||||||
|
/// #if MOBILE
|
||||||
|
responsiveHTML = `<div class="b3-label">
|
||||||
|
${window.siyuan.languages.apiTimeout}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__flex-center fn__block" type="number" step="1" min="5" max="600" id="apiTimeout" value="${window.siyuan.config.ai.openAI.apiTimeout}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiTimeoutTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
${window.siyuan.languages.apiMaxTokens}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__flex-center fn__block" type="number" step="1" min="0" id="apiMaxTokens" max="4096" value="${window.siyuan.config.ai.openAI.apiMaxTokens}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiMaxTokensTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
${window.siyuan.languages.apiKey}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__block" id="apiKey" value="${window.siyuan.config.ai.openAI.apiKey}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiKeyTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
${window.siyuan.languages.apiProxy}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__block" id="apiProxy" value="${window.siyuan.config.ai.openAI.apiProxy}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiProxyTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
${window.siyuan.languages.apiBaseURL}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__block" id="apiBaseURL" value="${window.siyuan.config.ai.openAI.apiBaseURL}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiBaseURLTip}</div>
|
||||||
|
</div>`;
|
||||||
|
/// #else
|
||||||
|
responsiveHTML = `<label class="fn__flex b3-label">
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
${window.siyuan.languages.apiTimeout}
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiTimeoutTip}</div>
|
||||||
|
</div>
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<input class="b3-text-field fn__flex-center fn__size200" type="number" step="1" min="5" max="600" id="apiTimeout" value="${window.siyuan.config.ai.openAI.apiTimeout}"/>
|
||||||
|
</label>
|
||||||
|
<label class="fn__flex b3-label">
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
${window.siyuan.languages.apiMaxTokens}
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiMaxTokensTip}</div>
|
||||||
|
</div>
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<input class="b3-text-field fn__flex-center fn__size200" type="number" step="1" min="0" id="apiMaxTokens" max="4096" value="${window.siyuan.config.ai.openAI.apiMaxTokens}"/>
|
||||||
|
</label>
|
||||||
|
<label class="fn__flex b3-label">
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
${window.siyuan.languages.apiKey}
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiKeyTip}</div>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__block" id="apiKey" value="${window.siyuan.config.ai.openAI.apiKey}"/>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<label class="fn__flex b3-label">
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
${window.siyuan.languages.apiProxy}
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiProxyTip}</div>
|
||||||
|
<span class="fn__hr"></span>
|
||||||
|
<input class="b3-text-field fn__block" id="apiProxy" value="${window.siyuan.config.ai.openAI.apiProxy}"/>
|
||||||
|
</div>
|
||||||
|
</label>
|
||||||
|
<label class="fn__flex b3-label">
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
${window.siyuan.languages.apiBaseURL}
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.apiBaseURLTip}</div>
|
||||||
|
<span class="fn__hr"></span>
|
||||||
|
<input class="b3-text-field fn__block" id="apiBaseURL" value="${window.siyuan.config.ai.openAI.apiBaseURL}"/>
|
||||||
|
</div>
|
||||||
|
</label>`;
|
||||||
|
/// #endif
|
||||||
return `<div class="fn__flex-column" style="height: 100%">
|
return `<div class="fn__flex-column" style="height: 100%">
|
||||||
<div class="layout-tab-bar fn__flex">
|
<div class="layout-tab-bar fn__flex">
|
||||||
<div data-type="openai" class="item item--full item--focus"><span class="fn__flex-1"></span><span class="item__text">OpenAI</span><span class="fn__flex-1"></span></div>
|
<div data-type="openai" class="item item--full item--focus"><span class="fn__flex-1"></span><span class="item__text">OpenAI</span><span class="fn__flex-1"></span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="fn__flex-1">
|
<div class="fn__flex-1">
|
||||||
<div data-type="openai">
|
<div data-type="openai">
|
||||||
<label class="fn__flex b3-label">
|
${responsiveHTML}
|
||||||
<div class="fn__flex-1">
|
|
||||||
${window.siyuan.languages.apiTimeout}
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.apiTimeoutTip}</div>
|
|
||||||
</div>
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<input class="b3-text-field fn__flex-center fn__size200" type="number" step="1" min="5" max="600" id="apiTimeout" value="${window.siyuan.config.ai.openAI.apiTimeout}"/>
|
|
||||||
</label>
|
|
||||||
<label class="fn__flex b3-label">
|
|
||||||
<div class="fn__flex-1">
|
|
||||||
${window.siyuan.languages.apiMaxTokens}
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.apiMaxTokensTip}</div>
|
|
||||||
</div>
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<input class="b3-text-field fn__flex-center fn__size200" type="number" step="1" min="0" id="apiMaxTokens" max="4096" value="${window.siyuan.config.ai.openAI.apiMaxTokens}"/>
|
|
||||||
</label>
|
|
||||||
<label class="fn__flex b3-label">
|
|
||||||
<div class="fn__flex-1">
|
|
||||||
${window.siyuan.languages.apiKey}
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.apiKeyTip}</div>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<input class="b3-text-field fn__block" id="apiKey" value="${window.siyuan.config.ai.openAI.apiKey}"/>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="fn__flex b3-label">
|
|
||||||
<div class="fn__flex-1">
|
|
||||||
${window.siyuan.languages.apiProxy}
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.apiProxyTip}</div>
|
|
||||||
<span class="fn__hr"></span>
|
|
||||||
<input class="b3-text-field fn__block" id="apiProxy" value="${window.siyuan.config.ai.openAI.apiProxy}"/>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
<label class="fn__flex b3-label">
|
|
||||||
<div class="fn__flex-1">
|
|
||||||
${window.siyuan.languages.apiBaseURL}
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.apiBaseURLTip}</div>
|
|
||||||
<span class="fn__hr"></span>
|
|
||||||
<input class="b3-text-field fn__block" id="apiBaseURL" value="${window.siyuan.config.ai.openAI.apiBaseURL}"/>
|
|
||||||
</div>
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,22 @@ import {fetchPost} from "../util/fetch";
|
||||||
export const flashcard = {
|
export const flashcard = {
|
||||||
element: undefined as Element,
|
element: undefined as Element,
|
||||||
genHTML: () => {
|
genHTML: () => {
|
||||||
return `<label class="fn__flex b3-label">
|
let responsiveHTML = ""
|
||||||
|
/// #if MOBILE
|
||||||
|
responsiveHTML = `<div class="b3-label">
|
||||||
|
${window.siyuan.languages.flashcardNewCardLimit}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__flex-center fn__block" id="newCardLimit" step="1" min="1" type="number"${window.siyuan.config.flashcard.newCardLimit ? " checked" : "" } value="${window.siyuan.config.flashcard.newCardLimit}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.flashcardNewCardLimitTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
${window.siyuan.languages.flashcardReviewCardLimit}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__flex-center fn__block" id="reviewCardLimit" step="1" min="1" type="number"${window.siyuan.config.flashcard.reviewCardLimit ? " checked" : ""} value="${window.siyuan.config.flashcard.reviewCardLimit}"/>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.flashcardReviewCardLimitTip}</div>
|
||||||
|
</div>`
|
||||||
|
/// #else
|
||||||
|
responsiveHTML = `<label class="fn__flex b3-label">
|
||||||
<div class="fn__flex-1">
|
<div class="fn__flex-1">
|
||||||
${window.siyuan.languages.flashcardNewCardLimit}
|
${window.siyuan.languages.flashcardNewCardLimit}
|
||||||
<div class="b3-label__text">${window.siyuan.languages.flashcardNewCardLimitTip}</div>
|
<div class="b3-label__text">${window.siyuan.languages.flashcardNewCardLimitTip}</div>
|
||||||
|
|
@ -18,7 +33,9 @@ export const flashcard = {
|
||||||
</div>
|
</div>
|
||||||
<span class="fn__space"></span>
|
<span class="fn__space"></span>
|
||||||
<input class="b3-text-field fn__flex-center fn__size200" id="reviewCardLimit" step="1" min="1" type="number"${window.siyuan.config.flashcard.reviewCardLimit ? " checked" : ""} value="${window.siyuan.config.flashcard.reviewCardLimit}"/>
|
<input class="b3-text-field fn__flex-center fn__size200" id="reviewCardLimit" step="1" min="1" type="number"${window.siyuan.config.flashcard.reviewCardLimit ? " checked" : ""} value="${window.siyuan.config.flashcard.reviewCardLimit}"/>
|
||||||
</label>
|
</label>`
|
||||||
|
/// #endif
|
||||||
|
return `${responsiveHTML}
|
||||||
<label class="fn__flex b3-label">
|
<label class="fn__flex b3-label">
|
||||||
<div class="fn__flex-1">
|
<div class="fn__flex-1">
|
||||||
${window.siyuan.languages.flashcardList}
|
${window.siyuan.languages.flashcardList}
|
||||||
|
|
|
||||||
384
app/src/mobile/settings/about.ts
Normal file
384
app/src/mobile/settings/about.ts
Normal file
|
|
@ -0,0 +1,384 @@
|
||||||
|
import {Constants} from "../../constants";
|
||||||
|
import {setAccessAuthCode} from "../../config/util/setAccessAuthCode";
|
||||||
|
import {Dialog} from "../../dialog";
|
||||||
|
import {fetchPost} from "../../util/fetch";
|
||||||
|
import {confirmDialog} from "../../dialog/confirmDialog";
|
||||||
|
import {showMessage} from "../../dialog/message";
|
||||||
|
import {openByMobile, writeText} from "../../protyle/util/compatibility";
|
||||||
|
import {exitSiYuan, processSync} from "../../dialog/processSystem";
|
||||||
|
import {pathPosix} from "../../util/pathName";
|
||||||
|
import {openModel} from "../util/model";
|
||||||
|
|
||||||
|
export const initAbout = () => {
|
||||||
|
if (!window.siyuan.config.localIPs || window.siyuan.config.localIPs.length === 0 ||
|
||||||
|
(window.siyuan.config.localIPs.length === 1 && window.siyuan.config.localIPs[0] === "")) {
|
||||||
|
window.siyuan.config.localIPs = ["127.0.0.1"];
|
||||||
|
}
|
||||||
|
|
||||||
|
openModel({
|
||||||
|
title: window.siyuan.languages.about,
|
||||||
|
icon: "iconInfo",
|
||||||
|
html: `<div class="b3-label fn__flex${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
<div class="fn__flex-1">
|
||||||
|
${window.siyuan.languages.about11}
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.about12}</div>
|
||||||
|
</div>
|
||||||
|
<div class="fn__space"></div>
|
||||||
|
<input class="b3-switch fn__flex-center" id="networkServe" type="checkbox"${window.siyuan.config.system.networkServe ? " checked" : ""}>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
${window.siyuan.languages.about2}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<input class="b3-text-field fn__block" readonly value="http://${window.siyuan.config.system.networkServe ? window.siyuan.config.localIPs[0] : "127.0.0.1"}:${location.port}">
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.about3.replace("${port}", location.port)}</div>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<span class="b3-label__text"><code class="fn__code">${window.siyuan.config.localIPs.join("</code> <code class='fn__code'>")}</code></span>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
${window.siyuan.languages.about5}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="authCode">
|
||||||
|
<svg><use xlink:href="#iconLock"></use></svg>${window.siyuan.languages.config}
|
||||||
|
</button>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.about6}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
${window.siyuan.languages.dataRepoKey}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<div class="${window.siyuan.config.repo.key ? "fn__none" : ""}">
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="importKey">
|
||||||
|
<svg><use xlink:href="#iconDownload"></use></svg>${window.siyuan.languages.importKey}
|
||||||
|
</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="initKey">
|
||||||
|
<svg><use xlink:href="#iconLock"></use></svg>${window.siyuan.languages.genKey}
|
||||||
|
</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="initKeyByPW">
|
||||||
|
${window.siyuan.languages.genKeyByPW}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="${window.siyuan.config.repo.key ? "" : "fn__none"}">
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="copyKey">
|
||||||
|
<svg><use xlink:href="#iconCopy"></use></svg>${window.siyuan.languages.copyKey}
|
||||||
|
</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="removeKey">
|
||||||
|
<svg><use xlink:href="#iconTrashcan"></use></svg>${window.siyuan.languages.resetRepo}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.dataRepoKeyTip1}</div>
|
||||||
|
<div class="b3-label__text ft__error">${window.siyuan.languages.dataRepoKeyTip2}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
${window.siyuan.languages.about13}
|
||||||
|
<span class="b3-label__text">${window.siyuan.config.api.token}</span>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="token">
|
||||||
|
<svg><use xlink:href="#iconCopy"></use></svg>${window.siyuan.languages.copy}
|
||||||
|
</button>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.about14}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
<div class="fn__flex">
|
||||||
|
${window.siyuan.languages.export}
|
||||||
|
</div>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="exportData">
|
||||||
|
<svg><use xlink:href="#iconUpload"></use></svg>Data
|
||||||
|
</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.exportDataTip}</div>
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" id="exportLog">
|
||||||
|
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.systemLog}
|
||||||
|
</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.systemLogTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
<div class="fn__flex">
|
||||||
|
${window.siyuan.languages.import}
|
||||||
|
</div>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button class="b3-button b3-button--outline fn__block" style="position: relative">
|
||||||
|
<input id="importData" class="b3-form__upload" type="file">
|
||||||
|
<svg><use xlink:href="#iconDownload"></use></svg> ${window.siyuan.languages.import} Data
|
||||||
|
</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<div class="b3-label__text">${window.siyuan.languages.importDataTip}</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
||||||
|
${window.siyuan.languages.workspaceList}
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button id="openWorkspace" class="b3-button b3-button--outline fn__block">${window.siyuan.languages.openBy}...</button>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<ul id="workspaceDir" class="b3-list b3-list--background"></ul>
|
||||||
|
<div class="fn__hr"></div>
|
||||||
|
<button id="creatWorkspace" class="b3-button fn__block">${window.siyuan.languages.new}</button>
|
||||||
|
</div>
|
||||||
|
<div class="b3-label">
|
||||||
|
<div class="config-about__logo">
|
||||||
|
<img src="/stage/icon.png">
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<div>
|
||||||
|
<span>${window.siyuan.languages.siyuanNote}</span>
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<span class="ft__on-surface">v${Constants.SIYUAN_VERSION}</span>
|
||||||
|
<br>
|
||||||
|
<span class="ft__on-surface">${window.siyuan.languages.slogan}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div style="color:var(--b3-theme-surface);font-family: cursive;">会泽百家 至公天下</div>
|
||||||
|
${window.siyuan.languages.about1}
|
||||||
|
</div>`,
|
||||||
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
|
const workspaceDirElement = modelMainElement.querySelector("#workspaceDir");
|
||||||
|
genWorkspace(workspaceDirElement);
|
||||||
|
const importKeyElement = modelMainElement.querySelector("#importKey");
|
||||||
|
modelMainElement.addEventListener("click", (event) => {
|
||||||
|
let target = event.target as HTMLElement;
|
||||||
|
while (target && !target.isSameNode(modelMainElement)) {
|
||||||
|
if (target.id === "authCode") {
|
||||||
|
setAccessAuthCode();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "importKey") {
|
||||||
|
const passwordDialog = new Dialog({
|
||||||
|
title: "🔑 " + window.siyuan.languages.key,
|
||||||
|
content: `<div class="b3-dialog__content">
|
||||||
|
<textarea class="b3-text-field fn__block" placeholder="${window.siyuan.languages.keyPlaceholder}"></textarea>
|
||||||
|
</div>
|
||||||
|
<div class="b3-dialog__action">
|
||||||
|
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
||||||
|
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
||||||
|
</div>`,
|
||||||
|
width: "80vw",
|
||||||
|
});
|
||||||
|
const textAreaElement = passwordDialog.element.querySelector("textarea");
|
||||||
|
textAreaElement.focus();
|
||||||
|
const btnsElement = passwordDialog.element.querySelectorAll(".b3-button");
|
||||||
|
btnsElement[0].addEventListener("click", () => {
|
||||||
|
passwordDialog.destroy();
|
||||||
|
});
|
||||||
|
btnsElement[1].addEventListener("click", () => {
|
||||||
|
fetchPost("/api/repo/importRepoKey", {key: textAreaElement.value}, () => {
|
||||||
|
window.siyuan.config.repo.key = textAreaElement.value;
|
||||||
|
importKeyElement.parentElement.classList.add("fn__none");
|
||||||
|
importKeyElement.parentElement.nextElementSibling.classList.remove("fn__none");
|
||||||
|
passwordDialog.destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "initKey") {
|
||||||
|
confirmDialog("🔑 " + window.siyuan.languages.genKey, window.siyuan.languages.initRepoKeyTip, () => {
|
||||||
|
fetchPost("/api/repo/initRepoKey", {}, (response) => {
|
||||||
|
window.siyuan.config.repo.key = response.data.key;
|
||||||
|
importKeyElement.parentElement.classList.add("fn__none");
|
||||||
|
importKeyElement.parentElement.nextElementSibling.classList.remove("fn__none");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "initKeyByPW") {
|
||||||
|
const initDialog = new Dialog({
|
||||||
|
title: "🔑 " + window.siyuan.languages.genKeyByPW,
|
||||||
|
content: `<div class="b3-dialog__content">
|
||||||
|
<input class="b3-text-field fn__block" placeholder="${window.siyuan.languages.password}">
|
||||||
|
</div>
|
||||||
|
<div class="b3-dialog__action">
|
||||||
|
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
||||||
|
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
||||||
|
</div>`,
|
||||||
|
width: "80vw",
|
||||||
|
});
|
||||||
|
const inputElement = initDialog.element.querySelector(".b3-text-field") as HTMLInputElement;
|
||||||
|
inputElement.focus();
|
||||||
|
const btnsElement = initDialog.element.querySelectorAll(".b3-button");
|
||||||
|
initDialog.bindInput(inputElement, () => {
|
||||||
|
(btnsElement[1] as HTMLButtonElement).click();
|
||||||
|
});
|
||||||
|
btnsElement[0].addEventListener("click", () => {
|
||||||
|
initDialog.destroy();
|
||||||
|
});
|
||||||
|
btnsElement[1].addEventListener("click", () => {
|
||||||
|
if (!inputElement.value) {
|
||||||
|
showMessage(window.siyuan.languages._kernel[142]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirmDialog("🔑 " + window.siyuan.languages.genKeyByPW, window.siyuan.languages.initRepoKeyTip, () => {
|
||||||
|
initDialog.destroy();
|
||||||
|
fetchPost("/api/repo/initRepoKeyFromPassphrase", {pass: inputElement.value}, (response) => {
|
||||||
|
window.siyuan.config.repo.key = response.data.key;
|
||||||
|
importKeyElement.parentElement.classList.add("fn__none");
|
||||||
|
importKeyElement.parentElement.nextElementSibling.classList.remove("fn__none");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "copyKey") {
|
||||||
|
showMessage(window.siyuan.languages.copied);
|
||||||
|
writeText(window.siyuan.config.repo.key);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "removeKey") {
|
||||||
|
confirmDialog("⚠️ " + window.siyuan.languages.resetRepo, window.siyuan.languages.resetRepoTip, () => {
|
||||||
|
fetchPost("/api/repo/resetRepo", {}, () => {
|
||||||
|
window.siyuan.config.repo.key = "";
|
||||||
|
window.siyuan.config.sync.enabled = false;
|
||||||
|
processSync();
|
||||||
|
importKeyElement.parentElement.classList.remove("fn__none");
|
||||||
|
importKeyElement.parentElement.nextElementSibling.classList.add("fn__none");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "token") {
|
||||||
|
showMessage(window.siyuan.languages.copied);
|
||||||
|
writeText(window.siyuan.config.api.token);
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "exportData") {
|
||||||
|
fetchPost("/api/export/exportData", {}, response => {
|
||||||
|
openByMobile(response.data.zip);
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "exportLog") {
|
||||||
|
fetchPost("/api/system/exportLog", {}, (response) => {
|
||||||
|
openByMobile(response.data.zip);
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "openWorkspace") {
|
||||||
|
fetchPost("/api/system/getMobileWorkspaces", {}, (response) => {
|
||||||
|
let selectHTML = "";
|
||||||
|
response.data.forEach((item: string, index: number) => {
|
||||||
|
selectHTML += `<option value="${item}"${index === 0 ? ' selected="selected"' : ""}>${pathPosix().basename(item)}</option>`;
|
||||||
|
});
|
||||||
|
const openWorkspaceDialog = new Dialog({
|
||||||
|
title: window.siyuan.languages.openBy,
|
||||||
|
content: `<div class="b3-dialog__content">
|
||||||
|
<select class="b3-text-field fn__block">${selectHTML}</select>
|
||||||
|
</div>
|
||||||
|
<div class="b3-dialog__action">
|
||||||
|
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
||||||
|
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
||||||
|
</div>`,
|
||||||
|
width: "80vw",
|
||||||
|
});
|
||||||
|
const btnsElement = openWorkspaceDialog.element.querySelectorAll(".b3-button");
|
||||||
|
btnsElement[0].addEventListener("click", () => {
|
||||||
|
openWorkspaceDialog.destroy();
|
||||||
|
});
|
||||||
|
btnsElement[1].addEventListener("click", () => {
|
||||||
|
const openPath = openWorkspaceDialog.element.querySelector("select").value;
|
||||||
|
if (openPath === window.siyuan.config.system.workspaceDir) {
|
||||||
|
openWorkspaceDialog.destroy();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
confirmDialog(window.siyuan.languages.confirm, `${pathPosix().basename(window.siyuan.config.system.workspaceDir)} -> ${pathPosix().basename(openPath)}?`, () => {
|
||||||
|
fetchPost("/api/system/setWorkspaceDir", {
|
||||||
|
path: openPath
|
||||||
|
}, () => {
|
||||||
|
exitSiYuan();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "creatWorkspace") {
|
||||||
|
const createWorkspaceDialog = new Dialog({
|
||||||
|
title: window.siyuan.languages.new,
|
||||||
|
content: `<div class="b3-dialog__content">
|
||||||
|
<input class="b3-text-field fn__block">
|
||||||
|
</div>
|
||||||
|
<div class="b3-dialog__action">
|
||||||
|
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
||||||
|
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
||||||
|
</div>`,
|
||||||
|
width: "80vw",
|
||||||
|
});
|
||||||
|
const inputElement = createWorkspaceDialog.element.querySelector("input");
|
||||||
|
inputElement.focus();
|
||||||
|
const btnsElement = createWorkspaceDialog.element.querySelectorAll(".b3-button");
|
||||||
|
btnsElement[0].addEventListener("click", () => {
|
||||||
|
createWorkspaceDialog.destroy();
|
||||||
|
});
|
||||||
|
btnsElement[1].addEventListener("click", () => {
|
||||||
|
fetchPost("/api/system/createWorkspaceDir", {
|
||||||
|
path: pathPosix().join(pathPosix().dirname(window.siyuan.config.system.workspaceDir), inputElement.value)
|
||||||
|
}, () => {
|
||||||
|
genWorkspace(workspaceDirElement);
|
||||||
|
createWorkspaceDialog.destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.getAttribute("data-type") === "remove") {
|
||||||
|
fetchPost("/api/system/removeWorkspaceDir", {path: target.parentElement.getAttribute("data-path")}, () => {
|
||||||
|
genWorkspace(workspaceDirElement);
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.classList.contains("b3-list-item") && !target.classList.contains("b3-list-item--focus")) {
|
||||||
|
confirmDialog(window.siyuan.languages.confirm, `${pathPosix().basename(window.siyuan.config.system.workspaceDir)} -> ${pathPosix().basename(target.getAttribute("data-path"))}?`, () => {
|
||||||
|
fetchPost("/api/system/setWorkspaceDir", {
|
||||||
|
path: target.getAttribute("data-path")
|
||||||
|
}, () => {
|
||||||
|
exitSiYuan();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
target = target.parentElement;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
modelMainElement.querySelector("#importData").addEventListener("change", (event: InputEvent & {
|
||||||
|
target: HTMLInputElement
|
||||||
|
}) => {
|
||||||
|
const formData = new FormData();
|
||||||
|
formData.append("file", event.target.files[0]);
|
||||||
|
fetchPost("/api/import/importData", formData);
|
||||||
|
});
|
||||||
|
const networkServeElement = modelMainElement.querySelector("#networkServe") as HTMLInputElement;
|
||||||
|
networkServeElement.addEventListener("change", () => {
|
||||||
|
fetchPost("/api/system/setNetworkServe", {networkServe: networkServeElement.checked}, () => {
|
||||||
|
exitSiYuan();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const genWorkspace = (workspaceDirElement: Element) => {
|
||||||
|
fetchPost("/api/system/getWorkspaces", {}, (response) => {
|
||||||
|
let html = "";
|
||||||
|
response.data.forEach((item: IWorkspace) => {
|
||||||
|
html += `<li data-path="${item.path}" class="b3-list-item b3-list-item--narrow${window.siyuan.config.system.workspaceDir === item.path ? " b3-list-item--focus" : ""}">
|
||||||
|
<span class="b3-list-item__text">${pathPosix().basename(item.path)}</span>
|
||||||
|
<span data-type="remove" class="b3-list-item__action">
|
||||||
|
<svg><use xlink:href="#iconMin"></use></svg>
|
||||||
|
</span>
|
||||||
|
</li>`;
|
||||||
|
});
|
||||||
|
workspaceDirElement.innerHTML = html;
|
||||||
|
});
|
||||||
|
};
|
||||||
215
app/src/mobile/settings/account.ts
Normal file
215
app/src/mobile/settings/account.ts
Normal file
|
|
@ -0,0 +1,215 @@
|
||||||
|
import {openModel} from "../util/model";
|
||||||
|
import {getEventName} from "../../protyle/util/compatibility";
|
||||||
|
import {fetchPost} from "../../util/fetch";
|
||||||
|
import {closePanel} from "../util/closePanel";
|
||||||
|
import {processSync} from "../../dialog/processSystem";
|
||||||
|
import {confirmDialog} from "../../dialog/confirmDialog";
|
||||||
|
import {showMessage} from "../../dialog/message";
|
||||||
|
import md5 from "blueimp-md5";
|
||||||
|
|
||||||
|
export const showAccountInfo = () => {
|
||||||
|
let userTitlesHTML = "";
|
||||||
|
if (window.siyuan.user.userTitles.length > 0) {
|
||||||
|
userTitlesHTML = '<div class="b3-chips" style="position: absolute">';
|
||||||
|
window.siyuan.user.userTitles.forEach((item) => {
|
||||||
|
userTitlesHTML += `<div class="b3-chip b3-chip--middle">${item.icon} ${item.name}</div>`;
|
||||||
|
});
|
||||||
|
userTitlesHTML += "</div>";
|
||||||
|
}
|
||||||
|
openModel({
|
||||||
|
title: window.siyuan.languages.accountManage,
|
||||||
|
icon: "iconAccount",
|
||||||
|
html: `<div class="fn__flex-column">
|
||||||
|
<div class="config-account__bg">
|
||||||
|
<div class="config-account__cover" style="background-image: url(${window.siyuan.user.userHomeBImgURL})"></div>
|
||||||
|
<a href="https://ld246.com/settings/avatar" class="config-account__avatar" style="background-image: url(${window.siyuan.user.userAvatarURL})" target="_blank"></a>
|
||||||
|
<h1 class="config-account__name">
|
||||||
|
<a target="_blank" class="fn__a" href="https://ld246.com/member/${window.siyuan.user.userName}">${window.siyuan.user.userName}</a>
|
||||||
|
</h1>
|
||||||
|
${userTitlesHTML}
|
||||||
|
</div>
|
||||||
|
<div class="config-account__info">
|
||||||
|
<div class="fn__flex">
|
||||||
|
<a class="b3-button b3-button--text" href="https://ld246.com/settings" target="_blank">${window.siyuan.languages.accountManage}</a>
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<button class="b3-button b3-button--cancel" id="logout">
|
||||||
|
${window.siyuan.languages.logout}
|
||||||
|
</button>
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<button class="b3-button b3-button--cancel" id="deactivateUser">
|
||||||
|
${window.siyuan.languages.deactivateUser}
|
||||||
|
</button>
|
||||||
|
<span class="fn__flex-1"></span>
|
||||||
|
<button class="b3-button b3-button--cancel" id="refresh">
|
||||||
|
<svg><use xlink:href="#iconRefresh"></use></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div></div>`,
|
||||||
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
|
modelMainElement.querySelector("#logout").addEventListener(getEventName(), () => {
|
||||||
|
fetchPost("/api/setting/logoutCloudUser", {}, () => {
|
||||||
|
window.siyuan.user = null;
|
||||||
|
closePanel();
|
||||||
|
document.getElementById("menuAccount").innerHTML = `<svg class="b3-menu__icon"><use xlink:href="#iconAccount"></use></svg><span class="b3-menu__label">${window.siyuan.languages.login}</span>`;
|
||||||
|
processSync();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
modelMainElement.querySelector("#deactivateUser").addEventListener(getEventName(), () => {
|
||||||
|
confirmDialog("⚠️ " + window.siyuan.languages.deactivateUser, window.siyuan.languages.deactivateUserTip, () => {
|
||||||
|
fetchPost("/api/account/deactivate", {}, () => {
|
||||||
|
window.siyuan.user = null;
|
||||||
|
closePanel();
|
||||||
|
document.getElementById("menuAccount").innerHTML = `<svg class="b3-menu__icon"><use xlink:href="#iconAccount"></use></svg><span class="b3-menu__label">${window.siyuan.languages.login}</span>`;
|
||||||
|
processSync();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
const refreshElement = modelMainElement.querySelector("#refresh");
|
||||||
|
refreshElement.addEventListener("click", () => {
|
||||||
|
const svgElement = refreshElement.firstElementChild;
|
||||||
|
if (svgElement.classList.contains("fn__rotate")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
svgElement.classList.add("fn__rotate");
|
||||||
|
fetchPost("/api/setting/getCloudUser", {
|
||||||
|
token: window.siyuan.user.userToken,
|
||||||
|
}, response => {
|
||||||
|
window.siyuan.user = response.data;
|
||||||
|
showMessage(window.siyuan.languages.refreshUser, 3000);
|
||||||
|
showAccountInfo();
|
||||||
|
const menuAccountElement = document.getElementById("menuAccount");
|
||||||
|
if (window.siyuan.user) {
|
||||||
|
menuAccountElement.innerHTML = `<img class="b3-menu__icon" src="${window.siyuan.user.userAvatarURL}"/><span class="b3-menu__label">${window.siyuan.user.userName}</span>`;
|
||||||
|
} else {
|
||||||
|
menuAccountElement.innerHTML = `<svg class="b3-menu__icon"><use xlink:href="#iconAccount"></use></svg><span class="b3-menu__label">${window.siyuan.languages.login}</span>`;
|
||||||
|
}
|
||||||
|
processSync();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
export const login = () => {
|
||||||
|
openModel({
|
||||||
|
title: window.siyuan.languages.login,
|
||||||
|
icon: "iconAccount",
|
||||||
|
html: `<div class="b3-form__space" id="form1">
|
||||||
|
<div class="b3-form__icon">
|
||||||
|
<svg class="b3-form__icon-icon"><use xlink:href="#iconAccount"></use></svg>
|
||||||
|
<input id="userName" class="b3-text-field fn__block b3-form__icon-input" placeholder="${window.siyuan.languages.accountName}">
|
||||||
|
</div>
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<div class="b3-form__icon">
|
||||||
|
<svg class="b3-form__icon-icon"><use xlink:href="#iconLock"></use></svg>
|
||||||
|
<input type="password" id="userPassword" class="b3-text-field b3-form__icon-input fn__block" placeholder="${window.siyuan.languages.password}">
|
||||||
|
</div>
|
||||||
|
<div class="b3-form__img fn__none">
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<img id="captchaImg" class="fn__pointer" style="top: 17px">
|
||||||
|
<input id="captcha" class="b3-text-field fn__block" placeholder="${window.siyuan.languages.captcha}">
|
||||||
|
</div>
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<label class="ft__smaller ft__on-surface fn__flex">
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<input type="checkbox" class="b3-switch fn__flex-center" id="agreeLogin">
|
||||||
|
<span class="fn__space"></span>
|
||||||
|
<span>${window.siyuan.languages.accountTip}</span>
|
||||||
|
</label>
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<button id="login" disabled class="b3-button fn__block">${window.siyuan.languages.login}</button>
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<div class="ft__center">
|
||||||
|
<a href="https://ld246.com/forget-pwd" class="b3-button b3-button--cancel" target="_blank">${window.siyuan.languages.forgetPassword}</a>
|
||||||
|
<span class="fn__space${window.siyuan.config.system.container === "ios" ? " fn__none" : ""}"></span>
|
||||||
|
<a href="https://ld246.com/register" class="b3-button b3-button--cancel${window.siyuan.config.system.container === "ios" ? " fn__none" : ""}" target="_blank">${window.siyuan.languages.register}</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="b3-form__space fn__none" id="form2">
|
||||||
|
<div class="b3-form__icon">
|
||||||
|
<svg class="b3-form__icon-icon"><use xlink:href="#iconLock"></use></svg>
|
||||||
|
<input id="twofactorAuthCode" class="b3-text-field fn__block b3-form__icon-input" placeholder="${window.siyuan.languages.twoFactorCaptcha}">
|
||||||
|
</div>
|
||||||
|
<div class="fn__hr--b"></div>
|
||||||
|
<button id="login2" class="b3-button fn__block">${window.siyuan.languages.login}</button>
|
||||||
|
</div>`,
|
||||||
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
|
const agreeLoginElement = modelMainElement.querySelector("#agreeLogin") as HTMLInputElement;
|
||||||
|
const userNameElement = modelMainElement.querySelector("#userName") as HTMLInputElement;
|
||||||
|
const userPasswordElement = modelMainElement.querySelector("#userPassword") as HTMLInputElement;
|
||||||
|
const captchaImgElement = modelMainElement.querySelector("#captchaImg") as HTMLInputElement;
|
||||||
|
const captchaElement = modelMainElement.querySelector("#captcha") as HTMLInputElement;
|
||||||
|
const twofactorAuthCodeElement = modelMainElement.querySelector("#twofactorAuthCode") as HTMLInputElement;
|
||||||
|
const loginBtnElement = modelMainElement.querySelector("#login") as HTMLButtonElement;
|
||||||
|
const login2BtnElement = modelMainElement.querySelector("#login2") as HTMLButtonElement;
|
||||||
|
userNameElement.focus();
|
||||||
|
let token: string;
|
||||||
|
let needCaptcha: string;
|
||||||
|
agreeLoginElement.addEventListener("click", () => {
|
||||||
|
if (agreeLoginElement.checked) {
|
||||||
|
loginBtnElement.removeAttribute("disabled");
|
||||||
|
} else {
|
||||||
|
loginBtnElement.setAttribute("disabled", "disabled");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
captchaImgElement.addEventListener("click", () => {
|
||||||
|
captchaImgElement.setAttribute("src", `https://ld246.com/captcha/login?needCaptcha=${needCaptcha}&t=${new Date().getTime()}`);
|
||||||
|
});
|
||||||
|
loginBtnElement.addEventListener("click", () => {
|
||||||
|
fetchPost("/api/account/login", {
|
||||||
|
userName: userNameElement.value.replace(/(^\s*)|(\s*$)/g, ""),
|
||||||
|
userPassword: md5(userPasswordElement.value),
|
||||||
|
captcha: captchaElement.value.replace(/(^\s*)|(\s*$)/g, ""),
|
||||||
|
}, (data) => {
|
||||||
|
if (data.code === 1) {
|
||||||
|
showMessage(data.msg);
|
||||||
|
if (data.data.needCaptcha) {
|
||||||
|
// 验证码
|
||||||
|
needCaptcha = data.data.needCaptcha;
|
||||||
|
captchaElement.parentElement.classList.remove("fn__none");
|
||||||
|
captchaElement.previousElementSibling.setAttribute("src",
|
||||||
|
`https://ld246.com/captcha/login?needCaptcha=${data.data.needCaptcha}`);
|
||||||
|
captchaElement.value = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (data.code === 10) {
|
||||||
|
// 两步验证
|
||||||
|
modelMainElement.querySelector("#form1").classList.add("fn__none");
|
||||||
|
modelMainElement.querySelector("#form2").classList.remove("fn__none");
|
||||||
|
twofactorAuthCodeElement.focus();
|
||||||
|
token = data.data.token;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fetchPost("/api/setting/getCloudUser", {
|
||||||
|
token: data.data.token,
|
||||||
|
}, response => {
|
||||||
|
window.siyuan.user = response.data;
|
||||||
|
closePanel();
|
||||||
|
document.getElementById("menuAccount").innerHTML = `<img class="b3-menu__icon" src="${window.siyuan.user.userAvatarURL}"/>
|
||||||
|
<span class="b3-menu__label">${window.siyuan.user.userName}</span>`;
|
||||||
|
processSync();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
login2BtnElement.addEventListener("click", () => {
|
||||||
|
fetchPost("/api/setting/login2faCloudUser", {
|
||||||
|
code: twofactorAuthCodeElement.value,
|
||||||
|
token,
|
||||||
|
}, faResponse => {
|
||||||
|
fetchPost("/api/setting/getCloudUser", {
|
||||||
|
token: faResponse.data.token,
|
||||||
|
}, response => {
|
||||||
|
window.siyuan.user = response.data;
|
||||||
|
closePanel();
|
||||||
|
document.getElementById("menuAccount").innerHTML = `<img class="b3-menu__icon" src="${window.siyuan.user.userAvatarURL}"/>
|
||||||
|
<span class="b3-menu__label">${window.siyuan.user.userName}</span>`;
|
||||||
|
processSync();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
14
app/src/mobile/settings/ai.ts
Normal file
14
app/src/mobile/settings/ai.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import {openModel} from "../util/model";
|
||||||
|
import {ai} from "../../config/ai";
|
||||||
|
|
||||||
|
export const initAI = () => {
|
||||||
|
openModel({
|
||||||
|
title: "AI",
|
||||||
|
icon: "iconSparkles",
|
||||||
|
html: ai.genHTML(),
|
||||||
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
|
ai.element = modelMainElement;
|
||||||
|
ai.bindEvent();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -2,12 +2,13 @@ import {fetchPost} from "../../util/fetch";
|
||||||
import {setInlineStyle} from "../../util/assets";
|
import {setInlineStyle} from "../../util/assets";
|
||||||
import {genOptions} from "../../util/genOptions";
|
import {genOptions} from "../../util/genOptions";
|
||||||
import {reloadProtyle} from "../../protyle/util/reload";
|
import {reloadProtyle} from "../../protyle/util/reload";
|
||||||
|
import {openModel} from "../util/model";
|
||||||
|
|
||||||
export const initAppearance = (modelElement: HTMLElement, modelMainElement: HTMLElement) => {
|
export const initAppearance = () => {
|
||||||
modelElement.style.top = "0";
|
openModel({
|
||||||
modelElement.querySelector(".toolbar__icon").innerHTML = '<use xlink:href="#iconTheme"></use>';
|
title: window.siyuan.languages.appearance,
|
||||||
modelElement.querySelector(".toolbar__text").textContent = window.siyuan.languages.appearance;
|
icon:"iconTheme",
|
||||||
modelMainElement.innerHTML = `<div class="b3-label">
|
html: `<div class="b3-label">
|
||||||
${window.siyuan.languages.appearance4}
|
${window.siyuan.languages.appearance4}
|
||||||
<div class="fn__hr"></div>
|
<div class="fn__hr"></div>
|
||||||
<select class="b3-select fn__block" id="mode">
|
<select class="b3-select fn__block" id="mode">
|
||||||
|
|
@ -49,29 +50,34 @@ export const initAppearance = (modelElement: HTMLElement, modelMainElement: HTML
|
||||||
<div class="fn__hr"></div>
|
<div class="fn__hr"></div>
|
||||||
<input class="b3-slider fn__block" max="72" min="9" step="1" type="range" value="${window.siyuan.config.editor.fontSize}">
|
<input class="b3-slider fn__block" max="72" min="9" step="1" type="range" value="${window.siyuan.config.editor.fontSize}">
|
||||||
<div class="b3-label__text">${window.siyuan.languages.fontSizeTip}</div>
|
<div class="b3-label__text">${window.siyuan.languages.fontSizeTip}</div>
|
||||||
</div>`;
|
</div>`,
|
||||||
modelMainElement.querySelector(".b3-slider").addEventListener("input", (event: InputEvent & { target: HTMLInputElement }) => {
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
modelMainElement.querySelector("#fontSize").textContent = event.target.value + "px";
|
modelMainElement.querySelector(".b3-slider").addEventListener("input", (event: InputEvent & {
|
||||||
window.siyuan.config.editor.fontSize = parseInt(event.target.value);
|
target: HTMLInputElement
|
||||||
fetchPost("/api/setting/setEditor", window.siyuan.config.editor, (response) => {
|
}) => {
|
||||||
window.siyuan.config.editor = response.data;
|
modelMainElement.querySelector("#fontSize").textContent = event.target.value + "px";
|
||||||
reloadProtyle(window.siyuan.mobile.editor.protyle);
|
window.siyuan.config.editor.fontSize = parseInt(event.target.value);
|
||||||
setInlineStyle();
|
fetchPost("/api/setting/setEditor", window.siyuan.config.editor, (response) => {
|
||||||
});
|
window.siyuan.config.editor = response.data;
|
||||||
});
|
reloadProtyle(window.siyuan.mobile.editor.protyle);
|
||||||
modelMainElement.querySelectorAll("select").forEach(item => {
|
setInlineStyle();
|
||||||
item.addEventListener("change", () => {
|
});
|
||||||
const modeElementValue = parseInt((modelMainElement.querySelector("#mode") as HTMLSelectElement).value);
|
|
||||||
fetchPost("/api/setting/setAppearance", Object.assign({}, window.siyuan.config.appearance, {
|
|
||||||
icon: (modelMainElement.querySelector("#icon") as HTMLSelectElement).value,
|
|
||||||
mode: modeElementValue === 2 ? window.siyuan.config.appearance.mode : modeElementValue,
|
|
||||||
modeOS: modeElementValue === 2,
|
|
||||||
themeDark: (modelMainElement.querySelector("#themeDark") as HTMLSelectElement).value,
|
|
||||||
themeLight: (modelMainElement.querySelector("#themeLight") as HTMLSelectElement).value,
|
|
||||||
lang: (modelMainElement.querySelector("#lang") as HTMLSelectElement).value,
|
|
||||||
}), () => {
|
|
||||||
window.location.reload();
|
|
||||||
});
|
});
|
||||||
});
|
modelMainElement.querySelectorAll("select").forEach(item => {
|
||||||
|
item.addEventListener("change", () => {
|
||||||
|
const modeElementValue = parseInt((modelMainElement.querySelector("#mode") as HTMLSelectElement).value);
|
||||||
|
fetchPost("/api/setting/setAppearance", Object.assign({}, window.siyuan.config.appearance, {
|
||||||
|
icon: (modelMainElement.querySelector("#icon") as HTMLSelectElement).value,
|
||||||
|
mode: modeElementValue === 2 ? window.siyuan.config.appearance.mode : modeElementValue,
|
||||||
|
modeOS: modeElementValue === 2,
|
||||||
|
themeDark: (modelMainElement.querySelector("#themeDark") as HTMLSelectElement).value,
|
||||||
|
themeLight: (modelMainElement.querySelector("#themeLight") as HTMLSelectElement).value,
|
||||||
|
lang: (modelMainElement.querySelector("#lang") as HTMLSelectElement).value,
|
||||||
|
}), () => {
|
||||||
|
window.location.reload();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
14
app/src/mobile/settings/riffCard.ts
Normal file
14
app/src/mobile/settings/riffCard.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
import {openModel} from "../util/model";
|
||||||
|
import {flashcard} from "../../config/flashcard";
|
||||||
|
|
||||||
|
export const initRiffCard = () => {
|
||||||
|
openModel({
|
||||||
|
title: window.siyuan.languages.riffCard,
|
||||||
|
icon: "iconRiffCard",
|
||||||
|
html: flashcard.genHTML(),
|
||||||
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
|
flashcard.element = modelMainElement;
|
||||||
|
flashcard.bindEvent();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
@ -67,7 +67,7 @@ export class MobileTags {
|
||||||
} else {
|
} else {
|
||||||
const modelElement = document.getElementById("model");
|
const modelElement = document.getElementById("model");
|
||||||
const modelMainElement = document.getElementById("modelMain");
|
const modelMainElement = document.getElementById("modelMain");
|
||||||
popSearch(modelElement, modelMainElement);
|
popSearch();
|
||||||
(document.getElementById("toolbarSearch") as HTMLInputElement).value = `#${element.getAttribute("data-label")}#`;
|
(document.getElementById("toolbarSearch") as HTMLInputElement).value = `#${element.getAttribute("data-label")}#`;
|
||||||
toolbarSearchEvent();
|
toolbarSearchEvent();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,118 +1,19 @@
|
||||||
import {fetchPost} from "../../util/fetch";
|
|
||||||
import {getEventName, openByMobile, writeText} from "../../protyle/util/compatibility";
|
|
||||||
import {popSearch} from "./search";
|
import {popSearch} from "./search";
|
||||||
import {initAppearance} from "../settings/appearance";
|
import {initAppearance} from "../settings/appearance";
|
||||||
import {closePanel} from "./closePanel";
|
import {closePanel} from "./closePanel";
|
||||||
import {Constants} from "../../constants";
|
|
||||||
import {setAccessAuthCode} from "../../config/util/setAccessAuthCode";
|
|
||||||
import {mountHelp, newDailyNote, newNotebook} from "../../util/mount";
|
import {mountHelp, newDailyNote, newNotebook} from "../../util/mount";
|
||||||
import {repos} from "../../config/repos";
|
import {repos} from "../../config/repos";
|
||||||
import * as md5 from "blueimp-md5";
|
|
||||||
import {showMessage} from "../../dialog/message";
|
|
||||||
import {exitSiYuan, lockScreen, processSync} from "../../dialog/processSystem";
|
import {exitSiYuan, lockScreen, processSync} from "../../dialog/processSystem";
|
||||||
import {confirmDialog} from "../../dialog/confirmDialog";
|
|
||||||
import {openHistory} from "../../history/history";
|
import {openHistory} from "../../history/history";
|
||||||
import {Dialog} from "../../dialog";
|
|
||||||
import {syncGuide} from "../../sync/syncGuide";
|
import {syncGuide} from "../../sync/syncGuide";
|
||||||
import {openCard} from "../../card/openCard";
|
import {openCard} from "../../card/openCard";
|
||||||
import {pathPosix} from "../../util/pathName";
|
|
||||||
import {activeBlur, hideKeyboardToolbar} from "./keyboardToolbar";
|
import {activeBlur, hideKeyboardToolbar} from "./keyboardToolbar";
|
||||||
|
import {initAI} from "../settings/ai";
|
||||||
|
import {initRiffCard} from "../settings/riffCard";
|
||||||
|
import {login, showAccountInfo} from "../settings/account";
|
||||||
|
import {openModel} from "./model";
|
||||||
|
import {initAbout} from "../settings/about";
|
||||||
|
|
||||||
const showAccountInfo = (modelElement: HTMLElement, modelMainElement: Element) => {
|
|
||||||
let userTitlesHTML = "";
|
|
||||||
if (window.siyuan.user.userTitles.length > 0) {
|
|
||||||
userTitlesHTML = '<div class="b3-chips" style="position: absolute">';
|
|
||||||
window.siyuan.user.userTitles.forEach((item) => {
|
|
||||||
userTitlesHTML += `<div class="b3-chip b3-chip--middle">${item.icon} ${item.name}</div>`;
|
|
||||||
});
|
|
||||||
userTitlesHTML += "</div>";
|
|
||||||
}
|
|
||||||
modelElement.style.top = "0";
|
|
||||||
modelElement.querySelector(".toolbar__icon").innerHTML = '<use xlink:href="#iconAccount"></use>';
|
|
||||||
modelElement.querySelector(".toolbar__text").textContent = window.siyuan.languages.accountManage;
|
|
||||||
modelMainElement.innerHTML = `<div class="fn__flex-column">
|
|
||||||
<div class="config-account__bg">
|
|
||||||
<div class="config-account__cover" style="background-image: url(${window.siyuan.user.userHomeBImgURL})"></div>
|
|
||||||
<a href="https://ld246.com/settings/avatar" class="config-account__avatar" style="background-image: url(${window.siyuan.user.userAvatarURL})" target="_blank"></a>
|
|
||||||
<h1 class="config-account__name">
|
|
||||||
<a target="_blank" class="fn__a" href="https://ld246.com/member/${window.siyuan.user.userName}">${window.siyuan.user.userName}</a>
|
|
||||||
</h1>
|
|
||||||
${userTitlesHTML}
|
|
||||||
</div>
|
|
||||||
<div class="config-account__info">
|
|
||||||
<div class="fn__flex">
|
|
||||||
<a class="b3-button b3-button--text" href="https://ld246.com/settings" target="_blank">${window.siyuan.languages.accountManage}</a>
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<button class="b3-button b3-button--cancel" id="logout">
|
|
||||||
${window.siyuan.languages.logout}
|
|
||||||
</button>
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<button class="b3-button b3-button--cancel" id="deactivateUser">
|
|
||||||
${window.siyuan.languages.deactivateUser}
|
|
||||||
</button>
|
|
||||||
<span class="fn__flex-1"></span>
|
|
||||||
<button class="b3-button b3-button--cancel" id="refresh">
|
|
||||||
<svg><use xlink:href="#iconRefresh"></use></svg>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div></div>`;
|
|
||||||
|
|
||||||
modelMainElement.querySelector("#logout").addEventListener(getEventName(), () => {
|
|
||||||
fetchPost("/api/setting/logoutCloudUser", {}, () => {
|
|
||||||
window.siyuan.user = null;
|
|
||||||
closePanel();
|
|
||||||
document.getElementById("menuAccount").innerHTML = `<svg class="b3-menu__icon"><use xlink:href="#iconAccount"></use></svg><span class="b3-menu__label">${window.siyuan.languages.login}</span>`;
|
|
||||||
processSync();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
modelMainElement.querySelector("#deactivateUser").addEventListener(getEventName(), () => {
|
|
||||||
confirmDialog("⚠️ " + window.siyuan.languages.deactivateUser, window.siyuan.languages.deactivateUserTip, () => {
|
|
||||||
fetchPost("/api/account/deactivate", {}, () => {
|
|
||||||
window.siyuan.user = null;
|
|
||||||
closePanel();
|
|
||||||
document.getElementById("menuAccount").innerHTML = `<svg class="b3-menu__icon"><use xlink:href="#iconAccount"></use></svg><span class="b3-menu__label">${window.siyuan.languages.login}</span>`;
|
|
||||||
processSync();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
const refreshElement = modelMainElement.querySelector("#refresh");
|
|
||||||
refreshElement.addEventListener("click", () => {
|
|
||||||
const svgElement = refreshElement.firstElementChild;
|
|
||||||
if (svgElement.classList.contains("fn__rotate")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
svgElement.classList.add("fn__rotate");
|
|
||||||
fetchPost("/api/setting/getCloudUser", {
|
|
||||||
token: window.siyuan.user.userToken,
|
|
||||||
}, response => {
|
|
||||||
window.siyuan.user = response.data;
|
|
||||||
showMessage(window.siyuan.languages.refreshUser, 3000);
|
|
||||||
showAccountInfo(modelElement, modelMainElement);
|
|
||||||
const menuAccountElement = document.getElementById("menuAccount");
|
|
||||||
if (window.siyuan.user) {
|
|
||||||
menuAccountElement.innerHTML = `<img class="b3-menu__icon" src="${window.siyuan.user.userAvatarURL}"/><span class="b3-menu__label">${window.siyuan.user.userName}</span>`;
|
|
||||||
} else {
|
|
||||||
menuAccountElement.innerHTML = `<svg class="b3-menu__icon"><use xlink:href="#iconAccount"></use></svg><span class="b3-menu__label">${window.siyuan.languages.login}</span>`;
|
|
||||||
}
|
|
||||||
processSync();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const genWorkspace = (workspaceDirElement: Element) => {
|
|
||||||
fetchPost("/api/system/getWorkspaces", {}, (response) => {
|
|
||||||
let html = "";
|
|
||||||
response.data.forEach((item: IWorkspace) => {
|
|
||||||
html += `<li data-path="${item.path}" class="b3-list-item b3-list-item--narrow${window.siyuan.config.system.workspaceDir === item.path ? " b3-list-item--focus" : ""}">
|
|
||||||
<span class="b3-list-item__text">${pathPosix().basename(item.path)}</span>
|
|
||||||
<span data-type="remove" class="b3-list-item__action">
|
|
||||||
<svg><use xlink:href="#iconMin"></use></svg>
|
|
||||||
</span>
|
|
||||||
</li>`;
|
|
||||||
});
|
|
||||||
workspaceDirElement.innerHTML = html;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
export const popMenu = () => {
|
export const popMenu = () => {
|
||||||
activeBlur();
|
activeBlur();
|
||||||
hideKeyboardToolbar();
|
hideKeyboardToolbar();
|
||||||
|
|
@ -161,6 +62,12 @@ ${accountHTML}
|
||||||
<svg class="b3-menu__icon"><use xlink:href="#iconHistory"></use></svg><span class="b3-menu__label">${window.siyuan.languages.dataHistory}</span>
|
<svg class="b3-menu__icon"><use xlink:href="#iconHistory"></use></svg><span class="b3-menu__label">${window.siyuan.languages.dataHistory}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="b3-menu__separator"></div>
|
<div class="b3-menu__separator"></div>
|
||||||
|
<div class="b3-menu__item${window.siyuan.config.readonly ? " fn__none" : ""}" id="menuRiffCard">
|
||||||
|
<svg class="b3-menu__icon"><use xlink:href="#iconRiffCard"></use></svg><span class="b3-menu__label">${window.siyuan.languages.riffCard}</span>
|
||||||
|
</div>
|
||||||
|
<div class="b3-menu__item${window.siyuan.config.readonly ? " fn__none" : ""}" id="menuAI">
|
||||||
|
<svg class="b3-menu__icon"><use xlink:href="#iconSparkles"></use></svg><span class="b3-menu__label">AI</span>
|
||||||
|
</div>
|
||||||
<div class="b3-menu__item${window.siyuan.config.readonly ? " fn__none" : ""}" id="menuAppearance">
|
<div class="b3-menu__item${window.siyuan.config.readonly ? " fn__none" : ""}" id="menuAppearance">
|
||||||
<svg class="b3-menu__icon"><use xlink:href="#iconTheme"></use></svg><span class="b3-menu__label">${window.siyuan.languages.appearance}</span>
|
<svg class="b3-menu__icon"><use xlink:href="#iconTheme"></use></svg><span class="b3-menu__label">${window.siyuan.languages.appearance}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -182,10 +89,8 @@ ${accountHTML}
|
||||||
<div class="b3-menu__item${(window.webkit?.messageHandlers || window.JSAndroid) ? "" : " fn__none"}" id="menuSafeQuit">
|
<div class="b3-menu__item${(window.webkit?.messageHandlers || window.JSAndroid) ? "" : " fn__none"}" id="menuSafeQuit">
|
||||||
<svg class="b3-menu__icon"><use xlink:href="#iconQuit"></use></svg><span class="b3-menu__label">${window.siyuan.languages.safeQuit}</span>
|
<svg class="b3-menu__icon"><use xlink:href="#iconQuit"></use></svg><span class="b3-menu__label">${window.siyuan.languages.safeQuit}</span>
|
||||||
</div>`;
|
</div>`;
|
||||||
// 只能用 click,否则无法上下滚动 https://github.com/siyuan-note/siyuan/issues/6628
|
|
||||||
processSync();
|
processSync();
|
||||||
const modelElement = document.getElementById("model");
|
// 只能用 click,否则无法上下滚动 https://github.com/siyuan-note/siyuan/issues/6628
|
||||||
const modelMainElement = document.getElementById("modelMain");
|
|
||||||
menuElement.addEventListener("click", (event) => {
|
menuElement.addEventListener("click", (event) => {
|
||||||
let target = event.target as HTMLElement;
|
let target = event.target as HTMLElement;
|
||||||
while (target && !target.isEqualNode(menuElement)) {
|
while (target && !target.isEqualNode(menuElement)) {
|
||||||
|
|
@ -195,12 +100,22 @@ ${accountHTML}
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "menuSearch") {
|
} else if (target.id === "menuSearch") {
|
||||||
popSearch(modelElement, modelMainElement);
|
popSearch();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "menuAppearance") {
|
} else if (target.id === "menuAppearance") {
|
||||||
initAppearance(modelElement, modelMainElement);
|
initAppearance();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "menuAI") {
|
||||||
|
initAI();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
} else if (target.id === "menuRiffCard") {
|
||||||
|
initRiffCard();
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
|
|
@ -243,12 +158,15 @@ ${accountHTML}
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
} else if (target.id === "menuSync") {
|
} else if (target.id === "menuSync") {
|
||||||
modelElement.style.top = "0";
|
openModel({
|
||||||
modelElement.querySelector(".toolbar__icon").innerHTML = '<use xlink:href="#iconCloud"></use>';
|
title: window.siyuan.languages.cloud,
|
||||||
modelElement.querySelector(".toolbar__text").textContent = window.siyuan.languages.cloud;
|
icon: "iconCloud",
|
||||||
modelMainElement.innerHTML = repos.genHTML();
|
html: repos.genHTML(),
|
||||||
repos.element = modelMainElement;
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
repos.bindEvent();
|
repos.element = modelMainElement;
|
||||||
|
repos.bindEvent();
|
||||||
|
}
|
||||||
|
});
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
break;
|
break;
|
||||||
|
|
@ -267,127 +185,10 @@ ${accountHTML}
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
if (document.querySelector("#menuAccount img")) {
|
if (document.querySelector("#menuAccount img")) {
|
||||||
showAccountInfo(modelElement, modelMainElement);
|
showAccountInfo();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
modelElement.style.top = "0";
|
login();
|
||||||
modelElement.querySelector(".toolbar__icon").innerHTML = '<use xlink:href="#iconAccount"></use>';
|
|
||||||
modelElement.querySelector(".toolbar__text").textContent = window.siyuan.languages.login;
|
|
||||||
modelMainElement.innerHTML = `<div class="b3-form__space" id="form1">
|
|
||||||
<div class="b3-form__icon">
|
|
||||||
<svg class="b3-form__icon-icon"><use xlink:href="#iconAccount"></use></svg>
|
|
||||||
<input id="userName" class="b3-text-field fn__block b3-form__icon-input" placeholder="${window.siyuan.languages.accountName}">
|
|
||||||
</div>
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<div class="b3-form__icon">
|
|
||||||
<svg class="b3-form__icon-icon"><use xlink:href="#iconLock"></use></svg>
|
|
||||||
<input type="password" id="userPassword" class="b3-text-field b3-form__icon-input fn__block" placeholder="${window.siyuan.languages.password}">
|
|
||||||
</div>
|
|
||||||
<div class="b3-form__img fn__none">
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<img id="captchaImg" class="fn__pointer" style="top: 17px">
|
|
||||||
<input id="captcha" class="b3-text-field fn__block" placeholder="${window.siyuan.languages.captcha}">
|
|
||||||
</div>
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<label class="ft__smaller ft__on-surface fn__flex">
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<input type="checkbox" class="b3-switch fn__flex-center" id="agreeLogin">
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<span>${window.siyuan.languages.accountTip}</span>
|
|
||||||
</label>
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<button id="login" disabled class="b3-button fn__block">${window.siyuan.languages.login}</button>
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<div class="ft__center">
|
|
||||||
<a href="https://ld246.com/forget-pwd" class="b3-button b3-button--cancel" target="_blank">${window.siyuan.languages.forgetPassword}</a>
|
|
||||||
<span class="fn__space${window.siyuan.config.system.container === "ios" ? " fn__none" : ""}"></span>
|
|
||||||
<a href="https://ld246.com/register" class="b3-button b3-button--cancel${window.siyuan.config.system.container === "ios" ? " fn__none" : ""}" target="_blank">${window.siyuan.languages.register}</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="b3-form__space fn__none" id="form2">
|
|
||||||
<div class="b3-form__icon">
|
|
||||||
<svg class="b3-form__icon-icon"><use xlink:href="#iconLock"></use></svg>
|
|
||||||
<input id="twofactorAuthCode" class="b3-text-field fn__block b3-form__icon-input" placeholder="${window.siyuan.languages.twoFactorCaptcha}">
|
|
||||||
</div>
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<button id="login2" class="b3-button fn__block">${window.siyuan.languages.login}</button>
|
|
||||||
</div>`;
|
|
||||||
const agreeLoginElement = modelMainElement.querySelector("#agreeLogin") as HTMLInputElement;
|
|
||||||
const userNameElement = modelMainElement.querySelector("#userName") as HTMLInputElement;
|
|
||||||
const userPasswordElement = modelMainElement.querySelector("#userPassword") as HTMLInputElement;
|
|
||||||
const captchaImgElement = modelMainElement.querySelector("#captchaImg") as HTMLInputElement;
|
|
||||||
const captchaElement = modelMainElement.querySelector("#captcha") as HTMLInputElement;
|
|
||||||
const twofactorAuthCodeElement = modelMainElement.querySelector("#twofactorAuthCode") as HTMLInputElement;
|
|
||||||
const loginBtnElement = modelMainElement.querySelector("#login") as HTMLButtonElement;
|
|
||||||
const login2BtnElement = modelMainElement.querySelector("#login2") as HTMLButtonElement;
|
|
||||||
userNameElement.focus();
|
|
||||||
let token: string;
|
|
||||||
let needCaptcha: string;
|
|
||||||
agreeLoginElement.addEventListener("click", () => {
|
|
||||||
if (agreeLoginElement.checked) {
|
|
||||||
loginBtnElement.removeAttribute("disabled");
|
|
||||||
} else {
|
|
||||||
loginBtnElement.setAttribute("disabled", "disabled");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
captchaImgElement.addEventListener("click", () => {
|
|
||||||
captchaImgElement.setAttribute("src", `https://ld246.com/captcha/login?needCaptcha=${needCaptcha}&t=${new Date().getTime()}`);
|
|
||||||
});
|
|
||||||
loginBtnElement.addEventListener("click", () => {
|
|
||||||
fetchPost("/api/account/login", {
|
|
||||||
userName: userNameElement.value.replace(/(^\s*)|(\s*$)/g, ""),
|
|
||||||
userPassword: md5(userPasswordElement.value),
|
|
||||||
captcha: captchaElement.value.replace(/(^\s*)|(\s*$)/g, ""),
|
|
||||||
}, (data) => {
|
|
||||||
if (data.code === 1) {
|
|
||||||
showMessage(data.msg);
|
|
||||||
if (data.data.needCaptcha) {
|
|
||||||
// 验证码
|
|
||||||
needCaptcha = data.data.needCaptcha;
|
|
||||||
captchaElement.parentElement.classList.remove("fn__none");
|
|
||||||
captchaElement.previousElementSibling.setAttribute("src",
|
|
||||||
`https://ld246.com/captcha/login?needCaptcha=${data.data.needCaptcha}`);
|
|
||||||
captchaElement.value = "";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (data.code === 10) {
|
|
||||||
// 两步验证
|
|
||||||
modelMainElement.querySelector("#form1").classList.add("fn__none");
|
|
||||||
modelMainElement.querySelector("#form2").classList.remove("fn__none");
|
|
||||||
twofactorAuthCodeElement.focus();
|
|
||||||
token = data.data.token;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
fetchPost("/api/setting/getCloudUser", {
|
|
||||||
token: data.data.token,
|
|
||||||
}, response => {
|
|
||||||
window.siyuan.user = response.data;
|
|
||||||
closePanel();
|
|
||||||
document.getElementById("menuAccount").innerHTML = `<img class="b3-menu__icon" src="${window.siyuan.user.userAvatarURL}"/>
|
|
||||||
<span class="b3-menu__label">${window.siyuan.user.userName}</span>`;
|
|
||||||
processSync();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
login2BtnElement.addEventListener("click", () => {
|
|
||||||
fetchPost("/api/setting/login2faCloudUser", {
|
|
||||||
code: twofactorAuthCodeElement.value,
|
|
||||||
token,
|
|
||||||
}, faResponse => {
|
|
||||||
fetchPost("/api/setting/getCloudUser", {
|
|
||||||
token: faResponse.data.token,
|
|
||||||
}, response => {
|
|
||||||
window.siyuan.user = response.data;
|
|
||||||
closePanel();
|
|
||||||
document.getElementById("menuAccount").innerHTML = `<img class="b3-menu__icon" src="${window.siyuan.user.userAvatarURL}"/>
|
|
||||||
<span class="b3-menu__label">${window.siyuan.user.userName}</span>`;
|
|
||||||
processSync();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
target = target.parentElement;
|
target = target.parentElement;
|
||||||
|
|
@ -395,361 +196,3 @@ ${accountHTML}
|
||||||
});
|
});
|
||||||
menuElement.style.right = "0";
|
menuElement.style.right = "0";
|
||||||
};
|
};
|
||||||
|
|
||||||
const initAbout = () => {
|
|
||||||
if (!window.siyuan.config.localIPs || window.siyuan.config.localIPs.length === 0 ||
|
|
||||||
(window.siyuan.config.localIPs.length === 1 && window.siyuan.config.localIPs[0] === "")) {
|
|
||||||
window.siyuan.config.localIPs = ["127.0.0.1"];
|
|
||||||
}
|
|
||||||
const modelElement = document.getElementById("model");
|
|
||||||
const modelMainElement = document.getElementById("modelMain");
|
|
||||||
|
|
||||||
modelElement.style.top = "0";
|
|
||||||
modelElement.querySelector(".toolbar__icon").innerHTML = '<use xlink:href="#iconInfo"></use>';
|
|
||||||
modelElement.querySelector(".toolbar__text").textContent = window.siyuan.languages.about;
|
|
||||||
modelMainElement.innerHTML = `<div class="b3-label fn__flex${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
<div class="fn__flex-1">
|
|
||||||
${window.siyuan.languages.about11}
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.about12}</div>
|
|
||||||
</div>
|
|
||||||
<div class="fn__space"></div>
|
|
||||||
<input class="b3-switch fn__flex-center" id="networkServe" type="checkbox"${window.siyuan.config.system.networkServe ? " checked" : ""}>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label">
|
|
||||||
${window.siyuan.languages.about2}
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<input class="b3-text-field fn__block" readonly value="http://${window.siyuan.config.system.networkServe ? window.siyuan.config.localIPs[0] : "127.0.0.1"}:${location.port}">
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.about3.replace("${port}", location.port)}</div>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<span class="b3-label__text"><code class="fn__code">${window.siyuan.config.localIPs.join("</code> <code class='fn__code'>")}</code></span>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
${window.siyuan.languages.about5}
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="authCode">
|
|
||||||
<svg><use xlink:href="#iconLock"></use></svg>${window.siyuan.languages.config}
|
|
||||||
</button>
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.about6}</div>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
${window.siyuan.languages.dataRepoKey}
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<div class="${window.siyuan.config.repo.key ? "fn__none" : ""}">
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="importKey">
|
|
||||||
<svg><use xlink:href="#iconDownload"></use></svg>${window.siyuan.languages.importKey}
|
|
||||||
</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="initKey">
|
|
||||||
<svg><use xlink:href="#iconLock"></use></svg>${window.siyuan.languages.genKey}
|
|
||||||
</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="initKeyByPW">
|
|
||||||
${window.siyuan.languages.genKeyByPW}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="${window.siyuan.config.repo.key ? "" : "fn__none"}">
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="copyKey">
|
|
||||||
<svg><use xlink:href="#iconCopy"></use></svg>${window.siyuan.languages.copyKey}
|
|
||||||
</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="removeKey">
|
|
||||||
<svg><use xlink:href="#iconTrashcan"></use></svg>${window.siyuan.languages.resetRepo}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.dataRepoKeyTip1}</div>
|
|
||||||
<div class="b3-label__text ft__error">${window.siyuan.languages.dataRepoKeyTip2}</div>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
${window.siyuan.languages.about13}
|
|
||||||
<span class="b3-label__text">${window.siyuan.config.api.token}</span>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="token">
|
|
||||||
<svg><use xlink:href="#iconCopy"></use></svg>${window.siyuan.languages.copy}
|
|
||||||
</button>
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.about14}</div>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
<div class="fn__flex">
|
|
||||||
${window.siyuan.languages.export}
|
|
||||||
</div>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="exportData">
|
|
||||||
<svg><use xlink:href="#iconUpload"></use></svg>Data
|
|
||||||
</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.exportDataTip}</div>
|
|
||||||
<div class="fn__hr--b"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" id="exportLog">
|
|
||||||
<svg><use xlink:href="#iconUpload"></use></svg>${window.siyuan.languages.systemLog}
|
|
||||||
</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.systemLogTip}</div>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
<div class="fn__flex">
|
|
||||||
${window.siyuan.languages.import}
|
|
||||||
</div>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button class="b3-button b3-button--outline fn__block" style="position: relative">
|
|
||||||
<input id="importData" class="b3-form__upload" type="file">
|
|
||||||
<svg><use xlink:href="#iconDownload"></use></svg> ${window.siyuan.languages.import} Data
|
|
||||||
</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<div class="b3-label__text">${window.siyuan.languages.importDataTip}</div>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label${window.siyuan.config.readonly ? " fn__none" : ""}">
|
|
||||||
${window.siyuan.languages.workspaceList}
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button id="openWorkspace" class="b3-button b3-button--outline fn__block">${window.siyuan.languages.openBy}...</button>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<ul id="workspaceDir" class="b3-list b3-list--background"></ul>
|
|
||||||
<div class="fn__hr"></div>
|
|
||||||
<button id="creatWorkspace" class="b3-button fn__block">${window.siyuan.languages.new}</button>
|
|
||||||
</div>
|
|
||||||
<div class="b3-label">
|
|
||||||
<div class="config-about__logo">
|
|
||||||
<img src="/stage/icon.png">
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<div>
|
|
||||||
<span>${window.siyuan.languages.siyuanNote}</span>
|
|
||||||
<span class="fn__space"></span>
|
|
||||||
<span class="ft__on-surface">v${Constants.SIYUAN_VERSION}</span>
|
|
||||||
<br>
|
|
||||||
<span class="ft__on-surface">${window.siyuan.languages.slogan}</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div style="color:var(--b3-theme-surface);font-family: cursive;">会泽百家 至公天下</div>
|
|
||||||
${window.siyuan.languages.about1}
|
|
||||||
</div>`;
|
|
||||||
const workspaceDirElement = modelMainElement.querySelector("#workspaceDir");
|
|
||||||
genWorkspace(workspaceDirElement);
|
|
||||||
const importKeyElement = modelMainElement.querySelector("#importKey");
|
|
||||||
modelMainElement.addEventListener("click", (event) => {
|
|
||||||
let target = event.target as HTMLElement;
|
|
||||||
while (target && !target.isSameNode(modelMainElement)) {
|
|
||||||
if (target.id === "authCode") {
|
|
||||||
setAccessAuthCode();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "importKey") {
|
|
||||||
const passwordDialog = new Dialog({
|
|
||||||
title: "🔑 " + window.siyuan.languages.key,
|
|
||||||
content: `<div class="b3-dialog__content">
|
|
||||||
<textarea class="b3-text-field fn__block" placeholder="${window.siyuan.languages.keyPlaceholder}"></textarea>
|
|
||||||
</div>
|
|
||||||
<div class="b3-dialog__action">
|
|
||||||
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
|
||||||
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
|
||||||
</div>`,
|
|
||||||
width: "80vw",
|
|
||||||
});
|
|
||||||
const textAreaElement = passwordDialog.element.querySelector("textarea");
|
|
||||||
textAreaElement.focus();
|
|
||||||
const btnsElement = passwordDialog.element.querySelectorAll(".b3-button");
|
|
||||||
btnsElement[0].addEventListener("click", () => {
|
|
||||||
passwordDialog.destroy();
|
|
||||||
});
|
|
||||||
btnsElement[1].addEventListener("click", () => {
|
|
||||||
fetchPost("/api/repo/importRepoKey", {key: textAreaElement.value}, () => {
|
|
||||||
window.siyuan.config.repo.key = textAreaElement.value;
|
|
||||||
importKeyElement.parentElement.classList.add("fn__none");
|
|
||||||
importKeyElement.parentElement.nextElementSibling.classList.remove("fn__none");
|
|
||||||
passwordDialog.destroy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "initKey") {
|
|
||||||
confirmDialog("🔑 " + window.siyuan.languages.genKey, window.siyuan.languages.initRepoKeyTip, () => {
|
|
||||||
fetchPost("/api/repo/initRepoKey", {}, (response) => {
|
|
||||||
window.siyuan.config.repo.key = response.data.key;
|
|
||||||
importKeyElement.parentElement.classList.add("fn__none");
|
|
||||||
importKeyElement.parentElement.nextElementSibling.classList.remove("fn__none");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "initKeyByPW") {
|
|
||||||
const initDialog = new Dialog({
|
|
||||||
title: "🔑 " + window.siyuan.languages.genKeyByPW,
|
|
||||||
content: `<div class="b3-dialog__content">
|
|
||||||
<input class="b3-text-field fn__block" placeholder="${window.siyuan.languages.password}">
|
|
||||||
</div>
|
|
||||||
<div class="b3-dialog__action">
|
|
||||||
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
|
||||||
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
|
||||||
</div>`,
|
|
||||||
width: "80vw",
|
|
||||||
});
|
|
||||||
const inputElement = initDialog.element.querySelector(".b3-text-field") as HTMLInputElement;
|
|
||||||
inputElement.focus();
|
|
||||||
const btnsElement = initDialog.element.querySelectorAll(".b3-button");
|
|
||||||
initDialog.bindInput(inputElement, () => {
|
|
||||||
(btnsElement[1] as HTMLButtonElement).click();
|
|
||||||
});
|
|
||||||
btnsElement[0].addEventListener("click", () => {
|
|
||||||
initDialog.destroy();
|
|
||||||
});
|
|
||||||
btnsElement[1].addEventListener("click", () => {
|
|
||||||
if (!inputElement.value) {
|
|
||||||
showMessage(window.siyuan.languages._kernel[142]);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
confirmDialog("🔑 " + window.siyuan.languages.genKeyByPW, window.siyuan.languages.initRepoKeyTip, () => {
|
|
||||||
initDialog.destroy();
|
|
||||||
fetchPost("/api/repo/initRepoKeyFromPassphrase", {pass: inputElement.value}, (response) => {
|
|
||||||
window.siyuan.config.repo.key = response.data.key;
|
|
||||||
importKeyElement.parentElement.classList.add("fn__none");
|
|
||||||
importKeyElement.parentElement.nextElementSibling.classList.remove("fn__none");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "copyKey") {
|
|
||||||
showMessage(window.siyuan.languages.copied);
|
|
||||||
writeText(window.siyuan.config.repo.key);
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "removeKey") {
|
|
||||||
confirmDialog("⚠️ " + window.siyuan.languages.resetRepo, window.siyuan.languages.resetRepoTip, () => {
|
|
||||||
fetchPost("/api/repo/resetRepo", {}, () => {
|
|
||||||
window.siyuan.config.repo.key = "";
|
|
||||||
window.siyuan.config.sync.enabled = false;
|
|
||||||
processSync();
|
|
||||||
importKeyElement.parentElement.classList.remove("fn__none");
|
|
||||||
importKeyElement.parentElement.nextElementSibling.classList.add("fn__none");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "token") {
|
|
||||||
showMessage(window.siyuan.languages.copied);
|
|
||||||
writeText(window.siyuan.config.api.token);
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "exportData") {
|
|
||||||
fetchPost("/api/export/exportData", {}, response => {
|
|
||||||
openByMobile(response.data.zip);
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "exportLog") {
|
|
||||||
fetchPost("/api/system/exportLog", {}, (response) => {
|
|
||||||
openByMobile(response.data.zip);
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "openWorkspace") {
|
|
||||||
fetchPost("/api/system/getMobileWorkspaces", {}, (response) => {
|
|
||||||
let selectHTML = "";
|
|
||||||
response.data.forEach((item: string, index: number) => {
|
|
||||||
selectHTML += `<option value="${item}"${index === 0 ? ' selected="selected"' : ""}>${pathPosix().basename(item)}</option>`;
|
|
||||||
});
|
|
||||||
const openWorkspaceDialog = new Dialog({
|
|
||||||
title: window.siyuan.languages.openBy,
|
|
||||||
content: `<div class="b3-dialog__content">
|
|
||||||
<select class="b3-text-field fn__block">${selectHTML}</select>
|
|
||||||
</div>
|
|
||||||
<div class="b3-dialog__action">
|
|
||||||
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
|
||||||
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
|
||||||
</div>`,
|
|
||||||
width: "80vw",
|
|
||||||
});
|
|
||||||
const btnsElement = openWorkspaceDialog.element.querySelectorAll(".b3-button");
|
|
||||||
btnsElement[0].addEventListener("click", () => {
|
|
||||||
openWorkspaceDialog.destroy();
|
|
||||||
});
|
|
||||||
btnsElement[1].addEventListener("click", () => {
|
|
||||||
const openPath = openWorkspaceDialog.element.querySelector("select").value;
|
|
||||||
if (openPath === window.siyuan.config.system.workspaceDir) {
|
|
||||||
openWorkspaceDialog.destroy();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
confirmDialog(window.siyuan.languages.confirm, `${pathPosix().basename(window.siyuan.config.system.workspaceDir)} -> ${pathPosix().basename(openPath)}?`, () => {
|
|
||||||
fetchPost("/api/system/setWorkspaceDir", {
|
|
||||||
path: openPath
|
|
||||||
}, () => {
|
|
||||||
exitSiYuan();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.id === "creatWorkspace") {
|
|
||||||
const createWorkspaceDialog = new Dialog({
|
|
||||||
title: window.siyuan.languages.new,
|
|
||||||
content: `<div class="b3-dialog__content">
|
|
||||||
<input class="b3-text-field fn__block">
|
|
||||||
</div>
|
|
||||||
<div class="b3-dialog__action">
|
|
||||||
<button class="b3-button b3-button--cancel">${window.siyuan.languages.cancel}</button><div class="fn__space"></div>
|
|
||||||
<button class="b3-button b3-button--text">${window.siyuan.languages.confirm}</button>
|
|
||||||
</div>`,
|
|
||||||
width: "80vw",
|
|
||||||
});
|
|
||||||
const inputElement = createWorkspaceDialog.element.querySelector("input");
|
|
||||||
inputElement.focus();
|
|
||||||
const btnsElement = createWorkspaceDialog.element.querySelectorAll(".b3-button");
|
|
||||||
btnsElement[0].addEventListener("click", () => {
|
|
||||||
createWorkspaceDialog.destroy();
|
|
||||||
});
|
|
||||||
btnsElement[1].addEventListener("click", () => {
|
|
||||||
fetchPost("/api/system/createWorkspaceDir", {
|
|
||||||
path: pathPosix().join(pathPosix().dirname(window.siyuan.config.system.workspaceDir), inputElement.value)
|
|
||||||
}, () => {
|
|
||||||
genWorkspace(workspaceDirElement);
|
|
||||||
createWorkspaceDialog.destroy();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.getAttribute("data-type") === "remove") {
|
|
||||||
fetchPost("/api/system/removeWorkspaceDir", {path: target.parentElement.getAttribute("data-path")}, () => {
|
|
||||||
genWorkspace(workspaceDirElement);
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
} else if (target.classList.contains("b3-list-item") && !target.classList.contains("b3-list-item--focus")) {
|
|
||||||
confirmDialog(window.siyuan.languages.confirm, `${pathPosix().basename(window.siyuan.config.system.workspaceDir)} -> ${pathPosix().basename(target.getAttribute("data-path"))}?`, () => {
|
|
||||||
fetchPost("/api/system/setWorkspaceDir", {
|
|
||||||
path: target.getAttribute("data-path")
|
|
||||||
}, () => {
|
|
||||||
exitSiYuan();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
target = target.parentElement;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
modelMainElement.querySelector("#importData").addEventListener("change", (event: InputEvent & {
|
|
||||||
target: HTMLInputElement
|
|
||||||
}) => {
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append("file", event.target.files[0]);
|
|
||||||
fetchPost("/api/import/importData", formData);
|
|
||||||
});
|
|
||||||
const networkServeElement = modelMainElement.querySelector("#networkServe") as HTMLInputElement;
|
|
||||||
networkServeElement.addEventListener("change", () => {
|
|
||||||
fetchPost("/api/system/setNetworkServe", {networkServe: networkServeElement.checked}, () => {
|
|
||||||
exitSiYuan();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
|
||||||
14
app/src/mobile/util/model.ts
Normal file
14
app/src/mobile/util/model.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
export const openModel = (obj: {
|
||||||
|
html: string,
|
||||||
|
icon: string,
|
||||||
|
title: string,
|
||||||
|
bindEvent: (element: HTMLElement) => void
|
||||||
|
}) => {
|
||||||
|
const modelElement = document.getElementById("model")
|
||||||
|
modelElement.style.top = "0";
|
||||||
|
modelElement.querySelector(".toolbar__icon use").setAttribute("xlink:href", "#" + obj.icon);
|
||||||
|
modelElement.querySelector(".toolbar__text").innerHTML = obj.title
|
||||||
|
const modelMainElement = modelElement.querySelector("#modelMain") as HTMLElement;
|
||||||
|
modelMainElement.innerHTML = obj.html;
|
||||||
|
obj.bindEvent(modelMainElement);
|
||||||
|
}
|
||||||
|
|
@ -5,6 +5,7 @@ import {fetchPost} from "../../util/fetch";
|
||||||
import {getIconByType} from "../../editor/getIcon";
|
import {getIconByType} from "../../editor/getIcon";
|
||||||
import {preventScroll} from "../../protyle/scroll/preventScroll";
|
import {preventScroll} from "../../protyle/scroll/preventScroll";
|
||||||
import {setStorageVal} from "../../protyle/util/compatibility";
|
import {setStorageVal} from "../../protyle/util/compatibility";
|
||||||
|
import {openModel} from "./model";
|
||||||
|
|
||||||
const onRecentBlocks = (data: IBlock[], matchedRootCount?:number, matchedBlockCount?:number) => {
|
const onRecentBlocks = (data: IBlock[], matchedRootCount?:number, matchedBlockCount?:number) => {
|
||||||
let resultHTML = "";
|
let resultHTML = "";
|
||||||
|
|
@ -61,32 +62,35 @@ const initToolbarSearch = () => {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
export const popSearch = (modelElement: HTMLElement, modelMainElement: HTMLElement) => {
|
export const popSearch = () => {
|
||||||
modelElement.style.top = "0";
|
openModel({
|
||||||
modelElement.querySelector(".toolbar__icon").innerHTML = '<use xlink:href="#iconSearch"></use>';
|
title: '<input id="toolbarSearch" style="background-color: var(--b3-theme-surface);border: 0;" class="b3-text-field fn__block">',
|
||||||
modelElement.querySelector(".toolbar__text").innerHTML = '<input id="toolbarSearch" style="background-color: var(--b3-theme-surface);border: 0;" class="b3-text-field fn__block">';
|
icon:"iconSearch",
|
||||||
modelMainElement.innerHTML = '<div id="searchPanel"></div>';
|
html: '<div id="searchPanel"></div>',
|
||||||
initToolbarSearch();
|
bindEvent(modelMainElement: HTMLElement) {
|
||||||
const searchElement = document.getElementById("searchPanel");
|
initToolbarSearch();
|
||||||
// 不能使用 getEventName() https://ld246.com/article/1638887457149
|
const searchElement = document.getElementById("searchPanel");
|
||||||
searchElement.addEventListener("click", (event) => {
|
// 不能使用 getEventName() https://ld246.com/article/1638887457149
|
||||||
let target = event.target as HTMLElement;
|
searchElement.addEventListener("click", (event) => {
|
||||||
while (target && !target.isEqualNode(searchElement)) {
|
let target = event.target as HTMLElement;
|
||||||
if (target.classList.contains("b3-list-item")) {
|
while (target && !target.isEqualNode(searchElement)) {
|
||||||
const id = target.getAttribute("data-id");
|
if (target.classList.contains("b3-list-item")) {
|
||||||
if (window.siyuan.mobile.editor.protyle) {
|
const id = target.getAttribute("data-id");
|
||||||
preventScroll(window.siyuan.mobile.editor.protyle);
|
if (window.siyuan.mobile.editor.protyle) {
|
||||||
|
preventScroll(window.siyuan.mobile.editor.protyle);
|
||||||
|
}
|
||||||
|
fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
|
||||||
|
openMobileFileById(id,foldResponse.data ? [Constants.CB_GET_ALL, Constants.CB_GET_HL] : [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]);
|
||||||
|
});
|
||||||
|
closePanel();
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
target = target.parentElement;
|
||||||
}
|
}
|
||||||
fetchPost("/api/block/checkBlockFold", {id}, (foldResponse) => {
|
}, false);
|
||||||
openMobileFileById(id,foldResponse.data ? [Constants.CB_GET_ALL, Constants.CB_GET_HL] : [Constants.CB_GET_HL, Constants.CB_GET_CONTEXT]);
|
toolbarSearchEvent();
|
||||||
});
|
|
||||||
closePanel();
|
|
||||||
event.preventDefault();
|
|
||||||
event.stopPropagation();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
target = target.parentElement;
|
|
||||||
}
|
}
|
||||||
}, false);
|
})
|
||||||
toolbarSearchEvent();
|
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue