forked from izu/student-web-if-development-kit
fix(tapops): deteksi format file dan format tag
This commit is contained in:
@@ -1,6 +1,5 @@
|
||||
import { ScriptLoader } from './script-loader.js';
|
||||
import { FileDownloader } from '../services/file-downloader.js';
|
||||
import { ViewerApi } from './viewer-api.js';
|
||||
import { ViewerProgressBar } from './viewer-progress-bar.js';
|
||||
|
||||
export class FileViewer {
|
||||
constructor() {
|
||||
@@ -29,10 +28,12 @@ export class FileViewer {
|
||||
this._setupDownload();
|
||||
|
||||
try {
|
||||
if (this.type === 'docx') {
|
||||
await this._renderDocx();
|
||||
} else {
|
||||
if (this._isOfficeType()) {
|
||||
this._renderOfficeOnline();
|
||||
} else if (this.type === 'pdf') {
|
||||
this._renderPdf();
|
||||
} else {
|
||||
this._renderUnsupported();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@@ -44,7 +45,8 @@ export class FileViewer {
|
||||
const ext = `.${this.type}`;
|
||||
const filename = this.name.toLowerCase().endsWith(ext) ? this.name : `${this.name}${ext}`;
|
||||
|
||||
this.downloadEl.removeAttribute('href');
|
||||
this.downloadEl.href = FileDownloader.originalDownloadUrl(this.assetUrl);
|
||||
this.downloadEl.download = filename;
|
||||
this.downloadEl.style.cursor = 'pointer';
|
||||
this.downloadEl.addEventListener('click', async event => {
|
||||
event.preventDefault();
|
||||
@@ -52,19 +54,10 @@ export class FileViewer {
|
||||
this.downloadEl.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Mengunduh…';
|
||||
this.downloadEl.style.pointerEvents = 'none';
|
||||
try {
|
||||
const blob = await ViewerApi.fetchBlob(this.assetUrl);
|
||||
const blobUrl = URL.createObjectURL(blob);
|
||||
const link = document.createElement('a');
|
||||
link.style.display = 'none';
|
||||
link.href = blobUrl;
|
||||
link.download = filename;
|
||||
document.body.appendChild(link);
|
||||
link.click();
|
||||
document.body.removeChild(link);
|
||||
URL.revokeObjectURL(blobUrl);
|
||||
await FileDownloader.download(this.assetUrl, filename);
|
||||
} catch (err) {
|
||||
console.warn('Blob download failed, falling back:', err);
|
||||
window.open(`${this.assetUrl}?download`, '_blank');
|
||||
window.open(FileDownloader.originalDownloadUrl(this.assetUrl), '_blank');
|
||||
} finally {
|
||||
this.downloadEl.innerHTML = originalHtml;
|
||||
this.downloadEl.style.pointerEvents = '';
|
||||
@@ -72,6 +65,20 @@ export class FileViewer {
|
||||
});
|
||||
}
|
||||
|
||||
_isOfficeType() {
|
||||
return ['doc', 'docx', 'ppt', 'pptx', 'xls', 'xlsx'].includes(this.type);
|
||||
}
|
||||
|
||||
_renderOfficeOnline() {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.className = 'viewer-office-frame';
|
||||
iframe.title = this.name;
|
||||
iframe.src = `https://view.officeapps.live.com/op/embed.aspx?src=${encodeURIComponent(this.assetUrl)}`;
|
||||
iframe.setAttribute('frameborder', '0');
|
||||
iframe.setAttribute('allowfullscreen', '');
|
||||
this.contentEl.replaceChildren(iframe);
|
||||
}
|
||||
|
||||
_renderPdf() {
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.className = 'viewer-pdf-frame';
|
||||
@@ -80,33 +87,18 @@ export class FileViewer {
|
||||
this.contentEl.replaceChildren(iframe);
|
||||
}
|
||||
|
||||
async _renderDocx() {
|
||||
const progressBar = new ViewerProgressBar(this.contentEl);
|
||||
const [blob] = await Promise.all([
|
||||
ViewerApi.fetchBlob(this.assetUrl, ratio => progressBar.update(ratio)),
|
||||
this._loadDocxLibraries(),
|
||||
]);
|
||||
progressBar.finish();
|
||||
_renderUnsupported() {
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.className = 'viewer-error';
|
||||
|
||||
if (!window.docx || typeof window.docx.renderAsync !== 'function') {
|
||||
throw new Error('Library docx-preview belum dimuat.');
|
||||
}
|
||||
const icon = document.createElement('i');
|
||||
icon.className = 'fas fa-file';
|
||||
|
||||
const container = document.createElement('div');
|
||||
container.className = 'viewer-docx-content';
|
||||
this.contentEl.replaceChildren(container);
|
||||
const span = document.createElement('span');
|
||||
span.textContent = `Pratinjau tidak tersedia untuk format ${this.type.toUpperCase()}. Silakan unduh berkas.`;
|
||||
|
||||
await window.docx.renderAsync(blob, container, null, {
|
||||
inWrapper: true,
|
||||
ignoreWidth: false,
|
||||
ignoreHeight: false,
|
||||
});
|
||||
}
|
||||
|
||||
async _loadDocxLibraries() {
|
||||
if (window.docx) return;
|
||||
await ScriptLoader.load('https://unpkg.com/jszip@3.10.1/dist/jszip.min.js');
|
||||
await ScriptLoader.load('https://unpkg.com/docx-preview@0.3.5/dist/docx-preview.js');
|
||||
wrapper.append(icon, span);
|
||||
this.contentEl.replaceChildren(wrapper);
|
||||
}
|
||||
|
||||
_renderError(message) {
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
export class ScriptLoader {
|
||||
static load(src) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = resolve;
|
||||
script.onerror = () => reject(new Error(`Gagal memuat skrip: ${src}`));
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
export class ViewerProgressBar {
|
||||
constructor(contentEl) {
|
||||
this.bar = document.createElement('div');
|
||||
this.bar.className = 'viewer-progress-bar';
|
||||
this.fill = document.createElement('div');
|
||||
this.fill.className = 'viewer-progress-fill';
|
||||
this.bar.appendChild(this.fill);
|
||||
contentEl.prepend(this.bar);
|
||||
}
|
||||
|
||||
update(ratio) {
|
||||
this.fill.style.width = `${Math.min(Math.round(ratio * 100), 100)}%`;
|
||||
}
|
||||
|
||||
finish() {
|
||||
this.fill.style.width = '100%';
|
||||
setTimeout(() => this.bar.remove(), 300);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user