logo

pleroma-fe

My custom branche(s) on git.pleroma.social/pleroma/pleroma-fe git clone https://hacktivis.me/git/pleroma-fe.git
commit: 8a030d935bda6fdf91015d6001d985919b022394
parent aa4983835587e20a7ad0ce45e7c706a35d045774
Author: Ekaterina Vaartis <vaartis@kotobank.ch>
Date:   Fri, 19 Jan 2024 23:16:21 +0300

Separate emoji editing and upload into a separate component

Handle all state in that component

Diffstat:

Msrc/components/settings_modal/admin_tabs/emoji_tab.js108+++++++++++--------------------------------------------------------------------
Msrc/components/settings_modal/admin_tabs/emoji_tab.scss11-----------
Msrc/components/settings_modal/admin_tabs/emoji_tab.vue160++++++++++++++++---------------------------------------------------------------
Asrc/components/settings_modal/helpers/emoji_editing_popover.vue207+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 253 insertions(+), 233 deletions(-)

diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.js b/src/components/settings_modal/admin_tabs/emoji_tab.js @@ -7,8 +7,7 @@ import Select from 'components/select/select.vue' import Popover from 'components/popover/popover.vue' import ConfirmModal from 'components/confirm_modal/confirm_modal.vue' import ModifiedIndicator from '../helpers/modified_indicator.vue' - -const newEmojiUploadBase = { shortcode: '', file: '', upload: [] } +import EmojiEditingPopover from '../helpers/emoji_editing_popover.vue' const EmojiTab = { components: { @@ -19,24 +18,31 @@ const EmojiTab = { Select, Popover, ConfirmModal, - ModifiedIndicator + ModifiedIndicator, + EmojiEditingPopover }, data () { return { knownLocalPacks: { }, knownRemotePacks: { }, - editedParts: { }, editedMetadata: { }, packName: '', newPackName: '', deleteModalVisible: false, - newEmojiUpload: clone(newEmojiUploadBase), remotePackInstance: '', remotePackDownloadAs: '' } }, + provide () { + return { + // Functions + emojiAddr: this.emojiAddr, + displayError: this.displayError + } + }, + computed: { pack () { return this.packName !== '' ? this.knownPacks[this.packName] : undefined @@ -58,11 +64,6 @@ const EmojiTab = { } return result - }, - newEmojiUploadPreview () { - if (this.newEmojiUpload.upload.length > 0) { - return URL.createObjectURL(this.newEmojiUpload.upload[0]) - } } }, @@ -82,27 +83,6 @@ const EmojiTab = { } }, - uploadEmoji () { - this.$refs.addEmojiPopover.hidePopover() - - this.$store.state.api.backendInteractor.addNewEmojiFile({ - packName: this.packName, - file: this.newEmojiUpload.upload[0], - shortcode: this.newEmojiUpload.shortcode, - filename: this.newEmojiUpload.file - }).then(resp => resp.json()).then(resp => { - if (resp.error !== undefined) { - this.displayError(resp.error) - return - } - - this.pack.files = resp - this.sortPackFiles(this.packName) - - this.newEmojiUpload = clone(newEmojiUploadBase) - }) - }, - createEmojiPack () { this.$store.state.api.backendInteractor.createEmojiPack( { name: this.newPackName } @@ -132,7 +112,6 @@ const EmojiTab = { } }).then(done => { delete this.editedMetadata[this.packName] - delete this.editedParts[this.packName] this.deleteModalVisible = false this.packName = '' @@ -162,68 +141,9 @@ const EmojiTab = { }) }, - revertEmoji (shortcode) { - // Delete current changes and overwrite them with defaults. If the window is closed, they'll get cleared anyway - delete this.editedParts[this.packName][shortcode] - this.editEmoji(shortcode) - }, - editEmoji (shortcode) { - if (this.editedParts[this.packName] === undefined) { this.editedParts[this.packName] = {} } - - if (this.editedParts[this.packName][shortcode] === undefined) { - this.editedParts[this.packName][shortcode] = { - shortcode, file: this.pack.files[shortcode] - } - } - }, - deleteEmoji (shortcode) { - this.editedParts[this.packName][shortcode].deleteModalVisible = false - - this.$store.state.api.backendInteractor.deleteEmojiFile( - { packName: this.packName, shortcode } - ).then(resp => resp.json()).then(resp => { - if (resp.error !== undefined) { - this.displayError(resp.error) - return - } - - this.pack.files = resp - delete this.editedParts[this.packName][shortcode] - - this.sortPackFiles(this.packName) - }) - }, - closedEditedEmoji (shortcode) { - const edited = this.editedParts[this.packName][shortcode] - - if (edited.shortcode === shortcode && edited.file === this.pack.files[shortcode]) { - delete this.editedParts[this.packName][shortcode] - - return true - } - - return false - }, - saveEditedEmoji (shortcode) { - if (this.closedEditedEmoji(shortcode)) return - - const edited = this.editedParts[this.packName][shortcode] - - this.$store.state.api.backendInteractor.updateEmojiFile( - { packName: this.packName, shortcode, newShortcode: edited.shortcode, newFilename: edited.file, force: false } - ).then(resp => { - if (resp.error !== undefined) { - this.displayError(resp.error) - return Promise.reject(resp.error) - } - - return resp.json() - }).then(resp => { - this.pack.files = resp - delete this.editedParts[this.packName][shortcode] - - this.sortPackFiles(this.packName) - }) + updatePackFiles (newFiles) { + this.pack.files = newFiles + this.sortPackFiles(this.packName) }, loadPacksPaginated (listFunction) { diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.scss b/src/components/settings_modal/admin_tabs/emoji_tab.scss @@ -39,17 +39,6 @@ margin-left: 0.5em; } -.emoji-tab-edit-popover { - padding-left: 0.5em; - padding-right: 0.5em; - padding-bottom: 0.5em; - - .emoji { - width: 32px; - height: 32px; - } -} - .emoji-tab-popover-input { margin-bottom: 0.5em; diff --git a/src/components/settings_modal/admin_tabs/emoji_tab.vue b/src/components/settings_modal/admin_tabs/emoji_tab.vue @@ -97,38 +97,44 @@ </li> </ul> - <div v-if="packName !== ''"> + <div v-if="pack"> <div class="pack-info-wrapper"> <ul class="setting-list"> <li> - <div> + <label> {{ $t('admin_dash.emoji.description') }} <ModifiedIndicator :changed="metaEdited('description')" message-key="admin_dash.emoji.metadata_changed" /> - </div> - <textarea - v-model="packMeta.description" - :disabled="pack.remote !== undefined" - class="bio resize-height" /> + + <textarea + v-model="packMeta.description" + :disabled="pack.remote !== undefined" + class="bio resize-height" /> + </label> </li> <li> - <div> + <label> {{ $t('admin_dash.emoji.homepage') }} <ModifiedIndicator :changed="metaEdited('homepage')" message-key="admin_dash.emoji.metadata_changed" /> - </div> + <input class="emoji-info-input" v-model="packMeta.homepage" :disabled="pack.remote !== undefined"> + </label> </li> <li> - <div> + <label> {{ $t('admin_dash.emoji.fallback_src') }} <ModifiedIndicator :changed="metaEdited('fallback-src')" message-key="admin_dash.emoji.metadata_changed" /> - </div> - <input class="emoji-info-input" v-model="packMeta['fallback-src']" :disabled="pack.remote !== undefined"> + + <input class="emoji-info-input" v-model="packMeta['fallback-src']" :disabled="pack.remote !== undefined"> + </label> </li> <li> - <div>{{ $t('admin_dash.emoji.fallback_sha256') }}</div> - <input :disabled="true" class="emoji-info-input" v-model="packMeta['fallback-src-sha256']"> + <label> + {{ $t('admin_dash.emoji.fallback_sha256') }} + + <input :disabled="true" class="emoji-info-input" v-model="packMeta['fallback-src-sha256']"> + </label> </li> <li> <Checkbox :disabled="pack.remote !== undefined" v-model="packMeta['share-files']"> @@ -218,132 +224,30 @@ {{ $t('admin_dash.emoji.files') }} <ModifiedIndicator v-if="pack" - :changed="editedParts[packName] && Object.keys(editedParts[packName]).length > 0" + :changed="$refs.emojiPopovers && $refs.emojiPopovers.some(p => p.isEdited)" message-key="admin_dash.emoji.emoji_changed"/> </h4> <div class="emoji-list" v-if="pack"> - <Popover + <EmojiEditingPopover v-if="pack.remote === undefined" - ref="addEmojiPopover" - trigger="click" - placement="bottom" - bound-to-selector=".emoji-tab" - popover-class="emoji-tab-edit-popover popover-default" - :bound-to="{ x: 'container' }" - :offset="{ y: 5 }" + placement="bottom" new-upload + :title="$t('admin_dash.emoji.adding_new')" + :packName="packName" @updatePackFiles="updatePackFiles" > <template #trigger> <FAIcon icon="plus" size="2x" :title="$t('admin_dash.emoji.add_file')" /> </template> - <template #content> - <h3> - {{ $t('admin_dash.emoji.adding_new') }} - </h3> - - <StillImage - class="emoji" v-if="newEmojiUploadPreview" - :src="newEmojiUploadPreview" - /> - <div v-else class="emoji"></div> - - <div class="emoji-tab-popover-input"> - <input - type="file" - accept="image/*" - class="emoji-tab-popover-file" - @change="newEmojiUpload.upload = $event.target.files" - > - </div> - <div> - <div class="emoji-tab-popover-input"> - <div>{{ $t('admin_dash.emoji.shortcode') }}</div> - <input class="emoji-data-input" - v-model="newEmojiUpload.shortcode" - :placeholder="$t('admin_dash.emoji.new_shortcode')"> - </div> + </EmojiEditingPopover> - <div class="emoji-tab-popover-input"> - <div>{{ $t('admin_dash.emoji.filename') }}</div> - <input class="emoji-data-input" - v-model="newEmojiUpload.file" - :placeholder="$t('admin_dash.emoji.new_filename')"> - </div> - - <button - class="button button-default btn" - type="button" - :disabled="this.newEmojiUpload.upload.length == 0" - @click="uploadEmoji"> - {{ $t('admin_dash.emoji.save') }} - </button> - </div> - </template> - </Popover> - - <Popover + <EmojiEditingPopover + placement="top" ref="emojiPopovers" v-for="(file, shortcode) in pack.files" :key="shortcode" - trigger="click" + :title="$t('admin_dash.emoji.editing', [shortcode])" :disabled="pack.remote !== undefined" - placement="top" - :class="{'emoji-unsaved': editedParts[packName] !== undefined && editedParts[packName][shortcode] !== undefined}" - popover-class="emoji-tab-edit-popover popover-default" - bound-to-selector=".emoji-list" - :bound-to="{ x: 'container' }" - :offset="{ y: 5 }" - @show="editEmoji(shortcode)" - @close="closedEditedEmoji(shortcode)" + :shortcode="shortcode" :file="file" :packName="packName" + @updatePackFiles="updatePackFiles" > - <template #content> - <h3> - {{ $t('admin_dash.emoji.editing', [shortcode]) }} - </h3> - - <StillImage class="emoji" :src="emojiAddr(file)" /> - - <div v-if="editedParts[packName] !== undefined && editedParts[packName][shortcode] !== undefined"> - <div class="emoji-tab-popover-input"> - <label for="emoji-edit-shortcode">{{ $t('admin_dash.emoji.shortcode') }}</label> - <input id="emoji-edit-shortcode" class="emoji-data-input" - v-model="editedParts[packName][shortcode].shortcode"> - </div> - <div class="emoji-tab-popover-input"> - <label for="emoji-edit-filename">{{ $t('admin_dash.emoji.filename') }}</label> - <input id="emoji-edit-filename" class="emoji-data-input" - v-model="editedParts[packName][shortcode].file"> - </div> - - <div> - <button - class="button button-default btn emoji-tab-popover-button" - type="button" - @click="saveEditedEmoji(shortcode)"> - {{ $t('admin_dash.emoji.save') }} - </button> - <button - class="button button-default btn emoji-tab-popover-button" - type="button" - @click="editedParts[packName][shortcode].deleteModalVisible = true"> - {{ $t('admin_dash.emoji.delete') }} - </button> - <button - class="button button-default btn emoji-tab-popover-button" - type="button" - @click="revertEmoji(shortcode)"> - {{ $t('admin_dash.emoji.revert') }} - </button> - <ConfirmModal - v-if="editedParts[packName][shortcode].deleteModalVisible" - :title="$t('admin_dash.emoji.delete_title')" - :cancel-text="$t('status.delete_confirm_cancel_button')" - :confirm-text="$t('status.delete_confirm_accept_button')" - @cancelled="editedParts[packName][shortcode].deleteModalVisible = false" - @accepted="deleteEmoji(shortcode)" > - {{ $t('admin_dash.emoji.delete_confirm', [shortcode]) }} - </ConfirmModal> - </div> - </div> - </template> <template #trigger> <StillImage class="emoji" @@ -352,7 +256,7 @@ :alt="`:${shortcode}:`" /> </template> - </Popover> + </EmojiEditingPopover> </div> </ul> </div> diff --git a/src/components/settings_modal/helpers/emoji_editing_popover.vue b/src/components/settings_modal/helpers/emoji_editing_popover.vue @@ -0,0 +1,207 @@ +<template> + <Popover + trigger="click" + :placement="placement" + bound-to-selector=".emoji-list" + popover-class="emoji-tab-edit-popover popover-default" + ref="emojiPopover" + :bound-to="{ x: 'container' }" + :offset="{ y: 5 }" + :disabled="disabled" + :class="{'emoji-unsaved': isEdited}" + > + <template #trigger> + <slot name="trigger" /> + </template> + <template #content> + <h3> + {{ title }} + </h3> + + <StillImage class="emoji" v-if="emojiPreview" :src="emojiPreview" /> + <div v-else class="emoji"></div> + + <div class="emoji-tab-popover-input" v-if="newUpload"> + <input + type="file" + accept="image/*" + class="emoji-tab-popover-file" + @change="uploadFile = $event.target.files"> + </div> + <div> + <div class="emoji-tab-popover-input"> + <label> + {{ $t('admin_dash.emoji.shortcode') }} + <input class="emoji-data-input" + v-model="editedShortcode" + :placeholder="$t('admin_dash.emoji.new_shortcode')"> + </label> + </div> + + <div class="emoji-tab-popover-input"> + <label> + {{ $t('admin_dash.emoji.filename') }} + + <input class="emoji-data-input" + v-model="editedFile" + :placeholder="$t('admin_dash.emoji.new_filename')"> + </label> + </div> + + <button + class="button button-default btn" + type="button" + :disabled="uploadFile.length == 0" + @click="newUpload ? uploadEmoji() : saveEditedEmoji()"> + {{ $t('admin_dash.emoji.save') }} + </button> + + <template v-if="!newUpload"> + <button + class="button button-default btn emoji-tab-popover-button" + type="button" + @click="deleteModalVisible = true"> + {{ $t('admin_dash.emoji.delete') }} + </button> + <button + class="button button-default btn emoji-tab-popover-button" + type="button" + @click="revertEmoji"> + {{ $t('admin_dash.emoji.revert') }} + </button> + <ConfirmModal + v-if="deleteModalVisible" + :title="$t('admin_dash.emoji.delete_title')" + :cancel-text="$t('status.delete_confirm_cancel_button')" + :confirm-text="$t('status.delete_confirm_accept_button')" + @cancelled="deleteModalVisible = false" + @accepted="deleteEmoji" > + {{ $t('admin_dash.emoji.delete_confirm', [shortcode]) }} + </ConfirmModal> + </template> + </div> + </template> + </Popover> +</template> + +<script> +import Popover from 'components/popover/popover.vue' +import ConfirmModal from 'components/confirm_modal/confirm_modal.vue' +import StillImage from 'components/still-image/still-image.vue' + +export default { + components: { Popover, ConfirmModal, StillImage }, + data () { + return { + uploadFile: [], + editedShortcode: this.shortcode, + editedFile: this.file, + deleteModalVisible: false + } + }, + computed: { + emojiPreview () { + if (this.newUpload && this.uploadFile.length > 0) { + return URL.createObjectURL(this.uploadFile[0]) + } else if (!this.newUpload) { + return this.emojiAddr(this.file) + } + + return null + }, + isEdited () { + return !this.newUpload && (this.editedShortcode !== this.shortcode || this.editedFile !== this.file) + } + }, + inject: ['emojiAddr', 'displayError'], + methods: { + saveEditedEmoji () { + if (!this.isEdited) return + + this.$store.state.api.backendInteractor.updateEmojiFile( + { packName: this.packName, shortcode: this.shortcode, newShortcode: this.editedShortcode, newFilename: this.editedFile, force: false } + ).then(resp => { + if (resp.error !== undefined) { + this.displayError(resp.error) + return Promise.reject(resp.error) + } + + return resp.json() + }).then(resp => this.$emit('updatePackFiles', resp)) + }, + uploadEmoji () { + this.$store.state.api.backendInteractor.addNewEmojiFile({ + packName: this.packName, + file: this.uploadFile[0], + shortcode: this.editedShortcode, + filename: this.editedFile + }).then(resp => resp.json()).then(resp => { + if (resp.error !== undefined) { + this.displayError(resp.error) + return + } + + this.$emit('updatePackFiles', resp) + this.$refs.emojiPopover.hidePopover() + + this.editedFile = '' + this.editedShortcode = '' + this.uploadFile = [] + }) + }, + revertEmoji () { + this.editedFile = this.file + this.editedShortcode = this.shortcode + }, + deleteEmoji () { + this.deleteModalVisible = false + + this.$store.state.api.backendInteractor.deleteEmojiFile( + { packName: this.packName, shortcode: this.editedShortcode } + ).then(resp => resp.json()).then(resp => { + if (resp.error !== undefined) { + this.displayError(resp.error) + return + } + + this.$emit('updatePackFiles', resp) + }) + } + }, + props: { + placement: String, + disabled: { + type: Boolean, + default: false + }, + + newUpload: Boolean, + + title: String, + packName: String, + shortcode: { + type: String, + // Only exists when this is not a new upload + default: '' + }, + file: { + type: String, + // Only exists when this is not a new upload + default: '' + } + } +} +</script> + +<style lang="scss"> + .emoji-tab-edit-popover { + padding-left: 0.5em; + padding-right: 0.5em; + padding-bottom: 0.5em; + + .emoji { + width: 32px; + height: 32px; + } + } +</style>