chore: update author name in package.json and refine file URL handling in renderer.js
This commit is contained in:
+3
-2
@@ -15,7 +15,7 @@
|
|||||||
"electron",
|
"electron",
|
||||||
"glassmorphism"
|
"glassmorphism"
|
||||||
],
|
],
|
||||||
"author": "Antigravity",
|
"author": "Trunçgil Technology",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"electron": "^31.3.0",
|
"electron": "^31.3.0",
|
||||||
@@ -34,7 +34,8 @@
|
|||||||
"files": [
|
"files": [
|
||||||
"**/*",
|
"**/*",
|
||||||
"!.venv/**",
|
"!.venv/**",
|
||||||
"!node_modules/**"
|
"!node_modules/**",
|
||||||
|
"node_modules/cropperjs/**"
|
||||||
],
|
],
|
||||||
"asarUnpack": [
|
"asarUnpack": [
|
||||||
"backend/**"
|
"backend/**"
|
||||||
|
|||||||
+78
-39
@@ -343,7 +343,7 @@ function handleImageSelection(filePath) {
|
|||||||
resetBgSettings();
|
resetBgSettings();
|
||||||
|
|
||||||
// Show image in preview element
|
// Show image in preview element
|
||||||
elements.imageElement.src = `file://${filePath}`;
|
elements.imageElement.src = toFileUrl(filePath);
|
||||||
|
|
||||||
// Set file metadata in control tower
|
// Set file metadata in control tower
|
||||||
const stats = getFileStats(filePath);
|
const stats = getFileStats(filePath);
|
||||||
@@ -367,7 +367,7 @@ function handleImageSelection(filePath) {
|
|||||||
// Initialize CropperJS on image
|
// Initialize CropperJS on image
|
||||||
initCropper();
|
initCropper();
|
||||||
};
|
};
|
||||||
img.src = `file://${filePath}`;
|
img.src = toFileUrl(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
function getFileStats(path) {
|
function getFileStats(path) {
|
||||||
@@ -388,6 +388,19 @@ function formatBytes(bytes, decimals = 2) {
|
|||||||
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toFileUrl(filePath) {
|
||||||
|
const normalized = filePath.replace(/\\/g, '/');
|
||||||
|
return normalized.startsWith('/')
|
||||||
|
? `file://${normalized}`
|
||||||
|
: `file:///${normalized}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unlockPostProcessingControls() {
|
||||||
|
elements.secCanvasBg.classList.remove('disabled-group');
|
||||||
|
elements.secExport.classList.remove('disabled-group');
|
||||||
|
elements.ctrlAutoTrim.disabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
// --- CROPPERJS CONTROLLER HUB ---
|
// --- CROPPERJS CONTROLLER HUB ---
|
||||||
function initCropper() {
|
function initCropper() {
|
||||||
if (cropper) {
|
if (cropper) {
|
||||||
@@ -412,7 +425,9 @@ function initCropper() {
|
|||||||
// Wire toolbar click listeners
|
// Wire toolbar click listeners
|
||||||
elements.ctrlCropDrag.classList.add('active');
|
elements.ctrlCropDrag.classList.add('active');
|
||||||
elements.ctrlCropBox.classList.remove('active');
|
elements.ctrlCropBox.classList.remove('active');
|
||||||
elements.ctrlAutoTrim.disabled = true; // Disabled until background is removed
|
elements.ctrlAutoTrim.disabled = !processedTempPath;
|
||||||
|
|
||||||
|
applyWorkspaceBackground();
|
||||||
}
|
}
|
||||||
|
|
||||||
function setupToolbarListeners() {
|
function setupToolbarListeners() {
|
||||||
@@ -1133,23 +1148,18 @@ async function executeBackgroundRemoval() {
|
|||||||
if (result.success) {
|
if (result.success) {
|
||||||
processedTempPath = result.outputPath;
|
processedTempPath = result.outputPath;
|
||||||
showToast(getTrans('toastTitleSuccess'), getTrans('toastTrimCompleteMsg'), "success");
|
showToast(getTrans('toastTitleSuccess'), getTrans('toastTrimCompleteMsg'), "success");
|
||||||
|
unlockPostProcessingControls();
|
||||||
|
|
||||||
// Update workspace preview image source to output transparent PNG
|
const freshSrc = `${toFileUrl(processedTempPath)}?t=${Date.now()}`;
|
||||||
// Add timestamp to bypass browser cache refreshing
|
elements.imageElement.onload = () => {
|
||||||
const freshSrc = `file://${processedTempPath}?t=${Date.now()}`;
|
elements.imageElement.onload = null;
|
||||||
|
try {
|
||||||
// Re-initialize CropperJS on the new image src
|
|
||||||
elements.imageElement.src = freshSrc;
|
|
||||||
|
|
||||||
// Wait for image source update to build the cropper safely
|
|
||||||
setTimeout(() => {
|
|
||||||
initCropper();
|
initCropper();
|
||||||
|
} catch (err) {
|
||||||
// Unlock background customization and export
|
console.error('Cropper init failed:', err);
|
||||||
elements.secCanvasBg.classList.remove('disabled-group');
|
}
|
||||||
elements.secExport.classList.remove('disabled-group');
|
};
|
||||||
elements.ctrlAutoTrim.disabled = false; // Unlock trim feature!
|
elements.imageElement.src = freshSrc;
|
||||||
}, 300);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
elements.errorOverlayLog.innerText = result.error || getTrans('toastSetupErrorMsg');
|
elements.errorOverlayLog.innerText = result.error || getTrans('toastSetupErrorMsg');
|
||||||
@@ -1184,44 +1194,81 @@ function switchBgMode(mode) {
|
|||||||
|
|
||||||
if (mode === 'transparent') {
|
if (mode === 'transparent') {
|
||||||
elements.tabBgTrans.classList.add('active');
|
elements.tabBgTrans.classList.add('active');
|
||||||
elements.canvasBgOverlay.style.opacity = '0';
|
|
||||||
} else if (mode === 'solid') {
|
} else if (mode === 'solid') {
|
||||||
elements.tabBgSolid.classList.add('active');
|
elements.tabBgSolid.classList.add('active');
|
||||||
elements.subpanelSolid.classList.remove('hidden');
|
elements.subpanelSolid.classList.remove('hidden');
|
||||||
elements.canvasBgOverlay.style.background = activeSolidColor;
|
|
||||||
elements.canvasBgOverlay.style.opacity = '1';
|
|
||||||
} else if (mode === 'gradient') {
|
} else if (mode === 'gradient') {
|
||||||
elements.tabBgGrad.classList.add('active');
|
elements.tabBgGrad.classList.add('active');
|
||||||
elements.subpanelGradient.classList.remove('hidden');
|
elements.subpanelGradient.classList.remove('hidden');
|
||||||
|
|
||||||
// Draw current active gradient stops onto the workspace preview
|
|
||||||
const cssGrad = buildCssGradientString(activeGradientStops);
|
|
||||||
elements.canvasBgOverlay.style.background = cssGrad;
|
|
||||||
elements.canvasBgOverlay.style.opacity = '1';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
applyWorkspaceBackground();
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildCssGradientString(stops) {
|
function buildCssGradientString(stops) {
|
||||||
return `linear-gradient(135deg, ${stops[0].color}, ${stops[1].color})`;
|
return `linear-gradient(135deg, ${stops[0].color}, ${stops[1].color})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function applyWorkspaceBackground() {
|
||||||
|
const wrapper = elements.canvasWrapper;
|
||||||
|
wrapper.style.background = '';
|
||||||
|
wrapper.style.backgroundImage = '';
|
||||||
|
wrapper.style.backgroundColor = '';
|
||||||
|
|
||||||
|
if (activeBgMode === 'transparent') {
|
||||||
|
wrapper.classList.add('checkerboard');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wrapper.classList.remove('checkerboard');
|
||||||
|
|
||||||
|
const bgValue = activeBgMode === 'solid'
|
||||||
|
? activeSolidColor
|
||||||
|
: buildCssGradientString(activeGradientStops);
|
||||||
|
|
||||||
|
wrapper.style.background = bgValue;
|
||||||
|
|
||||||
|
// Keep cropper inner layers transparent so the wrapper background shows through
|
||||||
|
wrapper.querySelectorAll('.cropper-wrap, .cropper-bg, .cropper-canvas').forEach((el) => {
|
||||||
|
el.style.background = 'transparent';
|
||||||
|
el.style.backgroundImage = 'none';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function selectGradientSwatch(btn) {
|
||||||
|
const gradKey = [...btn.classList].find((cls) => cls.startsWith('grad-'));
|
||||||
|
if (!gradKey || !GRADIENTS[gradKey]) return;
|
||||||
|
|
||||||
|
document.querySelectorAll('.grad-swatch').forEach((s) => s.classList.remove('active'));
|
||||||
|
btn.classList.add('active');
|
||||||
|
activeGradientStops = GRADIENTS[gradKey].map((stop) => ({ ...stop }));
|
||||||
|
|
||||||
|
if (activeBgMode === 'gradient') {
|
||||||
|
applyWorkspaceBackground();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function setupBgSwatches() {
|
function setupBgSwatches() {
|
||||||
// Solid Swatches
|
// Solid Swatches
|
||||||
const solidSwatches = document.querySelectorAll('.swatch:not(.custom)');
|
const solidSwatches = document.querySelectorAll('.swatch:not(.custom)');
|
||||||
solidSwatches.forEach(swatch => {
|
solidSwatches.forEach(swatch => {
|
||||||
swatch.addEventListener('click', (e) => {
|
swatch.addEventListener('click', (e) => {
|
||||||
solidSwatches.forEach(s => s.classList.remove('active'));
|
solidSwatches.forEach(s => s.classList.remove('active'));
|
||||||
e.target.classList.add('active');
|
e.currentTarget.classList.add('active');
|
||||||
|
|
||||||
activeSolidColor = e.target.getAttribute('data-color');
|
activeSolidColor = e.currentTarget.getAttribute('data-color');
|
||||||
elements.canvasBgOverlay.style.background = activeSolidColor;
|
if (activeBgMode === 'solid') {
|
||||||
|
applyWorkspaceBackground();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Custom Color Picker
|
// Custom Color Picker
|
||||||
elements.customColorPicker.addEventListener('input', (e) => {
|
elements.customColorPicker.addEventListener('input', (e) => {
|
||||||
activeSolidColor = e.target.value;
|
activeSolidColor = e.target.value;
|
||||||
elements.canvasBgOverlay.style.background = activeSolidColor;
|
if (activeBgMode === 'solid') {
|
||||||
|
applyWorkspaceBackground();
|
||||||
|
}
|
||||||
|
|
||||||
// Highlight custom swatch borders
|
// Highlight custom swatch borders
|
||||||
elements.btnCustomColorPicker.classList.add('active');
|
elements.btnCustomColorPicker.classList.add('active');
|
||||||
@@ -1232,14 +1279,7 @@ function setupBgSwatches() {
|
|||||||
const gradSwatches = document.querySelectorAll('.grad-swatch');
|
const gradSwatches = document.querySelectorAll('.grad-swatch');
|
||||||
gradSwatches.forEach(swatch => {
|
gradSwatches.forEach(swatch => {
|
||||||
swatch.addEventListener('click', (e) => {
|
swatch.addEventListener('click', (e) => {
|
||||||
gradSwatches.forEach(s => s.classList.remove('active'));
|
selectGradientSwatch(e.currentTarget);
|
||||||
e.target.classList.add('active');
|
|
||||||
|
|
||||||
const gradKey = e.target.className.split(' ').find(cls => cls.startsWith('grad-'));
|
|
||||||
if (GRADIENTS[gradKey]) {
|
|
||||||
activeGradientStops = GRADIENTS[gradKey];
|
|
||||||
elements.canvasBgOverlay.style.background = e.target.getAttribute('data-gradient');
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1276,7 +1316,6 @@ async function executeExport() {
|
|||||||
ctx.fillStyle = activeSolidColor;
|
ctx.fillStyle = activeSolidColor;
|
||||||
ctx.fillRect(0, 0, finalCanvas.width, finalCanvas.height);
|
ctx.fillRect(0, 0, finalCanvas.width, finalCanvas.height);
|
||||||
} else if (activeBgMode === 'gradient') {
|
} else if (activeBgMode === 'gradient') {
|
||||||
// Render the 135deg gradient vector on final output canvas
|
|
||||||
const grad = ctx.createLinearGradient(0, 0, finalCanvas.width, finalCanvas.height);
|
const grad = ctx.createLinearGradient(0, 0, finalCanvas.width, finalCanvas.height);
|
||||||
activeGradientStops.forEach(stop => {
|
activeGradientStops.forEach(stop => {
|
||||||
grad.addColorStop(stop.offset, stop.color);
|
grad.addColorStop(stop.offset, stop.color);
|
||||||
|
|||||||
Reference in New Issue
Block a user