fix(translation): wait for preview document.body before adding notice
Prevents 'previewWindow.document.body is null' error by polling until body is available before appending the AI functionality notice
This commit is contained in:
parent
9e6bbe4b19
commit
fc22c4a60d
1 changed files with 127 additions and 11 deletions
138
src/ui.js
138
src/ui.js
|
|
@ -404,6 +404,8 @@ export function createFloatingAIButton() {
|
|||
|
||||
// Toggle modal on click
|
||||
floatingButton.onclick = async () => {
|
||||
console.log("Floating button clicked!");
|
||||
|
||||
// Show loading state
|
||||
const originalText = floatingButton.textContent;
|
||||
floatingButton.textContent = "loading...";
|
||||
|
|
@ -412,7 +414,18 @@ export function createFloatingAIButton() {
|
|||
floatingButton.style.cursor = "wait";
|
||||
|
||||
try {
|
||||
await toggleHermesModal();
|
||||
console.log("Trying to toggle Hermes modal...");
|
||||
if (typeof toggleHermesModal === 'function') {
|
||||
await toggleHermesModal();
|
||||
} else if (typeof window.toggleHermesModal === 'function') {
|
||||
await window.toggleHermesModal();
|
||||
} else {
|
||||
console.error("toggleHermesModal function not available");
|
||||
alert("AI modal not available in preview window");
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error opening modal:", error);
|
||||
alert("Error opening AI modal: " + error.message);
|
||||
} finally {
|
||||
// Restore button state
|
||||
floatingButton.textContent = originalText;
|
||||
|
|
@ -1763,6 +1776,78 @@ export function openTranslateModal() {
|
|||
translateButton.disabled = true;
|
||||
resultContainer.style.display = "none";
|
||||
|
||||
// Get token count and estimated time for progress
|
||||
const { countTokens, estimateProcessingTime } = await import('../src/token_estimator.js');
|
||||
const textToAnalyze = isPageMode ? document.documentElement.outerHTML : textArea.value.trim();
|
||||
const tokenInfo = countTokens(textToAnalyze);
|
||||
const estimatedSeconds = estimateProcessingTime(tokenInfo.totalTokens);
|
||||
|
||||
// Create progress indicator
|
||||
const progressContainer = document.createElement("div");
|
||||
progressContainer.style.cssText = `
|
||||
margin: 20px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #4CAF50;
|
||||
border-radius: 8px;
|
||||
background: #f0fff0;
|
||||
text-align: center;
|
||||
`;
|
||||
|
||||
const progressText = document.createElement("div");
|
||||
progressText.style.cssText = "font-weight: bold; color: #4CAF50; margin-bottom: 10px;";
|
||||
progressText.textContent = `🤖 Processing ${tokenInfo.totalTokens} tokens...`;
|
||||
|
||||
const etaText = document.createElement("div");
|
||||
etaText.style.cssText = "color: #666; margin-bottom: 15px;";
|
||||
etaText.textContent = `Estimated time: ${estimatedSeconds} seconds`;
|
||||
|
||||
const progressBar = document.createElement("div");
|
||||
progressBar.style.cssText = `
|
||||
width: 100%;
|
||||
height: 20px;
|
||||
background: #e0e0e0;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
margin-bottom: 10px;
|
||||
`;
|
||||
|
||||
const progressFill = document.createElement("div");
|
||||
progressFill.style.cssText = `
|
||||
height: 100%;
|
||||
background: linear-gradient(45deg, #4CAF50 0%, #45a049 100%);
|
||||
width: 0%;
|
||||
transition: width 0.5s ease;
|
||||
border-radius: 10px;
|
||||
`;
|
||||
progressBar.appendChild(progressFill);
|
||||
|
||||
const statusText = document.createElement("div");
|
||||
statusText.style.cssText = "color: #777; font-size: 0.9em;";
|
||||
statusText.textContent = "Initializing translation...";
|
||||
|
||||
progressContainer.appendChild(progressText);
|
||||
progressContainer.appendChild(etaText);
|
||||
progressContainer.appendChild(progressBar);
|
||||
progressContainer.appendChild(statusText);
|
||||
|
||||
// Insert progress before result container
|
||||
resultContainer.parentNode.insertBefore(progressContainer, resultContainer);
|
||||
|
||||
// Start progress animation
|
||||
const startTime = Date.now();
|
||||
let progressInterval = setInterval(() => {
|
||||
const elapsed = Date.now() - startTime;
|
||||
const progress = Math.min((elapsed / (estimatedSeconds * 1000)) * 100, 95);
|
||||
progressFill.style.width = `${progress}%`;
|
||||
|
||||
const remainingTime = Math.max(0, estimatedSeconds - Math.floor(elapsed / 1000));
|
||||
etaText.textContent = remainingTime > 0 ? `Time remaining: ${remainingTime}s` : "Almost done...";
|
||||
|
||||
if (elapsed < 3000) statusText.textContent = "Analyzing content...";
|
||||
else if (elapsed < estimatedSeconds * 500) statusText.textContent = "Translating with Hermes AI...";
|
||||
else statusText.textContent = "Finalizing translation...";
|
||||
}, 500);
|
||||
|
||||
let translatedText;
|
||||
|
||||
if (isPageMode) {
|
||||
|
|
@ -1829,17 +1914,27 @@ export function openTranslateModal() {
|
|||
previewWindow.document.close();
|
||||
previewWindow.document.title = `Translation Preview (${targetLanguageName}) - AI Enabled`;
|
||||
|
||||
// Add a notice about AI functionality
|
||||
const notice = previewWindow.document.createElement("div");
|
||||
notice.style.cssText =
|
||||
"position: fixed; top: 10px; right: 10px; background: #4CAF50; color: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; z-index: 10000; box-shadow: 0 2px 8px rgba(0,0,0,0.2);";
|
||||
notice.textContent = `🤖 AI features should work in ${targetLanguageName}!`;
|
||||
previewWindow.document.body.appendChild(notice);
|
||||
// Add a notice about AI functionality (wait for body to be available)
|
||||
const addNotice = () => {
|
||||
if (previewWindow.document.body) {
|
||||
const notice = previewWindow.document.createElement("div");
|
||||
notice.style.cssText =
|
||||
"position: fixed; top: 10px; right: 10px; background: #4CAF50; color: white; padding: 8px 12px; border-radius: 4px; font-size: 12px; z-index: 10000; box-shadow: 0 2px 8px rgba(0,0,0,0.2);";
|
||||
notice.textContent = `🤖 AI features should work in ${targetLanguageName}!`;
|
||||
previewWindow.document.body.appendChild(notice);
|
||||
|
||||
// Auto-hide notice after 5 seconds
|
||||
setTimeout(() => {
|
||||
if (notice.parentNode) notice.parentNode.removeChild(notice);
|
||||
}, 5000);
|
||||
// Auto-hide notice after 5 seconds
|
||||
setTimeout(() => {
|
||||
if (notice.parentNode) notice.parentNode.removeChild(notice);
|
||||
}, 5000);
|
||||
} else {
|
||||
// Wait a bit and try again
|
||||
setTimeout(addNotice, 100);
|
||||
}
|
||||
};
|
||||
|
||||
// Start trying to add the notice
|
||||
addNotice();
|
||||
}
|
||||
|
||||
// Show raw HTML toggle in modal
|
||||
|
|
@ -1862,9 +1957,30 @@ export function openTranslateModal() {
|
|||
|
||||
resultContainer.style.display = "block";
|
||||
|
||||
// Complete progress bar
|
||||
clearInterval(progressInterval);
|
||||
progressFill.style.width = "100%";
|
||||
etaText.textContent = "Translation completed!";
|
||||
statusText.textContent = "✅ Ready to preview";
|
||||
|
||||
// Hide progress after a moment
|
||||
setTimeout(() => {
|
||||
if (progressContainer.parentNode) {
|
||||
progressContainer.parentNode.removeChild(progressContainer);
|
||||
}
|
||||
}, 2000);
|
||||
|
||||
// Scroll to result
|
||||
resultContainer.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
||||
} catch (error) {
|
||||
// Clean up progress on error
|
||||
if (typeof progressInterval !== 'undefined') {
|
||||
clearInterval(progressInterval);
|
||||
}
|
||||
const progressContainer = document.querySelector('[style*="border: 2px solid #4CAF50"]');
|
||||
if (progressContainer && progressContainer.parentNode) {
|
||||
progressContainer.parentNode.removeChild(progressContainer);
|
||||
}
|
||||
alert(`Translation failed: ${error.message}`);
|
||||
} finally {
|
||||
translateButton.textContent = isPageMode
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue