Files
NeoTachyon/fe-app-podkop/src/podkop/tabs/diagnostic/initController.ts
T

417 lines
10 KiB
TypeScript

import { onMount, preserveScrollForPage } from '../../../helpers';
import { runDnsCheck } from './checks/runDnsCheck';
import { runSingBoxCheck } from './checks/runSingBoxCheck';
import { runNftCheck } from './checks/runNftCheck';
import { runFakeIPCheck } from './checks/runFakeIPCheck';
import { loadingDiagnosticsChecksStore } from './diagnostic.store';
import { store, StoreType } from '../../services';
import {
IRenderSystemInfoRow,
renderAvailableActions,
renderCheckSection,
renderRunAction,
renderSystemInfo,
} from './partials';
import { PodkopShellMethods } from '../../methods';
import { fetchServicesInfo } from '../../fetchers';
import { normalizeCompiledVersion } from '../../../helpers/normalizeCompiledVersion';
async function fetchSystemInfo() {
const systemInfo = await PodkopShellMethods.getSystemInfo();
if (systemInfo.success) {
store.set({
diagnosticsSystemInfo: {
loading: false,
...systemInfo.data,
},
});
} else {
store.set({
diagnosticsSystemInfo: {
loading: false,
podkop_version: 'unknown',
podkop_latest_version: 'unknown',
luci_app_version: 'unknown',
sing_box_version: 'unknown',
openwrt_version: 'unknown',
device_model: 'unknown',
},
});
}
}
function renderDiagnosticsChecks() {
console.log('renderDiagnosticsChecks');
const diagnosticsChecks = store
.get()
.diagnosticsChecks.sort((a, b) => a.order - b.order);
const container = document.getElementById('pdk_diagnostic-page-checks');
const renderedDiagnosticsChecks = diagnosticsChecks.map((check) =>
renderCheckSection(check),
);
return preserveScrollForPage(() => {
container!.replaceChildren(...renderedDiagnosticsChecks);
});
}
function renderDiagnosticRunActionWidget() {
console.log('renderDiagnosticRunActionWidget');
const { loading } = store.get().diagnosticsRunAction;
const container = document.getElementById('pdk_diagnostic-page-run-check');
const renderedAction = renderRunAction({
loading,
click: () => runChecks(),
});
return preserveScrollForPage(() => {
container!.replaceChildren(renderedAction);
});
}
async function handleRestart() {
const diagnosticsActions = store.get().diagnosticsActions;
store.set({
diagnosticsActions: {
...diagnosticsActions,
restart: { loading: true },
},
});
try {
await PodkopShellMethods.restart();
} catch (e) {
console.log('handleRestart - e', e);
} finally {
setTimeout(async () => {
await fetchServicesInfo();
store.set({
diagnosticsActions: {
...diagnosticsActions,
restart: { loading: false },
},
});
store.reset(['diagnosticsChecks']);
}, 5000);
}
}
async function handleStop() {
const diagnosticsActions = store.get().diagnosticsActions;
store.set({
diagnosticsActions: {
...diagnosticsActions,
stop: { loading: true },
},
});
try {
await PodkopShellMethods.stop();
} catch (e) {
console.log('handleStop - e', e);
} finally {
await fetchServicesInfo();
store.set({
diagnosticsActions: {
...diagnosticsActions,
stop: { loading: false },
},
});
store.reset(['diagnosticsChecks']);
}
}
async function handleStart() {
const diagnosticsActions = store.get().diagnosticsActions;
store.set({
diagnosticsActions: {
...diagnosticsActions,
start: { loading: true },
},
});
try {
await PodkopShellMethods.start();
} catch (e) {
console.log('handleStart - e', e);
} finally {
setTimeout(async () => {
await fetchServicesInfo();
store.set({
diagnosticsActions: {
...diagnosticsActions,
start: { loading: false },
},
});
store.reset(['diagnosticsChecks']);
}, 5000);
}
}
async function handleEnable() {
const diagnosticsActions = store.get().diagnosticsActions;
store.set({
diagnosticsActions: {
...diagnosticsActions,
enable: { loading: true },
},
});
try {
await PodkopShellMethods.enable();
} catch (e) {
console.log('handleEnable - e', e);
} finally {
await fetchServicesInfo();
store.set({
diagnosticsActions: {
...diagnosticsActions,
enable: { loading: false },
},
});
}
}
async function handleDisable() {
const diagnosticsActions = store.get().diagnosticsActions;
store.set({
diagnosticsActions: {
...diagnosticsActions,
disable: { loading: true },
},
});
try {
await PodkopShellMethods.disable();
} catch (e) {
console.log('handleDisable - e', e);
} finally {
await fetchServicesInfo();
store.set({
diagnosticsActions: {
...diagnosticsActions,
disable: { loading: false },
},
});
}
}
function renderDiagnosticAvailableActionsWidget() {
const diagnosticsActions = store.get().diagnosticsActions;
const servicesInfoWidget = store.get().servicesInfoWidget;
console.log('renderDiagnosticActionsWidget');
const podkopEnabled = Boolean(servicesInfoWidget.data.podkop);
const singBoxRunning = Boolean(servicesInfoWidget.data.singbox);
const atLeastOneServiceCommandLoading =
servicesInfoWidget.loading ||
diagnosticsActions.restart.loading ||
diagnosticsActions.start.loading ||
diagnosticsActions.stop.loading;
const container = document.getElementById('pdk_diagnostic-page-actions');
const renderedActions = renderAvailableActions({
restart: {
loading: diagnosticsActions.restart.loading,
visible: true,
onClick: handleRestart,
disabled: atLeastOneServiceCommandLoading,
},
start: {
loading: diagnosticsActions.start.loading,
visible: !singBoxRunning,
onClick: handleStart,
disabled: atLeastOneServiceCommandLoading,
},
stop: {
loading: diagnosticsActions.stop.loading,
visible: singBoxRunning,
onClick: handleStop,
disabled: atLeastOneServiceCommandLoading,
},
enable: {
loading: diagnosticsActions.enable.loading,
visible: !podkopEnabled,
onClick: handleEnable,
disabled: atLeastOneServiceCommandLoading,
},
disable: {
loading: diagnosticsActions.disable.loading,
visible: podkopEnabled,
onClick: handleDisable,
disabled: atLeastOneServiceCommandLoading,
},
globalCheck: {
loading: diagnosticsActions.globalCheck.loading,
visible: true,
onClick: () => {},
disabled: atLeastOneServiceCommandLoading,
},
viewLogs: {
loading: diagnosticsActions.viewLogs.loading,
visible: true,
onClick: () => {},
disabled: atLeastOneServiceCommandLoading,
},
showSingBoxConfig: {
loading: diagnosticsActions.showSingBoxConfig.loading,
visible: true,
onClick: () => {},
disabled: atLeastOneServiceCommandLoading,
},
});
return preserveScrollForPage(() => {
container!.replaceChildren(renderedActions);
});
}
function renderDiagnosticSystemInfoWidget() {
console.log('renderDiagnosticSystemInfoWidget');
const diagnosticsSystemInfo = store.get().diagnosticsSystemInfo;
const container = document.getElementById('pdk_diagnostic-page-system-info');
function getPodkopVersionRow(): IRenderSystemInfoRow {
const loading = diagnosticsSystemInfo.loading;
const unknown = diagnosticsSystemInfo.podkop_version === 'unknown';
const hasActualVersion = Boolean(
diagnosticsSystemInfo.podkop_latest_version,
);
const version = normalizeCompiledVersion(
diagnosticsSystemInfo.podkop_version,
);
const isDevVersion = version === 'dev';
if (loading || unknown || !hasActualVersion || isDevVersion) {
return {
key: 'Podkop',
value: version,
};
}
if (version !== diagnosticsSystemInfo.podkop_latest_version) {
return {
key: 'Podkop',
value: version,
tag: {
label: 'Outdated',
kind: 'warning',
},
};
}
return {
key: 'Podkop',
value: version,
tag: {
label: 'Latest',
kind: 'success',
},
};
}
const renderedSystemInfo = renderSystemInfo({
items: [
getPodkopVersionRow(),
{
key: 'Luci App',
value: normalizeCompiledVersion(diagnosticsSystemInfo.luci_app_version),
},
{
key: 'Sing-box',
value: diagnosticsSystemInfo.sing_box_version,
},
{
key: 'OS',
value: diagnosticsSystemInfo.openwrt_version,
},
{
key: 'Device',
value: diagnosticsSystemInfo.device_model,
},
],
});
return preserveScrollForPage(() => {
container!.replaceChildren(renderedSystemInfo);
});
}
async function onStoreUpdate(
next: StoreType,
prev: StoreType,
diff: Partial<StoreType>,
) {
if (diff.diagnosticsChecks) {
renderDiagnosticsChecks();
}
if (diff.diagnosticsRunAction) {
renderDiagnosticRunActionWidget();
}
if (diff.diagnosticsActions || diff.servicesInfoWidget) {
renderDiagnosticAvailableActionsWidget();
}
if (diff.diagnosticsSystemInfo) {
renderDiagnosticSystemInfoWidget();
}
}
async function runChecks() {
try {
store.set({
diagnosticsRunAction: { loading: true },
diagnosticsChecks: loadingDiagnosticsChecksStore.diagnosticsChecks,
});
await runDnsCheck();
await runSingBoxCheck();
await runNftCheck();
await runFakeIPCheck();
} catch (e) {
console.log('runChecks - e', e);
} finally {
store.set({ diagnosticsRunAction: { loading: false } });
}
}
export async function initController(): Promise<void> {
onMount('diagnostic-status').then(() => {
console.log('diagnostic controller initialized.');
// Remove old listener
store.unsubscribe(onStoreUpdate);
// Add new listener
store.subscribe(onStoreUpdate);
// Initial checks render
renderDiagnosticsChecks();
// Initial run checks action render
renderDiagnosticRunActionWidget();
// Initial available actions render
renderDiagnosticAvailableActionsWidget();
// Initial system info render
renderDiagnosticSystemInfoWidget();
// Initial services info fetch
fetchServicesInfo();
// Initial system info fetch
fetchSystemInfo();
});
}