Skip to content

Commit

Permalink
enh(NcEmojiPicker): Always show a skin tone selector
Browse files Browse the repository at this point in the history
Also save the selected skin tone for future uses and communicate it with all other NcEmojiPicker instances

Signed-off-by: Ferdinand Thiessen <opensource@fthiessen.de>
  • Loading branch information
susnux committed Jan 23, 2024
1 parent 5a2bc22 commit b2527dd
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 26 deletions.
21 changes: 21 additions & 0 deletions l10n/messages.pot
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,9 @@ msgstr ""
msgid "Custom"
msgstr ""

msgid "Dark skin tone"
msgstr ""

#. TRANSLATORS: A color name for RGB(136, 85, 168)
msgid "Deluge"
msgstr ""
Expand Down Expand Up @@ -164,13 +167,25 @@ msgstr ""
msgid "Keyboard navigation help"
msgstr ""

msgid "Light skin tone"
msgstr ""

msgid "Load more \"{options}\""
msgstr ""

#. TRANSLATORS: A color name for RGB(45, 115, 190)
msgid "Mariner"
msgstr ""

msgid "Medium dark skin tone"
msgstr ""

msgid "Medium light skin tone"
msgstr ""

msgid "Medium skin tone"
msgstr ""

msgid "Message limit of {count} characters reached"
msgstr ""

Expand All @@ -180,6 +195,9 @@ msgstr ""
msgid "More options"
msgstr ""

msgid "Neutral skin color"
msgstr ""

msgid "Next"
msgstr ""

Expand Down Expand Up @@ -316,6 +334,9 @@ msgstr ""
msgid "Show password"
msgstr ""

msgid "Skin tone"
msgstr ""

msgid "Skip to app navigation"
msgstr ""

Expand Down
118 changes: 92 additions & 26 deletions src/components/NcEmojiPicker/NcEmojiPicker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -145,23 +145,37 @@ This component allows the user to pick an emoji.
:per-line="8"
:picker-styles="{ width: '320px' }"
:show-preview="showPreview"
:skin="currentSkinTone"
:show-skin-tones="false"
:title="previewFallbackName"
role="dialog"
:aria-label="t('Emoji picker')"
v-bind="$attrs"
@select="select">
<template #searchTemplate="slotProps">
<NcTextField ref="search"
class="search"
:value.sync="search"
:label="t('Search')"
:label-visible="true"
:placeholder="i18n.search"
trailing-button-icon="close"
:trailing-button-label="t('Clear search')"
:show-trailing-button="search !== ''"
@trailing-button-click="clearSearch(); slotProps.onSearch(search);"
@update:value="slotProps.onSearch(search)" />
<div class="search__wrapper">
<NcTextField ref="search"
class="search"
:value.sync="search"
:label="t('Search')"
:label-visible="true"
:placeholder="i18n.search"
trailing-button-icon="close"
:trailing-button-label="t('Clear search')"
:show-trailing-button="search !== ''"
@trailing-button-click="clearSearch(); slotProps.onSearch(search);"
@update:value="slotProps.onSearch(search)" />
<NcColorPicker palette-only
:palette="skinTonePalette"
:value="currentColor.color"
@update:value="onChangeSkinTone">
<NcButton :aria-label="t('Skin tone')" type="tertiary-no-background">
<template #icon>
<IconCircle :style="{ color: currentColor.color }" :title="currentColor.name" :size="20" />
</template>
</NcButton>
</NcColorPicker>
</div>
</template>
<template v-if="allowUnselect && selectedEmoji" #customCategory>
<div class="emoji-mart-category-label">
Expand All @@ -187,17 +201,24 @@ This component allows the user to pick an emoji.
</template>

