From b36c420063ec2a8bd87658bef47c3ae8fc2e2605 Mon Sep 17 00:00:00 2001 From: Vanessa Date: Fri, 21 Jul 2023 22:46:28 +0800 Subject: [PATCH] :art: https://github.com/siyuan-note/siyuan/issues/8621 --- app/src/assets/scss/component/_menu.scss | 1 + app/src/assets/scss/mobile.scss | 17 +- app/src/mobile/util/keyboardToolbar.ts | 237 ++++++++++++++++++----- app/src/protyle/toolbar/Font.ts | 26 +-- 4 files changed, 210 insertions(+), 71 deletions(-) diff --git a/app/src/assets/scss/component/_menu.scss b/app/src/assets/scss/component/_menu.scss index e39d9d6d7..4434389eb 100644 --- a/app/src/assets/scss/component/_menu.scss +++ b/app/src/assets/scss/component/_menu.scss @@ -53,6 +53,7 @@ box-shadow: none; border: 0; padding: 24px 0; + border-radius: 0; & > .b3-menu__item:first-child { border-top: .5px solid var(--b3-theme-background-light); diff --git a/app/src/assets/scss/mobile.scss b/app/src/assets/scss/mobile.scss index 96fd74d40..1156e8eb8 100644 --- a/app/src/assets/scss/mobile.scss +++ b/app/src/assets/scss/mobile.scss @@ -327,27 +327,28 @@ &__slash { &-title { height: 24px; + padding: 0 8px; + line-height: 24px; + color: var(--b3-theme-on-surface); } &-block { display: flex; - padding: 0px 0 8px 8px; + padding-left: 8px; + flex-wrap: wrap; } &-item { background-color: var(--b3-theme-background); border-radius: var(--b3-border-radius); - flex: 1; + width: calc(50% - 8px); display: flex; align-items: center; - margin-right: 8px; + margin: 4px 8px 4px 0; position: relative; box-shadow: inset 0 0 0 .6px var(--b3-theme-on-surface); - } - - &-empty { - flex: 1; - margin-right: 8px; + border: 0; + color: var(--b3-theme-on-background); } &-icon { diff --git a/app/src/mobile/util/keyboardToolbar.ts b/app/src/mobile/util/keyboardToolbar.ts index 89e1e0a3d..92f388b8a 100644 --- a/app/src/mobile/util/keyboardToolbar.ts +++ b/app/src/mobile/util/keyboardToolbar.ts @@ -9,6 +9,7 @@ import {moveToDown, moveToUp} from "../../protyle/wysiwyg/move"; import {Constants} from "../../constants"; import {focusByRange, getSelectionPosition} from "../../protyle/util/selection"; import {getCurrentEditor} from "../editor"; +import {fontEvent, getFontNodeElements} from "../../protyle/toolbar/Font"; let renderKeyboardToolbarTimeout: number; let showUtil = false; @@ -26,6 +27,158 @@ const getSlashItem = (value: string, icon: string, text: string, focus = "false" `; }; +const renderTextMenu = (protyle: IProtyle, toolbarElement: Element) => { + let colorHTML = ""; + ["var(--b3-font-color1)", "var(--b3-font-color2)", "var(--b3-font-color3)", "var(--b3-font-color4)", + "var(--b3-font-color5)", "var(--b3-font-color6)", "var(--b3-font-color7)", "var(--b3-font-color8)", + "var(--b3-font-color9)", "var(--b3-font-color10)", "var(--b3-font-color11)", "var(--b3-font-color12)", + "var(--b3-font-color13)"].forEach((item, index) => { + colorHTML += ``; + }); + let bgHTML = ""; + ["var(--b3-font-background1)", "var(--b3-font-background2)", "var(--b3-font-background3)", "var(--b3-font-background4)", + "var(--b3-font-background5)", "var(--b3-font-background6)", "var(--b3-font-background7)", "var(--b3-font-background8)", + "var(--b3-font-background9)", "var(--b3-font-background10)", "var(--b3-font-background11)", "var(--b3-font-background12)", + "var(--b3-font-background13)"].forEach((item, index) => { + bgHTML += ``; + }); + + let lastColorHTML = ""; + const lastFonts = window.siyuan.storage[Constants.LOCAL_FONTSTYLES]; + if (lastFonts.length > 0) { + lastColorHTML = `
+ ${window.siyuan.languages.lastUsed} +
+
`; + lastFonts.forEach((item: string) => { + const lastFontStatus = item.split(Constants.ZWSP); + switch (lastFontStatus[0]) { + case "color": + lastColorHTML += ``; + break; + case "backgroundColor": + lastColorHTML += ``; + break; + case "style2": + lastColorHTML += ``; + break; + case "style4": + lastColorHTML += ``; + break; + case "fontSize": + lastColorHTML += ``; + break; + case "style1": + lastColorHTML += ``; + break; + case "clear": + lastColorHTML += ``; + break; + } + }); + lastColorHTML += "
"; + } + let textElement: HTMLElement; + let fontSize = "16px"; + const nodeElements = getFontNodeElements(protyle); + if (nodeElements && nodeElements.length > 0) { + textElement = nodeElements[0]; + } else { + textElement = protyle.toolbar.range.cloneContents().querySelector('[data-type~="text"]') as HTMLElement; + if (!textElement) { + textElement = hasClosestByAttribute(protyle.toolbar.range.startContainer, "data-type", "text") as HTMLElement; + } + } + if (textElement) { + fontSize = textElement.style.fontSize || "16px"; + } + const utilElement = toolbarElement.querySelector(".keyboard__util") as HTMLElement; + utilElement.innerHTML = `${lastColorHTML} +
${window.siyuan.languages.color}
+
+ + + + +
+
${window.siyuan.languages.colorFont}
+
+ ${colorHTML} +
+
${window.siyuan.languages.colorPrimary}
+
+ ${bgHTML} +
+
${window.siyuan.languages.fontStyle}
+
+ + + +
+
${window.siyuan.languages.fontSize}
+
+ +
`; + utilElement.querySelector("select").addEventListener("change", function (event: Event) { + fontEvent(protyle, nodeElements, "fontSize", (event.target as HTMLSelectElement).value); + }); +}; + const renderSlashMenu = (protyle: IProtyle, toolbarElement: Element) => { protyle.hint.splitChar = "/"; protyle.hint.lastIndex = -1; @@ -34,74 +187,42 @@ const renderSlashMenu = (protyle: IProtyle, toolbarElement: Element) => {
${getSlashItem(Constants.ZWSP, "iconMarkdown", window.siyuan.languages.template)} ${getSlashItem(Constants.ZWSP + 1, "iconBoth", window.siyuan.languages.widget)} -
-
${getSlashItem(Constants.ZWSP + 2, "iconImage", window.siyuan.languages.assets)} ${getSlashItem("((", "iconRef", window.siyuan.languages.ref, "true")} -
-
${getSlashItem("{{", "iconSQL", window.siyuan.languages.blockEmbed, "true")} ${getSlashItem(Constants.ZWSP + 5, "iconSparkles", "AI Chat")} -
-
${getSlashItem(Constants.ZWSP + 4, "iconFile", window.siyuan.languages.newFile)} -
${getSlashItem("# " + Lute.Caret, "iconH1", window.siyuan.languages.heading1, "true")} ${getSlashItem("## " + Lute.Caret, "iconH2", window.siyuan.languages.heading2, "true")} -
-
${getSlashItem("### " + Lute.Caret, "iconH3", window.siyuan.languages.heading3, "true")} ${getSlashItem("#### " + Lute.Caret, "iconH4", window.siyuan.languages.heading4, "true")} -
-
${getSlashItem("##### " + Lute.Caret, "iconH5", window.siyuan.languages.heading5, "true")} ${getSlashItem("###### " + Lute.Caret, "iconH6", window.siyuan.languages.heading6, "true")} -
-
${getSlashItem("* " + Lute.Caret, "iconList", window.siyuan.languages.list, "true")} ${getSlashItem("1. " + Lute.Caret, "iconOrderedList", window.siyuan.languages["ordered-list"], "true")} -
-
${getSlashItem("* [ ] " + Lute.Caret, "iconCheck", window.siyuan.languages.check, "true")} ${getSlashItem("> " + Lute.Caret, "iconQuote", window.siyuan.languages.quote, "true")} -
-
${getSlashItem("```", "iconCode", window.siyuan.languages.code, "true")} ${getSlashItem(`| ${Lute.Caret} | | |\n| --- | --- | --- |\n| | | |\n| | | |`, "iconTable", window.siyuan.languages.table, "true")} -
-
${getSlashItem("---", "iconLine", window.siyuan.languages.line, "true")} ${getSlashItem("$$", "iconMath", window.siyuan.languages.math)} -
-
${getSlashItem("
", "iconHTML5", "HTML")} -
${getSlashItem("emoji", "iconEmoji", window.siyuan.languages.emoji, "true")} ${getSlashItem("a", "iconLink", window.siyuan.languages.link)} -
-
${getSlashItem("strong", "iconBold", window.siyuan.languages.bold, "true")} ${getSlashItem("em", "iconItalic", window.siyuan.languages.italic, "true")} -
-
${getSlashItem("u", "iconUnderline", window.siyuan.languages.underline, "true")} ${getSlashItem("s", "iconStrike", window.siyuan.languages.strike, "true")} -
-
${getSlashItem("mark", "iconMark", window.siyuan.languages.mark, "true")} ${getSlashItem("sup", "iconSup", window.siyuan.languages.sup, "true")} -
-
${getSlashItem("sub", "iconSub", window.siyuan.languages.sub, "true")} ${getSlashItem("tag", "iconTags", window.siyuan.languages.tag, "true")} -
-
${getSlashItem("code", "iconInlineCode", window.siyuan.languages["inline-code"], "true")} ${getSlashItem("inline-math", "iconMath", window.siyuan.languages["inline-math"])}
@@ -109,44 +230,27 @@ const renderSlashMenu = (protyle: IProtyle, toolbarElement: Element) => {
${getSlashItem(Constants.ZWSP + 3, "iconDownload", window.siyuan.languages.insertAsset + '", "true")} ${getSlashItem('', "iconLanguage", window.siyuan.languages.insertIframeURL, "true")} -
-
${getSlashItem("![]()", "iconImage", window.siyuan.languages.insertImgURL, "true")} ${getSlashItem('', "iconVideo", window.siyuan.languages.insertVideoURL, "true")} -
-
${getSlashItem('', "iconRecord", window.siyuan.languages.insertAudioURL, "true")} -
${getSlashItem("```abc\n```", "", window.siyuan.languages.staff, "true")} ${getSlashItem("```echarts\n```", "", window.siyuan.languages.chart, "true")} -
-
${getSlashItem("```flowchart\n```", "", "Flow Chart", "true")} ${getSlashItem("```graphviz\n```", "", "Graph", "true")} -
-
${getSlashItem("```mermaid\n```", "", "Mermaid", "true")} ${getSlashItem("```mindmap\n```", "", window.siyuan.languages.mindmap, "true")} -
-
${getSlashItem("```plantuml\n```", "", "UML", "true")} -
${getSlashItem(`style${Constants.ZWSP}color: var(--b3-card-info-color);background-color: var(--b3-card-info-background);`, '
A
', window.siyuan.languages.infoStyle, "true")} ${getSlashItem(`style${Constants.ZWSP}color: var(--b3-card-success-color);background-color: var(--b3-card-success-background);`, '
A
', window.siyuan.languages.successStyle, "true")} -
-
${getSlashItem(`style${Constants.ZWSP}color: var(--b3-card-warning-color);background-color: var(--b3-card-warning-background);`, '
A
', window.siyuan.languages.warningStyle, "true")} ${getSlashItem(`style${Constants.ZWSP}color: var(--b3-card-error-color);background-color: var(--b3-card-error-background);`, '
A
', window.siyuan.languages.errorStyle, "true")} -
-
${getSlashItem(`style${Constants.ZWSP}`, '
A
', window.siyuan.languages.clearFontStyle, "true")} -
`; protyle.hint.bindUploadEvent(protyle, utilElement); }; @@ -179,6 +283,7 @@ const hideKeyboardToolbarUtil = () => { editor.protyle.element.parentElement.style.paddingBottom = "42px"; } toolbarElement.querySelector('.keyboard__action[data-type="add"]').classList.remove("protyle-toolbar__item--current"); + toolbarElement.querySelector('.keyboard__action[data-type="text"]').classList.remove("protyle-toolbar__item--current"); toolbarElement.querySelector('.keyboard__action[data-type="done"] use').setAttribute("xlink:href", "#iconKeyboardHide"); }; @@ -387,7 +492,7 @@ export const initKeyboardToolbar = () => { const target = event.target as HTMLElement; const slashBtnElement = hasClosestByClassName(event.target as HTMLElement, "keyboard__slash-item"); const protyle = getCurrentEditor().protyle; - if (slashBtnElement) { + if (slashBtnElement && !slashBtnElement.getAttribute("data-type")) { const dataValue = decodeURIComponent(slashBtnElement.getAttribute("data-value")); protyle.hint.fill(dataValue, protyle, false); // 点击后 range 会改变 if (dataValue !== Constants.ZWSP + 3) { @@ -453,16 +558,28 @@ export const initKeyboardToolbar = () => { dynamicElements[0].classList.add("fn__none"); focusByRange(range); return; - } else if (["a", "block-ref", "inline-math", "inline-memo", "text"].includes(type)) { + } else if (["a", "block-ref", "inline-math", "inline-memo"].includes(type)) { if (!hasClosestByAttribute(range.startContainer, "data-type", "NodeCodeBlock")) { protyle.toolbar.element.querySelector(`[data-type="${type}"]`).dispatchEvent(new CustomEvent("click")); } return; - } else if (["strong", "em", "s", "code", "mark", "tag", "u", "sup", "clear", "sub", "kbd"].includes(type)) { + } else if (buttonElement.classList.contains("keyboard__action") && ["strong", "em", "s", "code", "mark", "tag", "u", "sup", "clear", "sub", "kbd"].includes(type)) { if (!hasClosestByAttribute(range.startContainer, "data-type", "NodeCodeBlock")) { protyle.toolbar.setInlineMark(protyle, type, "toolbar"); } return; + } else if (type === "text") { + if (buttonElement.classList.contains("protyle-toolbar__item--current")) { + hideKeyboardToolbarUtil(); + focusByRange(range); + } else { + buttonElement.classList.add("protyle-toolbar__item--current"); + toolbarElement.querySelector('.keyboard__action[data-type="done"] use').setAttribute("xlink:href", "#iconCloseRound"); + const oldScrollTop = protyle.contentElement.scrollTop; + renderTextMenu(protyle, toolbarElement); + showKeyboardToolbarUtil(oldScrollTop); + } + return; } else if (type === "moveup") { moveToUp(protyle, nodeElement, range); focusByRange(range); @@ -504,6 +621,22 @@ export const initKeyboardToolbar = () => { } else if (type === "indent") { listIndent(protyle, [nodeElement.parentElement], range); focusByRange(range); + return; + } + // appearance + if (["clear", "style2", "style4", "color", "backgroundColor", "fontSize", "style1"].includes(type)) { + const nodeElements = getFontNodeElements(protyle) + if (type === "style1") { + fontEvent(protyle, nodeElements, type, buttonElement.firstElementChild.style.backgroundColor + Constants.ZWSP + buttonElement.firstElementChild.style.color); + } else if (type === "fontSize") { + fontEvent(protyle, nodeElements, type, buttonElement.firstElementChild.textContent.trim()); + } else if (type === "backgroundColor") { + fontEvent(protyle, nodeElements, type, buttonElement.firstElementChild.style.backgroundColor); + } else if (type === "color") { + fontEvent(protyle, nodeElements, type, buttonElement.firstElementChild.style.color); + } else { + fontEvent(protyle, nodeElements, type); + } } }); }; diff --git a/app/src/protyle/toolbar/Font.ts b/app/src/protyle/toolbar/Font.ts index cb9152f32..f84ce4dd7 100644 --- a/app/src/protyle/toolbar/Font.ts +++ b/app/src/protyle/toolbar/Font.ts @@ -12,21 +12,11 @@ export class Font extends ToolbarItem { constructor(protyle: IProtyle, menuItem: IMenuItem) { super(protyle, menuItem); this.element.addEventListener("click", () => { - let nodeElements: Element[]; - if (protyle.toolbar.range.toString() === "") { - nodeElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select")); - if (nodeElements.length === 0) { - const nodeElement = hasClosestBlock(protyle.toolbar.range.startContainer); - if (nodeElement) { - nodeElements = [nodeElement]; - } - } - } protyle.toolbar.element.classList.add("fn__none"); protyle.toolbar.subElement.innerHTML = ""; protyle.toolbar.subElement.style.width = ""; protyle.toolbar.subElement.style.padding = ""; - protyle.toolbar.subElement.append(appearanceMenu(protyle, nodeElements)); + protyle.toolbar.subElement.append(appearanceMenu(protyle, getFontNodeElements())); protyle.toolbar.subElement.classList.remove("fn__none"); protyle.toolbar.subElementCloseCB = undefined; focusByRange(protyle.toolbar.range); @@ -418,3 +408,17 @@ export const hasSameTextStyle = (currentElement: HTMLElement, sideElement: HTMLE } return true; // 清除字体样式会使用 "text" 作为标识 }; + +export const getFontNodeElements = (protyle: IProtyle) => { + let nodeElements: Element[]; + if (protyle.toolbar.range.toString() === "") { + nodeElements = Array.from(protyle.wysiwyg.element.querySelectorAll(".protyle-wysiwyg--select")); + if (nodeElements.length === 0) { + const nodeElement = hasClosestBlock(protyle.toolbar.range.startContainer); + if (nodeElement) { + nodeElements = [nodeElement]; + } + } + } + return nodeElements; +}