feat: add rustfmt configuration and CI workflow for code formatting

refactor: streamline formatting workflow by removing unused taplo steps and clarifying directory change

refactor: remove unnecessary directory change step in formatting workflow
This commit is contained in:
Tunglies
2025-06-06 21:11:14 +08:00
parent 689042df60
commit 09969d95de
89 changed files with 2630 additions and 2008 deletions

View File

@@ -199,10 +199,12 @@ export const getProxyProviders = async () => {
providers: Record<string, IProxyProviderItem>;
}>("get_providers_proxies");
if (!response || !response.providers) {
console.warn("getProxyProviders: Invalid response structure, returning empty object");
console.warn(
"getProxyProviders: Invalid response structure, returning empty object",
);
return {};
}
const providers = response.providers as Record<string, IProxyProviderItem>;
return Object.fromEntries(
@@ -351,65 +353,65 @@ const IP_CHECK_SERVICES: ServiceConfig[] = [
{
url: "https://api.ip.sb/geoip",
mapping: (data) => ({
ip: data.ip || '',
country_code: data.country_code || '',
country: data.country || '',
region: data.region || '',
city: data.city || '',
organization: data.organization || data.isp || '',
ip: data.ip || "",
country_code: data.country_code || "",
country: data.country || "",
region: data.region || "",
city: data.city || "",
organization: data.organization || data.isp || "",
asn: data.asn || 0,
asn_organization: data.asn_organization || '',
asn_organization: data.asn_organization || "",
longitude: data.longitude || 0,
latitude: data.latitude || 0,
timezone: data.timezone || '',
timezone: data.timezone || "",
}),
},
{
url: "https://ipapi.co/json",
mapping: (data) => ({
ip: data.ip || '',
country_code: data.country_code || '',
country: data.country_name || '',
region: data.region || '',
city: data.city || '',
organization: data.org || '',
asn: data.asn? parseInt(data.asn.replace('AS', '')) : 0,
asn_organization: data.org || '',
ip: data.ip || "",
country_code: data.country_code || "",
country: data.country_name || "",
region: data.region || "",
city: data.city || "",
organization: data.org || "",
asn: data.asn ? parseInt(data.asn.replace("AS", "")) : 0,
asn_organization: data.org || "",
longitude: data.longitude || 0,
latitude: data.latitude || 0,
timezone: data.timezone || '',
timezone: data.timezone || "",
}),
},
{
url: "https://api.ipapi.is/",
mapping: (data) => ({
ip: data.ip || '',
country_code: data.location?.country_code || '',
country: data.location?.country || '',
region: data.location?.state || '',
city: data.location?.city || '',
organization: data.asn?.org || data.company?.name || '',
ip: data.ip || "",
country_code: data.location?.country_code || "",
country: data.location?.country || "",
region: data.location?.state || "",
city: data.location?.city || "",
organization: data.asn?.org || data.company?.name || "",
asn: data.asn?.asn || 0,
asn_organization: data.asn?.org || '',
asn_organization: data.asn?.org || "",
longitude: data.location?.longitude || 0,
latitude: data.location?.latitude || 0,
timezone: data.location?.timezone || '',
timezone: data.location?.timezone || "",
}),
},
{
url: "https://ipwho.is/",
mapping: (data) => ({
ip: data.ip || '',
country_code: data.country_code || '',
country: data.country || '',
region: data.region || '',
city: data.city || '',
organization: data.connection?.org || data.connection?.isp || '',
ip: data.ip || "",
country_code: data.country_code || "",
country: data.country || "",
region: data.region || "",
city: data.city || "",
organization: data.connection?.org || data.connection?.isp || "",
asn: data.connection?.asn || 0,
asn_organization: data.connection?.isp || '',
asn_organization: data.connection?.isp || "",
longitude: data.longitude || 0,
latitude: data.latitude || 0,
timezone: data.timezone?.id || '',
timezone: data.timezone?.id || "",
}),
},
];
@@ -418,43 +420,39 @@ const IP_CHECK_SERVICES: ServiceConfig[] = [
function shuffleServices() {
// 过滤无效服务并确保每个元素符合ServiceConfig接口
const validServices = IP_CHECK_SERVICES.filter(
(service): service is ServiceConfig =>
service !== null &&
service !== undefined &&
typeof service.url === 'string' &&
typeof service.mapping === 'function' // 添加对mapping属性的检查
(service): service is ServiceConfig =>
service !== null &&
service !== undefined &&
typeof service.url === "string" &&
typeof service.mapping === "function", // 添加对mapping属性的检查
);
if (validServices.length === 0) {
console.error('No valid services found in IP_CHECK_SERVICES');
console.error("No valid services found in IP_CHECK_SERVICES");
return [];
}
// 使用单一Fisher-Yates洗牌算法增强随机性
const shuffled = [...validServices];
const length = shuffled.length;
// 使用多个种子进行多次洗牌
const seeds = [
Math.random(),
Date.now() / 1000,
performance.now() / 1000
];
const seeds = [Math.random(), Date.now() / 1000, performance.now() / 1000];
for (const seed of seeds) {
const prng = createPrng(seed);
// Fisher-Yates洗牌算法
for (let i = length - 1; i > 0; i--) {
const j = Math.floor(prng() * (i + 1));
// 使用临时变量进行交换,避免解构赋值可能的问题
const temp = shuffled[i];
shuffled[i] = shuffled[j];
shuffled[j] = temp;
}
}
return shuffled;
}
@@ -462,11 +460,11 @@ function shuffleServices() {
function createPrng(seed: number): () => number {
// 使用xorshift32算法
let state = seed >>> 0;
// 如果种子为0设置一个默认值
if (state === 0) state = 123456789;
return function() {
return function () {
state ^= state << 13;
state ^= state >>> 17;
state ^= state << 5;
@@ -522,7 +520,7 @@ export const getIpInfo = async (): Promise<IpInfo> => {
lastError = error;
console.log(
`尝试 ${attempt + 1}/${maxRetries} 失败 (${service.url}):`,
error.message
error.message,
);
if (error.name === "AbortError") {
@@ -530,7 +528,7 @@ export const getIpInfo = async (): Promise<IpInfo> => {
}
if (attempt < maxRetries - 1) {
await new Promise(resolve => setTimeout(resolve, 1000));
await new Promise((resolve) => setTimeout(resolve, 1000));
}
}
}
@@ -539,9 +537,9 @@ export const getIpInfo = async (): Promise<IpInfo> => {
if (lastError) {
throw new Error(`所有IP检测服务都失败: ${lastError.message}`);
} else {
throw new Error('没有可用的IP检测服务');
throw new Error("没有可用的IP检测服务");
}
} finally {
clearTimeout(overallTimeoutId);
}
};
};

View File

@@ -1,8 +1,8 @@
import { ReactNode } from 'react';
import { ReactNode } from "react";
export interface NoticeItem {
id: number;
type: 'success' | 'error' | 'info';
type: "success" | "error" | "info";
message: ReactNode;
duration: number;
timerId?: ReturnType<typeof setTimeout>;
@@ -21,13 +21,13 @@ function notifyListeners() {
// Shows a notification.
export function showNotice(
type: 'success' | 'error' | 'info',
type: "success" | "error" | "info",
message: ReactNode,
duration?: number,
): number {
const id = nextId++;
const effectiveDuration =
duration ?? (type === 'error' ? 8000 : type === 'info' ? 5000 : 3000); // Longer defaults
duration ?? (type === "error" ? 8000 : type === "info" ? 5000 : 3000); // Longer defaults
const newNotice: NoticeItem = {
id,
@@ -38,12 +38,11 @@ export function showNotice(
// Auto-hide timer (only if duration is not null/0)
if (effectiveDuration > 0) {
newNotice.timerId = setTimeout(() => {
hideNotice(id);
}, effectiveDuration);
newNotice.timerId = setTimeout(() => {
hideNotice(id);
}, effectiveDuration);
}
notices = [...notices, newNotice];
notifyListeners();
return id;
@@ -54,7 +53,7 @@ export function showNotice(
export function hideNotice(id: number) {
const notice = notices.find((n) => n.id === id);
if (notice?.timerId) {
clearTimeout(notice.timerId); // Clear timeout if manually closed
clearTimeout(notice.timerId); // Clear timeout if manually closed
}
notices = notices.filter((n) => n.id !== id);
notifyListeners();
@@ -72,9 +71,9 @@ export function subscribeNotices(listener: Listener): () => void {
// Function to clear all notices at once
export function clearAllNotices() {
notices.forEach(n => {
if (n.timerId) clearTimeout(n.timerId);
});
notices = [];
notifyListeners();
}
notices.forEach((n) => {
if (n.timerId) clearTimeout(n.timerId);
});
notices = [];
notifyListeners();
}