enhance(client): update emoji picker immediately on all input (#9385)
* enhance: update emoji picker immediately on all input * refactor: remove reference to window.clipboardData * refactor: done() receives a string * refactor: typescript-favored `.char` access
This commit is contained in:
parent
aa23dbbb8a
commit
69087f2242
@ -1,6 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
|
<div class="omfetrab" :class="['s' + size, 'w' + width, 'h' + height, { asDrawer }]" :style="{ maxHeight: maxHeight ? maxHeight + 'px' : undefined }">
|
||||||
<input ref="search" v-model.trim="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" @paste.stop="paste" @keyup.enter="done()">
|
<input ref="search" :value="q" class="search" data-prevent-emoji-insert :class="{ filled: q != null && q != '' }" :placeholder="i18n.ts.search" type="search" @input="input()" @paste.stop="paste" @keyup.enter="done()">
|
||||||
<div ref="emojis" class="emojis">
|
<div ref="emojis" class="emojis">
|
||||||
<section class="result">
|
<section class="result">
|
||||||
<div v-if="searchResultCustom.length > 0" class="body">
|
<div v-if="searchResultCustom.length > 0" class="body">
|
||||||
@ -121,7 +121,7 @@ const width = computed(() => props.asReactionPicker ? reactionPickerWidth.value
|
|||||||
const height = computed(() => props.asReactionPicker ? reactionPickerHeight.value : 2);
|
const height = computed(() => props.asReactionPicker ? reactionPickerHeight.value : 2);
|
||||||
const customEmojiCategories = emojiCategories;
|
const customEmojiCategories = emojiCategories;
|
||||||
const customEmojis = instance.emojis;
|
const customEmojis = instance.emojis;
|
||||||
const q = ref<string | null>(null);
|
const q = ref<string>('');
|
||||||
const searchResultCustom = ref<Misskey.entities.CustomEmoji[]>([]);
|
const searchResultCustom = ref<Misskey.entities.CustomEmoji[]>([]);
|
||||||
const searchResultUnicode = ref<UnicodeEmojiDef[]>([]);
|
const searchResultUnicode = ref<UnicodeEmojiDef[]>([]);
|
||||||
const tab = ref<'index' | 'custom' | 'unicode' | 'tags'>('index');
|
const tab = ref<'index' | 'custom' | 'unicode' | 'tags'>('index');
|
||||||
@ -129,7 +129,7 @@ const tab = ref<'index' | 'custom' | 'unicode' | 'tags'>('index');
|
|||||||
watch(q, () => {
|
watch(q, () => {
|
||||||
if (emojis.value) emojis.value.scrollTop = 0;
|
if (emojis.value) emojis.value.scrollTop = 0;
|
||||||
|
|
||||||
if (q.value == null || q.value === '') {
|
if (q.value === '') {
|
||||||
searchResultCustom.value = [];
|
searchResultCustom.value = [];
|
||||||
searchResultUnicode.value = [];
|
searchResultUnicode.value = [];
|
||||||
return;
|
return;
|
||||||
@ -281,7 +281,7 @@ function reset() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function getKey(emoji: string | Misskey.entities.CustomEmoji | UnicodeEmojiDef): string {
|
function getKey(emoji: string | Misskey.entities.CustomEmoji | UnicodeEmojiDef): string {
|
||||||
return typeof emoji === 'string' ? emoji : (emoji.char || `:${emoji.name}:`);
|
return typeof emoji === 'string' ? emoji : 'char' in emoji ? emoji.char : `:${emoji.name}:`;
|
||||||
}
|
}
|
||||||
|
|
||||||
function chosen(emoji: any, ev?: MouseEvent) {
|
function chosen(emoji: any, ev?: MouseEvent) {
|
||||||
@ -305,14 +305,21 @@ function chosen(emoji: any, ev?: MouseEvent) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function paste(event: ClipboardEvent) {
|
function input(): void {
|
||||||
const paste = (event.clipboardData || window.clipboardData).getData('text');
|
// Using custom input event instead of v-model to respond immediately on
|
||||||
if (done(paste)) {
|
// Android, where composition happens on all languages
|
||||||
|
// (v-model does not update during composition)
|
||||||
|
q.value = search.value?.value.trim() ?? '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function paste(event: ClipboardEvent): void {
|
||||||
|
const pasted = event.clipboardData?.getData('text') ?? '';
|
||||||
|
if (done(pasted)) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function done(query?: any): boolean | void {
|
function done(query?: string): boolean | void {
|
||||||
if (query == null) query = q.value;
|
if (query == null) query = q.value;
|
||||||
if (query == null || typeof query !== 'string') return;
|
if (query == null || typeof query !== 'string') return;
|
||||||
|
|
||||||
|
@ -16,10 +16,14 @@ export class Autocomplete {
|
|||||||
private opening: boolean;
|
private opening: boolean;
|
||||||
|
|
||||||
private get text(): string {
|
private get text(): string {
|
||||||
return this.textRef.value;
|
// Use raw .value to get the latest value
|
||||||
|
// (Because v-model does not update while composition)
|
||||||
|
return this.textarea.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private set text(text: string) {
|
private set text(text: string) {
|
||||||
|
// Use ref value to notify other watchers
|
||||||
|
// (Because .value setter never fires input/change events)
|
||||||
this.textRef.value = text;
|
this.textRef.value = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user