<script>
import NcPopover from '../NcPopover/index.js'
import NcTextField from '../NcTextField/index.js'
import { getBuilder } from '@nextcloud/browser-storage'
import { Picker, Emoji, EmojiIndex } from 'emoji-mart-vue-fast'
import { t } from '../../l10n.js'
import { Color } from '../../utils/GenColors.js'
import { Picker, Emoji, EmojiIndex } from 'emoji-mart-vue-fast'
import data from 'emoji-mart-vue-fast/data/all.json'
import IconCircle from 'vue-material-design-icons/Circle.vue'
import NcButton from '../NcButton/index.js'
import NcColorPicker from '../NcColorPicker/NcColorPicker.vue'
import NcPopover from '../NcPopover/index.js'
import NcTextField from '../NcTextField/index.js'
// Shared emoji index for all NcEmojiPicker instances
// Shared emoji index and skinTone for all NcEmojiPicker instances
// Will be initialized on the first NcEmojiPicker creating
let emojiIndex
const storage = getBuilder('nextcloud-vue').persist(true).build()
const i18n = {
search: t('Search emoji'),
notfound: t('No emoji found'),
Expand All @@ -217,14 +238,28 @@ const i18n = {
},
}
const skinTonePalette = [
new Color(255, 222, 52, t('Neutral skin color')),
new Color(228, 205, 166, t('Light skin tone')),
new Color(250, 221, 192, t('Medium light skin tone')),
new Color(174, 129, 87, t('Medium skin tone')),
new Color(158, 113, 88, t('Medium dark skin tone')),
new Color(96, 79, 69, t('Dark skin tone')),
]
export default {
name: 'NcEmojiPicker',
components: {
Emoji,
IconCircle,
NcButton,
NcColorPicker,
NcPopover,
NcTextField,
Emoji,
Picker,
},
props: {
/**
* The emoji-set
Expand Down Expand Up @@ -299,21 +334,36 @@ export default {
return {
// Non-reactive constants
emojiIndex,
skinTonePalette,
i18n,
}
},
data() {
// sanizized value (skin tone is allowed from 1 to 6)
const currentSkinTone = Math.min(Math.max(Number.parseInt(storage.getItem('NcEmojiPicker::currentSkinTone') ?? '1'), 1), 6)
return {
/**
* The current active color from the skin tone palette
*/
currentColor: skinTonePalette[currentSkinTone - 1],
/**
* The current active skin tone
* @type {1|2|3|4|5|6}
*/
currentSkinTone,
search: '',
open: false,
}
},
computed: {
native() {
return this.activeSet === 'native'
},
},
methods: {
t,
Expand All @@ -325,6 +375,19 @@ export default {
}
},
/**
* Update the current skin tone by the result of the color picker
* @param {string} color Color set
*/
onChangeSkinTone(color) {
const index = this.skinTonePalette.findIndex((tone) => tone.color.toLowerCase() === color.toLowerCase())
if (index > -1) {
this.currentSkinTone = index + 1
this.currentColor = this.skinTonePalette[index]
storage.setItem('NcEmojiPicker::currentSkinTone', `${this.currentSkinTone}`)
}
},
select(emojiObject) {
/**
* Emits a string containing the emoji e.g. '👩🏿‍💻'
Expand Down Expand Up @@ -491,20 +554,23 @@ export default {
}
}
.search {
padding: 4px 8px;
}
</style>
<style scoped>
.row-selected span {
vertical-align: middle;
<style scoped lang="scss">
.search {
&__wrapper {
display: flex;
flex-direction: row;
gap: 4px; // for focus-visible outlines
align-items: end;
padding: 4px 8px;
}
}
.row-selected button {
vertical-align: middle;
.row-selected {
button, span {
vertical-align: middle;
}
}
.emoji-delete {
Expand Down
1 change: 1 addition & 0 deletions tests/setup.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import OC from './OC.js'
import 'regenerator-runtime/runtime'

global.OC = OC
global.appName = 'nextcloud-vue'

global.PRODUCTION = false
global.SCOPE_VERSION = 1
Expand Down

0 comments on commit b2527dd

Please sign in to comment.