0

Make GIFs clearable

Add a context menu for <emoji-image /> (under history group), so users can remove GIFs individually.

Bug: b:282083514
Change-Id: I7d0411c091a3a812839b8430ced5093ad3a3d860
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4533818
Reviewed-by: Zac Partridge <zacpartridge@google.com>
Commit-Queue: Grey Wang <greywang@google.com>
Cr-Commit-Position: refs/heads/main@{#1144564}
This commit is contained in:
Grey Wang
2023-05-16 07:15:41 +00:00
committed by Chromium LUCI CQ
parent f4538fa9bf
commit 6bb21a64ac
5 changed files with 119 additions and 28 deletions
chrome/browser/resources/chromeos/emoji_picker

@ -248,7 +248,8 @@
<emoji-image index="[[getIndex(item)]]"
item="[[item]]"
show-tooltip="[[showTooltip]]"
emoji-click="[[onEmojiClick]]">
emoji-click="[[onEmojiClick]]"
clearable="[[clearable]]">
</emoji-image>
</template>
</div>
@ -257,7 +258,8 @@
<emoji-image index="[[getIndex(item)]]"
item="[[item]]"
show-tooltip="[[showTooltip]]"
emoji-click="[[onEmojiClick]]">
emoji-click="[[onEmojiClick]]"
clearable="[[clearable]]">
</emoji-image>
</template>
</div>

@ -1,4 +1,8 @@
<style>
.emoji-image-container {
position: relative;
}
.emoji-image {
background-color: var(--cros-button-stroke-color-secondary-disabled);
border: none;
@ -39,15 +43,53 @@
opacity: 1;
}
}
.emoji-image-clear {
background-color: var(--cros-bg-color);
border: 2px solid transparent;
border-radius: 4px;
box-shadow: var(--cr-elevation-1);
color: var(--cros-text-color-secondary);
cursor: pointer;
font-family: 'Roboto', sans-serif;
font-size: 12px;
height: var(--emoji-size);
outline: none;
padding: 7px 11px 7px 11px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
white-space: nowrap;
width: fit-content;
z-index: 200;
}
.emoji-image-clear:focus,
.emoji-image-clear:active {
border: 2px solid var(--cros-toggle-color);
}
</style>
<img data-index$="[[index]]"
class$="[[getImageClassName(loading)]]"
is="cr-auto-img"
auto-src="[[getUrl()]]"
alt$="[[item.base.name]]"
load="lazy"
on-mouseenter="handleMouseEnter"
on-focus="handleFocus"
on-click="handleClick"
on-load="handleLoad">
<div class="emoji-image-container"
on-contextmenu="handleContextMenu"
on-mouseleave="handleMouseLeave"
style$="[[getStyles(item)]]">
<img data-index$="[[index]]"
class$="[[getImageClassName(loading)]]"
is="cr-auto-img"
auto-src="[[getUrl(item)]]"
alt$="[[item.base.name]]"
load="lazy"
on-mouseenter="handleMouseEnter"
on-focus="handleFocus"
on-click="handleClick"
on-load="handleLoad">
<template is="dom-if" if="[[showClearButton]]">
<button class="emoji-image-clear" on-click="handleClear">
Remove from recently used GIFs
</button>
</template>
</div>

@ -6,7 +6,8 @@ import {PolymerElement} from 'chrome://resources/polymer/v3_0/polymer/polymer_bu
import {VISUAL_CONTENT_WIDTH} from './constants.js';
import {getTemplate} from './emoji_image.html.js';
import {EmojiVariants} from './types.js';
import { createCustomEvent, EMOJI_CLEAR_RECENTS_CLICK } from './events.js';
import {CategoryEnum, EmojiVariants} from './types.js';
export class EmojiImageComponent extends PolymerElement {
static get is() {
@ -23,6 +24,9 @@ export class EmojiImageComponent extends PolymerElement {
item: Object,
showTooltip: Object,
emojiClick: Object,
clearable: {type: Boolean, value: false},
showClearButton: {type: Boolean, value: false},
};
}
@ -33,6 +37,9 @@ export class EmojiImageComponent extends PolymerElement {
showTooltip: (e: MouseEvent|FocusEvent) => void;
emojiClick: (e: MouseEvent) => void;
clearable: boolean;
showClearButton: boolean;
private handleMouseEnter(event: MouseEvent): void {
this.showTooltip(event);
}
@ -49,6 +56,32 @@ export class EmojiImageComponent extends PolymerElement {
this.loading = false;
}
private handleContextMenu(evt: Event): void {
if (this.clearable) {
evt.preventDefault();
evt.stopPropagation();
this.showClearButton = true;
}
}
private handleMouseLeave(): void {
if (this.showClearButton) {
this.showClearButton = false;
}
}
private handleClear(evt: Event): void {
evt.preventDefault();
evt.stopPropagation();
this.showClearButton = false;
this.dispatchEvent(createCustomEvent(
EMOJI_CLEAR_RECENTS_CLICK, {
category: CategoryEnum.GIF,
item: this.item,
},
));
}
private getImageClassName(loading: boolean) {
return loading ? 'emoji-image loading' : 'emoji-image';
}
@ -56,12 +89,12 @@ export class EmojiImageComponent extends PolymerElement {
/**
* Returns visual content preview url.
*/
private getUrl() {
return this.item.base.visualContent?.url.preview.url;
private getUrl(item: EmojiVariants) {
return item.base.visualContent?.url.preview.url;
}
private setHeight() {
const {visualContent} = this.item.base;
private getStyles(item: EmojiVariants) {
const {visualContent} = item.base;
if (visualContent === undefined) {
return;
@ -69,14 +102,8 @@ export class EmojiImageComponent extends PolymerElement {
const {height, width} = visualContent.previewSize;
const visualContentHeight = height / width * VISUAL_CONTENT_WIDTH;
this.updateStyles({
'--visual-content-height': `${visualContentHeight}px`,
});
}
override ready() {
super.ready();
this.setHeight();
return `--visual-content-height: ${visualContentHeight}px`;
}
}

@ -600,7 +600,8 @@ export class EmojiPicker extends PolymerElement {
private clearRecentEmoji(event: events.EmojiClearRecentClickEvent) {
const category = event.detail.category;
this.clearHistoryData(category);
const item = event.detail.item;
this.clearHistoryData(category, item);
afterNextRender(this, () => {
this.updateActiveGroup();
this.updateHistoryTabDisabledProperty();
@ -1099,14 +1100,19 @@ export class EmojiPicker extends PolymerElement {
}
/**
* Clears history items for a category.
* Clears history item(s) for a category.
*/
private clearHistoryData(category: CategoryEnum) {
private clearHistoryData(category: CategoryEnum, item?: EmojiVariants) {
if (this.incognito) {
return;
}
this.categoriesHistory[category]?.clearRecents();
if (item === undefined) {
this.categoriesHistory[category]?.clearRecents();
} else {
this.categoriesHistory[category]?.clearItem(category, item);
}
this.categoryHistoryUpdated(category, true, false);
}

@ -75,6 +75,20 @@ export class RecentlyUsedStore {
save(this.storeName, this.data);
}
clearItem(category: CategoryEnum, item: EmojiVariants) {
if (category === CategoryEnum.GIF) {
this.data.history = this.data.history.filter(
x =>
(x.base.visualContent &&
x.base.visualContent.id !== item.base.visualContent?.id));
} else {
this.data.history = this.data.history.filter(
x =>
(x.base.string && x.base.string !== item.base.string));
}
save(this.storeName, this.data);
}
/**
* Moves the given item to the front of the MRU list, inserting it if
* it did not previously exist.