cl
This commit is contained in:
parent
f738bbdd73
commit
3e849c0286
@ -1,4 +1,5 @@
|
||||
import { spriteOffsets, notification } from '@/application/state';
|
||||
import { type Sprite } from '@/application/types';
|
||||
|
||||
/**
|
||||
* Logger utility with consistent error format
|
||||
@ -60,3 +61,86 @@ export function isImageReady(img: HTMLImageElement): boolean {
|
||||
export function getPixelPerfectCoordinate(value: number): number {
|
||||
return Math.floor(value) + 0.5;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a sprite object from a file
|
||||
*/
|
||||
export function createSpriteFromFile(file: File, index: number): Promise<Sprite> {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Create a URL for the file
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
|
||||
const img = new Image();
|
||||
|
||||
// Set up event handlers
|
||||
img.onload = () => {
|
||||
// Verify the image has loaded properly
|
||||
if (img.width === 0 || img.height === 0) {
|
||||
logger.error('Image loaded with invalid dimensions:', { name: file.name, width: img.width, height: img.height });
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
reject(new Error(`Image has invalid dimensions: ${file.name}`));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the sprite object
|
||||
const sprite: Sprite = {
|
||||
img,
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
x: 0,
|
||||
y: 0,
|
||||
name: file.name,
|
||||
id: `sprite-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
||||
uploadOrder: index,
|
||||
};
|
||||
|
||||
// Keep the objectUrl reference and don't revoke it yet
|
||||
// The image is still needed for rendering later
|
||||
resolve(sprite);
|
||||
};
|
||||
|
||||
img.onerror = error => {
|
||||
logger.error('Error loading image:', { name: file.name, error });
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
reject(new Error(`Failed to load image: ${file.name}`));
|
||||
};
|
||||
|
||||
// Set the source to the object URL
|
||||
img.src = objectUrl;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Process multiple files and create sprites
|
||||
*/
|
||||
export async function processImageFiles(files: FileList): Promise<{ newSprites: Sprite[], errorCount: number }> {
|
||||
const imageFiles = Array.from(files).filter(file => file.type.startsWith('image/'));
|
||||
|
||||
if (imageFiles.length === 0) {
|
||||
return { newSprites: [], errorCount: 0 };
|
||||
}
|
||||
|
||||
const newSprites: Sprite[] = [];
|
||||
let errorCount = 0;
|
||||
|
||||
for (let i = 0; i < imageFiles.length; i++) {
|
||||
const file = imageFiles[i];
|
||||
|
||||
try {
|
||||
const sprite = await createSpriteFromFile(file, i);
|
||||
newSprites.push(sprite);
|
||||
} catch (error) {
|
||||
errorCount++;
|
||||
logger.error('Error loading sprite:', error);
|
||||
}
|
||||
}
|
||||
|
||||
return { newSprites, errorCount };
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncate text to a specific length and add ellipsis if needed
|
||||
*/
|
||||
export function truncateText(text: string, maxLength: number = 15): string {
|
||||
return text.length > maxLength ? `${text.substring(0, maxLength)}...` : text;
|
||||
}
|
||||
|
@ -54,20 +54,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
const newSprites: Sprite[] = [];
|
||||
let errorCount = 0;
|
||||
// Use the utility function to process image files
|
||||
const { newSprites, errorCount } = await store.processImageFiles(files);
|
||||
|
||||
for (let i = 0; i < imageFiles.length; i++) {
|
||||
const file = imageFiles[i];
|
||||
|
||||
try {
|
||||
const sprite = await createSpriteFromFile(file, i);
|
||||
newSprites.push(sprite);
|
||||
} catch (error) {
|
||||
errorCount++;
|
||||
console.error('Error loading sprite:', error);
|
||||
store.showNotification(`Failed to load ${file.name}`, 'error');
|
||||
}
|
||||
// Handle individual file errors
|
||||
if (errorCount > 0) {
|
||||
store.showNotification(`Failed to load ${errorCount} file(s)`, 'error');
|
||||
}
|
||||
|
||||
if (newSprites.length > 0) {
|
||||
@ -75,54 +67,7 @@
|
||||
emit('files-uploaded', newSprites);
|
||||
store.showNotification(`Added ${newSprites.length} sprites successfully`);
|
||||
} else if (errorCount > 0) {
|
||||
store.showNotification(`Failed to load all ${errorCount} sprites`, 'error');
|
||||
store.showNotification(`Failed to load all sprites`, 'error');
|
||||
}
|
||||
};
|
||||
|
||||
const createSpriteFromFile = (file: File, index: number): Promise<Sprite> => {
|
||||
return new Promise((resolve, reject) => {
|
||||
// Create a URL for the file
|
||||
const objectUrl = URL.createObjectURL(file);
|
||||
|
||||
const img = new Image();
|
||||
|
||||
// Set up event handlers
|
||||
img.onload = () => {
|
||||
// Verify the image has loaded properly
|
||||
if (img.width === 0 || img.height === 0) {
|
||||
console.error('Image loaded with invalid dimensions:', file.name, img.width, img.height);
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
reject(new Error(`Image has invalid dimensions: ${file.name}`));
|
||||
return;
|
||||
}
|
||||
|
||||
// Create the sprite object
|
||||
const sprite: Sprite = {
|
||||
img,
|
||||
width: img.width,
|
||||
height: img.height,
|
||||
x: 0,
|
||||
y: 0,
|
||||
name: file.name,
|
||||
id: `sprite-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`,
|
||||
uploadOrder: index,
|
||||
};
|
||||
|
||||
// Keep the objectUrl reference and don't revoke it yet
|
||||
// The image is still needed for rendering later
|
||||
// URL.revokeObjectURL(objectUrl); - Don't do this anymore
|
||||
|
||||
resolve(sprite);
|
||||
};
|
||||
|
||||
img.onerror = error => {
|
||||
console.error('Error loading image:', file.name, error);
|
||||
URL.revokeObjectURL(objectUrl);
|
||||
reject(new Error(`Failed to load image: ${file.name}`));
|
||||
};
|
||||
|
||||
// Set the source to the object URL
|
||||
img.src = objectUrl;
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
@ -10,7 +10,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import type { Sprite } from '../composables/useSpritesheetStore';
|
||||
import { useSpritesheetStore, type Sprite } from '../composables/useSpritesheetStore';
|
||||
|
||||
defineProps<{
|
||||
sprites: Sprite[];
|
||||
@ -20,7 +20,10 @@
|
||||
spriteClicked: [id: string];
|
||||
}>();
|
||||
|
||||
const store = useSpritesheetStore();
|
||||
|
||||
// Use the utility function for truncating text with a custom length
|
||||
const truncateName = (name: string) => {
|
||||
return name.length > 10 ? `${name.substring(0, 10)}...` : name;
|
||||
return store.truncateText(name, 10);
|
||||
};
|
||||
</script>
|
||||
|
@ -69,7 +69,8 @@
|
||||
}
|
||||
};
|
||||
|
||||
// Use the utility function for truncating text
|
||||
const truncateName = (name: string) => {
|
||||
return name.length > 15 ? `${name.substring(0, 15)}...` : name;
|
||||
return store.truncateText(name);
|
||||
};
|
||||
</script>
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { sprites, canvas, ctx, cellSize, columns, draggedSprite, dragOffset, isShiftPressed, isModalOpen, isSettingsModalOpen, isSpritesModalOpen, isHelpModalOpen, zoomLevel, previewBorder, animation, notification, currentSpriteOffset, spriteOffsets } from '@/application/state';
|
||||
|
||||
import { getSpriteOffset, showNotification } from '@/application/utilities';
|
||||
import { getSpriteOffset, showNotification, createSpriteFromFile, processImageFiles, truncateText } from '@/application/utilities';
|
||||
|
||||
import { addSprites, updateCellSize, autoArrangeSprites, highlightSprite, clearAllSprites, applyOffsetsToMainView } from '@/application/spriteOperations';
|
||||
|
||||
@ -36,6 +36,9 @@ export function useSpritesheetStore() {
|
||||
// Utils
|
||||
getSpriteOffset,
|
||||
showNotification,
|
||||
createSpriteFromFile,
|
||||
processImageFiles,
|
||||
truncateText,
|
||||
|
||||
// Sprite operations
|
||||
addSprites,
|
||||
|
Loading…
x
Reference in New Issue
Block a user