diff options
| author | MeiMei <30769358+mei23@users.noreply.github.com> | 2019-10-21 00:43:39 +0900 |
|---|---|---|
| committer | syuilo <Syuilotan@yahoo.co.jp> | 2019-10-21 00:43:39 +0900 |
| commit | 4c6c06c80afd3e2309b305f40c2e67e48863bf31 (patch) | |
| tree | d9d24139b126867a3ff1f4e893175aea05ebd01e /src/client | |
| parent | Add ssl to elasticsearch config settings (#5527) (diff) | |
| download | sharkey-4c6c06c80afd3e2309b305f40c2e67e48863bf31.tar.gz sharkey-4c6c06c80afd3e2309b305f40c2e67e48863bf31.tar.bz2 sharkey-4c6c06c80afd3e2309b305f40c2e67e48863bf31.zip | |
Improve emoji-picker (#5515)
* Improve emoji-picker
* remove unimplanted translation
* カテゴリのサジェスト
* use unique
Diffstat (limited to 'src/client')
| -rw-r--r-- | src/client/app/admin/views/emoji.vue | 19 | ||||
| -rw-r--r-- | src/client/app/common/views/components/emoji-picker.vue | 112 | ||||
| -rw-r--r-- | src/client/app/store.ts | 2 |
3 files changed, 103 insertions, 30 deletions
diff --git a/src/client/app/admin/views/emoji.vue b/src/client/app/admin/views/emoji.vue index 9f2f3a0c88..2925fcab57 100644 --- a/src/client/app/admin/views/emoji.vue +++ b/src/client/app/admin/views/emoji.vue @@ -8,6 +8,9 @@ <span>{{ $t('add-emoji.name') }}</span> <template #desc>{{ $t('add-emoji.name-desc') }}</template> </ui-input> + <ui-input v-model="category" :datalist="categoryList"> + <span>{{ $t('add-emoji.category') }}</span> + </ui-input> <ui-input v-model="aliases"> <span>{{ $t('add-emoji.aliases') }}</span> <template #desc>{{ $t('add-emoji.aliases-desc') }}</template> @@ -24,7 +27,7 @@ <ui-card> <template #title><fa :icon="faGrin"/> {{ $t('emojis.title') }}</template> - <section v-for="emoji in emojis" class="oryfrbft"> + <section v-for="emoji in emojis" :key="emoji.name" class="oryfrbft"> <div> <img :src="emoji.url" :alt="emoji.name" style="width: 64px;"/> </div> @@ -33,6 +36,9 @@ <ui-input v-model="emoji.name"> <span>{{ $t('add-emoji.name') }}</span> </ui-input> + <ui-input v-model="emoji.category" :datalist="categoryList"> + <span>{{ $t('add-emoji.category') }}</span> + </ui-input> <ui-input v-model="emoji.aliases"> <span>{{ $t('add-emoji.aliases') }}</span> </ui-input> @@ -55,12 +61,14 @@ import Vue from 'vue'; import i18n from '../../i18n'; import { faGrin } from '@fortawesome/free-regular-svg-icons'; +import { unique } from '../../../../prelude/array'; export default Vue.extend({ i18n: i18n('admin/views/emoji.vue'), data() { return { name: '', + category: '', url: '', aliases: '', emojis: [], @@ -72,10 +80,17 @@ export default Vue.extend({ this.fetchEmojis(); }, + computed: { + categoryList() { + return unique(this.emojis.map((x: any) => x.category || '').filter((x: string) => x !== '')); + } + }, + methods: { add() { this.$root.api('admin/emoji/add', { name: this.name, + category: this.category, url: this.url, aliases: this.aliases.split(' ').filter(x => x.length > 0) }).then(() => { @@ -94,7 +109,6 @@ export default Vue.extend({ fetchEmojis() { this.$root.api('admin/emoji/list').then(emojis => { - emojis.reverse(); for (const e of emojis) { e.aliases = (e.aliases || []).join(' '); } @@ -106,6 +120,7 @@ export default Vue.extend({ this.$root.api('admin/emoji/update', { id: emoji.id, name: emoji.name, + category: emoji.category, url: emoji.url, aliases: emoji.aliases.split(' ').filter(x => x.length > 0) }).then(() => { diff --git a/src/client/app/common/views/components/emoji-picker.vue b/src/client/app/common/views/components/emoji-picker.vue index 88761ae933..abae69e28a 100644 --- a/src/client/app/common/views/components/emoji-picker.vue +++ b/src/client/app/common/views/components/emoji-picker.vue @@ -11,25 +11,46 @@ </button> </header> <div class="emojis"> - <header><fa :icon="categories.find(x => x.isActive).icon" fixed-width/> {{ categories.find(x => x.isActive).text }}</header> - <div v-if="categories.find(x => x.isActive).name"> - <button v-for="emoji in emojilist.filter(e => e.category === categories.find(x => x.isActive).name)" - :title="emoji.name" - @click="chosen(emoji.char)" - :key="emoji.name" - > - <mk-emoji :emoji="emoji.char"/> - </button> - </div> - <div v-else> - <button v-for="emoji in customEmojis" - :title="emoji.name" - @click="chosen(`:${emoji.name}:`)" - :key="emoji.name" - > - <img :src="emoji.url" :alt="emoji.name"/> - </button> - </div> + <template v-if="categories[0].isActive"> + <header class="category"><fa :icon="faHistory" fixed-width/> {{ $t('recent-emoji') }}</header> + <div class="list"> + <button v-for="(emoji, i) in ($store.state.device.recentEmojis || [])" + :title="emoji.name" + @click="chosen(emoji)" + :key="i" + > + <mk-emoji v-if="emoji.char != null" :emoji="emoji.char"/> + <img v-else :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/> + </button> + </div> + </template> + + <header class="category"><fa :icon="categories.find(x => x.isActive).icon" fixed-width/> {{ categories.find(x => x.isActive).text }}</header> + <template v-if="categories.find(x => x.isActive).name"> + <div class="list"> + <button v-for="emoji in emojilist.filter(e => e.category === categories.find(x => x.isActive).name)" + :title="emoji.name" + @click="chosen(emoji)" + :key="emoji.name" + > + <mk-emoji :emoji="emoji.char"/> + </button> + </div> + </template> + <template v-else> + <div v-for="(key, i) in Object.keys(customEmojis)" :key="i"> + <header class="sub">{{ key || $t('no-category') }}</header> + <div class="list"> + <button v-for="emoji in customEmojis[key]" + :title="emoji.name" + @click="chosen(emoji)" + :key="emoji.name" + > + <img :src="$store.state.device.disableShowingAnimatedImages ? getStaticImageUrl(emoji.url) : emoji.url"/> + </button> + </div> + </div> + </template> </div> </div> </template> @@ -38,8 +59,10 @@ import Vue from 'vue'; import i18n from '../../../i18n'; import { emojilist } from '../../../../../misc/emojilist'; -import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice } from '@fortawesome/free-solid-svg-icons'; +import { getStaticImageUrl } from '../../../common/scripts/get-static-image-url'; +import { faAsterisk, faLeaf, faUtensils, faFutbol, faCity, faDice, faGlobe, faHistory } from '@fortawesome/free-solid-svg-icons'; import { faHeart, faFlag } from '@fortawesome/free-regular-svg-icons'; +import { groupByX } from '../../../../../prelude/array'; export default Vue.extend({ i18n: i18n('common/views/components/emoji-picker.vue'), @@ -47,7 +70,9 @@ export default Vue.extend({ data() { return { emojilist, - customEmojis: [], + getStaticImageUrl, + customEmojis: {}, + faGlobe, faHistory, categories: [{ text: this.$t('custom-emoji'), icon: faAsterisk, @@ -97,18 +122,43 @@ export default Vue.extend({ }, created() { - this.customEmojis = (this.$root.getMetaSync() || { emojis: [] }).emojis || []; + let local = (this.$root.getMetaSync() || { emojis: [] }).emojis || []; + local = groupByX(local, (x: any) => x.category || ''); + this.customEmojis = local; + + if (this.$store.state.device.activeEmojiCategoryName) { + this.goCategory(this.$store.state.device.activeEmojiCategoryName); + } }, methods: { - go(category) { + go(category: any) { + this.goCategory(category.name); + }, + + goCategory(name: string) { + let matched = false; for (const c of this.categories) { - c.isActive = c.name === category.name; + c.isActive = c.name === name; + if (c.isActive) { + matched = true; + this.$store.commit('device/set', { key: 'activeEmojiCategoryName', value: c.name }); + } + } + if (!matched) { + this.categories[0].isActive = true; } }, - chosen(emoji) { - this.$emit('chosen', emoji); + chosen(emoji: any) { + const getKey = (emoji: any) => emoji.char || `:${emoji.name}:`; + + let recents = this.$store.state.device.recentEmojis || []; + recents = recents.filter((e: any) => getKey(e) !== getKey(emoji)); + recents.unshift(emoji) + this.$store.commit('device/set', { key: 'recentEmojis', value: recents.splice(0, 16) }); + + this.$emit('chosen', getKey(emoji)); } } }); @@ -142,7 +192,7 @@ export default Vue.extend({ overflow-y auto overflow-x hidden - > header + > header.category position sticky top 0 left 0 @@ -152,7 +202,12 @@ export default Vue.extend({ color var(--text) font-size 12px - > div + >>> header.sub + padding 4px 8px + color var(--text) + font-size 12px + + >>> div.list display grid grid-template-columns 1fr 1fr 1fr 1fr 1fr 1fr 1fr 1fr gap 4px @@ -180,6 +235,7 @@ export default Vue.extend({ left 0 width 100% height 100% + object-fit contain font-size 28px transition transform 0.2s ease pointer-events none diff --git a/src/client/app/store.ts b/src/client/app/store.ts index f4ec9e501a..fd3aceb728 100644 --- a/src/client/app/store.ts +++ b/src/client/app/store.ts @@ -79,6 +79,8 @@ const defaultDeviceSettings = { enableMobileQuickNotificationView: false, roomGraphicsQuality: 'medium', roomUseOrthographicCamera: true, + activeEmojiCategoryName: undefined, + recentEmojis: [], }; export default (os: MiOS) => new Vuex.Store({ |