pleroma-fe/src/components/settings_modal/admin_tabs/emoji_tab.js

316 lines
9.6 KiB
JavaScript

import { clone, assign } from 'lodash'
import TabSwitcher from 'src/components/tab_switcher/tab_switcher.jsx'
import StringSetting from '../helpers/string_setting.vue'
import Checkbox from 'components/checkbox/checkbox.vue'
import StillImage from 'components/still-image/still-image.vue'
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: [] }
const EmojiTab = {
components: {
TabSwitcher,
StringSetting,
Checkbox,
StillImage,
Select,
Popover,
ConfirmModal,
ModifiedIndicator
},
data () {
return {
knownLocalPacks: { },
knownRemotePacks: { },
editedParts: { },
editedMetadata: { },
packName: '',
newPackName: '',
deleteModalVisible: false,
newEmojiUpload: clone(newEmojiUploadBase),
remotePackInstance: '',
remotePackDownloadAs: ''
}
},
computed: {
pack () {
return this.packName !== '' ? this.knownPacks[this.packName] : undefined
},
packMeta () {
if (this.editedMetadata[this.packName] === undefined) {
this.editedMetadata[this.packName] = clone(this.pack.pack)
}
return this.editedMetadata[this.packName]
},
knownPacks () {
// Copy the object itself but not the children, so they are still passed by reference and modified
const result = clone(this.knownLocalPacks)
for (const instName in this.knownRemotePacks) {
for (const instPack in this.knownRemotePacks[instName]) {
result[`${instPack}@${instName}`] = this.knownRemotePacks[instName][instPack]
}
}
return result
}
},
methods: {
reloadEmoji () {
this.$store.state.api.backendInteractor.reloadEmoji()
},
importFromFS () {
this.$store.state.api.backendInteractor.importEmojiFromFS()
},
emojiAddr (name) {
if (this.pack.remote !== undefined) {
// Remote pack
return `${this.pack.remote.instance}/emoji/${encodeURIComponent(this.pack.remote.baseName)}/${name}`
} else {
return `${this.$store.state.instance.server}/emoji/${encodeURIComponent(this.packName)}/${name}`
}
},
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 }
).then(resp => resp.json()).then(resp => {
if (resp === 'ok') {
return this.refreshPackList()
} else {
this.displayError(resp.error)
return Promise.reject(resp)
}
}).then(done => {
this.$refs.createPackPopover.hidePopover()
this.packName = this.newPackName
this.newPackName = ''
})
},
deleteEmojiPack () {
this.$store.state.api.backendInteractor.deleteEmojiPack(
{ name: this.packName }
).then(resp => resp.json()).then(resp => {
if (resp === 'ok') {
return this.refreshPackList()
} else {
this.displayError(resp.error)
return Promise.reject(resp)
}
}).then(done => {
delete this.editedMetadata[this.packName]
delete this.editedParts[this.packName]
this.deleteModalVisible = false
this.packName = ''
})
},
metaEdited (prop) {
return this.pack && this.packMeta[prop] !== this.pack.pack[prop]
},
savePackMetadata () {
this.$store.state.api.backendInteractor.saveEmojiPackMetadata({ name: this.packName, newData: this.packMeta }).then(
resp => resp.json()
).then(resp => {
if (resp.error !== undefined) {
this.displayError(resp.error)
return
}
// Update actual pack data
this.pack.pack = resp
// Delete edited pack data, should auto-update itself
delete this.editedMetadata[this.packName]
})
},
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)
})
},
saveEditedEmoji (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
}
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)
})
},
loadPacksPaginated (listFunction) {
const pageSize = 25
const allPacks = {}
return listFunction({ instance: this.remotePackInstance, 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.remotePackInstance, 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(finished => allPacks)
.catch(data => {
this.displayError(data)
})
},
refreshPackList () {
this.loadPacksPaginated(this.$store.state.api.backendInteractor.listEmojiPacks)
.then(allPacks => {
this.knownLocalPacks = allPacks
for (const name of Object.keys(this.knownLocalPacks)) {
this.sortPackFiles(name)
}
})
},
listRemotePacks () {
this.loadPacksPaginated(this.$store.state.api.backendInteractor.listRemoteEmojiPacks)
.then(allPacks => {
let inst = this.remotePackInstance
if (!inst.startsWith('http')) { inst = 'https://' + inst }
const instUrl = new URL(inst)
inst = instUrl.host
for (const packName in allPacks) {
allPacks[packName].remote = {
baseName: packName,
instance: instUrl.origin
}
}
this.knownRemotePacks[inst] = allPacks
for (const pack in this.knownRemotePacks[inst]) {
this.sortPackFiles(`${pack}@${inst}`)
}
this.$refs.remotePackPopover.hidePopover()
})
.catch(data => {
this.displayError(data)
})
},
downloadRemotePack () {
if (this.remotePackDownloadAs.trim() === '') {
this.remotePackDownloadAs = this.pack.remote.baseName
}
this.$store.state.api.backendInteractor.downloadRemoteEmojiPack({
instance: this.pack.remote.instance, packName: this.pack.remote.baseName, as: this.remotePackDownloadAs
})
.then(data => data.json())
.then(resp => {
if (resp === 'ok') {
this.$refs.dlPackPopover.hidePopover()
return this.refreshPackList()
} else {
this.displayError(resp.error)
return Promise.reject(resp)
}
}).then(done => {
this.packName = this.remotePackDownloadAs
this.remotePackDownloadAs = ''
})
},
displayError (msg) {
this.$store.dispatch('pushGlobalNotice', {
messageKey: 'admin_dash.emoji.error',
messageArgs: [msg],
level: 'error'
})
},
sortPackFiles (nameOfPack) {
// Sort by key
const sorted = Object.keys(this.knownPacks[nameOfPack].files).sort().reduce((acc, key) => {
if (key.length === 0) return acc
acc[key] = this.knownPacks[nameOfPack].files[key]
return acc
}, {})
this.knownPacks[nameOfPack].files = sorted
}
},
mounted () {
this.refreshPackList()
}
}
export default EmojiTab