Merge branch 'copy-emoji-one' into 'develop'
Allow copying a single emoji from a pack, copying emojis from posts, and show a popover on emoji click See merge request pleroma/pleroma-fe!2207
This commit is contained in:
commit
0424992a35
15 changed files with 325 additions and 36 deletions
1
changelog.d/emoji-copying-post.add
Normal file
1
changelog.d/emoji-copying-post.add
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Allow copying an emoji from a remote post into a local pack
|
||||||
1
changelog.d/emoji-copying.add
Normal file
1
changelog.d/emoji-copying.add
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
Allow copying one emoji from a remote pack into a local pack
|
||||||
1
changelog.d/emoji-popover.add
Normal file
1
changelog.d/emoji-popover.add
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
When an emoji is clicked in a post, show a popover with its name and a bigger image. Admins can also copy it to a local pack
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
:title="'@'+(user && user.screen_name_ui)"
|
:title="'@'+(user && user.screen_name_ui)"
|
||||||
:html="htmlTitle"
|
:html="htmlTitle"
|
||||||
:emoji="user.emoji || []"
|
:emoji="user.emoji || []"
|
||||||
|
:is-local="user.is_local"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@
|
||||||
:title="'@'+notification.from_profile.screen_name_ui"
|
:title="'@'+notification.from_profile.screen_name_ui"
|
||||||
:html="notification.from_profile.name_html"
|
:html="notification.from_profile.name_html"
|
||||||
:emoji="notification.from_profile.emoji"
|
:emoji="notification.from_profile.emoji"
|
||||||
|
:is-local="notification.from_profile.is_local"
|
||||||
/>
|
/>
|
||||||
</bdi>
|
</bdi>
|
||||||
<!-- eslint-enable vue/no-v-html -->
|
<!-- eslint-enable vue/no-v-html -->
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import { unescape, flattenDeep } from 'lodash'
|
||||||
import { getTagName, processTextForEmoji, getAttrs } from 'src/services/html_converter/utility.service.js'
|
import { getTagName, processTextForEmoji, getAttrs } from 'src/services/html_converter/utility.service.js'
|
||||||
import { convertHtmlToTree } from 'src/services/html_converter/html_tree_converter.service.js'
|
import { convertHtmlToTree } from 'src/services/html_converter/html_tree_converter.service.js'
|
||||||
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
import { convertHtmlToLines } from 'src/services/html_converter/html_line_converter.service.js'
|
||||||
import StillImage from 'src/components/still-image/still-image.vue'
|
import StillImageEmojiPopover from 'src/components/still-image/still-image-emoji-popover.vue'
|
||||||
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
import MentionsLine from 'src/components/mentions_line/mentions_line.vue'
|
||||||
import { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.js'
|
import { MENTIONS_LIMIT } from 'src/components/mentions_line/mentions_line.js'
|
||||||
import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue'
|
import HashtagLink from 'src/components/hashtag_link/hashtag_link.vue'
|
||||||
|
|
@ -86,6 +86,12 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
// Assume is local to be true if unspecified, so the button isn't show where it probably should not be
|
||||||
|
isLocal: {
|
||||||
|
required: false,
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// NEVER EVER TOUCH DATA INSIDE RENDER
|
// NEVER EVER TOUCH DATA INSIDE RENDER
|
||||||
|
|
@ -162,11 +168,14 @@ export default {
|
||||||
item,
|
item,
|
||||||
this.emoji,
|
this.emoji,
|
||||||
({ shortcode, url }) => {
|
({ shortcode, url }) => {
|
||||||
return <StillImage
|
return <StillImageEmojiPopover
|
||||||
class="emoji img"
|
class="emoji img"
|
||||||
src={url}
|
src={url}
|
||||||
title={`:${shortcode}:`}
|
title={`:${shortcode}:`}
|
||||||
alt={`:${shortcode}:`}
|
alt={`:${shortcode}:`}
|
||||||
|
|
||||||
|
shortcode={shortcode}
|
||||||
|
isLocal={this.isLocal}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
)]
|
)]
|
||||||
|
|
|
||||||
|
|
@ -145,9 +145,9 @@ const EmojiTab = {
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
updatePackFiles (newFiles) {
|
updatePackFiles (newFiles, packName) {
|
||||||
this.pack.files = newFiles
|
this.knownPacks[packName].files = newFiles
|
||||||
this.sortPackFiles(this.packName)
|
this.sortPackFiles(packName)
|
||||||
},
|
},
|
||||||
|
|
||||||
loadPacksPaginated (listFunction) {
|
loadPacksPaginated (listFunction) {
|
||||||
|
|
|
||||||
|
|
@ -387,11 +387,12 @@
|
||||||
ref="emojiPopovers"
|
ref="emojiPopovers"
|
||||||
:key="shortcode"
|
:key="shortcode"
|
||||||
placement="top"
|
placement="top"
|
||||||
:title="$t('admin_dash.emoji.editing', [shortcode])"
|
:title="$t(`admin_dash.emoji.${pack.remote === undefined ? 'editing' : 'copying'}`, [shortcode])"
|
||||||
:disabled="pack.remote !== undefined"
|
|
||||||
:shortcode="shortcode"
|
:shortcode="shortcode"
|
||||||
:file="file"
|
:file="file"
|
||||||
:pack-name="packName"
|
:pack-name="packName"
|
||||||
|
:remote="pack.remote"
|
||||||
|
:known-local-packs="knownLocalPacks"
|
||||||
@update-pack-files="updatePackFiles"
|
@update-pack-files="updatePackFiles"
|
||||||
@display-error="displayError"
|
@display-error="displayError"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,6 @@
|
||||||
popover-class="emoji-tab-edit-popover popover-default"
|
popover-class="emoji-tab-edit-popover popover-default"
|
||||||
:bound-to="{ x: 'container' }"
|
:bound-to="{ x: 'container' }"
|
||||||
:offset="{ y: 5 }"
|
:offset="{ y: 5 }"
|
||||||
:disabled="disabled"
|
|
||||||
:class="{'emoji-unsaved': isEdited}"
|
:class="{'emoji-unsaved': isEdited}"
|
||||||
>
|
>
|
||||||
<template #trigger>
|
<template #trigger>
|
||||||
|
|
@ -28,17 +27,26 @@
|
||||||
class="emoji"
|
class="emoji"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<div
|
<div v-if="newUpload" class="emoji-tab-popover-new-upload">
|
||||||
v-if="newUpload"
|
<h4>{{ $t('admin_dash.emoji.emoji_source') }}</h4>
|
||||||
class="emoji-tab-popover-input"
|
|
||||||
>
|
<div class="emoji-tab-popover-input">
|
||||||
<input
|
<input
|
||||||
type="file"
|
type="file"
|
||||||
accept="image/*"
|
accept="image/*"
|
||||||
class="emoji-tab-popover-file input"
|
class="emoji-tab-popover-file input"
|
||||||
@change="uploadFile = $event.target.files"
|
@change="uploadFile = $event.target.files"
|
||||||
>
|
>
|
||||||
|
</div>
|
||||||
|
<div class="emoji-tab-popover-input ">
|
||||||
|
<input
|
||||||
|
v-model="uploadURL"
|
||||||
|
:placeholder="$t('admin_dash.emoji.upload_url')"
|
||||||
|
class="emoji-data-input input"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<div class="emoji-tab-popover-input">
|
<div class="emoji-tab-popover-input">
|
||||||
<label>
|
<label>
|
||||||
|
|
@ -63,16 +71,50 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-if="remote !== undefined"
|
||||||
|
class="emoji-tab-popover-input"
|
||||||
|
>
|
||||||
|
<label>
|
||||||
|
{{ $t('admin_dash.emoji.copy_to') }}
|
||||||
|
|
||||||
|
<SelectComponent
|
||||||
|
v-model="copyToPack"
|
||||||
|
class="form-control"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
value=""
|
||||||
|
disabled
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
{{ $t('admin_dash.emoji.emoji_pack') }}
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
v-for="(pack, listPackName) in knownLocalPacks"
|
||||||
|
:key="listPackName"
|
||||||
|
:label="listPackName"
|
||||||
|
>
|
||||||
|
{{ listPackName }}
|
||||||
|
</option>
|
||||||
|
</SelectComponent>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
For local emojis, disable the button if nothing was edited.
|
||||||
|
For remote emojis, also disable it if a local pack is not selected.
|
||||||
|
Remote emojis are processed by the same function that uploads new ones, as that is effectively what it does
|
||||||
|
-->
|
||||||
<button
|
<button
|
||||||
class="button button-default btn"
|
class="button button-default btn"
|
||||||
type="button"
|
type="button"
|
||||||
:disabled="newUpload ? uploadFile.length == 0 : !isEdited"
|
:disabled="saveButtonDisabled"
|
||||||
@click="newUpload ? uploadEmoji() : saveEditedEmoji()"
|
@click="(newUpload || remote !== undefined) ? uploadEmoji() : saveEditedEmoji()"
|
||||||
>
|
>
|
||||||
{{ $t('admin_dash.emoji.save') }}
|
{{ $t('admin_dash.emoji.save') }}
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<template v-if="!newUpload">
|
<template v-if="!newUpload && remote === undefined">
|
||||||
<button
|
<button
|
||||||
class="button button-default btn emoji-tab-popover-button"
|
class="button button-default btn emoji-tab-popover-button"
|
||||||
type="button"
|
type="button"
|
||||||
|
|
@ -107,19 +149,16 @@
|
||||||
import Popover from 'components/popover/popover.vue'
|
import Popover from 'components/popover/popover.vue'
|
||||||
import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
|
import ConfirmModal from 'components/confirm_modal/confirm_modal.vue'
|
||||||
import StillImage from 'components/still-image/still-image.vue'
|
import StillImage from 'components/still-image/still-image.vue'
|
||||||
|
import SelectComponent from 'components/select/select.vue'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { Popover, ConfirmModal, StillImage },
|
components: { Popover, ConfirmModal, StillImage, SelectComponent },
|
||||||
inject: ['emojiAddr'],
|
inject: ['emojiAddr'],
|
||||||
props: {
|
props: {
|
||||||
placement: {
|
placement: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
disabled: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
|
|
||||||
newUpload: Boolean,
|
newUpload: Boolean,
|
||||||
|
|
||||||
|
|
@ -140,21 +179,35 @@ export default {
|
||||||
type: String,
|
type: String,
|
||||||
// Only exists when this is not a new upload
|
// Only exists when this is not a new upload
|
||||||
default: ''
|
default: ''
|
||||||
|
},
|
||||||
|
|
||||||
|
// Only exists for emojis from remote packs
|
||||||
|
remote: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
knownLocalPacks: {
|
||||||
|
type: Object,
|
||||||
|
default: undefined
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: ['updatePackFiles', 'displayError'],
|
emits: ['updatePackFiles', 'displayError'],
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
uploadFile: [],
|
uploadFile: [],
|
||||||
|
uploadURL: '',
|
||||||
editedShortcode: this.shortcode,
|
editedShortcode: this.shortcode,
|
||||||
editedFile: this.file,
|
editedFile: this.file,
|
||||||
deleteModalVisible: false
|
deleteModalVisible: false,
|
||||||
|
copyToPack: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
emojiPreview () {
|
emojiPreview () {
|
||||||
if (this.newUpload && this.uploadFile.length > 0) {
|
if (this.newUpload && this.uploadFile.length > 0) {
|
||||||
return URL.createObjectURL(this.uploadFile[0])
|
return URL.createObjectURL(this.uploadFile[0])
|
||||||
|
} else if (this.newUpload && this.uploadURL !== '') {
|
||||||
|
return this.uploadURL
|
||||||
} else if (!this.newUpload) {
|
} else if (!this.newUpload) {
|
||||||
return this.emojiAddr(this.file)
|
return this.emojiAddr(this.file)
|
||||||
}
|
}
|
||||||
|
|
@ -163,6 +216,12 @@ export default {
|
||||||
},
|
},
|
||||||
isEdited () {
|
isEdited () {
|
||||||
return !this.newUpload && (this.editedShortcode !== this.shortcode || this.editedFile !== this.file)
|
return !this.newUpload && (this.editedShortcode !== this.shortcode || this.editedFile !== this.file)
|
||||||
|
},
|
||||||
|
saveButtonDisabled() {
|
||||||
|
if (this.remote === undefined)
|
||||||
|
return this.newUpload ? (this.uploadURL === "" && this.uploadFile.length == 0) : !this.isEdited
|
||||||
|
else
|
||||||
|
return this.copyToPack === ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -181,9 +240,12 @@ export default {
|
||||||
}).then(resp => this.$emit('updatePackFiles', resp))
|
}).then(resp => this.$emit('updatePackFiles', resp))
|
||||||
},
|
},
|
||||||
uploadEmoji () {
|
uploadEmoji () {
|
||||||
|
let packName = this.remote === undefined ? this.packName : this.copyToPack
|
||||||
this.$store.state.api.backendInteractor.addNewEmojiFile({
|
this.$store.state.api.backendInteractor.addNewEmojiFile({
|
||||||
packName: this.packName,
|
packName: packName,
|
||||||
file: this.uploadFile[0],
|
file: this.remote === undefined
|
||||||
|
? (this.uploadURL !== "" ? this.uploadURL : this.uploadFile[0])
|
||||||
|
: this.emojiAddr(this.file),
|
||||||
shortcode: this.editedShortcode,
|
shortcode: this.editedShortcode,
|
||||||
filename: this.editedFile
|
filename: this.editedFile
|
||||||
}).then(resp => resp.json()).then(resp => {
|
}).then(resp => resp.json()).then(resp => {
|
||||||
|
|
@ -192,7 +254,7 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('updatePackFiles', resp)
|
this.$emit('updatePackFiles', resp, packName)
|
||||||
this.$refs.emojiPopover.hidePopover()
|
this.$refs.emojiPopover.hidePopover()
|
||||||
|
|
||||||
this.editedFile = ''
|
this.editedFile = ''
|
||||||
|
|
@ -215,7 +277,7 @@ export default {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.$emit('updatePackFiles', resp)
|
this.$emit('updatePackFiles', resp, this.packName)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -228,9 +290,22 @@ export default {
|
||||||
padding-right: 0.5em;
|
padding-right: 0.5em;
|
||||||
padding-bottom: 0.5em;
|
padding-bottom: 0.5em;
|
||||||
|
|
||||||
|
.emoji-tab-popover-new-upload {
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
.emoji {
|
.emoji {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Select {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
margin-bottom: 1em;
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -79,6 +79,7 @@
|
||||||
<RichContent
|
<RichContent
|
||||||
:html="retweeterHtml"
|
:html="retweeterHtml"
|
||||||
:emoji="retweeterUser.emoji"
|
:emoji="retweeterUser.emoji"
|
||||||
|
:is-local="retweeterUser.is_local"
|
||||||
/>
|
/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<router-link
|
<router-link
|
||||||
|
|
@ -139,6 +140,7 @@
|
||||||
<RichContent
|
<RichContent
|
||||||
:html="status.user.name"
|
:html="status.user.name"
|
||||||
:emoji="status.user.emoji"
|
:emoji="status.user.emoji"
|
||||||
|
:is-local="status.user.is_local"
|
||||||
/>
|
/>
|
||||||
</h4>
|
</h4>
|
||||||
<h4
|
<h4
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ library.add(
|
||||||
faPollH
|
faPollH
|
||||||
)
|
)
|
||||||
|
|
||||||
const StatusContent = {
|
const StatusBody = {
|
||||||
name: 'StatusContent',
|
name: 'StatusBody',
|
||||||
props: [
|
props: [
|
||||||
'compact',
|
'compact',
|
||||||
'status',
|
'status',
|
||||||
|
|
@ -145,4 +145,4 @@ const StatusContent = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default StatusContent
|
export default StatusBody
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@
|
||||||
:faint="compact"
|
:faint="compact"
|
||||||
:html="status.summary_raw_html"
|
:html="status.summary_raw_html"
|
||||||
:emoji="status.emojis"
|
:emoji="status.emojis"
|
||||||
|
:is-local="status.isLocal"
|
||||||
/>
|
/>
|
||||||
<button
|
<button
|
||||||
v-show="longSubject && showingLongSubject"
|
v-show="longSubject && showingLongSubject"
|
||||||
|
|
@ -44,6 +45,7 @@
|
||||||
:faint="compact"
|
:faint="compact"
|
||||||
:greentext="mergedConfig.greentext"
|
:greentext="mergedConfig.greentext"
|
||||||
:attentions="status.attentions"
|
:attentions="status.attentions"
|
||||||
|
:is-local="status.is_local"
|
||||||
@parse-ready="onParseReady"
|
@parse-ready="onParseReady"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
|
|
|
||||||
189
src/components/still-image/still-image-emoji-popover.vue
Normal file
189
src/components/still-image/still-image-emoji-popover.vue
Normal file
|
|
@ -0,0 +1,189 @@
|
||||||
|
<template>
|
||||||
|
<Popover
|
||||||
|
ref="emojiPopover"
|
||||||
|
trigger="click"
|
||||||
|
placement="top"
|
||||||
|
:bound-to="{ x: 'container' }"
|
||||||
|
:offset="{ y: 10 }"
|
||||||
|
@show="fetchEmojiPacksIfAdmin"
|
||||||
|
>
|
||||||
|
<template #trigger>
|
||||||
|
<StillImage v-bind="$attrs" />
|
||||||
|
</template>
|
||||||
|
<template #content>
|
||||||
|
<div class="emoji-popover">
|
||||||
|
<h3>{{ $attrs.title }}</h3>
|
||||||
|
|
||||||
|
<div class="emoji-popover-centered">
|
||||||
|
<StillImage
|
||||||
|
class="emoji"
|
||||||
|
v-bind="$attrs"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isUserAdmin && !isLocal">
|
||||||
|
<button
|
||||||
|
class="button button-default btn emoji-popover-button"
|
||||||
|
type="button"
|
||||||
|
@click="copyToLocalPack"
|
||||||
|
:disabled="packName == ''"
|
||||||
|
>
|
||||||
|
{{ $t('admin_dash.emoji.copy_to_pack') }}
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<SelectComponent
|
||||||
|
v-model="packName"
|
||||||
|
>
|
||||||
|
<option
|
||||||
|
value=""
|
||||||
|
disabled
|
||||||
|
hidden
|
||||||
|
>
|
||||||
|
{{ $t('admin_dash.emoji.emoji_pack') }}
|
||||||
|
</option>
|
||||||
|
<option
|
||||||
|
v-for="(pack, listPackName) in knownLocalPacks"
|
||||||
|
:key="listPackName"
|
||||||
|
:label="listPackName"
|
||||||
|
>
|
||||||
|
{{ listPackName }}
|
||||||
|
</option>
|
||||||
|
</SelectComponent>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Popover>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { assign } from 'lodash'
|
||||||
|
|
||||||
|
import StillImage from './still-image.vue'
|
||||||
|
import Popover from 'components/popover/popover.vue'
|
||||||
|
import SelectComponent from 'components/select/select.vue'
|
||||||
|
import { useInterfaceStore } from 'src/stores/interface'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { StillImage, Popover, SelectComponent },
|
||||||
|
props: {
|
||||||
|
shortcode: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
isLocal: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
knownLocalPacks: { },
|
||||||
|
packName: ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isUserAdmin () {
|
||||||
|
return this.$store.state.users.currentUser.rights.admin
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
displayError (msg) {
|
||||||
|
useInterfaceStore().pushGlobalNotice({
|
||||||
|
messageKey: 'admin_dash.emoji.error',
|
||||||
|
messageArgs: [msg],
|
||||||
|
level: 'error'
|
||||||
|
})
|
||||||
|
},
|
||||||
|
copyToLocalPack() {
|
||||||
|
this.$store.state.api.backendInteractor.addNewEmojiFile({
|
||||||
|
packName: this.packName,
|
||||||
|
file: this.$attrs.src,
|
||||||
|
shortcode: this.shortcode,
|
||||||
|
filename: ""
|
||||||
|
}).then(resp => resp.json()).then(resp => {
|
||||||
|
if (resp.error !== undefined) {
|
||||||
|
this.displayError(resp.error)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
useInterfaceStore().pushGlobalNotice({
|
||||||
|
messageKey: 'admin_dash.emoji.copied_successfully',
|
||||||
|
messageArgs: [this.shortcode, this.packName],
|
||||||
|
level: 'success'
|
||||||
|
})
|
||||||
|
|
||||||
|
this.$refs.emojiPopover.hidePopover()
|
||||||
|
this.packName = ''
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// Copied from emoji_tab.js
|
||||||
|
loadPacksPaginated (listFunction) {
|
||||||
|
const pageSize = 25
|
||||||
|
const allPacks = {}
|
||||||
|
|
||||||
|
return listFunction({ instance: this.$store.state.instance.server, page: 1, pageSize: 0 })
|
||||||
|
.then(data => data.json())
|
||||||
|
.then(data => {
|
||||||
|
if (data.error !== undefined) { return Promise.reject(data.error) }
|
||||||
|
|
||||||
|
let resultingPromise = Promise.resolve({})
|
||||||
|
for (let i = 0; i < Math.ceil(data.count / pageSize); i++) {
|
||||||
|
resultingPromise = resultingPromise.then(() => listFunction({ instance: this.$store.state.instance.server, page: i, pageSize })
|
||||||
|
).then(data => data.json()).then(pageData => {
|
||||||
|
if (pageData.error !== undefined) { return Promise.reject(pageData.error) }
|
||||||
|
|
||||||
|
assign(allPacks, pageData.packs)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return resultingPromise
|
||||||
|
})
|
||||||
|
.then(() => allPacks)
|
||||||
|
.catch(data => {
|
||||||
|
this.displayError(data)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
fetchEmojiPacksIfAdmin() {
|
||||||
|
if (!this.isUserAdmin) return
|
||||||
|
|
||||||
|
this.loadPacksPaginated(this.$store.state.api.backendInteractor.listEmojiPacks)
|
||||||
|
.then(allPacks => {
|
||||||
|
// Sort by key
|
||||||
|
const sorted = Object.keys(allPacks).sort().reduce((acc, key) => {
|
||||||
|
if (key.length === 0) return acc
|
||||||
|
acc[key] = allPacks[key]
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
this.knownLocalPacks = sorted
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.emoji-popover {
|
||||||
|
margin: 0 0.5em 0.5em;
|
||||||
|
text-align: center;
|
||||||
|
|
||||||
|
.emoji {
|
||||||
|
width: 4.6em;
|
||||||
|
height: 4.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-popover-centered {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.emoji-popover-button {
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.Select {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -1205,6 +1205,8 @@
|
||||||
"adding_new": "Adding new emoji",
|
"adding_new": "Adding new emoji",
|
||||||
"shortcode": "Shortcode",
|
"shortcode": "Shortcode",
|
||||||
"filename": "Filename",
|
"filename": "Filename",
|
||||||
|
"emoji_source": "Emoji file source",
|
||||||
|
"upload_url": "Upload from URL",
|
||||||
"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}?",
|
||||||
|
|
@ -1215,10 +1217,14 @@
|
||||||
"download_as_name_full": "New name, leave blank to reuse",
|
"download_as_name_full": "New name, leave blank to reuse",
|
||||||
"files": "Files",
|
"files": "Files",
|
||||||
"editing": "Editing {0}",
|
"editing": "Editing {0}",
|
||||||
|
"copying": "Copying {0}",
|
||||||
|
"copy_to": "Copy to",
|
||||||
|
"copy_to_pack": "Copy to local pack",
|
||||||
"delete_title": "Delete?",
|
"delete_title": "Delete?",
|
||||||
"metadata_changed": "Metadata different from saved",
|
"metadata_changed": "Metadata different from saved",
|
||||||
"emoji_changed": "Unsaved emoji file changes, check highlighted emoji",
|
"emoji_changed": "Unsaved emoji file changes, check highlighted emoji",
|
||||||
"replace_warning": "This will REPLACE the local pack of the same name"
|
"replace_warning": "This will REPLACE the local pack of the same name",
|
||||||
|
"copied_successfully": "Successfully copied emoji \"{0}\" to pack \"{1}\""
|
||||||
},
|
},
|
||||||
"temp_overrides": {
|
"temp_overrides": {
|
||||||
":pleroma": {
|
":pleroma": {
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,7 @@ describe('RichContent', () => {
|
||||||
const html = p('Ebin :DDDD :spurdo:')
|
const html = p('Ebin :DDDD :spurdo:')
|
||||||
const expected = p(
|
const expected = p(
|
||||||
'Ebin :DDDD ',
|
'Ebin :DDDD ',
|
||||||
'<anonymous-stub src="about:blank" alt=":spurdo:" class="emoji img" title=":spurdo:"></anonymous-stub>'
|
'<anonymous-stub shortcode="spurdo" islocal="true" class="emoji img" src="about:blank" title=":spurdo:" alt=":spurdo:"></anonymous-stub>'
|
||||||
)
|
)
|
||||||
|
|
||||||
const wrapper = shallowMount(RichContent, {
|
const wrapper = shallowMount(RichContent, {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue