diff --git a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue
index 615a06d4e..edafd98d3 100644
--- a/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue
+++ b/apps/app-frontend/src/components/ui/skin/EditSkinModal.vue
@@ -26,7 +26,7 @@
Texture
-
@@ -85,9 +85,6 @@
Cancel
-
- Delete
-
@@ -231,19 +228,35 @@ function show(e: MouseEvent, skin?: Skin) {
modal.value?.show(e)
}
+function showNew(e: MouseEvent, skinTexture: Uint8Array, filename: string) {
+ mode.value = 'new'
+ currentSkin.value = null
+ fileUploadTextureBlob.value = skinTexture
+ fileName.value = filename
+ variant.value = 'CLASSIC'
+ selectedCape.value = undefined
+ visibleCapeList.value = []
+ initVisibleCapeList()
+ modal.value?.show(e)
+}
+
+function restoreWithNewTexture(skinTexture: Uint8Array, filename: string) {
+ fileUploadTextureBlob.value = skinTexture
+ fileName.value = filename
+
+ if (shouldRestoreModal.value) {
+ setTimeout(() => {
+ modal.value?.show()
+ shouldRestoreModal.value = false
+ }, 0)
+ }
+}
+
function hide() {
modal.value?.hide()
setTimeout(() => resetState(), 250)
}
-async function onTextureSelected(files: FileList|null) {
- if (!files?.length) return
- const file = files[0]
- fileName.value = file.name
- const buf = await file.arrayBuffer()
- fileUploadTextureBlob.value = new Uint8Array(buf)
-}
-
function selectCape(cape: Cape|undefined) {
if (cape && selectedCape.value?.id !== cape.id) {
const isInVisibleList = visibleCapeList.value.some(c => c.id === cape.id)
@@ -298,17 +311,10 @@ function openSelectCapeModal(e: MouseEvent) {
}, 0)
}
-async function handleDelete() {
- try {
- if (currentSkin.value?.is_equipped) {
- await unequip_skin()
- }
- await remove_custom_skin(currentSkin.value!)
- emit('deleted', currentSkin.value!)
- hide()
- } catch (err) {
- handleError(err)
- }
+function openUploadSkinModal(e: MouseEvent) {
+ shouldRestoreModal.value = true
+ modal.value?.hide()
+ emit('open-upload-modal', e)
}
async function save() {
@@ -345,9 +351,16 @@ watch(() => props.capes, () => {
}, { immediate: true })
const emit = defineEmits<{
- (e:'saved'):void
- (e:'deleted', skin: Skin):void
+ (event: 'saved'): void
+ (event: 'deleted', skin: Skin): void
+ (event: 'open-upload-modal', mouseEvent: MouseEvent): void
}>()
-defineExpose({ show, hide })
+defineExpose({
+ show,
+ showNew,
+ restoreWithNewTexture,
+ hide,
+ shouldRestoreModal
+})
diff --git a/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue b/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue
new file mode 100644
index 000000000..e798031a0
--- /dev/null
+++ b/apps/app-frontend/src/components/ui/skin/UploadSkinModal.vue
@@ -0,0 +1,101 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/app-frontend/src/pages/Skins.vue b/apps/app-frontend/src/pages/Skins.vue
index c208cbd2d..ad5917bf0 100644
--- a/apps/app-frontend/src/pages/Skins.vue
+++ b/apps/app-frontend/src/pages/Skins.vue
@@ -9,9 +9,10 @@ import {
ConfirmModal
} from '@modrinth/ui'
import type { Ref } from 'vue';
-import { ref, computed, useTemplateRef, watch, onMounted, onUnmounted, inject, nextTick } from 'vue'
+import { ref, computed, useTemplateRef, watch, onMounted, onUnmounted, inject } from 'vue'
import EditSkinModal from '@/components/ui/skin/EditSkinModal.vue'
import SelectCapeModal from '@/components/ui/skin/SelectCapeModal.vue'
+import UploadSkinModal from '@/components/ui/skin/UploadSkinModal.vue'
import { handleError } from '@/store/notifications'
import {
get_available_skins,
@@ -33,13 +34,13 @@ import type AccountsCard from "@/components/ui/AccountsCard.vue";
const editSkinModal = useTemplateRef('editSkinModal')
const selectCapeModal = useTemplateRef('selectCapeModal')
+const uploadSkinModal = useTemplateRef('uploadSkinModal')
const settings = ref(await getSettings())
const skins = ref([])
const capes = ref([])
const accountsCard = inject('accountsCard') as Ref
-const loginInProgress = ref(false);
const currentUser = ref(undefined)
const currentUserId = ref(undefined)
@@ -151,6 +152,33 @@ async function login() {
accountsCard.value.setLoginDisabled(false);
}
+function openUploadSkinModal(e: MouseEvent) {
+ uploadSkinModal.value?.show(e)
+}
+
+function onSkinFileUploaded(file: File) {
+ const fakeEvent = new MouseEvent('click')
+ file.arrayBuffer().then(buf => {
+ const skinTexture = new Uint8Array(buf)
+
+ if (editSkinModal.value && editSkinModal.value.shouldRestoreModal) {
+ editSkinModal.value.restoreWithNewTexture(skinTexture, file.name)
+ } else {
+ editSkinModal.value?.showNew(fakeEvent, skinTexture, file.name)
+ }
+ })
+}
+
+function onUploadCanceled() {
+ if (editSkinModal.value && editSkinModal.value.shouldRestoreModal) {
+ setTimeout(() => {
+ const fakeEvent = new MouseEvent('click')
+ editSkinModal.value!.show(fakeEvent)
+ editSkinModal.value!.shouldRestoreModal = false
+ }, 0)
+ }
+}
+
watch(
() => selectedSkin.value?.cape_id,
() => {}
@@ -190,8 +218,10 @@ await Promise.all([loadCapes(), loadSkins(), loadCurrentUser()])
:capes="capes"
@saved="onSkinSaved"
@deleted="() => loadSkins()"
+ @open-upload-modal="openUploadSkinModal"
/>
+
diff --git a/packages/ui/src/components/skin/CapeLikeTextButton.vue b/packages/ui/src/components/skin/CapeLikeTextButton.vue
index 21f5d0400..fb5415d05 100644
--- a/packages/ui/src/components/skin/CapeLikeTextButton.vue
+++ b/packages/ui/src/components/skin/CapeLikeTextButton.vue
@@ -56,7 +56,7 @@ withDefaults(
@supports (background-color: color-mix(in srgb, transparent, transparent)) {
.highlighted-glow::before {
- box-shadow: inset 0 0 2px 4px color-mix(in srgb, var(--color-brand), transparent 10%);
+ box-shadow: inset 0 0 2px 2px color-mix(in srgb, var(--color-brand), transparent 10%);
}
}