mirror of
https://github.com/siyuan-note/siyuan.git
synced 2026-01-28 19:26:09 +01:00
This commit is contained in:
parent
885b1ffad3
commit
9127b6b50e
6 changed files with 132 additions and 74 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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">
|
||||
|
|
|
|||
|
|
@ -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") {
|
||||
|
|
|
|||
|
|
@ -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 || "";
|
||||
|
|
|
|||
2
app/src/types/index.d.ts
vendored
2
app/src/types/index.d.ts
vendored
|
|
@ -49,7 +49,7 @@ interface Window {
|
|||
|
||||
goBack(): void
|
||||
|
||||
showKeyboardToolbar(bottom?: number): void
|
||||
showKeyboardToolbar(bottom: number, height: number): void
|
||||
|
||||
hideKeyboardToolbar(): void
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue