File size: 13,599 Bytes
a91e387
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
// Debug helpers
function debug(message) {
    console.log(`[Debug] ${message}`);
}

document.addEventListener('DOMContentLoaded', function() {
    // Debug print
    debug("UI initialized");
    
    // Get DOM elements
    const urlForm = document.getElementById('url-form');
    const pdfForm = document.getElementById('pdf-form');
    const tabButtons = document.querySelectorAll('.tab-btn');
    const tabPanes = document.querySelectorAll('.tab-pane');
    const fileInput = document.getElementById('pdf-file');
    const fileNameDisplay = document.querySelector('.file-name');
    const resultsContainer = document.getElementById('results');
    const resultsGrid = document.querySelector('.results-grid');
    const progressContainer = document.querySelector('.progress-container');
    const progressText = document.querySelector('.progress-text');
    const progressFill = document.querySelector('.progress-fill');
    const tryNowBtn = document.getElementById('try-now-btn');
    
    // Handle Try Now button click
    if (tryNowBtn) {
        tryNowBtn.addEventListener('click', function() {
            const translatorSection = document.getElementById('translator');
            translatorSection.scrollIntoView({ behavior: 'smooth' });
        });
    }
    
    // Handle tab switching
    tabButtons.forEach(button => {
        button.addEventListener('click', function() {
            // Get the target tab
            const tabId = this.getAttribute('data-tab');
            
            // Remove active class from all tabs and panes
            tabButtons.forEach(btn => btn.classList.remove('active'));
            tabPanes.forEach(pane => pane.classList.remove('active'));
            
            // Add active class to current tab and pane
            this.classList.add('active');
            document.getElementById(tabId).classList.add('active');
            
            debug(`Switched to tab: ${tabId}`);
        });
    });
    
    // Handle file input change
    if (fileInput) {
        fileInput.addEventListener('change', function() {
            if (this.files.length > 0) {
                const fileName = this.files[0].name;
                fileNameDisplay.textContent = fileName;
                debug(`Selected file: ${fileName}`);
            } else {
                fileNameDisplay.textContent = 'No file chosen';
            }
        });
    }
    
    // Handle URL form submission
    if (urlForm) {
        urlForm.addEventListener('submit', async function(e) {
            e.preventDefault();
            
            // Get form data
            const url = document.getElementById('manga-url').value;
            const srcLang = document.getElementById('url-src-lang').value;
            const tgtLang = document.getElementById('url-tgt-lang').value;
            
            debug(`Submitting URL form with url=${url}, srcLang=${srcLang}, tgtLang=${tgtLang}`);
            
            // Show progress bar
            resultsGrid.innerHTML = '';
            progressFill.style.width = '0%';
            progressText.textContent = 'Preparing translation...';
            progressContainer.style.display = 'block';
            
            // Submit form data to API
            try {
                // Create the request body
                const requestBody = {
                    url: url,
                    src_lang: srcLang,
                    tgt_lang: tgtLang,
                    translator: 'google'
                };
                
                // Call the API with streaming response
                await handleTranslation('/translate/url', requestBody);
                
            } catch (error) {
                debug(`Error during URL translation: ${error}`);
                showError("An error occurred during translation. Please try again.");
            }
        });
    }
    
    // Handle PDF form submission
    if (pdfForm) {
        pdfForm.addEventListener('submit', async function(e) {
            e.preventDefault();
            
            // Check if a file is selected
            if (!fileInput.files[0]) {
                showError("Please select a PDF file first.");
                return;
            }
            
            // Get form data
            const file = fileInput.files[0];
            const srcLang = document.getElementById('pdf-src-lang').value;
            const tgtLang = document.getElementById('pdf-tgt-lang').value;
            
            debug(`Submitting PDF form with file=${file.name}, srcLang=${srcLang}, tgtLang=${tgtLang}`);
            
            // Show progress bar
            resultsGrid.innerHTML = '';
            progressFill.style.width = '0%';
            progressText.textContent = 'Preparing PDF translation...';
            progressContainer.style.display = 'block';
            
            // Create FormData
            const formData = new FormData();
            formData.append('file', file);
            formData.append('src_lang', srcLang);
            formData.append('tgt_lang', tgtLang);
            formData.append('translator', 'google');
            
            // Submit form data to API
            try {
                // Call the translation endpoint with streaming response
                await handlePdfTranslation('/translate/pdf', formData);
                
            } catch (error) {
                debug(`Error during PDF translation: ${error}`);
                showError("An error occurred during translation. Please try again.");
            }
        });
    }
    
    // Function to handle URL translation with streaming response
    async function handleTranslation(endpoint, requestBody) {
        try {
            const response = await fetch(endpoint, {
                method: 'POST',
                headers: {
                    'Content-Type': 'application/json'
                },
                body: JSON.stringify(requestBody)
            });
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            
            let receivedImages = 0;
            let totalImages = 5; // Default assumption, will be updated if more info is available
            
            while (true) {
                const { value, done } = await reader.read();
                
                if (done) {
                    break;
                }
                
                // Process the streamed response
                const text = decoder.decode(value, { stream: true });
                const lines = text.split('\n\n');
                
                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        try {
                            const data = JSON.parse(line.substring(6));
                            processTranslationUpdate(data, receivedImages, totalImages);
                            
                            if (data.status === 'success' && data.image_url) {
                                receivedImages++;
                                updateProgress(receivedImages, totalImages);
                            } else if (data.status === 'complete') {
                                progressContainer.style.display = 'none';
                            }
                        } catch (e) {
                            debug(`Error parsing JSON: ${e}`);
                        }
                    }
                }
            }
            
        } catch (error) {
            debug(`Error during translation: ${error}`);
            showError("An error occurred during translation. Please try again.");
        }
    }
    
    // Function to handle PDF translation with streaming response
    async function handlePdfTranslation(endpoint, formData) {
        try {
            const response = await fetch(endpoint, {
                method: 'POST',
                body: formData
            });
            
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            
            const reader = response.body.getReader();
            const decoder = new TextDecoder();
            
            let receivedImages = 0;
            let totalImages = 5; // Default assumption, will be updated if more info is available
            
            while (true) {
                const { value, done } = await reader.read();
                
                if (done) {
                    break;
                }
                
                // Process the streamed response
                const text = decoder.decode(value, { stream: true });
                const lines = text.split('\n\n');
                
                for (const line of lines) {
                    if (line.startsWith('data: ')) {
                        try {
                            const data = JSON.parse(line.substring(6));
                            processTranslationUpdate(data, receivedImages, totalImages);
                            
                            if (data.status === 'success' && data.image_url) {
                                receivedImages++;
                                updateProgress(receivedImages, totalImages);
                            } else if (data.status === 'complete') {
                                progressContainer.style.display = 'none';
                            }
                        } catch (e) {
                            debug(`Error parsing JSON: ${e}`);
                        }
                    }
                }
            }
            
        } catch (error) {
            debug(`Error during translation: ${error}`);
            showError("An error occurred during translation. Please try again.");
        }
    }
    
    // Process translation updates
    function processTranslationUpdate(data, currentImage, totalImages) {
        debug(`Received update: ${JSON.stringify(data)}`);
        
        if (data.status === 'error') {
            showError(data.message || "An error occurred during translation.");
            progressContainer.style.display = 'none';
            return;
        }
        
        if (data.status === 'processing') {
            progressText.textContent = data.message || `Processing image ${currentImage + 1}/${totalImages}...`;
            return;
        }
        
        if (data.status === 'success' && data.image_url) {
            // Add the translated image to the results
            addImageToResults(data.image_url);
        }
        
        if (data.status === 'complete') {
            progressText.textContent = 'Translation complete!';
            progressFill.style.width = '100%';
            setTimeout(() => {
                progressContainer.style.display = 'none';
            }, 1000);
        }
    }
    
    // Update progress bar
    function updateProgress(current, total) {
        const percentage = Math.min(Math.round((current / total) * 100), 100);
        progressFill.style.width = `${percentage}%`;
        progressText.textContent = `Processing page ${current}/${total}...`;
    }
    
    // Add an image to the results grid
    function addImageToResults(imageUrl) {
        // Create result card
        const resultCard = document.createElement('div');
        resultCard.className = 'result-card';
        
        // Create image
        const img = document.createElement('img');
        img.className = 'result-image';
        img.src = imageUrl;
        img.alt = 'Translated Image';
        img.loading = 'lazy';
        
        // Create actions div
        const actionsDiv = document.createElement('div');
        actionsDiv.className = 'result-actions';
        
        // Create download link
        const downloadLink = document.createElement('a');
        downloadLink.href = imageUrl;
        downloadLink.download = 'translated-' + imageUrl.split('/').pop();
        downloadLink.className = 'btn';
        downloadLink.innerHTML = '<i class="fas fa-download"></i> Download';
        
        // Create view link
        const viewLink = document.createElement('a');
        viewLink.href = imageUrl;
        viewLink.target = '_blank';
        viewLink.className = 'btn';
        viewLink.innerHTML = '<i class="fas fa-external-link-alt"></i> View';
        
        // Append elements
        actionsDiv.appendChild(downloadLink);
        actionsDiv.appendChild(viewLink);
        resultCard.appendChild(img);
        resultCard.appendChild(actionsDiv);
        resultsGrid.appendChild(resultCard);
    }
    
    // Show error message
    function showError(message) {
        resultsGrid.innerHTML = `
            <div class="error-message">
                <i class="fas fa-exclamation-circle"></i>
                <p>${message}</p>
            </div>
        `;
    }
    
    // Create placeholder image on page load for visual preview
    function createPlaceholderImage() {
        const placeholderUrl = '/static/ui/placeholder.png';
        debug('Creating placeholder UI example');
        
        // Only add placeholder if no results yet
        if (resultsGrid.children.length === 0) {
            addImageToResults(placeholderUrl);
            addImageToResults(placeholderUrl);
        }
    }
    
    // Optional: Add placeholder images for demo purposes
    // Uncomment to enable placeholders on page load
    // createPlaceholderImage();
});