mirror of
https://github.com/discourse/discourse.git
synced 2024-11-29 05:16:30 +08:00
FIX: allows custom groups updates to be reflected without recompilation (#9421)
This commit is contained in:
parent
f07c4a781c
commit
d9db0e6691
|
@ -1,4 +1,5 @@
|
|||
import { inject as service } from "@ember/service";
|
||||
import { schedule } from "@ember/runloop";
|
||||
import Component from "@ember/component";
|
||||
import { on, observes } from "discourse-common/utils/decorators";
|
||||
import { findRawTemplate } from "discourse/lib/raw-templates";
|
||||
|
@ -16,23 +17,16 @@ const { run } = Ember;
|
|||
const PER_ROW = 11;
|
||||
function customEmojis() {
|
||||
const list = extendedEmojiList();
|
||||
const emojis = Object.keys(list)
|
||||
.map(code => {
|
||||
const { group } = list[code];
|
||||
return {
|
||||
const groups = [];
|
||||
Object.keys(list).forEach(code => {
|
||||
const emoji = list[code];
|
||||
groups[emoji.group] = groups[emoji.group] || [];
|
||||
groups[emoji.group].push({
|
||||
code,
|
||||
src: emojiUrlFor(code),
|
||||
group,
|
||||
key: `emoji_picker.${group || "default"}`
|
||||
};
|
||||
})
|
||||
.reduce((acc, curr) => {
|
||||
if (!acc[curr.group]) acc[curr.group] = [];
|
||||
acc[curr.group].push(curr);
|
||||
return acc;
|
||||
}, {});
|
||||
|
||||
return Object.values(emojis);
|
||||
src: emojiUrlFor(code)
|
||||
});
|
||||
});
|
||||
return groups;
|
||||
}
|
||||
|
||||
export default Component.extend({
|
||||
|
@ -42,9 +36,8 @@ export default Component.extend({
|
|||
close() {
|
||||
this._unbindEvents();
|
||||
|
||||
this.$picker
|
||||
.css({ width: "", left: "", bottom: "", display: "none" })
|
||||
.empty();
|
||||
this.$picker &&
|
||||
this.$picker.css({ width: "", left: "", bottom: "", display: "none" });
|
||||
|
||||
this.$modal.removeClass("fadeIn");
|
||||
|
||||
|
@ -52,11 +45,6 @@ export default Component.extend({
|
|||
},
|
||||
|
||||
show() {
|
||||
const template = findRawTemplate("emoji-picker")({
|
||||
customEmojis: customEmojis()
|
||||
});
|
||||
this.$picker.html(template);
|
||||
|
||||
this.$filter = this.$picker.find(".filter");
|
||||
this.$results = this.$picker.find(".results");
|
||||
this.$list = this.$picker.find(".list");
|
||||
|
@ -84,6 +72,7 @@ export default Component.extend({
|
|||
|
||||
@on("init")
|
||||
_setInitialValues() {
|
||||
this.set("customEmojis", customEmojis());
|
||||
this._checkTimeout = null;
|
||||
this.scrollPosition = 0;
|
||||
this.$visibleSections = [];
|
||||
|
@ -100,14 +89,21 @@ export default Component.extend({
|
|||
|
||||
@on("didInsertElement")
|
||||
_setup() {
|
||||
this.$picker = $(this.element.querySelector(".emoji-picker"));
|
||||
this.$modal = $(this.element.querySelector(".emoji-picker-modal"));
|
||||
this.appEvents.on("emoji-picker:close", this, "_closeEmojiPicker");
|
||||
},
|
||||
|
||||
@on("didUpdateAttrs")
|
||||
_setState() {
|
||||
schedule("afterRender", () => {
|
||||
if (!this.element) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$picker = $(this.element.querySelector(".emoji-picker"));
|
||||
this.$modal = $(this.element.querySelector(".emoji-picker-modal"));
|
||||
|
||||
this.active ? this.show() : this.close();
|
||||
});
|
||||
},
|
||||
|
||||
@observes("filter")
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
<div class="emoji-picker"></div>
|
||||
<div class="emoji-picker-modal"></div>
|
|
@ -0,0 +1,88 @@
|
|||
<div class="emoji-picker">
|
||||
{{#if active}}
|
||||
<div class='categories-column'>
|
||||
<div class='category-icon'>
|
||||
<button type="button" class="emoji" tabindex="-1" title="{{i18n 'emoji_picker.recent'}}" data-section="recent" data-tabicon="star"></button>
|
||||
</div>
|
||||
|
||||
<% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %>
|
||||
<div class='category-icon'>
|
||||
<button type="button" class="emoji" tabindex="-1" data-tabicon="<%= group["tabicon"] %>" data-section="<%= group["name"] %>" title="{{i18n '<%= "emoji_picker.#{group["name"]}" %>'}}"></button>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
{{#each-in customEmojis as |group emojis|}}
|
||||
<div class='category-icon'>
|
||||
<button data-tabicon={{emojis.firstObject.code}} type="button" class="emoji" tabindex="-1" data-section="custom-{{group}}" title="{{i18n (concat 'emoji_picker.' group)}}"></button>
|
||||
</div>
|
||||
{{/each-in}}
|
||||
</div>
|
||||
|
||||
<div class='main-column'>
|
||||
<div class='filter'>
|
||||
{{d-icon 'search'}}
|
||||
<input type='text' name="filter" placeholder="{{i18n 'emoji_picker.filter_placeholder'}}" autocomplete="discourse"/>
|
||||
<button class='clear-filter'>
|
||||
{{d-icon 'times'}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class='results'></div>
|
||||
|
||||
<div class='list'>
|
||||
<div class='section' data-section='recent'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.recent'}}</span>
|
||||
<a href='#' class='clear-recent'>{{d-icon "trash-alt"}}</a>
|
||||
</div>
|
||||
<div class='section-group'></div>
|
||||
</div>
|
||||
|
||||
<% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %>
|
||||
<div class='section' data-section='<%= group["name"] %>'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.<%= group["name"] %>'}}</span>
|
||||
</div>
|
||||
<div class='section-group'>
|
||||
<% group["icons"].each do |icon| %>
|
||||
<button type="button" class="emoji <%= "diversity" if icon["diversity"] %>" tabindex="-1" title="<%= icon['name']%>"></button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
{{#each-in customEmojis as |group emojis|}}
|
||||
<div class='section' data-section='custom-{{group}}'>
|
||||
<div class='section-header'>
|
||||
<span class="title">
|
||||
{{i18n (concat 'emoji_picker.' group)}}
|
||||
</span>
|
||||
</div>
|
||||
{{#if emojis.length}}
|
||||
<div class='section-group'>
|
||||
{{#each emojis as |emoji|}}
|
||||
<button type="button" class="emoji" tabindex="-1" title=":{{emoji.code}}:">
|
||||
<img loading="lazy" class="emoji" src="{{emoji.src}}">
|
||||
</button>
|
||||
{{/each}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/each-in}}
|
||||
</div>
|
||||
|
||||
<div class='footer'>
|
||||
<div class='info'></div>
|
||||
<div class='diversity-picker'>
|
||||
<% ['default', 'light', 'medium-light', 'medium', 'medium-dark', 'dark'].each.with_index do |diversity, index| %>
|
||||
<a href='#' title="{{i18n 'emoji_picker.<%= diversity.gsub('-', '_') %>_tone'}}" class='diversity-scale <%= diversity %>' data-level="<%= index + 1 %>">
|
||||
{{d-icon "check"}}
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<div class="emoji-picker-modal"></div>
|
|
@ -1,81 +0,0 @@
|
|||
<div class='categories-column'>
|
||||
<div class='category-icon'>
|
||||
<button type="button" class="emoji" tabindex="-1" title="{{i18n 'emoji_picker.recent'}}" data-section="recent" data-tabicon="star"></button>
|
||||
</div>
|
||||
|
||||
<% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %>
|
||||
<div class='category-icon'>
|
||||
<button type="button" class="emoji" tabindex="-1" data-tabicon="<%= group["tabicon"] %>" data-section="<%= group["name"] %>" title="{{i18n '<%= "emoji_picker.#{group["name"]}" %>'}}"></button>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<% Emoji.custom.group_by { |emoji| emoji.group }.each do |group, emojis| %>
|
||||
<% if emojis.present? %>
|
||||
<div class='category-icon'>
|
||||
<button data-tabicon="<%= emojis.first.name %>" type="button" class="emoji" tabindex="-1" data-section="custom-<%= group %>" title="{{i18n 'emoji_picker.<%= group %>'}}"></button>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<div class='main-column'>
|
||||
<div class='filter'>
|
||||
{{d-icon 'search'}}
|
||||
<input type='text' name="filter" placeholder="{{i18n 'emoji_picker.filter_placeholder'}}" autocomplete="discourse"/>
|
||||
<button class='clear-filter'>
|
||||
{{d-icon 'times'}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class='results'></div>
|
||||
|
||||
<div class='list'>
|
||||
<div class='section' data-section='recent'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.recent'}}</span>
|
||||
<a href='#' class='clear-recent'>{{d-icon "trash-alt"}}</a>
|
||||
</div>
|
||||
<div class='section-group'></div>
|
||||
</div>
|
||||
|
||||
<% JSON.parse(File.read("lib/emoji/groups.json")).each.with_index do |group, group_index| %>
|
||||
<div class='section' data-section='<%= group["name"] %>'>
|
||||
<div class='section-header'>
|
||||
<span class="title">{{i18n 'emoji_picker.<%= group["name"] %>'}}</span>
|
||||
</div>
|
||||
<div class='section-group'>
|
||||
<% group["icons"].each do |icon| %>
|
||||
<button type="button" class="emoji <%= "diversity" if icon["diversity"] %>" tabindex="-1" title="<%= icon['name']%>"></button>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
{{#each customEmojis as |emojis|}}
|
||||
{{#if emojis.length}}
|
||||
<div class='section' data-section='custom-{{emojis.firstObject.group}}'>
|
||||
<div class='section-header'>
|
||||
<span class="title">
|
||||
{{i18n emojis.firstObject.key}}
|
||||
</span>
|
||||
</div>
|
||||
<div class='section-group'>
|
||||
{{#each emojis as |emoji|}}
|
||||
<button style="background-url: url("{{emoji.src}}")" type="button" class="emoji" tabindex="-1" title="{{emoji.code}}"></button>
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class='footer'>
|
||||
<div class='info'></div>
|
||||
<div class='diversity-picker'>
|
||||
<% ['default', 'light', 'medium-light', 'medium', 'medium-dark', 'dark'].each.with_index do |diversity, index| %>
|
||||
<a href='#' title="{{i18n 'emoji_picker.<%= diversity.gsub('-', '_') %>_tone'}}" class='diversity-scale <%= diversity %>' data-level="<%= index + 1 %>">
|
||||
{{d-icon "check"}}
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -35,6 +35,13 @@ sup img.emoji {
|
|||
color: $primary;
|
||||
background-color: $secondary;
|
||||
border: 1px solid $primary-low;
|
||||
|
||||
img.emoji {
|
||||
// custom emojis might import images of various sizes
|
||||
// we don't want the picker to be difformed
|
||||
width: 20px !important;
|
||||
height: 20px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.emoji-picker .categories-column {
|
||||
|
|
|
@ -22,7 +22,7 @@ QUnit.test("emoji picker can be opened/closed", async assert => {
|
|||
find(".emoji-picker")
|
||||
.html()
|
||||
.trim(),
|
||||
"",
|
||||
"<!---->",
|
||||
"it opens the picker"
|
||||
);
|
||||
|
||||
|
@ -31,7 +31,7 @@ QUnit.test("emoji picker can be opened/closed", async assert => {
|
|||
find(".emoji-picker")
|
||||
.html()
|
||||
.trim(),
|
||||
"",
|
||||
"<!---->",
|
||||
"it closes the picker"
|
||||
);
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user