mirror of
https://github.com/discourse/discourse.git
synced 2025-06-24 03:01:33 +08:00
FEATURE: favorites emojis will also show in composer autocomplete (#8011)
This commit is contained in:
@ -220,6 +220,7 @@ export default Ember.Component.extend({
|
|||||||
_mouseTrap: null,
|
_mouseTrap: null,
|
||||||
showLink: true,
|
showLink: true,
|
||||||
emojiPickerIsActive: false,
|
emojiPickerIsActive: false,
|
||||||
|
emojiStore: Ember.inject.service("emoji-store"),
|
||||||
|
|
||||||
@computed("placeholder")
|
@computed("placeholder")
|
||||||
placeholderTranslated(placeholder) {
|
placeholderTranslated(placeholder) {
|
||||||
@ -422,6 +423,7 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
transformComplete: v => {
|
transformComplete: v => {
|
||||||
if (v.code) {
|
if (v.code) {
|
||||||
|
this.emojiStore.track(v.code);
|
||||||
return `${v.code}:`;
|
return `${v.code}:`;
|
||||||
} else {
|
} else {
|
||||||
$editorInput.autocomplete({ cancel: true });
|
$editorInput.autocomplete({ cancel: true });
|
||||||
@ -458,7 +460,17 @@ export default Ember.Component.extend({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (term === "") {
|
if (term === "") {
|
||||||
return resolve(["slight_smile", "smile", "wink", "sunny", "blush"]);
|
if (this.emojiStore.favorites.length) {
|
||||||
|
return resolve(this.emojiStore.favorites.slice(0, 5));
|
||||||
|
} else {
|
||||||
|
return resolve([
|
||||||
|
"slight_smile",
|
||||||
|
"smile",
|
||||||
|
"wink",
|
||||||
|
"sunny",
|
||||||
|
"blush"
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (translations[full]) {
|
if (translations[full]) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { on, observes } from "ember-addons/ember-computed-decorators";
|
import { on, observes } from "ember-addons/ember-computed-decorators";
|
||||||
import { findRawTemplate } from "discourse/lib/raw-templates";
|
import { findRawTemplate } from "discourse/lib/raw-templates";
|
||||||
import { emojiUrlFor } from "discourse/lib/text";
|
import { emojiUrlFor } from "discourse/lib/text";
|
||||||
import KeyValueStore from "discourse/lib/key-value-store";
|
|
||||||
import {
|
import {
|
||||||
extendedEmojiList,
|
extendedEmojiList,
|
||||||
isSkinTonableEmoji,
|
isSkinTonableEmoji,
|
||||||
@ -10,21 +10,14 @@ import {
|
|||||||
import { safariHacksDisabled } from "discourse/lib/utilities";
|
import { safariHacksDisabled } from "discourse/lib/utilities";
|
||||||
const { run } = Ember;
|
const { run } = Ember;
|
||||||
|
|
||||||
const keyValueStore = new KeyValueStore("discourse_emojis_");
|
|
||||||
const EMOJI_USAGE = "emojiUsage";
|
|
||||||
const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity";
|
|
||||||
const PER_ROW = 11;
|
const PER_ROW = 11;
|
||||||
const customEmojis = _.keys(extendedEmojiList()).map(code => {
|
const customEmojis = _.keys(extendedEmojiList()).map(code => {
|
||||||
return { code, src: emojiUrlFor(code) };
|
return { code, src: emojiUrlFor(code) };
|
||||||
});
|
});
|
||||||
|
|
||||||
export function resetCache() {
|
|
||||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
|
|
||||||
keyValueStore.setObject({ key: EMOJI_SELECTED_DIVERSITY, value: 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
automaticPositioning: true,
|
automaticPositioning: true,
|
||||||
|
emojiStore: Ember.inject.service("emoji-store"),
|
||||||
|
|
||||||
close() {
|
close() {
|
||||||
this._unbindEvents();
|
this._unbindEvents();
|
||||||
@ -46,11 +39,10 @@ export default Ember.Component.extend({
|
|||||||
this.$results = this.$picker.find(".results");
|
this.$results = this.$picker.find(".results");
|
||||||
this.$list = this.$picker.find(".list");
|
this.$list = this.$picker.find(".list");
|
||||||
|
|
||||||
this.set(
|
this.setProperties({
|
||||||
"selectedDiversity",
|
selectedDiversity: this.emojiStore.diversity,
|
||||||
keyValueStore.getObject(EMOJI_SELECTED_DIVERSITY) || 1
|
recentEmojis: this.emojiStore.favorites
|
||||||
);
|
});
|
||||||
this.set("recentEmojis", keyValueStore.getObject(EMOJI_USAGE) || []);
|
|
||||||
|
|
||||||
run.scheduleOnce("afterRender", this, function() {
|
run.scheduleOnce("afterRender", this, function() {
|
||||||
this._bindEvents();
|
this._bindEvents();
|
||||||
@ -88,18 +80,7 @@ export default Ember.Component.extend({
|
|||||||
_setup() {
|
_setup() {
|
||||||
this.$picker = $(this.element.querySelector(".emoji-picker"));
|
this.$picker = $(this.element.querySelector(".emoji-picker"));
|
||||||
this.$modal = $(this.element.querySelector(".emoji-picker-modal"));
|
this.$modal = $(this.element.querySelector(".emoji-picker-modal"));
|
||||||
|
|
||||||
this.appEvents.on("emoji-picker:close", this, "_closeEmojiPicker");
|
this.appEvents.on("emoji-picker:close", this, "_closeEmojiPicker");
|
||||||
|
|
||||||
if (!keyValueStore.getObject(EMOJI_USAGE)) {
|
|
||||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
|
|
||||||
} else if (_.isPlainObject(keyValueStore.getObject(EMOJI_USAGE))) {
|
|
||||||
// handle legacy format
|
|
||||||
keyValueStore.setObject({
|
|
||||||
key: EMOJI_USAGE,
|
|
||||||
value: _.keys(keyValueStore.getObject(EMOJI_USAGE))
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@on("didUpdateAttrs")
|
@on("didUpdateAttrs")
|
||||||
@ -116,10 +97,7 @@ export default Ember.Component.extend({
|
|||||||
|
|
||||||
@observes("selectedDiversity")
|
@observes("selectedDiversity")
|
||||||
selectedDiversityChanged() {
|
selectedDiversityChanged() {
|
||||||
keyValueStore.setObject({
|
this.emojiStore.diversity = this.selectedDiversity;
|
||||||
key: EMOJI_SELECTED_DIVERSITY,
|
|
||||||
value: this.selectedDiversity
|
|
||||||
});
|
|
||||||
|
|
||||||
$.each(
|
$.each(
|
||||||
this.$list.find(".emoji[data-loaded='1'].diversity"),
|
this.$list.find(".emoji[data-loaded='1'].diversity"),
|
||||||
@ -326,7 +304,7 @@ export default Ember.Component.extend({
|
|||||||
".section[data-section='recent'] .clear-recent"
|
".section[data-section='recent'] .clear-recent"
|
||||||
);
|
);
|
||||||
$recent.on("click", () => {
|
$recent.on("click", () => {
|
||||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: [] });
|
this.emojiStore.favorites = [];
|
||||||
this.set("recentEmojis", []);
|
this.set("recentEmojis", []);
|
||||||
this._scrollTo(0);
|
this._scrollTo(0);
|
||||||
return false;
|
return false;
|
||||||
@ -608,12 +586,8 @@ export default Ember.Component.extend({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_trackEmojiUsage(code) {
|
_trackEmojiUsage(code) {
|
||||||
let recent = keyValueStore.getObject(EMOJI_USAGE) || [];
|
this.emojiStore.track(code);
|
||||||
recent = recent.filter(r => r !== code);
|
this.set("recentEmojis", this.emojiStore.favorites.slice(0, PER_ROW));
|
||||||
recent.unshift(code);
|
|
||||||
recent.length = Math.min(recent.length, PER_ROW);
|
|
||||||
keyValueStore.setObject({ key: EMOJI_USAGE, value: recent });
|
|
||||||
this.set("recentEmojis", recent);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_scrollTo(y) {
|
_scrollTo(y) {
|
||||||
|
48
app/assets/javascripts/discourse/services/emoji-store.js.es6
Normal file
48
app/assets/javascripts/discourse/services/emoji-store.js.es6
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import KeyValueStore from "discourse/lib/key-value-store";
|
||||||
|
|
||||||
|
const EMOJI_USAGE = "emojiUsage";
|
||||||
|
const EMOJI_SELECTED_DIVERSITY = "emojiSelectedDiversity";
|
||||||
|
const TRACKED_EMOJIS = 15;
|
||||||
|
const STORE_NAMESPACE = "discourse_emojis_";
|
||||||
|
|
||||||
|
export default Ember.Service.extend({
|
||||||
|
init() {
|
||||||
|
this._super(...arguments);
|
||||||
|
|
||||||
|
this.store = new KeyValueStore(STORE_NAMESPACE);
|
||||||
|
|
||||||
|
if (!this.store.getObject(EMOJI_USAGE)) {
|
||||||
|
this.favorites = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
get diversity() {
|
||||||
|
return this.store.getObject(EMOJI_SELECTED_DIVERSITY) || 1;
|
||||||
|
},
|
||||||
|
|
||||||
|
set diversity(value) {
|
||||||
|
this.store.setObject({ key: EMOJI_SELECTED_DIVERSITY, value: value || 1 });
|
||||||
|
},
|
||||||
|
|
||||||
|
get favorites() {
|
||||||
|
return this.store.getObject(EMOJI_USAGE) || [];
|
||||||
|
},
|
||||||
|
|
||||||
|
set favorites(value) {
|
||||||
|
this.store.setObject({ key: EMOJI_USAGE, value: value || [] });
|
||||||
|
},
|
||||||
|
|
||||||
|
track(code) {
|
||||||
|
const normalizedCode = code.replace(/(^:)|(:$)/g, "");
|
||||||
|
const recent = this.favorites.filter(r => r !== normalizedCode);
|
||||||
|
recent.unshift(normalizedCode);
|
||||||
|
recent.length = Math.min(recent.length, TRACKED_EMOJIS);
|
||||||
|
this.favorites = recent;
|
||||||
|
},
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
const store = new KeyValueStore(STORE_NAMESPACE);
|
||||||
|
store.setObject({ key: EMOJI_USAGE, value: [] });
|
||||||
|
store.setObject({ key: EMOJI_SELECTED_DIVERSITY, value: 1 });
|
||||||
|
}
|
||||||
|
});
|
@ -1,11 +1,11 @@
|
|||||||
import { acceptance } from "helpers/qunit-helpers";
|
import { acceptance } from "helpers/qunit-helpers";
|
||||||
import { IMAGE_VERSION as v } from "pretty-text/emoji/version";
|
import { IMAGE_VERSION as v } from "pretty-text/emoji/version";
|
||||||
import { resetCache } from "discourse/components/emoji-picker";
|
|
||||||
|
|
||||||
acceptance("EmojiPicker", {
|
acceptance("EmojiPicker", {
|
||||||
loggedIn: true,
|
loggedIn: true,
|
||||||
beforeEach() {
|
beforeEach() {
|
||||||
resetCache();
|
const store = Discourse.__container__.lookup("service:emojis-store");
|
||||||
|
store.reset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
33
test/javascripts/lib/emoji-store-test.js.es6
Normal file
33
test/javascripts/lib/emoji-store-test.js.es6
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
QUnit.module("lib:emoji-store", {
|
||||||
|
afterEach() {
|
||||||
|
const store = Discourse.__container__.lookup("service:emoji-store");
|
||||||
|
store.reset();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("defaults", assert => {
|
||||||
|
const store = Discourse.__container__.lookup("service:emoji-store");
|
||||||
|
assert.deepEqual(store.favorites, []);
|
||||||
|
assert.equal(store.diversity, 1);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("diversity", assert => {
|
||||||
|
const store = Discourse.__container__.lookup("service:emoji-store");
|
||||||
|
store.diversity = 2;
|
||||||
|
assert.equal(store.diversity, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("favorites", assert => {
|
||||||
|
const store = Discourse.__container__.lookup("service:emoji-store");
|
||||||
|
store.favorites = ["smile"];
|
||||||
|
assert.deepEqual(store.favorites, ["smile"]);
|
||||||
|
});
|
||||||
|
|
||||||
|
QUnit.test("track", assert => {
|
||||||
|
const store = Discourse.__container__.lookup("service:emoji-store");
|
||||||
|
store.track("woman:t4");
|
||||||
|
assert.deepEqual(store.favorites, ["woman:t4"]);
|
||||||
|
store.track("otter");
|
||||||
|
store.track(":otter:");
|
||||||
|
assert.deepEqual(store.favorites, ["otter", "woman:t4"]);
|
||||||
|
});
|
Reference in New Issue
Block a user