feat: add copy & download actions for modal

This commit is contained in:
divocat
2025-10-18 00:56:52 +03:00
parent d7235e8c06
commit fd64eb5bcb
5 changed files with 91 additions and 11 deletions

View File

@@ -0,0 +1,12 @@
export function copyToClipboard(text: string) {
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
} catch (_err) {
console.error('copyToClipboard - e', _err);
}
document.body.removeChild(textarea);
}

View File

@@ -0,0 +1,15 @@
export function downloadAsTxt(text: string, filename: string) {
const blob = new Blob([text], { type: 'text/plain;charset=utf-8' });
const link = document.createElement('a');
link.href = URL.createObjectURL(blob);
const safeName = filename.endsWith('.txt') ? filename : `${filename}.txt`;
link.download = safeName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
}

View File

@@ -1,6 +1,8 @@
import { renderButton } from '../button/renderButton'; import { renderButton } from '../button/renderButton';
import { copyToClipboard } from '../../helpers/copyToClipboard';
import { downloadAsTxt } from '../../helpers/downloadAsTxt';
export function renderModal(text: string) { export function renderModal(text: string, name: string) {
return E( return E(
'div', 'div',
{ class: 'pdk-partial-modal__body' }, { class: 'pdk-partial-modal__body' },
@@ -8,10 +10,16 @@ export function renderModal(text: string) {
E('pre', { class: 'pdk-partial-modal__content' }, E('code', {}, text)), E('pre', { class: 'pdk-partial-modal__content' }, E('code', {}, text)),
E('div', { class: 'pdk-partial-modal__footer' }, [ E('div', { class: 'pdk-partial-modal__footer' }, [
renderButton({
classNames: ['cbi-button-apply'],
text: _('Download'),
onClick: () => downloadAsTxt(text, name),
}),
renderButton({ renderButton({
classNames: ['cbi-button-apply'], classNames: ['cbi-button-apply'],
text: _('Copy'), text: _('Copy'),
onClick: () => {}, onClick: () =>
copyToClipboard(` \`\`\`${name} \n ${text} \n \`\`\``),
}), }),
renderButton({ renderButton({
classNames: ['cbi-button-remove'], classNames: ['cbi-button-remove'],

View File

@@ -214,7 +214,10 @@ async function handleShowGlobalCheck() {
const globalCheck = await PodkopShellMethods.globalCheck(); const globalCheck = await PodkopShellMethods.globalCheck();
if (globalCheck.success) { if (globalCheck.success) {
ui.showModal(_('Global check'), renderModal(globalCheck.data as string)); ui.showModal(
_('Global check'),
renderModal(globalCheck.data as string, 'global_check'),
);
} }
} catch (e) { } catch (e) {
console.log('handleShowGlobalCheck - e', e); console.log('handleShowGlobalCheck - e', e);
@@ -241,7 +244,10 @@ async function handleViewLogs() {
const viewLogs = await PodkopShellMethods.checkLogs(); const viewLogs = await PodkopShellMethods.checkLogs();
if (viewLogs.success) { if (viewLogs.success) {
ui.showModal(_('View logs'), renderModal(viewLogs.data as string)); ui.showModal(
_('View logs'),
renderModal(viewLogs.data as string, 'view_logs'),
);
} }
} catch (e) { } catch (e) {
console.log('handleViewLogs - e', e); console.log('handleViewLogs - e', e);
@@ -270,7 +276,7 @@ async function handleShowSingBoxConfig() {
if (showSingBoxConfig.success) { if (showSingBoxConfig.success) {
ui.showModal( ui.showModal(
_('Show sing-box config'), _('Show sing-box config'),
renderModal(showSingBoxConfig.data as string), renderModal(showSingBoxConfig.data as string, 'show_sing_box_config'),
); );
} }
} catch (e) { } catch (e) {

View File

@@ -2954,19 +2954,52 @@ function renderButton({
); );
} }
// src/helpers/copyToClipboard.ts
function copyToClipboard(text) {
const textarea = document.createElement("textarea");
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand("copy");
} catch (_err) {
console.error("copyToClipboard - e", _err);
}
document.body.removeChild(textarea);
}
// src/helpers/downloadAsTxt.ts
function downloadAsTxt(text, filename) {
const blob = new Blob([text], { type: "text/plain;charset=utf-8" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
const safeName = filename.endsWith(".txt") ? filename : `${filename}.txt`;
link.download = safeName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
URL.revokeObjectURL(link.href);
}
// src/partials/modal/renderModal.ts // src/partials/modal/renderModal.ts
function renderModal(text) { function renderModal(text, name) {
return E( return E(
"div", "div",
{ class: "pdk-partial-modal__body" }, { class: "pdk-partial-modal__body" },
E("div", {}, [ E("div", {}, [
E("pre", { class: "pdk-partial-modal__content" }, E("code", {}, text)), E("pre", { class: "pdk-partial-modal__content" }, E("code", {}, text)),
E("div", { class: "pdk-partial-modal__footer" }, [ E("div", { class: "pdk-partial-modal__footer" }, [
renderButton({
classNames: ["cbi-button-apply"],
text: _("Download"),
onClick: () => downloadAsTxt(text, name)
}),
renderButton({ renderButton({
classNames: ["cbi-button-apply"], classNames: ["cbi-button-apply"],
text: _("Copy"), text: _("Copy"),
onClick: () => { onClick: () => copyToClipboard(` \`\`\`${name}
} ${text}
\`\`\``)
}), }),
renderButton({ renderButton({
classNames: ["cbi-button-remove"], classNames: ["cbi-button-remove"],
@@ -3464,7 +3497,10 @@ async function handleShowGlobalCheck() {
try { try {
const globalCheck = await PodkopShellMethods.globalCheck(); const globalCheck = await PodkopShellMethods.globalCheck();
if (globalCheck.success) { if (globalCheck.success) {
ui.showModal(_("Global check"), renderModal(globalCheck.data)); ui.showModal(
_("Global check"),
renderModal(globalCheck.data, "global_check")
);
} }
} catch (e) { } catch (e) {
console.log("handleShowGlobalCheck - e", e); console.log("handleShowGlobalCheck - e", e);
@@ -3488,7 +3524,10 @@ async function handleViewLogs() {
try { try {
const viewLogs = await PodkopShellMethods.checkLogs(); const viewLogs = await PodkopShellMethods.checkLogs();
if (viewLogs.success) { if (viewLogs.success) {
ui.showModal(_("View logs"), renderModal(viewLogs.data)); ui.showModal(
_("View logs"),
renderModal(viewLogs.data, "view_logs")
);
} }
} catch (e) { } catch (e) {
console.log("handleViewLogs - e", e); console.log("handleViewLogs - e", e);
@@ -3514,7 +3553,7 @@ async function handleShowSingBoxConfig() {
if (showSingBoxConfig.success) { if (showSingBoxConfig.success) {
ui.showModal( ui.showModal(
_("Show sing-box config"), _("Show sing-box config"),
renderModal(showSingBoxConfig.data) renderModal(showSingBoxConfig.data, "show_sing_box_config")
); );
} }
} catch (e) { } catch (e) {