pinafore/src/routes/_components/dialog/components/EmojiDialog.html

123 lines
3.6 KiB
HTML

<ModalDialog
{id}
{label}
{title}
background="var(--main-bg)"
>
<div class="emoji-container" {style} >
{#if loaded}
<emoji-mart props-json={emojiMartPropsJson} ></emoji-mart>
{:elseif error}
<div>Failed to load emoji picker: {error}</div>
{:else}
<div class="emoji-container-loading" >
<LoadingSpinner />
</div>
{/if}
</div>
</ModalDialog>
<style>
.emoji-container {
max-width: calc(100vw - 20px);
position: relative;
}
.emoji-container-loading {
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display: flex;
align-items: center;
justify-content: center;
}
:global(.emoji-mart-category .emoji-mart-emoji-custom span,
.emoji-mart-preview-emoji .emoji-mart-emoji-custom span) {
/* some custom emoji look repeated because they aren't tall enough */
background-repeat: no-repeat;
background-position: center center;
}
:global(.emoji-container .emoji-mart-emoji-native) {
/* remove if/when https://github.com/missive/emoji-mart/pull/256 is merged */
font-family: PinaforeEmoji, sans-serif;
}
</style>
<script>
import ModalDialog from './ModalDialog.html'
import { store } from '../../../_store/store'
import { insertEmoji } from '../../../_actions/emoji'
import { show } from '../helpers/showDialog'
import { close } from '../helpers/closeDialog'
import { oncreate as onCreateDialog } from '../helpers/onCreateDialog'
import { define } from 'remount/es6'
import LoadingSpinner from '../../../_components/LoadingSpinner.html'
import { on } from '../../../_utils/eventBus'
import { createEmojiMartPicker } from '../../../_react/createEmojiMartPicker'
export default {
async oncreate () {
onCreateDialog.call(this)
on('emoji-selected', this, emoji => this.onEmojiSelected(emoji))
try {
let Picker = await createEmojiMartPicker()
if (!customElements.get('emoji-mart')) {
define({ 'emoji-mart': Picker })
}
this.set({ loaded: true })
} catch (error) {
this.set({ error }) // should never happen, but you never know
}
},
components: {
ModalDialog,
LoadingSpinner
},
store: () => store,
data: () => ({
loading: true,
loaded: false,
error: void 0
}),
computed: {
// try to estimate size of emoji-mart based on mobile vs desktop
style: ({ $isSmallMobileSize }) => (`
min-width: ${$isSmallMobileSize ? 250 : 300}px;
min-height: ${$isSmallMobileSize ? 300 : 400}px;
`),
emojiMartPropsJson: ({ emojiMartProps }) => JSON.stringify(emojiMartProps),
emojiMartProps: ({ perLine, custom, showPreview }) => ({
perLine,
custom,
showPreview,
color: 'var(--nav-bg)',
emoji: 'sailboat',
title: 'Emoji'
}),
showPreview: ({ $isSmallMobileSize }) => !$isSmallMobileSize,
perLine: ({ $isSmallMobileSize }) => $isSmallMobileSize ? 7 : 9,
custom: ({ $currentCustomEmoji, $autoplayGifs }) => {
if (!$currentCustomEmoji) {
return []
}
return $currentCustomEmoji.filter(emoji => emoji.visible_in_picker).map(emoji => ({
name: emoji.shortcode,
short_names: [emoji.shortcode],
text: `:${emoji.shortcode}:`,
emoticons: [],
keywords: [emoji.shortcode],
imageUrl: $autoplayGifs ? emoji.url : emoji.static_url
}))
}
},
methods: {
show,
close,
onEmojiSelected (emoji) {
let { realm } = this.get()
insertEmoji(realm, emoji)
this.close()
}
}
}
</script>