Expand README with architecture and setup details
This commit is contained in:
2162
src/app/App.tsx
Normal file
2162
src/app/App.tsx
Normal file
File diff suppressed because it is too large
Load Diff
83
src/app/readiness.ts
Normal file
83
src/app/readiness.ts
Normal file
@@ -0,0 +1,83 @@
|
||||
export type RouteMode = 'external' | 'local-singbox';
|
||||
|
||||
export interface ApplyReadinessInput {
|
||||
routeMode: RouteMode;
|
||||
appCount: number;
|
||||
proxiFyreInstalled: boolean;
|
||||
singBoxInstalled: boolean;
|
||||
selectedServerTag?: string;
|
||||
externalProxyValue: string;
|
||||
externalProxyError?: string | null;
|
||||
busy: boolean;
|
||||
}
|
||||
|
||||
export interface ApplyReadiness {
|
||||
ready: boolean;
|
||||
title?: string;
|
||||
text?: string;
|
||||
}
|
||||
|
||||
export function getApplyReadiness(input: ApplyReadinessInput): ApplyReadiness {
|
||||
if (input.busy) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'Операция уже выполняется',
|
||||
text: 'Дождись завершения текущего действия перед повторным применением.',
|
||||
};
|
||||
}
|
||||
|
||||
if (!input.proxiFyreInstalled) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'ProxiFyre не установлен',
|
||||
text: 'Установи ProxiFyre, чтобы маршрутизировать выбранные приложения.',
|
||||
};
|
||||
}
|
||||
|
||||
if (input.appCount < 1) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'Нет приложений',
|
||||
text: 'Добавь хотя бы один процесс, EXE-файл или папку.',
|
||||
};
|
||||
}
|
||||
|
||||
if (input.routeMode === 'external') {
|
||||
if (!input.externalProxyValue.trim()) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'Прокси не указан',
|
||||
text: 'Введи адрес SOCKS5 прокси в формате host:port или socks5://host:port.',
|
||||
};
|
||||
}
|
||||
|
||||
if (input.externalProxyError) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'Проверь формат прокси',
|
||||
text: input.externalProxyError,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (input.routeMode === 'local-singbox') {
|
||||
if (!input.singBoxInstalled) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'Local sing-box не установлен',
|
||||
text: 'Установи Local sing-box, чтобы применить локальный маршрут.',
|
||||
};
|
||||
}
|
||||
|
||||
if (!input.selectedServerTag) {
|
||||
return {
|
||||
ready: false,
|
||||
title: 'Сервер не выбран',
|
||||
text: 'Выбери сервер Local sing-box перед применением маршрута.',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return { ready: true };
|
||||
}
|
||||
|
||||
15
src/app/viewModel.ts
Normal file
15
src/app/viewModel.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import type { ComponentStatus } from '../domain/types';
|
||||
import type { ServiceControlState } from '../ui';
|
||||
|
||||
export function serviceControlState(
|
||||
component: ComponentStatus | undefined,
|
||||
checking: boolean,
|
||||
): ServiceControlState {
|
||||
if (checking) return 'checking';
|
||||
if (!component) return 'missing';
|
||||
if (component.state === 'error') return 'error';
|
||||
if (component.running) return 'running';
|
||||
if (component.installed) return 'stopped';
|
||||
return 'missing';
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user