logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe
commit: 4827e4d972f8ee11e606693e24ae4ca21711c6b1
parent: 28f777cb8a94f7a28edb6f99a62a6b864c2aa8dc
Author: HJ <30-hj@users.noreply.git.pleroma.social>
Date:   Wed, 24 Jul 2019 19:35:52 +0000

Merge branch 'feature/add-sticker-picker' into 'develop'

Feature/add sticker picker

See merge request pleroma/pleroma-fe!885

Diffstat:

Msrc/boot/after_store.js32++++++++++++++++++++++++++++++++
Msrc/components/post_status_form/post_status_form.js21++++++++++++++++++++-
Msrc/components/post_status_form/post_status_form.vue24++++++++++++++++++++++--
Asrc/components/sticker_picker/sticker_picker.js52++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/components/sticker_picker/sticker_picker.vue62++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/components/tab_switcher/tab_switcher.js14+++++++++++++-
Msrc/components/tab_switcher/tab_switcher.scss6++++++
Msrc/i18n/en.json3+++
8 files changed, 210 insertions(+), 4 deletions(-)

diff --git a/src/boot/after_store.js b/src/boot/after_store.js @@ -148,6 +148,37 @@ const getInstancePanel = async ({ store }) => { } } +const getStickers = async ({ store }) => { + try { + const res = await window.fetch('/static/stickers.json') + if (res.ok) { + const values = await res.json() + const stickers = (await Promise.all( + Object.entries(values).map(async ([name, path]) => { + const resPack = await window.fetch(path + 'pack.json') + var meta = {} + if (resPack.ok) { + meta = await resPack.json() + } + return { + pack: name, + path, + meta + } + }) + )).sort((a, b) => { + return a.meta.title.localeCompare(b.meta.title) + }) + store.dispatch('setInstanceOption', { name: 'stickers', value: stickers }) + } else { + throw (res) + } + } catch (e) { + console.warn("Can't load stickers") + console.warn(e) + } +} + const getStaticEmoji = async ({ store }) => { try { const res = await window.fetch('/static/emoji.json') @@ -286,6 +317,7 @@ const afterStoreSetup = async ({ store, i18n }) => { setConfig({ store }), getTOS({ store }), getInstancePanel({ store }), + getStickers({ store }), getStaticEmoji({ store }), getCustomEmoji({ store }), getNodeInfo({ store }) diff --git a/src/components/post_status_form/post_status_form.js b/src/components/post_status_form/post_status_form.js @@ -3,6 +3,7 @@ import MediaUpload from '../media_upload/media_upload.vue' import ScopeSelector from '../scope_selector/scope_selector.vue' import EmojiInput from '../emoji-input/emoji-input.vue' import PollForm from '../poll/poll_form.vue' +import StickerPicker from '../sticker_picker/sticker_picker.vue' import fileTypeService from '../../services/file_type/file_type.service.js' import { reject, map, uniqBy } from 'lodash' import suggestor from '../emoji-input/suggestor.js' @@ -34,6 +35,7 @@ const PostStatusForm = { MediaUpload, EmojiInput, PollForm, + StickerPicker, ScopeSelector }, mounted () { @@ -82,7 +84,8 @@ const PostStatusForm = { contentType }, caret: 0, - pollFormVisible: false + pollFormVisible: false, + stickerPickerVisible: false } }, computed: { @@ -158,6 +161,12 @@ const PostStatusForm = { safeDMEnabled () { return this.$store.state.instance.safeDM }, + stickersAvailable () { + if (this.$store.state.instance.stickers) { + return this.$store.state.instance.stickers.length > 0 + } + return 0 + }, pollsAvailable () { return this.$store.state.instance.pollsAvailable && this.$store.state.instance.pollLimits.max_options >= 2 @@ -213,6 +222,7 @@ const PostStatusForm = { poll: {} } this.pollFormVisible = false + this.stickerPickerVisible = false this.$refs.mediaUpload.clearFile() this.clearPollForm() this.$emit('posted') @@ -229,6 +239,7 @@ const PostStatusForm = { addMediaFile (fileInfo) { this.newStatus.files.push(fileInfo) this.enableSubmit() + this.stickerPickerVisible = false }, removeMediaFile (fileInfo) { let index = this.newStatus.files.indexOf(fileInfo) @@ -288,6 +299,14 @@ const PostStatusForm = { changeVis (visibility) { this.newStatus.visibility = visibility }, + toggleStickerPicker () { + this.stickerPickerVisible = !this.stickerPickerVisible + }, + clearStickerPicker () { + if (this.$refs.stickerPicker) { + this.$refs.stickerPicker.clear() + } + }, togglePollForm () { this.pollFormVisible = !this.pollFormVisible }, diff --git a/src/components/post_status_form/post_status_form.vue b/src/components/post_status_form/post_status_form.vue @@ -158,6 +158,17 @@ @upload-failed="uploadFailed" /> <div + v-if="stickersAvailable" + class="sticker-icon" + > + <i + :title="$t('stickers.add_sticker')" + class="icon-picture btn btn-default" + :class="{ selected: stickerPickerVisible }" + @click="toggleStickerPicker" + /> + </div> + <div v-if="pollsAvailable" class="poll-icon" > @@ -169,7 +180,6 @@ /> </div> </div> - <button v-if="posting" disabled @@ -248,6 +258,11 @@ <label for="filesSensitive">{{ $t('post_status.attachments_sensitive') }}</label> </div> </form> + <sticker-picker + v-if="stickerPickerVisible" + ref="stickerPicker" + @uploaded="addMediaFile" + /> </div> </template> @@ -310,7 +325,7 @@ } } - .poll-icon { + .poll-icon, .sticker-icon { font-size: 26px; flex: 1; @@ -320,6 +335,11 @@ } } + .sticker-icon { + flex: 0; + min-width: 50px; + } + .icon-chart-bar { cursor: pointer; } diff --git a/src/components/sticker_picker/sticker_picker.js b/src/components/sticker_picker/sticker_picker.js @@ -0,0 +1,52 @@ +/* eslint-env browser */ +import statusPosterService from '../../services/status_poster/status_poster.service.js' +import TabSwitcher from '../tab_switcher/tab_switcher.js' + +const StickerPicker = { + components: [ + TabSwitcher + ], + data () { + return { + meta: { + stickers: [] + }, + path: '' + } + }, + computed: { + pack () { + return this.$store.state.instance.stickers || [] + } + }, + methods: { + clear () { + this.meta = { + stickers: [] + } + }, + pick (sticker, name) { + const store = this.$store + // TODO remove this workaround by finding a way to bypass reuploads + fetch(sticker) + .then((res) => { + res.blob().then((blob) => { + var file = new File([blob], name, { mimetype: 'image/png' }) + var formData = new FormData() + formData.append('file', file) + statusPosterService.uploadMedia({ store, formData }) + .then((fileData) => { + this.$emit('uploaded', fileData) + this.clear() + }, (error) => { + console.warn("Can't attach sticker") + console.warn(error) + this.$emit('upload-failed', 'default') + }) + }) + }) + } + } +} + +export default StickerPicker diff --git a/src/components/sticker_picker/sticker_picker.vue b/src/components/sticker_picker/sticker_picker.vue @@ -0,0 +1,62 @@ +<template> + <div + class="sticker-picker" + > + <div + class="sticker-picker-panel" + > + <tab-switcher + :render-only-focused="true" + > + <div + v-for="stickerpack in pack" + :key="stickerpack.path" + :image-tooltip="stickerpack.meta.title" + :image="stickerpack.path + stickerpack.meta.tabIcon" + class="sticker-picker-content" + > + <div + v-for="sticker in stickerpack.meta.stickers" + :key="sticker" + class="sticker" + @click="pick(stickerpack.path + sticker, stickerpack.meta.title)" + > + <img + :src="stickerpack.path + sticker" + > + </div> + </div> + </tab-switcher> + </div> + </div> +</template> + +<script src="./sticker_picker.js"></script> + +<style lang="scss"> +@import '../../_variables.scss'; + +.sticker-picker { + .sticker-picker-panel { + display: inline-block; + width: 100%; + .sticker-picker-content { + max-height: 300px; + overflow-y: scroll; + overflow-x: auto; + .sticker { + display: inline-block; + width: 20%; + height: 20%; + img { + width: 100%; + &:hover { + filter: drop-shadow(0 0 5px var(--link, $fallback--link)); + } + } + } + } + } +} + +</style> diff --git a/src/components/tab_switcher/tab_switcher.js b/src/components/tab_switcher/tab_switcher.js @@ -45,7 +45,19 @@ export default Vue.component('tab-switcher', { classesTab.push('active') classesWrapper.push('active') } - + if (slot.data.attrs.image) { + return ( + <div class={ classesWrapper.join(' ')}> + <button + disabled={slot.data.attrs.disabled} + onClick={this.activateTab(index)} + class={classesTab.join(' ')}> + <img src={slot.data.attrs.image} title={slot.data.attrs['image-tooltip']}/> + {slot.data.attrs.label ? '' : slot.data.attrs.label} + </button> + </div> + ) + } return ( <div class={ classesWrapper.join(' ')}> <button diff --git a/src/components/tab_switcher/tab_switcher.scss b/src/components/tab_switcher/tab_switcher.scss @@ -53,6 +53,12 @@ background: transparent; z-index: 5; } + + img { + max-height: 26px; + vertical-align: top; + margin-top: -5px; + } } &:not(.active) { diff --git a/src/i18n/en.json b/src/i18n/en.json @@ -106,6 +106,9 @@ "expired": "Poll ended {0} ago", "not_enough_options": "Too few unique options in poll" }, + "stickers": { + "add_sticker": "Add Sticker" + }, "interactions": { "favs_repeats": "Repeats and Favorites", "follows": "New follows",