Improved proxy selector view
This commit is contained in:
@@ -41,12 +41,14 @@ interface IProxyGroup {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// --- Вспомогательная функция для цвета задержки ---
|
// --- Вспомогательная функция для цвета задержки ---
|
||||||
function getDelayBadgeVariant(
|
function getDelayColorClasses(delayValue: number): string {
|
||||||
delayValue: number,
|
if (delayValue < 0) {
|
||||||
): "default" | "secondary" | "destructive" | "outline" {
|
return "text-muted-foreground border-border";
|
||||||
if (delayValue < 0) return "secondary";
|
}
|
||||||
if (delayValue >= 150) return "destructive";
|
if (delayValue >= 150) {
|
||||||
return "default";
|
return "text-destructive border-destructive/40";
|
||||||
|
}
|
||||||
|
return "text-green-600 border-green-500/40 dark:text-green-400 dark:border-green-400/30";
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- Дочерний компонент для элемента списка с "живым" обновлением пинга ---
|
// --- Дочерний компонент для элемента списка с "живым" обновлением пинга ---
|
||||||
@@ -80,20 +82,21 @@ const ProxySelectItem = ({
|
|||||||
}, [proxyName, groupName]);
|
}, [proxyName, groupName]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<SelectItem key={proxyName} value={proxyName}>
|
<SelectItem key={proxyName} value={proxyName}>
|
||||||
<div className="flex items-center justify-between w-full">
|
<div className="flex items-center justify-between w-full">
|
||||||
<span className="truncate">{proxyName}</span>
|
<Badge
|
||||||
<Badge
|
variant="outline"
|
||||||
variant={getDelayBadgeVariant(delay)}
|
className={cn(
|
||||||
className={cn(
|
"mr-2 flex-shrink-0 px-2 h-5 w-8 justify-center transition-colors duration-300",
|
||||||
"ml-4 flex-shrink-0 px-2 h-5 justify-center transition-colors duration-300",
|
getDelayColorClasses(delay),
|
||||||
isJustUpdated && "bg-primary/20 border-primary/50",
|
isJustUpdated && "bg-primary/10 border-primary/50",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
{delay < 0 || delay > 10000 ? "---" : delay}
|
{delay < 0 || delay > 10000 ? "---" : delay}
|
||||||
</Badge>
|
</Badge>
|
||||||
</div>
|
<span className="truncate">{proxyName}</span>
|
||||||
</SelectItem>
|
</div>
|
||||||
|
</SelectItem>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -259,11 +262,21 @@ export const ProxySelectors: React.FC = () => {
|
|||||||
?.all;
|
?.all;
|
||||||
|
|
||||||
if (sourceList) {
|
if (sourceList) {
|
||||||
options = sourceList
|
const rawOptions = sourceList
|
||||||
.map((proxy: any) => ({
|
.map((proxy: any) => ({
|
||||||
name: typeof proxy === "string" ? proxy : proxy.name,
|
name: typeof proxy === "string" ? proxy : proxy.name,
|
||||||
}))
|
}))
|
||||||
.filter((p: { name: string }) => p.name);
|
.filter((p: { name: string }) => p.name);
|
||||||
|
|
||||||
|
// Удаляем дубли по имени прокси
|
||||||
|
const uniqueNames = new Set<string>();
|
||||||
|
options = rawOptions.filter((proxy: any) => {
|
||||||
|
if (!uniqueNames.has(proxy.name)) {
|
||||||
|
uniqueNames.add(proxy.name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sortType === "name")
|
if (sortType === "name")
|
||||||
@@ -345,44 +358,37 @@ export const ProxySelectors: React.FC = () => {
|
|||||||
{sortType === "name" && <WholeWord className="h-4 w-4" />}
|
{sortType === "name" && <WholeWord className="h-4 w-4" />}
|
||||||
</Button>
|
</Button>
|
||||||
</span>
|
</span>
|
||||||
</TooltipTrigger>
|
|
||||||
<TooltipContent>
|
|
||||||
{sortType === "default" && <p>{t("Sort by default")}</p>}
|
|
||||||
{sortType === "delay" && <p>{t("Sort by delay")}</p>}
|
|
||||||
{sortType === "name" && <p>{t("Sort by name")}</p>}
|
|
||||||
</TooltipContent>
|
|
||||||
</Tooltip>
|
|
||||||
</div>
|
|
||||||
<Select
|
|
||||||
value={selectedProxy}
|
|
||||||
onValueChange={handleProxyChange}
|
|
||||||
disabled={isDirectMode}
|
|
||||||
onOpenChange={handleProxyListOpen}
|
|
||||||
>
|
|
||||||
<SelectTrigger className="w-100">
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>
|
|
||||||
<span className="truncate">
|
|
||||||
<SelectValue placeholder={t("Select a proxy...")} />
|
|
||||||
</span>
|
|
||||||
</TooltipTrigger>
|
</TooltipTrigger>
|
||||||
<TooltipContent>
|
<TooltipContent>
|
||||||
<p>{selectedProxy}</p>
|
{sortType === "default" && <p>{t("Sort by default")}</p>}
|
||||||
|
{sortType === "delay" && <p>{t("Sort by delay")}</p>}
|
||||||
|
{sortType === "name" && <p>{t("Sort by name")}</p>}
|
||||||
</TooltipContent>
|
</TooltipContent>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
</SelectTrigger>
|
</div>
|
||||||
<SelectContent>
|
<Select
|
||||||
{proxyOptions.map((proxy) => (
|
value={selectedProxy}
|
||||||
<ProxySelectItem
|
onValueChange={handleProxyChange}
|
||||||
key={proxy.name}
|
disabled={isDirectMode}
|
||||||
proxyName={proxy.name}
|
onOpenChange={handleProxyListOpen}
|
||||||
groupName={selectedGroup}
|
>
|
||||||
/>
|
<SelectTrigger className="w-100">
|
||||||
))}
|
<span className="truncate">
|
||||||
</SelectContent>
|
<SelectValue placeholder={t("Select a proxy...")} />
|
||||||
</Select>
|
</span>
|
||||||
|
</SelectTrigger>
|
||||||
|
<SelectContent>
|
||||||
|
{proxyOptions.map((proxy) => (
|
||||||
|
<ProxySelectItem
|
||||||
|
key={proxy.name}
|
||||||
|
proxyName={proxy.name}
|
||||||
|
groupName={selectedGroup}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
|
</SelectContent>
|
||||||
|
</Select>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</TooltipProvider>
|
||||||
</TooltipProvider>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user