fix clipboard for the panel
This commit is contained in:
@ -1011,6 +1011,7 @@ const fileContextMenu = (elDisplay = null) => {
|
|||||||
.setLabel('Copy path')
|
.setLabel('Copy path')
|
||||||
.setClickHandler(() => {
|
.setClickHandler(() => {
|
||||||
const path = isNoneSelected ? activeConnection.path : selectedFiles[0].dataset.path;
|
const path = isNoneSelected ? activeConnection.path : selectedFiles[0].dataset.path;
|
||||||
|
console.log('Clipboard context:', window.location.href, window.top === window ? 'Parent' : 'Iframe');
|
||||||
navigator.clipboard.writeText(path);
|
navigator.clipboard.writeText(path);
|
||||||
setStatus(`Copied path to clipboard`);
|
setStatus(`Copied path to clipboard`);
|
||||||
})
|
})
|
||||||
@ -2318,8 +2319,25 @@ btnShare.addEventListener('click', async() => {
|
|||||||
} else if (isMultiSelected)
|
} else if (isMultiSelected)
|
||||||
url = await getZipDownloadUrl(selected.map(el => el.dataset.path), activeConnection.path);
|
url = await getZipDownloadUrl(selected.map(el => el.dataset.path), activeConnection.path);
|
||||||
if (url) {
|
if (url) {
|
||||||
navigator.clipboard.writeText(url);
|
try {
|
||||||
setStatus(`Copied download link to clipboard`);
|
await navigator.clipboard.writeText(url);
|
||||||
|
setStatus(`Copied download link to clipboard`);
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Clipboard error:', err);
|
||||||
|
// Fallback
|
||||||
|
const textarea = document.createElement('textarea');
|
||||||
|
textarea.value = url;
|
||||||
|
document.body.appendChild(textarea);
|
||||||
|
textarea.select();
|
||||||
|
try {
|
||||||
|
document.execCommand('copy');
|
||||||
|
setStatus(`Copied download link to clipboard (fallback)`);
|
||||||
|
} catch (fallbackErr) {
|
||||||
|
console.error('Fallback failed:', fallbackErr);
|
||||||
|
setStatus(`Failed to copy link. Please copy manually: ${url}`, true);
|
||||||
|
}
|
||||||
|
document.body.removeChild(textarea);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.addAction(action => action.setLabel('Cancel'))
|
.addAction(action => action.setLabel('Cancel'))
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||||
<meta name="theme-color" content="#1f2733">
|
<meta name="theme-color" content="#1f2733">
|
||||||
<link rel="manifest" href="/manifest.json" />
|
<meta http-equiv="Permissions-Policy" content="clipboard-write=(self 'https://sftp.my-mc.link')">
|
||||||
|
<link rel="manifest" href="/manifest.json" />
|
||||||
<link rel="icon" href="/icon.png">
|
<link rel="icon" href="/icon.png">
|
||||||
<link rel="stylesheet" href="https://src.simplecyber.org/v2/themes.css">
|
<link rel="stylesheet" href="https://src.simplecyber.org/v2/themes.css">
|
||||||
<link rel="stylesheet" href="https://src.simplecyber.org/v2/base.css">
|
<link rel="stylesheet" href="https://src.simplecyber.org/v2/base.css">
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
self.addEventListener('activate', (e) => {
|
self.addEventListener('activate', (e) => {
|
||||||
self.clients.claim();
|
self.clients.claim();
|
||||||
});
|
});
|
||||||
@ -6,24 +5,44 @@ self.addEventListener('activate', (e) => {
|
|||||||
self.addEventListener('fetch', (e) => {
|
self.addEventListener('fetch', (e) => {
|
||||||
const reqUrl = e.request.url;
|
const reqUrl = e.request.url;
|
||||||
e.respondWith((async() => {
|
e.respondWith((async() => {
|
||||||
// Open asset cache and see if this request is in it
|
// Open asset cache
|
||||||
const cache = await caches.open('main');
|
const cache = await caches.open('main');
|
||||||
const match = await caches.match(e.request);
|
const match = await caches.match(e.request);
|
||||||
// Request the resource from the network
|
|
||||||
|
// Request from network
|
||||||
const netRes = fetch(e.request).then((res) => {
|
const netRes = fetch(e.request).then((res) => {
|
||||||
// If the request was successful and this isn't an API call,
|
// Create a new response with updated headers
|
||||||
// update the cached resource
|
const newHeaders = new Headers(res.headers);
|
||||||
|
newHeaders.set('Permissions-Policy', 'clipboard-write=(self), clipboard-read=(self)');
|
||||||
|
|
||||||
|
const newRes = new Response(res.body, {
|
||||||
|
status: res.status,
|
||||||
|
statusText: res.statusText,
|
||||||
|
headers: newHeaders
|
||||||
|
});
|
||||||
|
|
||||||
|
// Cache non-API responses
|
||||||
if (res.ok && !reqUrl.match(/\/api\/sftp\/.*$/)) {
|
if (res.ok && !reqUrl.match(/\/api\/sftp\/.*$/)) {
|
||||||
cache.put(e.request, res.clone());
|
cache.put(e.request, newRes.clone());
|
||||||
}
|
}
|
||||||
// Return the response
|
|
||||||
return res;
|
return newRes;
|
||||||
}).catch(e => {
|
}).catch(e => {
|
||||||
console.error(e);
|
console.error('Fetch error:', e);
|
||||||
return match;
|
if (match) {
|
||||||
|
// Add header to cached response
|
||||||
|
const newHeaders = new Headers(match.headers);
|
||||||
|
newHeaders.set('Permissions-Policy', 'clipboard-write=(self), clipboard-read=(self)');
|
||||||
|
return new Response(match.body, {
|
||||||
|
status: match.status,
|
||||||
|
statusText: match.statusText,
|
||||||
|
headers: newHeaders
|
||||||
|
});
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
});
|
});
|
||||||
// Return the cached resource if it exists
|
|
||||||
// Otherwise, return the network request
|
// Return cached or network response
|
||||||
return match || netRes;
|
return match || netRes;
|
||||||
})());
|
})());
|
||||||
});
|
});
|
Reference in New Issue
Block a user