@@ -4,7 +4,7 @@ SPDX-License-Identifier: AGPL-3.0-only
44-->
55
66<template >
7- <div class =" omfetrab _popup" :class =" ['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow }]" :style =" { maxHeight: maxHeight ? maxHeight + 'px' : undefined }" >
7+ <div class =" omfetrab _popup" :class =" ['s' + size, 'w' + width, 'h' + height, { asDrawer, asWindow, allowWideCustomEmojis: prefer.s.allowWideCustomEmojisInPicker }]" :style =" { maxHeight: maxHeight ? maxHeight + 'px' : undefined }" >
88 <input
99 ref =" searchEl"
1010 :value =" q"
@@ -30,7 +30,10 @@ SPDX-License-Identifier: AGPL-3.0-only
3030 :title =" emoji.name"
3131 tabindex =" 0"
3232 @pointerenter =" (ev) => startPreview(`:${emoji.name}:`, ev)"
33- @pointerleave =" endPreview"
33+ @pointerleave =" leavePreview"
34+ @pointerdown =" (ev) => startTouchPreview(`:${emoji.name}:`, ev)"
35+ @pointerup =" endTouchPreview"
36+ @pointercancel =" cancelTouchPreview"
3437 @click =" chosen(emoji, $event)"
3538 >
3639 <MkCustomEmoji class="emoji" :name =" emoji .name " :fallbackToImage =" true " />
@@ -44,7 +47,10 @@ SPDX-License-Identifier: AGPL-3.0-only
4447 :title =" emoji.name"
4548 tabindex =" 0"
4649 @pointerenter =" (ev) => startPreview(emoji.char, ev)"
47- @pointerleave =" endPreview"
50+ @pointerleave =" leavePreview"
51+ @pointerdown =" (ev) => startTouchPreview(emoji.char, ev)"
52+ @pointerup =" endTouchPreview"
53+ @pointercancel =" cancelTouchPreview"
4854 @click =" chosen(emoji, $event)"
4955 >
5056 <MkEmoji class="emoji" :emoji =" emoji .char " />
@@ -64,7 +70,10 @@ SPDX-License-Identifier: AGPL-3.0-only
6470 :title =" emoji.name"
6571 tabindex =" 0"
6672 @pointerenter =" (ev) => startPreview(`:${emoji.name}:`, ev)"
67- @pointerleave =" endPreview"
73+ @pointerleave =" leavePreview"
74+ @pointerdown =" (ev) => startTouchPreview(`:${emoji.name}:`, ev)"
75+ @pointerup =" endTouchPreview"
76+ @pointercancel =" cancelTouchPreview"
6877 @click =" chosen(emoji, $event)"
6978 >
7079 <MkCustomEmoji class="emoji" :name =" emoji .name " :normal =" true " />
@@ -83,7 +92,10 @@ SPDX-License-Identifier: AGPL-3.0-only
8392 :disabled =" !canReact(emoji)"
8493 tabindex =" 0"
8594 @pointerenter =" (ev) => { startPreview(getKey(emoji), ev); computeButtonTitle(ev); }"
86- @pointerleave =" endPreview"
95+ @pointerleave =" leavePreview"
96+ @pointerdown =" (ev) => startTouchPreview(getKey(emoji), ev)"
97+ @pointerup =" endTouchPreview"
98+ @pointercancel =" cancelTouchPreview"
8799 @click =" chosen(emoji, $event)"
88100 >
89101 <MkCustomEmoji v-if =" ! emoji .hasOwnProperty (' char' )" class="emoji" :name =" getKey (emoji )" :normal =" true " />
@@ -103,7 +115,10 @@ SPDX-License-Identifier: AGPL-3.0-only
103115 :disabled =" !canReact(emoji)"
104116 :data-emoji =" getKey(emoji)"
105117 @pointerenter =" (ev) => { startPreview(getKey(emoji), ev); computeButtonTitle(ev); }"
106- @pointerleave =" endPreview"
118+ @pointerleave =" leavePreview"
119+ @pointerdown =" (ev) => startTouchPreview(getKey(emoji), ev)"
120+ @pointerup =" endTouchPreview"
121+ @pointercancel =" cancelTouchPreview"
107122 @click =" chosen(emoji, $event)"
108123 >
109124 <MkCustomEmoji v-if =" ! emoji .hasOwnProperty (' char' )" class="emoji" :name =" getKey (emoji )" :normal =" true " />
@@ -124,14 +139,17 @@ SPDX-License-Identifier: AGPL-3.0-only
124139 :customEmojiTree =" child .children "
125140 @chosen =" chosen "
126141 @previewEnter =" (emoji : string , ev : PointerEvent ) => startPreview (emoji , ev ) "
142+ @previewTouchStart =" (emoji : string , ev : PointerEvent ) => startTouchPreview (emoji , ev ) "
127143 @previewLeave =" endPreview "
144+ @previewTouchEnd =" endTouchPreview "
145+ @previewTouchCancel =" cancelTouchPreview "
128146 >
129147 {{ child.value || i18n.ts.other }}
130148 </XSection >
131149 </div >
132150 <div v-once class =" group" >
133151 <header class =" _acrylic" >{{ i18n.ts.emoji }}</header >
134- <XSection v-for =" category in categories " :key =" category " :emojis =" emojiCharByCategory .get (category ) ?? []" :hasChildSection =" false " @chosen =" chosen " @previewEnter =" (emoji : string , ev : PointerEvent ) => startPreview (emoji , ev ) " @previewLeave =" endPreview " >{{ category }}</XSection >
152+ <XSection v-for =" category in categories " :key =" category " :emojis =" emojiCharByCategory .get (category ) ?? []" :hasChildSection =" false " @chosen =" chosen " @previewEnter =" (emoji : string , ev : PointerEvent ) => startPreview (emoji , ev ) " @previewTouchStart = " ( emoji : string , ev : PointerEvent ) => startTouchPreview ( emoji , ev ) " @ previewLeave =" endPreview " @ previewTouchEnd = " endTouchPreview " @ previewTouchCancel = " cancelTouchPreview " >{{ category }}</XSection >
135153 </div >
136154 </div >
137155 <div class =" tabs" >
@@ -213,6 +231,7 @@ const emit = defineEmits<{
213231let previewTimer: number | null = null ;
214232let previewPopupDispose: (() => void ) | null = null ;
215233let closePreviewPopup: (() => void ) | null = null ;
234+ let suppressNextClick = false ;
216235
217236function clearPreviewTimer(): void {
218237 if (previewTimer !== null ) {
@@ -253,25 +272,60 @@ function showPreviewPopup(emoji: string, anchorElement: HTMLElement): void {
253272 };
254273}
255274
275+ function schedulePreview(emoji : string , target : HTMLElement , options : { suppressClickOnOpen? : boolean } = {}): void {
276+ clearPreviewTimer ();
277+ hidePreviewPopup ();
278+
279+ previewTimer = window .setTimeout (() => {
280+ showPreviewPopup (emoji , target );
281+ if (options .suppressClickOnOpen ) suppressNextClick = true ;
282+ }, PREVIEW_DELAY );
283+ }
284+
256285function startPreview(emoji : string , ev : PointerEvent ): void {
257286 if (ev .pointerType === ' touch' ) return ;
258287
259288 const target = ev .currentTarget as HTMLElement | null ;
260289 if (target == null ) return ;
261290
262- clearPreviewTimer ( );
263- hidePreviewPopup ();
291+ schedulePreview ( emoji , target );
292+ }
264293
265- previewTimer = window .setTimeout (() => {
266- showPreviewPopup (emoji , target );
267- }, PREVIEW_DELAY );
294+ function startTouchPreview(emoji : string , ev : PointerEvent ): void {
295+ if (ev .pointerType !== ' touch' ) return ;
296+
297+ const target = ev .currentTarget as HTMLElement | null ;
298+ if (target == null ) return ;
299+
300+ suppressNextClick = false ;
301+ schedulePreview (emoji , target , { suppressClickOnOpen: true });
268302}
269303
270304function endPreview(): void {
271305 clearPreviewTimer ();
272306 hidePreviewPopup ();
273307}
274308
309+ function endTouchPreview(ev : PointerEvent ): void {
310+ if (ev .pointerType !== ' touch' ) return ;
311+ endPreview ();
312+ }
313+
314+ function cancelTouchPreview(ev : PointerEvent ): void {
315+ if (ev .pointerType !== ' touch' ) return ;
316+ suppressNextClick = false ;
317+ endPreview ();
318+ }
319+
320+ function leavePreview(ev : PointerEvent ): void {
321+ if (ev .pointerType === ' touch' ) {
322+ cancelTouchPreview (ev );
323+ return ;
324+ }
325+
326+ endPreview ();
327+ }
328+
275329const searchEl = useTemplateRef (' searchEl' );
276330const emojisEl = useTemplateRef (' emojisEl' );
277331
@@ -640,6 +694,14 @@ function computeButtonTitle(ev: PointerEvent): void {
640694}
641695
642696function chosen(emoji : string | Misskey .entities .EmojiSimple | UnicodeEmojiDef , ev ? : PointerEvent ) {
697+ if (suppressNextClick ) {
698+ ev ?.preventDefault ();
699+ ev ?.stopPropagation ();
700+ suppressNextClick = false ;
701+ endPreview ();
702+ return ;
703+ }
704+
643705 endPreview ();
644706
645707 const el = ev && (ev .currentTarget ?? ev .target ) as HTMLElement | null | undefined ;
@@ -906,6 +968,32 @@ defineExpose({
906968 }
907969 }
908970
971+ & .allowWideCustomEmojis {
972+ > .emojis {
973+ ::v-deep (section ) {
974+ > .body {
975+ display : flex ;
976+ flex-wrap : wrap ;
977+ align-content : flex-start ;
978+
979+ > .item {
980+ aspect-ratio : auto ;
981+ width : fit-content ;
982+ height : var (--eachSize );
983+ min-width : var (--eachSize );
984+ contain : layout style ;
985+ box-sizing : border-box ;
986+
987+ > .emoji {
988+ width : auto ;
989+ object-fit : unset ;
990+ }
991+ }
992+ }
993+ }
994+ }
995+ }
996+
909997 > .search {
910998 width : 100% ;
911999 padding : 12px ;
0 commit comments