diff --git a/src/api/emojiPacks.js b/src/api/emojiPacks.js
index cc07b1b6f28fe9a987f203860f9381808670fc75..61319cec44d099eb689b9d107492e49580ee3a4c 100644
--- a/src/api/emojiPacks.js
+++ b/src/api/emojiPacks.js
@@ -2,40 +2,86 @@ import request from '@/utils/request'
 import { getToken } from '@/utils/auth'
 import { baseName } from './utils'
 
-import _ from 'lodash'
+export async function addNewEmojiFile(packName, file, shortcode, filename, host, token) {
+  const data = new FormData()
+  if (filename.trim() !== '') {
+    data.set('filename', filename)
+  }
+  if (shortcode.trim() !== '') {
+    data.set('shortcode', shortcode)
+  }
+  data.set('file', file)
 
-export async function deletePack(host, token, name) {
   return await request({
     baseURL: baseName(host),
-    url: `/api/pleroma/emoji/packs/${name}`,
-    method: 'delete',
-    headers: authHeaders(token)
+    url: `/api/pleroma/emoji/packs/${packName}/files`,
+    method: 'post',
+    headers: authHeaders(token),
+    data
   })
 }
 
-export async function reloadEmoji(host, token) {
+export function addressOfEmojiInPack(host, packName, name) {
+  return `${baseName(host)}/emoji/${packName}/${name}`
+}
+
+export async function createPack(host, token, packName) {
   return await request({
     baseURL: baseName(host),
-    url: '/api/pleroma/admin/reload_emoji',
+    url: `/api/pleroma/emoji/packs/${packName}`,
     method: 'post',
     headers: authHeaders(token)
   })
 }
 
-export async function importFromFS(host, token) {
+export async function deleteEmojiFile(packName, shortcode, host, token) {
+  return await request({
+    baseURL: baseName(host),
+    url: `/api/pleroma/emoji/packs/${packName}/files`,
+    method: 'delete',
+    headers: authHeaders(token),
+    data: { shortcode }
+  })
+}
+
+export async function deletePack(host, token, packName) {
   return await request({
     baseURL: baseName(host),
-    url: '/api/pleroma/emoji/packs/import_from_fs',
+    url: `/api/pleroma/emoji/packs/${packName}`,
+    method: 'delete',
+    headers: authHeaders(token)
+  })
+}
+
+export async function downloadFrom(host, instance, packName, as, token) {
+  if (as.trim() === '') {
+    as = null
+  }
+
+  return await request({
+    baseURL: baseName(host),
+    url: '/api/pleroma/emoji/packs/download',
     method: 'post',
+    headers: authHeaders(token),
+    data: { url: baseName(instance), name: packName, as },
+    timeout: 0
+  })
+}
+
+export async function fetchPack(packName, host, token) {
+  return await request({
+    baseURL: baseName(host),
+    url: `/api/pleroma/emoji/packs/${packName}`,
+    method: 'get',
     headers: authHeaders(token)
   })
 }
 
-export async function createPack(host, token, name) {
+export async function importFromFS(host, token) {
   return await request({
     baseURL: baseName(host),
-    url: `/api/pleroma/emoji/packs/${name}`,
-    method: 'put',
+    url: '/api/pleroma/emoji/packs/import',
+    method: 'get',
     headers: authHeaders(token)
   })
 }
@@ -51,106 +97,40 @@ export async function listPacks(host) {
 export async function listRemotePacks(host, token, instance) {
   return await request({
     baseURL: baseName(host),
-    url: `/api/pleroma/emoji/packs/list_from`,
-    method: 'post',
-    headers: authHeaders(token),
-    data: { instance_address: baseName(instance) }
+    url: `/api/pleroma/emoji/packs/remote?url=${baseName(instance)}`,
+    method: 'get',
+    headers: authHeaders(token)
   })
 }
 
-export async function downloadFrom(host, instance_address, pack_name, as, token) {
-  if (as.trim() === '') {
-    as = null
-  }
-
+export async function reloadEmoji(host, token) {
   return await request({
     baseURL: baseName(host),
-    url: '/api/pleroma/emoji/packs/download_from',
+    url: '/api/pleroma/admin/reload_emoji',
     method: 'post',
-    headers: authHeaders(token),
-    data: { instance_address: baseName(instance_address), pack_name, as },
-    timeout: 0
+    headers: authHeaders(token)
   })
 }
 
-export async function savePackMetadata(host, token, name, new_data) {
+export async function savePackMetadata(host, token, packName, metadata) {
   return await request({
     baseURL: baseName(host),
-    url: `/api/pleroma/emoji/packs/${name}/update_metadata`,
-    method: 'post',
+    url: `/api/pleroma/emoji/packs/${packName}`,
+    method: 'patch',
     headers: authHeaders(token),
-    data: { name, new_data },
+    data: { metadata },
     timeout: 0 // This might take a long time
   })
 }
 
-function fileUpdateFormData(d) {
-  const data = new FormData()
-
-  _.each(d, (v, k) => {
-    data.set(k, v)
-  })
-
-  return data
-}
-
-export async function updatePackFile(host, token, args) {
-  let data = null
-
-  switch (args.action) {
-    case 'add': {
-      const { shortcode, file, fileName } = args
-
-      data = fileUpdateFormData({
-        action: 'add',
-        shortcode: shortcode,
-        file: file
-      })
-      if (fileName.trim() !== '') {
-        data.set('filename', fileName)
-      }
-
-      break
-    }
-
-    case 'update': {
-      const { oldName, newName, newFilename } = args
-
-      data = fileUpdateFormData({
-        action: 'update',
-        shortcode: oldName,
-        new_shortcode: newName,
-        new_filename: newFilename
-      })
-
-      break
-    }
-
-    case 'remove': {
-      const { name } = args
-      data = fileUpdateFormData({
-        action: 'remove',
-        shortcode: name
-      })
-
-      break
-    }
-  }
-
-  const { packName } = args
-
+export async function updateEmojiFile(packName, shortcode, newShortcode, newFilename, force, host, token) {
   return await request({
     baseURL: baseName(host),
-    url: `/api/pleroma/emoji/packs/${packName}/update_file`,
-    method: 'post',
+    url: `/api/pleroma/emoji/packs/${packName}/files`,
+    method: 'patch',
     headers: authHeaders(token),
-    data: data,
-    timeout: 0
+    data: { shortcode, new_shortcode: newShortcode, new_filename: newFilename, force }
   })
 }
 
-export function addressOfEmojiInPack(host, packName, name) {
-  return `${baseName(host)}/emoji/${packName}/${name}`
-}
-
 const authHeaders = (token) => token ? { 'Authorization': `Bearer ${getToken()}` } : {}
diff --git a/src/store/modules/emojiPacks.js b/src/store/modules/emojiPacks.js
index f92e0fa533338989b801f4a5ca7cb7cf65fd0492..e4748c2644a3b91864477ed082b87834a9fcfb0f 100644
--- a/src/store/modules/emojiPacks.js
+++ b/src/store/modules/emojiPacks.js
@@ -1,13 +1,16 @@
 import {
+  addNewEmojiFile,
+  createPack,
+  deleteEmojiFile,
+  deletePack,
+  downloadFrom,
+  importFromFS,
   listPacks,
   listRemotePacks,
-  downloadFrom,
   reloadEmoji,
-  createPack,
-  deletePack,
   savePackMetadata,
-  importFromFS,
-  updatePackFile } from '@/api/emojiPacks'
+  updateEmojiFile
+} from '@/api/emojiPacks'
 import i18n from '@/lang'
 import { Message } from 'element-ui'
 
@@ -49,6 +52,36 @@ const packs = {
     }
   },
   actions: {
+    async AddNewEmojiFile({ commit, getters }, { packName, file, shortcode, filename }) {
+      let result
+      try {
+        result = await addNewEmojiFile(packName, file, shortcode, filename, getters.authHost, getters.token)
+      } catch (_e) {
+        return
+      }
+      Message({
+        message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`,
+        type: 'success',
+        duration: 5 * 1000
+      })
+
+      commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data })
+    },
+    async DeleteEmojiFile({ commit, getters }, { packName, shortcode }) {
+      let result
+      try {
+        result = await deleteEmojiFile(packName, shortcode, getters.authHost, getters.token)
+      } catch (_e) {
+        return
+      }
+      Message({
+        message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`,
+        type: 'success',
+        duration: 5 * 1000
+      })
+
+      commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data })
+    },
     async CreatePack({ getters }, { name }) {
       await createPack(getters.authHost, getters.token, name)
     },
@@ -116,20 +149,23 @@ const packs = {
       commit('SET_REMOTE_INSTANCE', remoteInstance)
       commit('SET_REMOTE_PACKS', data)
     },
-    async UpdateAndSavePackFile({ commit, getters }, args) {
-      const result = await updatePackFile(getters.authHost, getters.token, args)
-
-      if (result.status === 200) {
-        const { packName } = args
-
-        Message({
-          message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`,
-          type: 'success',
-          duration: 5 * 1000
-        })
-
-        commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data })
+    SetRemoteInstance({ commit }, instance) {
+      commit('SET_REMOTE_INSTANCE', instance)
+    },
+    async UpdateEmojiFile({ commit, getters }, { packName, shortcode, newShortcode, newFilename, force }) {
+      let result
+      try {
+        result = await updateEmojiFile(packName, shortcode, newShortcode, newFilename, force, getters.authHost, getters.token)
+      } catch (_e) {
+        return
       }
+      Message({
+        message: `${i18n.t('settings.successfullyUpdated')} ${packName} ${i18n.t('settings.metadatLowerCase')}`,
+        type: 'success',
+        duration: 5 * 1000
+      })
+
+      commit('UPDATE_LOCAL_PACK_FILES', { name: packName, files: result.data })
     },
     async UpdateLocalPackVal({ commit }, args) {
       commit('UPDATE_LOCAL_PACK_VAL', args)
diff --git a/src/views/emojiPacks/components/LocalEmojiPack.vue b/src/views/emojiPacks/components/LocalEmojiPack.vue
index 917ff4dd52d4a6609dc3ffad013473ada9803dcb..c03ba580d10dc5d04f6354e88dbb8710da7fc15b 100644
--- a/src/views/emojiPacks/components/LocalEmojiPack.vue
+++ b/src/views/emojiPacks/components/LocalEmojiPack.vue
@@ -44,11 +44,11 @@
       </el-collapse-item>
       <el-collapse-item v-if="Object.keys(pack.files).length > 0" :title=" $t('emoji.manageEmoji')" name="manageEmoji" class="no-background">
         <single-emoji-editor
-          v-for="(file, ename) in pack.files"
-          :key="ename"
+          v-for="(file, shortcode) in pack.files"
+          :key="shortcode"
           :host="host"
           :pack-name="name"
-          :name="ename"
+          :shortcode="shortcode"
           :file="file"
           :is-local="isLocal" />
       </el-collapse-item>
@@ -96,9 +96,9 @@ export default {
       if (this.isMobile) {
         return '90px'
       } else if (this.isTablet) {
-        return '120px'
+        return '155px'
       } else {
-        return '120px'
+        return '155px'
       }
     },
     share: {
diff --git a/src/views/emojiPacks/components/NewEmojiUploader.vue b/src/views/emojiPacks/components/NewEmojiUploader.vue
index f364b49e2918b5e1e31bc215d614ec57c677dd5f..5229e566e9c2fb36105b9aa9050714cbbbe7bf98 100644
--- a/src/views/emojiPacks/components/NewEmojiUploader.vue
+++ b/src/views/emojiPacks/components/NewEmojiUploader.vue
@@ -1,7 +1,7 @@
 <template>
   <el-form :label-position="isMobile ? 'top' : 'left'" label-width="130px" size="small" class="new-emoji-uploader-form">
     <el-form-item :label="$t('emoji.shortcode')">
-      <el-input v-model="shortcode" :placeholder="$t('emoji.required')"/>
+      <el-input v-model="shortcode" :placeholder="$t('emoji.optional')"/>
     </el-form-item>
     <el-form-item :label="$t('emoji.customFilename')">
       <el-input v-model="customFileName" :placeholder="$t('emoji.optional')"/>
@@ -9,7 +9,7 @@
     <el-form-item :label="$t('emoji.uploadFile')">
       <div class="upload-file-url">
         <el-input v-model="imageUploadURL" :placeholder="$t('emoji.url')"/>
-        <el-button :disabled="shortcodePresent" type="primary" class="upload-button" @click="uploadEmoji">{{ $t('emoji.upload') }}</el-button>
+        <el-button type="primary" class="upload-button" @click="uploadEmoji">{{ $t('emoji.upload') }}</el-button>
       </div>
       <div class="upload-container">
         <p class="text">or</p>
@@ -18,7 +18,7 @@
           :multiple="false"
           :show-file-list="false"
           action="add">
-          <el-button :disabled="shortcodePresent" type="primary">{{ $t('emoji.clickToUpload') }}</el-button>
+          <el-button type="primary">{{ $t('emoji.clickToUpload') }}</el-button>
         </el-upload>
       </div>
     </el-form-item>
@@ -46,26 +46,25 @@ export default {
     },
     isMobile() {
       return this.$store.state.app.device === 'mobile'
-    },
-    shortcodePresent() {
-      return this.shortcode.trim() === ''
     }
   },
   methods: {
-    uploadEmoji({ file }) {
-      this.$store.dispatch('UpdateAndSavePackFile', {
-        action: 'add',
-        packName: this.packName,
-        shortcode: this.shortcode,
-        file: file || this.imageUploadURL,
-        fileName: this.customFileName
-      }).then(() => {
-        this.shortcode = ''
-        this.imageUploadURL = ''
-        this.customFileName = ''
+    async uploadEmoji({ file }) {
+      try {
+        this.$store.dispatch('AddNewEmojiFile', {
+          packName: this.packName,
+          file: file || this.imageUploadURL,
+          shortcode: this.shortcode,
+          filename: this.customFileName
+        })
+      } catch (e) {
+        return
+      }
+      this.shortcode = ''
+      this.imageUploadURL = ''
+      this.customFileName = ''
 
-        this.$store.dispatch('ReloadEmoji')
-      })
+      this.$store.dispatch('ReloadEmoji')
     }
   }
 }
diff --git a/src/views/emojiPacks/components/RemoteEmojiPack.vue b/src/views/emojiPacks/components/RemoteEmojiPack.vue
index 0c9ecaf3f59639ac16c9a59b5efb683d54363286..0f31d88ccf09c05df76e19f3e52665dbdbfb6af2 100644
--- a/src/views/emojiPacks/components/RemoteEmojiPack.vue
+++ b/src/views/emojiPacks/components/RemoteEmojiPack.vue
@@ -36,11 +36,11 @@
       <el-collapse v-model="showPackContent" class="contents-collapse">
         <el-collapse-item v-if="Object.keys(pack.files).length > 0" :title=" $t('emoji.manageEmoji')" name="manageEmoji" class="no-background">
           <single-emoji-editor
-            v-for="(file, ename) in pack.files"
-            :key="ename"
+            v-for="(file, shortcode) in pack.files"
+            :key="shortcode"
             :host="host"
             :pack-name="name"
-            :name="ename"
+            :shortcode="shortcode"
             :file="file"
             :is-local="isLocal" />
         </el-collapse-item>
@@ -52,7 +52,7 @@
           </p>
           <div class="download-shared-pack">
             <el-input v-model="downloadSharedAs" :placeholder=" $t('emoji.downloadAsOptional')"/>
-            <el-button type="primary" class="download-shared-pack-button" @click="downloadFromInstance(pack.pack['homepage'])">
+            <el-button type="primary" class="download-shared-pack-button" @click="downloadFromInstance">
               {{ isDesktop ? $t('emoji.downloadSharedPack') : $t('emoji.downloadSharedPackMobile') }}
             </el-button>
           </div>
@@ -113,6 +113,9 @@ export default {
     loadRemotePack() {
       return this.$store.state.emojiPacks.activeCollapseItems.includes(this.name)
     },
+    remoteInstanceAddress() {
+      return this.$store.state.emojiPacks.remoteInstance
+    },
     share: {
       get() { return this.pack.pack['share-files'] },
       set(value) {
@@ -171,11 +174,10 @@ export default {
     }
   },
   methods: {
-    downloadFromInstance(url) {
-      const instanceAddress = `${new URL(url).protocol}//${new URL(url).hostname}`
+    downloadFromInstance() {
       this.$store.dispatch(
         'DownloadFrom',
-        { instanceAddress, packName: this.name, as: this.downloadSharedAs }
+        { instanceAddress: this.remoteInstanceAddress, packName: this.name, as: this.downloadSharedAs }
       ).then(() => this.$store.dispatch('ReloadEmoji'))
         .then(() => this.$store.dispatch('SetLocalEmojiPacks'))
     }
diff --git a/src/views/emojiPacks/components/SingleEmojiEditor.vue b/src/views/emojiPacks/components/SingleEmojiEditor.vue
index cd0eeb7fc8a8dca0f095d9a58f6d3444c4795518..bb82a2989079e043b90e13ecfeaee8f24d5b37c6 100644
--- a/src/views/emojiPacks/components/SingleEmojiEditor.vue
+++ b/src/views/emojiPacks/components/SingleEmojiEditor.vue
@@ -34,6 +34,7 @@
         <el-button
           :disabled="!copyToLocalPackName"
           type="primary"
+          class="copy-to-local-pack-button"
           @click="copyToLocal">{{ $t('emoji.copy') }}</el-button>
         <el-button slot="reference" type="primary" class="emoji-button">{{ $t('emoji.copyToLocalPack') }}</el-button>
       </el-popover>
@@ -54,7 +55,7 @@ export default {
       type: String,
       required: true
     },
-    name: {
+    shortcode: {
       type: String,
       required: true
     },
@@ -69,7 +70,7 @@ export default {
   },
   data() {
     return {
-      newName: null,
+      newShortcode: null,
       newFile: null,
       copyToLocalPackName: null,
       copyPopoverVisible: false,
@@ -80,14 +81,14 @@ export default {
   computed: {
     emojiName: {
       get() {
-        // Return a modified name if it was modified, otherwise return the old name
-        return this.newName !== null ? this.newName : this.name
+        // Return a modified shortcode if it was modified, otherwise return the old shortcode
+        return this.newShortcode !== null ? this.newShortcode : this.shortcode
       },
-      set(val) { this.newName = val }
+      set(val) { this.newShortcode = val }
     },
     emojiFile: {
       get() {
-        // Return a modified name if it was modified, otherwise return the old name
+        // Return a modified file name if it was modified, otherwise return the old file name
         return this.newFile !== null ? this.newFile : this.file
       },
       set(val) { this.newFile = val }
@@ -102,23 +103,26 @@ export default {
       return this.$store.state.emojiPacks.localPacks
     },
     remoteInstance() {
-      return this.$store.state.emojiPacks.remoteInstance
+      return new URL(this.$store.state.emojiPacks.remoteInstance).host
     }
   },
   methods: {
-    update() {
-      this.$store.dispatch('UpdateAndSavePackFile', {
-        action: 'update',
-        packName: this.packName,
-        oldName: this.name,
-        newName: this.emojiName,
-        newFilename: this.emojiFile
-      }).then(() => {
-        this.newName = null
-        this.newFile = null
+    async update() {
+      try {
+        this.$store.dispatch('UpdateEmojiFile', {
+          packName: this.packName,
+          shortcode: this.shortcode,
+          newShortcode: this.emojiName,
+          newFilename: this.emojiFile,
+          force: true
+        })
+      } catch (e) {
+        return
+      }
+      this.newShortcode = null
+      this.newFile = null
 
-        this.$store.dispatch('ReloadEmoji')
-      })
+      this.$store.dispatch('ReloadEmoji')
     },
     remove() {
       this.$confirm('This will delete the emoji, are you sure?', 'Warning', {
@@ -126,12 +130,11 @@ export default {
         cancelButtonText: 'No, leave it be',
         type: 'warning'
       }).then(() => {
-        this.$store.dispatch('UpdateAndSavePackFile', {
-          action: 'remove',
+        this.$store.dispatch('DeleteEmojiFile', {
           packName: this.packName,
-          name: this.name
+          shortcode: this.shortcode
         }).then(() => {
-          this.newName = null
+          this.newShortcode = null
           this.newFile = null
 
           this.$store.dispatch('ReloadEmoji')
@@ -139,20 +142,22 @@ export default {
       })
     },
     copyToLocal() {
-      this.$store.dispatch('UpdateAndSavePackFile', {
-        action: 'add',
-        packName: this.copyToLocalPackName,
-        shortcode: this.copyToShortcode.trim() !== '' ? this.copyToShortcode.trim() : this.name,
-        fileName: this.copyToFilename.trim() !== '' ? this.copyToFilename.trim() : this.file,
-        file: this.addressOfEmojiInPack(this.host, this.packName, this.file)
-      }).then(() => {
-        this.copyToLocalPackName = null
-        this.copyToLocalVisible = false
-        this.copyToShortcode = ''
-        this.copyToFilename = ''
+      try {
+        this.$store.dispatch('AddNewEmojiFile', {
+          packName: this.copyToLocalPackName,
+          file: this.addressOfEmojiInPack(this.remoteInstance, this.packName, this.file),
+          shortcode: this.copyToShortcode.trim() !== '' ? this.copyToShortcode.trim() : this.shortcode,
+          filename: this.copyToFilename.trim() !== '' ? this.copyToFilename.trim() : this.file
+        })
+      } catch (e) {
+        return
+      }
+      this.copyToLocalPackName = null
+      this.copyToLocalVisible = false
+      this.copyToShortcode = ''
+      this.copyToFilename = ''
 
-        this.$store.dispatch('ReloadEmoji')
-      })
+      this.$store.dispatch('ReloadEmoji')
     },
     addressOfEmojiInPack
   }
@@ -163,6 +168,10 @@ export default {
 .copy-popover {
   width: 330px
 }
+.copy-to-local-pack-button {
+  margin-top: 15px;
+  float: right;
+}
 .emoji-buttons {
   place-self: center;
   min-width: 200px
diff --git a/src/views/emojiPacks/index.vue b/src/views/emojiPacks/index.vue
index a66507fef01bbbe1022660480f32dc42df332e22..20bfe6ce254f3cf97192588d35c6445d2c801a98 100644
--- a/src/views/emojiPacks/index.vue
+++ b/src/views/emojiPacks/index.vue
@@ -69,7 +69,6 @@ export default {
   components: { LocalEmojiPack, RebootButton, RemoteEmojiPack },
   data() {
     return {
-      remoteInstanceAddress: '',
       newPackName: '',
       activeLocalPack: [],
       activeRemotePack: [],
@@ -95,6 +94,14 @@ export default {
     localPacks() {
       return this.$store.state.emojiPacks.localPacks
     },
+    remoteInstanceAddress: {
+      get() {
+        return this.$store.state.emojiPacks.remoteInstance
+      },
+      set(instance) {
+        this.$store.dispatch('SetRemoteInstance', instance)
+      }
+    },
     remotePacks() {
       return this.$store.state.emojiPacks.remotePacks
     }