mirror of
https://github.com/clash-verge-rev/clash-verge-rev.git
synced 2024-11-15 19:22:26 +08:00
feat: reactive after save when profile content changes
Some checks are pending
Alpha Build / alpha (macos-latest, aarch64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (macos-latest, x86_64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, aarch64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, armv7-unknown-linux-gnueabihf) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, i686-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (arm64, windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x64, windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x86, windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / Update tag (push) Blocked by required conditions
Some checks are pending
Alpha Build / alpha (macos-latest, aarch64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (macos-latest, x86_64-apple-darwin) (push) Waiting to run
Alpha Build / alpha (windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha (windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, aarch64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, armv7-unknown-linux-gnueabihf) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, i686-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-linux (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (arm64, windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x64, windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Alpha Build / alpha-for-fixed-webview2 (x86, windows-latest, i686-pc-windows-msvc) (push) Waiting to run
Alpha Build / Update tag (push) Blocked by required conditions
This commit is contained in:
parent
3f1caa702b
commit
9ee5390ec7
|
@ -27,10 +27,10 @@ export const ConfirmViewer = (props: Props) => {
|
|||
|
||||
return (
|
||||
<Dialog open={open} onClose={onClose} maxWidth="xs" fullWidth>
|
||||
<DialogTitle>{t(title)}</DialogTitle>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
|
||||
<DialogContent sx={{ pb: 1, userSelect: "text" }}>
|
||||
{t(message)}
|
||||
{message}
|
||||
</DialogContent>
|
||||
|
||||
<DialogActions>
|
||||
|
|
|
@ -32,7 +32,7 @@ interface Props {
|
|||
language: "yaml" | "javascript" | "css";
|
||||
schema?: "clash" | "merge";
|
||||
onClose: () => void;
|
||||
onChange?: (content?: string) => void;
|
||||
onChange?: (prev?: string, curr?: string) => void;
|
||||
}
|
||||
|
||||
// yaml worker
|
||||
|
@ -90,6 +90,7 @@ export const EditorViewer = (props: Props) => {
|
|||
const editorRef = useRef<any>();
|
||||
const instanceRef = useRef<editor.IStandaloneCodeEditor | null>(null);
|
||||
const themeMode = useThemeMode();
|
||||
const prevData = useRef<string>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!open) return;
|
||||
|
@ -136,6 +137,8 @@ export const EditorViewer = (props: Props) => {
|
|||
fontLigatures: true, // 连字符
|
||||
smoothScrolling: true, // 平滑滚动
|
||||
});
|
||||
|
||||
prevData.current = data;
|
||||
});
|
||||
|
||||
return () => {
|
||||
|
@ -147,15 +150,15 @@ export const EditorViewer = (props: Props) => {
|
|||
}, [open]);
|
||||
|
||||
const onSave = useLockFn(async () => {
|
||||
const value = instanceRef.current?.getValue();
|
||||
const currData = instanceRef.current?.getValue();
|
||||
|
||||
if (value == null) return;
|
||||
if (currData == null) return;
|
||||
|
||||
try {
|
||||
if (mode === "profile") {
|
||||
await saveProfileFile(property, value);
|
||||
await saveProfileFile(property, currData);
|
||||
}
|
||||
onChange?.(value);
|
||||
onChange?.(prevData.current, currData);
|
||||
onClose();
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString());
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
} from "@mui/material";
|
||||
import { RefreshRounded, DragIndicator } from "@mui/icons-material";
|
||||
import { useLoadingCache, useSetLoadingCache } from "@/services/states";
|
||||
import { updateProfile, deleteProfile, viewProfile } from "@/services/cmds";
|
||||
import { updateProfile, viewProfile } from "@/services/cmds";
|
||||
import { Notice } from "@/components/base";
|
||||
import { EditorViewer } from "@/components/profile/editor-viewer";
|
||||
import { ProfileBox } from "./profile-box";
|
||||
|
@ -36,10 +36,20 @@ interface Props {
|
|||
itemData: IProfileItem;
|
||||
onSelect: (force: boolean) => void;
|
||||
onEdit: () => void;
|
||||
onChange?: (prev?: string, curr?: string) => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
export const ProfileItem = (props: Props) => {
|
||||
const { selected, activating, itemData, onSelect, onEdit } = props;
|
||||
const {
|
||||
selected,
|
||||
activating,
|
||||
itemData,
|
||||
onSelect,
|
||||
onEdit,
|
||||
onChange,
|
||||
onDelete,
|
||||
} = props;
|
||||
const { attributes, listeners, setNodeRef, transform, transition } =
|
||||
useSortable({ id: props.id });
|
||||
|
||||
|
@ -53,6 +63,7 @@ export const ProfileItem = (props: Props) => {
|
|||
|
||||
// local file mode
|
||||
// remote file mode
|
||||
// remote file mode
|
||||
const hasUrl = !!itemData.url;
|
||||
const hasExtra = !!extra; // only subscription url has extra info
|
||||
const hasHome = !!itemData.home; // only subscription url has home page
|
||||
|
@ -162,16 +173,6 @@ export const ProfileItem = (props: Props) => {
|
|||
}
|
||||
});
|
||||
|
||||
const onDelete = useLockFn(async () => {
|
||||
setAnchorEl(null);
|
||||
try {
|
||||
await deleteProfile(itemData.uid);
|
||||
mutate("getProfiles");
|
||||
} catch (err: any) {
|
||||
Notice.error(err?.message || err.toString());
|
||||
}
|
||||
});
|
||||
|
||||
const urlModeMenu = (
|
||||
hasHome ? [{ label: "Home", handler: onOpenHome }] : []
|
||||
).concat([
|
||||
|
@ -242,7 +243,7 @@ export const ProfileItem = (props: Props) => {
|
|||
backdropFilter: "blur(2px)",
|
||||
}}
|
||||
>
|
||||
<CircularProgress size={20} />
|
||||
<CircularProgress color="inherit" size={20} />
|
||||
</Box>
|
||||
)}
|
||||
<Box position="relative">
|
||||
|
@ -312,7 +313,7 @@ export const ProfileItem = (props: Props) => {
|
|||
</Typography>
|
||||
) : (
|
||||
hasUrl && (
|
||||
<Typography noWrap title={`From ${from}`}>
|
||||
<Typography noWrap title={`${t("From")} ${from}`}>
|
||||
{from}
|
||||
</Typography>
|
||||
)
|
||||
|
@ -323,7 +324,7 @@ export const ProfileItem = (props: Props) => {
|
|||
flex="1 0 auto"
|
||||
fontSize={14}
|
||||
textAlign="right"
|
||||
title={`Updated Time: ${parseExpire(updated)}`}
|
||||
title={`${t("Update Time")}: ${parseExpire(updated)}`}
|
||||
>
|
||||
{updated > 0 ? dayjs(updated * 1000).fromNow() : ""}
|
||||
</Typography>
|
||||
|
@ -334,17 +335,21 @@ export const ProfileItem = (props: Props) => {
|
|||
{/* the third line show extra info or last updated time */}
|
||||
{hasExtra ? (
|
||||
<Box sx={{ ...boxStyle, fontSize: 14 }}>
|
||||
<span title="Used / Total">
|
||||
<span title={t("Used / Total")}>
|
||||
{parseTraffic(upload + download)} / {parseTraffic(total)}
|
||||
</span>
|
||||
<span title="Expire Time">{expire}</span>
|
||||
<span title={t("Expire Time")}>{expire}</span>
|
||||
</Box>
|
||||
) : (
|
||||
<Box sx={{ ...boxStyle, fontSize: 12, justifyContent: "flex-end" }}>
|
||||
<span title="Updated Time">{parseExpire(updated)}</span>
|
||||
<span title={t("Update Time")}>{parseExpire(updated)}</span>
|
||||
</Box>
|
||||
)}
|
||||
<LinearProgress variant="determinate" value={progress} />
|
||||
<LinearProgress
|
||||
variant="determinate"
|
||||
value={progress}
|
||||
style={{ opacity: progress > 0 ? 1 : 0 }}
|
||||
/>
|
||||
</ProfileBox>
|
||||
|
||||
<Menu
|
||||
|
@ -390,11 +395,12 @@ export const ProfileItem = (props: Props) => {
|
|||
open={fileOpen}
|
||||
language="yaml"
|
||||
schema="clash"
|
||||
onChange={onChange}
|
||||
onClose={() => setFileOpen(false)}
|
||||
/>
|
||||
<ConfirmViewer
|
||||
title="Confirm deletion"
|
||||
message="This operation is not reversible"
|
||||
title={t("Confirm deletion")}
|
||||
message={t("This operation is not reversible")}
|
||||
open={confirmOpen}
|
||||
onClose={() => setConfirmOpen(false)}
|
||||
onConfirm={() => {
|
||||
|
|
|
@ -9,6 +9,7 @@ import {
|
|||
MenuItem,
|
||||
Menu,
|
||||
IconButton,
|
||||
CircularProgress,
|
||||
} from "@mui/material";
|
||||
import { FeaturedPlayListRounded } from "@mui/icons-material";
|
||||
import { viewProfile } from "@/services/cmds";
|
||||
|
@ -20,6 +21,7 @@ import { ConfirmViewer } from "./confirm-viewer";
|
|||
|
||||
interface Props {
|
||||
selected: boolean;
|
||||
activating: boolean;
|
||||
itemData: IProfileItem;
|
||||
enableNum: number;
|
||||
logInfo?: [string, string][];
|
||||
|
@ -27,14 +29,16 @@ interface Props {
|
|||
onDisable: () => void;
|
||||
onMoveTop: () => void;
|
||||
onMoveEnd: () => void;
|
||||
onDelete: () => void;
|
||||
onEdit: () => void;
|
||||
onChange?: (prev?: string, curr?: string) => void;
|
||||
onDelete: () => void;
|
||||
}
|
||||
|
||||
// profile enhanced item
|
||||
export const ProfileMore = (props: Props) => {
|
||||
const {
|
||||
selected,
|
||||
activating,
|
||||
itemData,
|
||||
enableNum,
|
||||
logInfo = [],
|
||||
|
@ -44,6 +48,7 @@ export const ProfileMore = (props: Props) => {
|
|||
onMoveEnd,
|
||||
onDelete,
|
||||
onEdit,
|
||||
onChange,
|
||||
} = props;
|
||||
|
||||
const { uid, type } = itemData;
|
||||
|
@ -132,6 +137,24 @@ export const ProfileMore = (props: Props) => {
|
|||
event.preventDefault();
|
||||
}}
|
||||
>
|
||||
{activating && (
|
||||
<Box
|
||||
sx={{
|
||||
position: "absolute",
|
||||
display: "flex",
|
||||
justifyContent: "center",
|
||||
alignItems: "center",
|
||||
top: 10,
|
||||
left: 10,
|
||||
right: 10,
|
||||
bottom: 2,
|
||||
zIndex: 10,
|
||||
backdropFilter: "blur(2px)",
|
||||
}}
|
||||
>
|
||||
<CircularProgress color="inherit" size={20} />
|
||||
</Box>
|
||||
)}
|
||||
<Box
|
||||
display="flex"
|
||||
justifyContent="space-between"
|
||||
|
@ -237,11 +260,12 @@ export const ProfileMore = (props: Props) => {
|
|||
open={fileOpen}
|
||||
language={type === "merge" ? "yaml" : "javascript"}
|
||||
schema={type === "merge" ? "merge" : undefined}
|
||||
onChange={onChange}
|
||||
onClose={() => setFileOpen(false)}
|
||||
/>
|
||||
<ConfirmViewer
|
||||
title="Confirm deletion"
|
||||
message="This operation is not reversible"
|
||||
title={t("Confirm deletion")}
|
||||
message={t("This operation is not reversible")}
|
||||
open={confirmOpen}
|
||||
onClose={() => setConfirmOpen(false)}
|
||||
onConfirm={() => {
|
||||
|
|
|
@ -249,10 +249,10 @@ export const SysproxyViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
property={value.pac_content ?? ""}
|
||||
open={editorOpen}
|
||||
language="javascript"
|
||||
onChange={(content) => {
|
||||
onChange={(_prev, curr) => {
|
||||
let pac = DEFAULT_PAC;
|
||||
if (content && content.trim().length > 0) {
|
||||
pac = content;
|
||||
if (curr && curr.trim().length > 0) {
|
||||
pac = curr;
|
||||
}
|
||||
setValue((v) => ({ ...v, pac_content: pac }));
|
||||
}}
|
||||
|
|
|
@ -129,8 +129,8 @@ export const ThemeViewer = forwardRef<DialogRef>((props, ref) => {
|
|||
property={theme.css_injection ?? ""}
|
||||
open={editorOpen}
|
||||
language="css"
|
||||
onChange={(content) => {
|
||||
theme.css_injection = content;
|
||||
onChange={(_prev, curr) => {
|
||||
theme.css_injection = curr;
|
||||
handleChange("css_injection");
|
||||
}}
|
||||
onClose={() => {
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
"Paste": "Paste",
|
||||
"Profile URL": "Profile URL",
|
||||
"Import": "Import",
|
||||
"From": "From",
|
||||
"Update Time": "Update Time",
|
||||
"Used / Total": "Used / Total",
|
||||
"Expire Time": "Expire Time",
|
||||
"Create Profile": "Create Profile",
|
||||
"Edit Profile": "Edit Profile",
|
||||
"Type": "Type",
|
||||
|
@ -178,6 +182,9 @@
|
|||
"Open UWP tool Info": "Since Windows 8, UWP apps (such as Microsoft Store) are restricted from directly accessing local host network services, and this tool can be used to bypass this restriction",
|
||||
"Update GeoData": "Update GeoData",
|
||||
|
||||
"TG Channel": "Telegram Channel",
|
||||
"Manual": "Manual",
|
||||
"Github Repo": "Github Repo",
|
||||
"Verge Setting": "Verge Setting",
|
||||
"Language": "Language",
|
||||
"Theme Mode": "Theme Mode",
|
||||
|
@ -246,9 +253,6 @@
|
|||
"Open Dev Tools": "Open Dev Tools",
|
||||
"Exit": "Exit",
|
||||
"Verge Version": "Verge Version",
|
||||
"TG Channel": "Telegram Channel",
|
||||
"Doc": "Docs",
|
||||
"Source Code": "Source Code",
|
||||
|
||||
"ReadOnly": "ReadOnly",
|
||||
"ReadOnlyMessage": "Cannot edit in read-only editor",
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
"Paste": "چسباندن",
|
||||
"Profile URL": "آدرس پروفایل",
|
||||
"Import": "وارد کردن",
|
||||
"From": "از",
|
||||
"Update Time": "زمان بهروزرسانی",
|
||||
"Used / Total": "استفادهشده / کل",
|
||||
"Expire Time": "زمان انقضا",
|
||||
"Create Profile": "ایجاد پروفایل",
|
||||
"Edit Profile": "ویرایش پروفایل",
|
||||
"Type": "نوع",
|
||||
|
@ -183,6 +187,9 @@
|
|||
"Open UWP tool Info": "از ویندوز 8 به بعد، برنامههای UWP (مانند Microsoft Store) از دسترسی مستقیم به خدمات شبکه محلی محدود شدهاند و این ابزار میتواند برای دور زدن این محدودیت استفاده شود",
|
||||
"Update GeoData": "بهروزرسانی GeoData",
|
||||
|
||||
"TG Channel": "کانال تلگرام",
|
||||
"Manual": "راهنما",
|
||||
"Github Repo": "مخزن GitHub",
|
||||
"Verge Setting": "تنظیمات Verge",
|
||||
"Language": "زبان",
|
||||
"Theme Mode": "حالت تم",
|
||||
|
@ -251,9 +258,6 @@
|
|||
"Open Dev Tools": "باز کردن ابزارهای توسعهدهنده",
|
||||
"Exit": "خروج",
|
||||
"Verge Version": "نسخه Verge",
|
||||
"TG Channel": "کانال تلگرام",
|
||||
"Doc": "سند",
|
||||
"Source Code": "کد منبع",
|
||||
|
||||
"ReadOnly": "فقط خواندنی",
|
||||
"ReadOnlyMessage": "نمیتوان در ویرایشگر فقط خواندنی ویرایش کرد",
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
"Paste": "Вставить",
|
||||
"Profile URL": "URL профиля",
|
||||
"Import": "Импорт",
|
||||
"From": "От",
|
||||
"Update Time": "Время обновления",
|
||||
"Used / Total": "Использовано / Всего",
|
||||
"Expire Time": "Время окончания",
|
||||
"Create Profile": "Создать профиль",
|
||||
"Edit Profile": "Изменить профиль",
|
||||
"Type": "Тип",
|
||||
|
@ -183,6 +187,9 @@
|
|||
"Open UWP tool Info": "С Windows 8 приложения UWP (такие как Microsoft Store) ограничены в прямом доступе к сетевым службам локального хоста, и этот инструмент позволяет обойти это ограничение",
|
||||
"Update GeoData": "Обновление GeoData",
|
||||
|
||||
"TG Channel": "Канал Telegram",
|
||||
"Manual": "Документация",
|
||||
"Github Repo": "GitHub репозиторий",
|
||||
"Verge Setting": "Настройки Verge",
|
||||
"Language": "Язык",
|
||||
"Theme Mode": "Режим темы",
|
||||
|
@ -251,9 +258,6 @@
|
|||
"Open Dev Tools": "Открыть инструменты разработчика",
|
||||
"Exit": "Выход",
|
||||
"Verge Version": "Версия Verge",
|
||||
"TG Channel": "Канал Telegram",
|
||||
"Doc": "документ",
|
||||
"Source Code": "Исходный код",
|
||||
|
||||
"ReadOnly": "Только для чтения",
|
||||
"ReadOnlyMessage": "Невозможно редактировать в режиме только для чтения",
|
||||
|
|
|
@ -49,6 +49,10 @@
|
|||
"Paste": "粘贴",
|
||||
"Profile URL": "订阅文件链接",
|
||||
"Import": "导入",
|
||||
"From": "来自",
|
||||
"Update Time": "更新时间",
|
||||
"Used / Total": "已使用 / 总量",
|
||||
"Expire Time": "到期时间",
|
||||
"Create Profile": "新建配置",
|
||||
"Edit Profile": "编辑配置",
|
||||
"Type": "类型",
|
||||
|
@ -154,6 +158,9 @@
|
|||
"Silent Start": "静默启动",
|
||||
"Silent Start Info": "程序启动时以后台模式运行,不显示程序面板",
|
||||
|
||||
"TG Channel": "Telegram 频道",
|
||||
"Manual": "使用手册",
|
||||
"Github Repo": "GitHub 项目地址",
|
||||
"Clash Setting": "Clash 设置",
|
||||
"Allow Lan": "局域网连接",
|
||||
"IPv6": "IPv6",
|
||||
|
@ -176,7 +183,7 @@
|
|||
"Upgrade": "升级内核",
|
||||
"Restart": "重启内核",
|
||||
"Release Version": "正式版",
|
||||
"Alpha Version": "内测版",
|
||||
"Alpha Version": "测试版",
|
||||
"Tun mode requires": "如需启用 Tun 模式需要授权",
|
||||
"Grant": "授权",
|
||||
"Open UWP tool": "UWP 工具",
|
||||
|
@ -251,9 +258,6 @@
|
|||
"Open Dev Tools": "打开开发者工具",
|
||||
"Exit": "退出",
|
||||
"Verge Version": "Verge 版本",
|
||||
"TG Channel": "Telegram 频道",
|
||||
"Doc": "文档",
|
||||
"Source Code": "源代码",
|
||||
|
||||
"ReadOnly": "只读",
|
||||
"ReadOnlyMessage": "无法在只读模式下编辑",
|
||||
|
|
|
@ -56,7 +56,7 @@ const ProfilePage = () => {
|
|||
|
||||
const [url, setUrl] = useState("");
|
||||
const [disabled, setDisabled] = useState(false);
|
||||
const [activating, setActivating] = useState("");
|
||||
const [activatings, setActivatings] = useState<string[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const sensors = useSensors(
|
||||
useSensor(PointerSensor),
|
||||
|
@ -128,6 +128,10 @@ const ProfilePage = () => {
|
|||
return { regularItems, enhanceItems };
|
||||
}, [profiles]);
|
||||
|
||||
const currentActivatings = () => {
|
||||
return [...new Set([profiles.current ?? "", ...chain])].filter(Boolean);
|
||||
};
|
||||
|
||||
const onImport = async () => {
|
||||
if (!url) return;
|
||||
setLoading(true);
|
||||
|
@ -138,13 +142,13 @@ const ProfilePage = () => {
|
|||
setUrl("");
|
||||
setLoading(false);
|
||||
|
||||
getProfiles().then((newProfiles) => {
|
||||
getProfiles().then(async (newProfiles) => {
|
||||
mutate("getProfiles", newProfiles);
|
||||
|
||||
const remoteItem = newProfiles.items?.find((e) => e.type === "remote");
|
||||
if (!newProfiles.current && remoteItem) {
|
||||
const current = remoteItem.uid;
|
||||
patchProfiles({ current });
|
||||
await patchProfiles({ current });
|
||||
mutateLogs();
|
||||
setTimeout(() => activateSelected(), 2000);
|
||||
}
|
||||
|
@ -171,7 +175,9 @@ const ProfilePage = () => {
|
|||
const onSelect = useLockFn(async (current: string, force: boolean) => {
|
||||
if (!force && current === profiles.current) return;
|
||||
// 避免大多数情况下loading态闪烁
|
||||
const reset = setTimeout(() => setActivating(current), 100);
|
||||
const reset = setTimeout(() => {
|
||||
setActivatings([...currentActivatings(), current]);
|
||||
}, 100);
|
||||
try {
|
||||
await patchProfiles({ current });
|
||||
mutateLogs();
|
||||
|
@ -182,42 +188,64 @@ const ProfilePage = () => {
|
|||
Notice.error(err?.message || err.toString(), 4000);
|
||||
} finally {
|
||||
clearTimeout(reset);
|
||||
setActivating("");
|
||||
setActivatings([]);
|
||||
}
|
||||
});
|
||||
|
||||
const onEnhance = useLockFn(async () => {
|
||||
setActivatings(currentActivatings());
|
||||
try {
|
||||
await enhanceProfiles();
|
||||
mutateLogs();
|
||||
Notice.success(t("Profile Reactivated"), 1000);
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString(), 3000);
|
||||
} finally {
|
||||
setActivatings([]);
|
||||
}
|
||||
});
|
||||
|
||||
const onEnable = useLockFn(async (uid: string) => {
|
||||
if (chain.includes(uid)) return;
|
||||
const newChain = [...chain, uid];
|
||||
await patchProfiles({ chain: newChain });
|
||||
mutateLogs();
|
||||
try {
|
||||
setActivatings([...currentActivatings(), uid]);
|
||||
const newChain = [...chain, uid];
|
||||
await patchProfiles({ chain: newChain });
|
||||
mutateLogs();
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString(), 3000);
|
||||
} finally {
|
||||
setActivatings([]);
|
||||
}
|
||||
});
|
||||
|
||||
const onDisable = useLockFn(async (uid: string) => {
|
||||
if (!chain.includes(uid)) return;
|
||||
const newChain = chain.filter((i) => i !== uid);
|
||||
await patchProfiles({ chain: newChain });
|
||||
mutateLogs();
|
||||
try {
|
||||
setActivatings([...currentActivatings(), uid]);
|
||||
const newChain = chain.filter((i) => i !== uid);
|
||||
await patchProfiles({ chain: newChain });
|
||||
mutateLogs();
|
||||
} catch (err: any) {
|
||||
Notice.error(err.message || err.toString(), 3000);
|
||||
} finally {
|
||||
setActivatings([]);
|
||||
}
|
||||
});
|
||||
|
||||
const onDelete = useLockFn(async (uid: string) => {
|
||||
const current = profiles.current === uid;
|
||||
try {
|
||||
await onDisable(uid);
|
||||
setActivatings([...(current ? currentActivatings() : []), uid]);
|
||||
await deleteProfile(uid);
|
||||
mutateProfiles();
|
||||
mutateLogs();
|
||||
current && (await onEnhance());
|
||||
} catch (err: any) {
|
||||
Notice.error(err?.message || err.toString());
|
||||
} finally {
|
||||
setActivatings([]);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -396,10 +424,14 @@ const ProfilePage = () => {
|
|||
<ProfileItem
|
||||
id={item.uid}
|
||||
selected={profiles.current === item.uid}
|
||||
activating={activating === item.uid}
|
||||
activating={activatings.includes(item.uid)}
|
||||
itemData={item}
|
||||
onSelect={(f) => onSelect(item.uid, f)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
onChange={async (prev, curr) => {
|
||||
prev !== curr && (await onEnhance());
|
||||
}}
|
||||
onDelete={() => onDelete(item.uid)}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
|
@ -423,6 +455,7 @@ const ProfilePage = () => {
|
|||
<Grid item xs={12} sm={6} md={4} lg={3} key={item.file}>
|
||||
<ProfileMore
|
||||
selected={!!chain.includes(item.uid)}
|
||||
activating={activatings.includes(item.uid)}
|
||||
itemData={item}
|
||||
enableNum={chain.length || 0}
|
||||
logInfo={chainLogs[item.uid]}
|
||||
|
@ -432,6 +465,9 @@ const ProfilePage = () => {
|
|||
onMoveTop={() => onMoveTop(item.uid)}
|
||||
onMoveEnd={() => onMoveEnd(item.uid)}
|
||||
onEdit={() => viewerRef.current?.edit(item)}
|
||||
onChange={async (prev, curr) => {
|
||||
prev !== curr && (await onEnhance());
|
||||
}}
|
||||
/>
|
||||
</Grid>
|
||||
))}
|
||||
|
|
|
@ -39,15 +39,7 @@ const SettingPage = () => {
|
|||
<IconButton
|
||||
size="medium"
|
||||
color="inherit"
|
||||
title={t("TG Channel")}
|
||||
onClick={toTelegramChannel}
|
||||
>
|
||||
<Telegram fontSize="inherit" />
|
||||
</IconButton>
|
||||
<IconButton
|
||||
size="medium"
|
||||
color="inherit"
|
||||
title={t("Doc")}
|
||||
title={t("Manual")}
|
||||
onClick={toGithubDoc}
|
||||
>
|
||||
<HelpOutlineSharp fontSize="inherit" />
|
||||
|
@ -55,7 +47,16 @@ const SettingPage = () => {
|
|||
<IconButton
|
||||
size="medium"
|
||||
color="inherit"
|
||||
title={t("Source Code")}
|
||||
title={t("TG Channel")}
|
||||
onClick={toTelegramChannel}
|
||||
>
|
||||
<Telegram fontSize="inherit" />
|
||||
</IconButton>
|
||||
|
||||
<IconButton
|
||||
size="medium"
|
||||
color="inherit"
|
||||
title={t("Github Repo")}
|
||||
onClick={toGithubRepo}
|
||||
>
|
||||
<GitHub fontSize="inherit" />
|
||||
|
|
Loading…
Reference in New Issue
Block a user