diff --git a/app/src/assets/scss/base.scss b/app/src/assets/scss/base.scss
index 2e947266b..2263476b9 100644
--- a/app/src/assets/scss/base.scss
+++ b/app/src/assets/scss/base.scss
@@ -34,6 +34,7 @@
@import "business/custom";
@import "business/resize";
@import "business/av";
+@import "business/emojis";
/*
.status: 2
diff --git a/app/src/assets/scss/business/_emojis.scss b/app/src/assets/scss/business/_emojis.scss
new file mode 100644
index 000000000..c8f8d265e
--- /dev/null
+++ b/app/src/assets/scss/business/_emojis.scss
@@ -0,0 +1,107 @@
+
+.emojis {
+ word-break: break-all;
+ white-space: normal;
+ display: flex;
+ flex-direction: column;
+ padding: 8px 0;
+ height: 100%;
+ box-sizing: border-box;
+
+ &__tabheader {
+ display: flex;
+ border-bottom: 1px solid var(--b3-border-color);
+ padding: 0 8px 8px;
+ }
+
+ &__tabbody {
+ flex: 1;
+ overflow: auto;
+
+ div[data-type="tab-emoji"] {
+ display: flex;
+ flex-direction: column;
+ height: 100%;
+ }
+ }
+
+ .emoji__dynamic {
+ &-item {
+ width: 73px;
+ margin: 8px;
+ cursor: pointer;
+ }
+
+ &-color {
+ padding: 8px 8px 4px 4px;
+ }
+ }
+
+ &__item {
+ font-size: 24px;
+ line-height: .9em; // windows 需要这样设置
+ font-family: var(--b3-font-family-emoji);
+ text-align: center;
+ height: 28px;
+ padding: 2px 4px;
+ cursor: pointer;
+ display: inline-block;
+ transition: var(--b3-transition);
+ background-color: transparent;
+ border: 0;
+ margin: 1px;
+ overflow: hidden;
+ border-radius: var(--b3-border-radius);
+
+ img, svg {
+ height: 24px;
+ display: block;
+ width: 24px;
+ }
+
+ &--current,
+ &:hover {
+ background: var(--b3-list-hover);
+ }
+ }
+
+ &__title {
+ color: var(--b3-theme-on-surface);
+ padding: 8px 4px 4px 4px;
+ }
+
+ &__panel {
+ flex: 1;
+ overflow: auto;
+ padding: 0 8px;
+ }
+
+ &__content {
+ display: flex;
+ flex-wrap: wrap;
+ }
+
+ &__type {
+ cursor: pointer;
+ flex: 1;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ height: 28px;
+ line-height: 28px;
+ transition: var(--b3-list-hover);
+ font-size: 16px;
+ background-color: transparent;
+ border: 0;
+ padding: 0;
+
+ &:hover {
+ background-color: var(--b3-theme-surface-lighter);
+ }
+
+ svg {
+ height: 16px;
+ width: 16px;
+ }
+ }
+}
diff --git a/app/src/assets/scss/component/_menu.scss b/app/src/assets/scss/component/_menu.scss
index 6378acf26..e6dab7c42 100644
--- a/app/src/assets/scss/component/_menu.scss
+++ b/app/src/assets/scss/component/_menu.scss
@@ -366,81 +366,3 @@
}
}
}
-
-.emojis {
- word-break: break-all;
- white-space: normal;
- display: flex;
- flex-direction: column;
- padding: 8px 0;
- height: 100%;
- box-sizing: border-box;
-
- &__item {
- font-size: 24px;
- line-height: .9em; // windows 需要这样设置
- font-family: var(--b3-font-family-emoji);
- text-align: center;
- height: 28px;
- padding: 2px 4px;
- cursor: pointer;
- display: inline-block;
- transition: var(--b3-transition);
- background-color: transparent;
- border: 0;
- margin: 1px;
- overflow: hidden;
- border-radius: var(--b3-border-radius);
-
- img, svg {
- height: 24px;
- display: block;
- width: 24px;
- }
-
- &--current,
- &:hover {
- background: var(--b3-list-hover);
- }
- }
-
- &__title {
- color: var(--b3-theme-on-surface);
- padding: 8px 4px 4px 4px;
- }
-
- &__panel {
- flex: 1;
- overflow: auto;
- padding: 0 8px;
- }
-
- &__content {
- display: flex;
- flex-wrap: wrap;
- }
-
- &__type {
- cursor: pointer;
- flex: 1;
- display: flex;
- align-items: center;
- justify-content: center;
- height: 28px;
- line-height: 28px;
- transition: var(--b3-list-hover);
- font-size: 16px;
- background-color: transparent;
- border: 0;
- padding: 0;
-
- &:hover {
- background-color: var(--b3-theme-surface-lighter);
- }
-
- svg {
- height: 16px;
- width: 16px;
- }
- }
-}
diff --git a/app/src/assets/scss/mobile.scss b/app/src/assets/scss/mobile.scss
index ff31b132d..5fd9a6660 100644
--- a/app/src/assets/scss/mobile.scss
+++ b/app/src/assets/scss/mobile.scss
@@ -27,6 +27,7 @@
@import "business/custom";
@import "business/av";
@import "business/search";
+@import "business/emojis";
.block__popover {
width: 80vw;
diff --git a/app/src/constants.ts b/app/src/constants.ts
index 2915e5c74..e60598f09 100644
--- a/app/src/constants.ts
+++ b/app/src/constants.ts
@@ -123,6 +123,7 @@ export abstract class Constants {
public static readonly LOCAL_OUTLINE = "local-outline";
public static readonly LOCAL_PLUGIN_DOCKS = "local-plugin-docks";
public static readonly LOCAL_IMAGES = "local-images";
+ public static readonly LOCAL_EMOJIS = "local-emojis";
// dialog
public static readonly DIALOG_OPENCARD = "dialog-opencard";
diff --git a/app/src/emoji/index.ts b/app/src/emoji/index.ts
index 0c92fe43b..232fdf3da 100644
--- a/app/src/emoji/index.ts
+++ b/app/src/emoji/index.ts
@@ -1,6 +1,5 @@
import {getRandom, isMobile} from "../util/functions";
import {fetchPost} from "../util/fetch";
-import {hasClosestByClassName} from "../protyle/util/hasClosest";
import {Constants} from "../constants";
import {Files} from "../layout/dock/Files";
/// #if !MOBILE
@@ -11,6 +10,8 @@ import {getAllEditor} from "../layout/getAll";
import {setNoteBook} from "../util/pathName";
import {Dialog} from "../dialog";
import {setPosition} from "../util/setPosition";
+import {setStorageVal} from "../protyle/util/compatibility";
+import * as dayjs from "dayjs";
export const getRandomEmoji = () => {
const emojis = window.siyuan.emojis[getRandom(0, window.siyuan.emojis.length - 1)];
@@ -27,6 +28,8 @@ export const unicode2Emoji = (unicode: string, className = "", needSpan = false,
let emoji = "";
if (unicode.indexOf(".") > -1) {
emoji = `
`;
+ } else if (unicode.startsWith("api/icon/getDynamicIcon")) {
+ emoji = `
`;
} else {
try {
unicode.split("-").forEach(item => {
@@ -198,28 +201,37 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
window.siyuan.menus.menu.removeScrollEvent();
}
+ const dynamicURL = 'api/icon/getDynamicIcon?'
const dialog = new Dialog({
disableAnimation: true,
transparent: true,
hideCloseIcon: true,
- width: isMobile() ? "80vw" : "360px",
+ width: isMobile() ? "80vw" : "368px",
height: "50vh",
content: `
-
-
-
-
-
-
-
-
+
-
${filterEmoji()}
-
- ${[
+
+
+
+
+
+
+
+
+
+
+
${filterEmoji()}
+
+ ${[
["2b50", window.siyuan.languages.recentEmoji],
["1f527", getEmojiTitle(0)],
["1f60d", getEmojiTitle(1)],
@@ -233,6 +245,75 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
].map(([unicode, title], index) =>
`
${unicode2Emoji(unicode)}
`
).join("")}
+
+
+
+
+
+
+ ${window.siyuan.languages.language}
+
+
+
+
+
+
+
+ ${window.siyuan.languages.date}
+
+
+
+
+
+
+
+ ${window.siyuan.languages.format}
+
+
+
+
+
+
+
+
+ ${window.siyuan.languages.custom}
+
+
+
+
+
+

+
+
`
});
@@ -241,42 +322,45 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
const dialogElement = dialog.element.querySelector(".b3-dialog") as HTMLElement;
dialogElement.style.justifyContent = "inherit";
dialogElement.style.alignItems = "inherit";
+ const currentTab = window.siyuan.storage[Constants.LOCAL_EMOJIS].currentTab;
+ dialog.element.querySelector(`.emojis__tabheader [data-type="tab-${currentTab}"]`).classList.add("block__icon--active");
+ dialog.element.querySelector(`.emojis__tabbody [data-type="tab-${currentTab}"]`).classList.remove("fn__none");
setPosition(dialog.element.querySelector(".b3-dialog__container"), position.x, position.y, position.h, position.w);
dialog.element.querySelector(".emojis__item").classList.add("emojis__item--current");
- const inputElement = dialog.element.querySelector(".b3-text-field") as HTMLInputElement;
+ const emojiSearchInputElement = dialog.element.querySelector('[data-type="tab-emoji"] .b3-text-field') as HTMLInputElement;
const emojisContentElement = dialog.element.querySelector(".emojis__panel");
- inputElement.addEventListener("compositionend", () => {
- emojisContentElement.innerHTML = filterEmoji(inputElement.value);
- if (inputElement.value) {
+ emojiSearchInputElement.addEventListener("compositionend", () => {
+ emojisContentElement.innerHTML = filterEmoji(emojiSearchInputElement.value);
+ if (emojiSearchInputElement.value) {
emojisContentElement.nextElementSibling.classList.add("fn__none");
} else {
emojisContentElement.nextElementSibling.classList.remove("fn__none");
}
emojisContentElement.scrollTop = 0;
dialog.element.querySelector(".emojis__item")?.classList.add("emojis__item--current");
- if (inputElement.value === "") {
+ if (emojiSearchInputElement.value === "") {
lazyLoadEmoji(dialog.element);
}
lazyLoadEmojiImg(dialog.element);
});
- inputElement.addEventListener("input", (event: InputEvent) => {
+ emojiSearchInputElement.addEventListener("input", (event: InputEvent) => {
if (event.isComposing) {
return;
}
- emojisContentElement.innerHTML = filterEmoji(inputElement.value);
- if (inputElement.value) {
+ emojisContentElement.innerHTML = filterEmoji(emojiSearchInputElement.value);
+ if (emojiSearchInputElement.value) {
emojisContentElement.nextElementSibling.classList.add("fn__none");
} else {
emojisContentElement.nextElementSibling.classList.remove("fn__none");
}
emojisContentElement.scrollTop = 0;
dialog.element.querySelector(".emojis__item")?.classList.add("emojis__item--current");
- if (inputElement.value === "") {
+ if (emojiSearchInputElement.value === "") {
lazyLoadEmoji(dialog.element);
}
lazyLoadEmojiImg(dialog.element);
});
- inputElement.addEventListener("keydown", (event: KeyboardEvent) => {
+ emojiSearchInputElement.addEventListener("keydown", (event: KeyboardEvent) => {
if (event.isComposing) {
return;
}
@@ -379,7 +463,7 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
}
if (newCurrentElement) {
newCurrentElement.classList.add("emojis__item--current");
- const inputHeight = inputElement.clientHeight + 6;
+ const inputHeight = emojiSearchInputElement.clientHeight + 6;
if (newCurrentElement.offsetTop - inputHeight < emojisContentElement.scrollTop) {
emojisContentElement.scrollTop = newCurrentElement.offsetTop - inputHeight - 6;
} else if (newCurrentElement.offsetTop - inputHeight - emojisContentElement.clientHeight + newCurrentElement.clientHeight > emojisContentElement.scrollTop) {
@@ -387,95 +471,160 @@ export const openEmojiPanel = (id: string, type: "doc" | "notebook" | "av", posi
}
}
});
- if (!isMobile()) {
- inputElement.focus();
+ if (!isMobile() && currentTab === "emoji") {
+ emojiSearchInputElement.focus();
}
lazyLoadEmoji(dialog.element);
lazyLoadEmojiImg(dialog.element);
// 不能使用 getEventName 否则 https://github.com/siyuan-note/siyuan/issues/5472
dialog.element.addEventListener("click", (event) => {
- const eventTarget = event.target as HTMLElement;
- const typeElement = hasClosestByClassName(eventTarget, "emojis__type");
- if (typeElement) {
- const titleElement = emojisContentElement.querySelector(`[data-type="${typeElement.getAttribute("data-type")}"]`) as HTMLElement;
- if (titleElement) {
- const index = titleElement.nextElementSibling.getAttribute("data-index");
- if (index) {
- let html = "";
- window.siyuan.emojis[parseInt(index)].items.forEach(emoji => {
- html += `