feat: enhance profile status
This commit is contained in:
parent
dad94edb20
commit
d63d49f246
@ -127,7 +127,7 @@ const ProfileItem = (props: Props) => {
|
|||||||
const urlModeMenu = [
|
const urlModeMenu = [
|
||||||
{ label: "Select", handler: onForceSelect },
|
{ label: "Select", handler: onForceSelect },
|
||||||
{ label: "Edit", handler: onEdit },
|
{ label: "Edit", handler: onEdit },
|
||||||
{ label: "View", handler: onView },
|
{ label: "File", handler: onView },
|
||||||
{ label: "Update", handler: onUpdateWrapper(false) },
|
{ label: "Update", handler: onUpdateWrapper(false) },
|
||||||
{ label: "Update(Proxy)", handler: onUpdateWrapper(true) },
|
{ label: "Update(Proxy)", handler: onUpdateWrapper(true) },
|
||||||
{ label: "Delete", handler: onDelete },
|
{ label: "Delete", handler: onDelete },
|
||||||
@ -135,7 +135,7 @@ const ProfileItem = (props: Props) => {
|
|||||||
const fileModeMenu = [
|
const fileModeMenu = [
|
||||||
{ label: "Select", handler: onForceSelect },
|
{ label: "Select", handler: onForceSelect },
|
||||||
{ label: "Edit", handler: onEdit },
|
{ label: "Edit", handler: onEdit },
|
||||||
{ label: "View", handler: onView },
|
{ label: "File", handler: onView },
|
||||||
{ label: "Delete", handler: onDelete },
|
{ label: "Delete", handler: onDelete },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
import { useState } from "react";
|
import { useEffect, useState } from "react";
|
||||||
import {
|
import {
|
||||||
alpha,
|
alpha,
|
||||||
Box,
|
Box,
|
||||||
@ -14,6 +14,7 @@ import { viewProfile } from "../../services/cmds";
|
|||||||
import relativeTime from "dayjs/plugin/relativeTime";
|
import relativeTime from "dayjs/plugin/relativeTime";
|
||||||
import ProfileEdit from "./profile-edit";
|
import ProfileEdit from "./profile-edit";
|
||||||
import Notice from "../base/base-notice";
|
import Notice from "../base/base-notice";
|
||||||
|
import enhance from "../../services/enhance";
|
||||||
|
|
||||||
dayjs.extend(relativeTime);
|
dayjs.extend(relativeTime);
|
||||||
|
|
||||||
@ -52,10 +53,17 @@ const ProfileMore = (props: Props) => {
|
|||||||
onEnhance,
|
onEnhance,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const { type } = itemData;
|
const { uid, type } = itemData;
|
||||||
const [anchorEl, setAnchorEl] = useState<any>(null);
|
const [anchorEl, setAnchorEl] = useState<any>(null);
|
||||||
const [position, setPosition] = useState({ left: 0, top: 0 });
|
const [position, setPosition] = useState({ left: 0, top: 0 });
|
||||||
const [editOpen, setEditOpen] = useState(false);
|
const [editOpen, setEditOpen] = useState(false);
|
||||||
|
const [status, setStatus] = useState(enhance.status(uid));
|
||||||
|
|
||||||
|
// unlisten when unmount
|
||||||
|
useEffect(() => enhance.listen(uid, setStatus), [uid]);
|
||||||
|
|
||||||
|
// error during enhanced mode
|
||||||
|
const hasError = status?.status === "error";
|
||||||
|
|
||||||
const onEdit = () => {
|
const onEdit = () => {
|
||||||
setAnchorEl(null);
|
setAnchorEl(null);
|
||||||
@ -80,16 +88,16 @@ const ProfileMore = (props: Props) => {
|
|||||||
{ label: "Disable", handler: closeWrapper(onDisable) },
|
{ label: "Disable", handler: closeWrapper(onDisable) },
|
||||||
{ label: "Refresh", handler: closeWrapper(onEnhance) },
|
{ label: "Refresh", handler: closeWrapper(onEnhance) },
|
||||||
{ label: "Edit", handler: onEdit },
|
{ label: "Edit", handler: onEdit },
|
||||||
{ label: "View", handler: onView },
|
{ label: "File", handler: onView },
|
||||||
{ label: "To Top", handler: closeWrapper(onMoveTop) },
|
{ label: "To Top", show: !hasError, handler: closeWrapper(onMoveTop) },
|
||||||
{ label: "To End", handler: closeWrapper(onMoveEnd) },
|
{ label: "To End", show: !hasError, handler: closeWrapper(onMoveEnd) },
|
||||||
{ label: "Delete", handler: closeWrapper(onDelete) },
|
{ label: "Delete", handler: closeWrapper(onDelete) },
|
||||||
];
|
];
|
||||||
|
|
||||||
const disableMenu = [
|
const disableMenu = [
|
||||||
{ label: "Enable", handler: closeWrapper(onEnable) },
|
{ label: "Enable", handler: closeWrapper(onEnable) },
|
||||||
{ label: "Edit", handler: onEdit },
|
{ label: "Edit", handler: onEdit },
|
||||||
{ label: "View", handler: onView },
|
{ label: "File", handler: onView },
|
||||||
{ label: "Delete", handler: closeWrapper(onDelete) },
|
{ label: "Delete", handler: closeWrapper(onDelete) },
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -105,15 +113,20 @@ const ProfileMore = (props: Props) => {
|
|||||||
<>
|
<>
|
||||||
<Wrapper
|
<Wrapper
|
||||||
sx={({ palette }) => {
|
sx={({ palette }) => {
|
||||||
const { mode, primary, text, grey } = palette;
|
// todo
|
||||||
|
// 区分 selected 和 error 和 mode 下各种颜色的排列组合
|
||||||
|
const { mode, primary, text, grey, error } = palette;
|
||||||
const key = `${mode}-${selected}`;
|
const key = `${mode}-${selected}`;
|
||||||
|
const bgkey = hasError ? `${mode}-err` : key;
|
||||||
|
|
||||||
const bgcolor = {
|
const bgcolor = {
|
||||||
"light-true": alpha(primary.main, 0.15),
|
"light-true": alpha(primary.main, 0.15),
|
||||||
"light-false": palette.background.paper,
|
"light-false": palette.background.paper,
|
||||||
"dark-true": alpha(primary.main, 0.35),
|
"dark-true": alpha(primary.main, 0.35),
|
||||||
"dark-false": alpha(grey[700], 0.35),
|
"dark-false": alpha(grey[700], 0.35),
|
||||||
}[key]!;
|
"light-err": alpha(error.main, 0.12),
|
||||||
|
"dark-err": alpha(error.main, 0.3),
|
||||||
|
}[bgkey]!;
|
||||||
|
|
||||||
const color = {
|
const color = {
|
||||||
"light-true": text.secondary,
|
"light-true": text.secondary,
|
||||||
@ -160,13 +173,24 @@ const ProfileMore = (props: Props) => {
|
|||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
<Box sx={boxStyle}>
|
<Box sx={boxStyle}>
|
||||||
<Typography
|
{hasError ? (
|
||||||
noWrap
|
<Typography
|
||||||
title={itemData.desc}
|
noWrap
|
||||||
sx={{ width: "calc(100% - 75px)" }}
|
color="error"
|
||||||
>
|
sx={{ width: "calc(100% - 75px)" }}
|
||||||
{itemData.desc}
|
title={status.message}
|
||||||
</Typography>
|
>
|
||||||
|
{status.message}
|
||||||
|
</Typography>
|
||||||
|
) : (
|
||||||
|
<Typography
|
||||||
|
noWrap
|
||||||
|
title={itemData.desc}
|
||||||
|
sx={{ width: "calc(100% - 75px)" }}
|
||||||
|
>
|
||||||
|
{itemData.desc}
|
||||||
|
</Typography>
|
||||||
|
)}
|
||||||
|
|
||||||
<Typography
|
<Typography
|
||||||
component="span"
|
component="span"
|
||||||
@ -189,15 +213,17 @@ const ProfileMore = (props: Props) => {
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(selected ? enableMenu : disableMenu).map((item) => (
|
{(selected ? enableMenu : disableMenu)
|
||||||
<MenuItem
|
.filter((item: any) => item.show !== false)
|
||||||
key={item.label}
|
.map((item) => (
|
||||||
onClick={item.handler}
|
<MenuItem
|
||||||
sx={{ minWidth: 133 }}
|
key={item.label}
|
||||||
>
|
onClick={item.handler}
|
||||||
{item.label}
|
sx={{ minWidth: 133 }}
|
||||||
</MenuItem>
|
>
|
||||||
))}
|
{item.label}
|
||||||
|
</MenuItem>
|
||||||
|
))}
|
||||||
</Menu>
|
</Menu>
|
||||||
|
|
||||||
{editOpen && (
|
{editOpen && (
|
||||||
|
@ -6,9 +6,9 @@ import ReactDOM from "react-dom";
|
|||||||
import { RecoilRoot } from "recoil";
|
import { RecoilRoot } from "recoil";
|
||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import Layout from "./pages/_layout";
|
import Layout from "./pages/_layout";
|
||||||
import setup from "./services/enhance";
|
import enhance from "./services/enhance";
|
||||||
|
|
||||||
setup();
|
enhance.setup();
|
||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
import { emit, listen } from "@tauri-apps/api/event";
|
import { emit, listen } from "@tauri-apps/api/event";
|
||||||
import { CmdType } from "./types";
|
import { CmdType } from "./types";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* process the merge mode
|
||||||
|
*/
|
||||||
function toMerge(
|
function toMerge(
|
||||||
merge: CmdType.ProfileMerge,
|
merge: CmdType.ProfileMerge,
|
||||||
data: CmdType.ProfileData
|
data: CmdType.ProfileData
|
||||||
@ -42,6 +45,9 @@ function toMerge(
|
|||||||
return newData;
|
return newData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* process the script mode
|
||||||
|
*/
|
||||||
function toScript(
|
function toScript(
|
||||||
script: string,
|
script: string,
|
||||||
data: CmdType.ProfileData
|
data: CmdType.ProfileData
|
||||||
@ -53,44 +59,89 @@ function toScript(
|
|||||||
const paramsName = `__verge${Math.floor(Math.random() * 1000)}`;
|
const paramsName = `__verge${Math.floor(Math.random() * 1000)}`;
|
||||||
const code = `'use strict';${script};return main(${paramsName});`;
|
const code = `'use strict';${script};return main(${paramsName});`;
|
||||||
const func = new Function(paramsName, code);
|
const func = new Function(paramsName, code);
|
||||||
return func(data); // support async main function
|
return func(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function setup() {
|
export type EStatus = { status: "ok" | "error"; message?: string };
|
||||||
listen("script-handler", async (event) => {
|
export type EListener = (status: EStatus) => void;
|
||||||
const payload = event.payload as CmdType.EnhancedPayload;
|
export type EUnlistener = () => void;
|
||||||
console.log(payload);
|
|
||||||
|
|
||||||
let pdata = payload.current || {};
|
/**
|
||||||
|
* The service helps to
|
||||||
|
* implement enhanced profiles
|
||||||
|
*/
|
||||||
|
class Enhance {
|
||||||
|
private isSetup = false;
|
||||||
|
private listenMap: Map<string, EListener>;
|
||||||
|
private resultMap: Map<string, EStatus>;
|
||||||
|
|
||||||
for (const each of payload.chain) {
|
constructor() {
|
||||||
try {
|
this.listenMap = new Map();
|
||||||
// process script
|
this.resultMap = new Map();
|
||||||
if (each.item.type === "script") {
|
}
|
||||||
pdata = await toScript(each.script!, pdata);
|
|
||||||
|
// setup some listener
|
||||||
|
// for the enhanced running status
|
||||||
|
listen(uid: string, cb: EListener): EUnlistener {
|
||||||
|
this.listenMap.set(uid, cb);
|
||||||
|
return () => this.listenMap.delete(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get the running status
|
||||||
|
status(uid: string): EStatus | undefined {
|
||||||
|
return this.resultMap.get(uid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup the handler
|
||||||
|
setup() {
|
||||||
|
if (this.isSetup) return;
|
||||||
|
this.isSetup = true;
|
||||||
|
|
||||||
|
listen("script-handler", async (event) => {
|
||||||
|
const payload = event.payload as CmdType.EnhancedPayload;
|
||||||
|
let pdata = payload.current || {};
|
||||||
|
|
||||||
|
for (const each of payload.chain) {
|
||||||
|
const { uid, type = "" } = each.item;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// process script
|
||||||
|
if (type === "script") {
|
||||||
|
// support async main function
|
||||||
|
pdata = await toScript(each.script!, { ...pdata });
|
||||||
|
}
|
||||||
|
|
||||||
|
// process merge
|
||||||
|
else if (type === "merge") {
|
||||||
|
pdata = toMerge(each.merge!, { ...pdata });
|
||||||
|
}
|
||||||
|
|
||||||
|
// invalid type
|
||||||
|
else {
|
||||||
|
throw new Error(`invalid enhanced profile type "${type}"`);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exec(uid, { status: "ok" });
|
||||||
|
} catch (err: any) {
|
||||||
|
this.exec(uid, {
|
||||||
|
status: "error",
|
||||||
|
message: err.message || err.toString(),
|
||||||
|
});
|
||||||
|
|
||||||
|
console.error(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
// process merge
|
|
||||||
else if (each.item.type === "merge") {
|
|
||||||
pdata = toMerge(each.merge!, pdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
// invalid type
|
|
||||||
else {
|
|
||||||
throw new Error(`invalid enhanced profile type "${each.item.type}"`);
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log("step", pdata);
|
|
||||||
} catch (err) {
|
|
||||||
console.error(err);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
const result: CmdType.EnhancedResult = {
|
const result = { data: pdata, status: "ok" };
|
||||||
data: pdata,
|
emit(payload.callback, JSON.stringify(result)).catch(console.error);
|
||||||
status: "success",
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
emit(payload.callback, JSON.stringify(result)).catch(console.error);
|
// exec the listener
|
||||||
});
|
private exec(uid: string, status: EStatus) {
|
||||||
|
this.resultMap.set(uid, status);
|
||||||
|
this.listenMap.get(uid)?.(status);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default new Enhance();
|
||||||
|
Loading…
Reference in New Issue
Block a user