// ==UserScript==
// @name Imagem Pro
// @name:pt-BR Imagem Pro
// @name:en Image Pro
// @name:es Imagen Pro
// @name:fr Image Pro
// @name:zh 图像专业版
// @name:ar صورة برو
// @name:hi इमेज प्रो
// @name:ja 画像プロ
// @name:ru Изображение Про
// @name:bn ইমেজ প্রো
// @name:ur تصویر پرو
// @description Image Pro is a powerful bulk image downloader built to turn any website into a complete visual capture hub. With a user-friendly graphical interface and advanced tools, it lets you collect, preview, filter, convert, and download dozens or hundreds of images at once — quickly and efficiently.
// @description:pt-BR O Imagem Pro é uma ferramenta poderosa de download em massa de imagens, feita para transformar qualquer site em uma central completa de captura visual. Com uma interface gráfica amigável e recursos avançados, ele permite coletar, visualizar, filtrar, converter e baixar dezenas ou centenas de imagens de uma vez só — tudo com apenas alguns cliques.
// @description:en Imagem Pro is a powerful bulk image downloader built to turn any website into a complete visual capture hub. With a user-friendly graphical interface and advanced tools, it lets you collect, preview, filter, convert, and download dozens or hundreds of images at once — quickly and efficiently.
// @description:es Imagen Pro es una poderosa herramienta de descarga masiva de imágenes, diseñada para convertir cualquier sitio web en un centro completo de captura visual. Con una interfaz gráfica fácil de usar y herramientas avanzadas, te permite recopilar, previsualizar, filtrar, convertir y descargar docenas o cientos de imágenes a la vez — rápida y eficientemente.
// @description:fr Image Pro est une puissante téléchargeuse de masse d'images conçue pour transformer n'importe quel site Web en un centre complet de capture visuelle. Avec une interface graphique conviviale et des outils avancés, il vous permet de collecter, prévisualiser, filtrer, convertir et télécharger des dizaines ou des centaines d'images en une seule fois — rapidement et efficacement.
// @description:zh Imagem Pro 是一个功能强大的批量图片下载器,旨在将任何网站变成一个完整的视觉捕捉中心。它具有用户友好的图形界面和高级工具,可以让你一次性收集、预览、过滤、转换和下载数十或数百张图片 — 快速而高效。
// @description:ar صورة برو هي أداة تنزيل صور عالية الأداء تم بناؤها لتحويل أي موقع ويب إلى مركز كامل للتقاط الصور. مع واجهة مستخدم مريحة وأدوات متقدمة، يمكنك تجميع ومعاينة وتصفية وتحويل وتنزيل عشرات أو مئات الصور في وقت واحد — بسرعة وكفاءة.
// @description:hi इमेज प्रो एक शक्तिशाली बैच इमेज डाउनलोडर है, जो किसी भी वेबसाइट को एक पूर्ण दृश्य कैप्चर हब में बदलने के लिए बनाया गया है। यह आपको एक उपयोगकर्ता के अनुकूल ग्राफिकल इंटरफेस और उन्नत उपकरणों के साथ, एक बार में दर्जनों या सैकड़ों छवियों को इकट्ठा करने, पूर्वावलोकन करने, फ़िल्टर करने, रूपांतरित करने और डाउनलोड करने की अनुमति देता है - जल्दी और कुशलता से。
// @description:ja イメージプロは、任意のWebサイトを完全なビジュアルキャプチャハブに変えるために構築された強力なバルク画像ダウンローダーです。ユーザーフレンドリーなグラフィカルインターフェイスと高度なツールを使用すると、数十または数百の画像を一度に収集、プレビュー、フィルタリング、変換、およびダウンロードできます - 迅速かつ効率的に。
// @description:ru Изображение Pro — это мощный инструмент для скачивания изображений, предназначенный для преобразования любого веб-сайта в полный центр виртуального захвата. С удобным графическим интерфейсом и расширенными инструментами, он позволяет собирать, просматривать, фильтровать, конвертировать и скачивать десятки или сотни изображений за раз — быстро и эффективно.
// @description:bn ইমেজ প্রো একটি শক্তিশালী টুল, যা যেকোনো ওয়েবসাইটকে একটি সম্পূর্ণ ইমেজ হাব হিসেবে রূপান্তর করতে ডিজাইন করা হয়েছে। এর মাধ্যমে আপনি একাধিক ছবি একসাথে সংগ্রহ, দেখানো, ফিল্টার, কনভার্ট এবং ডাউনলোড করতে পারেন - সবকিছুই ব্যবহারকারী-বান্ধব গ্রাফিক্যাল ইন্টারফেস, সঠিক ফিল্টার, বহু ভাষার সমর্থন এবং রিভার্স ইমেজ সার্চ টুলগুলির সাথে একীকরণের মাধ্যমে。
// @description:ur تصویر پرو ایک طاقتور ٹول ہے، جو کسی بھی ویب سائٹ کو ایک مکمل امیج حب میں تبدیل کرنے کے لیے بنایا گیا ہے۔ اس کے ذریعے آپ ایک ساتھ کئی تصاویر جمع، دیکھ، فلٹر، تبدیل اور ڈاؤن لوڈ کر سکتے ہیں - سب کچھ صارف دوست گرافیکل انٹرفیس، درست فلٹرز، کثیر لسانی حمایت اور ریورس امیج سرچ ٹولز کے ساتھ انضمام کے ذریعے۔
// @namespace L4pisD4Silv4_Imagem_Pro
// @version 1.0
// @author L4pisD4Silv4
// @homepage https://ko-fi.com/l4pisd4silv4#
// @icon https://cdn-icons-png.flaticon.com/512/685/685687.png
// @match *://*/*
// @grant GM_download
// @grant GM_setValue
// @grant GM_getValue
// @grant GM_registerMenuCommand
// @grant GM_xmlhttpRequest
// @require https://update.greasyfork.dpdns.org/scripts/518632/1489865/jszip-min-js.js
// @license AGPL-3.0
// ==/UserScript==
/*
⚠️AVISO IMPORTANTE⚠️
Este script está protegido pelo autor e seu uso deve ser feito de forma ética e responsável.
Não autoriza a cópia, redistribuição, modificação ou uso comercial sem autorização prévia e expressa.
Se desejar permissão para qualquer uso além do pessoal, entre em contato:
L4pisD4Silv4 — https://ko-fi.com/l4pisd4silv4#
Obrigado por respeitar o esforço e dedicação dedicados a este projeto.
*/
(function() {
'use strict';
const ImagemPro = {
imageToConvert: null,
hotkeyListener: null,
eventListeners: [],
currentLang: 'pt-br'
};
const imagemProPolicy = window.trustedTypes
? window.trustedTypes.createPolicy('imagem-pro-policy', {
createHTML: (input) => input,
createScriptURL: (input) => input,
createScript: (input) => input
})
: null;
function setInnerHTML(element, html) {
if (element) {
if (window.trustedTypes && imagemProPolicy) {
element.innerHTML = imagemProPolicy.createHTML(html);
} else {
element.innerHTML = html;
}
}
}
function debug(message, isError = false) {
if (isError) {
console.error('[Imagem Pro]', message);
} else {
console.log('[Imagem Pro]', message);
}
}
function registerMenuCommands() {
if (typeof GM_registerMenuCommand !== 'undefined') {
try {
GM_registerMenuCommand(__('menuOpenPanel'), togglePanel);
GM_registerMenuCommand(__('menuLanguages'), showLanguageMenu);
GM_registerMenuCommand(__('menuSupportMe'), function() {
criarBanner();
});
debug('Comandos de menu registrados com sucesso');
} catch (menuErr) {
debug('Erro ao registrar comandos de menu: ' + menuErr.message, true);
}
} else {
debug('GM_registerMenuCommand não disponível, usando apenas atalho');
}
}
function initLanguage() {
const savedLang = GM_getValue('imagemProLanguage', 'pt-br');
ImagemPro.currentLang = savedLang;
if (typeof GM_registerMenuCommand !== 'undefined') {
registerMenuCommands();
}
const styleEl = document.createElement('style');
styleEl.textContent = languageMenuStyles;
document.head.appendChild(styleEl);
}
function changeLanguage(langCode) {
try {
if (!translations[langCode]) {
langCode = translations['en'] ? 'en' : 'pt-br';
}
GM_setValue('imagemProLanguage', langCode);
const feedbackDiv = document.createElement('div');
feedbackDiv.style.cssText = `
position: fixed !important;
top: 20px !important;
left: 50% !important;
transform: translateX(-50%) !important;
background: rgba(46, 204, 113, 0.9) !important;
color: white !important;
padding: 15px 25px !important;
border-radius: 8px !important;
z-index: 9999999 !important;
font-family: 'Kiwi Maru' !important;
box-shadow: 0 4px 15px rgba(0,0,0,0.3) !important;
animation: slideDown 0.3s ease !important;
`;
switch(langCode) {
case 'en':
feedbackDiv.textContent = 'Language changed to English! Reloading page...';
break;
case 'es':
feedbackDiv.textContent = '¡Idioma cambiado a Español! Recargando página...';
break;
case 'zh':
feedbackDiv.textContent = '语言已更改为中文!重新加载页面...';
break;
case 'fr':
feedbackDiv.textContent = 'Langue changée en Français! Rechargement de la page...';
break;
case 'ar':
feedbackDiv.textContent = 'تم تغيير اللغة إلى العربية! جاري إعادة تحميل الصفحة...';
break;
case 'hi':
feedbackDiv.textContent = 'भाषा हिंदी में बदली गई! पेज रीलोड हो रहा है...';
break;
case 'ja':
feedbackDiv.textContent = '言語が日本語に変更されました!ページを再読み込みしています...';
break;
case 'ru':
feedbackDiv.textContent = 'Язык изменен на русский! Перезагрузка страницы...';
break;
case 'bn':
feedbackDiv.textContent = 'ভাষা বাংলায় পরিবর্তন করা হয়েছে! পৃষ্ঠা পুনরায় লোড হচ্ছে...';
break;
case 'ur':
feedbackDiv.textContent = 'زبان اردو میں تبدیل کر دی گئی ہے! صفحہ دوبارہ لوڈ ہو رہا ہے...';
break;
default:
feedbackDiv.textContent = 'Idioma alterado para Português! Recarregando página...';
break;
}
document.body.appendChild(feedbackDiv);
setTimeout(() => {
location.reload();
}, 1500);
} catch (e) {
console.error('Error changing language:', e);
}
}
function setupSettingsSaveButton() {
const saveButton = document.getElementById('settings-save-btn');
if (!saveButton) {
console.error('Botão de salvar configurações não encontrado!');
return;
}
saveButton.addEventListener('click', function() {
try {
console.log('Botão de salvar configurações clicado');
const zipDownloadElem = document.getElementById('settings-zip-download');
const gifConvertElem = document.getElementById('settings-gif-convert');
const autoConvertElem = document.getElementById('settings-auto-convert');
const searchEngineElem = document.getElementById('settings-search-engine');
const hotkeyInput = document.getElementById('settings-hotkey');
const limitPxElem = document.getElementById('settings-limit-px');
const pixelPriorityElem = document.getElementById('settings-pixel-priority');
if (hotkeyInput && hotkeyInput.dataset.storedValue) {
hotkeyInput.value = hotkeyInput.dataset.storedValue;
}
const newSettings = {
zipDownload: zipDownloadElem ? zipDownloadElem.checked : defaultSettings.zipDownload,
convertGifToMp4: gifConvertElem ? gifConvertElem.checked : defaultSettings.convertGifToMp4,
autoConvertFormat: autoConvertElem ? autoConvertElem.value : defaultSettings.autoConvertFormat,
searchEngine: searchEngineElem ? searchEngineElem.value : defaultSettings.searchEngine,
hotkeyCombo: hotkeyInput ? hotkeyInput.value : defaultSettings.hotkeyCombo,
limitPx: limitPxElem ? parseInt(limitPxElem.value || 0) : defaultSettings.limitPx,
pixelPriority: pixelPriorityElem ? pixelPriorityElem.value : defaultSettings.pixelPriority
};
console.log('Salvando configurações:', newSettings);
GM_setValue('imagemProSettings', JSON.stringify(newSettings));
console.log('Configurações salvas com sucesso');
const modal = document.querySelector('#imagem-pro-settings-modal');
if (modal) {
modal.classList.remove('show');
}
showSavedMessage();
} catch (error) {
console.error('Erro ao salvar configurações:', error);
showErrorMessage(error.message);
}
});
}
function showSavedMessage() {
const feedbackDiv = document.createElement('div');
feedbackDiv.style.cssText = `
position: fixed !important;
top: 20px !important;
left: 50% !important;
transform: translateX(-50%) !important;
background: rgba(46, 204, 113, 0.9) !important;
color: white !important;
padding: 15px 25px !important;
border-radius: 8px !important;
z-index: 9999999 !important;
font-family: 'Kiwi Maru' !important;
box-shadow: 0 4px 15px rgba(0,0,0,0.3) !important;
animation: slideDown 0.3s ease !important;
`;
feedbackDiv.textContent = __('settingsSaved');
document.body.appendChild(feedbackDiv);
console.log('Mensagem de salvamento exibida, recarregando em 1.5s');
setTimeout(() => {
location.reload();
}, 1500);
}
function showErrorMessage(message) {
const feedbackDiv = document.createElement('div');
feedbackDiv.style.cssText = `
position: fixed !important;
top: 20px !important;
left: 50% !important;
transform: translateX(-50%) !important;
background: rgba(255, 77, 77, 0.9) !important;
color: white !important;
padding: 15px 25px !important;
border-radius: 8px !important;
z-index: 9999999 !important;
font-family: 'Kiwi Maru' !important;
box-shadow: 0 4px 15px rgba(0,0,0,0.3) !important;
animation: slideDown 0.3s ease !important;
`;
feedbackDiv.textContent = 'Erro ao salvar: ' + message;
document.body.appendChild(feedbackDiv);
setTimeout(() => {
feedbackDiv.remove();
}, 3000);
}
const translations = {
"pt-br": {
title: "Imagem Pro",
found: "Encontradas {} images",
foundSingular: "Encontrada {} imagem",
noImages: "Nenhuma imagem encontrada com os filtros atuais.",
loading: "Carregando imagens...",
searchingNew: "Procurando novas imagens...",
selectAll: "Selecionar todas",
selected: "{} de {} selecionada{}",
refresh: "Atualizar",
downloadSelected: "Baixar selecionadas",
close: "Fechar",
openNewTab: "Abrir em nova guia",
searchWith: "Pesquisar com {}",
downloadImage: "Baixar imagem",
allFormats: "Todos os formatos",
allQualities: "Todas as qualidades",
allPositions: "Todas as posições",
highQuality: "Alta qualidade",
mediumQuality: "Média qualidade",
lowQuality: "Baixa qualidade",
topPage: "Topo da página",
middlePage: "Centro da página",
bottomPage: "Final da página",
format: "Formato",
quality: "Qualidade",
position: "Posição",
dimensions: "Dimensões",
url: "URL",
settings: "Configurações",
generalTab: "Geral",
converterTab: "Converter",
searchTab: "Pesquisar",
zipDownload: "Baixar em massa .ZIP",
convertGif: "Converter GIF/MP4",
autoConversion: "Conversão Automática",
original: "Original",
searchEngine: "Procurar Imagem",
hotkey: "Atalho de Teclado",
filterMinSize: "Filtrar Tamanho Mínimo",
reset: "Resetar",
save: "Salvar",
supportDev: "Apoie o Desenvolvedor",
importImage: "Importar Imagem",
noImageSelected: "Nenhuma imagem selecionada",
convert: "Converter",
converting: "Convertendo...",
preparing: "Preparando...",
loadingImage: "Carregando imagem...",
convertingTo: "Convertendo para {}...",
finishing: "Finalizando...",
downloadStarted: "Download iniciado!",
conversionComplete: "Conversão concluída",
conversionSuccess: "Imagem convertida com sucesso para {}!",
searchPlaceholder: "Digite o que deseja pesquisar...",
emptyField: "Campo vazio",
pleaseEnterSearch: "Por favor, digite o que deseja pesquisar.",
attention: "Atenção - Download Individual",
individualDownloadMsg: "Ao desativar o download em massa ZIP, o navegador poderá perguntar onde salvar CADA arquivo individualmente. Para evitar isso, configure seu navegador:\n\nVá em \"Configurações > Downloads\" e desative \"Perguntar onde salvar cada arquivo antes de fazer download\".\n\nCaso contrário, o navegador perguntará onde salvar cada imagem separadamente.",
understood: "Entendi",
selectOneImage: "Selecione pelo menos uma imagem para baixar.",
noImageConverterMsg: "Por favor, selecione uma imagem antes de converter.",
ok: "OK",
settingsSaved: "Configurações salvas! Recarregando página...",
preparingDownload: "Preparando download individual...",
processingImage: "Processando imagem {} de {}...",
errorProcessingImage: "Erro: Não foi possível processar nenhuma imagem. Tentando método alternativo...",
generatingZip: "Gerando arquivo ZIP com {} imagens...",
pressKeys: "Pressione combinação de teclas...",
clickToSetHotkey: "Clique para definir atalho",
clickAndPress: "(clique e pressione teclas)",
switchToEnglish: "Alternar para Inglês",
invalidUrl: "URL inválida",
noImage: "Sem imagem",
menuOpenPanel: "📷 Painel de Imagens",
menuLanguages: "🌐 Idiomas",
menuSupportMe: "🙌 Apoiar Desenvolvedor",
quality_alta: "Alta",
quality_média: "Média",
quality_baixa: "Baixa",
position_topo: "Topo",
position_meio: "Centro",
position_baixo: "Final",
otherFormats: "Outros",
pixelPriority: "Priorizar",
pixelPriorityNormal: "Normal",
pixelPriorityHigher: "Maior pixel",
pixelPriorityLower: "Menor pixel",
refreshingImages: "Atualizando imagens..."
},
"en": {
title: "Image Pro",
found: "{} images found",
foundSingular: "{} image found",
noImages: "No images found with current filters.",
loading: "Loading images...",
searchingNew: "Searching for new images...",
selectAll: "Select all",
selected: "{} of {} selected",
refresh: "Refresh",
downloadSelected: "Download selected",
close: "Close",
openNewTab: "Open in new tab",
searchWith: "Search with {}",
downloadImage: "Download image",
allFormats: "All formats",
allQualities: "All qualities",
allPositions: "All positions",
highQuality: "High quality",
mediumQuality: "Medium quality",
lowQuality: "Low quality",
topPage: "Top of page",
middlePage: "Middle of page",
bottomPage: "Bottom of page",
format: "Format",
quality: "Quality",
position: "Position",
dimensions: "Dimensions",
url: "URL",
settings: "Settings",
generalTab: "General",
converterTab: "Convert",
searchTab: "Search",
zipDownload: "Batch download as ZIP",
convertGif: "Convert GIF to MP4",
autoConversion: "Auto Conversion",
original: "Original",
searchEngine: "Image Search",
hotkey: "Keyboard Shortcut",
filterMinSize: "Filter Min Size",
reset: "Reset",
save: "Save",
supportDev: "Support Developer",
importImage: "Import Image",
noImageSelected: "No image selected",
convert: "Convert",
converting: "Converting...",
preparing: "Preparing...",
loadingImage: "Loading image...",
convertingTo: "Converting to {}...",
finishing: "Finishing...",
downloadStarted: "Download started!",
conversionComplete: "Conversion complete",
conversionSuccess: "Image successfully converted to {}!",
searchPlaceholder: "Type what you want to search...",
emptyField: "Empty field",
pleaseEnterSearch: "Please enter what you want to search.",
attention: "Attention - Individual Download",
individualDownloadMsg: "By disabling batch ZIP download, the browser might ask where to save EACH file individually. To avoid this, configure your browser:\n\nGo to \"Settings > Downloads\" and disable \"Ask where to save each file before downloading\".\n\nOtherwise, the browser will ask where to save each image separately.",
understood: "Understood",
selectOneImage: "Select at least one image to download.",
noImageConverterMsg: "Please select an image before converting.",
ok: "OK",
settingsSaved: "Settings saved! Reloading page...",
preparingDownload: "Preparing individual download...",
processingImage: "Processing image {} of {}...",
errorProcessingImage: "Error: Could not process any images. Trying alternative method...",
generatingZip: "Generating ZIP file with {} images...",
pressKeys: "Press key combination...",
clickToSetHotkey: "Click to set hotkey",
clickAndPress: "(click and press keys)",
switchToEnglish: "Switch to Portuguese",
invalidUrl: "Invalid URL",
noImage: "No image",
menuOpenPanel: "📷 Image Panel",
menuLanguages: "🌐 Languages",
menuSupportMe: "🙌 Support Developer",
quality_alta: "High",
quality_média: "Medium",
quality_baixa: "Low",
position_topo: "Top",
position_meio: "Middle",
position_baixo: "Bottom",
otherFormats: "Others",
pixelPriority: "Prioritize",
pixelPriorityNormal: "Normal",
pixelPriorityHigher: "Higher pixel",
pixelPriorityLower: "Lower pixel",
refreshingImages: "Refreshing images..."
},
"es": {
title: "Imagen Pro",
found: "{} imágenes encontradas",
foundSingular: "{} imagen encontrada",
noImages: "No se encontraron imágenes con los filtros actuales.",
loading: "Cargando imágenes...",
searchingNew: "Buscando nuevas imágenes...",
selectAll: "Seleccionar todo",
selected: "{} de {} seleccionada{}",
refresh: "Actualizar",
downloadSelected: "Descargar seleccionadas",
close: "Cerrar",
openNewTab: "Abrir en nueva pestaña",
searchWith: "Buscar con {}",
downloadImage: "Descargar imagen",
allFormats: "Todos los formatos",
allQualities: "Todas las calidades",
allPositions: "Todas las posiciones",
highQuality: "Alta calidad",
mediumQuality: "Calidad media",
lowQuality: "Baja calidad",
topPage: "Parte superior",
middlePage: "Centro de página",
bottomPage: "Parte inferior",
format: "Formato",
quality: "Calidad",
position: "Posición",
dimensions: "Dimensiones",
url: "URL",
settings: "Configuración",
generalTab: "General",
converterTab: "Convertir",
searchTab: "Buscar",
zipDownload: "Descarga masiva .ZIP",
convertGif: "Convertir GIF/MP4",
autoConversion: "Conversión automática",
original: "Original",
searchEngine: "Buscador de imágenes",
hotkey: "Atajo de teclado",
filterMinSize: "Filtrar tamaño mínimo",
reset: "Restablecer",
save: "Guardar",
supportDev: "Apoyar al desarrollador",
importImage: "Importar imagen",
noImageSelected: "Ninguna imagen seleccionada",
convert: "Convertir",
converting: "Convirtiendo...",
preparing: "Preparando...",
loadingImage: "Cargando imagen...",
convertingTo: "Convirtiendo a {}...",
finishing: "Finalizando...",
downloadStarted: "¡Descarga iniciada!",
conversionComplete: "Conversión completa",
conversionSuccess: "¡Imagen convertida exitosamente a {}!",
searchPlaceholder: "Escribe lo que deseas buscar...",
emptyField: "Campo vacío",
pleaseEnterSearch: "Por favor, escribe lo que deseas buscar.",
attention: "Atención - Descarga individual",
individualDownloadMsg: "Al desactivar la descarga masiva ZIP, el navegador podría preguntar dónde guardar CADA archivo individualmente. Para evitar esto, configura tu navegador:\n\nVe a \"Configuración > Descargas\" y desactiva \"Preguntar dónde guardar cada archivo antes de descargar\".\n\nDe lo contrario, el navegador preguntará dónde guardar cada imagen por separado.",
understood: "Entendido",
selectOneImage: "Selecciona al menos una imagen para descargar.",
noImageConverterMsg: "Por favor, selecciona una imagen antes de convertir.",
ok: "OK",
settingsSaved: "¡Configuración guardada! Recargando página...",
preparingDownload: "Preparando descarga individual...",
processingImage: "Procesando imagen {} de {}...",
errorProcessingImage: "Error: No se pudieron procesar las imágenes. Intentando método alternativo...",
generatingZip: "Generando archivo ZIP con {} imágenes...",
pressKeys: "Presiona combinación de teclas...",
clickToSetHotkey: "Haz clic para definir atajo",
clickAndPress: "(haz clic y presiona teclas)",
switchToEnglish: "Cambiar a Inglés",
invalidUrl: "URL inválida",
noImage: "Sin imagen",
menuOpenPanel: "📷 Panel de imágenes",
menuLanguages: "🌐 Idiomas",
menuSupportMe: "🙌 Apoyar al desarrollador",
quality_alta: "Alta",
quality_média: "Media",
quality_baixa: "Baja",
position_topo: "Top",
position_meio: "Middle",
position_baixo: "Bottom",
otherFormats: "Otros",
pixelPriority: "Priorizar",
pixelPriorityNormal: "Normal",
pixelPriorityHigher: "Pixel más alto",
pixelPriorityLower: "Pixel más bajo",
refreshingImages: "Actualizando imágenes..."
},
"fr": {
title: "Image Pro",
found: "{} images trouvées",
foundSingular: "{} image trouvée",
noImages: "Aucune image trouvée avec les filtres actuels.",
loading: "Chargement des images...",
searchingNew: "Recherche de nouvelles images...",
selectAll: "Sélectionner tout",
selected: "{} sur {} sélectionnée{}",
refresh: "Actualiser",
downloadSelected: "Télécharger la sélection",
close: "Fermer",
openNewTab: "Ouvrir dans un nouvel onglet",
searchWith: "Rechercher avec {}",
downloadImage: "Télécharger l'image",
allFormats: "Tous les formats",
allQualities: "Toutes les qualités",
allPositions: "Toutes les positions",
highQuality: "Haute qualité",
mediumQuality: "Qualité moyenne",
lowQuality: "Basse qualité",
topPage: "Haut de page",
middlePage: "Milieu de page",
bottomPage: "Bas de page",
format: "Format",
quality: "Qualité",
position: "Position",
dimensions: "Dimensions",
url: "URL",
settings: "Paramètres",
generalTab: "Général",
converterTab: "Convertir",
searchTab: "Rechercher",
zipDownload: "Téléchargement groupé .ZIP",
convertGif: "Convertir GIF/MP4",
autoConversion: "Conversion automatique",
original: "Original",
searchEngine: "Recherche d'image",
hotkey: "Raccourci clavier",
filterMinSize: "Filtrer taille minimale",
reset: "Réinitialiser",
save: "Enregistrer",
supportDev: "Soutenir le développeur",
importImage: "Importer une image",
noImageSelected: "Aucune image sélectionnée",
convert: "Convertir",
converting: "Conversion...",
preparing: "Préparation...",
loadingImage: "Chargement de l'image...",
convertingTo: "Conversion en {}...",
finishing: "Finalisation...",
downloadStarted: "Téléchargement démarré !",
conversionComplete: "Conversion terminée",
conversionSuccess: "Image convertie avec succès en {} !",
searchPlaceholder: "Tapez ce que vous voulez rechercher...",
emptyField: "Champ vide",
pleaseEnterSearch: "Veuillez saisir ce que vous souhaitez rechercher.",
attention: "Attention - Téléchargement individuel",
individualDownloadMsg: "En désactivant le téléchargement ZIP groupé, le navigateur pourrait demander où enregistrer CHAQUE fichier individuellement. Pour éviter cela, configurez votre navigateur :\n\nAllez dans \"Paramètres > Téléchargements\" et désactivez \"Demander où enregistrer chaque fichier avant le téléchargement\".\n\nSinon, le navigateur demandera où enregistrer chaque image séparément.",
understood: "Compris",
selectOneImage: "Sélectionnez au moins une image à télécharger.",
noImageConverterMsg: "Veuillez sélectionner une image avant de convertir.",
ok: "OK",
settingsSaved: "Paramètres sauvegardés ! Rechargement de la page...",
preparingDownload: "Préparation du téléchargement individuel...",
processingImage: "Traitement de l'image {} sur {}...",
errorProcessingImage: "Erreur : Impossible de traiter les images. Essai de méthode alternative...",
generatingZip: "Génération du fichier ZIP avec {} images...",
pressKeys: "Appuyez sur combinaison de touches...",
clickToSetHotkey: "Cliquez pour définir le raccourci",
clickAndPress: "(cliquez et appuyez sur les touches)",
switchToEnglish: "Passer à l'Anglais",
invalidUrl: "URL invalide",
noImage: "Pas d'image",
menuOpenPanel: "📷 Panneau d'images",
menuLanguages: "🌐 Langues",
menuSupportMe: "🙌 Soutenir le développeur",
quality_alta: "Haute",
quality_média: "Média",
quality_baixa: "Basse",
position_topo: "Haut",
position_meio: "Milieu",
position_baixo: "Bas",
otherFormats: "Autres",
pixelPriority: "Prioriser",
pixelPriorityNormal: "Normal",
pixelPriorityHigher: "Pixel supérieur",
pixelPriorityLower: "Pixel inférieur",
refreshingImages: "Mise à jour des images..."
},
"zh": {
title: "图像专业版",
found: "找到 {} 张图片",
foundSingular: "找到 {} 张图片",
noImages: "当前过滤条件下未找到图片。",
loading: "正在加载图片...",
searchingNew: "正在搜索新图片...",
selectAll: "全选",
selected: "已选择 {}/{}",
refresh: "刷新",
downloadSelected: "下载所选",
close: "关闭",
openNewTab: "在新标签页中打开",
searchWith: "用 {} 搜索",
downloadImage: "下载图片",
allFormats: "所有格式",
allQualities: "所有质量",
allPositions: "所有位置",
highQuality: "高质量",
mediumQuality: "中等质量",
lowQuality: "低质量",
topPage: "页面顶部",
middlePage: "页面中部",
bottomPage: "页面底部",
format: "格式",
quality: "质量",
position: "位置",
dimensions: "尺寸",
url: "网址",
settings: "设置",
generalTab: "常规",
converterTab: "转换",
searchTab: "搜索",
zipDownload: "批量下载 .ZIP",
convertGif: "转换 GIF/MP4",
autoConversion: "自动转换",
original: "原始格式",
searchEngine: "图片搜索",
hotkey: "键盘快捷键",
filterMinSize: "过滤最小尺寸",
reset: "重置",
save: "保存",
supportDev: "支持开发者",
importImage: "导入图片",
noImageSelected: "未选择图片",
convert: "转换",
converting: "正在转换...",
preparing: "正在准备...",
loadingImage: "正在加载图片...",
convertingTo: "正在转换为 {}...",
finishing: "正在完成...",
downloadStarted: "下载已开始!",
conversionComplete: "转换完成",
conversionSuccess: "图片已成功转换为 {}!",
searchPlaceholder: "输入你想搜索的内容...",
emptyField: "空白字段",
pleaseEnterSearch: "请输入你想搜索的内容。",
attention: "注意 - 单独下载",
individualDownloadMsg: "禁用批量ZIP下载后,浏览器可能会询问每个文件单独保存的位置。要避免这种情况,请配置浏览器:\\n\\n前往\"设置 > 下载\"并禁用\"下载前询问每个文件的保存位置\"。\\n\\n否则,浏览器会单独询问每张图片的保存位置。",
understood: "明白了",
selectOneImage: "请至少选择一张图片下载。",
noImageConverterMsg: "请先选择一张图片再转换。",
ok: "确定",
settingsSaved: "设置已保存!正在重新加载页面...",
preparingDownload: "正在准备单独下载...",
processingImage: "正在处理图片 {}/{}...",
errorProcessingImage: "错误:无法处理图片。正在尝试替代方法...",
generatingZip: "正在生成包含 {} 张图片的ZIP文件...",
pressKeys: "请按组合键...",
clickToSetHotkey: "点击设置快捷键",
clickAndPress: "(点击并按下按键)",
switchToEnglish: "切换到英文",
invalidUrl: "无效网址",
noImage: "无图片",
menuOpenPanel: "📷 图片面板",
menuLanguages: "🌐 语言",
menuSupportMe: "🙌 支持开发者",
quality_alta: "高",
quality_média: "中",
quality_baixa: "低",
position_topo: "顶部",
position_meio: "中部",
position_baixo: "底部",
otherFormats: "其他",
pixelPriority: "优先处理",
pixelPriorityNormal: "正常",
pixelPriorityHigher: "更高像素",
pixelPriorityLower: "更低像素",
refreshingImages: "正在刷新图像..."
},
"ar": {
title:"برو الصورة",
found:"تم العثور على {} صور",
foundSingular:"تم العثور على {} صورة",
noImages:"لم يتم العثور على أي صور مع الفلاتر الحالية.",
loading:"جاري تحميل الصور...",
searchingNew:"البحث عن صور جديدة...",
selectAll:"تحديد الكل",
selected:"{} من {} محددة",
refresh:"تحديث",
downloadSelected:"تنزيل المحدد",
close:"إغلاق",
openNewTab:"فتح في علامة تبويب جديدة",
searchWith:"البحث باستخدام {}",
downloadImage:"تنزيل الصورة",
allFormats:"جميع التنسيقات",
allQualities:"جميع الجودات",
allPositions:"جميع المواضع",
highQuality:"جودة عالية",
mediumQuality:"جودة متوسطة",
lowQuality:"جودة منخفضة",
topPage:"أعلى الصفحة",
middlePage:"منتصف الصفحة",
bottomPage:"أسفل الصفحة",
format:"التنسيق",
quality:"الجودة",
position:"الموضع",
dimensions:"الأبعاد",
url:"الرابط",
settings:"الإعدادات",
generalTab:"عام",
converterTab:"المحول",
searchTab:"بحث",
zipDownload:"تنزيل كمضغوط ZIP",
convertGif:"تحويل GIF/MP4",
autoConversion:"تحويل تلقائي",
original:"الأصل",
searchEngine:"محرك بحث الصور",
hotkey:"اختصار لوحة المفاتيح",
filterMinSize:"تصفية الحجم الأدنى",
reset:"إعادة تعيين",
save:"حفظ",
supportDev:"ادعم المطور",
importImage:"استيراد صورة",
noImageSelected:"لم يتم تحديد أي صورة",
convert:"تحويل",
converting:"جاري التحويل...",
preparing:"جاري التحضير...",
loadingImage:"جاري تحميل الصورة...",
convertingTo:"جاري التحويل إلى {}...",
finishing:"جاري الانتهاء...",
downloadStarted:"بدأ التنزيل!",
conversionComplete:"اكتمل التحويل",
conversionSuccess:"تم تحويل الصورة بنجاح إلى {}!",
searchPlaceholder:"اكتب ما تريد البحث عنه...",
emptyField:"حقل فارغ",
pleaseEnterSearch:"الرجاء إدخال ما تريد البحث عنه.",
attention:"تنبيه - تنزيل فردي",
individualDownloadMsg: "عند تعطيل التنزيل الجماعي ZIP، قد يطلب المتصفح مكان حفظ كل ملف على حدة. لتجنب ذلك، قم بتعيين إعدادات المتصفح:\n\nاذهب إلى \الإعدادات > التنزيلات\ وعطل \السؤال عن مكان حفظ كل ملف قبل التنزيل\.\n\nوإلا سيطلب المتصفح مكان حفظ كل صورة بشكل منفصل.",
understood:"فهمت",
selectOneImage: "الرجاء تحديد صورة واحدة على الأقل للتنزيل.",
noImageConverterMsg: "الرجاء تحديد صورة قبل التحويل.",
ok: "موافق",
settingsSaved: "تم حفظ الإعدادات! جاري إعادة تحميل الصفحة...",
preparingDownload: "جاري تحضير التنزيل الفردي...",
processingImage: "جاري معالجة الصورة {} من {}...",
errorProcessingImage: "خطأ: تعذر معالجة أي صور. جاري تجربة طريقة بديلة...",
generatingZip: "جاري إنشاء ملف ZIP يحتوي على {} صور...",
pressKeys: "اضغط على مجموعة المفاتيح...",
clickToSetHotkey: "انقر لتعيين الاختصار",
clickAndPress: "(انقر واضغط المفاتيح)",
switchToEnglish: "التبديل إلى الإنجليزية",
invalidUrl: "رابط غير صالح",
noImage: "لا توجد صورة",
menuOpenPanel: "📷 لوحة الصور",
menuLanguages: "🌐 اللغات",
menuSupportMe: "🙌 دعم المطور",
quality_alta: "عالي",
quality_média: "متوسط",
quality_baixa: "منخفض",
position_topo: "أعلى",
position_meio: "وسط",
position_baixo: "أسفل",
otherFormats: "أخرى",
pixelPriority: "الأولوية",
pixelPriorityNormal: "عادي",
pixelPriorityHigher: "بكسل أعلى",
pixelPriorityLower: "بكسل أقل",
refreshingImages: "جاري تحديث الصور..."
},
"hi": {
title: "इमेज प्रो",
found: "{} छवियां मिलीं",
foundSingular: "{} छवि मिली",
noImages: "वर्तमान फ़िल्टर के साथ कोई छवि नहीं मिली।",
loading: "छवियां लोड हो रही हैं...",
searchingNew: "नई छवियां खोज रहा हूँ...",
selectAll: "सभी चुनें",
selected: "{} में से {} चयनित",
refresh: "ताज़ा करें",
downloadSelected: "चयनित डाउनलोड करें",
close: "बंद करें",
openNewTab: "नए टैब में खोलें",
searchWith: "{} के साथ खोजें",
downloadImage: "छवि डाउनलोड करें",
allFormats: "सभी प्रारूप",
allQualities: "सभी गुणवत्ता",
allPositions: "सभी स्थान",
highQuality: "उच्च गुणवत्ता",
mediumQuality: "मध्यम गुणवत्ता",
lowQuality: "निम्न गुणवत्ता",
topPage: "पृष्ठ का शीर्ष",
middlePage: "पृष्ठ का मध्य",
bottomPage: "पृष्ठ का अंत",
format: "प्रारूप",
quality: "गुणवत्ता",
position: "स्थान",
dimensions: "आयाम",
url: "यूआरएल",
settings: "सेटिंग्स",
generalTab: "सामान्य",
converterTab: "कनवर्टर",
searchTab: "खोज",
zipDownload: "बल्क डाउनलोड .ZIP",
convertGif: "कन्वर्ट GIF/MP4",
autoConversion: "स्वत: रूपांतरण",
original: "मूल",
searchEngine: "छवि खोज",
hotkey: "कीबोर्ड शॉर्टकट",
filterMinSize: "न्यूनतम आकार फ़िल्टर",
reset: "रीसेट",
save: "सहेजें",
supportDev: "डेवलपर को सपोर्ट करें",
importImage: "छवि आयात करें",
noImageSelected: "कोई छवि चयनित नहीं",
convert: "कन्वर्ट",
converting: "कन्वर्ट हो रहा है...",
preparing: "तैयार हो रहा है...",
loadingImage: "छवि लोड हो रही है...",
convertingTo: "{} में कन्वर्ट हो रहा है...",
finishing: "समाप्त हो रहा है...",
downloadStarted: "डाउनलोड शुरू!",
conversionComplete: "रूपांतरण पूर्ण",
conversionSuccess: "छवि {} में सफलतापूर्वक कन्वर्ट!",
searchPlaceholder: "खोजने के लिए टाइप करें...",
emptyField: "खाली फ़ील्ड",
pleaseEnterSearch: "कृपया खोजने के लिए कुछ टाइप करें।",
attention: "ध्यान - व्यक्तिगत डाउनलोड",
individualDownloadMsg: "ZIP बल्क डाउनलोड अक्षम करने पर, ब्राउज़र प्रत्येक फ़ाइल को अलग से सेव करने का स्थान पूछ सकता है। इसे रोकने के लिए अपने ब्राउज़र सेट करें:\n\n\सेटिंग्स > डाउनलोड\ पर जाएं और \प्रत्येक डाउनलोड से पहले स्थान पूछें\ अक्षम करें।\n\nअन्यथा, ब्राउज़र प्रत्येक छवि के लिए अलग से पूछेगा।",
understood: "समझ गया",
selectOneImage: "डाउनलोड के लिए कम से कम एक छवि चुनें।",
noImageConverterMsg: "कन्वर्ट करने से पहले कृपया एक छवि चुनें।",
ok: "ठीक",
settingsSaved: "सेटिंग्स सेव! पेज रीलोड हो रहा है...",
preparingDownload: "व्यक्तिगत डाउनलोड तैयार हो रहा है...",
processingImage: "{} में से {} छवि प्रोसेस हो रही है...",
errorProcessingImage: "त्रुटि: कोई छवि प्रोसेस नहीं हो सकी। वैकल्पिक विधि आजमा रहा हूँ...",
generatingZip: "{} छवियों के साथ ZIP फ़ाइल जेनरेट हो रही है...",
pressKeys: "कुंजी संयोजन दबाएँ...",
clickToSetHotkey: "शॉर्टकट सेट करने के लिए क्लिक करें",
clickAndPress: "(क्लिक करें और कुंजियाँ दबाएँ)",
switchToEnglish: "अंग्रेजी में स्विच करें",
invalidUrl: "अमान्य यूआरएल",
noImage: "कोई छवि नहीं",
menuOpenPanel: "📷 छवि पैनल",
menuLanguages: "🌐 भाषाएँ",
menuSupportMe: "🙌 डेवलपर को सपोर्ट करें",
quality_alta: "उच्च",
quality_média: "मध्यम",
quality_baixa: "निम्न",
position_topo: "शीर्ष",
position_meio: "मध्य",
position_baixo: "तल",
otherFormats: "अन्य",
pixelPriority: "प्राथमिकता",
pixelPriorityNormal: "सामान्य",
pixelPriorityHigher: "उच्च पिक्सेल",
pixelPriorityLower: "निम्न पिक्सेल",
refreshingImages: "छवियां ताज़ा हो रही हैं..."
},
"ja": {
title: "イメージプロ",
found: "{} 枚の画像が見つかりました",
foundSingular: "{} 枚の画像が見つかりました",
noImages: "現在のフィルタに一致する画像はありません。",
loading: "画像を読み込んでいます...",
searchingNew: "新しい画像を検索中...",
selectAll: "すべて選択",
selected: "{} / {} 選択済み",
refresh: "更新",
downloadSelected: "選択したものをダウンロード",
close: "閉じる",
openNewTab: "新しいタブで開く",
searchWith: "{} で検索",
downloadImage: "画像をダウンロード",
allFormats: "すべての形式",
allQualities: "すべての品質",
allPositions: "すべての位置",
highQuality: "高品質",
mediumQuality: "中品質",
lowQuality: "低品質",
topPage: "ページ上部",
middlePage: "ページ中央",
bottomPage: "ページ下部",
format: "形式",
quality: "品質",
position: "位置",
dimensions: "サイズ",
url: "URL",
settings: "設定",
generalTab: "一般",
converterTab: "変換",
searchTab: "検索",
zipDownload: "一括ZIPダウンロード",
convertGif: "GIF/MP4変換",
autoConversion: "自動変換",
original: "オリジナル",
searchEngine: "画像検索",
hotkey: "キーボードショートカット",
filterMinSize: "最小サイズフィルター",
reset: "リセット",
save: "保存",
supportDev: "開発者を支援",
importImage: "画像をインポート",
noImageSelected: "画像が選択されていません",
convert: "変換",
converting: "変換中...",
preparing: "準備中...",
loadingImage: "画像を読み込み中...",
convertingTo: "{} に変換中...",
finishing: "終了処理中...",
downloadStarted: "ダウンロードを開始しました!",
conversionComplete: "変換完了",
conversionSuccess: "{} への変換に成功しました!",
searchPlaceholder: "検索キーワードを入力...",
emptyField: "空のフィールド",
pleaseEnterSearch: "検索キーワードを入力してください。",
attention: "注意 - 個別ダウンロード",
individualDownloadMsg: "ZIP一括ダウンロードを無効にすると、ブラウザが各ファイルの保存場所を個別に質問する場合があります。これを防ぐにはブラウザ設定を変更してください:\n\n\設定 > ダウンロード\ で \ダウンロード前に保存場所を確認する\ を無効にします。\n\nそうしない場合、各画像の保存場所を個別に質問されます。",
understood: "理解しました",
selectOneImage: "ダウンロードする画像を1枚以上選択してください。",
noImageConverterMsg: "変換前に画像を選択してください。",
ok: "OK",
settingsSaved: "設定を保存しました! ページを再読み込み中...",
preparingDownload: "個別ダウンロード準備中...",
processingImage: "{} / {} の画像を処理中...",
errorProcessingImage: "エラー:画像を処理できませんでした。代替方法を試行中...",
generatingZip: "{} 枚のZIPファイルを生成中...",
pressKeys: "キーの組み合わせを入力...",
clickToSetHotkey: "ショートカットを設定",
clickAndPress: "(クリックしてキーを押す)",
switchToEnglish: "英語に切り替え",
invalidUrl: "無効なURL",
noImage: "画像なし",
menuOpenPanel: "📷 画像パネル",
menuLanguages: "🌐 言語",
menuSupportMe: "🙌 開発者を支援",
quality_alta: "高",
quality_média: "中",
quality_baixa: "低",
position_topo: "上部",
position_meio: "中央",
position_baixo: "下部",
otherFormats: "その他",
pixelPriority: "優先順位",
pixelPriorityNormal: "標準",
pixelPriorityHigher: "高画素優先",
pixelPriorityLower: "低画素優先",
refreshingImages: "画像を更新中..."
},
"ru": {
title: "Imagem Pro",
found: "Найдено {} изображений",
foundSingular: "Найдено {} изображение",
noImages: "Изображения с текущими фильтрами не найдены.",
loading: "Загрузка изображений...",
searchingNew: "Поиск новых изображений...",
selectAll: "Выбрать все",
selected: "{} из {} выбрано",
refresh: "Обновить",
downloadSelected: "Скачать выбранное",
close: "Закрыть",
openNewTab: "Открыть в новой вкладке",
searchWith: "Искать с {}",
downloadImage: "Скачать изображение",
allFormats: "Все форматы",
allQualities: "Все качества",
allPositions: "Все позиции",
highQuality: "Высокое качество",
mediumQuality: "Среднее качество",
lowQuality: "Низкое качество",
topPage: "Верх страницы",
middlePage: "Середина страницы",
bottomPage: "Низ страницы",
format: "Формат",
quality: "Качество",
position: "Позиция",
dimensions: "Размеры",
url: "URL",
settings: "Настройки",
generalTab: "Общие",
converterTab: "Конвертер",
searchTab: "Поиск",
zipDownload: "Скачать ZIP-архивом",
convertGif: "Конвертировать GIF/MP4",
autoConversion: "Автоконвертация",
original: "Оригинал",
searchEngine: "Поиск изображений",
hotkey: "Горячие клавиши",
filterMinSize: "Фильтр минимального размера",
reset: "Сброс",
save: "Сохранить",
supportDev: "Поддержать разработчика",
importImage: "Импорт изображения",
noImageSelected: "Изображения не выбраны",
convert: "Конвертировать",
converting: "Конвертация...",
preparing: "Подготовка...",
loadingImage: "Загрузка изображения...",
convertingTo: "Конвертация в {}...",
finishing: "Завершение...",
downloadStarted: "Скачивание начато!",
conversionComplete: "Конвертация завершена",
conversionSuccess: "Изображение успешно конвертировано в {}!",
searchPlaceholder: "Введите запрос...",
emptyField: "Пустое поле",
pleaseEnterSearch: "Пожалуйста, введите поисковый запрос.",
attention: "Внимание - Индивидуальная загрузка",
individualDownloadMsg: "При отключении массовой ZIP-загрузки браузер может запрашивать место сохранения для КАЖДОГО файла отдельно. Чтобы избежать этого, настройте браузер:\n\nПерейдите в \Настройки > Загрузки\ и отключите \Спрашивать место сохранения перед загрузкой\.\n\nВ противном случае браузер будет запрашивать место для каждого изображения отдельно.",
understood: "Понятно",
selectOneImage: "Выберите хотя бы одно изображение для скачивания.",
noImageConverterMsg: "Пожалуйста, выберите изображение перед конвертацией.",
ok: "OK",
settingsSaved: "Настройки сохранены! Перезагрузка страницы...",
preparingDownload: "Подготовка индивидуальной загрузки...",
processingImage: "Обработка изображения {} из {}...",
errorProcessingImage: "Ошибка: Не удалось обработать изображения. Пробую альтернативный метод...",
generatingZip: "Создание ZIP-архива с {} изображениями...",
pressKeys: "Нажмите комбинацию клавиш...",
clickToSetHotkey: "Нажмите для установки горячей клавиши",
clickAndPress: "(нажмите и введите клавиши)",
switchToEnglish: "Переключить на английский",
invalidUrl: "Неверный URL",
noImage: "Нет изображения",
menuOpenPanel: "📷 Панель изображений",
menuLanguages: "🌐 Языки",
menuSupportMe: "🙌 Поддержать разработчика",
quality_alta: "Высокая",
quality_média: "Средняя",
quality_baixa: "Низкая",
position_topo: "Верх",
position_meio: "Центр",
position_baixo: "Низ",
otherFormats: "Другие",
pixelPriority: "Приоритет",
pixelPriorityNormal: "Обычный",
pixelPriorityHigher: "Высокий пиксель",
pixelPriorityLower: "Низкий пиксель",
refreshingImages: "Обновление изображений..."
},
"bn": {
title: "ইমেজ প্রো",
found: "{}টি ছবি পাওয়া গেছে",
foundSingular: "{}টি ছবি পাওয়া গেছে",
noImages: "বর্তমান ফিল্টারে কোন ছবি পাওয়া যায়নি।",
loading: "ছবি লোড হচ্ছে...",
searchingNew: "নতুন ছবি খুঁজছি...",
selectAll: "সব নির্বাচন করুন",
selected: "{} এর মধ্যে {} নির্বাচিত",
refresh: "রিফ্রেশ",
downloadSelected: "নির্বাচিত ডাউনলোড",
close: "বন্ধ করুন",
openNewTab: "নতুন ট্যাবে খুলুন",
searchWith: "{} দিয়ে অনুসন্ধান",
downloadImage: "ছবি ডাউনলোড",
allFormats: "সব ফরম্যাট",
allQualities: "সব গুণমান",
allPositions: "সব অবস্থান",
highQuality: "উচ্চ গুণমান",
mediumQuality: "মাঝারি গুণমান",
lowQuality: "নিম্ন গুণমান",
topPage: "পৃষ্ঠার শীর্ষ",
middlePage: "পৃষ্ঠার মাঝামাঝি",
bottomPage: "পৃষ্ঠার নিচ",
format: "ফরম্যাট",
quality: "গুণমান",
position: "অবস্থান",
dimensions: "মাত্রা",
url: "ইউআরএল",
settings: "সেটিংস",
generalTab: "সাধারণ",
converterTab: "কনভার্টার",
searchTab: "অনুসন্ধান",
zipDownload: "জিপ হিসাবে ডাউনলোড",
convertGif: "GIF/MP4 কনভার্ট করুন",
autoConversion: "স্বয়ংক্রিয় রূপান্তর",
original: "আসল",
searchEngine: "ছবি অনুসন্ধান",
hotkey: "কীবোর্ড শর্টকাট",
filterMinSize: "ন্যূনতম আকার ফিল্টার",
reset: "রিসেট",
save: "সংরক্ষণ",
supportDev: "ডেভেলপারকে সহায়তা করুন",
importImage: "ছবি আমদানি করুন",
noImageSelected: "কোন ছবি নির্বাচন করা হয়নি",
convert: "কনভার্ট",
converting: "কনভার্ট হচ্ছে...",
preparing: "প্রস্তুত করা হচ্ছে...",
loadingImage: "ছবি লোড হচ্ছে...",
convertingTo: "{} তে কনভার্ট হচ্ছে...",
finishing: "শেষ হচ্ছে...",
downloadStarted: "ডাউনলোড শুরু হয়েছে!",
conversionComplete: "রূপান্তর সম্পূর্ণ",
conversionSuccess: "ছবি {} এ সফলভাবে কনভার্ট হয়েছে!",
searchPlaceholder: "অনুসন্ধান করতে টাইপ করুন...",
emptyField: "ফাঁকা ক্ষেত্র",
pleaseEnterSearch: "অনুসন্ধান করতে কিছু টাইপ করুন।",
attention: "মনোযোগ - একক ডাউনলোড",
individualDownloadMsg: "জিপ ডাউনলোড বন্ধ করলে ব্রাউজার প্রতিটি ফাইল আলাদাভাবে সেভ করার স্থান জিজ্ঞাসা করতে পারে। এড়াতে ব্রাউজার সেটিংস পরিবর্তন করুন:\n\n\সেটিংস > ডাউনলোড\ এ গিয়ে \প্রতিটি ডাউনলোডের আগে জিজ্ঞাসা করুন\ বন্ধ করুন।\n\nনাহলে ব্রাউজার প্রতিটি ছবির জন্য আলাদা করে জিজ্ঞাসা করবে।",
understood: "বুঝেছি",
selectOneImage: "ডাউনলোডের জন্য অন্তত একটি ছবি নির্বাচন করুন।",
noImageConverterMsg: "কনভার্ট করার আগে একটি ছবি নির্বাচন করুন।",
ok: "ঠিক আছে",
settingsSaved: "সেটিংস সংরক্ষিত! পৃষ্ঠা রিলোড হচ্ছে...",
preparingDownload: "একক ডাউনলোড প্রস্তুত হচ্ছে...",
processingImage: "{} এর {} ছবি প্রক্রিয়াকরণ হচ্ছে...",
errorProcessingImage: "ত্রুটি: কোন ছবি প্রক্রিয়া করা যায়নি। বিকল্প পদ্ধতি চেষ্টা করা হচ্ছে...",
generatingZip: "{} ছবি সহ জিপ ফাইল তৈরি হচ্ছে...",
pressKeys: "কী কম্বিনেশন চাপুন...",
clickToSetHotkey: "শর্টকাট সেট করতে ক্লিক করুন",
clickAndPress: "(ক্লিক করুন এবং কী চাপুন)",
switchToEnglish: "ইংরেজিতে স্যুইচ করুন",
invalidUrl: "অবৈধ ইউআরএল",
noImage: "কোন ছবি নেই",
menuOpenPanel: "📷 ছবি প্যানেল",
menuLanguages: "🌐 ভাষা",
menuSupportMe: "🙌 ডেভেলপারকে সহায়তা করুন",
quality_alta: "উচ্চ",
quality_média: "মাঝারি",
quality_baixa: "নিম্ন",
position_topo: "শীর্ষ",
position_meio: "মধ্য",
position_baixo: "নিচ",
otherFormats: "অন্যান্য",
pixelPriority: "অগ্রাধিকার",
pixelPriorityNormal: "সাধারণ",
pixelPriorityHigher: "উচ্চ পিক্সেল",
pixelPriorityLower: "নিম্ন পিক্সেল",
refreshingImages: "ছবি রিফ্রেশ করা হচ্ছে..."
},
"ur": {
title: "تصویر پرو",
found: "{} تصاویر مل گئیں",
foundSingular: "{} تصویر ملی",
noImages: "موجودہ فلٹرز کے ساتھ کوئی تصویر نہیں ملی۔",
loading: "تصاویر لوڈ ہو رہی ہیں...",
searchingNew: "نئی تصاویر تلاش کی جا رہی ہیں...",
selectAll: "سب منتخب کریں",
selected: "{} میں سے {} منتخب",
refresh: "ریفریش",
downloadSelected: "منتخب ڈاؤن لوڈ کریں",
close: "بند کریں",
openNewTab: "نئی ٹیب میں کھولیں",
searchWith: "{} کے ساتھ تلاش کریں",
downloadImage: "تصویر ڈاؤن لوڈ کریں",
allFormats: "تمام فارمیٹس",
allQualities: "تمام معیارات",
allPositions: "تمام پوزیشنیں",
highQuality: "اعلی معیار",
mediumQuality: "درمیانہ معیار",
lowQuality: "کم معیار",
topPage: "صفحہ کا اوپری حصہ",
middlePage: "صفحہ کا درمیان",
bottomPage: "صفحہ کا نیچے",
format: "فارمیٹ",
quality: "معیار",
position: "پوزیشن",
dimensions: "ابعاد",
url: "یوآرایل",
settings: "ترتیبات",
generalTab: "عام",
converterTab: "کنورٹر",
searchTab: "تلاش",
zipDownload: "بطور ZIP ڈاؤن لوڈ کریں",
convertGif: "GIF/MP4 کنورٹ کریں",
autoConversion: "خودکار تبدیلی",
original: "اصل",
searchEngine: "تصویر تلاش کریں",
hotkey: "کی بورڈ شارٹ کٹ",
filterMinSize: "کم سے کم سائز فلٹر",
reset: "ری سیٹ",
save: "محفوظ کریں",
supportDev: "ڈویلپر کی حمایت کریں",
importImage: "تصویر درآمد کریں",
noImageSelected: "کوئی تصویر منتخب نہیں کی گئی",
convert: "تبدیل کریں",
converting: "تبدیل ہو رہا ہے...",
preparing: "تیار ہو رہا ہے...",
loadingImage: "تصویر لوڈ ہو رہی ہے...",
convertingTo: "{} میں تبدیل ہو رہا ہے...",
finishing: "ختم ہو رہا ہے...",
downloadStarted: "ڈاؤن لوڈ شروع ہو گیا!",
conversionComplete: "تبدیلی مکمل",
conversionSuccess: "تصویر {} میں کامیابی سے تبدیل ہو گئی!",
searchPlaceholder: "تلاش کرنے کے لیے ٹائپ کریں...",
emptyField: "خالی فیلڈ",
pleaseEnterSearch: "براہ کرم تلاش کرنے کے لیے کچھ ٹائپ کریں۔",
attention: "توجہ - انفرادی ڈاؤن لوڈ",
individualDownloadMsg: "ZIP بڑے پیمانے پر ڈاؤن لوڈ کو غیر فعال کرنے پر، براؤزر ہر فائل کو الگ سے محفوظ کرنے کی جگہ پوچھ سکتا ہے۔ اس سے بچنے کے لیے اپنے براؤزر کی ترتیبات کریں:\n\n\ترتیبات > ڈاؤن لوڈز\ پر جائیں اور \ہر ڈاؤن لوڈ سے پہلے پوچھیں\ کو غیر فعال کریں۔\n\nورنہ براؤزر ہر تصویر کو الگ سے پوچھے گا۔",
understood: "سمجھ گیا",
selectOneImage: "ڈاؤن لوڈ کرنے کے لیے کم از کم ایک تصویر منتخب کریں۔",
noImageConverterMsg: "تبدیل کرنے سے پہلے براہ کرم ایک تصویر منتخب کریں۔",
ok: "ٹھیک ہے",
settingsSaved: "ترتیبات محفوظ ہو گئیں! صفحہ دوبارہ لوڈ ہو رہا ہے...",
preparingDownload: "انفرادی ڈاؤن لوڈ تیار ہو رہا ہے...",
processingImage: "{} میں سے {} تصویر پراسیس ہو رہی ہے...",
errorProcessingImage: "خرابی: کوئی تصویر پراسیس نہیں ہو سکی۔ متبادل طریقہ آزمایا جا رہا ہے...",
generatingZip: "{} تصاویر کے ساتھ ZIP فائل بن رہی ہے...",
pressKeys: "کی ترکیب دبائیں...",
clickToSetHotkey: "شارٹ کٹ سیٹ کرنے کے لیے کلک کریں",
clickAndPress: "(کلک کریں اور کی دبائیں)",
switchToEnglish: "انگریزی پر سوئچ کریں",
invalidUrl: "غلط یوآرایل",
noImage: "کوئی تصویر نہیں",
menuOpenPanel: "📷 تصویر پینل",
menuLanguages: "🌐 زبانیں",
menuSupportMe: "🙌 ڈویلپر کی حمایت کریں",
quality_alta: "اعلی",
quality_média: "درمیانہ",
quality_baixa: "کم",
position_topo: "اوپری",
position_meio: "درمیان",
position_baixo: "نیچے",
otherFormats: "دیگر",
pixelPriority: "ترجیح",
pixelPriorityNormal: "عام",
pixelPriorityHigher: "زیادہ پکسل",
pixelPriorityLower: "کم پکسل",
refreshingImages: "تصاویر کو تازہ کیا جا رہا ہے..."
}
};
const languageMenuStyles = `
.imagem-pro-language-overlay {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0, 0, 0, 0.7) !important;
backdrop-filter: blur(5px) !important;
-webkit-backdrop-filter: blur(5px) !important;
z-index: 9999999 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
opacity: 0 !important;
transition: opacity 0.3s ease !important;
}
.imagem-pro-language-overlay.visible {
opacity: 1 !important;
}
.imagem-pro-language-menu {
background-color: rgba(28, 28, 32, 0.98) !important;
border-radius: 16px !important;
padding: 15px !important;
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
width: 330px !important;
max-width: 90vw !important;
position: fixed !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) scale(0.9) !important;
transition: transform 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) !important;
font-family: 'Kiwi Maru' !important;
}
.imagem-pro-language-menu.visible {
transform: translate(-50%, -50%) scale(1) !important;
}
.imagem-pro-language-list {
display: flex !important;
flex-direction: column !important;
gap: 10px !important;
}
.imagem-pro-language-button {
background-color: rgba(255, 255, 255, 0.08) !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 10px !important;
padding: 12px 15px !important;
color: white !important;
font-family: 'Kiwi Maru' !important;
font-size: 15px !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
display: flex !important;
align-items: center !important;
text-align: center !important;
justify-content: center !important;
}
.imagem-pro-language-button:hover {
background-color: rgba(255, 255, 255, 0.15) !important;
transform: translateY(-2px) !important;
}
.imagem-pro-language-button.active {
background-color: rgba(67, 97, 238, 0.3) !important;
border-color: #4361ee !important;
}
.imagem-pro-language-button .language-name {
font-weight: 500 !important;
}
`;
function __(key, ...args) {
const lang = ImagemPro.currentLang;
let text = translations[lang][key] || key;
if (args.length > 0) {
args.forEach((arg, i) => {
text = text.replace(new RegExp('\\{\\}', 'g'), function(match, offset, string) {
return typeof args[i] !== 'undefined' ? args[i] : match;
});
});
}
return text;
}
const SVG_ICONS = {
close: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6L6 18M6 6l12 12"/></svg>',
refresh: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 10C21 10 18.995 7.26822 17.3662 5.63824C15.7373 4.00827 13.4864 3 11 3C6.02944 3 2 7.02944 2 12C2 16.9706 6.02944 21 11 21C15.1031 21 18.5649 18.2543 19.6482 14.5M21 10V4M21 10H15"/></svg>',
search: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>',
externalLink: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M7 17L17 7M17 7H8M17 7V16"/></svg>',
download: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" 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-4M7 10l5 5 5-5M12 15V3"/></svg>',
settings: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-2 2 2 2 0 0 1-2-2v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1-2-2 2 2 0 0 1 2-2h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 2-2 2 2 0 0 1 2 2v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 2 2 2 2 0 0 1-2 2h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>'
};
const styles = `
#imagem-pro-container {
box-sizing: border-box !important;
font-family: 'Kiwi Maru' !important;
line-height: 1.4 !important;
}
#imagem-pro-container * {
box-sizing: border-box !important;
font-family: 'Kiwi Maru' !important;
line-height: 1.4 !important;
}
#imagem-pro-container svg,
#imagem-pro-container button svg,
#imagem-pro-container .imagem-pro-btn svg,
.imagem-pro-btn svg,
#imagem-pro-close-btn svg,
#imagem-pro-settings-btn svg {
all: unset !important;
width: 18px !important;
height: 18px !important;
min-width: 18px !important;
min-height: 18px !important;
display: inline-block !important;
vertical-align: middle !important;
margin-right: 5px !important;
visibility: visible !important;
opacity: 1 !important;
pointer-events: none !important;
}
#imagem-pro-container svg *,
#imagem-pro-container button svg *,
#imagem-pro-container .imagem-pro-btn svg *,
.imagem-pro-btn svg *,
#imagem-pro-close-btn svg *,
#imagem-pro-settings-btn svg * {
fill: none !important;
stroke: currentColor !important;
stroke-width: 2 !important;
stroke-linecap: round !important;
stroke-linejoin: round !important;
visibility: visible !important;
opacity: 1 !important;
vector-effect: non-scaling-stroke !important;
}
#imagem-pro-container {
position: fixed !important;
top: 0 !important;
right: 0 !important;
width: 350px !important;
height: 100vh !important;
background-color: rgba(25, 25, 25, 0.96) !important;
color: #fff !important;
z-index: 999999 !important;
overflow-y: auto !important;
padding: 10px !important;
box-shadow: -5px 0 15px rgba(0, 0, 0, 0.5) !important;
font-family: 'Kiwi Maru'!important;
transform: translateX(100%) !important;
transition: transform 0.3s ease !important;
display: flex !important;
flex-direction: column !important;
font-size: 14px !important;
}
#imagem-pro-container.show {
transform: translateX(0) !important;
}
#imagem-pro-container .imagem-pro-header {
position: sticky !important;
top: 0 !important;
background-color: rgba(25, 25, 25, 0.95) !important;
z-index: 2 !important;
padding-bottom: 10px !important;
}
#imagem-pro-container h2 {
color: #fff !important;
font-family: 'Kiwi Maru' !important;
font-size: 18px !important;
font-weight: bold !important;
margin-top: 0 !important;
padding: 10px 0 !important;
padding-left: 5px !important;
text-align: left !important;
}
#imagem-pro-container .imagem-pro-filters {
margin: 10px 0 !important;
display: flex !important;
flex-direction: column !important;
gap: 10px !important;
padding-bottom: 10px !important;
}
#imagem-pro-container .imagem-pro-filter-row {
display: flex !important;
gap: 10px !important;
flex-direction: row !important;
align-items: center !important;
}
#imagem-pro-container .imagem-pro-filter-row select,
#imagem-pro-container .imagem-pro-filter-row input {
flex-grow: 1 !important;
padding: 5px !important;
background-color: #333 !important;
color: white !important;
border: 1px solid #555 !important;
border-radius: 3px !important;
width: 100% !important;
font-family: 'Kiwi Maru' !important;
font-size: 14px !important;
}
#imagem-pro-container .imagem-pro-filter-row select option {
background-color: #333 !important;
color: white !important;
font-family: 'Kiwi Maru' !important;
font-size: 14px !important;
}
#imagem-pro-container #imagem-pro-count {
padding: 5px 0 !important;
font-weight: bold !important;
margin: 10px 0 !important;
font-size: 14px !important;
color: #ffeb3b !important;
text-align: left !important;
font-family: 'Kiwi Maru' !important;
}
#imagem-pro-container #imagem-pro-images {
overflow-y: auto !important;
flex-grow: 1 !important;
}
#imagem-pro-container .imagem-pro-item {
margin: 15px 0 !important;
padding: 15px !important;
border-radius: 8px !important;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3) !important;
transition: transform 0.2s !important;
position: relative !important;
overflow: visible !important;
isolation: isolate !important;
}
#imagem-pro-container .imagem-pro-item:hover {
transform: translateY(-2px) !important;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.4) !important;
}
#imagem-pro-container .imagem-pro-preview {
width: 100% !important;
height: 200px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
background-color: rgba(0, 0, 0, 0.2) !important;
border-radius: 5px !important;
overflow: hidden !important;
position: relative !important;
margin-bottom: 10px !important;
}
#imagem-pro-container .imagem-pro-item img {
max-width: 100% !important;
max-height: 200px !important;
object-fit: contain !important;
display: block !important;
margin: 0 auto !important;
cursor: pointer !important;
}
#imagem-pro-container .imagem-pro-item-info {
font-size: 12px !important;
color: #ddd !important;
margin: 10px 0 !important;
padding: 5px 0 !important;
border-top: 1px solid rgba(255,255,255,0.1) !important;
border-bottom: 1px solid rgba(255,255,255,0.1) !important;
text-align: left !important;
font-family: 'Kiwi Maru' !important;
background: none !important;
}
#imagem-pro-container .imagem-pro-actions {
display: flex !important;
justify-content: space-between !important;
margin-top: 10px !important;
gap: 5px !important;
}
#imagem-pro-container .imagem-pro-btn {
background-color:rgb(64, 130, 253) !important;
border: none !important;
color: white !important;
padding: 5px 10px !important;
border-radius: 3px !important;
cursor: pointer !important;
flex-grow: 1 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
font-size: 18px !important;
position: relative !important;
}
.imagem-pro-btn svg {
width: 18px !important;
height: 18px !important;
display: inline-block !important;
vertical-align: middle !important;
}
#imagem-pro-container .imagem-pro-btn:hover {
background-color: rgb(64, 130, 253) !important;
box-shadow: 0 2px 4px rgba(0,0,0,0.2) !important;
}
#imagem-pro-container .imagem-pro-btn.lens {
background-color: #9c27b0 !important;
}
#imagem-pro-container .imagem-pro-btn.open {
background-color:rgb(243, 187, 33) !important;
}
#imagem-pro-container .imagem-pro-btn.download {
background-color: rgb(55, 190, 67) !important;
}
#imagem-pro-container .imagem-pro-btn.download-all {
background-color:rgb(55, 190, 67) !important;
}
#imagem-pro-container .imagem-pro-btn.close {
background-color: #f44336 !important;
}
#imagem-pro-container .imagem-pro-btn-tooltip {
position: absolute !important;
background-color: #333 !important;
color: white !important;
padding: 5px 10px !important;
border-radius: 3px !important;
font-size: 12px !important;
bottom: 125% !important;
left: 50% !important;
transform: translateX(-50%) !important;
white-space: nowrap !important;
visibility: hidden !important;
opacity: 0 !important;
transition: opacity 0.2s, visibility 0.2s !important;
pointer-events: none !important;
z-index: 10 !important;
box-shadow: 0 2px 5px rgba(0,0,0,0.3) !important;
}
#imagem-pro-container .imagem-pro-btn:hover .imagem-pro-btn-tooltip {
visibility: visible !important;
opacity: 1 !important;
}
#imagem-pro-container .imagem-pro-no-images {
padding: 20px !important;
text-align: center !important;
color: #bbb !important;
font-family: 'Kiwi Maru' !important;
}
#imagem-pro-container .imagem-pro-loading {
text-align: center !important;
padding: 20px !important;
color: #fff !important;
font-family: 'Kiwi Maru' !important;
}
#imagem-pro-container .imagem-pro-checkbox-container {
position: absolute !important;
top: 5px !important;
left: 5px !important;
z-index: 5 !important;
background-color: rgba(0,0,0,0.7) !important;
border-radius: 4px !important;
padding: 3px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
width: 24px !important;
height: 24px !important;
border: 1px solid rgba(255,255,255,0.2) !important;
overflow: hidden !important;
}
#imagem-pro-container .imagem-pro-checkbox {
width: 18px !important;
height: 18px !important;
margin: 0 !important;
padding: 0 !important;
appearance: auto !important;
-webkit-appearance: checkbox !important;
-moz-appearance: checkbox !important;
accent-color: #2196F3 !important;
cursor: pointer !important;
opacity: 1 !important;
position: static !important;
border: 2px solid white !important;
outline: none !important;
display: block !important;
}
#imagem-pro-container .imagem-pro-select-all {
display: flex !important;
align-items: center !important;
margin-bottom: 10px !important;
background-color: rgba(33, 33, 33, 0.8) !important;
padding: 6px 10px !important;
border-radius: 4px !important;
border: 1px solid rgba(255, 255, 255, 0.15) !important;
}
#imagem-pro-container .imagem-pro-select-all label {
color: white !important;
margin-left: 10px !important;
font-size: 13px !important;
font-family: 'Kiwi Maru' !important;
user-select: none !important;
}
#imagem-pro-container .imagem-pro-selected-count {
margin-left: auto !important;
font-size: 12px !important;
color: #ffeb3b !important;
font-family: 'Kiwi Maru' !important;
}
#imagem-pro-container .imagem-pro-settings-btn {
position: absolute !important;
top: 0 !important;
right: 10px !important;
background: none !important;
border: none !important;
color: #ccc !important;
font-size: 20px !important;
cursor: pointer !important;
z-index: 10 !important;
}
#imagem-pro-container .imagem-pro-settings-btn:hover {
color: white !important;
}
.imagem-pro-converter-container {
display: flex !important;
flex-direction: column !important;
gap: 20px !important;
align-items: center !important;
}
.imagem-pro-file-upload {
width: 100% !important;
text-align: center !important;
}
.imagem-pro-preview-container {
width: 100% !important;
height: 150px !important;
background: rgba(0, 0, 0, 0.2) !important;
border-radius: 8px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
overflow: hidden !important;
border: 1px dashed rgba(255, 255, 255, 0.2) !important;
margin: 10px 0 !important;
}
.imagem-pro-search-options {
display: flex !important;
justify-content: center !important;
gap: 15px !important;
margin-top: 20px !important;
width: 100% !important;
}
.imagem-pro-search-option {
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 5px !important;
padding: 10px !important;
background: rgba(255, 255, 255, 0.05) !important;
border-radius: 8px !important;
cursor: pointer !important;
flex: 1 !important;
max-width: 80px !important;
transition: all 0.3s ease !important;
}
.imagem-pro-search-option:hover {
background: rgba(255, 255, 255, 0.1) !important;
}
.imagem-pro-search-option input {
margin: 0 !important;
}
.imagem-pro-search-option label {
font-size: 12px !important;
color: white !important;
text-align: center !important;
cursor: pointer !important;
}
.imagem-pro-search-option input:checked + label {
color: #4361ee !important;
font-weight: bold !important;
}
.imagem-pro-search-option input:checked ~ .imagem-pro-search-option {
background: rgba(67, 97, 238, 0.1) !important;
}
.imagem-pro-select-wrapper select,
#imagem-pro-format-filter,
#imagem-pro-quality-filter,
#imagem-pro-position-filter,
#converter-format-select,
#settings-auto-convert,
#settings-search-engine,
.imagem-pro-input,
.imagem-pro-input option {
color: white !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
-webkit-appearance: none !important;
-moz-appearance: none !important;
appearance: none !important;
}
select::-ms-expand {
display: none !important;
}
@media screen and (-webkit-min-device-pixel-ratio:0) {
select {
background-color: rgba(28, 28, 32, 0.98) !important;
}
select option {
background-color: rgba(28, 28, 32, 0.98) !important;
color: white !important;
}
}
@-moz-document url-prefix() {
select,
select option {
background-color: rgba(28, 28, 32, 0.98) !important;
color: white !important;
text-align: center !important;
}
}
body select option,
body .imagem-pro-select-wrapper select option {
background-color: rgba(28, 28, 32, 0.98) !important;
color: white !important;
}
.imagem-pro-select-wrapper select option:hover,
#imagem-pro-format-filter option:hover,
#imagem-pro-quality-filter option:hover,
#imagem-pro-position-filter option:hover,
#converter-format-select option:hover,
#settings-auto-convert option:hover,
#settings-search-engine option:hover {
background-color: rgba(67, 97, 238, 0.5) !important;
}
.imagem-pro-alert-title.warning {
color: #FFA500 !important;
}
.imagem-pro-alert-box.warning {
border-left: 4px solid #FFA500 !important;
}
.imagem-pro-alert-content p {
margin: 0 0 10px 0 !important;
}
.imagem-pro-alert-content p:last-child {
margin-bottom: 0 !important;
}
`;
const styleEl = document.createElement('style');
styleEl.textContent = styles;
document.head.appendChild(styleEl);
function detectImageFormat(url) {
if (!url) return 'Desconhecido';
const lowerUrl = url.toLowerCase();
if (lowerUrl.includes('data:image/svg')) return 'SVG';
if (lowerUrl.match(/\.(jpg|jpeg|jfif|pjpeg|pjp)($|\?)/)) return 'JPG';
if (lowerUrl.match(/\.png($|\?)/)) return 'PNG';
if (lowerUrl.match(/\.gif($|\?)/)) return 'GIF';
if (lowerUrl.match(/\.svg($|\?)/)) return 'SVG';
if (lowerUrl.match(/\.webp($|\?)/)) return 'WEBP';
if (lowerUrl.match(/\.bmp($|\?)/)) return 'BMP';
if (lowerUrl.match(/\.ico($|\?)/)) return 'ICO';
if (lowerUrl.match(/\.(tif|tiff)($|\?)/)) return 'TIFF';
if (lowerUrl.match(/\.avif($|\?)/)) return 'AVIF';
if (lowerUrl.match(/\.apng($|\?)/)) return 'APNG';
if (lowerUrl.startsWith('data:image/jpeg')) return 'JPG';
if (lowerUrl.startsWith('data:image/png')) return 'PNG';
if (lowerUrl.startsWith('data:image/gif')) return 'GIF';
if (lowerUrl.startsWith('data:image/svg')) return 'SVG';
if (lowerUrl.startsWith('data:image/webp')) return 'WEBP';
if (lowerUrl.startsWith('data:image/bmp')) return 'BMP';
if (lowerUrl.startsWith('data:image/ico')) return 'ICO';
if (lowerUrl.startsWith('data:image/tiff')) return 'TIFF';
return 'Outro';
}
function detectImageQuality(width, height) {
if (!width || !height) return 'Média';
const area = width * height;
if (area < 90000) return 'Baixa'; // Menor que 300x300 pixels
if (area < 360000) return 'Média'; // Entre 300x300 e 600x600 pixels
return 'Alta'; // Maior que 600x600 pixels
}
function detectPosition(element) {
if (!element || !element.getBoundingClientRect) return 'Meio';
try {
const rect = element.getBoundingClientRect();
const windowHeight = window.innerHeight;
if (rect.top < windowHeight / 3) return 'Topo';
if (rect.top < windowHeight * 2/3) return 'Meio';
return 'Baixo';
} catch(e) {
debug('Erro ao detectar posição: ' + e.message, true);
return 'Meio';
}
}
const imageCache = {
images: [],
urlMap: new Map(),
normalizedUrlSet: new Set(),
normalizeUrl: function(url) {
if (!url || typeof url !== 'string') return '';
try {
let normalizedUrl = url.trim();
if (normalizedUrl.includes('/hqdefault.jpg')) {
const baseUrl = normalizedUrl.split('/hqdefault.jpg')[0];
return baseUrl + '/maxresdefault.jpg';
}
if (normalizedUrl.includes('i.pinimg.com/') && !normalizedUrl.includes('i.pinimg.com/originals/')) {
normalizedUrl = normalizedUrl.replace(/i\.pinimg\.com\/[^\/]+\//, 'i.pinimg.com/originals/');
}
const urlObj = new URL(normalizedUrl);
const paramsToRemove = ['width', 'height', 'w', 'h', 'size', 'quality', 'q',
'resize', 'version', 'v', 'timestamp', 't', 'token',
'sig', 'signature'];
paramsToRemove.forEach(param => {
urlObj.searchParams.delete(param);
});
const path = urlObj.pathname.toLowerCase();
const fileExtMatch = path.match(/\.(jpe?g|png|jpeg|gif|webp)/i);
if (fileExtMatch) {
const fileExt = fileExtMatch[1].replace('jpeg', 'jpg');
normalizedUrl = urlObj.origin + urlObj.pathname + urlObj.search;
}
else {
normalizedUrl = urlObj.toString();
}
normalizedUrl = normalizedUrl
.replace(/\/\d+x\/|\/236x\/|\/474x\/|\/736x\//, '/')
.replace(/\?name=\w+/, '')
.replace(/(i\.ytimg\.com\/vi\/[^\/]+)\/[^\/]+\.jpg/, '$1')
.replace(/(&|\?)w=\d+/, '')
.replace(/(&|\?)h=\d+/, '')
.replace(/\?v=.*$/, '')
.replace(/\.(jpg|jpeg|png)\?.*$/, '.$1');
return normalizedUrl;
} catch(e) {
debug('Erro ao normalizar URL: ' + e.message, true);
return url;
}
},
isDuplicate: function(img) {
if (!img || !img.src) return true;
if (this.urlMap.has(img.src)) {
debug(`URL duplicada encontrada: ${img.src}`);
return true;
}
const normalizedUrl = this.normalizeUrl(img.src);
if (!normalizedUrl) return true;
if (this.normalizedUrlSet.has(normalizedUrl)) {
debug(`URL normalizada duplicada: ${img.src} → ${normalizedUrl}`);
return true;
}
return false;
},
addImages: function(newImages) {
if (!newImages || !newImages.length) return;
let addedCount = 0;
let skippedCount = 0;
newImages.forEach(img => {
if (this.isDuplicate(img)) {
skippedCount++;
return;
}
this.urlMap.set(img.src, true);
const normalizedUrl = this.normalizeUrl(img.src);
if (normalizedUrl) {
this.normalizedUrlSet.add(normalizedUrl);
}
this.images.push(img);
addedCount++;
});
if (addedCount > 0 || skippedCount > 0) {
debug(`Cache de imagens: ${addedCount} adicionadas, ${skippedCount} duplicatas ignoradas`);
}
},
clear: function() {
this.images = [];
this.urlMap.clear();
this.normalizedUrlSet.clear();
debug('Cache de imagens limpo completamente');
},
getImages: function() {
return this.images;
}
};
let loadingInProgress = false;
function updateImageCount() {
const countElement = document.getElementById('imagem-pro-count');
if (countElement) {
const totalImages = document.querySelectorAll('#imagem-pro-images .imagem-pro-item').length;
countElement.textContent = totalImages === 1 ?
__('foundSingular', totalImages) :
__('found', totalImages);
}
}
function loadImages(append = true) {
if (loadingInProgress) {
debug('Carregamento já em andamento, ignorando nova solicitação');
return;
}
loadingInProgress = true;
debug('Iniciando carregamento de imagens (append: ' + append + ')');
try {
const imagesContainer = document.getElementById('imagem-pro-images');
if (!imagesContainer) {
debug('Container de imagens não encontrado', true);
loadingInProgress = false;
return;
}
const settings = loadSettings();
const minPixelSize = parseInt(settings.limitPx) || 0;
if (!append) {
setInnerHTML(imagesContainer, `<div class="imagem-pro-loading">${__('loading')}</div>`);
imageCache.clear();
} else {
const loadingIndicator = document.createElement('div');
loadingIndicator.className = 'imagem-pro-loading';
loadingIndicator.textContent = __('searchingNew');
loadingIndicator.id = 'imagem-pro-loading-indicator';
imagesContainer.appendChild(loadingIndicator);
}
let newImages = [];
try {
newImages = imageManager.getImages() || [];
debug(`Novas imagens encontradas: ${newImages.length}`);
if (newImages.length > 0) {
const uniqueImages = [];
const tempUrlMap = new Map();
const tempNormalizedSet = new Set();
newImages.forEach(img => {
if (!img || !img.src) return;
if (tempUrlMap.has(img.src)) return;
const normalizedUrl = imageCache.normalizeUrl(img.src);
if (normalizedUrl && tempNormalizedSet.has(normalizedUrl)) return;
if (imageCache.isDuplicate(img)) return;
tempUrlMap.set(img.src, true);
if (normalizedUrl) tempNormalizedSet.add(normalizedUrl);
uniqueImages.push(img);
});
debug(`Filtro de duplicatas: ${newImages.length} → ${uniqueImages.length} imagens únicas`);
newImages = uniqueImages;
}
imageCache.addImages(newImages);
} catch (e) {
debug('Erro ao obter imagens: ' + e.message, true);
console.error(e);
if (!append) {
setInnerHTML(imagesContainer, '<p>Erro ao obter imagens. Verifique o console.</p>');
} else {
const loadingIndicator = document.getElementById('imagem-pro-loading-indicator');
if (loadingIndicator) loadingIndicator.remove();
}
return;
}
let images = imageCache.getImages();
if (minPixelSize > 0) {
const originalCacheCount = images.length;
images = images.filter(img => {
return (img.width >= minPixelSize || img.height >= minPixelSize);
});
debug(`Filtradas ${originalCacheCount - images.length} imagens em cache menores que ${minPixelSize}px`);
}
const formatFilter = document.getElementById('imagem-pro-format-filter').value;
const qualityFilter = document.getElementById('imagem-pro-quality-filter').value;
const positionFilter = document.getElementById('imagem-pro-position-filter').value;
if (formatFilter !== 'ALL') {
images = images.filter(img => img.format === formatFilter);
}
if (qualityFilter !== 'ALL') {
images = images.filter(img => img.quality === qualityFilter);
}
if (positionFilter !== 'ALL') {
images = images.filter(img => img.position === positionFilter);
}
if (settings.pixelPriority === 'higher') {
images.sort((a, b) => {
const aArea = a.width * a.height;
const bArea = b.width * b.height;
return bArea - aArea;
});
debug('Imagens ordenadas por tamanho de pixel: maior para menor');
} else if (settings.pixelPriority === 'lower') {
images.sort((a, b) => {
const aArea = a.width * a.height;
const bArea = b.width * b.height;
return aArea - bArea;
});
debug('Imagens ordenadas por tamanho de pixel: menor para maior');
} else {
debug('Mantendo a ordem normal das imagens');
}
if (!append) {
setInnerHTML(imagesContainer, '');
} else {
const loadingIndicator = document.getElementById('imagem-pro-loading-indicator');
if (loadingIndicator) loadingIndicator.remove();
}
if (images.length === 0) {
if (!append) {
setInnerHTML(imagesContainer, `<div class="imagem-pro-no-images">${__('noImages')}</div>`);
}
updateImageCount();
return;
}
const BATCH_SIZE = 20; // Número de imagens a processar de cada vez
let currentIndex = 0;
function processBatch() {
const endIndex = Math.min(currentIndex + BATCH_SIZE, images.length);
for (let i = currentIndex; i < endIndex; i++) {
const img = images[i];
if (append && document.querySelector(`.imagem-pro-item[data-src="${img.src}"]`)) {
continue;
}
if (!img.src) continue;
const testImage = new Image();
testImage.onload = function() {
createImageElement(img, i);
};
testImage.onerror = function() {
debug(`Ignorando imagem com erro: ${img.src}`);
};
testImage.src = img.src;
}
currentIndex = endIndex;
if (currentIndex < images.length) {
setTimeout(processBatch, 16);
} else {
updateImageCount();
loadingInProgress = false;
}
}
processBatch();
} catch (e) {
debug('Erro ao carregar imagens: ' + e.message, true);
console.error(e);
if (!append) {
const imagesContainer = document.getElementById('imagem-pro-images');
if (imagesContainer) {
setInnerHTML(imagesContainer, '<p>Ocorreu um erro ao carregar as imagens. Verifique o console para mais detalhes.</p>');
}
} else {
const loadingIndicator = document.getElementById('imagem-pro-loading-indicator');
if (loadingIndicator) loadingIndicator.remove();
}
} finally {
loadingInProgress = false;
}
}
const imageManager = {
imageType: {
IMG: 'IMG'
},
imgList: [],
googleImageCache: {
links: {},
originalSources: {},
timestamp: null,
maxAgeMs: 600000 // 10 minutos
},
yandexImageCache: {
links: {},
originalSources: {},
timestamp: null,
maxAgeMs: 600000 // 10 minutos
},
getImages: function getImages() {
this.imgList = [];
if (this.googleImageCache.timestamp &&
Date.now() - this.googleImageCache.timestamp > this.googleImageCache.maxAgeMs) {
this.googleImageCache.links = {};
this.googleImageCache.originalSources = {};
this.googleImageCache.timestamp = null;
}
if (!this.googleImageCache.timestamp) {
this.googleImageCache.timestamp = Date.now();
}
if (this.yandexImageCache.timestamp &&
Date.now() - this.yandexImageCache.timestamp > this.yandexImageCache.maxAgeMs) {
this.yandexImageCache.links = {};
this.yandexImageCache.originalSources = {};
this.yandexImageCache.timestamp = null;
}
if (!this.yandexImageCache.timestamp) {
this.yandexImageCache.timestamp = Date.now();
}
this.scanForGoogleImageLinks();
this.scanForYandexImageLinks();
const processImageUrls = (url) => {
if (!url || typeof url !== 'string') return url;
if (this.googleImageCache.links[url]) {
debug(`Usando link do Google convertido: ${this.googleImageCache.links[url]}`);
return this.googleImageCache.links[url];
}
if (this.yandexImageCache.links[url]) {
debug(`Usando link do Yandex convertido: ${this.yandexImageCache.links[url]}`);
return this.yandexImageCache.links[url];
}
if (url.includes('yandex.') && url.includes('/images/')) {
try {
if (url.includes('&img_url=')) {
const imgUrlMatch = url.match(/&img_url=([^&]+)/);
if (imgUrlMatch && imgUrlMatch[1]) {
const decodedUrl = decodeURIComponent(imgUrlMatch[1]);
debug(`URL do Yandex melhorada: ${url} → ${decodedUrl}`);
return decodedUrl;
}
}
} catch (e) {
debug(`Erro ao processar URL do Yandex: ${e.message}`, true);
}
}
if (url.includes('m.media-amazon.com/images/') && url.includes('@') && url.includes('.jpg')) {
const cleanedUrl = url.replace(/(@.*?)\.jpg/, '@.jpg');
debug(`URL do IMDb melhorada: ${url} → ${cleanedUrl}`);
return cleanedUrl;
}
if (url.includes('m.media-amazon.com/images/') && url.includes('._') && url.includes('.jpg')) {
const baseUrl = url.substring(0, url.indexOf('._') + 2);
const extension = url.substring(url.lastIndexOf('.jpg'));
return baseUrl + extension;
}
if (url.includes('i.pinimg.com/')) {
const convertedUrl = url.replace(/i\.pinimg\.com\/[^\/]+\//, 'i.pinimg.com/originals/');
debug(`URL do Pinterest convertida: ${url} → ${convertedUrl}`);
return convertedUrl;
}
if (url.includes('imgur.com')) {
if (url.includes('i.imgur.com/') && url.includes('_')) {
const imgurId = url.split('i.imgur.com/')[1].split('_')[0];
if (imgurId) {
const directUrl = `https://i.imgur.com/${imgurId}.jpeg`;
debug(`URL do Imgur com underscore convertida: ${url} → ${directUrl}`);
return directUrl;
}
}
if (/https:\/\/i\.imgur\.com\/([a-zA-Z0-9]+)([bstmlh])(\.[a-zA-Z]+)$/i.test(url)) {
const convertedUrl = url.replace(/([a-zA-Z0-9]+)([bstmlh])(\.[a-zA-Z]+)$/i, '$1$3');
debug(`URL do Imgur convertida: ${url} → ${convertedUrl}`);
return convertedUrl;
}
if (/https:\/\/imgur\.com\/([a-zA-Z0-9]+)$/i.test(url)) {
const imgurId = url.match(/imgur\.com\/([a-zA-Z0-9]+)$/i)[1];
const directUrl = `https://i.imgur.com/${imgurId}.jpg`;
debug(`URL da página do Imgur convertida: ${url} → ${directUrl}`);
return directUrl;
}
}
if (url.includes('/hqdefault.jpg')) {
const baseUrl = url.split('/hqdefault.jpg')[0];
const convertedUrl = baseUrl + '/maxresdefault.jpg';
debug(`Convertido link hqdefault: ${url} → ${convertedUrl}`);
return convertedUrl;
}
if (url.includes('i.ytimg.com/vi/') && url.includes('/hq720.jpg?v=')) {
const basePattern = /^(https:\/\/i\.ytimg\.com\/vi\/[^\/]+\/hq720\.jpg\?v=).+$/;
return url.replace(basePattern, '$1...');
}
if (url.includes('i.ytimg.com/') && url.includes('jpg?')) {
const basePattern = /^(.*jpg\?).+$/;
return url.replace(basePattern, '$1...');
}
if (url.includes('pbs.twimg.com/')) {
if (url.includes('name=')) {
return url.replace(/name=\w+/g, 'name=4096x4096');
} else if (url.includes('?')) {
return url + '&name=4096x4096';
} else {
return url + '?name=4096x4096';
}
}
if (url.includes('comicvine.gamespot.com/a/uploads/')) {
if (url.includes('/square_medium/')) {
const convertedUrl = url.replace('/square_medium/', '/original/');
debug(`URL do ComicVine convertida: ${url} → ${convertedUrl}`);
return convertedUrl;
} else if (url.includes('/scale_small/')) {
const convertedUrl = url.replace('/scale_small/', '/original/');
debug(`URL do ComicVine convertida: ${url} → ${convertedUrl}`);
return convertedUrl;
} else if (url.includes('/screen_kubrick/')) {
const convertedUrl = url.replace('/screen_kubrick/', '/original/');
debug(`URL do ComicVine convertida: ${url} → ${convertedUrl}`);
return convertedUrl;
}
}
if (url.includes('sinaimg.cn/orj360/')) {
const convertedUrl = url.replace('/orj360/', '/mw690/');
debug(`URL do Weibo convertida: ${url} → ${convertedUrl}`);
return convertedUrl;
}
if (url.includes('hdslb.com/')) {
const jpgIndex = url.indexOf('.jpg');
const pngIndex = url.indexOf('.png');
if (jpgIndex !== -1) {
const cleanUrl = url.substring(0, jpgIndex + 4);
debug(`URL do Bilibili convertida: ${url} → ${cleanUrl}`);
return cleanUrl;
}
else if (pngIndex !== -1) {
const cleanUrl = url.substring(0, pngIndex + 4);
debug(`URL do Bilibili convertida: ${url} → ${cleanUrl}`);
return cleanUrl;
}
}
return url;
};
let imgs = document.getElementsByTagName('img');
for (var i = 0; i < imgs.length; i++) {
var img = imgs[i];
var newImg = new Image();
newImg.src = processImageUrls(img.src);
var width = 0;
var height = 0;
width = parseInt(img.naturalWidth) || 0;
height = parseInt(img.naturalHeight) || 0;
var nwidth = parseInt(newImg.width) || 0;
var nheight = parseInt(newImg.height) || 0;
width = nwidth > width ? nwidth : width;
height = nheight > height ? nheight : height;
this.addImg(
imageManager.imageType.IMG,
processImageUrls(img.src),
width,
height,
detectImageFormat(img.src),
detectImageQuality(width, height),
detectPosition(img)
);
}
imgs = document.images;
if (imgs && imgs.length > 0) {
for (var i = 0; i < imgs.length; i++) {
try {
var img = imgs[i];
var newImg = new Image();
const processedUrl = processImageUrls(img.currentSrc || img.src);
newImg.src = processedUrl;
var width = 0;
var height = 0;
width = parseInt(img.naturalWidth) || 0;
height = parseInt(img.naturalHeight) || 0;
var nwidth = parseInt(newImg.width) || 0;
var nheight = parseInt(newImg.height) || 0;
width = nwidth > width ? nwidth : width;
height = nheight > height ? nheight : height;
newImg = null;
this.addImg(
imageManager.imageType.IMG,
processedUrl,
width,
height,
detectImageFormat(processedUrl),
detectImageQuality(width, height),
detectPosition(img)
);
} catch (e) {
debug('Erro ao processar imagem: ' + e.message, true);
}
}
}
return this.imgList;
},
isGoogleImageDuplicate: function(newUrl) {
const isGoogleUrl = newUrl.includes('google') || newUrl.includes('gstatic') || newUrl.includes('googleusercontent');
if (isGoogleUrl) {
const normalizedUrl = newUrl.split('=')[0].split('?')[0];
return this.imgList.some(img => {
const existingUrl = img.src;
if (existingUrl === newUrl) return true;
if (existingUrl.includes('google') || existingUrl.includes('gstatic') || existingUrl.includes('googleusercontent')) {
const existingNormalized = existingUrl.split('=')[0].split('?')[0];
if (existingNormalized === normalizedUrl) return true;
const newIdMatch = newUrl.match(/\/([^\/]+)\.(jpg|png|jpeg|gif|webp)/i);
const existingIdMatch = existingUrl.match(/\/([^\/]+)\.(jpg|png|jpeg|gif|webp)/i);
if (newIdMatch && existingIdMatch && newIdMatch[1] === existingIdMatch[1]) {
return true;
}
}
if (this.googleImageCache && this.googleImageCache.links) {
const newOriginal = this.googleImageCache.links[newUrl];
const existingOriginal = this.googleImageCache.links[existingUrl];
if (newOriginal && existingOriginal && newOriginal === existingOriginal) {
return true;
}
}
return false;
});
} else {
return this.imgList.some(img => img.src === newUrl);
}
},
scanForYandexImageLinks: function() {
try {
const isYandexSite = /yandex\.(com|ru|net|ua|by|kz|uz|fr|com\.tr)/i.test(window.location.href);
if (!isYandexSite) {
return;
}
debug("Detectado site do Yandex. Buscando imagens reais...");
let foundOriginalUrls = new Set();
let thumbnailToOriginalMap = new Map();
document.querySelectorAll('[data-bem]').forEach(elem => {
try {
const bemData = JSON.parse(elem.dataset.bem);
if (bemData && bemData["serp-item__thumb"] && bemData["serp-item__thumb"].url) {
const originalUrl = bemData["serp-item__thumb"].url;
debug(`Encontrada URL original via data-bem: ${originalUrl}`);
foundOriginalUrls.add(originalUrl);
elem.querySelectorAll('img').forEach(img => {
if (img.src) {
this.yandexImageCache.links[img.src] = originalUrl;
debug(`Mapeamento Yandex: ${img.src} → ${originalUrl}`);
thumbnailToOriginalMap.set(img.src, originalUrl);
}
});
}
if (bemData && bemData["image-viewer__image"]) {
const imageData = bemData["image-viewer__image"];
if (imageData && imageData.url) {
const originalUrl = imageData.url;
debug(`Encontrada URL original via image-viewer: ${originalUrl}`);
foundOriginalUrls.add(originalUrl);
}
}
} catch (e) {
}
});
document.querySelectorAll('a[href*="img_url="]').forEach(link => {
try {
const match = link.href.match(/img_url=([^&]+)/);
if (match && match[1]) {
const originalUrl = decodeURIComponent(match[1]);
if (originalUrl.match(/^https?:\/\//)) {
debug(`URL original via img_url: ${originalUrl}`);
foundOriginalUrls.add(originalUrl);
const parent = link.closest('.serp-item, .MMImageContainer');
if (parent) {
parent.querySelectorAll('img').forEach(img => {
if (img.src) {
this.yandexImageCache.links[img.src] = originalUrl;
thumbnailToOriginalMap.set(img.src, originalUrl);
debug(`Mapeamento por proximidade: ${img.src} → ${originalUrl}`);
}
});
}
}
}
} catch (e) {
}
});
document.querySelectorAll('meta[property="og:image"]').forEach(meta => {
if (meta.content && meta.content.startsWith('http')) {
debug(`Encontrada imagem original via meta og:image: ${meta.content}`);
foundOriginalUrls.add(meta.content);
}
});
document.querySelectorAll('.MMImage-Origin, .MMImageWrapper img.MMImage-Preview, .MMImagePreview-Image, .serp-item__thumb img').forEach(img => {
if (img.src) {
debug(`Imagem potencial do Yandex encontrada: ${img.src}`);
const improvedUrl = this.improveYandexImageUrl(img.src);
if (improvedUrl !== img.src) {
debug(`URL melhorada: ${img.src} → ${improvedUrl}`);
this.yandexImageCache.links[img.src] = improvedUrl;
foundOriginalUrls.add(improvedUrl);
thumbnailToOriginalMap.set(img.src, improvedUrl);
} else {
foundOriginalUrls.add(img.src);
}
}
});
document.querySelectorAll('script:not([src])').forEach(script => {
try {
const content = script.textContent;
if (content.includes('"originImage"') || content.includes('"fullImageUrl"')) {
const originUrlMatches = content.match(/"originImage"\s*:\s*"([^"]+)"/g) || [];
const fullUrlMatches = content.match(/"fullImageUrl"\s*:\s*"([^"]+)"/g) || [];
[...originUrlMatches, ...fullUrlMatches].forEach(match => {
const url = match.split(/:\s*"/)[1].replace('"', '');
if (url && url.startsWith('http')) {
debug(`URL de imagem extraída de script: ${url}`);
foundOriginalUrls.add(url);
}
});
}
} catch (e) {
}
});
debug(`Total de URLs originais Yandex encontradas: ${foundOriginalUrls.size}`);
debug(`Mapeamentos thumbnail → original: ${thumbnailToOriginalMap.size}`);
foundOriginalUrls.forEach(url => {
if (!this.imgList.some(img => img.src === url)) {
const img = new Image();
img.src = url;
this.addImg(
this.imageType.IMG,
url,
img.width || 0,
img.height || 0,
detectImageFormat(url),
'Alta',
'Meio'
);
debug(`Adicionada imagem de alta qualidade do Yandex: ${url}`);
}
});
} catch (e) {
debug(`Erro ao processar imagens do Yandex: ${e.message}`, true);
console.error("Erro detalhado:", e);
}
},
improveYandexImageUrl: function(url) {
if (!url || typeof url !== 'string') return url;
try {
if (url.includes('images.yandex') && url.includes('&img_url=')) {
const match = url.match(/&img_url=([^&]+)/);
if (match && match[1]) {
return decodeURIComponent(match[1]);
}
}
if (url.includes('resize.yandex') && url.includes('&url=')) {
const match = url.match(/&url=([^&]+)/);
if (match && match[1]) {
return decodeURIComponent(match[1]);
}
}
if (url.match(/\.(png|jpe?g|gif|webp)/i) && url.includes('?')) {
const sizeParams = ['size', 'width', 'height', 'w', 'h'];
let hasChanged = false;
let modifiedUrl = new URL(url);
sizeParams.forEach(param => {
if (modifiedUrl.searchParams.has(param)) {
modifiedUrl.searchParams.delete(param);
hasChanged = true;
}
});
return hasChanged ? modifiedUrl.toString() : url;
}
} catch (e) {
debug(`Erro ao melhorar URL do Yandex: ${e.message}`, true);
}
return url;
},
clearCache: function() {
this.googleImageCache.links = {};
this.googleImageCache.originalSources = {};
this.googleImageCache.timestamp = null;
this.yandexImageCache.links = {};
this.yandexImageCache.originalSources = {};
this.yandexImageCache.timestamp = null;
debug('Cache de links do Google e Yandex limpo');
},
scanForGoogleImageLinks: function() {
try {
const isGoogleImages = window.location.href.includes('google') &&
(window.location.href.includes('/images') ||
window.location.href.includes('tbm=isch'));
debug("Buscando imagens do Google com método aprimorado...");
const highQualityImages = [];
document.querySelectorAll('a[href*="?tbm=shop"], a[href*="google.com/shopping"]').forEach(link => {
const imageElements = link.querySelectorAll('img[src^="http"]');
imageElements.forEach(img => {
if (img.src && img.src.includes('google') && !img.src.includes('base64')) {
const originalParent = img.closest('[data-ved], [data-item-id]');
if (originalParent) {
const dataId = originalParent.getAttribute('data-item-id') || originalParent.getAttribute('data-ved');
debug(`Imagem de produto encontrada: ${img.src} (ID: ${dataId})`);
highQualityImages.push(this.improveGoogleImageUrl(img.src));
}
}
});
});
document.querySelectorAll('[data-tbnid], .isv-r, .islrc > div, .PNCib').forEach(container => {
const dataId = container.getAttribute('data-id') || container.getAttribute('data-tbnid') ||
container.getAttribute('data-item-id') || container.getAttribute('data-ved');
if (!dataId) return;
const imgElements = container.querySelectorAll('img');
imgElements.forEach(img => {
const dataSrc = img.getAttribute('data-src') || '';
const dataIurl = img.getAttribute('data-iurl') || '';
const originalSource = img.getAttribute('data-iurl') || img.getAttribute('data-source') ||
img.getAttribute('data-src') || img.getAttribute('src');
if (originalSource && originalSource.startsWith('http') && !originalSource.includes('base64')) {
const betterUrl = this.improveGoogleImageUrl(originalSource);
debug(`Fonte de imagem original encontrada: ${betterUrl}`);
highQualityImages.push(betterUrl);
if (img.src && dataIurl && img.src !== dataIurl) {
this.googleImageCache.links[img.src] = dataIurl;
debug(`Mapeando: ${img.src} -> ${dataIurl}`);
}
}
if (img.srcset) {
const srcsetUrls = img.srcset.split(',')
.map(src => src.trim().split(' ')[0])
.filter(src => src && src.startsWith('http'));
if (srcsetUrls.length > 0) {
const largestImage = srcsetUrls[srcsetUrls.length-1];
debug(`Maior imagem do srcset: ${largestImage}`);
highQualityImages.push(this.improveGoogleImageUrl(largestImage));
}
}
});
const links = container.querySelectorAll('a[href*="imgurl="]');
links.forEach(link => {
const match = link.href.match(/imgurl=([^&]+)/);
if (match && match[1]) {
try {
const originalUrl = decodeURIComponent(match[1]);
if (originalUrl.match(/^https?:\/\//)) {
debug(`URL original encontrada em link: ${originalUrl}`);
highQualityImages.push(originalUrl);
const containerImages = container.querySelectorAll('img[src^="http"]');
containerImages.forEach(img => {
if (img.src) {
this.googleImageCache.links[img.src] = originalUrl;
debug(`Mapeando imagem do container: ${img.src} -> ${originalUrl}`);
}
});
}
} catch (e) {
debug(`Erro ao processar URL: ${e.message}`, true);
}
}
});
});
document.querySelectorAll('.rg_i, .rg_aic, .rg_bx, .isv-ib, .isv-r').forEach(container => {
const metaTags = container.querySelectorAll('[data-ved], [data-tbnid]');
metaTags.forEach(meta => {
const img = container.querySelector('img');
if (img) {
const fullSizeUrl = img.getAttribute('data-iurl') ||
img.getAttribute('data-src') ||
img.getAttribute('src');
if (fullSizeUrl && fullSizeUrl.startsWith('http') && !fullSizeUrl.includes('base64')) {
debug(`Imagem de alta qualidade em container: ${fullSizeUrl}`);
highQualityImages.push(this.improveGoogleImageUrl(fullSizeUrl));
}
}
const imgLinks = container.querySelectorAll('a[href*="imgurl="]');
imgLinks.forEach(link => {
const urlMatch = link.href.match(/imgurl=([^&]+)/);
if (urlMatch && urlMatch[1]) {
try {
const decodedUrl = decodeURIComponent(urlMatch[1]);
if (decodedUrl.match(/^https?:\/\//)) {
debug(`URL original em link interno: ${decodedUrl}`);
highQualityImages.push(decodedUrl);
}
} catch (e) {}
}
});
});
});
document.querySelectorAll('script:not([src])').forEach(script => {
try {
const content = script.textContent || '';
const ouMatches = content.match(/"ou":"([^"]+)"/g) || [];
ouMatches.forEach(match => {
try {
const url = match.replace(/"ou":"/, '').replace(/"$/, '');
if (url && url.startsWith('http')) {
debug(`URL extraída de script (ou): ${url}`);
highQualityImages.push(url);
}
} catch (e) {}
});
const urlPatterns = [/"([^"]*?\.(?:jpe?g|png|gif|webp))[^"]*?"/gi, /'([^']*?\.(?:jpe?g|png|gif|webp))[^']*?'/gi];
urlPatterns.forEach(pattern => {
const matches = content.match(pattern) || [];
matches.forEach(match => {
try {
const url = match.replace(/['"]/g, '');
if (url && url.startsWith('http') &&
!url.includes('google.com/') &&
!url.includes('gstatic.com/') &&
!url.includes('base64')) {
debug(`URL de imagem potencial extraída: ${url}`);
highQualityImages.push(url);
}
} catch (e) {}
});
});
} catch (e) {
}
});
if (isGoogleImages) {
const metaElements = document.querySelectorAll('meta[property="og:image"], meta[name="og:image"]');
metaElements.forEach(meta => {
if (meta.content && meta.content.startsWith('http')) {
debug(`Imagem de alta qualidade em metadados OG: ${meta.content}`);
highQualityImages.push(meta.content);
}
});
}
this.improveGoogleImageUrl = function(url) {
if (!url) return url;
if (url.includes('google.com/') || url.includes('gstatic.com/')) {
url = url.replace(/([?&])w=\d+(&|$)/, '$1')
.replace(/([?&])h=\d+(&|$)/, '$1')
.replace(/([?&])s=\d+(&|$)/, '$1')
.replace(/=s\d+-c/, '=s0')
.replace(/=w\d+-h\d+/, '=w0-h0');
}
if (url.includes('/proxy?') && url.includes('googleusercontent.com')) {
const urlMatch = url.match(/&url=([^&]+)/);
if (urlMatch && urlMatch[1]) {
try {
const decodedUrl = decodeURIComponent(urlMatch[1]);
if (decodedUrl.match(/^https?:\/\//)) {
return decodedUrl;
}
} catch (e) {}
}
}
return url;
};
const uniqueUrls = [...new Set(highQualityImages)].filter(url => {
return url && typeof url === 'string' && url.startsWith('http') && !url.includes('base64');
});
debug(`Total de URLs únicas de alta qualidade encontradas: ${uniqueUrls.length}`);
uniqueUrls.forEach(imageUrl => {
if (!this.isGoogleImageDuplicate(imageUrl)) {
const tempImg = new Image();
tempImg.src = imageUrl;
this.addImg(
this.imageType.IMG,
imageUrl,
tempImg.width || 0,
tempImg.height || 0,
detectImageFormat(imageUrl),
'Alta',
'Meio'
);
debug(`Imagem de alta qualidade adicionada: ${imageUrl}`);
} else {
debug(`Imagem duplicada ignorada: ${imageUrl}`);
}
});
const cacheSize = Object.keys(this.googleImageCache.links).length;
debug(`Total de links do Google processados: ${cacheSize}`);
} catch (e) {
debug('Erro ao escanear links do Google: ' + e.message, true);
console.error("Detalhes completos do erro:", e);
}
},
addImg: function addImg(type, src, width, height, format = 'Outro', quality = 'Média', position = 'Meio') {
this.imgList.push({
type: type,
src: src,
width: width,
height: height,
format: format,
quality: quality,
position: position
});
},
};
function doActualDownload(url, filename, callback, isBlob = false) {
if (typeof GM_download !== 'undefined') {
GM_download({
url: url,
name: filename,
onload: function() {
debug(`Download completo: ${filename}`);
if (isBlob) URL.revokeObjectURL(url);
if (callback) callback();
},
onerror: function(error) {
debug(`Erro no download: ${error}`, true);
if (isBlob) URL.revokeObjectURL(url);
if (callback) callback(error);
}
});
} else {
const a = document.createElement('a');
a.href = url;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(() => {
document.body.removeChild(a);
if (isBlob) URL.revokeObjectURL(url);
debug(`Download completado: ${filename}`);
if (callback) callback();
}, 100);
}
}
function getImageSearchUrl(imgSrc, searchEngine) {
switch (searchEngine) {
case 'yandex':
return `https://yandex.com/images/search?rpt=imageview&url=${encodeURIComponent(imgSrc)}`;
default:
return `https://lens.google.com/uploadbyurl?url=${encodeURIComponent(imgSrc)}`;
}
}
function convertImageAdvanced(blob, targetFormat, callback) {
if (['png', 'jpeg'].includes(targetFormat)) {
const blobUrl = URL.createObjectURL(blob);
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
const mimeType = targetFormat === 'png' ? 'image/png' : 'image/jpeg';
const quality = targetFormat === 'jpeg' ? 0.92 : undefined;
canvas.toBlob(function(newBlob) {
URL.revokeObjectURL(blobUrl);
const dataUrl = canvas.toDataURL(mimeType, quality);
callback(newBlob, dataUrl);
}, mimeType, quality);
};
img.onerror = function() {
URL.revokeObjectURL(blobUrl);
showModernAlert({
title: __('conversionError'),
message: __('imageProcessingError'),
buttonText: __('ok')
});
callback(blob, null);
};
img.src = blobUrl;
return;
}
if (targetFormat === 'ico') {
const blobUrl = URL.createObjectURL(blob);
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
const size = 32;
canvas.width = size;
canvas.height = size;
const ctx = canvas.getContext('2d');
ctx.imageSmoothingEnabled = true;
ctx.drawImage(img, 0, 0, size, size);
canvas.toBlob(function(pngBlob) {
const fileReader = new FileReader();
fileReader.onload = function() {
try {
const pngData = new Uint8Array(fileReader.result);
const header = new Uint8Array([
0, 0,
1, 0,
1, 0
]);
const directory = new Uint8Array([
size,
size,
0,
0,
1, 0,
32, 0,
0, 0, 0, 0,
22, 0, 0, 0
]);
const imageSize = pngData.length;
directory[8] = imageSize & 0xFF;
directory[9] = (imageSize >> 8) & 0xFF;
directory[10] = (imageSize >> 16) & 0xFF;
directory[11] = (imageSize >> 24) & 0xFF;
const icoData = new Uint8Array(22 + imageSize);
icoData.set(header, 0);
icoData.set(directory, 6);
icoData.set(pngData, 22);
const icoBlob = new Blob([icoData.buffer], {type: 'image/x-icon'});
URL.revokeObjectURL(blobUrl);
const icoUrl = URL.createObjectURL(icoBlob);
callback(icoBlob, icoUrl);
debug('Arquivo ICO criado com tamanho: ' + icoData.length + ' bytes');
} catch (error) {
debug('Erro ao criar ICO: ' + error.message, true);
URL.revokeObjectURL(blobUrl);
convertImageAdvanced(blob, 'png', callback);
}
};
fileReader.onerror = function() {
debug('Erro ao ler PNG para conversão ICO', true);
URL.revokeObjectURL(blobUrl);
convertImageAdvanced(blob, 'png', callback);
};
fileReader.readAsArrayBuffer(pngBlob);
}, 'image/png');
};
img.onerror = function() {
debug('Erro ao carregar imagem para conversão ICO', true);
URL.revokeObjectURL(blobUrl);
convertImageAdvanced(blob, 'png', callback);
};
img.src = blobUrl;
return;
}
if (targetFormat === 'base64') {
const blobUrl = URL.createObjectURL(blob);
const img = new Image();
img.onload = function() {
const canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
const ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0);
const dataUrl = canvas.toDataURL('image/png');
URL.revokeObjectURL(blobUrl);
callback(null, dataUrl);
};
img.onerror = function() {
URL.revokeObjectURL(blobUrl);
callback(blob, null);
};
img.src = blobUrl;
return;
}
debug(`Formato desconhecido: ${targetFormat}, usando PNG como fallback`);
convertImageAdvanced(blob, 'png', callback);
}
function downloadImage(url, filename, callback, options = {}) {
debug(`Iniciando download: ${filename} de ${url}`);
const settings = loadSettings();
const isGif = filename.toLowerCase().endsWith('.gif');
const shouldConvertGif = isGif && settings.convertGifToMp4;
const processImage = options.noConvert ? false :
(settings.autoConvertFormat !== 'original' || shouldConvertGif);
if (!processImage) {
debug(`Baixando no formato original sem conversão: ${filename}`);
doActualDownload(url, filename, callback);
return;
}
let targetFormat = settings.autoConvertFormat;
debug(`Usando formato de conversão configurado: ${targetFormat}`);
if (shouldConvertGif) {
targetFormat = 'mp4';
debug('GIF será convertido para MP4');
}
fetch(url, {
mode: 'cors',
cache: 'no-cache'
})
.then(response => {
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
return response.blob();
})
.then(blob => {
debug(`Blob recebido: ${blob.type}, ${blob.size} bytes`);
if (targetFormat === 'mp4' && isGif) {
debug('Convertendo GIF para MP4');
return new Blob([blob], { type: 'video/mp4' });
} else if (targetFormat !== 'original') {
debug(`Convertendo para formato: ${targetFormat}`);
return new Promise((resolve) => {
convertImageAdvanced(blob, targetFormat, resolve);
});
}
debug('Mantendo formato original');
return blob;
})
.then(processedBlob => {
const newFilename = filename.replace(/\.\w+$/, `.${targetFormat}`);
debug(`Nome de arquivo final após conversão: ${newFilename}`);
const blobUrl = URL.createObjectURL(processedBlob);
doActualDownload(blobUrl, newFilename, callback, true);
})
.catch(error => {
debug(`Erro ao processar imagem: ${error.message}`, true);
doActualDownload(url, filename, callback);
});
}
function downloadImagesAsZip(items) {
const settings = loadSettings();
debug(`Iniciando download de ${items.length} imagens. Configuração ZIP: ${settings.zipDownload}`);
if (!settings.zipDownload) {
debug('Download em ZIP desativado, baixando imagens individualmente...');
const statusMsg = document.createElement('div');
statusMsg.className = 'imagem-pro-loading';
statusMsg.textContent = __('preparingDownload');
statusMsg.id = 'imagem-pro-download-status';
const imagesContainer = document.getElementById('imagem-pro-images');
if (imagesContainer) imagesContainer.prepend(statusMsg);
let currentIndex = 0;
const totalItems = items.length;
let hasErrors = false;
function downloadNext() {
if (currentIndex >= totalItems) {
if (statusMsg.parentNode) statusMsg.parentNode.removeChild(statusMsg);
if (hasErrors) {
alert(__('downloadErrors'));
}
return;
}
const item = items[currentIndex];
const src = item.dataset.src;
let format = item.dataset.format === 'Outro' ? 'png' : item.dataset.format.toLowerCase() || 'jpg';
if (settings.convertGifToMp4 && format === 'gif') {
format = 'mp4';
debug(`Imagem ${currentIndex + 1} é GIF - convertendo para MP4`);
}
else if (settings.autoConvertFormat !== 'original') {
format = settings.autoConvertFormat;
debug(`Imagem ${currentIndex + 1} - usando formato configurado: ${format}`);
}
statusMsg.textContent = __('processingImage', currentIndex + 1, totalItems);
if (!src) {
debug(`URL vazia para imagem ${currentIndex + 1}, pulando...`);
currentIndex++;
setTimeout(downloadNext, 500);
return;
}
downloadImage(src, __('imageFilename', currentIndex + 1) + `.${format}`, function(error) {
if (error) {
hasErrors = true;
debug(`Erro ao baixar imagem ${currentIndex + 1}: ${error}`, true);
}
currentIndex++;
setTimeout(downloadNext, 500);
});
}
downloadNext();
return;
}
debug('Usando método de download em ZIP...');
loadJSZip((error) => {
if (error) {
debug('Erro ao carregar JSZip, usando download individual', true);
settings.zipDownload = false;
downloadImagesAsZip(items);
return;
}
const statusMsg = document.createElement('div');
statusMsg.className = 'imagem-pro-loading';
statusMsg.textContent = 'Preparando download em ZIP...';
statusMsg.id = 'imagem-pro-download-status';
const imagesContainer = document.getElementById('imagem-pro-images');
if (imagesContainer) imagesContainer.prepend(statusMsg);
const zip = new JSZip();
const folder = zip.folder("imagens");
let completed = 0;
const total = items.length;
const errors = [];
const promises = [];
const successfulItems = [];
items.forEach((item, index) => {
const src = item.dataset.src;
let format = item.dataset.format === 'Outro' ? 'png' : item.dataset.format.toLowerCase() || 'jpg';
if (!src) {
completed++;
debug(`ZIP: URL vazia para imagem ${index + 1}, pulando...`);
return;
}
if (settings.convertGifToMp4 && format === 'gif') {
format = 'mp4';
} else if (settings.autoConvertFormat !== 'original') {
format = settings.autoConvertFormat;
}
const fileName = `imagem_${index + 1}.${format}`;
const itemPromise = new Promise((resolve, reject) => {
statusMsg.textContent = `Processando imagem ${index + 1} de ${total}...`;
fetch(src, { mode: 'cors', cache: 'no-cache' })
.then(response => {
if (!response.ok) throw new Error(`HTTP error! Status: ${response.status}`);
return response.blob();
})
.then(blob => {
debug(`ZIP: Blob recebido para imagem ${index + 1}: ${blob.type}, tamanho: ${blob.size}`);
if (settings.convertGifToMp4 && format === 'mp4') {
return new Blob([blob], { type: 'video/mp4' });
}
else if (settings.autoConvertFormat !== 'original') {
return new Promise((convertResolve) => {
convertImageFormat(blob, settings.autoConvertFormat, convertResolve);
});
}
return blob;
})
.then(processedBlob => {
debug(`ZIP: Adicionando imagem ${index + 1} ao zip: ${fileName}, tamanho: ${processedBlob.size}`);
folder.file(fileName, processedBlob);
debug(`ZIP: Imagem ${index + 1} adicionada com sucesso`);
successfulItems.push({
index: index,
fileName: fileName
});
resolve();
})
.catch(error => {
debug(`ZIP: Erro ao processar imagem ${index + 1}: ${error.message}, tentando alternativa...`, true);
if (typeof GM_xmlhttpRequest !== 'undefined') {
debug(`ZIP: Tentando download alternativo para imagem ${index + 1}`);
GM_xmlhttpRequest({
method: 'GET',
url: src,
responseType: 'blob',
onload: function(response) {
try {
const blob = response.response;
folder.file(fileName, blob);
debug(`ZIP: Imagem ${index + 1} adicionada com sucesso (método alternativo)`);
successfulItems.push({
index: index,
fileName: fileName
});
resolve();
} catch (e) {
debug(`ZIP: Erro no método alternativo para imagem ${index + 1}: ${e.message}`, true);
errors.push(`Imagem ${index + 1}: ${e.message}`);
resolve();
}
},
onerror: function(response) {
debug(`ZIP: Erro no método alternativo para imagem ${index + 1}`, true);
errors.push(`Imagem ${index + 1}: Falha no download alternativo`);
resolve();
}
});
} else {
errors.push(`Imagem ${index + 1}: ${error.message}`);
resolve();
}
})
.finally(() => {
completed++;
const progress = Math.round((completed / total) * 100);
statusMsg.textContent = `Processando: ${progress}% (${completed}/${total})`;
});
});
promises.push(itemPromise);
});
Promise.all(promises).then(() => {
if (errors.length > 0) {
debug(`Concluído com ${errors.length} erros: ${errors.join(', ')}`, true);
}
if (successfulItems.length === 0) {
statusMsg.textContent = __('errorProcessingImage');
debug('Erro: ZIP vazio - nenhuma imagem adicionada. Tentando método alternativo...', true);
setTimeout(() => {
statusMsg.remove();
settings.zipDownload = false;
downloadImagesAsZip(items);
}, 2000);
return;
}
statusMsg.textContent = __('generatingZip', successfulItems.length);
debug(`Gerando ZIP com ${successfulItems.length} imagens`);
zip.generateAsync({type:"blob"})
.then(function(content) {
const zipName = __('zipFilename', new Date().getTime()) + '.zip';
debug(`ZIP gerado com sucesso: ${content.size} bytes`);
if (typeof GM_download !== "undefined") {
statusMsg.textContent = __('downloadStarted');
GM_download({
url: URL.createObjectURL(content),
name: zipName,
onload: function() {
statusMsg.remove();
debug(`Download do ZIP completo: ${zipName}`);
},
onerror: function(e) {
statusMsg.textContent = 'Erro ao baixar o arquivo ZIP, tentando método alternativo...';
setTimeout(() => {
statusMsg.remove();
const link = document.createElement('a');
link.href = URL.createObjectURL(content);
link.download = zipName;
document.body.appendChild(link);
link.click();
setTimeout(() => {
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
debug(`Download do ZIP iniciado via método alternativo: ${zipName}`);
}, 100);
}, 1000);
debug(`Erro ao baixar ZIP: ${e}`, true);
}
});
} else {
const link = document.createElement('a');
link.href = URL.createObjectURL(content);
link.download = zipName;
document.body.appendChild(link);
link.click();
setTimeout(() => {
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
statusMsg.remove();
debug(`Download do ZIP iniciado via fallback: ${zipName}`);
}, 100);
}
})
.catch(function(error) {
statusMsg.textContent = 'Erro ao gerar o arquivo ZIP, tentando download individual...';
setTimeout(() => {
statusMsg.remove();
settings.zipDownload = false;
downloadImagesAsZip(items);
}, 2000);
debug(`Erro ao gerar ZIP: ${error.message}`, true);
});
});
});
}
function createImageElement(img, index) {
if (img.src && img.src.includes('/hqdefault.jpg')) {
const baseUrl = img.src.split('/hqdefault.jpg')[0];
img.src = baseUrl + '/maxresdefault.jpg';
debug(`URL do YouTube convertida na criação do elemento: ${baseUrl}/maxresdefault.jpg`);
}
if (img.src && img.src.includes('i.pinimg.com/') && !img.src.includes('i.pinimg.com/originals/')) {
img.src = img.src.replace(/i\.pinimg\.com\/[^\/]+\//, 'i.pinimg.com/originals/');
}
const imagesContainer = document.getElementById('imagem-pro-images');
if (!imagesContainer) return;
if (document.querySelector(`.imagem-pro-item[data-src="${img.src}"]`)) {
debug(`Imagem já existe no painel DOM: ${img.src}`);
return;
}
const normalizedUrl = imageCache.normalizeUrl(img.src);
if (normalizedUrl && document.querySelector(`.imagem-pro-item[data-normalized-url="${normalizedUrl}"]`)) {
debug(`Imagem normalizada já existe no painel: ${normalizedUrl}`);
return;
}
const settings = loadSettings();
const imgDiv = document.createElement('div');
imgDiv.className = 'imagem-pro-item';
imgDiv.dataset.src = img.src;
imgDiv.dataset.normalizedUrl = normalizedUrl;
imgDiv.dataset.type = img.type;
imgDiv.dataset.format = img.format;
imgDiv.dataset.quality = img.quality;
imgDiv.dataset.position = img.position;
const previewContainer = document.createElement('div');
previewContainer.className = 'imagem-pro-preview';
const checkboxContainer = document.createElement('div');
checkboxContainer.className = 'imagem-pro-checkbox-container';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.className = 'imagem-pro-checkbox';
checkbox.dataset.index = index;
checkbox.addEventListener('click', function(e) {
e.stopPropagation();
});
checkbox.addEventListener('change', function() {
setTimeout(updateSelectedCount, 50);
});
ImagemPro.eventListeners.push({
element: checkbox,
event: 'change',
handler: function() { setTimeout(updateSelectedCount, 50); }
});
checkboxContainer.appendChild(checkbox);
previewContainer.appendChild(checkboxContainer);
if (img.src) {
try {
new URL(img.src);
if (img.src.startsWith('data:image/svg')) {
const imgEl = document.createElement('div');
imgEl.style.width = '100%';
imgEl.style.height = '100%';
imgEl.style.backgroundImage = `url("${img.src}")`;
imgEl.style.backgroundSize = 'contain';
imgEl.style.backgroundRepeat = 'no-repeat';
imgEl.style.backgroundPosition = 'center';
previewContainer.appendChild(imgEl);
} else {
const imgEl = document.createElement('img');
imgEl.alt = `Imagem ${index + 1}`;
imgEl.src = img.src;
previewContainer.appendChild(imgEl);
}
} catch (e) {
debug(`URL inválida ignorada: ${img.src}`, true);
const errorEl = document.createElement('div');
errorEl.style.width = '100%';
errorEl.style.height = '100%';
errorEl.style.display = 'flex';
errorEl.style.alignItems = 'center';
errorEl.style.justifyContent = 'center';
errorEl.textContent = __('invalidUrl');
previewContainer.appendChild(errorEl);
}
} else {
const noImgEl = document.createElement('div');
noImgEl.style.width = '100%';
noImgEl.style.height = '100%';
noImgEl.style.display = 'flex';
noImgEl.style.alignItems = 'center';
noImgEl.style.justifyContent = 'center';
noImgEl.textContent = __('noImage');
previewContainer.appendChild(noImgEl);S
}
imgDiv.appendChild(previewContainer);
const infoDiv = document.createElement('div');
infoDiv.className = 'imagem-pro-item-info';
setInnerHTML(infoDiv, `
${__('format')}: ${img.format} | ${__('quality')}: ${__('quality_' + img.quality.toLowerCase())} | ${__('position')}: ${__('position_' + img.position.toLowerCase())}<br>
${img.width && img.height ? `${__('dimensions')}: ${img.width}x${img.height}px<br>` : ''}
${__('url')}: ${img.src.substring(0, 50)}${img.src.length > 50 ? '...' : ''}
`);
imgDiv.appendChild(infoDiv);
const actionsDiv = document.createElement('div');
actionsDiv.className = 'imagem-pro-actions';
const openBtn = document.createElement('button');
openBtn.className = 'imagem-pro-btn open';
setInnerHTML(openBtn, SVG_ICONS.externalLink + `<span class="imagem-pro-btn-tooltip">${__('openNewTab')}</span>`);
openBtn.addEventListener('click', function(e) {
e.preventDefault();
window.open(img.src, '_blank');
});
actionsDiv.appendChild(openBtn);
const lensBtn = document.createElement('button');
lensBtn.className = 'imagem-pro-btn lens';
let tooltipText = __('searchWith', 'Google Lens');
if (settings.searchEngine === 'yandex') {
tooltipText = __('searchWith', 'Yandex');
}
setInnerHTML(lensBtn, SVG_ICONS.search + `<span class="imagem-pro-btn-tooltip">${tooltipText}</span>`);
lensBtn.addEventListener('click', function() {
const searchUrl = getImageSearchUrl(img.src, settings.searchEngine);
window.open(searchUrl, '_blank');
});
actionsDiv.appendChild(lensBtn);
const downloadBtn = document.createElement('button');
downloadBtn.className = 'imagem-pro-btn download';
setInnerHTML(downloadBtn, SVG_ICONS.download + `<span class="imagem-pro-btn-tooltip">${__('downloadImage')}</span>`);
downloadBtn.addEventListener('click', function() {
let format = img.format === 'Outro' ? 'png' : img.format.toLowerCase();
if (img.src && imageManager.googleImageCache.originalSources[img.src]) {
downloadImage(imageManager.googleImageCache.originalSources[img.src], `imagem_${index+1}.${format}`);
} else {
downloadImage(img.src, `imagem_${index+1}.${format}`);
}
});
actionsDiv.appendChild(downloadBtn);
imgDiv.appendChild(actionsDiv);
imagesContainer.appendChild(imgDiv);
updateSelectedCount();
updateImageCount();
}
function createUI() {
if (document.getElementById('imagem-pro-container')) {
return;
}
if (!document.getElementById('kiwi-maru-font')) {
const fontLink = document.createElement('link');
fontLink.id = 'kiwi-maru-font';
fontLink.rel = 'stylesheet';
fontLink.href = 'https://fonts.googleapis.com/css2?family=Kiwi+Maru:wght@300;400;500&display=swap';
document.head.appendChild(fontLink);
}
const container = document.createElement('div');
container.id = 'imagem-pro-container';
const header = document.createElement('div');
header.className = 'imagem-pro-header';
const title = document.createElement('h2');
title.textContent = __('title');
header.appendChild(title);
const settingsBtn = document.createElement('button');
settingsBtn.className = 'imagem-pro-settings-btn';
settingsBtn.id = 'imagem-pro-settings-btn';
settingsBtn.title = __('settings');
setInnerHTML(settingsBtn, SVG_ICONS.settings);
settingsBtn.addEventListener('click', function() {
showSettingsModal();
});
header.appendChild(settingsBtn);
const filtersDiv = document.createElement('div');
filtersDiv.className = 'imagem-pro-filters';
const selectAllDiv = document.createElement('div');
selectAllDiv.className = 'imagem-pro-select-all';
const selectAllCheckbox = document.createElement('input');
selectAllCheckbox.type = 'checkbox';
selectAllCheckbox.id = 'imagem-pro-select-all-checkbox';
selectAllCheckbox.className = 'imagem-pro-checkbox';
const selectAllLabel = document.createElement('label');
selectAllLabel.htmlFor = 'imagem-pro-select-all-checkbox';
selectAllLabel.textContent = __('selectAll');
const selectedCount = document.createElement('span');
selectedCount.className = 'imagem-pro-selected-count';
selectedCount.textContent = __('selected', 0, 0, '');
selectAllDiv.appendChild(selectAllCheckbox);
selectAllDiv.appendChild(selectAllLabel);
selectAllDiv.appendChild(selectedCount);
filtersDiv.appendChild(selectAllDiv);
const formatFilterRow = document.createElement('div');
formatFilterRow.className = 'imagem-pro-filter-row';
const formatSelect = document.createElement('select');
formatSelect.id = 'imagem-pro-format-filter';
const formatOptions = [
{ value: 'ALL', text: __('allFormats') },
{ value: 'JPG', text: 'JPG/JPEG' },
{ value: 'PNG', text: 'PNG' },
{ value: 'SVG', text: 'SVG' },
{ value: 'GIF', text: 'GIF' },
{ value: 'WEBP', text: 'WEBP' },
{ value: 'ICO', text: 'ICO' },
{ value: 'BMP', text: 'BMP' },
{ value: 'TIFF', text: 'TIFF' },
{ value: 'Outro', text: __('otherFormats') }
];
formatOptions.forEach(opt => {
const option = document.createElement('option');
option.value = opt.value;
option.textContent = opt.text;
formatSelect.appendChild(option);
});
formatFilterRow.appendChild(formatSelect);
filtersDiv.appendChild(formatFilterRow);
const qualityFilterRow = document.createElement('div');
qualityFilterRow.className = 'imagem-pro-filter-row';
const qualitySelect = document.createElement('select');
qualitySelect.id = 'imagem-pro-quality-filter';
const qualityOptions = [
{ value: 'ALL', text: __('allQualities') },
{ value: 'Alta', text: __('highQuality') },
{ value: 'Média', text: __('mediumQuality') },
{ value: 'Baixa', text: __('lowQuality') }
];
qualityOptions.forEach(opt => {
const option = document.createElement('option');
option.value = opt.value;
option.textContent = opt.text;
qualitySelect.appendChild(option);
});
qualityFilterRow.appendChild(qualitySelect);
filtersDiv.appendChild(qualityFilterRow);
const positionFilterRow = document.createElement('div');
positionFilterRow.className = 'imagem-pro-filter-row';
const positionSelect = document.createElement('select');
positionSelect.id = 'imagem-pro-position-filter';
const positionOptions = [
{ value: 'ALL', text: __('allPositions') },
{ value: 'Topo', text: __('topPage') },
{ value: 'Meio', text: __('middlePage') },
{ value: 'Baixo', text: __('bottomPage') }
];
positionOptions.forEach(opt => {
const option = document.createElement('option');
option.value = opt.value;
option.textContent = opt.text;
positionSelect.appendChild(option);
});
positionFilterRow.appendChild(positionSelect);
filtersDiv.appendChild(positionFilterRow);
const actionsRow = document.createElement('div');
actionsRow.className = 'imagem-pro-filter-row';
actionsRow.style.display = 'flex';
actionsRow.style.justifyContent = 'space-between';
const refreshBtn = document.createElement('button');
refreshBtn.id = 'imagem-pro-refresh';
refreshBtn.className = 'imagem-pro-btn';
refreshBtn.style.flex = '1';
refreshBtn.style.margin = '0 5px';
setInnerHTML(refreshBtn, SVG_ICONS.refresh + `<span class="imagem-pro-btn-tooltip">${__('refresh')}</span>`);
const downloadAllBtn = document.createElement('button');
downloadAllBtn.id = 'imagem-pro-download-all';
downloadAllBtn.className = 'imagem-pro-btn download-all';
downloadAllBtn.style.flex = '1';
downloadAllBtn.style.margin = '0 5px';
setInnerHTML(downloadAllBtn, SVG_ICONS.download + `<span class="imagem-pro-btn-tooltip">${__('downloadSelected')}</span>`);
const closeBtn = document.createElement('button');
closeBtn.id = 'imagem-pro-close';
closeBtn.className = 'imagem-pro-btn close';
closeBtn.style.flex = '1';
closeBtn.style.margin = '0 5px';
setInnerHTML(closeBtn, SVG_ICONS.close + `<span class="imagem-pro-btn-tooltip">${__('close')}</span>`);
actionsRow.appendChild(refreshBtn);
actionsRow.appendChild(downloadAllBtn);
actionsRow.appendChild(closeBtn);
filtersDiv.appendChild(actionsRow);
header.appendChild(filtersDiv);
const countElement = document.createElement('div');
countElement.id = 'imagem-pro-count';
countElement.textContent = '';
header.appendChild(countElement);
const imagesContainer = document.createElement('div');
imagesContainer.id = 'imagem-pro-images';
container.appendChild(header);
container.appendChild(imagesContainer);
document.body.appendChild(container);
document.getElementById('imagem-pro-format-filter').addEventListener('change', applyFilters);
document.getElementById('imagem-pro-quality-filter').addEventListener('change', applyFilters);
document.getElementById('imagem-pro-position-filter').addEventListener('change', applyFilters);
document.getElementById('imagem-pro-refresh').addEventListener('click', function() {
applyFilters();
});
document.getElementById('imagem-pro-download-all').addEventListener('click', function() {
const items = document.querySelectorAll('#imagem-pro-images .imagem-pro-item');
const selectedItems = Array.from(items).filter(item => {
const checkbox = item.querySelector('.imagem-pro-checkbox');
return checkbox && checkbox.checked;
});
if (selectedItems.length === 0) {
alert(__('selectOneImage'));
return;
}
if (selectedItems.length === 1) {
const item = selectedItems[0];
const src = item.dataset.src;
const format = item.dataset.format === 'Outro' ? 'png' : item.dataset.format.toLowerCase() || 'jpg';
if (!src) return;
downloadImage(src, `imagem_1.${format}`);
return;
}
downloadImagesAsZip(selectedItems);
});
document.getElementById('imagem-pro-close').addEventListener('click', function() {
container.classList.remove('show');
imageCache.clear();
debug('Cache de imagens limpo (fechamento via botão)');
});
document.getElementById('imagem-pro-select-all-checkbox').addEventListener('change', function() {
const checkboxes = document.querySelectorAll('.imagem-pro-item .imagem-pro-checkbox');
checkboxes.forEach(cb => {
cb.checked = this.checked;
});
updateSelectedCount();
});
setTimeout(() => {
addScrollListener();
}, 500);
}
function togglePanel() {
if (!document.getElementById('imagem-pro-container')) {
debug('Criando interface do usuário');
createUI();
}
const container = document.getElementById('imagem-pro-container');
if (!container) {
debug('Container não encontrado', true);
return;
}
const isVisible = container.classList.contains('show');
if (isVisible) {
container.classList.remove('show');
imageCache.clear();
imageManager.clearCache();
ImagemPro.eventListeners.forEach(listener => {
if (listener.element && listener.event && listener.handler) {
listener.element.removeEventListener(listener.event, listener.handler);
}
});
ImagemPro.eventListeners = [];
debug('Painel fechado e todos os caches limpos');
imageCache.images = [];
} else {
container.classList.add('show');
imageCache.clear();
imageManager.clearCache();
const imagesContainer = document.getElementById('imagem-pro-images');
if (imagesContainer) {
setInnerHTML(imagesContainer, `<div class="imagem-pro-loading">${__('refreshingImages')}</div>`);
}
setTimeout(() => {
loadImages(false);
debug('Painel aberto, atualizando e carregando imagens do zero...');
setTimeout(() => {
addScrollListener();
}, 500);
}, 100);
}
}
function loadJSZip(callback) {
if (window.JSZip) {
callback();
return;
}
const script = document.createElement('script');
script.src = 'https://update.greasyfork.dpdns.org/scripts/518632/1489865/jszip-min-js.js';
script.onload = callback;
script.onerror = () => {
debug('Erro ao carregar JSZip. Usando método de download alternativo.', true);
alert(__('jsZipError'));
callback(true);
};
document.head.appendChild(script);
}
function applyFilters() {
loadImages(false);
updateImageCount();
}
function updateSelectedCount() {
try {
const checkboxes = document.querySelectorAll('.imagem-pro-item .imagem-pro-checkbox');
const selectedCount = Array.from(checkboxes).filter(cb => cb.checked).length;
const totalCount = checkboxes.length;
const countElement = document.querySelector('.imagem-pro-selected-count');
if (countElement) {
countElement.textContent = __('selected', selectedCount, totalCount, selectedCount === 1 ? '' : 's');
}
const selectAllCheckbox = document.getElementById('imagem-pro-select-all-checkbox');
if (selectAllCheckbox && totalCount > 0) {
selectAllCheckbox.checked = selectedCount > 0 && selectedCount === totalCount;
selectAllCheckbox.indeterminate = selectedCount > 0 && selectedCount < totalCount;
}
debug(`Atualização de seleção: ${selectedCount} de ${totalCount} imagens selecionadas`);
} catch (e) {
debug('Erro ao atualizar contagem de seleção: ' + e.message, true);
}
}
function addScrollListener() {
const imagesContainer = document.getElementById('imagem-pro-images');
if (!imagesContainer) return;
let isLoading = false;
let scrollTimeout = null;
let lastScrollTime = 0;
const SCROLL_THROTTLE = 150;
imagesContainer.addEventListener('scroll', function() {
if (isLoading) return;
const now = Date.now();
if (now - lastScrollTime < SCROLL_THROTTLE) {
if (scrollTimeout) {
clearTimeout(scrollTimeout);
}
scrollTimeout = setTimeout(() => {
checkScrollPosition();
scrollTimeout = null;
}, SCROLL_THROTTLE);
return;
}
lastScrollTime = now;
checkScrollPosition();
});
function checkScrollPosition() {
requestAnimationFrame(() => {
const scrollPosition = imagesContainer.scrollTop + imagesContainer.offsetHeight;
const scrollHeight = imagesContainer.scrollHeight;
if (scrollPosition >= scrollHeight - 300) {
debug('Alcançou o fim da rolagem, carregando mais imagens...');
isLoading = true;
setTimeout(() => {
loadImages(true);
setTimeout(() => {
isLoading = false;
}, 800);
}, 50);
}
});
}
debug('Listener de rolagem otimizado adicionado');
}
const defaultSettings = {
zipDownload: true,
convertGifToMp4: false,
autoConvertFormat: 'original',
searchEngine: 'googlelens',
hotkeyCombo: 'shift+s',
limitPx: 0,
pixelPriority: 'higher'
};
function loadSettings() {
let settings = defaultSettings;
try {
if (typeof GM_getValue === 'undefined') {
debug('GM_getValue não disponível, usando configurações padrão');
return settings;
}
const savedSettings = GM_getValue('imagemProSettings');
if (savedSettings) {
settings = { ...defaultSettings, ...JSON.parse(savedSettings) };
}
} catch (e) {
debug('Erro ao carregar configurações: ' + e.message, true);
}
return settings;
}
function saveSettings(settings) {
try {
if (typeof GM_setValue === 'undefined') {
debug('GM_setValue não disponível, configurações não foram salvas', true);
return;
}
GM_setValue('imagemProSettings', JSON.stringify(settings));
debug('Configurações salvas com sucesso');
} catch (e) {
debug('Erro ao salvar configurações: ' + e.message, true);
}
}
function showSettingsModal() {
if (document.getElementById('imagem-pro-settings-modal')) {
document.getElementById('imagem-pro-settings-modal').classList.add('show');
enhanceHotkeyInput();
return;
}
if (!document.getElementById('kiwi-maru-font')) {
const fontLink = document.createElement('link');
fontLink.id = 'kiwi-maru-font';
fontLink.rel = 'stylesheet';
fontLink.href = 'https://fonts.googleapis.com/css2?family=Kiwi+Maru:wght@300;400;500&display=swap';
document.head.appendChild(fontLink);
}
const settings = loadSettings();
const modal = document.createElement('div');
modal.id = 'imagem-pro-settings-modal';
setInnerHTML(modal, `
<div id="imagem-pro-settings-header">
<h2 id="imagem-pro-settings-title">${__('settings')}</h2>
<button id="imagem-pro-settings-close">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12.8536 2.85355C13.0488 2.65829 13.0488 2.34171 12.8536 2.14645C12.6583 1.95118 12.3417 1.95118 12.1464 2.14645L8 6.29289L3.85355 2.14645C3.65829 1.95118 3.34171 1.95118 3.14645 2.14645C2.95118 2.34171 2.95118 2.65829 3.14645 2.85355L7.29289 7L3.14645 11.1464C2.95118 11.3417 2.95118 11.6583 3.14645 11.8536C3.34171 12.0488 3.65829 12.0488 3.85355 11.8536L8 7.70711L12.1464 11.8536C12.3417 12.0488 12.6583 12.0488 12.8536 11.8536C13.0488 11.6583 13.0488 11.3417 12.8536 11.1464L8.70711 7L12.8536 2.85355Z" fill="currentColor"/>
</svg>
</button>
</div>
<div id="imagem-pro-settings-tabs">
<button class="imagem-pro-tab active" data-tab="general">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M19.4 15C19.2669 15.3016 19.2272 15.6362 19.286 15.9606C19.3448 16.285 19.4995 16.5843 19.73 16.82L19.79 16.88C19.976 17.0657 20.1235 17.2863 20.2241 17.5291C20.3248 17.7719 20.3766 18.0322 20.3766 18.295C20.3766 18.5578 20.3248 18.8181 20.2241 19.0609C20.1235 19.3037 19.976 19.5243 19.79 19.71C19.6043 19.896 19.3837 20.0435 19.1409 20.1441C18.8981 20.2448 18.6378 20.2966 18.375 20.2966C18.1122 20.2966 17.8519 20.2448 17.6091 20.1441C17.3663 20.0435 17.1457 19.896 16.96 19.71L16.9 19.65C16.6643 19.4195 16.365 19.2648 16.0406 19.206C15.7162 19.1472 15.3816 19.1869 15.08 19.32C14.7842 19.4468 14.532 19.6572 14.3543 19.9255C14.1766 20.1938 14.0813 20.5082 14.08 20.83V21C14.08 21.5304 13.8693 22.0391 13.4942 22.4142C13.1191 22.7893 12.6104 23 12.08 23C11.5496 23 11.0409 22.7893 10.6658 22.4142C10.2907 22.0391 10.08 21.5304 10.08 21V20.91C10.0723 20.579 9.96512 20.258 9.77251 19.9887C9.5799 19.7194 9.31074 19.5143 9 19.4C8.69838 19.2669 8.36381 19.2272 8.03941 19.286C7.71502 19.3448 7.41568 19.4995 7.18 19.73L7.12 19.79C6.93425 19.976 6.71368 20.1235 6.47088 20.2241C6.22808 20.3248 5.96783 20.3766 5.705 20.3766C5.44217 20.3766 5.18192 20.3248 4.93912 20.2241C4.69632 20.1235 4.47575 19.976 4.29 19.79C4.10405 19.6043 3.95653 19.3837 3.85588 19.1409C3.75523 18.8981 3.70343 18.6378 3.70343 18.375C3.70343 18.1122 3.75523 17.8519 3.85588 17.6091C3.95653 17.3663 4.10405 17.1457 4.29 16.96L4.35 16.9C4.58054 16.6643 4.73519 16.365 4.794 16.0406C4.85282 15.7162 4.81312 15.3816 4.68 15.08C4.55324 14.7842 4.34276 14.532 4.07447 14.3543C3.80618 14.1766 3.49179 14.0813 3.17 14.08H3C2.46957 14.08 1.96086 13.8693 1.58579 13.4942C1.21071 13.1191 1 12.6104 1 12.08C1 11.5496 1.21071 11.0409 1.58579 10.6658C1.96086 10.2907 2.46957 10.08 3 10.08H3.09C3.42099 10.0723 3.742 9.96512 4.0113 9.77251C4.28059 9.5799 4.48572 9.31074 4.6 9C4.73312 8.69838 4.77282 8.36381 4.714 8.03941C4.65519 7.71502 4.50054 7.41568 4.27 7.18L4.21 7.12C4.02405 6.93425 3.87653 6.71368 3.77588 6.47088C3.67523 6.22808 3.62343 5.96783 3.62343 5.705C3.62343 5.44217 3.67523 5.18192 3.77588 4.93912C3.87653 4.69632 4.02405 4.47575 4.21 4.29C4.39575 4.10405 4.61632 3.95653 4.85912 3.85588C5.10192 3.75523 5.36217 3.70343 5.625 3.70343C5.88783 3.70343 6.14808 3.75523 6.39088 3.85588C6.63368 3.95653 6.85425 4.10405 7.04 4.29L7.1 4.35C7.33568 4.58054 7.63502 4.73519 7.95941 4.794C8.28381 4.85282 8.61838 4.81312 8.92 4.68H9C9.29577 4.55324 9.54802 4.34276 9.72569 4.07447C9.90337 3.80618 9.99872 3.49179 10 3.17V3C10 2.46957 10.2107 1.96086 10.5858 1.58579C10.9609 1.21071 11.4696 1 12 1C12.5304 1 13.0391 1.21071 13.4142 1.58579C13.7893 1.96086 14 2.46957 14 3V3.09C14.0013 3.41179 14.0966 3.72618 14.2743 3.99447C14.452 4.26276 14.7042 4.47324 15 4.6C15.3016 4.73312 15.6362 4.77282 15.9606 4.714C16.285 4.65519 16.5843 4.50054 16.82 4.27L16.88 4.21C17.0657 4.02405 17.2863 3.87653 17.5291 3.77588C17.7719 3.67523 18.0322 3.62343 18.295 3.62343C18.5578 3.62343 18.8181 3.67523 19.0609 3.77588C19.3037 3.87653 19.5243 4.02405 19.71 4.21C19.896 4.39575 20.0435 4.61632 20.1441 4.85912C20.2448 5.10192 20.2966 5.36217 20.2966 5.625C20.2966 5.88783 20.2448 6.14808 20.1441 6.39088C20.0435 6.63368 19.896 6.85425 19.71 7.04L19.65 7.1C19.4195 7.33568 19.2648 7.63502 19.206 7.95941C19.1472 8.28381 19.1869 8.61838 19.32 8.92V9C19.4468 9.29577 19.6572 9.54802 19.9255 9.72569C20.1938 9.90337 20.5082 9.99872 20.83 10H21C21.5304 10 22.0391 10.2107 22.4142 10.5858C22.7893 10.9609 23 11.4696 23 12C23 12.5304 22.7893 13.0391 22.4142 13.4142C22.0391 13.7893 21.5304 14 21 14H20.91C20.5882 14.0013 20.2738 14.0966 20.0055 14.2743C19.7372 14.452 19.5268 14.7042 19.4 15Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
${__('generalTab')}
</button>
<button class="imagem-pro-tab" data-tab="converter">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 5L3 10L8 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 5L21 10L16 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 3L10 17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span>${__('converterTab')}</span>
</button>
<button class="imagem-pro-tab" data-tab="search">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21 21L16.65 16.65" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<span>${__('searchTab')}</span>
</button>
</div>
<div id="imagem-pro-settings-content">
<div class="imagem-pro-settings-tab-content active" id="tab-general">
<div class="imagem-pro-settings-section">
<div class="imagem-pro-toggle-group">
<div class="imagem-pro-settings-option">
<span class="imagem-pro-settings-option-label">${__('zipDownload')}</span>
<label class="imagem-pro-settings-toggle">
<input type="checkbox" id="settings-zip-download" ${settings.zipDownload ? 'checked' : ''}>
<span class="imagem-pro-settings-toggle-slider"></span>
</label>
</div>
<div class="imagem-pro-settings-option">
<span class="imagem-pro-settings-option-label">${__('convertGif')}</span>
<label class="imagem-pro-settings-toggle">
<input type="checkbox" id="settings-gif-convert" ${settings.convertGifToMp4 ? 'checked' : ''}>
<span class="imagem-pro-settings-toggle-slider"></span>
</label>
</div>
</div>
<div class="imagem-pro-input-group">
<div class="imagem-pro-input-field">
<label for="settings-auto-convert">${__('autoConversion')}</label>
<div class="imagem-pro-select-wrapper">
<select id="settings-auto-convert" class="imagem-pro-input">
<option value="original" ${settings.autoConvertFormat === 'original' ? 'selected' : ''}>${__('original')}</option>
<option value="png" ${settings.autoConvertFormat === 'png' ? 'selected' : ''}>PNG</option>
<option value="jpeg" ${settings.autoConvertFormat === 'jpeg' ? 'selected' : ''}>JPEG</option>
</select>
<svg class="imagem-pro-select-arrow" viewBox="0 0 10 6" width="10" height="6" fill="none">
<path d="M1 1L5 5L9 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
<div class="imagem-pro-input-field">
<label for="settings-search-engine">${__('searchEngine')}</label>
<div class="imagem-pro-select-wrapper">
<select id="settings-search-engine" class="imagem-pro-input">
<option value="googlelens" ${settings.searchEngine === 'googlelens' ? 'selected' : ''}>Google Lens</option>
<option value="yandex" ${settings.searchEngine === 'yandex' ? 'selected' : ''}>Yandex</option>
</select>
<svg class="imagem-pro-select-arrow" viewBox="0 0 10 6" width="10" height="6" fill="none">
<path d="M1 1L5 5L9 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
<div class="imagem-pro-input-field">
<label for="settings-hotkey">${__('hotkey')}</label>
<input type="text" id="settings-hotkey" class="imagem-pro-input" value="${settings.hotkeyCombo}" placeholder="ex: shift+s">
</div>
<div class="imagem-pro-input-field">
<label for="settings-limit-px">${__('filterMinSize')} (px)</label>
<input type="number" id="settings-limit-px" class="imagem-pro-input" value="${settings.limitPx}" placeholder="0">
</div>
<div class="imagem-pro-input-field">
<label for="settings-pixel-priority">${__('pixelPriority')}</label>
<div class="imagem-pro-select-wrapper">
<select id="settings-pixel-priority" class="imagem-pro-input">
<option value="normal" ${settings.pixelPriority === 'normal' ? 'selected' : ''}>${__('pixelPriorityNormal')}</option>
<option value="higher" ${settings.pixelPriority === 'higher' ? 'selected' : ''}>${__('pixelPriorityHigher')}</option>
<option value="lower" ${settings.pixelPriority === 'lower' ? 'selected' : ''}>${__('pixelPriorityLower')}</option>
</select>
<svg class="imagem-pro-select-arrow" viewBox="0 0 10 6" width="10" height="6" fill="none">
<path d="M1 1L5 5L9 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
</div>
</div>
</div>
</div>
<div class="imagem-pro-settings-tab-content" id="tab-converter">
<div class="imagem-pro-settings-section">
<div class="imagem-pro-converter-container">
<div class="imagem-pro-file-upload">
<input type="file" id="converter-file-input" accept="image/*" style="display:none;">
<button id="converter-import-btn" class="imagem-pro-btn primary" style="margin: 0 auto; display: block; width: 80%;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M21 15V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 8L12 3L7 8" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 3V15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
${__('importImage')}
</button>
<div id="converter-filename" class="imagem-pro-filename" style="text-align: center; margin-top: 10px; color: rgba(255,255,255,0.6);">${__('noImageSelected')}</div>
</div>
<div class="imagem-pro-preview-container">
<div id="converter-preview" class="imagem-pro-image-preview"></div>
</div>
<div class="imagem-pro-select-wrapper" style="width: 100% !important;">
<select id="converter-format-select" class="imagem-pro-input">
<option value="jpeg">JPEG</option>
<option value="png">PNG</option>
<option value="ico">ICO</option>
<option value="base64">Base64</option>
</select>
<svg class="imagem-pro-select-arrow" viewBox="0 0 10 6" width="10" height="6" fill="none">
<path d="M1 1L5 5L9 1" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</div>
<button id="converter-convert-btn" class="imagem-pro-btn success" style="width: 100% !important;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 5L3 10L8 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M16 5L21 10L16 15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M14 3L10 17" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
${__('convert')}
</button>
</div>
</div>
</div>
<div class="imagem-pro-settings-tab-content" id="tab-search">
<div class="imagem-pro-settings-section">
<div class="imagem-pro-search-container">
<div class="imagem-pro-search-form">
<div class="imagem-pro-search-input-wrapper">
<input type="text" id="imagem-pro-search-input" class="imagem-pro-search-input" placeholder="${__('searchPlaceholder')}">
<button id="imagem-pro-search-button" class="imagem-pro-search-button">
<svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11 19C15.4183 19 19 15.4183 19 11C19 6.58172 15.4183 3 11 3C6.58172 3 3 6.58172 3 11C3 15.4183 6.58172 19 11 19Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M21 21L16.65 16.65" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
</button>
</div>
</div>
<div class="imagem-pro-search-options">
<div class="imagem-pro-search-option">
<input type="radio" id="search-google" name="search-site" value="googlelens" checked>
<label for="search-google">Google</label>
</div>
<div class="imagem-pro-search-option">
<input type="radio" id="search-yandex" name="search-site" value="yandex">
<label for="search-yandex">Yandex</label>
<div class="star-badge">★</div>
</div>
<div class="imagem-pro-search-option">
<input type="radio" id="search-mavink" name="search-site" value="mavink">
<label for="search-mavink">Mavink</label>
<div class="star-badge">★</div>
</div>
<div class="imagem-pro-search-option">
<input type="radio" id="search-pinterest" name="search-site" value="pinterest">
<label for="search-pinterest">Pinterest</label>
</div>
<div class="imagem-pro-search-option">
<input type="radio" id="search-baidu" name="search-site" value="baidu">
<label for="search-baidu">Baidu</label>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="imagem-pro-footer">
<div class="imagem-pro-footer-left">
<button id="settings-reset-btn" class="imagem-pro-btn neutral">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 4V10H7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M23 20V14H17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M20.49 9C19.9828 7.56678 19.1209 6.2854 17.9845 5.27542C16.8482 4.26543 15.4745 3.55976 13.9917 3.22426C12.5089 2.88875 10.9652 2.93434 9.50481 3.35677C8.04437 3.77921 6.71475 4.56471 5.64 5.64L1 10M23 14L18.36 18.36C17.2853 19.4353 15.9556 20.2208 14.4952 20.6432C13.0348 21.0657 11.4911 21.1112 10.0083 20.7757C8.52547 20.4402 7.1518 19.7346 6.01547 18.7246C4.87913 17.7146 4.01717 16.4332 3.51 15" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
${__('reset')}
</button>
<button id="settings-save-btn" class="imagem-pro-btn success">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M19 21H5C4.46957 21 3.96086 20.7893 3.58579 20.4142C3.21071 20.0391 3 19.5304 3 19V5C3 4.46957 3.21071 3.96086 3.58579 3.58579C3.96086 3.21071 4.46957 3 5 3H16L21 8V19C21 19.5304 20.7893 20.0391 20.4142 20.4142C20.0391 20.7893 19.5304 21 19 21Z" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M17 21V13H7V21" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M7 3V8H15" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
${__('save')}
</button>
</div>
<button id="support-dev-btn" class="imagem-pro-btn support">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M18 8H19C20.0609 8 21.0783 8.42143 21.8284 9.17157C22.5786 9.92172 23 10.9391 23 12C23 13.0609 22.5786 14.0783 21.8284 14.8284C21.0783 15.5786 20.0609 16 19 16H18" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 8H5C3.93913 8 2.92172 8.42143 2.17157 9.17157C1.42143 9.92172 1 10.9391 1 12C1 13.0609 1.42143 14.0783 2.17157 14.8284C2.92172 15.5786 3.93913 16 5 16H6" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M6 12H18" stroke="white" stroke-width="2" stroke-linecap="roundO" stroke-linejoin="round"/>
<path d="M12 2V6" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
<path d="M12 18V22" stroke="white" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>
${__('supportDev')}
</button>
</div>
`);
document.body.appendChild(modal);
const settingsStyles = document.createElement('style');
settingsStyles.textContent = `
#imagem-pro-settings-modal,
#imagem-pro-settings-modal * {
box-sizing: border-box !important;
font-family: 'Kiwi Maru' !important;
}
#imagem-pro-settings-modal {
position: fixed !important;
top: 50% !important;
left: 50% !important;
transform: translate(-50%, -50%) !important;
width: 500px !important;
max-width: 90vw !important;
max-height: 90vh !important;
background-color: rgba(28, 28, 32, 0.98) !important;
border-radius: 16px !important;
z-index: 1000000 !important;
box-shadow: 0 5px 30px rgba(0, 0, 0, 0.8), 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
display: none !important;
flex-direction: column !important;
overflow: hidden !important;
color: white !important;
backdrop-filter: blur(10px) !important;
opacity: 0 !important;
transition: opacity 0.3s ease, transform 0.3s ease !important;
}
#imagem-pro-settings-modal.show {
display: flex !important;
opacity: 1 !important;
}
#imagem-pro-settings-header {
padding: 20px !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
position: relative !important;
}
#imagem-pro-settings-title {
font-size: 22px !important;
font-weight: 500 !important;
color: white !important;
margin: 0 !important;
text-align: center !important;
}
#imagem-pro-settings-close {
position: absolute !important;
right: 16px !important;
top: 50% !important;
transform: translateY(-50%) !important;
background: rgba(255, 255, 255, 0.1) !important;
border: none !important;
color: #ccc !important;
width: 28px !important;
height: 28px !important;
border-radius: 50% !important;
cursor: pointer !important;
padding: 0 !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
transition: all 0.2s ease !important;
}
#imagem-pro-settings-close:hover {
background: rgba(255, 255, 255, 0.2) !important;
color: white !important;
}
#imagem-pro-settings-tabs {
display: flex !important;
border-bottom: 1px solid rgba(255, 255, 255, 0.1) !important;
background: rgba(20, 20, 24, 0.5) !important;
}
.imagem-pro-tab {
flex: 1 !important;
padding: 12px 5px !important;
background: none !important;
border: none !important;
color: rgba(255, 255, 255, 0.6) !important;
cursor: pointer !important;
transition: all 0.2s ease !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 5px !important;
font-size: 14px !important;
position: relative !important;
}
.imagem-pro-tab::after {
content: "" !important;
position: absolute !important;
bottom: -1px !important;
left: 50% !important;
width: 0 !important;
height: 2px !important;
background: #4361ee !important;
transition: all 0.3s ease !important;
transform: translateX(-50%) !important;
}
.imagem-pro-tab.active {
color: rgba(255, 255, 255, 1) !important;
}
.imagem-pro-tab.active::after {
width: 80% !important;
}
.imagem-pro-tab:hover {
color: rgba(255, 255, 255, 0.9) !important;
background: rgba(255, 255, 255, 0.05) !important;
}
.imagem-pro-tab svg {
opacity: 0.7 !important;
transition: all 0.2s ease !important;
}
.imagem-pro-tab.active svg {
opacity: 1 !important;
}
#imagem-pro-settings-content {
flex: 1 !important;
overflow-y: auto !important;
padding: 0 !important;
}
.imagem-pro-settings-tab-content {
display: none !important;
padding: 20px !important;
animation: fadeIn 0.3s ease !important;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.imagem-pro-settings-tab-content.active {
display: block !important;
}
.imagem-pro-section-title {
font-size: 16px !important;
margin: 0 0 15px 0 !important;
color: rgba(255, 255, 255, 0.9) !important;
font-weight: 500 !important;
position: relative !important;
padding-bottom: 10px !important;
}
.imagem-pro-section-title::after {
content: "" !important;
position: absolute !important;
bottom: 0 !important;
left: 0 !important;
width: 40px !important;
height: 2px !important;
background: #4361ee !important;
}
.imagem-pro-toggle-group {
display: flex !important;
flex-direction: column !important;
gap: 15px !important;
margin-bottom: 25px !important;
}
.imagem-pro-settings-option {
display: flex !important;
align-items: center !important;
justify-content: space-between !important;
background: rgba(255, 255, 255, 0.05) !important;
padding: 12px 16px !important;
border-radius: 8px !important;
transition: all 0.2s ease !important;
text-align: center !important;
}
.imagem-pro-settings-option:hover {
background: rgba(255, 255, 255, 0.08) !important;
}
.imagem-pro-settings-option-label {
flex-grow: 0 !important;
font-size: 14px !important;
color: rgba(255, 255, 255, 0.9) !important;
text-align: center !important;
}
.imagem-pro-settings-toggle {
position: relative !important;
display: inline-block !important;
width: 44px !important;
height: 24px !important;
}
.imagem-pro-settings-toggle input {
opacity: 0 !important;
width: 0 !important;
height: 0 !important;
}
.imagem-pro-settings-toggle-slider {
position: absolute !important;
cursor: pointer !important;
top: 0 !important;
left: 0 !important;
right: 0 !important;
bottom: 0 !important;
background-color: rgba(255, 255, 255, 0.2) !important;
transition: .3s !important;
border-radius: 24px !important;
}
.imagem-pro-settings-toggle-slider:before {
position: absolute !important;
content: "" !important;
height: 18px !important;
width: 18px !important;
left: 3px !important;
bottom: 3px !important;
background-color: white !important;
transition: .3s !important;
border-radius: 50% !important;
}
.imagem-pro-settings-toggle input:checked + .imagem-pro-settings-toggle-slider {
background-color: #4361ee !important;
}
.imagem-pro-settings-toggle input:checked + .imagem-pro-settings-toggle-slider:before {
transform: translateX(20px) !important;
}
.imagem-pro-input-group {
display: grid !important;
grid-template-columns: 1fr !important;
gap: 15px !important;
}
.imagem-pro-input-field {
display: flex !important;
flex-direction: column !important;
gap: 8px !important;
}
.imagem-pro-input-field label {
font-size: 13px !important;
color:rgb(255, 255, 255) !important;
margin-left: 15px !important;
width: 100% !important;
display: block !important;
}
.imagem-pro-input {
background-color: rgba(255, 255, 255, 0.08) !important;
color: white !important;
padding: 12px 15px !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 8px !important;
font-family: 'Kiwi Maru' !important;
font-size: 14px !important;
width: 100% !important;
transition: all 0.2s ease !important;
text-align: center !important;
}
.imagem-pro-input:focus {
border-color: #4361ee !important;
outline: none !important;
box-shadow: 0 0 0 2px rgba(67, 97, 238, 0.25) !important;
}
.imagem-pro-select-wrapper {
position: relative !important;
width: 100% !important;
}
.imagem-pro-select-wrapper select {
appearance: none !important;
-webkit-appearance: none !important;
text-align: center !important;
text-align-last: center !important;
}
.imagem-pro-select-arrow {
position: absolute !important;
right: 15px !important;
top: 50% !important;
transform: translateY(-50%) !important;
pointer-events: none !important;
color: rgba(255, 255, 255, 0.7) !important;
}
@-moz-document url-prefix() {
.imagem-pro-select-wrapper select {
text-align: center !important;
}
}
.imagem-pro-converter-container {
display: flex !important;
flex-direction: column !important;
gap: 20px !important;
align-items: center !important;
}
.imagem-pro-file-upload {
width: 100% !important;
text-align: center !important;
}
.imagem-pro-filename {
margin-top: 10px !important;
font-size: 13px !important;
color: rgba(255, 255, 255, 0.6) !important;
max-width: 100% !important;
overflow: hidden !important;
text-overflow: ellipsis !important;
white-space: nowrap !important;
text-align: center !important;
}
.imagem-pro-converter-options {
display: flex !important;
width: 100% !important;
gap: 15px !important;
}
.imagem-pro-converter-options .imagem-pro-select-wrapper {
flex: 1 !important;
}
.imagem-pro-preview-container {
width: 100% !important;
height: 120px !important;
background: rgba(0, 0, 0, 0.2) !important;
border-radius: 8px !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
overflow: hidden !important;
border: 1px dashed rgba(255, 255, 255, 0.2) !important;
}
.imagem-pro-image-preview {
max-width: 100% !important;
max-height: 100% !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
color: rgba(255, 255, 255, 0.5) !important;
font-size: 14px !important;
text-align: center !important;
}
.imagem-pro-image-preview img {
max-width: 100% !important;
max-height: 100% !important;
object-fit: contain !important;
}
.imagem-pro-search-container {
width: 100% !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
gap: 20px !important;
}
.imagem-pro-search-form {
width: 100% !important;
}
.imagem-pro-search-input-wrapper {
position: relative !important;
width: 100% !important;
}
.imagem-pro-search-input {
background-color: rgba(255, 255, 255, 0.08) !important;
color: white !important;
padding: 14px 20px !important;
padding-right: 60px !important;
border: 1px solid rgba(255, 255, 255, 0.1) !important;
border-radius: 30px !important;
font-family: 'Kiwi Maru' !important;
font-size: 14px !important;
width: 100% !important;
transition: all 0.3s ease !important;
}
.imagem-pro-search-input:focus {
border-color: #4361ee !important;
outline: none !important;
box-shadow: 0 0 0 2px rgba(67, 97, 238, 0.25) !important;
}
.imagem-pro-search-button {
position: absolute !important;
right: 5px !important;
top: 50% !important;
transform: translateY(-50%) !important;
background: #4361ee !important;
border: none !important;
width: 44px !important;
height: 44px !important;
border-radius: 50% !important;
cursor: pointer !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
transition: all 0.2s ease !important;
}
.imagem-pro-search-button:hover {
background: #3350dc !important;
transform: translateY(-50%) scale(1.05) !important;
}
.imagem-pro-search-help {
font-size: 12px !important;
color: rgba(255, 255, 255, 0.5) !important;
text-align: center !important;
margin-top: 15px !important;
}
.imagem-pro-footer {
display: flex !important;
justify-content: space-between !important;
padding: 15px 20px !important;
border-top: 1px solid rgba(255, 255, 255, 0.1) !important;
background: rgba(20, 20, 24, 0.5) !important;
}
.imagem-pro-footer-left {
display: flex !important;
gap: 10px !important;
}
.imagem-pro-btn {
padding: 10px 16px !important;
border-radius: 8px !important;
font-family: 'Kiwi Maru' !important;
font-size: 13px !important;
cursor: pointer !important;
border: none !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
gap: 8px !important;
transition: all 0.2s ease !important;
color: white !important;
background: rgba(255, 255, 255, 0.1) !important;
}
.imagem-pro-btn:hover {
transform: translateY(-1px) !important;
filter: brightness(1.1) !important;
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3) !important;
}
.imagem-pro-btn:active {
transform: translateY(0) !important;
}
.imagem-pro-btn.primary {
background: #4361ee !important;
}
.imagem-pro-btn.success {
background: #2ecc71 !important;
}
.imagem-pro-btn.neutral {
background: #607d8b !important;
}
.imagem-pro-btn.support {
background: linear-gradient(45deg, #ff9a00, #ff6b6b) !important;
}
.imagem-pro-alert-overlay {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0, 0, 0, 0.7) !important;
backdrop-filter: blur(5px) !important;
display: flex !important;
align-items: center !important;
justify-content: center !important;
z-index: 1000001 !important;
animation: fadeIn 0.2s ease !important;
}
.imagem-pro-alert-box {
background-color: rgba(28, 28, 32, 0.95) !important;
padding: 25px !important;
border-radius: 16px !important;
max-width: 450px !important;
width: 90% !important;
text-align: center !important;
color: white !important;
font-family: 'Kiwi Maru' !important;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
animation: scaleIn 0.3s ease !important;
}
@keyframes scaleIn {
from { opacity: 0; transform: scale(0.9); }
to { opacity: 1; transform: scale(1); }
}
.imagem-pro-alert-title {
font-size: 18px !important;
font-weight: 500 !important;
margin-bottom: 15px !important;
color: #ffeb3b !important;
}
.imagem-pro-alert-content {
margin-bottom: 25px !important;
line-height: 1.6 !important;
font-size: 14px !important;
}
.imagem-pro-alert-link {
color: #4361ee !important;
text-decoration: none !important;
cursor: pointer !important;
position: relative !important;
display: inline-block !important;
margin: 5px 0 !important;
font-weight: 500 !important;
}
.imagem-pro-alert-link::after {
content: '' !important;
position: absolute !important;
width: 100% !important;
height: 1px !important;
bottom: -2px !important;
left: 0 !important;
background-color: #4361ee !important;
transform: scaleX(0) !important;
transform-origin: bottom right !important;
transition: transform 0.3s ease-out !important;
}
.imagem-pro-alert-link:hover::after {
transform: scaleX(1) !important;
transform-origin: bottom left !important;
}
.imagem-pro-alert-btn {
background-color: #4361ee !important;
color: white !important;
border: none !important;
padding: 10px 20px !important;
border-radius: 8px !important;
cursor: pointer !important;
font-family: 'Kiwi Maru' !important;
font-size: 14px !important;
transition: all 0.2s ease !important;
}
.imagem-pro-alert-btn:hover {
background-color: #3350dc !important;
transform: translateY(-2px) !important;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2) !important;
}
.imagem-pro-loading-overlay {
position: fixed !important;
top: 0 !important;
left: 0 !important;
width: 100% !important;
height: 100% !important;
background-color: rgba(0, 0, 0, 0.7) !important;
backdrop-filter: blur(5px) !important;
display: flex !important;
flex-direction: column !important;
align-items: center !important;
justify-content: center !important;
z-index: 1000002 !important;
animation: fadeIn 0.3s ease !important;
}
.imagem-pro-loading-container {
background-color: rgba(28, 28, 32, 0.95) !important;
padding: 25px !important;
border-radius: 16px !important;
width: 300px !important;
text-align: center !important;
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.1) !important;
}
.imagem-pro-loading-title {
color: white !important;
font-size: 18px !important;
margin: 0 0 20px 0 !important;
font-weight: 500 !important;
font-family: 'Kiwi Maru' !important;
}
.imagem-pro-progress-bar {
width: 100% !important;
height: 8px !important;
background-color: rgba(255, 255, 255, 0.1) !important;
border-radius: 4px !important;
overflow: hidden !important;
margin-bottom: 15px !important;
}
.imagem-pro-progress-fill {
height: 100% !important;
background: linear-gradient(90deg, #4361ee, #3a0ca3) !important;
width: 0% !important;
border-radius: 4px !important;
transition: width 0.3s ease !important;
background-size: 200% 100% !important;
animation: gradientMove 2s linear infinite !important;
}
@keyframes gradientMove {
0% { background-position: 0% 0%; }
100% { background-position: 200% 0%; }
}
.imagem-pro-loading-text {
color: rgba(255, 255, 255, 0.8) !important;
font-size: 14px !important;
margin: 0 !important;
font-family: 'Kiwi Maru' !important;
}
.star-badge {
position: absolute;
top: -5px;
right: -5px;
font-size: 14px;
color: gold;
text-shadow: 0 0 5px rgba(255, 215, 0, 0.7);
animation: starPulse 1.5s infinite alternate ease-in-out;
z-index: 10;
pointer-events: none;
transform-origin: center;
}
@keyframes starPulse {
0% {
transform: scale(0.9) rotate(0deg);
opacity: 0.8;
}
50% {
transform: scale(1.1) rotate(5deg);
opacity: 1;
text-shadow: 0 0 10px rgba(255, 215, 0, 1), 0 0 20px rgba(255, 215, 0, 0.5);
}
100% {
transform: scale(0.95) rotate(-3deg);
opacity: 0.9;
}
}
.imagem-pro-search-option {
position: relative !important;
overflow: visible !important;
}
#search-yandex:checked ~ label,
#search-mavink:checked ~ label {
color: #ffcc00 !important;
text-shadow: 0 0 5px rgba(255, 204, 0, 0.3) !important;
}
#search-yandex:checked ~ .star-badge,
#search-mavink:checked ~ .star-badge {
animation: starPulse 2.2s infinite alternate ease-in-out !important;
color: #ffcc00 !important;
text-shadow: 0 0 8px rgba(255, 204, 0, 0.8) !important;
}
`;
document.head.appendChild(settingsStyles);
setTimeout(() => {
modal.classList.add('show');
}, 10);
const tabs = document.querySelectorAll('.imagem-pro-tab');
tabs.forEach(tab => {
tab.addEventListener('click', function() {
const tabName = this.getAttribute('data-tab');
document.querySelectorAll('.imagem-pro-tab').forEach(t => t.classList.remove('active'));
document.querySelectorAll('.imagem-pro-settings-tab-content').forEach(c => c.classList.remove('active'));
this.classList.add('active');
document.getElementById(`tab-${tabName}`).classList.add('active');
});
});
document.getElementById('imagem-pro-settings-close').addEventListener('click', () => {
modal.classList.remove('show');
setTimeout(() => {
}, 300);
});
setupSettingsSaveButton();
document.getElementById('settings-zip-download').addEventListener('change', function() {
if (!this.checked) {
showModernAlert({
title: __('attention'),
message: __('individualDownloadMsg'),
buttonText: __('ok')
});
}
});
document.getElementById('settings-reset-btn').addEventListener('click', function() {
document.getElementById('settings-zip-download').checked = defaultSettings.zipDownload;
document.getElementById('settings-gif-convert').checked = defaultSettings.convertGifToMp4;
document.getElementById('settings-auto-convert').value = defaultSettings.autoConvertFormat;
document.getElementById('settings-search-engine').value = defaultSettings.searchEngine;
document.getElementById('settings-hotkey').value = defaultSettings.hotkeyCombo;
document.getElementById('settings-limit-px').value = defaultSettings.limitPx;
document.getElementById('settings-pixel-priority').value = defaultSettings.pixelPriority;
});
document.getElementById('support-dev-btn').addEventListener('click', function() {
window.open('https://ko-fi.com/l4pisd4silv4#', '_blank');
});
document.getElementById('converter-import-btn').addEventListener('click', function() {
document.getElementById('converter-file-input').click();
});
document.getElementById('converter-file-input').addEventListener('change', function() {
if (!this.files || !this.files[0]) return;
const file = this.files[0];
let filenameEl = document.getElementById('converter-filename');
if (!filenameEl) {
filenameEl = document.createElement('div');
filenameEl.id = 'converter-filename';
filenameEl.className = 'imagem-pro-filename';
filenameEl.style.textAlign = 'center';
filenameEl.style.marginTop = '10px';
document.querySelector('.imagem-pro-file-upload').appendChild(filenameEl);
}
filenameEl.textContent = __('filename', file.name);
filenameEl.style.color = 'rgba(255, 255, 255, 0.9)';
const reader = new FileReader();
reader.onload = function(e) {
ImagemPro.imageToConvert = {
name: file.name,
data: e.target.result
};
const previewEl = document.getElementById('converter-preview');
setInnerHTML(previewEl, '');
const img = document.createElement('img');
img.src = URL.createObjectURL(file);
img.onload = function() {
URL.revokeObjectURL(this.src);
};
previewEl.appendChild(img);
};
reader.readAsArrayBuffer(file);
});
document.getElementById('converter-convert-btn').addEventListener('click', function() {
if (!ImagemPro.imageToConvert) {
showModernAlert({
title: __('noImageSelected'),
message: __('noImageConverterMsg'),
buttonText: __('ok')
});
return;
}
const targetFormat = document.getElementById('converter-format-select').value;
const originalName = ImagemPro.imageToConvert.name.split('.')[0];
const loadingOverlay = document.createElement('div');
loadingOverlay.className = 'imagem-pro-loading-overlay';
const loadingContainer = document.createElement('div');
loadingContainer.className = 'imagem-pro-loading-container';
const loadingTitle = document.createElement('h3');
loadingTitle.className = 'imagem-pro-loading-title';
loadingTitle.textContent = __('converting');
const progressBar = document.createElement('div');
progressBar.className = 'imagem-pro-progress-bar';
const progressFill = document.createElement('div');
progressFill.className = 'imagem-pro-progress-fill';
progressBar.appendChild(progressFill);
const loadingText = document.createElement('p');
loadingText.textContent = __('preparing');
loadingContainer.appendChild(loadingTitle);
loadingContainer.appendChild(progressBar);
loadingContainer.appendChild(loadingText);
loadingOverlay.appendChild(loadingContainer);
document.body.appendChild(loadingOverlay);
let progress = 0;
const progressInterval = setInterval(() => {
progress += 5;
progressFill.style.width = Math.min(progress, 95) + '%';
if (progress < 30) {
loadingText.textContent = __('loadingImage');
} else if (progress < 70) {
loadingText.textContent = __('convertingTo', targetFormat.toUpperCase());
} else {
loadingText.textContent = __('finishing');
}
if (progress >= 100) {
clearInterval(progressInterval);
}
}, 100);
const blob = new Blob([ImagemPro.imageToConvert.data]);
convertImageAdvanced(blob, targetFormat, (convertedBlob, dataUrl) => {
clearInterval(progressInterval);
progressFill.style.width = '100%';
loadingText.textContent = __('downloadStarted');
setTimeout(() => {
document.body.removeChild(loadingOverlay);
if (targetFormat === 'base64') {
const textBlob = new Blob([dataUrl], {type: 'text/plain'});
doActualDownload(URL.createObjectURL(textBlob), `${originalName}.txt`, () => {
URL.revokeObjectURL(textBlob);
}, true);
} else {
doActualDownload(URL.createObjectURL(convertedBlob), `${originalName}.${targetFormat}`, () => {
URL.revokeObjectURL(convertedBlob);
}, true);
}
showModernAlert({
title: __('conversionComplete'),
message: __('conversionSuccess', targetFormat.toUpperCase()),
buttonText: __('ok')
});
}, 1000);
});
});
document.getElementById('settings-search-engine').addEventListener('change', function() {
settings.searchEngine = this.value;
saveSettings(settings);
});
document.getElementById('imagem-pro-search-button').addEventListener('click', function() {
const searchInput = document.getElementById('imagem-pro-search-input');
const searchTerm = searchInput.value.trim();
if (searchTerm) {
const selectedSearch = document.querySelector('input[name="search-site"]:checked').value;
let searchUrl;
switch(selectedSearch) {
case 'yandex':
searchUrl = `https://yandex.com/images/search?text=${encodeURIComponent(searchTerm)}`;
break;
case 'mavink':
searchUrl = `https://mavink.com/explore.php?q=${encodeURIComponent(searchTerm)}`;
break;
case 'pinterest':
searchUrl = `https://www.pinterest.com/search/pins/?q=${encodeURIComponent(searchTerm)}`;
break;
case 'baidu':
searchUrl = `https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=&st=-1&fm=index&fr=&hs=0&xthttps=111110&sf=1&fmq=&pv=&ic=0&nc=1&z=&se=&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=${encodeURIComponent(searchTerm)}`;
break;
case 'googlelens':
default:
searchUrl = `https://www.google.com/search?q=${encodeURIComponent(searchTerm)}&tbm=isch`;
break;
}
window.open(searchUrl, '_blank');
} else {
showModernAlert({
title: __('emptyField'),
message: __('pleaseEnterSearchTerm'),
buttonText: __('ok')
});
}
});
document.getElementById('imagem-pro-search-input').addEventListener('keydown', function(e) {
if (e.key === 'Enter') {
e.preventDefault();
document.getElementById('imagem-pro-search-button').click();
}
});
function showModernAlert(options) {
const overlay = document.createElement('div');
overlay.className = 'imagem-pro-alert-overlay';
const alertBox = document.createElement('div');
alertBox.className = 'imagem-pro-alert-box';
const title = document.createElement('div');
title.className = 'imagem-pro-alert-title';
title.textContent = options.title || __('warning');
const content = document.createElement('div');
content.className = 'imagem-pro-alert-content';
if (options.message) {
const paragraphs = options.message.split('\n');
paragraphs.forEach((paragraph, index) => {
const p = document.createElement('p');
p.textContent = paragraph;
content.appendChild(p);
if (index < paragraphs.length - 1) {
p.style.marginBottom = '10px';
}
});
}
if (options.link) {
const link = document.createElement('a');
link.className = 'imagem-pro-alert-link';
link.textContent = options.linkText || 'Clique aqui';
link.href = options.link;
link.target = '_blank';
const linkContainer = document.createElement('p');
linkContainer.appendChild(link);
content.appendChild(linkContainer);
}
const button = document.createElement('button');
button.className = 'imagem-pro-alert-btn';
button.textContent = options.buttonText || 'OK';
button.addEventListener('click', function() {
document.body.removeChild(overlay);
if (options.onClose) options.onClose();
});
alertBox.appendChild(title);
alertBox.appendChild(content);
alertBox.appendChild(button);
overlay.appendChild(alertBox);
document.body.appendChild(overlay);
}
setTimeout(() => {
enhanceHotkeyInput();
}, 100);
}
function enhanceHotkeyInput() {
const hotkeyInput = document.getElementById('settings-hotkey');
if (!hotkeyInput) return;
hotkeyInput.readOnly = true;
hotkeyInput.classList.add('hotkey-capture-button');
hotkeyInput.setAttribute('placeholder', __('pressKeys'));
function formatHotkey(ctrl, alt, shift, key) {
const parts = [];
if (ctrl) parts.push('Ctrl');
if (alt) parts.push('Alt');
if (shift) parts.push('Shift');
if (key && !['control', 'alt', 'shift', 'meta'].includes(key)) parts.push(key.toUpperCase());
return parts.join(' + ');
}
function formatStoredHotkey(ctrl, alt, shift, key) {
const parts = [];
if (ctrl) parts.push('ctrl');
if (alt) parts.push('alt');
if (shift) parts.push('shift');
if (key) parts.push(key.toLowerCase());
return parts.join('+');
}
hotkeyInput.addEventListener('keydown', function(e) {
e.preventDefault();
e.stopPropagation();
const ignoreKeys = ['Tab', 'Enter', 'Escape', 'CapsLock'];
if (ignoreKeys.includes(e.key)) {
return;
}
let key = e.key.toLowerCase();
if (key === ' ') key = 'space';
if (key === 'arrowup') key = 'up';
if (key === 'arrowdown') key = 'down';
if (key === 'arrowleft') key = 'left';
if (key === 'arrowright') key = 'right';
const isFunctionKey = key.startsWith('f') && !isNaN(key.substring(1)) && parseInt(key.substring(1)) <= 12;
if (!e.ctrlKey && !e.altKey && !e.shiftKey && !isFunctionKey) {
this.classList.add('hotkey-error');
setTimeout(() => {
this.classList.remove('hotkey-error');
}, 1000);
return;
}
if (['control', 'alt', 'shift', 'meta'].includes(key)) {
return;
}
const hotkey = formatHotkey(e.ctrlKey, e.altKey, e.shiftKey, key);
this.value = hotkey;
const storedHotkey = formatStoredHotkey(e.ctrlKey, e.altKey, e.shiftKey, key);
this.dataset.storedValue = storedHotkey;
this.setAttribute('data-value', storedHotkey);
this.classList.add('hotkey-success');
setTimeout(() => {
this.classList.remove('hotkey-success');
}, 1000);
});
hotkeyInput.addEventListener('keypress', function(e) {
e.preventDefault();
});
hotkeyInput.addEventListener('paste', function(e) {
e.preventDefault();
});
hotkeyInput.addEventListener('focus', function() {
this.classList.add('hotkey-capture-mode');
this.value = '';
this.setAttribute('placeholder', __('pressKeys'));
});
hotkeyInput.addEventListener('blur', function() {
this.classList.remove('hotkey-capture-mode');
if (!this.value) {
this.value = this.dataset.originalValue || 'shift+s';
}
this.setAttribute('placeholder', __('clickToSetHotkey'));
});
hotkeyInput.dataset.originalValue = hotkeyInput.value;
const style = document.createElement('style');
style.textContent = `
.hotkey-capture-button {
text-align: center !important;
cursor: pointer !important;
background-color: rgba(38, 50, 56, 0.8) !important;
border: 1px solid rgba(255, 255, 255, 0.2) !important;
color: white !important;
font-weight: 500 !important;
letter-spacing: 0.5px !important;
}
.hotkey-capture-mode {
background-color: rgba(33, 150, 243, 0.15) !important;
border: 1px solid #2196f3 !important;
box-shadow: 0 0 5px rgba(33, 150, 243, 0.3) !important;
color: #90CAF9 !important;
}
.hotkey-success {
background-color: rgba(76, 175, 80, 0.15) !important;
border-color: #4CAF50 !important;
color: #A5D6A7 !important;
transition: all 0.3s ease !important;
}
.hotkey-error {
background-color: rgba(244, 67, 54, 0.15) !important;
border-color: #F44336 !important;
color: #EF9A9A !important;
animation: shake 0.4s linear !important;
}
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-5px); }
40%, 80% { transform: translateX(5px); }
}
.imagem-pro-input-field label[for="settings-hotkey"]::after {
content: "${__('clickAndPress')}" !important;
font-size: 11px !important;
color: rgba(255, 255, 255, 0.6) !important;
font-style: italic !important;
}
`;
document.head.appendChild(style);
document.getElementById('settings-save-btn').addEventListener('click', function() {
const hotkeyInput = document.getElementById('settings-hotkey');
if (hotkeyInput && hotkeyInput.dataset.storedValue) {
hotkeyInput.value = hotkeyInput.dataset.storedValue;
}
}, { once: true });
}
function setupHotkey() {
const settings = loadSettings();
const hotkeyCombo = settings.hotkeyCombo || 'shift+s';
if (ImagemPro.hotkeyListener) {
document.removeEventListener('keydown', ImagemPro.hotkeyListener);
}
ImagemPro.hotkeyListener = function(e) {
try {
const parts = hotkeyCombo.toLowerCase().split('+');
const key = parts[parts.length - 1];
const needsCtrl = parts.includes('ctrl') || parts.includes('control');
const needsAlt = parts.includes('alt');
const needsShift = parts.includes('shift');
const ctrlMatch = needsCtrl === (e.ctrlKey || e.metaKey);
const altMatch = needsAlt === e.altKey;
const shiftMatch = needsShift === e.shiftKey;
let currentKey = e.key.toLowerCase();
if (currentKey === ' ') currentKey = 'space';
if (currentKey === 'arrowup') currentKey = 'up';
if (currentKey === 'arrowdown') currentKey = 'down';
if (currentKey === 'arrowleft') currentKey = 'left';
if (currentKey === 'arrowright') currentKey = 'right';
if (ctrlMatch && altMatch && shiftMatch && currentKey === key) {
e.preventDefault();
togglePanel();
debug(`Atalho ativado: ${hotkeyCombo}`);
}
} catch (err) {
debug('Erro ao processar atalho: ' + err.message, true);
}
};
document.addEventListener('keydown', ImagemPro.hotkeyListener);
debug(`Atalho de teclado configurado: ${hotkeyCombo}`);
}
function showLanguageMenu() {
try {
const existingOverlay = document.querySelector('.imagem-pro-language-overlay');
if (existingOverlay) {
existingOverlay.remove();
return;
}
const overlay = document.createElement('div');
overlay.className = 'imagem-pro-language-overlay';
const menuContainer = document.createElement('div');
menuContainer.id = 'imagem-pro-language-menu';
menuContainer.className = 'imagem-pro-language-menu';
const languageList = document.createElement('div');
languageList.className = 'imagem-pro-language-list';
const languages = [
{ code: 'pt-br', name: 'Português Brasileiro' },
{ code: 'en', name: 'English' },
{ code: 'es', name: 'Español' },
{ code: 'zh', name: '中文' },
{ code: 'fr', name: 'Français' },
{ code: 'ar', name: 'العربية' },
{ code: 'hi', name: 'हिन्दी' },
{ code: 'ja', name: '日本語' },
{ code: 'ru', name: 'Русский' },
{ code: 'bn', name: 'বাংলা' },
{ code: 'ur', name: 'اردو' }
];
const currentLang = GM_getValue('imagemProLanguage', 'pt-br');
languages.forEach(lang => {
const langButton = document.createElement('button');
langButton.className = 'imagem-pro-language-button';
if (lang.code === currentLang) {
langButton.classList.add('active');
}
langButton.setAttribute('data-lang', lang.code);
const nameSpan = document.createElement('span');
nameSpan.className = 'language-name';
nameSpan.textContent = lang.name;
langButton.appendChild(nameSpan);
langButton.addEventListener('click', function() {
changeLanguage(lang.code);
overlay.remove();
});
languageList.appendChild(langButton);
});
menuContainer.appendChild(languageList);
overlay.appendChild(menuContainer);
document.body.appendChild(overlay);
setTimeout(() => {
overlay.classList.add('visible');
menuContainer.classList.add('visible');
}, 50);
overlay.addEventListener('click', function(e) {
if (e.target === overlay) {
overlay.classList.remove('visible');
menuContainer.classList.remove('visible');
setTimeout(() => {
overlay.remove();
}, 300);
}
});
} catch (error) {
console.error('Erro ao mostrar menu de idiomas:', error);
}
}
function criarBanner() {
const overlay = document.createElement('div');
const banner = document.createElement('div');
const signature = document.createElement('div');
overlay.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
backdrop-filter: blur(5px) brightness(0.8);
-webkit-backdrop-filter: blur(5px) brightness(0.8);
background-color: rgba(0, 0, 0, 0.4);
z-index: 9998;
transition: all 0.5s ease;
opacity: 0;
`;
banner.style.cssText = `
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%) scale(0.75);
width: 1948px;
height: 940px;
background-image: url(https://i.imgur.com/qn1xxfD.png);
background-size: cover;
background-position: center;
z-index: 9999;
opacity: 0;
transition: all 0.8s cubic-bezier(0.4, 0, 0.2, 1);
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
will-change: transform, opacity;
`;
signature.textContent = "by: L4pisD4Silv4";
signature.style.cssText = `
position: fixed !important;
bottom: 70px !important;
left: 50% !important;
transform: translateX(-50%) !important;
color: rgba(255, 255, 255, 0.7) !important;
font-family: 'Consolas', 'Monaco', 'Courier New', monospace !important;
font-size: 12px !important;
font-weight: 300 !important;
letter-spacing: 2px !important;
z-index: 10000 !important;
opacity: 0;
transition: opacity 0.8s ease !important;
text-shadow: 0 1px 4px rgba(0, 157, 255, 0.5) !important;
text-transform: lowercase !important;
`;
document.body.appendChild(overlay);
document.body.appendChild(banner);
document.body.appendChild(signature);
setTimeout(() => {
overlay.style.opacity = '1';
banner.style.opacity = '1';
signature.style.opacity = '1';
}, 50);
function fecharBanner() {
banner.style.opacity = '0';
banner.style.transform = 'translate(-50%, -50%) scale(0.6)';
overlay.style.opacity = '0';
signature.style.opacity = '0';
setTimeout(() => {
banner.remove();
overlay.remove();
signature.remove();
}, 800);
}
function criarBotao(src, x, y, w, h, link) {
const btn = document.createElement('div');
btn.style.cssText = `
position: absolute;
left: ${x}px;
top: ${y}px;
width: ${w}px;
height: ${h}px;
background-image: url(${src});
background-size: contain;
background-position: center;
background-repeat: no-repeat;
cursor: pointer;
transition: transform 0.3s ease;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
will-change: transform;
`;
btn.addEventListener('mouseenter', () => {
btn.style.transform = 'scale(1.1)';
});
btn.addEventListener('mouseleave', () => {
btn.style.transform = 'scale(1)';
});
btn.addEventListener('click', () => {
if (link) window.open(link, '_blank');
else fecharBanner();
});
return btn;
}
banner.appendChild(criarBotao(
'https://i.imgur.com/6C466vU.png', 985, 649, 132, 150,
'https://linktr.ee/L4pisD4Silv4'
));
banner.appendChild(criarBotao(
'https://i.imgur.com/T32os95.png', 1308, 651, 426, 116,
'https://ko-fi.com/l4pisd4silv4'
));
banner.appendChild(criarBotao(
'https://i.imgur.com/HbC1dXb.png', 1773, 788, 52, 52
));
overlay.addEventListener('click', fecharBanner);
}
function initImagemPro() {
try {
if (window.trustedTypes && !imagemProPolicy) {
debug("Aviso: TrustedTypes está disponível mas não conseguimos criar a política", true);
}
initLanguage();
setupHotkey();
debug('Imagem Pro inicializado com sucesso');
} catch (e) {
debug('Erro ao inicializar Imagem Pro: ' + e.message, true);
console.error(e);
}
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initImagemPro);
} else {
initImagemPro();
}
})();
/*
------------------------------
© 2025 L4pisD4Silv4. Todos os direitos reservados.
Qualquer cópia, modificação, redistribuição ou uso comercial
não autorizado deste script é proibido e pode resultar em ações legais.
Obrigado por respeitar este trabalho e a dedicação investida.
------------------------------
*/