refactor: unify dynamic page structure

This commit is contained in:
divocat
2025-10-14 21:49:09 +03:00
parent 33dfb8c3f0
commit 67ec5f3090
22 changed files with 430 additions and 404 deletions

View File

@@ -1,2 +1,7 @@
export * from './renderDashboard'; import { render } from './render';
export * from './initDashboardController'; import { initController } from './initController';
export const DashboardTab = {
render,
initController,
};

View File

@@ -5,14 +5,13 @@ import {
preserveScrollForPage, preserveScrollForPage,
} from '../../../helpers'; } from '../../../helpers';
import { prettyBytes } from '../../../helpers/prettyBytes'; import { prettyBytes } from '../../../helpers/prettyBytes';
import { renderSections } from './renderSections';
import { renderWidget } from './renderWidget';
import { import {
ClashMethods, ClashMethods,
CustomPodkopMethods, CustomPodkopMethods,
PodkopShellMethods, PodkopShellMethods,
} from '../../methods'; } from '../../methods';
import { socket, store, StoreType } from '../../services'; import { socket, store, StoreType } from '../../services';
import { renderSections, renderWidget } from './partials';
// Fetchers // Fetchers
@@ -420,7 +419,7 @@ async function onStoreUpdate(
} }
} }
export async function initDashboardController(): Promise<void> { export async function initController(): Promise<void> {
onMount('dashboard-status').then(() => { onMount('dashboard-status').then(() => {
// Remove old listener // Remove old listener
store.unsubscribe(onStoreUpdate); store.unsubscribe(onStoreUpdate);

View File

@@ -0,0 +1,2 @@
export * from './renderSections';
export * from './renderWidget';

View File

@@ -1,5 +1,5 @@
import { Podkop } from '../../types'; import { Podkop } from '../../../types';
import { getClashApiUrl } from '../../../helpers'; import { getClashApiUrl } from '../../../../helpers';
interface IRenderSectionsProps { interface IRenderSectionsProps {
loading: boolean; loading: boolean;

View File

@@ -1,7 +1,6 @@
import { renderSections } from './renderSections'; import { renderSections, renderWidget } from './partials';
import { renderWidget } from './renderWidget';
export function renderDashboard() { export function render() {
return E( return E(
'div', 'div',
{ {

View File

@@ -1,13 +1,13 @@
import { updateDiagnosticsCheck } from '../updateDiagnosticsCheck';
import { insertIf } from '../../../../helpers'; import { insertIf } from '../../../../helpers';
import { DIAGNOSTICS_CHECKS_MAP } from './contstants'; import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods } from '../../../methods'; import { PodkopShellMethods } from '../../../methods';
import { IDiagnosticsChecksItem } from '../../../services'; import { IDiagnosticsChecksItem } from '../../../services';
import { updateCheckStore } from './updateCheckStore';
export async function runDnsCheck() { export async function runDnsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.DNS; const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.DNS;
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -19,7 +19,7 @@ export async function runDnsCheck() {
const dnsChecks = await PodkopShellMethods.checkDNSAvailable(); const dnsChecks = await PodkopShellMethods.checkDNSAvailable();
if (!dnsChecks.success) { if (!dnsChecks.success) {
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -57,7 +57,7 @@ export async function runDnsCheck() {
return 'error'; return 'error';
} }
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,

View File

@@ -1,13 +1,13 @@
import { updateDiagnosticsCheck } from '../updateDiagnosticsCheck';
import { insertIf } from '../../../../helpers'; import { insertIf } from '../../../../helpers';
import { DIAGNOSTICS_CHECKS_MAP } from './contstants'; import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods, RemoteFakeIPMethods } from '../../../methods'; import { PodkopShellMethods, RemoteFakeIPMethods } from '../../../methods';
import { IDiagnosticsChecksItem } from '../../../services'; import { IDiagnosticsChecksItem } from '../../../services';
import { updateCheckStore } from './updateCheckStore';
export async function runFakeIPCheck() { export async function runFakeIPCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.FAKEIP; const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.FAKEIP;
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -68,7 +68,7 @@ export async function runFakeIPCheck() {
const { state, description } = getMeta(); const { state, description } = getMeta();
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,

View File

@@ -1,11 +1,11 @@
import { updateDiagnosticsCheck } from '../updateDiagnosticsCheck';
import { DIAGNOSTICS_CHECKS_MAP } from './contstants'; import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { RemoteFakeIPMethods, PodkopShellMethods } from '../../../methods'; import { RemoteFakeIPMethods, PodkopShellMethods } from '../../../methods';
import { updateCheckStore } from './updateCheckStore';
export async function runNftCheck() { export async function runNftCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.NFT; const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.NFT;
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -20,7 +20,7 @@ export async function runNftCheck() {
const nftablesChecks = await PodkopShellMethods.checkNftRules(); const nftablesChecks = await PodkopShellMethods.checkNftRules();
if (!nftablesChecks.success) { if (!nftablesChecks.success) {
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -68,7 +68,7 @@ export async function runNftCheck() {
return 'error'; return 'error';
} }
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,

View File

@@ -1,11 +1,11 @@
import { updateDiagnosticsCheck } from '../updateDiagnosticsCheck';
import { DIAGNOSTICS_CHECKS_MAP } from './contstants'; import { DIAGNOSTICS_CHECKS_MAP } from './contstants';
import { PodkopShellMethods } from '../../../methods'; import { PodkopShellMethods } from '../../../methods';
import { updateCheckStore } from './updateCheckStore';
export async function runSingBoxCheck() { export async function runSingBoxCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.SINGBOX; const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.SINGBOX;
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -17,7 +17,7 @@ export async function runSingBoxCheck() {
const singBoxChecks = await PodkopShellMethods.checkSingBox(); const singBoxChecks = await PodkopShellMethods.checkSingBox();
if (!singBoxChecks.success) { if (!singBoxChecks.success) {
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,
@@ -61,7 +61,7 @@ export async function runSingBoxCheck() {
return 'error'; return 'error';
} }
updateDiagnosticsCheck({ updateCheckStore({
order, order,
code, code,
title, title,

View File

@@ -1,6 +1,6 @@
import { IDiagnosticsChecksStoreItem, store } from '../../services'; import { IDiagnosticsChecksStoreItem, store } from '../../../services';
export function updateDiagnosticsCheck( export function updateCheckStore(
check: IDiagnosticsChecksStoreItem, check: IDiagnosticsChecksStoreItem,
minified?: boolean, minified?: boolean,
) { ) {

View File

@@ -1,2 +1,7 @@
export * from './renderDiagnostic'; import { render } from './renderDiagnostic';
export * from './initDiagnosticController'; import { initController } from './initController';
export const DiagnosticTab = {
render,
initController,
};

View File

@@ -1,14 +1,16 @@
import { onMount, preserveScrollForPage } from '../../../helpers'; import { onMount, preserveScrollForPage } from '../../../helpers';
import { renderCheckSection } from './renderCheckSection';
import { runDnsCheck } from './checks/runDnsCheck'; import { runDnsCheck } from './checks/runDnsCheck';
import { runSingBoxCheck } from './checks/runSingBoxCheck'; import { runSingBoxCheck } from './checks/runSingBoxCheck';
import { runNftCheck } from './checks/runNftCheck'; import { runNftCheck } from './checks/runNftCheck';
import { runFakeIPCheck } from './checks/runFakeIPCheck'; import { runFakeIPCheck } from './checks/runFakeIPCheck';
import { renderDiagnosticRunAction } from './renderDiagnosticRunAction';
import { renderAvailableActions } from './renderAvailableActions';
import { renderSystemInfo } from './renderSystemInfo';
import { loadingDiagnosticsChecksStore } from './diagnostic.store'; import { loadingDiagnosticsChecksStore } from './diagnostic.store';
import { store, StoreType } from '../../services'; import { store, StoreType } from '../../services';
import {
renderAvailableActions,
renderCheckSection,
renderRunAction,
renderSystemInfo,
} from './partials';
function renderDiagnosticsChecks() { function renderDiagnosticsChecks() {
console.log('renderDiagnosticsChecks'); console.log('renderDiagnosticsChecks');
@@ -32,7 +34,7 @@ function renderDiagnosticRunActionWidget() {
const { loading } = store.get().diagnosticsRunAction; const { loading } = store.get().diagnosticsRunAction;
const container = document.getElementById('pdk_diagnostic-page-run-check'); const container = document.getElementById('pdk_diagnostic-page-run-check');
const renderedAction = renderDiagnosticRunAction({ const renderedAction = renderRunAction({
loading, loading,
click: () => runChecks(), click: () => runChecks(),
}); });
@@ -124,7 +126,7 @@ async function runChecks() {
} }
} }
export async function initDiagnosticController(): Promise<void> { export async function initController(): Promise<void> {
onMount('diagnostic-status').then(() => { onMount('diagnostic-status').then(() => {
console.log('diagnostic controller initialized.'); console.log('diagnostic controller initialized.');
// Remove old listener // Remove old listener

View File

@@ -0,0 +1,4 @@
export * from './renderAvailableActions';
export * from './renderCheckSection';
export * from './renderRunAction';
export * from './renderSystemInfo';

View File

@@ -7,8 +7,8 @@ import {
renderLoaderCircleIcon24, renderLoaderCircleIcon24,
renderTriangleAlertIcon24, renderTriangleAlertIcon24,
renderXIcon24, renderXIcon24,
} from '../../../icons'; } from '../../../../icons';
import { IDiagnosticsChecksStoreItem } from '../../services'; import { IDiagnosticsChecksStoreItem } from '../../../services';
type IRenderCheckSectionProps = IDiagnosticsChecksStoreItem; type IRenderCheckSectionProps = IDiagnosticsChecksStoreItem;

View File

@@ -3,7 +3,7 @@ interface IRenderDiagnosticRunActionProps {
click: () => void; click: () => void;
} }
export function renderDiagnosticRunAction({ export function renderRunAction({
loading, loading,
click, click,
}: IRenderDiagnosticRunActionProps) { }: IRenderDiagnosticRunActionProps) {

View File

@@ -1,4 +1,4 @@
export function renderDiagnostic() { export function render() {
return E('div', { id: 'diagnostic-status', class: 'pdk_diagnostic-page' }, [ return E('div', { id: 'diagnostic-status', class: 'pdk_diagnostic-page' }, [
E('div', { class: 'pdk_diagnostic-page__left-bar' }, [ E('div', { class: 'pdk_diagnostic-page__left-bar' }, [
E('div', { id: 'pdk_diagnostic-page-run-check' }), E('div', { id: 'pdk_diagnostic-page-run-check' }),

View File

@@ -10,8 +10,8 @@ function createDashboardContent(section) {
const o = section.option(form.DummyValue, '_mount_node'); const o = section.option(form.DummyValue, '_mount_node');
o.rawhtml = true; o.rawhtml = true;
o.cfgvalue = () => { o.cfgvalue = () => {
main.initDashboardController(); main.DashboardTab.initController();
return main.renderDashboard(); return main.DashboardTab.render();
}; };
} }

View File

@@ -10,8 +10,8 @@ function createDiagnosticContent(section) {
const o = section.option(form.DummyValue, '_mount_node'); const o = section.option(form.DummyValue, '_mount_node');
o.rawhtml = true; o.rawhtml = true;
o.cfgvalue = () => { o.cfgvalue = () => {
main.initDiagnosticController(); main.DiagnosticTab.initController();
return main.renderDiagnostic(); return main.DiagnosticTab.render();
}; };
} }

View File

@@ -1716,7 +1716,7 @@ var SocketManager = class _SocketManager {
}; };
var socket = SocketManager.getInstance(); var socket = SocketManager.getInstance();
// src/podkop/tabs/dashboard/renderSections.ts // src/podkop/tabs/dashboard/partials/renderSections.ts
function renderFailedState() { function renderFailedState() {
return E( return E(
"div", "div",
@@ -1823,7 +1823,7 @@ function renderSections(props) {
return renderDefaultState(props); return renderDefaultState(props);
} }
// src/podkop/tabs/dashboard/renderWidget.ts // src/podkop/tabs/dashboard/partials/renderWidget.ts
function renderFailedState2() { function renderFailedState2() {
return E( return E(
"div", "div",
@@ -1885,8 +1885,8 @@ function renderWidget(props) {
return renderDefaultState2(props); return renderDefaultState2(props);
} }
// src/podkop/tabs/dashboard/renderDashboard.ts // src/podkop/tabs/dashboard/render.ts
function renderDashboard() { function render() {
return E( return E(
"div", "div",
{ {
@@ -1953,7 +1953,7 @@ function prettyBytes(n) {
return n + " " + unit; return n + " " + unit;
} }
// src/podkop/tabs/dashboard/initDashboardController.ts // src/podkop/tabs/dashboard/initController.ts
async function fetchDashboardSections() { async function fetchDashboardSections() {
const prev = store.get().sectionsWidget; const prev = store.get().sectionsWidget;
store.set({ store.set({
@@ -2290,7 +2290,7 @@ async function onStoreUpdate(next, prev, diff) {
renderServicesInfoWidget(); renderServicesInfoWidget();
} }
} }
async function initDashboardController() { async function initController() {
onMount("dashboard-status").then(() => { onMount("dashboard-status").then(() => {
store.unsubscribe(onStoreUpdate); store.unsubscribe(onStoreUpdate);
store.reset([ store.reset([
@@ -2307,8 +2307,14 @@ async function initDashboardController() {
}); });
} }
// src/podkop/tabs/dashboard/index.ts
var DashboardTab = {
render,
initController
};
// src/podkop/tabs/diagnostic/renderDiagnostic.ts // src/podkop/tabs/diagnostic/renderDiagnostic.ts
function renderDiagnostic() { function render2() {
return E("div", { id: "diagnostic-status", class: "pdk_diagnostic-page" }, [ return E("div", { id: "diagnostic-status", class: "pdk_diagnostic-page" }, [
E("div", { class: "pdk_diagnostic-page__left-bar" }, [ E("div", { class: "pdk_diagnostic-page__left-bar" }, [
E("div", { id: "pdk_diagnostic-page-run-check" }), E("div", { id: "pdk_diagnostic-page-run-check" }),
@@ -2324,6 +2330,349 @@ function renderDiagnostic() {
]); ]);
} }
// src/podkop/tabs/diagnostic/checks/updateCheckStore.ts
function updateCheckStore(check, minified) {
const diagnosticsChecks = store.get().diagnosticsChecks;
const other = diagnosticsChecks.filter((item) => item.code !== check.code);
const smallCheck = {
...check,
items: check.items.filter((item) => item.state !== "success")
};
const targetCheck = minified ? smallCheck : check;
store.set({
diagnosticsChecks: [...other, targetCheck]
});
}
// src/podkop/tabs/diagnostic/checks/runDnsCheck.ts
async function runDnsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.DNS;
updateCheckStore({
order,
code,
title,
description: _("Checking dns, please wait"),
state: "loading",
items: []
});
const dnsChecks = await PodkopShellMethods.checkDNSAvailable();
if (!dnsChecks.success) {
updateCheckStore({
order,
code,
title,
description: _("Cannot receive DNS checks result"),
state: "error",
items: []
});
throw new Error("DNS checks failed");
}
const data = dnsChecks.data;
const allGood = Boolean(data.local_dns_status) && Boolean(data.bootstrap_dns_status) && Boolean(data.dns_status);
const atLeastOneGood = Boolean(data.local_dns_status) || Boolean(data.bootstrap_dns_status) || Boolean(data.dns_status);
console.log("dnsChecks", dnsChecks);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
updateCheckStore({
order,
code,
title,
description: _("DNS checks passed"),
state: getStatus(),
items: [
...insertIf(
data.dns_type === "doh" || data.dns_type === "dot",
[
{
state: data.bootstrap_dns_status ? "success" : "error",
key: _("Bootsrap DNS"),
value: data.bootstrap_dns_server
}
]
),
{
state: data.dns_status ? "success" : "error",
key: _("Main DNS"),
value: `${data.dns_server} [${data.dns_type}]`
},
{
state: data.local_dns_status ? "success" : "error",
key: _("Local DNS"),
value: ""
}
]
});
if (!atLeastOneGood) {
throw new Error("DNS checks failed");
}
}
// src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts
async function runSingBoxCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.SINGBOX;
updateCheckStore({
order,
code,
title,
description: _("Checking sing-box, please wait"),
state: "loading",
items: []
});
const singBoxChecks = await PodkopShellMethods.checkSingBox();
if (!singBoxChecks.success) {
updateCheckStore({
order,
code,
title,
description: _("Cannot receive Sing-box checks result"),
state: "error",
items: []
});
throw new Error("Sing-box checks failed");
}
const data = singBoxChecks.data;
const allGood = Boolean(data.sing_box_installed) && Boolean(data.sing_box_version_ok) && Boolean(data.sing_box_service_exist) && Boolean(data.sing_box_autostart_disabled) && Boolean(data.sing_box_process_running) && Boolean(data.sing_box_ports_listening);
const atLeastOneGood = Boolean(data.sing_box_installed) || Boolean(data.sing_box_version_ok) || Boolean(data.sing_box_service_exist) || Boolean(data.sing_box_autostart_disabled) || Boolean(data.sing_box_process_running) || Boolean(data.sing_box_ports_listening);
console.log("singBoxChecks", singBoxChecks);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
updateCheckStore({
order,
code,
title,
description: _("Sing-box checks passed"),
state: getStatus(),
items: [
{
state: data.sing_box_installed ? "success" : "error",
key: _("Sing-box installed"),
value: ""
},
{
state: data.sing_box_version_ok ? "success" : "error",
key: _("Sing-box version >= 1.12.4"),
value: ""
},
{
state: data.sing_box_service_exist ? "success" : "error",
key: _("Sing-box service exist"),
value: ""
},
{
state: data.sing_box_autostart_disabled ? "success" : "error",
key: _("Sing-box autostart disabled"),
value: ""
},
{
state: data.sing_box_process_running ? "success" : "error",
key: _("Sing-box process running"),
value: ""
},
{
state: data.sing_box_ports_listening ? "success" : "error",
key: _("Sing-box listening ports"),
value: ""
}
]
});
if (!atLeastOneGood) {
throw new Error("Sing-box checks failed");
}
}
// src/podkop/tabs/diagnostic/checks/runNftCheck.ts
async function runNftCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.NFT;
updateCheckStore({
order,
code,
title,
description: _("Checking nftables, please wait"),
state: "loading",
items: []
});
await RemoteFakeIPMethods.getFakeIpCheck();
await RemoteFakeIPMethods.getIpCheck();
const nftablesChecks = await PodkopShellMethods.checkNftRules();
if (!nftablesChecks.success) {
updateCheckStore({
order,
code,
title,
description: _("Cannot receive nftables checks result"),
state: "error",
items: []
});
throw new Error("Nftables checks failed");
}
const data = nftablesChecks.data;
const allGood = Boolean(data.table_exist) && Boolean(data.rules_mangle_exist) && Boolean(data.rules_mangle_counters) && Boolean(data.rules_mangle_output_exist) && Boolean(data.rules_mangle_output_counters) && Boolean(data.rules_proxy_exist) && Boolean(data.rules_proxy_counters) && Boolean(data.rules_other_mark_exist);
const atLeastOneGood = Boolean(data.table_exist) || Boolean(data.rules_mangle_exist) || Boolean(data.rules_mangle_counters) || Boolean(data.rules_mangle_output_exist) || Boolean(data.rules_mangle_output_counters) || Boolean(data.rules_proxy_exist) || Boolean(data.rules_proxy_counters) || Boolean(data.rules_other_mark_exist);
console.log("nftablesChecks", nftablesChecks);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
updateCheckStore({
order,
code,
title,
description: allGood ? _("Nftables checks passed") : _("Nftables checks partially passed"),
state: getStatus(),
items: [
{
state: data.table_exist ? "success" : "error",
key: _("Table exist"),
value: ""
},
{
state: data.rules_mangle_exist ? "success" : "error",
key: _("Rules mangle exist"),
value: ""
},
{
state: data.rules_mangle_counters ? "success" : "error",
key: _("Rules mangle counters"),
value: ""
},
{
state: data.rules_mangle_output_exist ? "success" : "error",
key: _("Rules mangle output exist"),
value: ""
},
{
state: data.rules_mangle_output_counters ? "success" : "error",
key: _("Rules mangle output counters"),
value: ""
},
{
state: data.rules_proxy_exist ? "success" : "error",
key: _("Rules proxy exist"),
value: ""
},
{
state: data.rules_proxy_counters ? "success" : "error",
key: _("Rules proxy counters"),
value: ""
},
{
state: !data.rules_other_mark_exist ? "success" : "warning",
key: !data.rules_other_mark_exist ? _("No other marking rules found") : _("Additional marking rules found"),
value: ""
}
]
});
if (!atLeastOneGood) {
throw new Error("Nftables checks failed");
}
}
// src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts
async function runFakeIPCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.FAKEIP;
updateCheckStore({
order,
code,
title,
description: _("Checking FakeIP, please wait"),
state: "loading",
items: []
});
const routerFakeIPResponse = await PodkopShellMethods.checkFakeIP();
const checkFakeIPResponse = await RemoteFakeIPMethods.getFakeIpCheck();
const checkIPResponse = await RemoteFakeIPMethods.getIpCheck();
console.log("runFakeIPCheck", {
routerFakeIPResponse,
checkFakeIPResponse,
checkIPResponse
});
const checks = {
router: routerFakeIPResponse.success && routerFakeIPResponse.data.fakeip,
browserFakeIP: checkFakeIPResponse.success && checkFakeIPResponse.data.fakeip,
differentIP: checkFakeIPResponse.success && checkIPResponse.success && checkFakeIPResponse.data.IP !== checkIPResponse.data.IP
};
console.log("checks", checks);
const allGood = checks.router || checks.browserFakeIP || checks.differentIP;
const atLeastOneGood = checks.router && checks.browserFakeIP && checks.differentIP;
function getMeta() {
if (allGood) {
return {
state: "success",
description: _("FakeIP checks passed")
};
}
if (atLeastOneGood) {
return {
state: "warning",
description: _("FakeIP checks partially passed")
};
}
return {
state: "error",
description: _("FakeIP checks failed")
};
}
const { state, description } = getMeta();
updateCheckStore({
order,
code,
title,
description,
state,
items: [
{
state: checks.router ? "success" : "warning",
key: checks.router ? _("Router DNS is routed through sing-box") : _("Router DNS is not routed through sing-box"),
value: ""
},
{
state: checks.browserFakeIP ? "success" : "error",
key: checks.browserFakeIP ? _("Browser is using FakeIP correctly") : _("Browser is not using FakeIP"),
value: ""
},
...insertIf(checks.browserFakeIP, [
{
state: checks.differentIP ? "success" : "error",
key: checks.differentIP ? _("Proxy traffic is routed via FakeIP") : _("Proxy traffic is not routed via FakeIP"),
value: ""
}
])
]
});
}
// src/podkop/tabs/diagnostic/partials/renderAvailableActions.ts
function renderAvailableActions() {
return E("div", { class: "pdk_diagnostic-page__right-bar__actions" }, [
E("b", {}, "Available actions"),
E("button", { class: "btn" }, "Restart podkop"),
E("button", { class: "btn" }, "Stop podkop"),
E("button", { class: "btn" }, "Disable podkop"),
E("button", { class: "btn" }, "Get global check"),
E("button", { class: "btn" }, "View logs"),
E("button", { class: "btn" }, "Show sing-box config")
]);
}
// src/icons/renderLoaderCircleIcon24.ts // src/icons/renderLoaderCircleIcon24.ts
function renderLoaderCircleIcon24() { function renderLoaderCircleIcon24() {
const NS = "http://www.w3.org/2000/svg"; const NS = "http://www.w3.org/2000/svg";
@@ -2560,7 +2909,7 @@ function renderTriangleAlertIcon24() {
); );
} }
// src/podkop/tabs/diagnostic/renderCheckSection.ts // src/podkop/tabs/diagnostic/partials/renderCheckSection.ts
function renderCheckSummary(items) { function renderCheckSummary(items) {
if (!items.length) { if (!items.length) {
return E("div", {}, ""); return E("div", {}, "");
@@ -2715,338 +3064,8 @@ function renderCheckSection(props) {
return E("div", {}, "Not implement yet"); return E("div", {}, "Not implement yet");
} }
// src/podkop/tabs/diagnostic/updateDiagnosticsCheck.ts // src/podkop/tabs/diagnostic/partials/renderRunAction.ts
function updateDiagnosticsCheck(check, minified) { function renderRunAction({
const diagnosticsChecks = store.get().diagnosticsChecks;
const other = diagnosticsChecks.filter((item) => item.code !== check.code);
const smallCheck = {
...check,
items: check.items.filter((item) => item.state !== "success")
};
const targetCheck = minified ? smallCheck : check;
store.set({
diagnosticsChecks: [...other, targetCheck]
});
}
// src/podkop/tabs/diagnostic/checks/runDnsCheck.ts
async function runDnsCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.DNS;
updateDiagnosticsCheck({
order,
code,
title,
description: _("Checking dns, please wait"),
state: "loading",
items: []
});
const dnsChecks = await PodkopShellMethods.checkDNSAvailable();
if (!dnsChecks.success) {
updateDiagnosticsCheck({
order,
code,
title,
description: _("Cannot receive DNS checks result"),
state: "error",
items: []
});
throw new Error("DNS checks failed");
}
const data = dnsChecks.data;
const allGood = Boolean(data.local_dns_status) && Boolean(data.bootstrap_dns_status) && Boolean(data.dns_status);
const atLeastOneGood = Boolean(data.local_dns_status) || Boolean(data.bootstrap_dns_status) || Boolean(data.dns_status);
console.log("dnsChecks", dnsChecks);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
updateDiagnosticsCheck({
order,
code,
title,
description: _("DNS checks passed"),
state: getStatus(),
items: [
...insertIf(
data.dns_type === "doh" || data.dns_type === "dot",
[
{
state: data.bootstrap_dns_status ? "success" : "error",
key: _("Bootsrap DNS"),
value: data.bootstrap_dns_server
}
]
),
{
state: data.dns_status ? "success" : "error",
key: _("Main DNS"),
value: `${data.dns_server} [${data.dns_type}]`
},
{
state: data.local_dns_status ? "success" : "error",
key: _("Local DNS"),
value: ""
}
]
});
if (!atLeastOneGood) {
throw new Error("DNS checks failed");
}
}
// src/podkop/tabs/diagnostic/checks/runSingBoxCheck.ts
async function runSingBoxCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.SINGBOX;
updateDiagnosticsCheck({
order,
code,
title,
description: _("Checking sing-box, please wait"),
state: "loading",
items: []
});
const singBoxChecks = await PodkopShellMethods.checkSingBox();
if (!singBoxChecks.success) {
updateDiagnosticsCheck({
order,
code,
title,
description: _("Cannot receive Sing-box checks result"),
state: "error",
items: []
});
throw new Error("Sing-box checks failed");
}
const data = singBoxChecks.data;
const allGood = Boolean(data.sing_box_installed) && Boolean(data.sing_box_version_ok) && Boolean(data.sing_box_service_exist) && Boolean(data.sing_box_autostart_disabled) && Boolean(data.sing_box_process_running) && Boolean(data.sing_box_ports_listening);
const atLeastOneGood = Boolean(data.sing_box_installed) || Boolean(data.sing_box_version_ok) || Boolean(data.sing_box_service_exist) || Boolean(data.sing_box_autostart_disabled) || Boolean(data.sing_box_process_running) || Boolean(data.sing_box_ports_listening);
console.log("singBoxChecks", singBoxChecks);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
updateDiagnosticsCheck({
order,
code,
title,
description: _("Sing-box checks passed"),
state: getStatus(),
items: [
{
state: data.sing_box_installed ? "success" : "error",
key: _("Sing-box installed"),
value: ""
},
{
state: data.sing_box_version_ok ? "success" : "error",
key: _("Sing-box version >= 1.12.4"),
value: ""
},
{
state: data.sing_box_service_exist ? "success" : "error",
key: _("Sing-box service exist"),
value: ""
},
{
state: data.sing_box_autostart_disabled ? "success" : "error",
key: _("Sing-box autostart disabled"),
value: ""
},
{
state: data.sing_box_process_running ? "success" : "error",
key: _("Sing-box process running"),
value: ""
},
{
state: data.sing_box_ports_listening ? "success" : "error",
key: _("Sing-box listening ports"),
value: ""
}
]
});
if (!atLeastOneGood) {
throw new Error("Sing-box checks failed");
}
}
// src/podkop/tabs/diagnostic/checks/runNftCheck.ts
async function runNftCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.NFT;
updateDiagnosticsCheck({
order,
code,
title,
description: _("Checking nftables, please wait"),
state: "loading",
items: []
});
await RemoteFakeIPMethods.getFakeIpCheck();
await RemoteFakeIPMethods.getIpCheck();
const nftablesChecks = await PodkopShellMethods.checkNftRules();
if (!nftablesChecks.success) {
updateDiagnosticsCheck({
order,
code,
title,
description: _("Cannot receive nftables checks result"),
state: "error",
items: []
});
throw new Error("Nftables checks failed");
}
const data = nftablesChecks.data;
const allGood = Boolean(data.table_exist) && Boolean(data.rules_mangle_exist) && Boolean(data.rules_mangle_counters) && Boolean(data.rules_mangle_output_exist) && Boolean(data.rules_mangle_output_counters) && Boolean(data.rules_proxy_exist) && Boolean(data.rules_proxy_counters) && Boolean(data.rules_other_mark_exist);
const atLeastOneGood = Boolean(data.table_exist) || Boolean(data.rules_mangle_exist) || Boolean(data.rules_mangle_counters) || Boolean(data.rules_mangle_output_exist) || Boolean(data.rules_mangle_output_counters) || Boolean(data.rules_proxy_exist) || Boolean(data.rules_proxy_counters) || Boolean(data.rules_other_mark_exist);
console.log("nftablesChecks", nftablesChecks);
function getStatus() {
if (allGood) {
return "success";
}
if (atLeastOneGood) {
return "warning";
}
return "error";
}
updateDiagnosticsCheck({
order,
code,
title,
description: allGood ? _("Nftables checks passed") : _("Nftables checks partially passed"),
state: getStatus(),
items: [
{
state: data.table_exist ? "success" : "error",
key: _("Table exist"),
value: ""
},
{
state: data.rules_mangle_exist ? "success" : "error",
key: _("Rules mangle exist"),
value: ""
},
{
state: data.rules_mangle_counters ? "success" : "error",
key: _("Rules mangle counters"),
value: ""
},
{
state: data.rules_mangle_output_exist ? "success" : "error",
key: _("Rules mangle output exist"),
value: ""
},
{
state: data.rules_mangle_output_counters ? "success" : "error",
key: _("Rules mangle output counters"),
value: ""
},
{
state: data.rules_proxy_exist ? "success" : "error",
key: _("Rules proxy exist"),
value: ""
},
{
state: data.rules_proxy_counters ? "success" : "error",
key: _("Rules proxy counters"),
value: ""
},
{
state: !data.rules_other_mark_exist ? "success" : "warning",
key: !data.rules_other_mark_exist ? _("No other marking rules found") : _("Additional marking rules found"),
value: ""
}
]
});
if (!atLeastOneGood) {
throw new Error("Nftables checks failed");
}
}
// src/podkop/tabs/diagnostic/checks/runFakeIPCheck.ts
async function runFakeIPCheck() {
const { order, title, code } = DIAGNOSTICS_CHECKS_MAP.FAKEIP;
updateDiagnosticsCheck({
order,
code,
title,
description: _("Checking FakeIP, please wait"),
state: "loading",
items: []
});
const routerFakeIPResponse = await PodkopShellMethods.checkFakeIP();
const checkFakeIPResponse = await RemoteFakeIPMethods.getFakeIpCheck();
const checkIPResponse = await RemoteFakeIPMethods.getIpCheck();
console.log("runFakeIPCheck", {
routerFakeIPResponse,
checkFakeIPResponse,
checkIPResponse
});
const checks = {
router: routerFakeIPResponse.success && routerFakeIPResponse.data.fakeip,
browserFakeIP: checkFakeIPResponse.success && checkFakeIPResponse.data.fakeip,
differentIP: checkFakeIPResponse.success && checkIPResponse.success && checkFakeIPResponse.data.IP !== checkIPResponse.data.IP
};
console.log("checks", checks);
const allGood = checks.router || checks.browserFakeIP || checks.differentIP;
const atLeastOneGood = checks.router && checks.browserFakeIP && checks.differentIP;
function getMeta() {
if (allGood) {
return {
state: "success",
description: _("FakeIP checks passed")
};
}
if (atLeastOneGood) {
return {
state: "warning",
description: _("FakeIP checks partially passed")
};
}
return {
state: "error",
description: _("FakeIP checks failed")
};
}
const { state, description } = getMeta();
updateDiagnosticsCheck({
order,
code,
title,
description,
state,
items: [
{
state: checks.router ? "success" : "warning",
key: checks.router ? _("Router DNS is routed through sing-box") : _("Router DNS is not routed through sing-box"),
value: ""
},
{
state: checks.browserFakeIP ? "success" : "error",
key: checks.browserFakeIP ? _("Browser is using FakeIP correctly") : _("Browser is not using FakeIP"),
value: ""
},
...insertIf(checks.browserFakeIP, [
{
state: checks.differentIP ? "success" : "error",
key: checks.differentIP ? _("Proxy traffic is routed via FakeIP") : _("Proxy traffic is not routed via FakeIP"),
value: ""
}
])
]
});
}
// src/podkop/tabs/diagnostic/renderDiagnosticRunAction.ts
function renderDiagnosticRunAction({
loading, loading,
click click
}) { }) {
@@ -3059,20 +3078,7 @@ function renderDiagnosticRunAction({
]); ]);
} }
// src/podkop/tabs/diagnostic/renderAvailableActions.ts // src/podkop/tabs/diagnostic/partials/renderSystemInfo.ts
function renderAvailableActions() {
return E("div", { class: "pdk_diagnostic-page__right-bar__actions" }, [
E("b", {}, "Available actions"),
E("button", { class: "btn" }, "Restart podkop"),
E("button", { class: "btn" }, "Stop podkop"),
E("button", { class: "btn" }, "Disable podkop"),
E("button", { class: "btn" }, "Get global check"),
E("button", { class: "btn" }, "View logs"),
E("button", { class: "btn" }, "Show sing-box config")
]);
}
// src/podkop/tabs/diagnostic/renderSystemInfo.ts
function renderSystemInfo({ items }) { function renderSystemInfo({ items }) {
return E("div", { class: "pdk_diagnostic-page__right-bar__system-info" }, [ return E("div", { class: "pdk_diagnostic-page__right-bar__system-info" }, [
E( E(
@@ -3089,7 +3095,7 @@ function renderSystemInfo({ items }) {
]); ]);
} }
// src/podkop/tabs/diagnostic/initDiagnosticController.ts // src/podkop/tabs/diagnostic/initController.ts
function renderDiagnosticsChecks() { function renderDiagnosticsChecks() {
console.log("renderDiagnosticsChecks"); console.log("renderDiagnosticsChecks");
const diagnosticsChecks = store.get().diagnosticsChecks.sort((a, b) => a.order - b.order); const diagnosticsChecks = store.get().diagnosticsChecks.sort((a, b) => a.order - b.order);
@@ -3105,7 +3111,7 @@ function renderDiagnosticRunActionWidget() {
console.log("renderDiagnosticRunActionWidget"); console.log("renderDiagnosticRunActionWidget");
const { loading } = store.get().diagnosticsRunAction; const { loading } = store.get().diagnosticsRunAction;
const container = document.getElementById("pdk_diagnostic-page-run-check"); const container = document.getElementById("pdk_diagnostic-page-run-check");
const renderedAction = renderDiagnosticRunAction({ const renderedAction = renderRunAction({
loading, loading,
click: () => runChecks() click: () => runChecks()
}); });
@@ -3176,7 +3182,7 @@ async function runChecks() {
store.set({ diagnosticsRunAction: { loading: false } }); store.set({ diagnosticsRunAction: { loading: false } });
} }
} }
async function initDiagnosticController() { async function initController2() {
onMount("diagnostic-status").then(() => { onMount("diagnostic-status").then(() => {
console.log("diagnostic controller initialized."); console.log("diagnostic controller initialized.");
store.unsubscribe(onStoreUpdate2); store.unsubscribe(onStoreUpdate2);
@@ -3187,6 +3193,12 @@ async function initDiagnosticController() {
renderDiagnosticSystemInfoWidget(); renderDiagnosticSystemInfoWidget();
}); });
} }
// src/podkop/tabs/diagnostic/index.ts
var DiagnosticTab = {
render: render2,
initController: initController2
};
return baseclass.extend({ return baseclass.extend({
ALLOWED_WITH_RUSSIA_INSIDE, ALLOWED_WITH_RUSSIA_INSIDE,
BOOTSTRAP_DNS_SERVER_OPTIONS, BOOTSTRAP_DNS_SERVER_OPTIONS,
@@ -3200,6 +3212,8 @@ return baseclass.extend({
DIAGNOSTICS_UPDATE_INTERVAL, DIAGNOSTICS_UPDATE_INTERVAL,
DNS_SERVER_OPTIONS, DNS_SERVER_OPTIONS,
DOMAIN_LIST_OPTIONS, DOMAIN_LIST_OPTIONS,
DashboardTab,
DiagnosticTab,
ERROR_POLL_INTERVAL, ERROR_POLL_INTERVAL,
FAKEIP_CHECK_DOMAIN, FAKEIP_CHECK_DOMAIN,
FETCH_TIMEOUT, FETCH_TIMEOUT,
@@ -3220,8 +3234,6 @@ return baseclass.extend({
getClashUIUrl, getClashUIUrl,
getClashWsUrl, getClashWsUrl,
getProxyUrlName, getProxyUrlName,
initDashboardController,
initDiagnosticController,
injectGlobalStyles, injectGlobalStyles,
insertIf, insertIf,
insertIfObj, insertIfObj,
@@ -3230,8 +3242,6 @@ return baseclass.extend({
parseQueryString, parseQueryString,
parseValueList, parseValueList,
preserveScrollForPage, preserveScrollForPage,
renderDashboard,
renderDiagnostic,
socket, socket,
splitProxyString, splitProxyString,
store, store,