Rearrange stuff in accordance with comments on the MR, mostly

Also, add support for a custom message to the modified indicator
This commit is contained in:
Ekaterina Vaartis 2024-01-17 22:41:18 +03:00
parent 872dffe51b
commit a2133f5283
5 changed files with 263 additions and 153 deletions

View File

@ -58,6 +58,11 @@ const EmojiTab = {
} }
return result return result
},
newEmojiUploadPreview () {
if (this.newEmojiUpload.upload.length > 0) {
return URL.createObjectURL(this.newEmojiUpload.upload[0])
}
} }
}, },
@ -135,7 +140,11 @@ const EmojiTab = {
}, },
metaEdited (prop) { metaEdited (prop) {
return this.pack && this.packMeta[prop] !== this.pack.pack[prop] if (!this.pack) return
const def = this.pack.pack[prop] || ''
const edited = this.packMeta[prop] || ''
return edited !== def
}, },
savePackMetadata () { savePackMetadata () {
this.$store.state.api.backendInteractor.saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta }).then( this.$store.state.api.backendInteractor.saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta }).then(
@ -153,6 +162,11 @@ 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) { editEmoji (shortcode) {
if (this.editedParts[this.packName] === undefined) { this.editedParts[this.packName] = {} } if (this.editedParts[this.packName] === undefined) { this.editedParts[this.packName] = {} }
@ -179,14 +193,22 @@ const EmojiTab = {
this.sortPackFiles(this.packName) this.sortPackFiles(this.packName)
}) })
}, },
saveEditedEmoji (shortcode) { closedEditedEmoji (shortcode) {
const edited = this.editedParts[this.packName][shortcode] const edited = this.editedParts[this.packName][shortcode]
if (edited.shortcode === shortcode && edited.file === this.pack.files[shortcode]) { if (edited.shortcode === shortcode && edited.file === this.pack.files[shortcode]) {
delete this.editedParts[this.packName][shortcode] delete this.editedParts[this.packName][shortcode]
return
return true
} }
return false
},
saveEditedEmoji (shortcode) {
if (this.closedEditedEmoji(shortcode)) return
const edited = this.editedParts[this.packName][shortcode]
this.$store.state.api.backendInteractor.updateEmojiFile( this.$store.state.api.backendInteractor.updateEmojiFile(
{ packName: this.packName, shortcode, newShortcode: edited.shortcode, newFilename: edited.file, force: false } { packName: this.packName, shortcode, newShortcode: edited.shortcode, newFilename: edited.file, force: false }
).then(resp => { ).then(resp => {

View File

@ -1,7 +1,7 @@
@import "src/variables"; @import "src/variables";
.emoji-tab { .emoji-tab {
.btn-group .btn { .btn-group .btn:not(:first-child) {
margin-left: 0.5em; margin-left: 0.5em;
} }
@ -35,21 +35,34 @@
} }
} }
.emoji-tab-popover-button:not(:first-child) {
margin-left: 0.5em;
}
.emoji-tab-edit-popover { .emoji-tab-edit-popover {
padding-left: 0.5em; padding-left: 0.5em;
padding-right: 0.5em; padding-right: 0.5em;
padding-bottom: 0.5em; padding-bottom: 0.5em;
}
.emoji-tab-popover-button { .emoji {
margin-left: 0.5em; width: 32px;
height: 32px;
}
} }
.emoji-tab-popover-input { .emoji-tab-popover-input {
width: 20em;
margin-bottom: 0.5em; margin-bottom: 0.5em;
&:not(:first-child) { label {
margin-left: 0.5em; display: block;
margin-bottom: 0.5em;
}
input {
width: 20em;
}
.emoji-tab-popover-file {
padding-top: 3px;
} }
} }

View File

@ -7,6 +7,8 @@
<h2>{{ $t('admin_dash.tabs.emoji') }}</h2> <h2>{{ $t('admin_dash.tabs.emoji') }}</h2>
<ul class="setting-list"> <ul class="setting-list">
<h2>{{ $t('admin_dash.emoji.global_actions') }}</h2>
<li class="btn-group setting-item"> <li class="btn-group setting-item">
<button <button
class="button button-default btn" class="button button-default btn"
@ -23,31 +25,6 @@
</li> </li>
<li class="btn-group setting-item"> <li class="btn-group setting-item">
<button
class="button button-default btn"
type="button"
@click="$refs.createPackPopover.showPopover">
{{ $t('admin_dash.emoji.create_pack') }}
</button>
<Popover
ref="createPackPopover"
trigger="click"
placement="bottom"
bound-to-selector=".emoji-tab"
:bound-to="{ x: 'container' }"
:offset="{ y: 5 }"
>
<template #content>
<input v-model="newPackName" :placeholder="$t('admin_dash.emoji.new_pack_name')">
<button
class="button button-default btn emoji-tab-popover-button"
type="button"
@click="createEmojiPack">
{{ $t('admin_dash.emoji.create') }}
</button>
</template>
</Popover>
<button <button
class="button button-default btn" class="button button-default btn"
type="button" type="button"
@ -56,6 +33,7 @@
<Popover <Popover
ref="remotePackPopover" ref="remotePackPopover"
popover-class="emoji-tab-edit-popover popover-default"
trigger="click" trigger="click"
placement="bottom" placement="bottom"
bound-to-selector=".emoji-tab" bound-to-selector=".emoji-tab"
@ -63,18 +41,23 @@
:offset="{ y: 5 }" :offset="{ y: 5 }"
> >
<template #content> <template #content>
<input v-model="remotePackInstance" :placeholder="$t('admin_dash.emoji.remote_pack_instance')"> <div class="emoji-tab-popover-input">
<button <h3>{{ $t('admin_dash.emoji.remote_pack_instance') }}</h3>
class="button button-default btn emoji-tab-popover-button" <input v-model="remotePackInstance" :placeholder="$t('admin_dash.emoji.remote_pack_instance')">
type="button" <button
@click="listRemotePacks"> class="button button-default btn emoji-tab-popover-button"
{{ $t('admin_dash.emoji.do_list') }} type="button"
</button> @click="listRemotePacks">
{{ $t('admin_dash.emoji.do_list') }}
</button>
</div>
</template> </template>
</Popover> </Popover>
</button> </button>
</li> </li>
<h2>{{ $t('admin_dash.emoji.emoji_packs') }}</h2>
<li> <li>
<Select class="form-control" v-model="packName"> <Select class="form-control" v-model="packName">
<option value="" disabled hidden>{{ $t('admin_dash.emoji.emoji_pack') }}</option> <option value="" disabled hidden>{{ $t('admin_dash.emoji.emoji_pack') }}</option>
@ -82,6 +65,35 @@
{{ listPackName }} {{ listPackName }}
</option> </option>
</Select> </Select>
<button
class="button button-default btn emoji-tab-popover-button"
type="button"
@click="$refs.createPackPopover.showPopover">
{{ $t('admin_dash.emoji.create_pack') }}
</button>
<Popover
ref="createPackPopover"
popover-class="emoji-tab-edit-popover popover-default"
trigger="click"
placement="bottom"
bound-to-selector=".emoji-tab"
:bound-to="{ x: 'container' }"
:offset="{ y: 5 }"
>
<template #content>
<div class="emoji-tab-popover-input">
<h3>{{ $t('admin_dash.emoji.new_pack_name') }}</h3>
<input v-model="newPackName" :placeholder="$t('admin_dash.emoji.new_pack_name')">
<button
class="button button-default btn emoji-tab-popover-button"
type="button"
@click="createEmojiPack">
{{ $t('admin_dash.emoji.create') }}
</button>
</div>
</template>
</Popover>
</li> </li>
</ul> </ul>
@ -91,7 +103,7 @@
<li> <li>
<div> <div>
{{ $t('admin_dash.emoji.description') }} {{ $t('admin_dash.emoji.description') }}
<ModifiedIndicator :changed="metaEdited('description')" /> <ModifiedIndicator :changed="metaEdited('description')" message-key="admin_dash.emoji.metadata_changed" />
</div> </div>
<textarea <textarea
v-model="packMeta.description" v-model="packMeta.description"
@ -101,7 +113,7 @@
<li> <li>
<div> <div>
{{ $t('admin_dash.emoji.homepage') }} {{ $t('admin_dash.emoji.homepage') }}
<ModifiedIndicator :changed="metaEdited('homepage')" /> <ModifiedIndicator :changed="metaEdited('homepage')" message-key="admin_dash.emoji.metadata_changed" />
</div> </div>
<input <input
class="emoji-info-input" v-model="packMeta.homepage" class="emoji-info-input" v-model="packMeta.homepage"
@ -110,7 +122,7 @@
<li> <li>
<div> <div>
{{ $t('admin_dash.emoji.fallback_src') }} {{ $t('admin_dash.emoji.fallback_src') }}
<ModifiedIndicator :changed="metaEdited('fallback-src')" /> <ModifiedIndicator :changed="metaEdited('fallback-src')" message-key="admin_dash.emoji.metadata_changed" />
</div> </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">
</li> </li>
@ -123,7 +135,7 @@
{{ $t('admin_dash.emoji.share') }} {{ $t('admin_dash.emoji.share') }}
</Checkbox> </Checkbox>
<ModifiedIndicator :changed="metaEdited('share-files')" /> <ModifiedIndicator :changed="metaEdited('share-files')" message-key="admin_dash.emoji.metadata_changed" />
</li> </li>
<li class="btn-group"> <li class="btn-group">
<button <button
@ -131,54 +143,14 @@
type="button" type="button"
v-if="pack.remote === undefined" v-if="pack.remote === undefined"
@click="savePackMetadata"> @click="savePackMetadata">
{{ $t('admin_dash.emoji.save') }} {{ $t('admin_dash.emoji.save_meta') }}
</button> </button>
<button <button
class="button button-default btn" class="button button-default btn"
type="button" type="button"
v-if="pack.remote === undefined" v-if="pack.remote === undefined"
@click="$refs.addEmojiPopover.showPopover"> @click="savePackMetadata">
{{ $t('admin_dash.emoji.add_file') }} {{ $t('admin_dash.emoji.revert_meta') }}
<Popover
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 }"
>
<template #content>
<h3>{{ $t('admin_dash.emoji.adding_new') }}</h3>
<div>
<input
type="file"
class="emoji-tab-popover-input emoji-tab-popover-file"
@change="newEmojiUpload.upload = $event.target.files"
>
</div>
<div>
<div>
<input class="emoji-data-input emoji-tab-popover-input"
v-model="newEmojiUpload.shortcode"
:placeholder="$t('admin_dash.emoji.new_shortcode')">
<input class="emoji-data-input emoji-tab-popover-input"
v-model="newEmojiUpload.file"
:placeholder="$t('admin_dash.emoji.new_filename')">
<button
class="button button-default btn emoji-tab-popover-button"
type="button"
:disabled="this.newEmojiUpload.upload.length == 0"
@click="uploadEmoji">
{{ $t('admin_dash.emoji.save') }}
</button>
</div>
</div>
</template>
</Popover>
</button> </button>
<button <button
@ -219,12 +191,15 @@
<h3>{{ $t('admin_dash.emoji.downloading_pack', [packName]) }}</h3> <h3>{{ $t('admin_dash.emoji.downloading_pack', [packName]) }}</h3>
<div> <div>
<div> <div>
<input class="emoji-data-input emoji-tab-popover-input" <div class="emoji-tab-popover-input">
v-model="remotePackDownloadAs" <label for="remote-download-as-input">{{ $t('admin_dash.emoji.download_as_name') }}</label>
:placeholder="$t('admin_dash.emoji.download_as_name')"> <input id="remote-download-as-input" class="emoji-data-input"
v-model="remotePackDownloadAs"
:placeholder="$t('admin_dash.emoji.download_as_name_full')">
</div>
<button <button
class="button button-default btn emoji-tab-popover-button" class="button button-default btn"
type="button" type="button"
@click="downloadRemotePack"> @click="downloadRemotePack">
{{ $t('admin_dash.emoji.download') }} {{ $t('admin_dash.emoji.download') }}
@ -238,64 +213,148 @@
</ul> </ul>
</div> </div>
<h2>{{ $t('admin_dash.emoji.files') }}</h2> <ul class="setting-list">
<h3>
{{ $t('admin_dash.emoji.files') }}
<div class="emoji-list" v-if="pack"> <ModifiedIndicator v-if="pack"
<Popover :changed="editedParts[packName] && Object.keys(editedParts[packName]).length > 0"
v-for="(file, shortcode) in pack.files" :key="shortcode" message-key="admin_dash.emoji.emoji_changed"/>
trigger="click" </h3>
: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)"
>
<template #content>
<h3>
{{ $t('admin_dash.emoji.editing', [shortcode]) }}
</h3>
<div v-if="editedParts[packName] !== undefined && editedParts[packName][shortcode] !== undefined">
<input class="emoji-data-input"
v-model="editedParts[packName][shortcode].shortcode">
<input class="emoji-data-input"
v-model="editedParts[packName][shortcode].file">
<button <div class="emoji-list" v-if="pack">
class="button button-default btn emoji-tab-popover-button" <Popover
type="button" v-if="pack.remote === undefined"
@click="saveEditedEmoji(shortcode)"> ref="addEmojiPopover"
{{ $t('admin_dash.emoji.save') }} trigger="click"
</button> placement="bottom"
<button bound-to-selector=".emoji-tab"
class="button button-default btn emoji-tab-popover-button" popover-class="emoji-tab-edit-popover popover-default"
type="button" :bound-to="{ x: 'container' }"
@click="editedParts[packName][shortcode].deleteModalVisible = true"> :offset="{ y: 5 }"
{{ $t('admin_dash.emoji.delete') }} >
</button> <template #trigger>
<ConfirmModal <FAIcon icon="plus" size="2x" :title="$t('admin_dash.emoji.add_file')" />
v-if="editedParts[packName][shortcode].deleteModalVisible" </template>
:title="$t('admin_dash.emoji.delete_title')" <template #content>
:cancel-text="$t('status.delete_confirm_cancel_button')" <h3>
:confirm-text="$t('status.delete_confirm_accept_button')" {{ $t('admin_dash.emoji.adding_new') }}
@cancelled="editedParts[packName][shortcode].deleteModalVisible = false" </h3>
@accepted="deleteEmoji(shortcode)" >
{{ $t('admin_dash.emoji.delete_confirm', [shortcode]) }} <StillImage
</ConfirmModal> class="emoji" v-if="newEmojiUploadPreview"
</div> :src="newEmojiUploadPreview"
</template> />
<template #trigger> <div v-else class="emoji"></div>
<StillImage
class="emoji" <div class="emoji-tab-popover-input">
:src="emojiAddr(file)" <input
:title="`:${shortcode}:`" type="file"
:alt="`:${shortcode}:`" accept="image/*"
/> class="emoji-tab-popover-file"
</template> @change="newEmojiUpload.upload = $event.target.files"
</Popover> >
</div> </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>
<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
v-for="(file, shortcode) in pack.files" :key="shortcode"
trigger="click"
: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)"
>
<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"
:src="emojiAddr(file)"
:title="`:${shortcode}:`"
:alt="`:${shortcode}:`"
/>
</template>
</Popover>
</div>
</ul>
</div> </div>
</div> </div>
</div> </div>

View File

@ -15,7 +15,7 @@
</template> </template>
<template #content> <template #content>
<div class="modified-tooltip"> <div class="modified-tooltip">
{{ $t('settings.setting_changed') }} {{ $t(messageKey) }}
</div> </div>
</template> </template>
</Popover> </Popover>
@ -33,7 +33,13 @@ library.add(
export default { export default {
components: { Popover }, components: { Popover },
props: ['changed'] props: {
changed: Boolean,
messageKey: {
type: String,
default: 'settings.setting_changed'
}
}
} }
</script> </script>

View File

@ -934,6 +934,7 @@
"success_installing_frontend": "Frontend {version} successfully installed" "success_installing_frontend": "Frontend {version} successfully installed"
}, },
"emoji": { "emoji": {
"global_actions": "Global actions",
"reload": "Reload emoji", "reload": "Reload emoji",
"importFS": "Import emoji from filesystem", "importFS": "Import emoji from filesystem",
"error": "Error: {0}", "error": "Error: {0}",
@ -941,6 +942,7 @@
"delete_pack": "Delete pack", "delete_pack": "Delete pack",
"new_pack_name": "New pack name", "new_pack_name": "New pack name",
"create": "Create", "create": "Create",
"emoji_packs": "Emoji packs",
"remote_packs": "Remote packs", "remote_packs": "Remote packs",
"do_list": "List", "do_list": "List",
"remote_pack_instance": "Remote pack instance", "remote_pack_instance": "Remote pack instance",
@ -951,19 +953,27 @@
"fallback_sha256": "Fallback SHA256", "fallback_sha256": "Fallback SHA256",
"share": "Share", "share": "Share",
"save": "Save", "save": "Save",
"save_meta": "Save metadata",
"revert_meta": "Revert metadata",
"delete": "Delete", "delete": "Delete",
"revert": "Revert",
"add_file": "Add file", "add_file": "Add file",
"adding_new": "Adding new emoji", "adding_new": "Adding new emoji",
"shortcode": "Shortcode",
"filename": "Filename",
"new_shortcode": "Shortcode, leave blank to infer", "new_shortcode": "Shortcode, leave blank to infer",
"new_filename": "Filename, leave blank to infer", "new_filename": "Filename, leave blank to infer",
"delete_confirm": "Are you sure you want to delete {0}?", "delete_confirm": "Are you sure you want to delete {0}?",
"download_pack": "Download pack", "download_pack": "Download pack",
"downloading_pack": "Downloading {0}", "downloading_pack": "Downloading {0}",
"download": "Download", "download": "Download",
"download_as_name": "New name, leave blank to reuse", "download_as_name": "New name",
"download_as_name_full": "New name, leave blank to reuse",
"files": "Files", "files": "Files",
"editing": "Editing {0}", "editing": "Editing {0}",
"delete_title": "Delete?" "delete_title": "Delete?",
"metadata_changed": "Metadata different from saved",
"emoji_changed": "Unsaved emoji file changes, check highlighted emoji"
}, },
"temp_overrides": { "temp_overrides": {
":pleroma": { ":pleroma": {