Vanessa 2023-03-05 13:01:39 +08:00
parent 885b1ffad3
commit 9127b6b50e
6 changed files with 132 additions and 74 deletions

View file

@ -55,7 +55,10 @@ ctrl+p 搜索: 202
.b3-menu: 210
// 需小于 .side-panel
#transactionTip & #keyboardToolbar: 212
#transactionTip: 212
// 需大于 mobile .status
.keyboard: 222
// 需小于 .b3-dialog 关于中的锁屏密码设置
.side-panel: 220

View file

@ -97,9 +97,7 @@
&__title {
flex: 1;
padding: 4px 8px;
border: 1px solid transparent;
background-color: transparent;
box-shadow: none;
}
&__search {
@ -228,10 +226,11 @@
box-sizing: border-box;
height: 42px;
background: var(--b3-theme-background);
z-index: 212;
z-index: 222;
display: flex;
border-top: 1px solid var(--b3-theme-surface-lighter);
overflow: hidden;
flex-direction: column;
&__dynamic {
overflow: auto;
@ -242,14 +241,23 @@
}
}
&__bar {
border-bottom: 1px solid var(--b3-theme-surface-lighter);
}
&__split {
width: 1px;
height: 28px;
background: var(--b3-border-color);
background-color: var(--b3-theme-surface-lighter);
align-self: center;
flex-shrink: 0;
}
&__util {
flex: 1;
overflow: auto;
}
button {
background: transparent;
padding: 0;
@ -333,8 +341,6 @@
}
.b3-menu {
width: 100%;
&__accelerator {
display: none;
}

View file

@ -2,7 +2,7 @@
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover">
<meta name="viewport" content="width=device-width, height=device-height, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, viewport-fit=cover">
<style id="editorFontSize" type="text/css"></style>
</head>
<body class="fn__flex-column">

View file

@ -6,11 +6,13 @@ import {focusByRange, getSelectionPosition} from "../../protyle/util/selection";
import {removeBlock} from "../../protyle/wysiwyg/remove";
import {hintSlash} from "../../protyle/hint/extend";
export const showKeyboardToolbar = (bottom = 0) => {
export const showKeyboardToolbar = (bottom = 0, height: number) => {
if (getSelection().rangeCount === 0 || window.siyuan.config.editor.readOnly || window.siyuan.config.readonly) {
return;
}
const toolbarElement = document.getElementById("keyboardToolbar");
toolbarElement.setAttribute("data-keyboardheight", height.toString())
hideKeyboardToolbarUtil();
if (!toolbarElement.classList.contains("fn__none")) {
return;
}
@ -37,12 +39,19 @@ export const showKeyboardToolbar = (bottom = 0) => {
};
let renderKeyboardToolbarTimeout: number;
let showKeyboardToolbarUtil = false;
export const renderKeyboardToolbar = () => {
clearTimeout(renderKeyboardToolbarTimeout);
renderKeyboardToolbarTimeout = window.setTimeout(() => {
if (getSelection().rangeCount === 0 || window.siyuan.config.editor.readOnly || window.siyuan.config.readonly) {
return;
}
hideKeyboardToolbarUtil();
if (window.innerHeight + 200 > ((window.orientation === 90 || window.orientation === -90) ? screen.width : screen.height)) {
hideKeyboardToolbar();
return;
}
const dynamicElements = document.querySelectorAll("#keyboardToolbar .keyboard__dynamic");
const range = getSelection().getRangeAt(0);
const selectText = range.toString();
@ -85,6 +94,9 @@ export const renderKeyboardToolbar = () => {
};
export const hideKeyboardToolbar = () => {
if (showKeyboardToolbarUtil) {
return;
}
const toolbarElement = document.getElementById("keyboardToolbar");
toolbarElement.classList.add("fn__none");
};
@ -93,52 +105,72 @@ export const hideKeyboard = () => {
(document.activeElement as HTMLElement).blur();
};
const renderKeyboardToolbarUtil = () => {
const toolbarElement = document.getElementById("keyboardToolbar");
const keyboardHeight = (parseInt(toolbarElement.getAttribute("data-keyboardheight")) + 42) + "px"
toolbarElement.style.height = keyboardHeight
window.siyuan.mobile.editor.protyle.element.style.marginBottom = keyboardHeight
window.siyuan.menus.menu.remove();
showKeyboardToolbarUtil = true;
setTimeout(() => {
showKeyboardToolbarUtil = false
}, 1000)
}
const hideKeyboardToolbarUtil = () => {
document.getElementById("keyboardToolbar").style.height = ""
window.siyuan.mobile.editor.protyle.element.style.marginBottom = ""
}
export const initKeyboardToolbar = () => {
document.addEventListener("selectionchange", () => {
renderKeyboardToolbar();
}, false);
const toolbarElement = document.getElementById("keyboardToolbar");
toolbarElement.innerHTML = `<div class="fn__flex-1">
<div class="fn__none keyboard__dynamic">
<button data-type="indent"><svg><use xlink:href="#iconIndent"></use></svg></button>
<button data-type="outdent"><svg><use xlink:href="#iconOutdent"></use></svg></button>
<span class="keyboard__split"></span>
<button data-type="add"><svg><use xlink:href="#iconAdd"></use></svg></button>
<button data-type="goinline"><svg class="keyboard__svg--big"><use xlink:href="#iconBIU"></use></svg></button>
<button data-type="remove"><svg><use xlink:href="#iconTrashcan"></use></svg></button>
<span class="keyboard__split"></span>
<button data-type="undo"><svg><use xlink:href="#iconUndo"></use></svg></button>
<button data-type="redo"><svg><use xlink:href="#iconRedo"></use></svg></button>
<button data-type="block"><svg><use xlink:href="#iconParagraph"></use></svg></button>
<button data-type="more"><svg><use xlink:href="#iconMore"></use></svg></button>
<span class="keyboard__split"></span>
<button data-type="moveup"><svg><use xlink:href="#iconUp"></use></svg></button>
<button data-type="movedown"><svg><use xlink:href="#iconDown"></use></svg></button>
</div>
<div class="fn__none keyboard__dynamic">
<button data-type="goback"><svg><use xlink:href="#iconBack"></use></svg></button>
<button data-type="block-ref"><svg><use xlink:href="#iconRef"></use></svg></button>
<button data-type="a"><svg><use xlink:href="#iconLink"></use></svg></button>
<button data-type="text"><svg><use xlink:href="#iconFont"></use></svg></button>
<button data-type="strong"><svg><use xlink:href="#iconBold"></use></svg></button>
<button data-type="em"><svg><use xlink:href="#iconItalic"></use></svg></button>
<button data-type="u"><svg><use xlink:href="#iconUnderline"></use></svg></button>
<button data-type="s"><svg><use xlink:href="#iconStrike"></use></svg></button>
<button data-type="mark"><svg><use xlink:href="#iconMark"></use></svg></button>
<button data-type="sup"><svg><use xlink:href="#iconSup"></use></svg></button>
<button data-type="sub"><svg><use xlink:href="#iconSub"></use></svg></button>
<button data-type="clear"><svg><use xlink:href="#iconClear"></use></svg></button>
<button data-type="code"><svg><use xlink:href="#iconInlineCode"></use></svg></button>
<button data-type="kbd"<use xlink:href="#iconKeymap"></use></svg></button>
<button data-type="tag"><svg><use xlink:href="#iconTags"></use></svg></button>
<button data-type="inline-math"><svg><use xlink:href="#iconMath"></use></svg></button>
<button data-type="inline-memo"><svg><use xlink:href="#iconM"></use></svg></button>
<button data-type="goback"><svg class="keyboard__svg--close"><use xlink:href="#iconClose"></use></svg></button>
toolbarElement.innerHTML = `<div class="fn__flex keyboard__bar">
<div class="fn__flex-1">
<div class="fn__none keyboard__dynamic">
<button data-type="indent"><svg><use xlink:href="#iconIndent"></use></svg></button>
<button data-type="outdent"><svg><use xlink:href="#iconOutdent"></use></svg></button>
<span class="keyboard__split"></span>
<button data-type="add"><svg><use xlink:href="#iconAdd"></use></svg></button>
<button data-type="goinline"><svg class="keyboard__svg--big"><use xlink:href="#iconBIU"></use></svg></button>
<button data-type="remove"><svg><use xlink:href="#iconTrashcan"></use></svg></button>
<span class="keyboard__split"></span>
<button data-type="undo"><svg><use xlink:href="#iconUndo"></use></svg></button>
<button data-type="redo"><svg><use xlink:href="#iconRedo"></use></svg></button>
<button data-type="block"><svg><use xlink:href="#iconParagraph"></use></svg></button>
<button data-type="more"><svg><use xlink:href="#iconMore"></use></svg></button>
<span class="keyboard__split"></span>
<button data-type="moveup"><svg><use xlink:href="#iconUp"></use></svg></button>
<button data-type="movedown"><svg><use xlink:href="#iconDown"></use></svg></button>
</div>
<div class="fn__none keyboard__dynamic">
<button data-type="goback"><svg><use xlink:href="#iconBack"></use></svg></button>
<button data-type="block-ref"><svg><use xlink:href="#iconRef"></use></svg></button>
<button data-type="a"><svg><use xlink:href="#iconLink"></use></svg></button>
<button data-type="text"><svg><use xlink:href="#iconFont"></use></svg></button>
<button data-type="strong"><svg><use xlink:href="#iconBold"></use></svg></button>
<button data-type="em"><svg><use xlink:href="#iconItalic"></use></svg></button>
<button data-type="u"><svg><use xlink:href="#iconUnderline"></use></svg></button>
<button data-type="s"><svg><use xlink:href="#iconStrike"></use></svg></button>
<button data-type="mark"><svg><use xlink:href="#iconMark"></use></svg></button>
<button data-type="sup"><svg><use xlink:href="#iconSup"></use></svg></button>
<button data-type="sub"><svg><use xlink:href="#iconSub"></use></svg></button>
<button data-type="clear"><svg><use xlink:href="#iconClear"></use></svg></button>
<button data-type="code"><svg><use xlink:href="#iconInlineCode"></use></svg></button>
<button data-type="kbd"<use xlink:href="#iconKeymap"></use></svg></button>
<button data-type="tag"><svg><use xlink:href="#iconTags"></use></svg></button>
<button data-type="inline-math"><svg><use xlink:href="#iconMath"></use></svg></button>
<button data-type="inline-memo"><svg><use xlink:href="#iconM"></use></svg></button>
<button data-type="goback"><svg class="keyboard__svg--close"><use xlink:href="#iconClose"></use></svg></button>
</div>
</div>
<span class="keyboard__split"></span>
<button data-type="done"><svg style="width: 36px"><use xlink:href="#iconKeyboardHide"></use></svg></button>
</div>
<span class="keyboard__split"></span>
<button data-type="done"><svg style="width: 36px"><use xlink:href="#iconKeyboardHide"></use></svg></button>`;
<div class="keyboard__util"></div>`;
toolbarElement.addEventListener("click", (event) => {
const target = event.target as HTMLElement;
const buttonElement = hasClosestByMatchTag(target, "BUTTON");
@ -150,6 +182,7 @@ export const initKeyboardToolbar = () => {
const type = buttonElement.getAttribute("data-type");
if (type === "done") {
hideKeyboard();
hideKeyboardToolbar();
return;
}
if (window.siyuan.config.readonly || window.siyuan.config.editor.readOnly || !window.siyuan.mobile.editor) {
@ -203,8 +236,16 @@ export const initKeyboardToolbar = () => {
} else if (type === "add") {
protyle.hint.splitChar = "/";
protyle.hint.lastIndex = -1;
protyle.hint.genHTML(hintSlash("", protyle), protyle);
focusByRange(range);
const utilElement = toolbarElement.querySelector(".keyboard__util") as HTMLElement
utilElement.innerHTML = protyle.hint.getHTMLByData(hintSlash("", protyle), false)
protyle.hint.bindUploadEvent(protyle, utilElement);
utilElement.addEventListener("click", (event) => {
const btnElement = hasClosestByClassName(event.target as HTMLElement, "b3-list-item");
if (btnElement) {
protyle.hint.fill(decodeURIComponent(btnElement.getAttribute("data-value")), protyle);
}
})
renderKeyboardToolbarUtil();
return;
} else if (type === "more") {
protyle.breadcrumb.showMenu(protyle, {
@ -215,7 +256,7 @@ export const initKeyboardToolbar = () => {
return;
} else if (type === "block") {
protyle.gutter.renderMenu(protyle, nodeElement);
window.siyuan.menus.menu.popup({x: 0, y:0}, true);
window.siyuan.menus.menu.popup({x: 0, y: 0}, true);
focusByRange(range);
return;
} else if (type === "outdent") {

View file

@ -202,14 +202,25 @@ ${unicode2Emoji(emoji.unicode, true)}</button>`;
}
}
public genHTML(data: IHintData[], protyle: IProtyle, hide = false, hasSearch = false) {
if (data.length === 0) {
if (!this.element.querySelector(".fn__loading") || hide) {
this.element.classList.add("fn__none");
}
return;
public bindUploadEvent (protyle:IProtyle, element:HTMLElement) {
const uploadElement = element.querySelector('input[type="file"]');
if (uploadElement) {
uploadElement.addEventListener("change", (event: InputEvent & { target: HTMLInputElement }) => {
if (event.target.files.length === 0) {
return;
}
const range = getEditorRange(protyle.wysiwyg.element);
if (this.lastIndex > -1) {
range.setStart(range.startContainer, this.lastIndex);
}
range.deleteContents();
uploadFiles(protyle, event.target.files, event.target);
hideElements(["hint", "toolbar"], protyle);
});
}
}
public getHTMLByData(data: IHintData[], hasSearch = false) {
let hintsHTML = "";
if (hasSearch) {
hintsHTML = '<input style="margin: 0 4px 4px 4px" class="b3-text-field"><div style="flex: 1;overflow:auto;">';
@ -234,7 +245,18 @@ ${unicode2Emoji(emoji.unicode, true)}</button>`;
if (hasSearch) {
hintsHTML = hintsHTML + "</div>";
}
this.element.innerHTML = hintsHTML;
return hintsHTML
}
public genHTML(data: IHintData[], protyle: IProtyle, hide = false, hasSearch = false) {
if (data.length === 0) {
if (!this.element.querySelector(".fn__loading") || hide) {
this.element.classList.add("fn__none");
}
return;
}
this.element.innerHTML = this.getHTMLByData(data, hasSearch);
this.element.classList.remove("fn__none");
// https://github.com/siyuan-note/siyuan/issues/4575
if (data[0].filter) {
@ -246,21 +268,7 @@ ${unicode2Emoji(emoji.unicode, true)}</button>`;
const textareaPosition = getSelectionPosition(protyle.wysiwyg.element);
setPosition(this.element, textareaPosition.left, textareaPosition.top + 26, 30);
this.element.scrollTop = 0;
const uploadElement = this.element.querySelector('input[type="file"]');
if (uploadElement) {
uploadElement.addEventListener("change", (event: InputEvent & { target: HTMLInputElement }) => {
if (event.target.files.length === 0) {
return;
}
const range = getEditorRange(protyle.wysiwyg.element);
if (this.lastIndex > -1) {
range.setStart(range.startContainer, this.lastIndex);
}
range.deleteContents();
uploadFiles(protyle, event.target.files, event.target);
hideElements(["hint", "toolbar"], protyle);
});
}
this.bindUploadEvent(protyle, this.element);
if (hasSearch) {
const searchElement = this.element.querySelector("input.b3-text-field") as HTMLInputElement;
const oldValue = this.element.querySelector("mark")?.textContent || "";

View file

@ -49,7 +49,7 @@ interface Window {
goBack(): void
showKeyboardToolbar(bottom?: number): void
showKeyboardToolbar(bottom: number, height: number): void
hideKeyboardToolbar(): void