mirror of
https://github.com/modrinth/code.git
synced 2026-08-31 03:55:59 +00:00
fix: dragging disable hover, wrong evt for edit skin + remove back of skin hover
This commit is contained in:
@@ -148,7 +148,6 @@ import { arrayBufferToBase64 } from '@modrinth/utils'
|
||||
import { computed, nextTick, ref, useTemplateRef, watch } from 'vue'
|
||||
|
||||
import {
|
||||
add_and_equip_custom_skin,
|
||||
type Cape,
|
||||
determineModelType,
|
||||
equip_skin,
|
||||
@@ -440,9 +439,22 @@ async function save() {
|
||||
const bytes: Uint8Array = new Uint8Array(await (await fetch(textureUrl)).arrayBuffer())
|
||||
|
||||
if (mode.value === 'new') {
|
||||
const addedSkin = await add_and_equip_custom_skin(bytes, variant.value, selectedCape.value)
|
||||
const addedSkin = await save_custom_skin(
|
||||
{
|
||||
texture_key: '',
|
||||
variant: variant.value,
|
||||
cape_id: selectedCape.value?.id,
|
||||
texture: textureUrl,
|
||||
source: 'custom',
|
||||
is_equipped: false,
|
||||
},
|
||||
bytes,
|
||||
variant.value,
|
||||
selectedCape.value,
|
||||
true,
|
||||
)
|
||||
emit('saved', {
|
||||
applied: true,
|
||||
applied: false,
|
||||
skin: addedSkin,
|
||||
})
|
||||
} else {
|
||||
|
||||
@@ -159,6 +159,9 @@ const sections = computed<SkinSection[]>(() => [
|
||||
const draggableSavedSkins = ref<Skin[]>([])
|
||||
const isDraggingSavedSkin = ref(false)
|
||||
const canReorderSavedSkins = computed(() => draggableSavedSkins.value.length > 1)
|
||||
const fixedSavedSkins = computed(() =>
|
||||
props.savedSkins.filter((skin) => !canPersistSkinOrder(skin)),
|
||||
)
|
||||
|
||||
const sectionLayouts = computed(() => {
|
||||
const layouts: Array<{ section: SkinSection; top: number; height: number; index: number }> = []
|
||||
@@ -223,7 +226,7 @@ watch(
|
||||
return
|
||||
}
|
||||
|
||||
draggableSavedSkins.value = [...nextSkins]
|
||||
draggableSavedSkins.value = nextSkins.filter(canPersistSkinOrder)
|
||||
},
|
||||
{ immediate: true },
|
||||
)
|
||||
@@ -280,10 +283,18 @@ function savedSkinKey(skin: Skin) {
|
||||
return skinKey(skin, 'saved-skin')
|
||||
}
|
||||
|
||||
function canPersistSkinOrder(skin: Skin) {
|
||||
return skin.source === 'custom'
|
||||
}
|
||||
|
||||
function doSkinOrdersMatch(firstSkins: Skin[], secondSkins: Skin[]) {
|
||||
const persistedSecondSkins = secondSkins.filter(canPersistSkinOrder)
|
||||
|
||||
return (
|
||||
firstSkins.length === secondSkins.length &&
|
||||
firstSkins.every((skin, index) => savedSkinKey(skin) === savedSkinKey(secondSkins[index]))
|
||||
firstSkins.length === persistedSecondSkins.length &&
|
||||
firstSkins.every(
|
||||
(skin, index) => savedSkinKey(skin) === savedSkinKey(persistedSecondSkins[index]),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -295,7 +306,7 @@ function onSavedSkinDragEnd() {
|
||||
isDraggingSavedSkin.value = false
|
||||
|
||||
if (doSkinOrdersMatch(draggableSavedSkins.value, props.savedSkins)) {
|
||||
draggableSavedSkins.value = [...props.savedSkins]
|
||||
draggableSavedSkins.value = props.savedSkins.filter(canPersistSkinOrder)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -404,7 +415,7 @@ defineExpose({ getAddSkinButtonElement })
|
||||
:list="draggableSavedSkins"
|
||||
class="grid w-full grid-cols-3 gap-3 min-[1300px]:grid-cols-4 min-[1750px]:grid-cols-5 min-[2050px]:grid-cols-6"
|
||||
:item-key="savedSkinKey"
|
||||
:disabled="!canReorderSavedSkins"
|
||||
:disabled="readOnly || !canReorderSavedSkins"
|
||||
:animation="250"
|
||||
:swap-threshold="1"
|
||||
:invert-swap="false"
|
||||
@@ -447,10 +458,50 @@ defineExpose({ getAddSkinButtonElement })
|
||||
<SkinButton
|
||||
class="h-full w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:backward-image-src="getBakedSkinTextures(skin)?.backwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:disabled="readOnly"
|
||||
:is-dragging="isDraggingSavedSkin"
|
||||
@select="emit('select', skin)"
|
||||
>
|
||||
<template v-if="!readOnly" #overlay-buttons>
|
||||
<ButtonStyled color="brand">
|
||||
<button
|
||||
:aria-label="formatMessage(messages.editSkinButton)"
|
||||
class="pointer-events-auto"
|
||||
@click.stop="(event: MouseEvent) => emit('edit', skin, event)"
|
||||
>
|
||||
<EditIcon /> {{ formatMessage(commonMessages.editButton) }}
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-show="!skin.is_equipped" circular color="red">
|
||||
<button
|
||||
v-tooltip="formatMessage(messages.deleteSkinButton)"
|
||||
:aria-label="formatMessage(messages.deleteSkinButton)"
|
||||
class="!rounded-[100%] pointer-events-auto"
|
||||
@click.stop="emit('delete', skin)"
|
||||
>
|
||||
<TrashIcon />
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</template>
|
||||
</SkinButton>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template #footer>
|
||||
<div
|
||||
v-for="skin in fixedSavedSkins"
|
||||
:key="savedSkinKey(skin)"
|
||||
class="relative aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
>
|
||||
<SkinButton
|
||||
class="h-full w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:disabled="readOnly"
|
||||
:is-dragging="isDraggingSavedSkin"
|
||||
@select="emit('select', skin)"
|
||||
>
|
||||
<template v-if="!readOnly" #overlay-buttons>
|
||||
@@ -488,11 +539,11 @@ defineExpose({ getAddSkinButtonElement })
|
||||
:key="skinKey(skin, section.key)"
|
||||
class="aspect-[31/40] w-full min-w-0 box-border rounded-[20px]"
|
||||
:forward-image-src="getBakedSkinTextures(skin)?.forwards"
|
||||
:backward-image-src="getBakedSkinTextures(skin)?.backwards"
|
||||
:selected="isSkinSelected(skin)"
|
||||
:active="isSkinActive(skin)"
|
||||
:tooltip="skin.name"
|
||||
:disabled="readOnly"
|
||||
:is-dragging="isDraggingSavedSkin"
|
||||
@select="emit('select', skin)"
|
||||
>
|
||||
<template #overlay-buttons>
|
||||
|
||||
@@ -15,12 +15,10 @@ import { skinPreviewStorage } from '../storage/skin-preview-storage'
|
||||
|
||||
export interface RenderResult {
|
||||
forwards: string
|
||||
backwards: string
|
||||
}
|
||||
|
||||
export interface RawRenderResult {
|
||||
forwards: Blob
|
||||
backwards: Blob
|
||||
}
|
||||
|
||||
class BatchSkinRenderer {
|
||||
@@ -92,12 +90,9 @@ class BatchSkinRenderer {
|
||||
}
|
||||
|
||||
const frontCameraPos: [number, number, number] = [-1.3, 1, 6.3]
|
||||
const backCameraPos: [number, number, number] = [-1.3, 1, -2.5]
|
||||
|
||||
const forwards = await this.renderView(frontCameraPos, lookAtTarget)
|
||||
const backwards = await this.renderView(backCameraPos, lookAtTarget)
|
||||
|
||||
return { forwards, backwards }
|
||||
return { forwards }
|
||||
}
|
||||
|
||||
private async renderView(
|
||||
@@ -407,7 +402,6 @@ async function generateSkinPreviewsForGeneration(
|
||||
if (rawCached && !skinBlobUrlMap.has(skinKey)) {
|
||||
const cached: RenderResult = {
|
||||
forwards: URL.createObjectURL(rawCached.forwards),
|
||||
backwards: URL.createObjectURL(rawCached.backwards),
|
||||
}
|
||||
skinBlobUrlMap.set(skinKey, cached)
|
||||
}
|
||||
@@ -427,7 +421,6 @@ async function generateSkinPreviewsForGeneration(
|
||||
if (DEBUG_MODE) {
|
||||
const result = skinBlobUrlMap.get(key)!
|
||||
URL.revokeObjectURL(result.forwards)
|
||||
URL.revokeObjectURL(result.backwards)
|
||||
skinBlobUrlMap.delete(key)
|
||||
} else continue
|
||||
}
|
||||
@@ -456,7 +449,6 @@ async function generateSkinPreviewsForGeneration(
|
||||
|
||||
const renderResult: RenderResult = {
|
||||
forwards: URL.createObjectURL(rawRenderResult.forwards),
|
||||
backwards: URL.createObjectURL(rawRenderResult.backwards),
|
||||
}
|
||||
|
||||
skinBlobUrlMap.set(key, renderResult)
|
||||
|
||||
@@ -2,7 +2,6 @@ import type { RawRenderResult } from '../rendering/batch-skin-renderer'
|
||||
|
||||
interface StoredPreview {
|
||||
forwards: Blob
|
||||
backwards: Blob
|
||||
timestamp: number
|
||||
}
|
||||
|
||||
@@ -38,7 +37,6 @@ export class SkinPreviewStorage {
|
||||
|
||||
const storedPreview: StoredPreview = {
|
||||
forwards: result.forwards,
|
||||
backwards: result.backwards,
|
||||
timestamp: Date.now(),
|
||||
}
|
||||
|
||||
@@ -67,7 +65,7 @@ export class SkinPreviewStorage {
|
||||
return
|
||||
}
|
||||
|
||||
resolve({ forwards: result.forwards, backwards: result.backwards })
|
||||
resolve({ forwards: result.forwards })
|
||||
}
|
||||
request.onerror = () => reject(request.error)
|
||||
})
|
||||
@@ -95,7 +93,7 @@ export class SkinPreviewStorage {
|
||||
const result = request.result as StoredPreview | undefined
|
||||
|
||||
if (result) {
|
||||
results[key] = { forwards: result.forwards, backwards: result.backwards }
|
||||
results[key] = { forwards: result.forwards }
|
||||
} else {
|
||||
results[key] = null
|
||||
}
|
||||
@@ -173,7 +171,7 @@ export class SkinPreviewStorage {
|
||||
const key = cursor.primaryKey as string
|
||||
const value = cursor.value as StoredPreview
|
||||
|
||||
const entrySize = value.forwards.size + value.backwards.size
|
||||
const entrySize = value.forwards.size
|
||||
totalSize += entrySize
|
||||
count++
|
||||
|
||||
|
||||
@@ -584,7 +584,9 @@ async function reorderSavedSkins(orderedSkins: Skin[]) {
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
|
||||
try {
|
||||
await set_custom_skin_order(nextSavedSkins.map((skin) => skin.texture_key))
|
||||
await set_custom_skin_order(
|
||||
nextSavedSkins.filter((skin) => skin.source === 'custom').map((skin) => skin.texture_key),
|
||||
)
|
||||
} catch (error) {
|
||||
skins.value = previousSkins
|
||||
generateSkinPreviews(skins.value, capes.value)
|
||||
|
||||
Reference in New Issue
Block a user