Client tool
This commit is contained in:
93
script.js
93
script.js
@@ -3,6 +3,63 @@
|
||||
(function () {
|
||||
'use strict';
|
||||
|
||||
function getServiceUrl(el) {
|
||||
var url = el.getAttribute('data-service-url') || '';
|
||||
url = (url || '').trim();
|
||||
if (!url) return '';
|
||||
// strip trailing slashes
|
||||
return url.replace(/\/+$/, '');
|
||||
}
|
||||
|
||||
function getServiceToken(el) {
|
||||
var token = el.getAttribute('data-service-token') || '';
|
||||
return (token || '').trim();
|
||||
}
|
||||
|
||||
function pingOpenViaImage(el, rawPath) {
|
||||
var baseUrl = getServiceUrl(el);
|
||||
if (!baseUrl) return;
|
||||
|
||||
var token = getServiceToken(el);
|
||||
var url = baseUrl + '/open?path=' + encodeURIComponent(rawPath);
|
||||
if (token) url += '&token=' + encodeURIComponent(token);
|
||||
|
||||
// Fire-and-forget without CORS.
|
||||
try {
|
||||
var img = new window.Image();
|
||||
img.src = url;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
function openViaService(el, rawPath) {
|
||||
var baseUrl = getServiceUrl(el);
|
||||
if (!baseUrl) return Promise.reject(new Error('No opener service configured'));
|
||||
|
||||
var headers = {
|
||||
'Content-Type': 'application/json'
|
||||
};
|
||||
var token = getServiceToken(el);
|
||||
if (token) headers['X-Filetools-Token'] = token;
|
||||
|
||||
return window.fetch(baseUrl + '/open', {
|
||||
method: 'POST',
|
||||
mode: 'cors',
|
||||
credentials: 'omit',
|
||||
headers: headers,
|
||||
body: JSON.stringify({ path: rawPath })
|
||||
}).then(function (res) {
|
||||
if (!res.ok) {
|
||||
return res.json().catch(function () { return null; }).then(function (body) {
|
||||
var msg = (body && body.message) ? body.message : ('HTTP ' + res.status);
|
||||
throw new Error(msg);
|
||||
});
|
||||
}
|
||||
return res.json().catch(function () { return { ok: true }; });
|
||||
});
|
||||
}
|
||||
|
||||
function normalizeToFileUrl(path) {
|
||||
if (!path) return '';
|
||||
|
||||
@@ -37,21 +94,29 @@
|
||||
if (!el || !el.classList || !el.classList.contains('filetools-open')) return;
|
||||
|
||||
var raw = el.getAttribute('data-path') || '';
|
||||
var url = normalizeToFileUrl(raw);
|
||||
console.log('Opening file URL:', url);
|
||||
if (!url) return;
|
||||
if (!raw) return;
|
||||
|
||||
// Best-effort: browsers may block file:// navigation depending on settings.
|
||||
try {
|
||||
window.open(url, '_blank', 'noopener');
|
||||
} catch (e) {
|
||||
console.error('Failed to open file URL in new tab:', e);
|
||||
try {
|
||||
window.location.href = url;
|
||||
} catch (e2) {
|
||||
console.error('Failed to open file URL:', e2);
|
||||
}
|
||||
}
|
||||
// Prefer local opener service.
|
||||
openViaService(el, raw)
|
||||
.catch(function (err) {
|
||||
// If the browser blocks the request before it reaches localhost (mixed-content,
|
||||
// extensions, stricter CORS handling), fall back to a no-CORS GET ping.
|
||||
pingOpenViaImage(el, raw);
|
||||
|
||||
// Fallback to old behavior (often blocked in modern browsers).
|
||||
var url = normalizeToFileUrl(raw);
|
||||
if (!url) return;
|
||||
console.warn('Local opener service failed, falling back to file:// navigation:', err);
|
||||
try {
|
||||
window.open(url, '_blank', 'noopener');
|
||||
} catch (e) {
|
||||
try {
|
||||
window.location.href = url;
|
||||
} catch (e2) {
|
||||
console.error('Failed to open file URL:', e2);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('click', onClick, false);
|
||||
|
||||
Reference in New Issue
Block a user