diff --git a/src/pages/background/core/rules.ts b/src/pages/background/core/rules.ts
index aeebf4f..8eddaa2 100644
--- a/src/pages/background/core/rules.ts
+++ b/src/pages/background/core/rules.ts
@@ -128,7 +128,7 @@ async function save(o: Rule) {
!o.isFunction &&
[RULE_TYPE.MODIFY_RECV_HEADER, RULE_TYPE.MODIFY_SEND_HEADER, RULE_TYPE.REDIRECT].includes(o.ruleType)
) {
- const writeValue = o.ruleType === RULE_TYPE.REDIRECT ? o.action : (o.action as RULE_ACTION_OBJ).value;
+ const writeValue = o.ruleType === RULE_TYPE.REDIRECT ? o.to : (o.action as RULE_ACTION_OBJ).value;
const key = `rule_switch_${getVirtualKey(o)}`;
const engine = getLocal();
engine.get(key).then((result) => {
diff --git a/src/pages/options/sections/options/index.tsx b/src/pages/options/sections/options/index.tsx
index 84d7f3e..9c321d9 100644
--- a/src/pages/options/sections/options/index.tsx
+++ b/src/pages/options/sections/options/index.tsx
@@ -24,6 +24,7 @@ const checkPrefs: { [key: string]: string } = {
'is-debug': t('debug_mode_enable'),
'rule-switch': t('rule-switch'),
'rule-history': t('rule-history'),
+ 'quick-edit': t('quick-edit'),
};
interface SelectItem {
diff --git a/src/pages/popup/rule/quick-edit.tsx b/src/pages/popup/rule/quick-edit.tsx
new file mode 100644
index 0000000..0be6f6d
--- /dev/null
+++ b/src/pages/popup/rule/quick-edit.tsx
@@ -0,0 +1,115 @@
+import { IconEdit } from '@douyinfe/semi-icons';
+import { Button, Form, Input, Modal } from '@douyinfe/semi-ui';
+import { css } from '@emotion/css';
+import { useLatest } from 'ahooks';
+import React, { ReactNode, useCallback } from 'react';
+import { RULE_TYPE } from '@/share/core/constant';
+import { RULE_ACTION_OBJ, Rule } from '@/share/core/types';
+import { t } from '@/share/core/utils';
+import useOption from '@/share/hooks/use-option';
+import Api from '@/share/pages/api';
+import { Toast } from '@/share/pages/toast';
+
+interface QuickEditProps {
+ rule: Rule;
+}
+
+const QuickEdit = ({ rule }: QuickEditProps) => {
+ const { isFunction, ruleType } = rule;
+ const ruleRef = useLatest(rule);
+
+ const isEnable = useOption('quick-edit', false);
+
+ const handleEdit = useCallback(() => {
+ const newRule = { ...ruleRef.current };
+
+ let content: ReactNode = null;
+ if (newRule.ruleType === RULE_TYPE.REDIRECT) {
+ content = (
+
+ (newRule.to = v)} />
+
+ );
+ }
+
+ if ([RULE_TYPE.MODIFY_RECV_HEADER, RULE_TYPE.MODIFY_SEND_HEADER].includes(newRule.ruleType)) {
+ newRule.action = { ...(newRule.action as RULE_ACTION_OBJ) };
+ content = (
+ <>
+
+ ((newRule.action as RULE_ACTION_OBJ).name = v)}
+ />
+
+
+ ((newRule.action as RULE_ACTION_OBJ).value = v)}
+ />
+
+ >
+ );
+ }
+
+ Modal.confirm({
+ icon: null,
+ closable: false,
+ className: css`
+ .semi-modal {
+ margin: 0;
+ position: fixed;
+ bottom: 0;
+ width: 100%;
+ > .semi-modal-content {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ border-bottom: 0;
+ border-left: 0;
+ border-right: 0;
+
+ > .semi-modal-footer {
+ margin-top: 0;
+ margin-bottom: 12px;
+ }
+ }
+ }
+ `,
+ content,
+ onOk: async () => {
+ if (newRule.ruleType === 'redirect' && (!newRule.to || newRule.to === '')) {
+ Toast().error(t('redirect_empty'));
+ return;
+ }
+ if (
+ (newRule.ruleType === 'modifySendHeader' || newRule.ruleType === 'modifyReceiveHeader') &&
+ (typeof newRule.action !== 'object' || newRule.action.name === '')
+ ) {
+ Toast().error(t('header_empty'));
+ return;
+ }
+ try {
+ await Api.saveRule(newRule);
+ Toast().success(t('saved'));
+ } catch (e) {
+ Toast().error(e.message);
+ }
+ },
+ });
+ }, []);
+
+ if (!isEnable) {
+ return null;
+ }
+
+ if (
+ isFunction ||
+ ![RULE_TYPE.MODIFY_RECV_HEADER, RULE_TYPE.MODIFY_SEND_HEADER, RULE_TYPE.REDIRECT].includes(ruleType)
+ ) {
+ return null;
+ }
+
+ return } onClick={handleEdit} />;
+};
+
+export default QuickEdit;
diff --git a/src/pages/popup/rule/rules.tsx b/src/pages/popup/rule/rules.tsx
index 14f447b..936da72 100644
--- a/src/pages/popup/rule/rules.tsx
+++ b/src/pages/popup/rule/rules.tsx
@@ -12,6 +12,7 @@ import RuleDetail from '@/share/components/rule-detail';
import notify from '@/share/core/notify';
import RuleContentSwitcher from '@/share/components/rule-content-switcher';
import { textEllipsis } from '@/share/pages/styles';
+import QuickEdit from './quick-edit';
const Rules = () => {
const { keys } = useMarkCommon('rule');
@@ -112,9 +113,12 @@ const Rules = () => {
} style={{ maxWidth: '300px' }}>
{item.name}
-
- } />
-
+
+
+
+ } />
+
+
))}
diff --git a/src/share/core/constant.ts b/src/share/core/constant.ts
index f89b75b..96e137b 100644
--- a/src/share/core/constant.ts
+++ b/src/share/core/constant.ts
@@ -38,6 +38,7 @@ export const defaultPrefValue: PrefValue = {
'dark-mode': 'auto',
'rule-switch': true,
'rule-history': true,
+ 'quick-edit': true,
};
export enum APIs {
diff --git a/src/share/core/types.ts b/src/share/core/types.ts
index 521203e..758899f 100644
--- a/src/share/core/types.ts
+++ b/src/share/core/types.ts
@@ -59,4 +59,7 @@ export interface PrefValue {
'modify-body': boolean; // Enable modify received body feature
'is-debug': boolean;
'dark-mode': 'auto' | 'on' | 'off';
+ 'rule-switch': boolean; // Enable rule quick switch
+ 'rule-history': boolean; // Auto save rule history into quick switch
+ 'quick-edit': boolean; // Quick edit rule in popup panel
}