mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-08 20:46:50 +03:00
236 lines
6.3 KiB
TypeScript
236 lines
6.3 KiB
TypeScript
import {
|
|
getDashboardSections,
|
|
getPodkopStatus,
|
|
getSingboxStatus,
|
|
} from '../podkop/methods';
|
|
import { renderOutboundGroup } from './renderer/renderOutboundGroup';
|
|
import { getClashWsUrl, onMount } from '../helpers';
|
|
import { store } from '../store';
|
|
import { socket } from '../socket';
|
|
import { renderDashboardWidget } from './renderer/renderWidget';
|
|
import { prettyBytes } from '../helpers/prettyBytes';
|
|
import {
|
|
triggerLatencyGroupTest,
|
|
triggerLatencyProxyTest,
|
|
triggerProxySelector,
|
|
} from '../clash';
|
|
|
|
// Fetchers
|
|
|
|
async function fetchDashboardSections() {
|
|
const sections = await getDashboardSections();
|
|
|
|
store.set({ sections });
|
|
}
|
|
|
|
async function fetchServicesInfo() {
|
|
const podkop = await getPodkopStatus();
|
|
const singbox = await getSingboxStatus();
|
|
|
|
console.log('podkop', podkop);
|
|
console.log('singbox', singbox);
|
|
store.set({
|
|
services: {
|
|
singbox: singbox.running,
|
|
podkop: podkop.enabled,
|
|
},
|
|
});
|
|
}
|
|
|
|
async function connectToClashSockets() {
|
|
socket.subscribe(`${getClashWsUrl()}/traffic?token=`, (msg) => {
|
|
const parsedMsg = JSON.parse(msg);
|
|
|
|
store.set({
|
|
traffic: { up: parsedMsg.up, down: parsedMsg.down },
|
|
});
|
|
});
|
|
|
|
socket.subscribe(`${getClashWsUrl()}/connections?token=`, (msg) => {
|
|
const parsedMsg = JSON.parse(msg);
|
|
|
|
store.set({
|
|
connections: {
|
|
connections: parsedMsg.connections,
|
|
downloadTotal: parsedMsg.downloadTotal,
|
|
uploadTotal: parsedMsg.uploadTotal,
|
|
memory: parsedMsg.memory,
|
|
},
|
|
});
|
|
});
|
|
|
|
socket.subscribe(`${getClashWsUrl()}/memory?token=`, (msg) => {
|
|
store.set({
|
|
memory: { inuse: msg.inuse, oslimit: msg.oslimit },
|
|
});
|
|
});
|
|
}
|
|
|
|
// Handlers
|
|
|
|
async function handleChooseOutbound(selector: string, tag: string) {
|
|
await triggerProxySelector(selector, tag);
|
|
await fetchDashboardSections();
|
|
}
|
|
|
|
async function handleTestGroupLatency(tag: string) {
|
|
await triggerLatencyGroupTest(tag);
|
|
await fetchDashboardSections();
|
|
}
|
|
|
|
async function handleTestProxyLatency(tag: string) {
|
|
await triggerLatencyProxyTest(tag);
|
|
await fetchDashboardSections();
|
|
}
|
|
|
|
function replaceTestLatencyButtonsWithSkeleton () {
|
|
document.querySelectorAll('.dashboard-sections-grid-item-test-latency').forEach(el => {
|
|
const newDiv = document.createElement('div');
|
|
newDiv.className = 'skeleton';
|
|
newDiv.style.width = '99px';
|
|
newDiv.style.height = '28px';
|
|
el.replaceWith(newDiv);
|
|
});
|
|
}
|
|
|
|
// Renderer
|
|
|
|
async function renderDashboardSections() {
|
|
const sections = store.get().sections;
|
|
console.log('render dashboard sections group');
|
|
const container = document.getElementById('dashboard-sections-grid');
|
|
const renderedOutboundGroups = sections.map((section) =>
|
|
renderOutboundGroup({
|
|
section,
|
|
onTestLatency: (tag) => {
|
|
replaceTestLatencyButtonsWithSkeleton();
|
|
|
|
if (section.withTagSelect) {
|
|
return handleTestGroupLatency(tag);
|
|
}
|
|
|
|
return handleTestProxyLatency(tag);
|
|
},
|
|
onChooseOutbound: (selector, tag) => {
|
|
handleChooseOutbound(selector, tag);
|
|
},
|
|
}),
|
|
);
|
|
|
|
container!.replaceChildren(...renderedOutboundGroups);
|
|
}
|
|
|
|
async function renderTrafficWidget() {
|
|
const traffic = store.get().traffic;
|
|
console.log('render dashboard traffic widget');
|
|
const container = document.getElementById('dashboard-widget-traffic');
|
|
const renderedWidget = renderDashboardWidget({
|
|
title: 'Traffic',
|
|
items: [
|
|
{ key: 'Uplink', value: `${prettyBytes(traffic.up)}/s` },
|
|
{ key: 'Downlink', value: `${prettyBytes(traffic.down)}/s` },
|
|
],
|
|
});
|
|
|
|
container!.replaceChildren(renderedWidget);
|
|
}
|
|
|
|
async function renderTrafficTotalWidget() {
|
|
const connections = store.get().connections;
|
|
console.log('render dashboard traffic total widget');
|
|
const container = document.getElementById('dashboard-widget-traffic-total');
|
|
const renderedWidget = renderDashboardWidget({
|
|
title: 'Traffic Total',
|
|
items: [
|
|
{ key: 'Uplink', value: String(prettyBytes(connections.uploadTotal)) },
|
|
{
|
|
key: 'Downlink',
|
|
value: String(prettyBytes(connections.downloadTotal)),
|
|
},
|
|
],
|
|
});
|
|
|
|
container!.replaceChildren(renderedWidget);
|
|
}
|
|
|
|
async function renderSystemInfoWidget() {
|
|
const connections = store.get().connections;
|
|
console.log('render dashboard system info widget');
|
|
const container = document.getElementById('dashboard-widget-system-info');
|
|
const renderedWidget = renderDashboardWidget({
|
|
title: 'System info',
|
|
items: [
|
|
{
|
|
key: 'Active Connections',
|
|
value: String(connections.connections.length),
|
|
},
|
|
{ key: 'Memory Usage', value: String(prettyBytes(connections.memory)) },
|
|
],
|
|
});
|
|
|
|
container!.replaceChildren(renderedWidget);
|
|
}
|
|
|
|
async function renderServiceInfoWidget() {
|
|
const services = store.get().services;
|
|
console.log('render dashboard service info widget');
|
|
const container = document.getElementById('dashboard-widget-service-info');
|
|
const renderedWidget = renderDashboardWidget({
|
|
title: 'Services info',
|
|
items: [
|
|
{
|
|
key: 'Podkop',
|
|
value: services.podkop ? '✔ Enabled' : '✘ Disabled',
|
|
attributes: {
|
|
class: services.podkop
|
|
? 'pdk_dashboard-page__widgets-section__item__row--success'
|
|
: 'pdk_dashboard-page__widgets-section__item__row--error',
|
|
},
|
|
},
|
|
{
|
|
key: 'Sing-box',
|
|
value: services.singbox ? '✔ Running' : '✘ Stopped',
|
|
attributes: {
|
|
class: services.singbox
|
|
? 'pdk_dashboard-page__widgets-section__item__row--success'
|
|
: 'pdk_dashboard-page__widgets-section__item__row--error',
|
|
},
|
|
},
|
|
],
|
|
});
|
|
|
|
container!.replaceChildren(renderedWidget);
|
|
}
|
|
|
|
export async function initDashboardController(): Promise<void> {
|
|
store.subscribe((next, prev, diff) => {
|
|
console.log('Store changed', { prev, next, diff });
|
|
|
|
// Update sections render
|
|
if (diff?.sections) {
|
|
renderDashboardSections();
|
|
}
|
|
|
|
if (diff?.traffic) {
|
|
renderTrafficWidget();
|
|
}
|
|
|
|
if (diff?.connections) {
|
|
renderTrafficTotalWidget();
|
|
renderSystemInfoWidget();
|
|
}
|
|
|
|
if (diff?.services) {
|
|
renderServiceInfoWidget();
|
|
}
|
|
});
|
|
|
|
onMount('dashboard-status').then(() => {
|
|
console.log('Mounting dashboard');
|
|
// Initial sections fetch
|
|
fetchDashboardSections();
|
|
fetchServicesInfo();
|
|
connectToClashSockets();
|
|
});
|
|
}
|