[FEAT] UX enhancements

This commit is contained in:
2025-11-23 03:40:26 +01:00
parent 2c25157621
commit 9a2bf6b2db
5 changed files with 135 additions and 68 deletions

View File

@@ -57,7 +57,6 @@
<p class="text-sm text-gray-600 dark:text-gray-400">Drag and drop images or import from JSON</p>
</div>
<file-uploader @upload-sprites="handleSpritesUpload" />
<input ref="jsonFileInput" type="file" accept=".json,application/json" class="hidden" @change="handleJSONFileChange" />
<div class="mt-10">
<div class="prose prose-lg dark:prose-invert max-w-none">
@@ -250,24 +249,14 @@
<!-- Right panel - Canvas Preview -->
<div class="p-6 overflow-y-auto overflow-x-auto max-h-[calc(100vh-200px)]">
<sprite-canvas
:layers="layers"
:active-layer-id="activeLayerId"
:columns="columns"
@update-sprite="updateSpritePosition"
@update-sprite-cell="updateSpriteCell"
@remove-sprite="removeSprite"
@replace-sprite="replaceSprite"
@add-sprite="addSprite"
@add-sprite-with-resize="addSpriteWithResize"
/>
<sprite-canvas :layers="layers" :active-layer-id="activeLayerId" :columns="columns" @update-sprite="updateSpritePosition" @update-sprite-cell="updateSpriteCell" @remove-sprite="removeSprite" @replace-sprite="replaceSprite" @add-sprite="addSprite" />
</div>
</div>
</main>
</div>
<Modal :is-open="isPreviewModalOpen" @close="closePreviewModal" title="Animation Preview">
<sprite-preview :layers="layers" :active-layer-id="activeLayerId" :columns="columns" @update-sprite="updateSpritePosition" />
<sprite-preview :layers="layers" :active-layer-id="activeLayerId" :columns="columns" @update-sprite="updateSpritePosition" @update-sprite-in-layer="updateSpriteInLayer" />
</Modal>
<HelpModal :is-open="isHelpModalOpen" @close="closeHelpModal" />
@@ -311,7 +300,7 @@
import type { SpriteFile } from './types/sprites';
const settingsStore = useSettingsStore();
const { layers, visibleLayers, activeLayer, activeLayerId, columns, updateSpritePosition, updateSpriteCell, removeSprite, replaceSprite, addSprite, addSpriteWithResize, processImageFiles, alignSprites, addLayer, removeLayer, moveLayer } = useLayers();
const { layers, visibleLayers, activeLayer, activeLayerId, columns, updateSpritePosition, updateSpriteInLayer, updateSpriteCell, removeSprite, replaceSprite, addSprite, processImageFiles, alignSprites, addLayer, removeLayer, moveLayer } = useLayers();
const { downloadSpritesheet, exportSpritesheetJSON, importSpritesheetJSON, downloadAsGif, downloadAsZip } = useExportLayers(
layers,
@@ -324,27 +313,27 @@
toRef(settingsStore, 'manualCellHeight')
);
const cellSize = computed(() => {
if (!layers.value.length) return { width: 0, height: 0 };
const getCellSize = () => {
if (!visibleLayers.value.length) return { width: 0, height: 0 };
// If manual cell size is enabled, use the manual values
if (settingsStore.manualCellSizeEnabled) {
return { width: settingsStore.manualCellWidth, height: settingsStore.manualCellHeight };
}
// Otherwise, calculate based on max dimensions
const { maxWidth, maxHeight } = getMaxDimensionsAcrossLayers(visibleLayers.value);
const allSprites = visibleLayers.value.flatMap(l => l.sprites);
const negativeSpacing = calculateNegativeSpacing(allSprites, settingsStore.negativeSpacingEnabled);
return { width: maxWidth + negativeSpacing, height: maxHeight + negativeSpacing };
});
};
const cellSize = computed(getCellSize);
const isPreviewModalOpen = ref(false);
const isHelpModalOpen = ref(false);
const isFeedbackModalOpen = ref(false);
const isSpritesheetSplitterOpen = ref(false);
const isGifFpsModalOpen = ref(false);
const jsonFileInput = ref<HTMLInputElement | null>(null);
const uploadInput = ref<HTMLInputElement | null>(null);
const jsonFileInput = ref<HTMLInputElement | null>(null);
const spritesheetImageUrl = ref('');
const spritesheetImageFile = ref<File | null>(null);
const showFeedbackPopup = ref(false);
@@ -356,12 +345,7 @@
const jsonFile = files.find(file => file.type === 'application/json' || file.name.endsWith('.json'));
if (jsonFile) {
try {
await importSpritesheetJSON(jsonFile);
} catch (error) {
console.error('Error importing JSON:', error);
alert('Failed to import JSON file. Please check the file format.');
}
await handleJSONImport(jsonFile);
return;
}
@@ -387,6 +371,15 @@
processImageFiles(files);
};
const handleJSONImport = async (jsonFile: File) => {
try {
await importSpritesheetJSON(jsonFile);
} catch (error) {
console.error('Error importing JSON:', error);
alert('Failed to import JSON file. Please check the file format.');
}
};
const openPreviewModal = () => {
if (!visibleLayers.value.some(l => l.sprites.length > 0)) {
alert('Please upload or import sprites to preview an animation.');
@@ -447,14 +440,8 @@
const handleJSONFileChange = async (event: Event) => {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const jsonFile = input.files[0];
try {
await importSpritesheetJSON(jsonFile);
} catch (error) {
console.error('Error importing JSON:', error);
alert('Failed to import JSON file. Please check the file format.');
}
if (jsonFileInput.value) jsonFileInput.value.value = '';
await handleJSONImport(input.files[0]);
input.value = '';
}
};
@@ -483,9 +470,8 @@
const handleUploadChange = async (event: Event) => {
const input = event.target as HTMLInputElement;
if (input.files && input.files.length > 0) {
const files = Array.from(input.files);
await handleSpritesUpload(files);
if (uploadInput.value) uploadInput.value.value = '';
await handleSpritesUpload(Array.from(input.files));
input.value = '';
}
};