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;
+}