Skip to content

Commit d53289e

Browse files
committed
feat: enhance popup
1 parent 1d5ede8 commit d53289e

File tree

8 files changed

+231
-92
lines changed

8 files changed

+231
-92
lines changed

src/pages/background/core/rules.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,10 @@ function filter(fromRules: InitdRule[], options?: RuleFilterOptions) {
110110
return false;
111111
}
112112

113+
if (options.group && rule.group !== options.group) {
114+
return false;
115+
}
116+
113117
if (typeof options.id !== 'undefined') {
114118
if (Array.isArray(options.id)) {
115119
if (!options.id.includes(rule.id)) {

src/pages/popup/index.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,22 @@ const basicStyle = css`
3838
display: flex;
3939
flex-direction: column;
4040
41-
> .item {
41+
> .title {
42+
padding: 8px;
43+
font-weight: bold;
44+
color: var(--semi-color-tertiary);
45+
display: flex;
46+
align-items: center;
47+
justify-content: space-between;
48+
49+
&.group {
50+
padding-top: 4px;
51+
padding-right: 4px;
52+
padding-bottom: 4px;
53+
}
54+
}
55+
56+
.item {
4257
display: flex;
4358
flex-direction: row;
4459
gap: 8px;

src/pages/popup/rules/all-rules.tsx

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,6 @@ import Api from '@/share/pages/api';
1414
import { textEllipsis } from '@/share/pages/styles';
1515
import QuickEdit from './quick-edit';
1616

17-
const titleStyle = css`
18-
font-size: 12px;
19-
font-weight: 500;
20-
line-height: 24px;
21-
padding: 0 8px;
22-
overflow: hidden;
23-
white-space: nowrap;
24-
text-overflow: ellipsis;
25-
`;
26-
2717
const AllRules = () => {
2818
const {
2919
data = [],
@@ -123,7 +113,7 @@ const AllRules = () => {
123113
}
124114
return (
125115
<Fragment key={item.group}>
126-
<div className={titleStyle}>{item.group}</div>
116+
<div className="title">{item.group}</div>
127117
{itemDOM}
128118
</Fragment>
129119
);
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
import { Spin } from '@douyinfe/semi-ui';
2+
import { useLatest, useRequest } from 'ahooks';
3+
import { type FC, useEffect } from 'react';
4+
import { EVENTs, TABLE_NAMES_ARR, VIRTUAL_KEY } from '@/share/core/constant';
5+
import notify from '@/share/core/notify';
6+
import type { Rule } from '@/share/core/types';
7+
import { getVirtualKey } from '@/share/core/utils';
8+
import Api from '@/share/pages/api';
9+
import RuleItem from './rule-item';
10+
11+
interface GroupItemProps {
12+
group: string;
13+
}
14+
15+
const GroupItem: FC<GroupItemProps> = ({ group }) => {
16+
const {
17+
data = [],
18+
loading,
19+
refresh,
20+
} = useRequest(
21+
async () =>
22+
(
23+
await Promise.all(
24+
TABLE_NAMES_ARR.map(t =>
25+
Api.getRules(t, {
26+
group,
27+
}),
28+
),
29+
)
30+
)
31+
.flat(1)
32+
.map(x => ({ ...x, [VIRTUAL_KEY]: getVirtualKey(x) })),
33+
{
34+
manual: false,
35+
refreshDeps: [group],
36+
},
37+
);
38+
39+
const dataRef = useLatest(data);
40+
41+
useEffect(() => {
42+
const handleRuleUpdate = (request: any) => {
43+
const rule: Rule = request.target;
44+
const key = getVirtualKey(rule);
45+
if (dataRef.current.some(x => getVirtualKey(x) === key)) {
46+
refresh();
47+
}
48+
};
49+
50+
notify.event.on(EVENTs.RULE_UPDATE, handleRuleUpdate);
51+
52+
return () => {
53+
notify.event.off(EVENTs.RULE_UPDATE, handleRuleUpdate);
54+
};
55+
}, []);
56+
57+
if (Object.keys(data).length === 0 && !loading) {
58+
return null;
59+
}
60+
61+
return (
62+
<Spin spinning={loading}>
63+
{data.map(item => (
64+
<RuleItem key={item[VIRTUAL_KEY]} rule={item} />
65+
))}
66+
</Spin>
67+
);
68+
};
69+
70+
export default GroupItem;

src/pages/popup/rules/common/group.tsx

Lines changed: 28 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import { IconLock, IconUnlock } from '@douyinfe/semi-icons';
22
import { Button, ButtonGroup, Tooltip } from '@douyinfe/semi-ui';
33
import { flatten } from 'lodash-es';
4+
import { Fragment } from 'react';
45
import { isValidArray, t } from '@/share/core/utils';
56
import useMarkCommon from '@/share/hooks/use-mark-common';
67
import Api from '@/share/pages/api';
78
import { Toast } from '@/share/pages/toast';
9+
import GroupItem from './group-item';
810

911
const toggleGroup = async (name: string, target: boolean) => {
1012
const rules = flatten(Object.values(await Api.getAllRules()));
@@ -33,29 +35,32 @@ const Group = () => {
3335
return (
3436
<div className="item-block">
3537
{keys.map(key => (
36-
<div className="item" key={key}>
37-
<div className="name">{key}</div>
38-
<ButtonGroup>
39-
<Tooltip content={t('enable')}>
40-
<Button
41-
theme="borderless"
42-
type="tertiary"
43-
onClick={() => toggleGroup(key, true)}
44-
size="small"
45-
icon={<IconUnlock />}
46-
/>
47-
</Tooltip>
48-
<Tooltip content={t('disable')}>
49-
<Button
50-
theme="borderless"
51-
type="tertiary"
52-
onClick={() => toggleGroup(key, false)}
53-
size="small"
54-
icon={<IconLock />}
55-
/>
56-
</Tooltip>
57-
</ButtonGroup>
58-
</div>
38+
<Fragment key={key}>
39+
<div className="title group">
40+
<div className="name">{key}</div>
41+
<ButtonGroup>
42+
<Tooltip content={t('enable')}>
43+
<Button
44+
theme="borderless"
45+
type="tertiary"
46+
onClick={() => toggleGroup(key, true)}
47+
size="small"
48+
icon={<IconUnlock />}
49+
/>
50+
</Tooltip>
51+
<Tooltip content={t('disable')}>
52+
<Button
53+
theme="borderless"
54+
type="tertiary"
55+
onClick={() => toggleGroup(key, false)}
56+
size="small"
57+
icon={<IconLock />}
58+
/>
59+
</Tooltip>
60+
</ButtonGroup>
61+
</div>
62+
<GroupItem group={key} />
63+
</Fragment>
5964
))}
6065
</div>
6166
);
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { IconBranch } from '@douyinfe/semi-icons';
2+
import { Button, Popover, Switch } from '@douyinfe/semi-ui';
3+
import { cx } from '@emotion/css';
4+
import type { FC } from 'react';
5+
import RuleContentSwitcher from '@/share/components/rule-content-switcher';
6+
import RuleDetail from '@/share/components/rule-detail';
7+
import type { Rule } from '@/share/core/types';
8+
import Api from '@/share/pages/api';
9+
import { textEllipsis } from '@/share/pages/styles';
10+
import QuickEdit from '../quick-edit';
11+
12+
interface RuleItemProps {
13+
rule: Rule;
14+
}
15+
16+
const RuleItem: FC<RuleItemProps> = ({ rule }) => {
17+
return (
18+
<div className="item">
19+
<Switch
20+
size="small"
21+
checked={rule.enable}
22+
onChange={checked =>
23+
Api.saveRule({
24+
...rule,
25+
enable: checked,
26+
})
27+
}
28+
/>
29+
<Popover
30+
showArrow
31+
position="top"
32+
content={<RuleDetail rule={rule} size="small" />}
33+
style={{ maxWidth: '300px' }}
34+
>
35+
<div className={cx(textEllipsis, 'name')}>{rule.name}</div>
36+
</Popover>
37+
<div className="actions">
38+
<QuickEdit rule={rule} />
39+
<RuleContentSwitcher
40+
rule={rule}
41+
type={rule.ruleType}
42+
size="small"
43+
add={false}
44+
>
45+
<Button
46+
theme="borderless"
47+
type="tertiary"
48+
size="small"
49+
icon={<IconBranch />}
50+
/>
51+
</RuleContentSwitcher>
52+
</div>
53+
</div>
54+
);
55+
};
56+
57+
export default RuleItem;

0 commit comments

Comments
 (0)