mirror of
https://github.com/MHSanaei/3x-ui.git
synced 2026-09-16 23:27:14 +00:00
feat(geodata): add standard source presets (#6504)
* feat(geodata): add standard source presets Expose the existing geofile allowlist to the Geodata editor so administrators can configure the supported scheduled downloads without copying URLs manually Tested with npm run test, npm run lint, npm run typecheck, npm run format:check, and go test ./internal/web/service ./internal/web/controller -run '^(TestStandardGeodataSources|TestGeodata)' -count=1 Assisted-by: OpenCode:openai/gpt-5.6-terra (mostly) * fix(geodata): preserve custom source entries Add missing standard sources instead of replacing existing custom entries. Assisted-by: OpenCode:openai/gpt-5.6-terra (mostly)
This commit is contained in:
@@ -3,6 +3,7 @@ import { useTranslation } from 'react-i18next';
|
||||
import { Alert, Button, Form, Input, Modal, Select, Space, Spin, Typography, message } from 'antd';
|
||||
import { PlusOutlined, DeleteOutlined } from '@ant-design/icons';
|
||||
|
||||
import { XrayConfigPayloadSchema } from '@/schemas/xray';
|
||||
import { HttpUtil } from '@/utils';
|
||||
|
||||
interface GeodataAssetRow {
|
||||
@@ -37,6 +38,7 @@ export default function GeodataSection({ active, onBusy, onClose }: GeodataSecti
|
||||
const [cron, setCron] = useState(DEFAULT_CRON);
|
||||
const [outbound, setOutbound] = useState<string | undefined>(undefined);
|
||||
const [rows, setRows] = useState<GeodataAssetRow[]>([]);
|
||||
const [standardSources, setStandardSources] = useState<GeodataAssetRow[]>([]);
|
||||
const [outboundTags, setOutboundTags] = useState<string[]>([]);
|
||||
const [template, setTemplate] = useState<Record<string, unknown> | null>(null);
|
||||
const outboundTestUrlRef = useRef('');
|
||||
@@ -45,8 +47,10 @@ export default function GeodataSection({ active, onBusy, onClose }: GeodataSecti
|
||||
try {
|
||||
const msg = await HttpUtil.post('/panel/api/xray/', undefined, { silent: true });
|
||||
if (!msg?.success || typeof msg.obj !== 'string') return;
|
||||
const payload = JSON.parse(msg.obj) as Record<string, unknown>;
|
||||
const next = (payload.xraySetting || {}) as Record<string, unknown>;
|
||||
const parsed = XrayConfigPayloadSchema.safeParse(JSON.parse(msg.obj));
|
||||
if (!parsed.success) return;
|
||||
const payload = parsed.data;
|
||||
const next = payload.xraySetting as Record<string, unknown>;
|
||||
setTemplate(next);
|
||||
outboundTestUrlRef.current =
|
||||
typeof payload.outboundTestUrl === 'string' ? payload.outboundTestUrl : '';
|
||||
@@ -62,6 +66,7 @@ export default function GeodataSection({ active, onBusy, onClose }: GeodataSecti
|
||||
setOutbound(
|
||||
typeof geodata.outbound === 'string' && geodata.outbound ? geodata.outbound : undefined,
|
||||
);
|
||||
setStandardSources(payload.geodataSources ?? []);
|
||||
|
||||
// Download outbound candidates: template outbounds + subscription outbounds.
|
||||
// Skip blackhole outbounds — routing a download through one just drops it.
|
||||
@@ -106,6 +111,13 @@ export default function GeodataSection({ active, onBusy, onClose }: GeodataSecti
|
||||
);
|
||||
}
|
||||
|
||||
function addStandardSources() {
|
||||
setRows((prev) => {
|
||||
const files = new Set(prev.map((row) => row.file));
|
||||
return [...prev, ...standardSources.filter((source) => !files.has(source.file))];
|
||||
});
|
||||
}
|
||||
|
||||
function save() {
|
||||
if (!template) return;
|
||||
const assets = rows
|
||||
@@ -217,6 +229,9 @@ export default function GeodataSection({ active, onBusy, onClose }: GeodataSecti
|
||||
>
|
||||
{t('pages.index.geodataAddFile')}
|
||||
</Button>
|
||||
<Button onClick={addStandardSources} disabled={standardSources.length === 0}>
|
||||
{t('pages.index.geodataUseStandardSources')}
|
||||
</Button>
|
||||
<Button type="primary" onClick={save} disabled={loading || !template}>
|
||||
{t('pages.index.geodataSaveRestart')}
|
||||
</Button>
|
||||
|
||||
Reference in New Issue
Block a user