refactor: cleanup

This commit is contained in:
zhom
2026-06-24 02:00:44 +04:00
parent fe3ae13928
commit 8588a44fb5
22 changed files with 172 additions and 82 deletions
+2 -2
View File
@@ -15,6 +15,7 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { translateBackendError } from "@/lib/backend-errors";
import type { ProfileGroup } from "@/types";
import { RippleButton } from "./ui/ripple";
@@ -50,8 +51,7 @@ export function CreateGroupDialog({
onClose();
} catch (err) {
console.error("Failed to create group:", err);
const errorMessage =
err instanceof Error ? err.message : t("groups.createFailed");
const errorMessage = translateBackendError(t, err);
setError(errorMessage);
toast.error(errorMessage);
} finally {
+2 -2
View File
@@ -16,6 +16,7 @@ import {
import { Label } from "@/components/ui/label";
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
import { ScrollArea } from "@/components/ui/scroll-area";
import { translateBackendError } from "@/lib/backend-errors";
import type { BrowserProfile, ProfileGroup } from "@/types";
import { RippleButton } from "./ui/ripple";
@@ -97,8 +98,7 @@ export function DeleteGroupDialog({
onClose();
} catch (err) {
console.error("Failed to delete group:", err);
const errorMessage =
err instanceof Error ? err.message : t("groups.deleteFailed");
const errorMessage = translateBackendError(t, err);
setError(errorMessage);
toast.error(errorMessage);
} finally {
+2 -2
View File
@@ -15,6 +15,7 @@ import {
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { translateBackendError } from "@/lib/backend-errors";
import type { ProfileGroup } from "@/types";
import { RippleButton } from "./ui/ripple";
@@ -61,8 +62,7 @@ export function EditGroupDialog({
onClose();
} catch (err) {
console.error("Failed to update group:", err);
const errorMessage =
err instanceof Error ? err.message : t("groups.updateFailed");
const errorMessage = translateBackendError(t, err);
setError(errorMessage);
toast.error(errorMessage);
} finally {
+10 -6
View File
@@ -495,9 +495,15 @@ export function GroupManagementDialog({
const results = await Promise.allSettled(
ids.map((groupId) => invoke("delete_profile_group", { groupId })),
);
const failed = results.filter((r) => r.status === "rejected");
if (failed.length > 0) {
showErrorToast(t("groups.deleteFailed"));
const firstRejection = results.find((r) => r.status === "rejected") as
| PromiseRejectedResult
| undefined;
if (firstRejection) {
showErrorToast(
parseBackendError(firstRejection.reason)
? translateBackendError(t, firstRejection.reason)
: t("groups.deleteFailed"),
);
} else {
showSuccessToast(t("groups.deleteSuccess"));
}
@@ -507,9 +513,7 @@ export function GroupManagementDialog({
onGroupManagementComplete();
} catch (err) {
console.error("Bulk group delete failed:", err);
showErrorToast(
err instanceof Error ? err.message : t("groups.deleteFailed"),
);
showErrorToast(translateBackendError(t, err));
} finally {
setIsBulkDeleting(false);
}
+13 -7
View File
@@ -1250,14 +1250,16 @@ export function ProfilesDataTable({
(id) => newSelection[id],
);
// Only update external state if selection actually changed
const prevIds = Object.keys(prevSelection).filter(
(id) => prevSelection[id],
// Only update external state if selection actually changed.
// A Set gives O(1) membership; Array.includes() inside .every() would
// be O(n*m) over large selections.
const prevIdSet = new Set(
Object.keys(prevSelection).filter((id) => prevSelection[id]),
);
if (
selectedIds.length !== prevIds.length ||
!selectedIds.every((id) => prevIds.includes(id))
selectedIds.length !== prevIdSet.size ||
!selectedIds.every((id) => prevIdSet.has(id))
) {
onSelectedProfilesChange(selectedIds);
}
@@ -1559,10 +1561,13 @@ export function ProfilesDataTable({
"get_all_traffic_snapshots",
);
const newSnapshots: Record<string, TrafficSnapshot> = {};
// O(1) membership; runningProfileIds.includes() in this loop would be
// O(snapshots * runningProfiles).
const runningSet = new Set(runningProfileIds);
for (const snapshot of allSnapshots) {
if (snapshot.profile_id) {
// Only keep snapshots for profiles that are currently running
if (runningProfileIds.includes(snapshot.profile_id)) {
if (runningSet.has(snapshot.profile_id)) {
const existing = newSnapshots[snapshot.profile_id];
if (!existing || snapshot.last_update > existing.last_update) {
newSnapshots[snapshot.profile_id] = snapshot;
@@ -1591,9 +1596,10 @@ export function ProfilesDataTable({
setTrafficSnapshots((prev) => {
const cleaned: Record<string, TrafficSnapshot> = {};
const runningSet = new Set(runningProfileIds);
for (const [profileId, snapshot] of Object.entries(prev)) {
// Only keep snapshots for profiles that are currently running
if (runningProfileIds.includes(profileId)) {
if (runningSet.has(profileId)) {
cleaned[profileId] = snapshot;
}
}
+6 -3
View File
@@ -21,6 +21,7 @@ import {
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { translateBackendError } from "@/lib/backend-errors";
import type { StoredProxy } from "@/types";
import { RippleButton } from "./ui/ripple";
@@ -127,9 +128,11 @@ export function ProxyFormDialog({
onClose();
} catch (error) {
console.error("Failed to save proxy:", error);
const errorMessage =
error instanceof Error ? error.message : String(error);
toast.error(t("proxies.form.saveFailed", { error: errorMessage }));
toast.error(
t("proxies.form.saveFailed", {
error: translateBackendError(t, error),
}),
);
} finally {
setIsSubmitting(false);
}