From adc5448adf863b99b9b2be29985e560f5c12dbd4 Mon Sep 17 00:00:00 2001 From: Zelong Lin Date: Tue, 29 Aug 2023 16:14:04 +0200 Subject: [PATCH] [IMP] mail: single unified Picker (Gif & Emoji) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, emoji and gif pickers were handled as 2 different pickers. They had dedicated buttons. This made composer quite bloated, especially in chat windows were size is narrow. Also the pickers were always displayed as popover, which is not the best way to show content in mobile. This commit improves those pickers in discuss so that only a single button is present (emoji button). Clicking on this button shows a picker that groups the emoji and gif picker, both of which can be selected in the header of the grouped picker. In mobile, instead of showing a popover, it now shows the grouped picker below the composer. This makes it show where the soft keyboard is present in mobile, making it easier to input emojis or gifs on those devices. This commit also added slight style changes to both pickers. Notably, the search bar has an improved style that makes it look good when next to the composer text input, especially in mobile layout. task-3015707 closes odoo/odoo#123671 Signed-off-by: Alexandre KΓΌhn (aku) --- .../mail/static/src/core/common/composer.js | 65 +++----- .../mail/static/src/core/common/composer.scss | 4 - .../mail/static/src/core/common/composer.xml | 8 +- addons/mail/static/src/core/common/core.scss | 4 + .../core/common/message_reaction_button.xml | 2 +- addons/mail/static/src/core/common/picker.js | 157 ++++++++++++++++++ .../mail/static/src/core/common/picker.scss | 17 ++ addons/mail/static/src/core/common/picker.xml | 10 ++ .../static/src/core/common/picker_content.js | 19 +++ .../src/core/common/picker_content.scss | 9 + .../static/src/core/common/picker_content.xml | 14 ++ .../static/src/core/web/command_palette.xml | 2 +- .../gif_picker/common/composer_patch.js | 51 +++--- .../gif_picker/common/composer_patch.xml | 10 +- .../gif_picker/common/gif_picker.dark.scss | 3 + .../discuss/gif_picker/common/gif_picker.js | 86 +++++----- .../discuss/gif_picker/common/gif_picker.scss | 27 +-- .../discuss/gif_picker/common/gif_picker.xml | 27 ++- .../gif_picker/common/picker_content_patch.js | 17 ++ .../common/picker_content_patch.scss | 12 ++ .../common/picker_content_patch.xml | 26 +++ .../discuss/gif_picker/common/picker_patch.js | 31 ++++ addons/mail/static/src/utils/common/hooks.js | 13 +- .../static/tests/composer/composer_tests.js | 10 +- addons/mail/static/tests/emoji/emoji_tests.js | 18 +- .../tests/gif_picker/gif_picker_test.js | 10 +- .../core/emoji_picker/emoji_picker.dark.scss | 3 + .../src/core/emoji_picker/emoji_picker.js | 44 +++-- .../src/core/emoji_picker/emoji_picker.scss | 51 ++---- .../src/core/emoji_picker/emoji_picker.xml | 33 ++-- 30 files changed, 531 insertions(+), 252 deletions(-) create mode 100644 addons/mail/static/src/core/common/picker.js create mode 100644 addons/mail/static/src/core/common/picker.scss create mode 100644 addons/mail/static/src/core/common/picker.xml create mode 100644 addons/mail/static/src/core/common/picker_content.js create mode 100644 addons/mail/static/src/core/common/picker_content.scss create mode 100644 addons/mail/static/src/core/common/picker_content.xml create mode 100644 addons/mail/static/src/discuss/gif_picker/common/gif_picker.dark.scss create mode 100644 addons/mail/static/src/discuss/gif_picker/common/picker_content_patch.js create mode 100644 addons/mail/static/src/discuss/gif_picker/common/picker_content_patch.scss create mode 100644 addons/mail/static/src/discuss/gif_picker/common/picker_content_patch.xml create mode 100644 addons/mail/static/src/discuss/gif_picker/common/picker_patch.js create mode 100644 addons/web/static/src/core/emoji_picker/emoji_picker.dark.scss diff --git a/addons/mail/static/src/core/common/composer.js b/addons/mail/static/src/core/common/composer.js index b8a80bdb854..2af4adf264d 100644 --- a/addons/mail/static/src/core/common/composer.js +++ b/addons/mail/static/src/core/common/composer.js @@ -3,7 +3,7 @@ import { AttachmentList } from "@mail/core/common/attachment_list"; import { useAttachmentUploader } from "@mail/core/common/attachment_uploader_hook"; import { useDropzone } from "@mail/core/common/dropzone_hook"; -import { EmojiPicker, useEmojiPicker } from "@web/core/emoji_picker/emoji_picker"; +import { Picker, usePicker } from "@mail/core/common/picker"; import { MessageConfirmDialog } from "@mail/core/common/message_confirm_dialog"; import { NavigableList } from "@mail/core/common/navigable_list"; import { useSuggestion } from "@mail/core/common/suggestion_hook"; @@ -18,12 +18,10 @@ import { onMounted, useChildSubEnv, useEffect, - useExternalListener, useRef, useState, } from "@odoo/owl"; -import { browser } from "@web/core/browser/browser"; import { _t } from "@web/core/l10n/translation"; import { useService } from "@web/core/utils/hooks"; import { FileUploader } from "@web/views/fields/file_handler"; @@ -52,7 +50,7 @@ const EDIT_CLICK_TYPE = { export class Composer extends Component { static components = { AttachmentList, - EmojiPicker, + Picker, FileUploader, NavigableList, }; @@ -82,10 +80,6 @@ export class Composer extends Component { this.SEND_KEYBIND_TO_SEND = markup( _t("%(send_keybind)s to send", { send_keybind: this.sendKeybind }) ); - this.KEYBOARD = { - NONE: "None", - EMOJI: "Emoji", - }; this.store = useState(useService("mail.store")); if (this.allowUpload) { this.attachmentUploader = useAttachmentUploader( @@ -97,12 +91,13 @@ export class Composer extends Component { this.threadService = useService("mail.thread"); this.ui = useState(useService("ui")); this.rpc = useService("rpc"); + this.mainActionsRef = useRef("main-actions"); this.ref = useRef("textarea"); this.fakeTextarea = useRef("fakeTextarea"); + this.emojiButton = useRef("emoji-button"); this.state = useState({ autofocus: 0, active: true, - keyboard: this.KEYBOARD.NONE, }); this.selection = useSelection({ refName: "textarea", @@ -132,26 +127,7 @@ export class Composer extends Component { useChildSubEnv({ inComposer: true, }); - if (!this.ui.isSmall) { - useEmojiPicker(useRef("emoji-button"), { - onSelect: (str) => this.addEmoji(str), - onClose: () => this.state.autofocus++, - }); - } - useExternalListener( - browser, - "click", - async (ev) => { - if (this.state.keyboard === this.KEYBOARD.NONE) { - return; - } - await new Promise(setTimeout); // let bubbling to catch marked event handled - if (!this.isEventHandledByPicker(ev)) { - this.state.keyboard = this.KEYBOARD.NONE; - } - }, - true - ); + this.picker = usePicker(this.pickerSettings); useEffect( (focus) => { if (focus && this.ref.el) { @@ -190,6 +166,20 @@ export class Composer extends Component { }); } + get pickerSettings() { + return { + anchor: this.props.mode === "extended" ? undefined : this.mainActionsRef, + buttons: [this.emojiButton], + close: () => { + if (!this.ui.isSmall) { + this.state.autofocus++; + } + }, + pickers: { emoji: (emoji) => this.addEmoji(emoji) }, + position: this.props.mode === "extended" ? "bottom-start" : "top-end", + }; + } + get placeholder() { if (this.props.placeholder) { return this.props.placeholder; @@ -234,17 +224,6 @@ export class Composer extends Component { return this.props.mode === "extended" ? _t("CTRL-Enter") : _t("Enter"); } - /** - * @param {Event} ev - * @returns {boolean} - */ - isEventHandledByPicker(ev) { - return ( - isEventHandled(ev, "Composer.onClickAddEmoji") || - isEventHandled(ev, "EmojiPicker.onClick") - ); - } - get thread() { return ( this.props.messageToReplyTo?.message?.originThread ?? this.props.composer.thread ?? null @@ -492,8 +471,6 @@ export class Composer extends Component { onClickAddEmoji(ev) { markEventHandled(ev, "Composer.onClickAddEmoji"); - this.state.keyboard = - this.state.keyboard === this.KEYBOARD.EMOJI ? this.KEYBOARD.NONE : this.KEYBOARD.EMOJI; } isEventTrusted(ev) { @@ -593,7 +570,9 @@ export class Composer extends Component { const secondPart = textContent.slice(this.props.composer.selection.end, textContent.length); this.props.composer.textInputContent = firstPart + str + secondPart; this.selection.moveCursor((firstPart + str).length); - this.state.autofocus++; + if (!this.ui.isSmall) { + this.state.autofocus++; + } } onFocusin() { diff --git a/addons/mail/static/src/core/common/composer.scss b/addons/mail/static/src/core/common/composer.scss index 35321ab6fb7..1c04322c361 100644 --- a/addons/mail/static/src/core/common/composer.scss +++ b/addons/mail/static/src/core/common/composer.scss @@ -40,10 +40,6 @@ } } -.o-mail-Composer-bottomPicker { - height: 60vh; -} - .o-mail-Composer-input { padding-top: 10px; // carefully crafted to have the text in the middle in chat window padding-bottom: 10px; diff --git a/addons/mail/static/src/core/common/composer.xml b/addons/mail/static/src/core/common/composer.xml index 664867d6219..4c79bf2a0dc 100644 --- a/addons/mail/static/src/core/common/composer.xml +++ b/addons/mail/static/src/core/common/composer.xml @@ -70,11 +70,11 @@ 'mx-3 border-top p-1': extended, }" > -
- -
@@ -93,7 +93,7 @@ attachments="props.composer.attachments" unlinkAttachment.bind="(...args) => attachmentUploader.unlink(...args)" imagesHeight="50"/> - + diff --git a/addons/mail/static/src/core/common/core.scss b/addons/mail/static/src/core/common/core.scss index 05605518b57..2279e093411 100644 --- a/addons/mail/static/src/core/common/core.scss +++ b/addons/mail/static/src/core/common/core.scss @@ -22,6 +22,10 @@ font-size: 0.7em !important; } +.o-min-height-0 { + min-height: 0; +} + .o-min-width-0 { min-width: 0; } diff --git a/addons/mail/static/src/core/common/message_reaction_button.xml b/addons/mail/static/src/core/common/message_reaction_button.xml index 8f0049b7376..cc051d7cb9b 100644 --- a/addons/mail/static/src/core/common/message_reaction_button.xml +++ b/addons/mail/static/src/core/common/message_reaction_button.xml @@ -1,7 +1,7 @@ - + diff --git a/addons/mail/static/src/core/common/picker.js b/addons/mail/static/src/core/common/picker.js new file mode 100644 index 00000000000..e49f5f81725 --- /dev/null +++ b/addons/mail/static/src/core/common/picker.js @@ -0,0 +1,157 @@ +/* @odoo-module */ + +import { Component, useExternalListener, useState } from "@odoo/owl"; +import { browser } from "@web/core/browser/browser"; +import { isEventHandled } from "@web/core/utils/misc"; +import { usePopover } from "@web/core/popover/popover_hook"; +import { useService } from "@web/core/utils/hooks"; +import { PickerContent } from "@mail/core/common/picker_content"; +import { useLazyExternalListener } from "@mail/utils/common/hooks"; + +export function usePicker(setting) { + const storeScroll = { + scrollValue: 0, + set: (value) => (storeScroll.scrollValue = value), + get: () => storeScroll.scrollValue, + }; + const PICKERS = { + NONE: "none", + EMOJI: "emoji", + GIF: "gif", + }; + return useState({ + PICKERS, + anchor: setting.anchor, + buttons: setting.buttons, + close: setting.close, + pickers: setting.pickers, + position: setting.position, + state: { + picker: PICKERS.NONE, + searchTerm: "", + }, + storeScroll, + }); +} + +/** + * Picker/usePicker is a component hook that can be used to display the emoji picker/gif picker (if it is enabled). + * It can be used in two ways: + * - with a popover when in large screen: the picker will be displayed in a popover triggered by provided buttons. + * - with a keyboard when in mobile view: the picker will be displayed in place where the Picker component is placed. + * The switch between the two modes is done automatically based on the screen size. + */ + +export class Picker extends Component { + static components = { + PickerContent, + }; + static props = [ + "PICKERS", + "anchor?", + "buttons", + "close?", + "state", + "pickers", + "position?", + "storeScroll", + ]; + static template = "mail.Picker"; + + setup() { + this.ui = useState(useService("ui")); + this.popover = usePopover(PickerContent, { + position: this.props.position, + fixedPosition: true, + onClose: () => this.close(), + closeOnClickAway: false, + popoverClass: "o-fast-popover", + }); + useExternalListener( + browser, + "click", + async (ev) => { + if (this.props.state.picker === this.props.PICKERS.NONE) { + return; + } + await new Promise(setTimeout); // let bubbling to catch marked event handled + if (!this.isEventHandledByPicker(ev)) { + this.close(); + } + }, + true + ); + for (const button of this.props.buttons) { + useLazyExternalListener( + () => button.el, + "click", + async (ev) => this.toggle(this.props.anchor?.el ?? button.el, ev) + ); + } + } + + get contentProps() { + const pickers = {}; + for (const [name, fn] of Object.entries(this.props.pickers)) { + pickers[name] = (str, resetOnSelect) => { + fn(str); + if (resetOnSelect) { + this.close(); + } + }; + } + return { + PICKERS: this.props.PICKERS, + close: () => this.close(), + pickers, + state: this.props.state, + storeScroll: this.props.storeScroll, + }; + } + + /** + * @param {Event} ev + * @returns {boolean} + */ + isEventHandledByPicker(ev) { + return ( + isEventHandled(ev, "Composer.onClickAddEmoji") || + isEventHandled(ev, "PickerContent.onClick") + ); + } + + async toggle(el, ev) { + // Let event be handled by bubbling handlers first. + await new Promise(setTimeout); + // In small screen, we toggle keyboard picker. + if (this.ui.isSmall) { + if (this.props.state.picker === this.props.PICKERS.NONE) { + this.props.state.picker = this.props.PICKERS.EMOJI; + } else { + this.props.state.picker = this.props.PICKERS.NONE; + } + return; + } + // In large screen, we toggle popover. + if (isEventHandled(ev, "Composer.onClickAddEmoji")) { + if (this.popover.isOpen) { + if (this.props.state.picker === this.props.PICKERS.EMOJI) { + this.props.state.picker = this.props.PICKERS.NONE; + this.popover.close(); + return; + } + this.props.state.picker = this.props.PICKERS.EMOJI; + } else { + this.props.state.picker = this.props.PICKERS.EMOJI; + this.popover.open(el, this.contentProps); + } + } + } + + close() { + this.props.close?.(); + this.popover.close(); + this.props.state.picker = this.props.PICKERS.NONE; + this.props.state.searchTerm = ""; + } +} diff --git a/addons/mail/static/src/core/common/picker.scss b/addons/mail/static/src/core/common/picker.scss new file mode 100644 index 00000000000..2a9b70b3cb0 --- /dev/null +++ b/addons/mail/static/src/core/common/picker.scss @@ -0,0 +1,17 @@ +// o-mail-Picker handles the styling of picker in mobile view only +.o-mail-Picker { + height: 55vh ; + + .o-EmojiPicker { + width: 100% !important; + + .o-Emoji { + width: 40px; + font-size: 1.5rem !important; + } + } + + .o-EmojiPicker-navbar { + gap: 0.5rem !important; + } +} diff --git a/addons/mail/static/src/core/common/picker.xml b/addons/mail/static/src/core/common/picker.xml new file mode 100644 index 00000000000..46bb8e96165 --- /dev/null +++ b/addons/mail/static/src/core/common/picker.xml @@ -0,0 +1,10 @@ + + + + +
+ +
+
+ +
diff --git a/addons/mail/static/src/core/common/picker_content.js b/addons/mail/static/src/core/common/picker_content.js new file mode 100644 index 00000000000..71541c44459 --- /dev/null +++ b/addons/mail/static/src/core/common/picker_content.js @@ -0,0 +1,19 @@ +/* @odoo-module */ + +import { Component } from "@odoo/owl"; +import { markEventHandled } from "@web/core/utils/misc"; +import { EmojiPicker } from "@web/core/emoji_picker/emoji_picker"; + +/** + * PickerContent is the content displayed in the popover/Picker. + * It is used to display the emoji picker/gif picker (if it is enabled). + */ +export class PickerContent extends Component { + static components = { EmojiPicker }; + static props = ["PICKERS", "close", "pickers", "state", "storeScroll"]; + static template = "mail.PickerContent"; + + onClick(ev) { + markEventHandled(ev, "PickerContent.onClick"); + } +} diff --git a/addons/mail/static/src/core/common/picker_content.scss b/addons/mail/static/src/core/common/picker_content.scss new file mode 100644 index 00000000000..c926e22ef34 --- /dev/null +++ b/addons/mail/static/src/core/common/picker_content.scss @@ -0,0 +1,9 @@ +.popover .o-mail-PickerContent { + width: 300px; + height: 365px; + + .o-EmojiPicker { + width: 100% !important; + height: 100% !important; + } +} diff --git a/addons/mail/static/src/core/common/picker_content.xml b/addons/mail/static/src/core/common/picker_content.xml new file mode 100644 index 00000000000..cc162df5079 --- /dev/null +++ b/addons/mail/static/src/core/common/picker_content.xml @@ -0,0 +1,14 @@ + + + + +
+
+
+ +
+
+
+
+ +
diff --git a/addons/mail/static/src/core/web/command_palette.xml b/addons/mail/static/src/core/web/command_palette.xml index bbde9149532..8aa8ae03149 100644 --- a/addons/mail/static/src/core/web/command_palette.xml +++ b/addons/mail/static/src/core/web/command_palette.xml @@ -1,7 +1,7 @@ - +
diff --git a/addons/mail/static/src/discuss/gif_picker/common/composer_patch.js b/addons/mail/static/src/discuss/gif_picker/common/composer_patch.js index 1845c6d049b..7f1e3377c39 100644 --- a/addons/mail/static/src/discuss/gif_picker/common/composer_patch.js +++ b/addons/mail/static/src/discuss/gif_picker/common/composer_patch.js @@ -1,50 +1,43 @@ /* @odoo-module */ -import { GifPicker, useGifPicker } from "@mail/discuss/gif_picker/common/gif_picker"; import { Composer } from "@mail/core/common/composer"; -import { onExternalClick } from "@mail/utils/common/hooks"; -import { isEventHandled, markEventHandled } from "@web/core/utils/misc"; +import { markEventHandled } from "@web/core/utils/misc"; -import { useState } from "@odoo/owl"; +import { useRef, useState } from "@odoo/owl"; import { useService } from "@web/core/utils/hooks"; import { patch } from "@web/core/utils/patch"; -Object.assign(Composer.components, { GifPicker }); /** @type {Composer} */ const composerPatch = { setup() { - super.setup(); - Object.assign(this.KEYBOARD, { GIF: "Gif" }); - onExternalClick("gif-picker", () => (this.state.keyboard = this.KEYBOARD.NONE)); - this.ui = useState(useService("ui")); this.gifPickerService = useState(useService("discuss.gifPicker")); - this.gifPicker = useGifPicker("gif-button", { - onSelected: this.sendGifMessage.bind(this), - }); + this.gifButton = useRef("gif-button"); + super.setup(); + this.ui = useState(useService("ui")); }, - /** - * @param {Event} ev - * @returns {boolean} - */ - isEventHandledByPicker(ev) { + get pickerSettings() { + const setting = super.pickerSettings; + if (this.hasGifPicker) { + setting.pickers.gif = (gif) => this.sendGifMessage(gif); + if (this.hasGifPickerButton) { + setting.buttons.push(this.gifButton); + } + } + return setting; + }, + get hasGifPicker() { return ( - super.isEventHandledByPicker(ev) || - isEventHandled(ev, "Composer.onClickAddGif") || - isEventHandled(ev, "GifPicker.onClick") + (this.gifPickerService.hasGifPickerFeature || this.store.user?.isAdmin) && + !this.env.inChatter && + !this.props.composer.message ); }, + get hasGifPickerButton() { + return this.hasGifPicker && !this.ui.isSmall && !this.env.inChatWindow; + }, onClickAddGif(ev) { markEventHandled(ev, "Composer.onClickAddGif"); - if (!this.ui.isSmall) { - this.gifPicker.toggle(); - } else { - if (this.state.keyboard !== this.KEYBOARD.GIF) { - this.state.keyboard = this.KEYBOARD.GIF; - } else { - this.state.keyboard = this.KEYBOARD.NONE; - } - } }, async sendGifMessage(gif) { await this._sendMessage(gif.url, { diff --git a/addons/mail/static/src/discuss/gif_picker/common/composer_patch.xml b/addons/mail/static/src/discuss/gif_picker/common/composer_patch.xml index a0d38b44303..e92cec1e07c 100644 --- a/addons/mail/static/src/discuss/gif_picker/common/composer_patch.xml +++ b/addons/mail/static/src/discuss/gif_picker/common/composer_patch.xml @@ -1,11 +1,13 @@ - - diff --git a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.dark.scss b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.dark.scss new file mode 100644 index 00000000000..7f5213f5d60 --- /dev/null +++ b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.dark.scss @@ -0,0 +1,3 @@ +.o-discuss-GifPicker { + --o-gif-picker-active: #{$white}; +} diff --git a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.js b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.js index a84b77ccc09..8ecac012240 100644 --- a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.js +++ b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.js @@ -1,12 +1,9 @@ /* @odoo-module */ +import { Component, onWillStart, useState, useEffect } from "@odoo/owl"; import { removeFromArrayWithPredicate } from "@mail/utils/common/arrays"; import { useOnBottomScrolled, useSequential } from "@mail/utils/common/hooks"; -import { markEventHandled } from "@web/core/utils/misc"; -import { Component, onWillStart, useRef, useState } from "@odoo/owl"; - -import { usePopover } from "@web/core/popover/popover_hook"; import { useService, useAutofocus } from "@web/core/utils/hooks"; import { useDebounced } from "@web/core/utils/timing"; @@ -41,36 +38,17 @@ import { useDebounced } from "@web/core/utils/timing"; * @property {{ tinygif: TenorMediaFormat }} media_formats */ -/** - * @param {import("@web/core/utils/common/hooks").Ref} ref - * @param {{ onSelected: function, className: String }} options - */ -export function useGifPicker(refName, options) { - const ref = useRef(refName); - const popover = usePopover(GifPicker, { - position: "top", - popoverClass: "o-fast-popover", - }); - function toggle() { - if (popover.isOpen) { - popover.close(); - } else { - popover.open(ref.el, options); - } - } - return { toggle }; -} - /** * @typedef {Object} Props - * @property {function} onSelected Callback to use when the gif is selected + * @property {function} onSelect Callback to use when the gif is selected * @property {string} [className] * @property {function} [close] + * @property {Object} [state] * @extends {Component} */ export class GifPicker extends Component { static template = "discuss.GifPicker"; - static props = ["onSelected", "className?", "close?"]; + static props = ["PICKERS?", "className?", "close?", "onSelect", "state?"]; setup() { this.rpc = useService("rpc"); @@ -130,6 +108,34 @@ export class GifPicker extends Component { this.loadFavorites(); }); } + useEffect( + () => { + if (this.props.state?.picker !== this.props.PICKERS?.GIF) { + return; + } + this.clear(); + this.state.loadingGif = true; + this.search(); + if (this.searchTerm) { + this.closeCategories(); + } else { + this.openCategories(); + } + }, + () => [this.searchTerm, this.props.state?.picker] + ); + } + + get searchTerm() { + return this.props.state ? this.props.state.searchTerm : this.state.searchTerm; + } + + set searchTerm(value) { + if (this.props.state) { + this.props.state.searchTerm = value; + } else { + this.state.searchTerm = value; + } } async loadCategories() { @@ -152,7 +158,7 @@ export class GifPicker extends Component { openCategories() { this.state.showCategories = true; - this.state.searchTerm = ""; + this.searchTerm = ""; this.clear(); } @@ -161,14 +167,14 @@ export class GifPicker extends Component { } async search() { - if (!this.state.searchTerm) { + if (!this.searchTerm) { return; } try { const params = { country: this.userService.lang.slice(3, 5), locale: this.userService.lang, - search_term: this.state.searchTerm, + search_term: this.searchTerm, }; if (this.next) { params.position = this.next; @@ -207,27 +213,12 @@ export class GifPicker extends Component { } } - onInput() { - this.clear(); - this.state.loadingGif = true; - this.search(); - if (this.state.searchTerm) { - this.closeCategories(); - } else { - this.openCategories(); - } - } - - onClick(ev) { - markEventHandled(ev, "GifPicker.onClick"); - } - /** * @param {TenorGif} gif */ onClickGif(gif) { - this.props.onSelected(gif); - this.props.close(); + this.props.onSelect(gif, true); + this.props.close?.(); } clear() { @@ -242,8 +233,7 @@ export class GifPicker extends Component { */ async onClickCategory(category) { this.clear(); - this.state.searchTerm = category.searchterm; - await this.search(); + this.props.state.searchTerm = category.searchterm; this.closeCategories(); } diff --git a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.scss b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.scss index f932e66f009..9bf17903047 100644 --- a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.scss +++ b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.scss @@ -4,33 +4,12 @@ } .o-discuss-GifPicker { - display: grid; - grid-template-areas: - "search" - "content"; - grid-template-rows: 40px 1fr; -} - -.o-discuss-GifPicker-search { - grid-area: search; - background-color: $input-bg; - - input { - &:focus, &:hover { - & + .oi-search { - @extend .bg-view !optional; - } - } - &:not(:focus) + .oi-search { - opacity: 60%; - } + --o-gif-picker-active: #{$gray-200}; + .o-active { + background-color: var(--o-gif-picker-active) !important; } } -.o-discuss-GifPicker-content { - grid-area: content; -} - .o-discuss-GifPickerCategory-img { object-fit: cover; } diff --git a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.xml b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.xml index 1984a72fbbd..7466e861dbc 100644 --- a/addons/mail/static/src/discuss/gif_picker/common/gif_picker.xml +++ b/addons/mail/static/src/discuss/gif_picker/common/gif_picker.xml @@ -1,20 +1,25 @@ -
-