mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-12 20:57:45 +02:00
Qfix: emoji input detection (#8927)
This commit is contained in:
@@ -1,8 +1,6 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
|
||||
<symbol id="emoji" viewBox="0 0 24 24">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2.75C6.89137 2.75 2.75 6.89137 2.75 12C2.75 17.1086 6.89137 21.25 12 21.25C17.1086 21.25 21.25 17.1086 21.25 12C21.25 6.89137 17.1086 2.75 12 2.75ZM1.25 12C1.25 6.06294 6.06294 1.25 12 1.25C17.9371 1.25 22.75 6.06294 22.75 12C22.75 17.9371 17.9371 22.75 12 22.75C6.06294 22.75 1.25 17.9371 1.25 12Z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7.54958 14.4003C7.88078 14.1516 8.35093 14.2184 8.59968 14.5496C9.37627 15.5835 10.6102 16.25 12 16.25C13.3898 16.25 14.6237 15.5835 15.4003 14.5496C15.6491 14.2184 16.1192 14.1516 16.4504 14.4003C16.7816 14.6491 16.8484 15.1192 16.5997 15.4504C15.552 16.8453 13.8816 17.75 12 17.75C10.1184 17.75 8.44797 16.8453 7.40031 15.4504C7.15155 15.1192 7.21838 14.6491 7.54958 14.4003Z"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M7 9C7 8.44772 7.44772 8 8 8H8.00897C8.56125 8 9.00897 8.44772 9.00897 9C9.00897 9.55228 8.56125 10 8.00897 10H8C7.44772 10 7 9.55228 7 9ZM14.991 9C14.991 8.44772 15.4387 8 15.991 8H16C16.5523 8 17 8.44772 17 9C17 9.55228 16.5523 10 16 10H15.991C15.4387 10 14.991 9.55228 14.991 9Z"/>
|
||||
<symbol id="emoji" viewBox="0 0 20 20">
|
||||
<path d="M10,2c4.4,0,8,3.6,8,8c0,4.4-3.6,8-8,8c-4.4,0-8-3.6-8-8C2,5.6,5.6,2,10,2z M10,3c-3.9,0-7,3.1-7,7c0,3.9,3.1,7,7,7c3.9,0,7-3.1,7-7C17,6.1,13.9,3,10,3z M7.2,12.4c1.5,1.5,3.9,1.6,5.5,0.2l0.2-0.2c0.2-0.2,0.5-0.2,0.7,0c0.2,0.2,0.2,0.4,0.1,0.6l-0.1,0.1l0,0c-2,2-5.1,1.9-7.1,0c-0.2-0.2-0.2-0.5,0-0.7C6.6,12.2,7,12.2,7.2,12.4z M12.5,7.5c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S11.9,7.5,12.5,7.5z M7.5,7.5c0.6,0,1,0.4,1,1s-0.4,1-1,1s-1-0.4-1-1S6.9,7.5,7.5,7.5z"/>
|
||||
</symbol>
|
||||
<symbol id="emoji-add" viewBox="0 0 24 24">
|
||||
<path d="M20.2502 0.99996C20.2502 0.585746 19.9143 0.249978 19.5001 0.25C19.0859 0.250022 18.7502 0.585826 18.7502 1.00004L18.7503 3.75032L16 3.75019C15.5858 3.75017 15.25 4.08594 15.25 4.50015C15.25 4.91436 15.5857 5.25017 16 5.25019L18.7504 5.25032L18.7505 8.00004C18.7506 8.41425 19.0864 8.75002 19.5006 8.75C19.9148 8.74998 20.2506 8.41417 20.2505 7.99996L20.2504 5.2504L23 5.25054C23.4142 5.25056 23.75 4.91479 23.75 4.50057C23.75 4.08636 23.4143 3.75056 23 3.75054L20.2503 3.7504L20.2502 0.99996Z"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 14 KiB |
@@ -38,8 +38,7 @@
|
||||
class="hulyPopupEmoji-button"
|
||||
class:preview
|
||||
class:selected
|
||||
class:skins={skins !== undefined && skins.length === 5}
|
||||
class:constructor={skins !== undefined && skins.length > 5}
|
||||
class:skins={skins !== undefined}
|
||||
data-skins={skins?.length}
|
||||
{disabled}
|
||||
on:touchstart
|
||||
@@ -74,15 +73,15 @@
|
||||
width: 1.75rem;
|
||||
height: 1.75rem;
|
||||
font-size: 1.5rem;
|
||||
border-radius: 0.75rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
&.preview {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
margin: 0rem;
|
||||
padding: 0.25rem;
|
||||
width: 1.5rem;
|
||||
height: 1.5rem;
|
||||
font-size: 1.25rem;
|
||||
border-radius: 0.375rem;
|
||||
border-radius: 0.25rem;
|
||||
}
|
||||
span {
|
||||
transform: translateY(1%);
|
||||
@@ -114,7 +113,6 @@
|
||||
|
||||
&.skins:not(.preview) {
|
||||
position: relative;
|
||||
border: 1px dashed var(--theme-button-border);
|
||||
|
||||
&:hover {
|
||||
&::after {
|
||||
@@ -129,32 +127,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
&.constructor:not(.preview) {
|
||||
position: relative;
|
||||
border: 1px dashed var(--theme-button-border);
|
||||
|
||||
&:hover {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -0.25rem;
|
||||
right: -0.25rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
border-radius: 50%;
|
||||
background-color: var(--global-focus-BorderColor);
|
||||
}
|
||||
&::after {
|
||||
content: attr(data-skins);
|
||||
position: absolute;
|
||||
top: 0.25rem;
|
||||
right: 0.25rem;
|
||||
font-size: 0.625rem;
|
||||
font-weight: 700;
|
||||
color: #fff;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -328,8 +328,8 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
min-height: 28.5rem;
|
||||
max-height: 28.5rem;
|
||||
min-height: 29rem;
|
||||
max-height: 29rem;
|
||||
user-select: none;
|
||||
|
||||
:global(.mobile-theme) & {
|
||||
|
||||
@@ -22,7 +22,7 @@ export const emojiRegex = EMOJI_REGEX
|
||||
export const emojiGlobalRegex = new RegExp(EMOJI_REGEX.source, EMOJI_REGEX.flags + 'g')
|
||||
|
||||
export const emoticonRegex = new RegExp(`(?:^|\\s)(${EMOTICON_REGEX.source})$`)
|
||||
export const emoticonGlobalRegex = new RegExp(`(?<!\\S)${EMOTICON_REGEX.source}(?!\\S)`, EMOTICON_REGEX.flags + 'g')
|
||||
export const emoticonGlobalRegex = new RegExp(EMOTICON_REGEX.source, EMOTICON_REGEX.flags + 'g')
|
||||
|
||||
export const shortcodeRegex = new RegExp(`(?:^|\\s)(${SHORTCODE_REGEX.source})$`)
|
||||
export const shortcodeGlobalRegex = new RegExp(`(?<!\\S)${SHORTCODE_REGEX.source}(?!\\S)`, SHORTCODE_REGEX.flags + 'g')
|
||||
export const shortcodeGlobalRegex = new RegExp(SHORTCODE_REGEX.source, SHORTCODE_REGEX.flags + 'g')
|
||||
|
||||
@@ -11,7 +11,14 @@ import {
|
||||
} from '@hcengineering/emoji'
|
||||
import emojiPlugin from '@hcengineering/emoji'
|
||||
import { type ResolvedPos } from '@tiptap/pm/model'
|
||||
import { type ExtendedRegExpMatchArray, type SingleCommands, type Range, InputRule, PasteRule } from '@tiptap/core'
|
||||
import {
|
||||
type ExtendedRegExpMatchArray,
|
||||
type SingleCommands,
|
||||
type Range,
|
||||
type PasteRuleMatch,
|
||||
InputRule,
|
||||
PasteRule
|
||||
} from '@tiptap/core'
|
||||
import { type EditorState } from '@tiptap/pm/state'
|
||||
import { getBlobRef } from '@hcengineering/presentation'
|
||||
import { getResource } from '@hcengineering/platform'
|
||||
@@ -63,6 +70,35 @@ function handleEmoji (
|
||||
}
|
||||
}
|
||||
|
||||
function detectPasteEmojis (text: string, regExp: RegExp): PasteRuleMatch[] | null | undefined {
|
||||
const matches = text.match(regExp)
|
||||
if (matches == null) return null
|
||||
let startIndex = 0
|
||||
const result: PasteRuleMatch[] = []
|
||||
for (let index = 0; index < matches.length; index++) {
|
||||
const match = matches[index]
|
||||
const matchStart = text.indexOf(match, startIndex)
|
||||
const matchEnd = matchStart + match.length
|
||||
const prevStartIndex = startIndex
|
||||
startIndex = matchEnd
|
||||
if (matchStart > prevStartIndex && text[matchStart - 1] !== ' ') {
|
||||
continue
|
||||
}
|
||||
if (matchEnd < text.length) {
|
||||
if (index === matches.length - 1 && text[matchEnd] !== ' ') continue
|
||||
if (
|
||||
index < matches.length - 1 &&
|
||||
text.indexOf(matches[index + 1], matchEnd) > matchEnd &&
|
||||
text[matchEnd] !== ' '
|
||||
) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
result.push({ index: matchStart, text: match })
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
export const EmojiExtension = EmojiNode.extend<EmojiNodeOptions>({
|
||||
addOptions () {
|
||||
return {
|
||||
@@ -80,19 +116,25 @@ export const EmojiExtension = EmojiNode.extend<EmojiNodeOptions>({
|
||||
})
|
||||
return [
|
||||
new PasteRule({
|
||||
find: shortcodeGlobalRegex,
|
||||
find: (text: string, event?: ClipboardEvent | null) => {
|
||||
return detectPasteEmojis(text, shortcodeGlobalRegex)
|
||||
},
|
||||
handler: ({ state, range, match, commands }) => {
|
||||
handleEmoji(state, range, match, commands, shortCodeFn)
|
||||
}
|
||||
}),
|
||||
new PasteRule({
|
||||
find: emojiGlobalRegex,
|
||||
find: (text: string, event?: ClipboardEvent | null) => {
|
||||
return detectPasteEmojis(text, emojiGlobalRegex)
|
||||
},
|
||||
handler: ({ state, range, match, commands }) => {
|
||||
handleEmoji(state, range, match, commands, (emoji: string | undefined) => emoji)
|
||||
}
|
||||
}),
|
||||
new PasteRule({
|
||||
find: emoticonGlobalRegex,
|
||||
find: (text: string, event?: ClipboardEvent | null) => {
|
||||
return detectPasteEmojis(text, emoticonGlobalRegex)
|
||||
},
|
||||
handler: ({ state, range, match, commands }) => {
|
||||
handleEmoji(state, range, match, commands, emoticonFn)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user