fix: complete progress log localization and resolve background customizer layering bug
This commit is contained in:
+238
-38
@@ -182,7 +182,7 @@ function resetWorkspaceToEmpty() {
|
|||||||
// Clear background customizations
|
// Clear background customizations
|
||||||
resetBgSettings();
|
resetBgSettings();
|
||||||
|
|
||||||
showToast("Image Changed", "Workspace cleared. You can now load a new image.", "info");
|
showToast(getTrans('toastImageChanged'), getTrans('toastImageChangedMsg'), "info");
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- PYTHON VENV INSTALLER ENGINE ---
|
// --- PYTHON VENV INSTALLER ENGINE ---
|
||||||
@@ -208,40 +208,55 @@ elements.btnStartSetup.addEventListener('click', async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
setStepActive(elements.stepVenv);
|
setStepActive(elements.stepVenv);
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupCreatingVenv');
|
||||||
|
|
||||||
// Listen for pipeline setup output logs
|
// Listen for pipeline setup output logs
|
||||||
window.api.onSetupProgress((progressText) => {
|
window.api.onSetupProgress((progressText) => {
|
||||||
elements.setupStatusText.innerText = progressText;
|
// Translate setup output progress text
|
||||||
|
|
||||||
// Parse step state
|
|
||||||
if (progressText.includes("Creating Python virtual environment")) {
|
if (progressText.includes("Creating Python virtual environment")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupCreatingVenv');
|
||||||
setStepActive(elements.stepVenv);
|
setStepActive(elements.stepVenv);
|
||||||
elements.setupProgressBar.style.width = '15%';
|
elements.setupProgressBar.style.width = '15%';
|
||||||
} else if (progressText.includes("Virtual environment successfully created") || progressText.includes("Virtual environment already exists")) {
|
} else if (progressText.includes("Virtual environment successfully created")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupVenvCreated');
|
||||||
|
setStepDone(elements.stepVenv);
|
||||||
|
setStepActive(elements.stepPip);
|
||||||
|
elements.setupProgressBar.style.width = '30%';
|
||||||
|
} else if (progressText.includes("Virtual environment already exists")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupVenvExists');
|
||||||
setStepDone(elements.stepVenv);
|
setStepDone(elements.stepVenv);
|
||||||
setStepActive(elements.stepPip);
|
setStepActive(elements.stepPip);
|
||||||
elements.setupProgressBar.style.width = '30%';
|
elements.setupProgressBar.style.width = '30%';
|
||||||
} else if (progressText.includes("Upgrading pip")) {
|
} else if (progressText.includes("Upgrading pip")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupUpgradingPip');
|
||||||
setStepActive(elements.stepPip);
|
setStepActive(elements.stepPip);
|
||||||
elements.setupProgressBar.style.width = '45%';
|
elements.setupProgressBar.style.width = '45%';
|
||||||
} else if (progressText.includes("Installing PyTorch")) {
|
} else if (progressText.includes("Installing PyTorch")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupInstallingTorch');
|
||||||
setStepDone(elements.stepPip);
|
setStepDone(elements.stepPip);
|
||||||
setStepActive(elements.stepDeps);
|
setStepActive(elements.stepDeps);
|
||||||
elements.setupProgressBar.style.width = '60%';
|
elements.setupProgressBar.style.width = '60%';
|
||||||
} else if (progressText.includes("Downloading torch") || progressText.includes("Installing collected packages")) {
|
} else if (progressText.includes("Downloading torch")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupDownloadingTorch');
|
||||||
elements.setupProgressBar.style.width = '75%';
|
elements.setupProgressBar.style.width = '75%';
|
||||||
|
} else if (progressText.includes("Installing collected packages")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupInstallingDeps');
|
||||||
|
elements.setupProgressBar.style.width = '85%';
|
||||||
} else if (progressText.includes("Setup completed successfully")) {
|
} else if (progressText.includes("Setup completed successfully")) {
|
||||||
|
elements.setupStatusText.innerText = getTrans('setupCompleted');
|
||||||
setStepDone(elements.stepDeps);
|
setStepDone(elements.stepDeps);
|
||||||
setStepDone(elements.stepLibs);
|
setStepDone(elements.stepLibs);
|
||||||
elements.setupProgressBar.style.width = '100%';
|
elements.setupProgressBar.style.width = '100%';
|
||||||
|
} else {
|
||||||
|
elements.setupStatusText.innerText = progressText;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await window.api.runPythonSetup();
|
const result = await window.api.runPythonSetup();
|
||||||
if (result.code === 0) {
|
if (result.code === 0) {
|
||||||
elements.setupStatusText.innerText = "Configuration Complete! Enjoy background removal.";
|
elements.setupStatusText.innerText = getTrans('setupCompleted');
|
||||||
showToast("Setup Success", "Python environment is fully configured.", "success");
|
showToast(getTrans('toastSetupSuccess'), getTrans('toastSetupSuccessMsg'), "success");
|
||||||
|
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
elements.setupOverlay.classList.add('hidden');
|
elements.setupOverlay.classList.add('hidden');
|
||||||
@@ -249,14 +264,14 @@ elements.btnStartSetup.addEventListener('click', async () => {
|
|||||||
}, 1500);
|
}, 1500);
|
||||||
} else {
|
} else {
|
||||||
setStepFailed(elements.stepDeps);
|
setStepFailed(elements.stepDeps);
|
||||||
elements.setupStatusText.innerText = "Setup failed. Check system dependencies.";
|
elements.setupStatusText.innerText = getTrans('setupFailed');
|
||||||
elements.btnStartSetup.disabled = false;
|
elements.btnStartSetup.disabled = false;
|
||||||
showToast("Setup Error", "Failed to build Python environment.", "error");
|
showToast(getTrans('toastSetupError'), getTrans('toastSetupErrorMsg'), "error");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
elements.setupStatusText.innerText = `Error: ${err.message}`;
|
elements.setupStatusText.innerText = `${getTrans('toastSetupError')}: ${err.message}`;
|
||||||
elements.btnStartSetup.disabled = false;
|
elements.btnStartSetup.disabled = false;
|
||||||
showToast("Setup Error", err.message, "error");
|
showToast(getTrans('toastSetupError'), err.message, "error");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -551,7 +566,39 @@ const TRANSLATIONS = {
|
|||||||
dragDropSub: "Supports PNG, JPG, JPEG, or WebP formats",
|
dragDropSub: "Supports PNG, JPG, JPEG, or WebP formats",
|
||||||
orText: "OR",
|
orText: "OR",
|
||||||
browseFiles: "Browse Local Files",
|
browseFiles: "Browse Local Files",
|
||||||
autoTrim: "Auto-Trim"
|
autoTrim: "Auto-Trim",
|
||||||
|
statusInit: "Initializing AI model...",
|
||||||
|
statusWeights: "Loading neural weights into memory...",
|
||||||
|
statusImporting: "Importing libraries...",
|
||||||
|
statusDetecting: "Detecting device...",
|
||||||
|
statusUsingDevice: "Using device: ",
|
||||||
|
statusLoadingModel: "Loading BiRefNet model...",
|
||||||
|
statusPreprocessing: "Loading and preprocessing image...",
|
||||||
|
statusInference: "Running background removal inference...",
|
||||||
|
statusGeneratingMask: "Generating transparency mask...",
|
||||||
|
statusSaving: "Saving output transparent image...",
|
||||||
|
statusDone: "Completed!",
|
||||||
|
subFirstRun: "This downloads ~200MB of weights on first run.",
|
||||||
|
subInference: "Extracting details and soft matting alpha...",
|
||||||
|
subSaving: "Assembling high-res RGBA container...",
|
||||||
|
subDefault: "Please wait while the AI model processes...",
|
||||||
|
setupReady: "Ready to configure environment.",
|
||||||
|
setupCreatingVenv: "Creating Python virtual environment...",
|
||||||
|
setupVenvCreated: "Virtual environment successfully created.",
|
||||||
|
setupVenvExists: "Virtual environment already exists.",
|
||||||
|
setupUpgradingPip: "Upgrading Python package installer (pip)...",
|
||||||
|
setupInstallingTorch: "Installing PyTorch AI Engine (CPU version)...",
|
||||||
|
setupDownloadingTorch: "Downloading torch and dependencies...",
|
||||||
|
setupInstallingDeps: "Installing collected packages...",
|
||||||
|
setupCompleted: "Configuration Complete! Enjoy background removal.",
|
||||||
|
setupFailed: "Setup failed. Check system dependencies.",
|
||||||
|
exportingMasterpiece: "Exporting masterpiece...",
|
||||||
|
toastExportSuccess: "Export Successful",
|
||||||
|
toastExportSuccessMsg: "Saved file correctly: ",
|
||||||
|
toastExportFailed: "Export Failed",
|
||||||
|
toastExportFailedMsg: "Save operation failed.",
|
||||||
|
toastExportError: "Export Error",
|
||||||
|
showInExplorer: "Show in File Explorer"
|
||||||
},
|
},
|
||||||
tr: {
|
tr: {
|
||||||
title: "Dekupai - Trunçgil AI Dekupaj",
|
title: "Dekupai - Trunçgil AI Dekupaj",
|
||||||
@@ -603,7 +650,39 @@ const TRANSLATIONS = {
|
|||||||
dragDropSub: "PNG, JPG, JPEG veya WebP formatlarını destekler",
|
dragDropSub: "PNG, JPG, JPEG veya WebP formatlarını destekler",
|
||||||
orText: "VEYA",
|
orText: "VEYA",
|
||||||
browseFiles: "Yerel Dosyalara Göz Atın",
|
browseFiles: "Yerel Dosyalara Göz Atın",
|
||||||
autoTrim: "Oto-Kırp"
|
autoTrim: "Oto-Kırp",
|
||||||
|
statusInit: "AI modeli başlatılıyor...",
|
||||||
|
statusWeights: "Yapay sinir ağları belleğe yükleniyor...",
|
||||||
|
statusImporting: "Kütüphaneler içe aktarılıyor...",
|
||||||
|
statusDetecting: "Donanım tespit ediliyor...",
|
||||||
|
statusUsingDevice: "Kullanılan donanım: ",
|
||||||
|
statusLoadingModel: "BiRefNet modeli yükleniyor...",
|
||||||
|
statusPreprocessing: "Görsel yükleniyor ve ön işleme yapılıyor...",
|
||||||
|
statusInference: "Arka plan temizleme algoritması çalıştırılıyor...",
|
||||||
|
statusGeneratingMask: "Şeffaflık maskesi oluşturuluyor...",
|
||||||
|
statusSaving: "Şeffaf görsel kaydediliyor...",
|
||||||
|
statusDone: "Tamamlandı!",
|
||||||
|
subFirstRun: "İlk çalıştırmada ~200MB ağırlık dosyası indirilir.",
|
||||||
|
subInference: "Detaylar ve yumuşak matlaştırma katmanı çıkarılıyor...",
|
||||||
|
subSaving: "Yüksek çözünürlüklü RGBA görsel birleştiriliyor...",
|
||||||
|
subDefault: "Yapay zeka modeli işleme yaparken lütfen bekleyin...",
|
||||||
|
setupReady: "Ortamı yapılandırmaya hazır.",
|
||||||
|
setupCreatingVenv: "Python sanal ortamı oluşturuluyor...",
|
||||||
|
setupVenvCreated: "Sanal ortam başarıyla oluşturuldu.",
|
||||||
|
setupVenvExists: "Sanal ortam zaten mevcut.",
|
||||||
|
setupUpgradingPip: "Python paket yükleyici (pip) güncelleniyor...",
|
||||||
|
setupInstallingTorch: "PyTorch AI motoru kuruluyor (CPU versiyonu)...",
|
||||||
|
setupDownloadingTorch: "Torch ve bağımlılıklar indiriliyor...",
|
||||||
|
setupInstallingDeps: "Toplanan paketler kuruluyor...",
|
||||||
|
setupCompleted: "Yapılandırma Tamamlandı! Arka plan temizlemenin keyfini çıkarın.",
|
||||||
|
setupFailed: "Kurulum başarısız oldu. Sistem bağımlılıklarını kontrol edin.",
|
||||||
|
exportingMasterpiece: "Çalışma dışa aktarılıyor...",
|
||||||
|
toastExportSuccess: "Dışa Aktarma Başarılı",
|
||||||
|
toastExportSuccessMsg: "Dosya başarıyla kaydedildi: ",
|
||||||
|
toastExportFailed: "Dışa Aktarma Başarısız",
|
||||||
|
toastExportFailedMsg: "Kaydetme işlemi başarısız oldu.",
|
||||||
|
toastExportError: "Dışa Aktarma Hatası",
|
||||||
|
showInExplorer: "Dosya Gezgininde Göster"
|
||||||
},
|
},
|
||||||
de: {
|
de: {
|
||||||
title: "Dekupai - Trunçgil AI Dekupage",
|
title: "Dekupai - Trunçgil AI Dekupage",
|
||||||
@@ -649,13 +728,45 @@ const TRANSLATIONS = {
|
|||||||
stepLibs: "Installation der HuggingFace Transformers & PIL Bibliothek",
|
stepLibs: "Installation der HuggingFace Transformers & PIL Bibliothek",
|
||||||
creditsVision: "Entwickelt unter der Vision von",
|
creditsVision: "Entwickelt unter der Vision von",
|
||||||
creditsExpertise: "durch die Software-Expertise von",
|
creditsExpertise: "durch die Software-Expertise von",
|
||||||
creditsDesc: "Dekupai ist ein fortschrittlicher Deep-Learning-Desktop-Arbeitsbereich, der eine lokale, hochpräzise Hintergrundentfernung mithilfe von BiRefNet-Segmentierungsnetzwerken bietet.",
|
creditsDesc: "Dekupai is ein fortschrittlicher Deep-Learning-Desktop-Arbeitsbereich, der eine lokale, hochpräzise Hintergrundentfernung mithilfe von BiRefNet-Segmentierungsnetzwerken bietet.",
|
||||||
closeCredits: "Schließen",
|
closeCredits: "Schließen",
|
||||||
dragDropText: "Bild hierher ziehen und ablegen",
|
dragDropText: "Bild hierher ziehen und ablegen",
|
||||||
dragDropSub: "Unterstützt PNG-, JPG-, JPEG- oder WebP-Formate",
|
dragDropSub: "Unterstützt PNG-, JPG-, JPEG- oder WebP-Formate",
|
||||||
orText: "ODER",
|
orText: "ODER",
|
||||||
browseFiles: "Lokale Dateien durchsuchen",
|
browseFiles: "Lokale Dateien durchsuchen",
|
||||||
autoTrim: "Auto-Trim"
|
autoTrim: "Auto-Trim",
|
||||||
|
statusInit: "AI-Modell wird initialisiert...",
|
||||||
|
statusWeights: "Neuronale Gewichte werden geladen...",
|
||||||
|
statusImporting: "Bibliotheken werden importiert...",
|
||||||
|
statusDetecting: "Hardware wird erkannt...",
|
||||||
|
statusUsingDevice: "Verwendetes Gerät: ",
|
||||||
|
statusLoadingModel: "BiRefNet-Modell wird geladen...",
|
||||||
|
statusPreprocessing: "Bild wird geladen und vorverarbeitet...",
|
||||||
|
statusInference: "Hintergrundentfernungs-Inferenz wird ausgeführt...",
|
||||||
|
statusGeneratingMask: "Transparenzmaske wird generiert...",
|
||||||
|
statusSaving: "Transparentes Ausgabebild wird gespeichert...",
|
||||||
|
statusDone: "Abgeschlossen!",
|
||||||
|
subFirstRun: "Erster Start lädt Modell herunter (~200MB)",
|
||||||
|
subInference: "Details und weiche Maske werden extrahiert...",
|
||||||
|
subSaving: "Hochauflösender RGBA-Container wird zusammengestellt...",
|
||||||
|
subDefault: "Bitte warten Sie, während das AI-Modell verarbeitet...",
|
||||||
|
setupReady: "Bereit zum Konfigurieren der Umgebung.",
|
||||||
|
setupCreatingVenv: "Isolierte virtuelle Umgebung (.venv) wird erstellt...",
|
||||||
|
setupVenvCreated: "Virtuelle Umgebung erfolgreich erstellt.",
|
||||||
|
setupVenvExists: "Virtuelle Umgebung existiert bereits.",
|
||||||
|
setupUpgradingPip: "Python-Paketinstallateur (pip) wird aktualisiert...",
|
||||||
|
setupInstallingTorch: "PyTorch AI-Engine (CPU-Version) wird installiert...",
|
||||||
|
setupDownloadingTorch: "Torch und Abhängigkeiten werden heruntergeladen...",
|
||||||
|
setupInstallingDeps: "Gesammelte Pakete werden installiert...",
|
||||||
|
setupCompleted: "Konfiguration abgeschlossen! Viel Spaß mit der Hintergrundentfernung.",
|
||||||
|
setupFailed: "Setup fehlgeschlagen. Systemabhängigkeiten prüfen.",
|
||||||
|
exportingMasterpiece: "Meisterwerk wird exportiert...",
|
||||||
|
toastExportSuccess: "Export erfolgreich",
|
||||||
|
toastExportSuccessMsg: "Datei erfolgreich gespeichert: ",
|
||||||
|
toastExportFailed: "Export fehlgeschlagen",
|
||||||
|
toastExportFailedMsg: "Speichervorgang fehlgeschlagen.",
|
||||||
|
toastExportError: "Exportfehler",
|
||||||
|
showInExplorer: "Im Datei-Explorer anzeigen"
|
||||||
},
|
},
|
||||||
ru: {
|
ru: {
|
||||||
title: "Dekupai - Trunçgil AI Декупаж",
|
title: "Dekupai - Trunçgil AI Декупаж",
|
||||||
@@ -707,7 +818,39 @@ const TRANSLATIONS = {
|
|||||||
dragDropSub: "Поддерживает форматы PNG, JPG, JPEG или WebP",
|
dragDropSub: "Поддерживает форматы PNG, JPG, JPEG или WebP",
|
||||||
orText: "ИЛИ",
|
orText: "ИЛИ",
|
||||||
browseFiles: "Обзор локальных файлов",
|
browseFiles: "Обзор локальных файлов",
|
||||||
autoTrim: "Автообрезка"
|
autoTrim: "Автообрезка",
|
||||||
|
statusInit: "Инициализация модели ИИ...",
|
||||||
|
statusWeights: "Загрузка весов нейросети в память...",
|
||||||
|
statusImporting: "Импорт библиотек...",
|
||||||
|
statusDetecting: "Обнаружение устройства...",
|
||||||
|
statusUsingDevice: "Используемое устройство: ",
|
||||||
|
statusLoadingModel: "Загрузка модели BiRefNet...",
|
||||||
|
statusPreprocessing: "Загрузка и предобработка изображения...",
|
||||||
|
statusInference: "Выполнение удаления фона...",
|
||||||
|
statusGeneratingMask: "Генерация маски прозрачности...",
|
||||||
|
statusSaving: "Сохранение выходного прозрачного изображения...",
|
||||||
|
statusDone: "Готово!",
|
||||||
|
subFirstRun: "Первый запуск загружает модель (~200 МБ)",
|
||||||
|
subInference: "Извлечение деталей и мягкой маски альфа...",
|
||||||
|
subSaving: "Сборка RGBA-контейнера высокого разрешения...",
|
||||||
|
subDefault: "Пожалуйста, подождите, пока модель ИИ обрабатывает...",
|
||||||
|
setupReady: "Готов к настройке среды.",
|
||||||
|
setupCreatingVenv: "Создание изолированной виртуальной среды (.venv)...",
|
||||||
|
setupVenvCreated: "Виртуальная среда успешно создана.",
|
||||||
|
setupVenvExists: "Виртуальная среда уже существует.",
|
||||||
|
setupUpgradingPip: "Обновление установщика пакетов Python (pip)...",
|
||||||
|
setupInstallingTorch: "Установка движка ИИ PyTorch (версия CPU)...",
|
||||||
|
setupDownloadingTorch: "Скачивание torch и зависимостей...",
|
||||||
|
setupInstallingDeps: "Установка собранных пакетов...",
|
||||||
|
setupCompleted: "Настройка завершена! Наслаждайтесь удалением фона.",
|
||||||
|
setupFailed: "Ошибка настройки. Проверьте системные зависимости.",
|
||||||
|
exportingMasterpiece: "Экспорт шедевра...",
|
||||||
|
toastExportSuccess: "Экспорт успешен",
|
||||||
|
toastExportSuccessMsg: "Файл успешно сохранен: ",
|
||||||
|
toastExportFailed: "Ошибка экспорта",
|
||||||
|
toastExportFailedMsg: "Операция сохранения не удалась.",
|
||||||
|
toastExportError: "Ошибка экспорта",
|
||||||
|
showInExplorer: "Показать в проводнике"
|
||||||
},
|
},
|
||||||
ar: {
|
ar: {
|
||||||
title: "Dekupai - Trunçgil AI إزالة الخلفية",
|
title: "Dekupai - Trunçgil AI إزالة الخلفية",
|
||||||
@@ -759,7 +902,39 @@ const TRANSLATIONS = {
|
|||||||
dragDropSub: "يدعم صيغ PNG أو JPG أو JPEG أو WebP",
|
dragDropSub: "يدعم صيغ PNG أو JPG أو JPEG أو WebP",
|
||||||
orText: "أو",
|
orText: "أو",
|
||||||
browseFiles: "تصفح الملفات المحلية",
|
browseFiles: "تصفح الملفات المحلية",
|
||||||
autoTrim: "قص تلقائي"
|
autoTrim: "قص تلقائي",
|
||||||
|
statusInit: "تهيئة نموذج الذكاء الاصطناعي...",
|
||||||
|
statusWeights: "تحميل أوزان الشبكة العصبية في الذاكرة...",
|
||||||
|
statusImporting: "استيراد المكتبات...",
|
||||||
|
statusDetecting: "الكشف عن الجهاز...",
|
||||||
|
statusUsingDevice: "الجهاز المستخدم: ",
|
||||||
|
statusLoadingModel: "تحميل نموذج BiRefNet...",
|
||||||
|
statusPreprocessing: "تحميل ومعالجة الصورة مسبقاً...",
|
||||||
|
statusInference: "تشغيل خوارزمية إزالة الخلفية...",
|
||||||
|
statusGeneratingMask: "إنشاء قناع الشفافية...",
|
||||||
|
statusSaving: "حفظ الصورة الشفافة الناتجة...",
|
||||||
|
statusDone: "اكتمل!",
|
||||||
|
subFirstRun: "التشغيل الأول يقوم بتنزيل النموذج (~200 ميجابايت)",
|
||||||
|
subInference: "استخراج التفاصيل والشفافية الناعمة...",
|
||||||
|
subSaving: "تجميع حاوية RGBA عالية الدقة...",
|
||||||
|
subDefault: "يرجى الانتظار أثناء معالجة نموذج الذكاء الاصطناعي...",
|
||||||
|
setupReady: "جاهز لتكوين البيئة.",
|
||||||
|
setupCreatingVenv: "إنشاء بيئة افتراضية معزولة (.venv)...",
|
||||||
|
setupVenvCreated: "تم إنشاء البيئة الافتراضية بنجاح.",
|
||||||
|
setupVenvExists: "البيئة الافتراضية موجودة بالفعل.",
|
||||||
|
setupUpgradingPip: "ترقية مثبت حزم بايثون (pip)...",
|
||||||
|
setupInstallingTorch: "تثبيت محرك الذكاء الاصطناعي PyTorch (نسخة CPU)...",
|
||||||
|
setupDownloadingTorch: "تنزيل torch والاعتمادات...",
|
||||||
|
setupInstallingDeps: "تثبيت الحزم التي تم جمعها...",
|
||||||
|
setupCompleted: "اكتمل التكوين! استمتع بإزالة الخلفية.",
|
||||||
|
setupFailed: "فشل الإعداد. تحقق من تبعيات النظام.",
|
||||||
|
exportingMasterpiece: "تصدير العمل الفني...",
|
||||||
|
toastExportSuccess: "تم التصدير بنجاح",
|
||||||
|
toastExportSuccessMsg: "تم حفظ الملف بنجاح: ",
|
||||||
|
toastExportFailed: "فشل التصدير",
|
||||||
|
toastExportFailedMsg: "فشلت عملية الحفظ.",
|
||||||
|
toastExportError: "خطأ في التصدير",
|
||||||
|
showInExplorer: "عرض في مستكشف الملفات"
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -862,8 +1037,8 @@ async function executeBackgroundRemoval() {
|
|||||||
|
|
||||||
elements.btnRemoveBg.classList.add('hidden');
|
elements.btnRemoveBg.classList.add('hidden');
|
||||||
elements.loaderBox.classList.remove('hidden');
|
elements.loaderBox.classList.remove('hidden');
|
||||||
elements.loaderText.innerText = "Initializing AI model...";
|
elements.loaderText.innerText = getTrans('statusInit');
|
||||||
elements.loaderSubtext.innerText = "Loading neural weights into memory...";
|
elements.loaderSubtext.innerText = getTrans('statusWeights');
|
||||||
|
|
||||||
// Get unique temporary output file path
|
// Get unique temporary output file path
|
||||||
const tempOut = await window.api.getTempPath('transparent_result.png');
|
const tempOut = await window.api.getTempPath('transparent_result.png');
|
||||||
@@ -871,15 +1046,40 @@ async function executeBackgroundRemoval() {
|
|||||||
// Listen to execution progress
|
// Listen to execution progress
|
||||||
window.api.onProcessProgress((progress) => {
|
window.api.onProcessProgress((progress) => {
|
||||||
if (progress.includes("[STATUS]")) {
|
if (progress.includes("[STATUS]")) {
|
||||||
const statusText = progress.replace("[STATUS] ", "");
|
const statusText = progress.replace("[STATUS] ", "").trim();
|
||||||
elements.loaderText.innerText = statusText;
|
|
||||||
|
|
||||||
if (statusText.includes("Hugging Face")) {
|
// Let's map statusText to localized keys
|
||||||
elements.loaderSubtext.innerText = "This downloads ~200MB of weights on first run.";
|
if (statusText.includes("Importing libraries")) {
|
||||||
} else if (statusText.includes("inference")) {
|
elements.loaderText.innerText = getTrans('statusImporting');
|
||||||
elements.loaderSubtext.innerText = "Extracting details and soft matting alpha...";
|
elements.loaderSubtext.innerText = getTrans('subDefault');
|
||||||
} else if (statusText.includes("Saving")) {
|
} else if (statusText.includes("Detecting device")) {
|
||||||
elements.loaderSubtext.innerText = "Assembling high-res RGBA container...";
|
elements.loaderText.innerText = getTrans('statusDetecting');
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subDefault');
|
||||||
|
} else if (statusText.startsWith("Using device:")) {
|
||||||
|
const device = statusText.replace("Using device:", "").trim();
|
||||||
|
elements.loaderText.innerText = getTrans('statusUsingDevice') + device;
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subDefault');
|
||||||
|
} else if (statusText.includes("Loading BiRefNet model")) {
|
||||||
|
elements.loaderText.innerText = getTrans('statusLoadingModel');
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subFirstRun');
|
||||||
|
} else if (statusText.includes("Loading and preprocessing image")) {
|
||||||
|
elements.loaderText.innerText = getTrans('statusPreprocessing');
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subDefault');
|
||||||
|
} else if (statusText.includes("Running background removal inference")) {
|
||||||
|
elements.loaderText.innerText = getTrans('statusInference');
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subInference');
|
||||||
|
} else if (statusText.includes("Generating transparency mask")) {
|
||||||
|
elements.loaderText.innerText = getTrans('statusGeneratingMask');
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subInference');
|
||||||
|
} else if (statusText.includes("Saving output transparent image")) {
|
||||||
|
elements.loaderText.innerText = getTrans('statusSaving');
|
||||||
|
elements.loaderSubtext.innerText = getTrans('subSaving');
|
||||||
|
} else if (statusText.includes("DONE")) {
|
||||||
|
elements.loaderText.innerText = getTrans('statusDone');
|
||||||
|
elements.loaderSubtext.innerText = "";
|
||||||
|
} else {
|
||||||
|
// Fallback for any other status logs
|
||||||
|
elements.loaderText.innerText = statusText;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -889,7 +1089,7 @@ async function executeBackgroundRemoval() {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
processedTempPath = result.outputPath;
|
processedTempPath = result.outputPath;
|
||||||
showToast("AI Success", "Image background removed successfully!", "success");
|
showToast(getTrans('toastTitleSuccess'), getTrans('toastTrimCompleteMsg'), "success");
|
||||||
|
|
||||||
// Update workspace preview image source to output transparent PNG
|
// Update workspace preview image source to output transparent PNG
|
||||||
// Add timestamp to bypass browser cache refreshing
|
// Add timestamp to bypass browser cache refreshing
|
||||||
@@ -909,10 +1109,10 @@ async function executeBackgroundRemoval() {
|
|||||||
}, 300);
|
}, 300);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
showToast("Inference Error", result.error || "Execution terminated unexpectedly.", "error");
|
showToast(getTrans('toastTitleError'), result.error || getTrans('toastSetupErrorMsg'), "error");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast("AI Fatal Error", err.message, "error");
|
showToast(getTrans('toastTitleError'), err.message, "error");
|
||||||
} finally {
|
} finally {
|
||||||
elements.loaderBox.classList.add('hidden');
|
elements.loaderBox.classList.add('hidden');
|
||||||
elements.btnRemoveBg.classList.remove('hidden');
|
elements.btnRemoveBg.classList.remove('hidden');
|
||||||
@@ -1006,7 +1206,7 @@ async function executeExport() {
|
|||||||
elements.btnExport.disabled = true;
|
elements.btnExport.disabled = true;
|
||||||
elements.btnExport.innerHTML = `
|
elements.btnExport.innerHTML = `
|
||||||
<svg class="loader-ring" viewBox="0 0 50 50" style="width:16px;height:16px;margin:0;"><circle cx="25" cy="25" r="20" fill="none" stroke-width="4" stroke="#fff"></circle></svg>
|
<svg class="loader-ring" viewBox="0 0 50 50" style="width:16px;height:16px;margin:0;"><circle cx="25" cy="25" r="20" fill="none" stroke-width="4" stroke="#fff"></circle></svg>
|
||||||
<span>Exporting masterpiece...</span>
|
<span>${getTrans('exportingMasterpiece')}</span>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
@@ -1069,22 +1269,22 @@ async function executeExport() {
|
|||||||
|
|
||||||
if (result.success) {
|
if (result.success) {
|
||||||
showToastWithAction(
|
showToastWithAction(
|
||||||
"Export Successful",
|
getTrans('toastExportSuccess'),
|
||||||
`Saved file correctly: ${result.filePath.split(/[\\/]/).pop()}`,
|
`${getTrans('toastExportSuccessMsg')}${result.filePath.split(/[\\/]/).pop()}`,
|
||||||
"success",
|
"success",
|
||||||
result.filePath
|
result.filePath
|
||||||
);
|
);
|
||||||
} else if (!result.canceled) {
|
} else if (!result.canceled) {
|
||||||
showToast("Export Failed", result.error || "Save operation failed.", "error");
|
showToast(getTrans('toastExportFailed'), result.error || getTrans('toastExportFailedMsg'), "error");
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showToast("Export Error", err.message, "error");
|
showToast(getTrans('toastExportError'), err.message, "error");
|
||||||
} finally {
|
} finally {
|
||||||
// Re-enable button
|
// Re-enable button
|
||||||
elements.btnExport.disabled = false;
|
elements.btnExport.disabled = false;
|
||||||
elements.btnExport.innerHTML = `
|
elements.btnExport.innerHTML = `
|
||||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path><polyline points="7 10 12 15 17 10"></polyline><line x1="12" y1="15" x2="12" y2="3"></line></svg>
|
||||||
<span>Export Masterpiece</span>
|
<span>${getTrans('exportMasterpiece')}</span>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
}, 100);
|
}, 100);
|
||||||
@@ -1118,7 +1318,7 @@ function showToastWithAction(title, message, type = 'success', filePath) {
|
|||||||
hideToast();
|
hideToast();
|
||||||
|
|
||||||
elements.toastTitle.innerText = title;
|
elements.toastTitle.innerText = title;
|
||||||
elements.toastMessage.innerHTML = `${message} <br><button id="btn-toast-explore" class="btn btn-secondary btn-sm" style="margin-top:6px;width:100%;">Show in File Explorer</button>`;
|
elements.toastMessage.innerHTML = `${message} <br><button id="btn-toast-explore" class="btn btn-secondary btn-sm" style="margin-top:6px;width:100%;">${getTrans('showInExplorer')}</button>`;
|
||||||
|
|
||||||
elements.toastBanner.className = 'toast-notification glass-panel-inner';
|
elements.toastBanner.className = 'toast-notification glass-panel-inner';
|
||||||
if (type === 'success') elements.toastBanner.classList.add('success');
|
if (type === 'success') elements.toastBanner.classList.add('success');
|
||||||
|
|||||||
+5
-1
@@ -348,13 +348,17 @@ body {
|
|||||||
left: 0;
|
left: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
z-index: 1;
|
z-index: 1 !important;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
transition: opacity 0.3s ease;
|
transition: opacity 0.3s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* CropperJS Custom Visual Styling overrides */
|
/* CropperJS Custom Visual Styling overrides */
|
||||||
|
.cropper-container {
|
||||||
|
z-index: 2 !important;
|
||||||
|
}
|
||||||
|
|
||||||
.cropper-view-box {
|
.cropper-view-box {
|
||||||
outline: 2px solid var(--accent-purple);
|
outline: 2px solid var(--accent-purple);
|
||||||
outline-color: var(--accent-purple);
|
outline-color: var(--accent-purple);
|
||||||
|
|||||||
Reference in New Issue
Block a user