From cd43449585892b5d342b945c33b8f9890f687161 Mon Sep 17 00:00:00 2001 From: Ivan K Date: Tue, 18 Feb 2025 13:59:04 +0300 Subject: [PATCH] feat: add version information tab to diagnostics --- .../resources/view/podkop/podkop.js | 134 +++++++++++++++--- luci-app-podkop/po/ru/podkop.po | 18 ++- luci-app-podkop/po/templates/podkop.pot | 14 +- podkop/files/etc/init.d/podkop | 25 +++- 4 files changed, 166 insertions(+), 25 deletions(-) diff --git a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js index a5ddfb8..60a2852 100644 --- a/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js +++ b/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js @@ -153,7 +153,7 @@ return view.extend({ if (removedServices.length > 0) { newValues = newValues.filter(v => allowedWithRussiaInside.includes(v)); - const warningMsg = _('Warning: Russia inside can only be used with Meta, Twitter, Discord, and Telegram. %s have been removed from selection.').format( + const warningMsg = _('Warning: Russia inside can only be used with Meta, Twitter, Discord, and Telegram. %s already in Russia inside and have been removed from selection.').format( removedServices.join(', ') ); @@ -469,7 +469,6 @@ return view.extend({ o.ucisection = 'main'; // Additional Settings Tab - o = s.tab('additional', _('Additional Settings')); o = s.taboption('additional', form.Flag, 'yacd', _('Yacd enable'), _('http://openwrt.lan:9090/ui')); @@ -497,6 +496,7 @@ return view.extend({ o.rmempty = false; o.ucisection = 'main'; + // Diagnostics tab o = s.tab('diagnostics', _('Diagnostics')); function formatDiagnosticOutput(output) { @@ -512,6 +512,76 @@ return view.extend({ `: ${status === 'available' ? '✓' : '✗'}`); } + // Version Information Section + o = s.taboption('diagnostics', form.Button, '_show_versions'); + o.title = _('Version Information'); + o.description = _('Show version information for all components'); + o.inputtitle = _('Show Versions'); + o.inputstyle = 'apply'; + o.onclick = function () { + Promise.all([ + fs.exec('/etc/init.d/podkop', ['show_version']), + fs.exec('/etc/init.d/podkop', ['show_luci_version']), + fs.exec('/etc/init.d/podkop', ['show_sing_box_version']), + fs.exec('/etc/init.d/podkop', ['show_system_info']) + ]).then(function ([podkop, luci, singbox, system]) { + const versions = [ + '=== Podkop Version ===\n' + (podkop.stdout || _('No output')) + '\n', + '=== LuCI App ===\n' + (luci.stdout || _('No output')) + '\n', + '=== sing-box ===\n' + (singbox.stdout || _('No output')) + '\n', + system.stdout || _('No output') + ].join('\n'); + + const formattedOutput = formatDiagnosticOutput(versions); + ui.showModal(_('Version Information'), [ + E('div', { + style: + 'max-height: 70vh;' + + 'overflow-y: auto;' + + 'margin: 1em 0;' + + 'padding: 1.5em;' + + 'background: #f8f9fa;' + + 'border: 1px solid #e9ecef;' + + 'border-radius: 4px;' + + 'font-family: monospace;' + + 'white-space: pre-wrap;' + + 'word-wrap: break-word;' + + 'line-height: 1.5;' + + 'font-size: 14px;' + }, [ + E('pre', { style: 'margin: 0;' }, formattedOutput) + ]), + E('div', { + style: 'display: flex; justify-content: space-between; margin-top: 1em;' + }, [ + E('button', { + 'class': 'btn', + 'click': function (ev) { + const textarea = document.createElement('textarea'); + textarea.value = '```txt\n' + formattedOutput + '\n```'; + document.body.appendChild(textarea); + textarea.select(); + try { + document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); + } catch (err) { + ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); + } + document.body.removeChild(textarea); + } + }, _('Copy to Clipboard')), + E('button', { + 'class': 'btn', + 'click': ui.hideModal + }, _('Close')) + ]) + ]); + }); + }; + // Connection Checks Section o = s.taboption('diagnostics', form.Button, '_check_nft'); o.title = _('NFT Rules'); @@ -545,13 +615,17 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); - textarea.value = formattedOutput; + textarea.value = '```txt\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); } @@ -567,8 +641,6 @@ return view.extend({ }); }; - - // Logs Section o = s.taboption('diagnostics', form.Button, '_check_sing_box_logs'); o.title = _('Sing-Box Logs'); @@ -602,15 +674,19 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); - textarea.value = formattedOutput; + textarea.value = '```logs\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { - ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); + ui.addNotification(null, E('p', {}, _('Failed to copy logs: ') + err.message)); } document.body.removeChild(textarea); } @@ -656,15 +732,19 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); - textarea.value = formattedOutput; + textarea.value = '```logs\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { - ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); + ui.addNotification(null, E('p', {}, _('Failed to copy logs: ') + err.message)); } document.body.removeChild(textarea); } @@ -711,13 +791,17 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); - textarea.value = formattedOutput; + textarea.value = '```txt\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); } @@ -765,13 +849,17 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); - textarea.value = formattedOutput; + textarea.value = '```txt\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); } @@ -819,13 +907,17 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); textarea.value = '```json\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); } @@ -873,13 +965,17 @@ return view.extend({ }, [ E('button', { 'class': 'btn', - 'click': function () { + 'click': function (ev) { const textarea = document.createElement('textarea'); - textarea.value = formattedOutput; + textarea.value = '```json\n' + formattedOutput + '\n```'; document.body.appendChild(textarea); textarea.select(); try { document.execCommand('copy'); + ev.target.textContent = _('Copied!'); + setTimeout(() => { + ev.target.textContent = _('Copy to Clipboard'); + }, 1000); } catch (err) { ui.addNotification(null, E('p', {}, _('Failed to copy: ') + err.message)); } diff --git a/luci-app-podkop/po/ru/podkop.po b/luci-app-podkop/po/ru/podkop.po index 1b2aecf..fd080a6 100644 --- a/luci-app-podkop/po/ru/podkop.po +++ b/luci-app-podkop/po/ru/podkop.po @@ -468,8 +468,8 @@ msgid "Warning: %s cannot be used together with %s. Previous selections have bee msgstr "Предупреждение: %s нельзя использовать вместе с %s. Предыдущие варианты были удалены." #: applications/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:XXX -msgid "Warning: Russia inside can only be used with Meta, Twitter, Discord, and Telegram. %s have been removed from selection." -msgstr "Внимание: Russia inside может использоваться только с Meta, Twitter, Discord и Telegram. %s были удалены из выбора." +msgid "Warning: Russia inside can only be used with Meta, Twitter, Discord, and Telegram. %s already in Russia inside and have been removed from selection." +msgstr "Внимание: Russia inside может использоваться только с Meta, Twitter, Discord и Telegram. %s уже в Russia inside и были удалены из выбора." #: applications/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:XXX msgid "Regional options cannot be used together" @@ -477,4 +477,16 @@ msgstr "Нельзя использовать несколько региона #: applications/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:XXX msgid "Russia inside restrictions" -msgstr "Ограничения Russia inside" \ No newline at end of file +msgstr "Ограничения Russia inside" + +msgid "Version Information" +msgstr "Информация о версиях" + +msgid "Show version information for all components" +msgstr "Показать информацию о версиях всех компонентов" + +msgid "Show Versions" +msgstr "Показать версии" + +msgid "Copied!" +msgstr "Скопировано!" \ No newline at end of file diff --git a/luci-app-podkop/po/templates/podkop.pot b/luci-app-podkop/po/templates/podkop.pot index 68a04c5..f501532 100644 --- a/luci-app-podkop/po/templates/podkop.pot +++ b/luci-app-podkop/po/templates/podkop.pot @@ -468,7 +468,7 @@ msgid "Warning: %s cannot be used together with %s. Previous selections have bee msgstr "" #: applications/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:XXX -msgid "Warning: Russia inside can only be used with Meta, Twitter, Discord, and Telegram. %s have been removed from selection." +msgid "Warning: Russia inside can only be used with Meta, Twitter, Discord, and Telegram. %s already in Russia inside and have been removed from selection." msgstr "" #: applications/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:XXX @@ -477,4 +477,16 @@ msgstr "" #: applications/luci-app-podkop/htdocs/luci-static/resources/view/podkop/podkop.js:XXX msgid "Russia inside restrictions" +msgstr "" + +msgid "Version Information" +msgstr "" + +msgid "Show version information for all components" +msgstr "" + +msgid "Show Versions" +msgstr "" + +msgid "Copied!" msgstr "" \ No newline at end of file diff --git a/podkop/files/etc/init.d/podkop b/podkop/files/etc/init.d/podkop index 1b1040f..a9a99b0 100755 --- a/podkop/files/etc/init.d/podkop +++ b/podkop/files/etc/init.d/podkop @@ -7,7 +7,7 @@ script=$(readlink "$initscript") NAME="$(basename ${script:-$initscript})" config_load "$NAME" -EXTRA_COMMANDS="main list_update check_proxy check_nft check_github check_logs check_sing_box_connections check_sing_box_logs check_dnsmasq show_config show_version show_sing_box_config" +EXTRA_COMMANDS="main list_update check_proxy check_nft check_github check_logs check_sing_box_connections check_sing_box_logs check_dnsmasq show_config show_version show_sing_box_config show_luci_version show_sing_box_version show_system_info" EXTRA_HELP=" list_update Updating domain and subnet lists check_proxy Check if sing-box proxy works correctly check_nft Show PodkopTable nftables rules @@ -18,7 +18,10 @@ EXTRA_HELP=" list_update Updating domain and subnet lists check_dnsmasq Show current DNSMasq configuration show_config Show current configuration with masked sensitive data show_version Show current version - show_sing_box_config Show current sing-box configuration" + show_sing_box_config Show current sing-box configuration + show_luci_version Show LuCI app version + show_sing_box_version Show sing-box version + show_system_info Show OpenWrt version and device model" [ ! -L /usr/sbin/podkop ] && ln -s /etc/init.d/podkop /usr/sbin/podkop @@ -1608,4 +1611,22 @@ show_config() { show_version() { local version=$(opkg info podkop | grep -m 1 "Version:" | cut -d' ' -f2) echo "$version" +} + +show_luci_version() { + local version=$(opkg info luci-app-podkop | grep -m 1 "Version:" | cut -d' ' -f2) + echo "$version" +} + +show_sing_box_version() { + local version=$(opkg info sing-box | grep -m 1 "Version:" | cut -d' ' -f2) + echo "$version" +} + +show_system_info() { + echo "=== OpenWrt Version ===" + grep OPENWRT_RELEASE /etc/os-release | cut -d'"' -f2 + echo + echo "=== Device Model ===" + cat /tmp/sysinfo/model } \ No newline at end of file