mirror of
https://github.com/itdoginfo/podkop.git
synced 2025-12-06 19:46:52 +03:00
fix: correct dashboard displaying
This commit is contained in:
@@ -8,3 +8,4 @@ export * from './getProxyUrlName';
|
||||
export * from './onMount';
|
||||
export * from './getClashApiUrl';
|
||||
export * from './splitProxyString';
|
||||
export * from './preserveScrollForPage';
|
||||
|
||||
9
fe-app-podkop/src/helpers/preserveScrollForPage.ts
Normal file
9
fe-app-podkop/src/helpers/preserveScrollForPage.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
export function preserveScrollForPage(renderFn: () => void) {
|
||||
const scrollY = window.scrollY;
|
||||
|
||||
renderFn();
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
window.scrollTo({ top: scrollY });
|
||||
});
|
||||
}
|
||||
@@ -62,9 +62,10 @@ export async function getDashboardSections(): Promise<IGetDashboardSectionsRespo
|
||||
);
|
||||
|
||||
const parsedOutbound = JSON.parse(section.outbound_json);
|
||||
const parsedTag = parsedOutbound?.tag ? decodeURIComponent(parsedOutbound?.tag) : undefined;
|
||||
const proxyDisplayName = parsedTag || outbound?.value?.name || ''
|
||||
|
||||
const parsedTag = parsedOutbound?.tag
|
||||
? decodeURIComponent(parsedOutbound?.tag)
|
||||
: undefined;
|
||||
const proxyDisplayName = parsedTag || outbound?.value?.name || '';
|
||||
|
||||
return {
|
||||
withTagSelect: false,
|
||||
|
||||
@@ -3,7 +3,11 @@ import {
|
||||
getPodkopStatus,
|
||||
getSingboxStatus,
|
||||
} from '../../methods';
|
||||
import { getClashWsUrl, onMount } from '../../../helpers';
|
||||
import {
|
||||
getClashWsUrl,
|
||||
onMount,
|
||||
preserveScrollForPage,
|
||||
} from '../../../helpers';
|
||||
import {
|
||||
triggerLatencyGroupTest,
|
||||
triggerLatencyProxyTest,
|
||||
@@ -31,6 +35,7 @@ async function fetchDashboardSections() {
|
||||
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
latencyFetching: false,
|
||||
loading: false,
|
||||
failed: !success,
|
||||
data,
|
||||
@@ -130,24 +135,40 @@ async function handleChooseOutbound(selector: string, tag: string) {
|
||||
}
|
||||
|
||||
async function handleTestGroupLatency(tag: string) {
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: true,
|
||||
},
|
||||
});
|
||||
|
||||
await triggerLatencyGroupTest(tag);
|
||||
await fetchDashboardSections();
|
||||
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function handleTestProxyLatency(tag: string) {
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: true,
|
||||
},
|
||||
});
|
||||
|
||||
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);
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: false,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -170,8 +191,12 @@ async function renderSectionsWidget() {
|
||||
},
|
||||
onTestLatency: () => {},
|
||||
onChooseOutbound: () => {},
|
||||
latencyFetching: sectionsWidget.latencyFetching,
|
||||
});
|
||||
|
||||
return preserveScrollForPage(() => {
|
||||
container!.replaceChildren(renderedWidget);
|
||||
});
|
||||
return container!.replaceChildren(renderedWidget);
|
||||
}
|
||||
|
||||
const renderedWidgets = sectionsWidget.data.map((section) =>
|
||||
@@ -179,9 +204,8 @@ async function renderSectionsWidget() {
|
||||
loading: sectionsWidget.loading,
|
||||
failed: sectionsWidget.failed,
|
||||
section,
|
||||
latencyFetching: sectionsWidget.latencyFetching,
|
||||
onTestLatency: (tag) => {
|
||||
replaceTestLatencyButtonsWithSkeleton();
|
||||
|
||||
if (section.withTagSelect) {
|
||||
return handleTestGroupLatency(tag);
|
||||
}
|
||||
@@ -194,7 +218,9 @@ async function renderSectionsWidget() {
|
||||
}),
|
||||
);
|
||||
|
||||
return container!.replaceChildren(...renderedWidgets);
|
||||
return preserveScrollForPage(() => {
|
||||
container!.replaceChildren(...renderedWidgets);
|
||||
});
|
||||
}
|
||||
|
||||
async function renderBandwidthWidget() {
|
||||
|
||||
@@ -6,6 +6,7 @@ interface IRenderSectionsProps {
|
||||
section: Podkop.OutboundGroup;
|
||||
onTestLatency: (tag: string) => void;
|
||||
onChooseOutbound: (selector: string, tag: string) => void;
|
||||
latencyFetching: boolean;
|
||||
}
|
||||
|
||||
function renderFailedState() {
|
||||
@@ -31,6 +32,7 @@ export function renderDefaultState({
|
||||
section,
|
||||
onChooseOutbound,
|
||||
onTestLatency,
|
||||
latencyFetching,
|
||||
}: IRenderSectionsProps) {
|
||||
function testLatency() {
|
||||
if (section.withTagSelect) {
|
||||
@@ -95,7 +97,9 @@ export function renderDefaultState({
|
||||
},
|
||||
section.displayName,
|
||||
),
|
||||
E(
|
||||
latencyFetching
|
||||
? E('div', { class: 'skeleton', style: 'width: 99px; height: 28px' })
|
||||
: E(
|
||||
'button',
|
||||
{
|
||||
class: 'btn dashboard-sections-grid-item-test-latency',
|
||||
|
||||
@@ -141,6 +141,7 @@ export interface StoreType {
|
||||
loading: boolean;
|
||||
failed: boolean;
|
||||
data: Podkop.OutboundGroup[];
|
||||
latencyFetching: boolean;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -172,6 +173,7 @@ const initialStore: StoreType = {
|
||||
sectionsWidget: {
|
||||
loading: true,
|
||||
failed: false,
|
||||
latencyFetching: false,
|
||||
data: [],
|
||||
},
|
||||
};
|
||||
|
||||
@@ -776,6 +776,15 @@ function splitProxyString(str) {
|
||||
return str.split("\n").map((line) => line.trim()).filter((line) => !line.startsWith("//")).filter(Boolean);
|
||||
}
|
||||
|
||||
// src/helpers/preserveScrollForPage.ts
|
||||
function preserveScrollForPage(renderFn) {
|
||||
const scrollY = window.scrollY;
|
||||
renderFn();
|
||||
requestAnimationFrame(() => {
|
||||
window.scrollTo({ top: scrollY });
|
||||
});
|
||||
}
|
||||
|
||||
// src/clash/methods/createBaseApiRequest.ts
|
||||
async function createBaseApiRequest(fetchFn) {
|
||||
try {
|
||||
@@ -1210,6 +1219,7 @@ var initialStore = {
|
||||
sectionsWidget: {
|
||||
loading: true,
|
||||
failed: false,
|
||||
latencyFetching: false,
|
||||
data: []
|
||||
}
|
||||
};
|
||||
@@ -1248,7 +1258,8 @@ function renderLoadingState() {
|
||||
function renderDefaultState({
|
||||
section,
|
||||
onChooseOutbound,
|
||||
onTestLatency
|
||||
onTestLatency,
|
||||
latencyFetching
|
||||
}) {
|
||||
function testLatency() {
|
||||
if (section.withTagSelect) {
|
||||
@@ -1304,7 +1315,7 @@ function renderDefaultState({
|
||||
},
|
||||
section.displayName
|
||||
),
|
||||
E(
|
||||
latencyFetching ? E("div", { class: "skeleton", style: "width: 99px; height: 28px" }) : E(
|
||||
"button",
|
||||
{
|
||||
class: "btn dashboard-sections-grid-item-test-latency",
|
||||
@@ -1573,6 +1584,7 @@ async function fetchDashboardSections() {
|
||||
const { data, success } = await getDashboardSections();
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
latencyFetching: false,
|
||||
loading: false,
|
||||
failed: !success,
|
||||
data
|
||||
@@ -1662,20 +1674,35 @@ async function handleChooseOutbound(selector, tag) {
|
||||
await fetchDashboardSections();
|
||||
}
|
||||
async function handleTestGroupLatency(tag) {
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: true
|
||||
}
|
||||
});
|
||||
await triggerLatencyGroupTest(tag);
|
||||
await fetchDashboardSections();
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: false
|
||||
}
|
||||
});
|
||||
}
|
||||
async function handleTestProxyLatency(tag) {
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: true
|
||||
}
|
||||
});
|
||||
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);
|
||||
store.set({
|
||||
sectionsWidget: {
|
||||
...store.get().sectionsWidget,
|
||||
latencyFetching: false
|
||||
}
|
||||
});
|
||||
}
|
||||
async function renderSectionsWidget() {
|
||||
@@ -1695,17 +1722,20 @@ async function renderSectionsWidget() {
|
||||
onTestLatency: () => {
|
||||
},
|
||||
onChooseOutbound: () => {
|
||||
}
|
||||
},
|
||||
latencyFetching: sectionsWidget.latencyFetching
|
||||
});
|
||||
return preserveScrollForPage(() => {
|
||||
container.replaceChildren(renderedWidget);
|
||||
});
|
||||
return container.replaceChildren(renderedWidget);
|
||||
}
|
||||
const renderedWidgets = sectionsWidget.data.map(
|
||||
(section) => renderSections({
|
||||
loading: sectionsWidget.loading,
|
||||
failed: sectionsWidget.failed,
|
||||
section,
|
||||
latencyFetching: sectionsWidget.latencyFetching,
|
||||
onTestLatency: (tag) => {
|
||||
replaceTestLatencyButtonsWithSkeleton();
|
||||
if (section.withTagSelect) {
|
||||
return handleTestGroupLatency(tag);
|
||||
}
|
||||
@@ -1716,7 +1746,9 @@ async function renderSectionsWidget() {
|
||||
}
|
||||
})
|
||||
);
|
||||
return container.replaceChildren(...renderedWidgets);
|
||||
return preserveScrollForPage(() => {
|
||||
container.replaceChildren(...renderedWidgets);
|
||||
});
|
||||
}
|
||||
async function renderBandwidthWidget() {
|
||||
console.log("renderBandwidthWidget");
|
||||
@@ -1906,6 +1938,7 @@ return baseclass.extend({
|
||||
maskIP,
|
||||
onMount,
|
||||
parseValueList,
|
||||
preserveScrollForPage,
|
||||
renderDashboard,
|
||||
splitProxyString,
|
||||
triggerLatencyGroupTest,
|
||||
|
||||
Reference in New Issue
Block a user