Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 设置页面单页化 & 支持划词功能禁止使用 #195

Merged
merged 1 commit into from
Nov 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 40 additions & 19 deletions src/background/core/configManager/wordMark.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
WordMarkConfigKey,
IWordMarkConfig,
defaultWordMarkConfig,
} from '@/isomorphic/constant/wordMark';
Expand All @@ -11,30 +10,22 @@ import Storage from '../storage';

class WordMarkConfigManager {
async get() {
const config: IWordMarkConfig =
(await Storage.get(STORAGE_KEYS.SETTINGS.WORD_MARK_CONFIG)) || {};

// 做一次 config 的合并,保证获取时一定包含 config 中的每一个元素
for (const _key of Object.keys(defaultWordMarkConfig)) {
const key = _key as keyof IWordMarkConfig;
const value = config[key];
if (typeof value === 'undefined') {
config[key] = defaultWordMarkConfig[key] as never;
}
}

return config;
const config = await this.getStorageConfig();
return this.transformConfig(config);
}

async update(key: string, value: any, option?: IConfigManagerOption) {
const config = await this.get();
async update(
key: keyof IWordMarkConfig,
value: any,
option?: IConfigManagerOption,
) {
const config = await this.getStorageConfig();
const result: IWordMarkConfig = {
...config,
[key]: value,
};

// enable 改变时,将 disable url 全部清空
if (key === WordMarkConfigKey.enable) {
if (key === 'enable') {
result.disableUrl = [];
}
await Chrome.storage.local.set({
Expand All @@ -58,12 +49,42 @@ class WordMarkConfigManager {
if (tab.id) {
Chrome.tabs.sendMessage(tab.id, {
action: ContentScriptEvents.WordMarkConfigChange,
data: config,
data: this.transformConfig(config),
});
}
}
});
}

private async getStorageConfig() {
const config: IWordMarkConfig =
(await Storage.get(STORAGE_KEYS.SETTINGS.WORD_MARK_CONFIG)) || {};

// 做一次 config 的合并,保证获取时一定包含 config 中的每一个元素
for (const _key of Object.keys(defaultWordMarkConfig)) {
const key = _key as keyof IWordMarkConfig;
const value = config[key];
if (typeof value === 'undefined') {
config[key] = defaultWordMarkConfig[key] as never;
}
}
return config;
}

private transformConfig(config: IWordMarkConfig) {
const disableFunction = config.disableFunction;

const result = {
...config,
filterInnerPinList: config.innerPinList.filter(
item => !disableFunction.includes(item),
),
filterToolbars: config.toolbars.filter(
item => !disableFunction.includes(item),
),
};
return result;
}
}

export const wordMarkConfigManager = new WordMarkConfigManager();
10 changes: 8 additions & 2 deletions src/components/WordMarkLayout/context.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
import { createContext } from 'react';
import { IWordMarkConfig } from '@/isomorphic/constant/wordMark';
import { WordMarkOptionTypeEnum } from '@/isomorphic/constants';

export type IWordMarkContext = IWordMarkConfig;
export const WordMarkContext = createContext<IWordMarkContext>({} as IWordMarkContext);
export type IWordMarkContext = IWordMarkConfig & {
filterInnerPinList: Array<WordMarkOptionTypeEnum>;
filterToolbars: Array<WordMarkOptionTypeEnum>;
};
export const WordMarkContext = createContext<IWordMarkContext>(
{} as IWordMarkContext,
);
9 changes: 4 additions & 5 deletions src/core/bridge/background/configManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,16 @@ import { BackgroundEvents } from '@/isomorphic/background';
import {
OperateConfigManagerEnum,
IConfigManagerOption,
ManagerType,
ManagerKey,
} from '@/isomorphic/background/configManager';
import type { ICallBridgeImpl } from './index';

export function createConfigManagerBridge(impl: ICallBridgeImpl) {
return {
configManager: {
async update(
managerType: ManagerType,
key: ManagerKey,
async update<T extends keyof ManagerKey>(
managerType: T,
key: ManagerKey[T],
value: any,
option?: IConfigManagerOption,
): Promise<boolean> {
Expand All @@ -33,7 +32,7 @@ export function createConfigManagerBridge(impl: ICallBridgeImpl) {
});
},

async get(managerType: ManagerType): Promise<any> {
async get<T extends keyof ManagerKey>(managerType: T): Promise<any> {
return new Promise(resolve => {
impl(
BackgroundEvents.OperateManagerConfig,
Expand Down
8 changes: 6 additions & 2 deletions src/isomorphic/background/configManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,12 @@ export enum OperateConfigManagerEnum {
update = 'update',
}

export type ManagerType = 'wordMark' | 'levitate';
export type ManagerKey = WordMarkConfigKey | LevitateConfigKey;
export type ManagerKey = {
wordMark: WordMarkConfigKey,
levitate: LevitateConfigKey
};

export type ManagerType = keyof ManagerKey;

export interface IConfigManagerOption {
notice?: boolean;
Expand Down
6 changes: 3 additions & 3 deletions src/isomorphic/constant/levitate.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
export type LevitateConfigKey = 'enable' | 'disableUrl' | 'position';

export interface ILevitateConfig {
export type ILevitateConfig = {
disableUrl: Array<{
origin: string;
icon: string;
Expand All @@ -9,6 +7,8 @@ export interface ILevitateConfig {
enable: boolean;
}

export type LevitateConfigKey = keyof ILevitateConfig;

export const defaultLevitateConfig: ILevitateConfig = {
enable: true,
disableUrl: [],
Expand Down
30 changes: 13 additions & 17 deletions src/isomorphic/constant/wordMark.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,34 @@
import { ISavePosition } from '@/core/bridge/background/request/mine';
import { WordMarkOptionTypeEnum } from '../constants';

export enum WordMarkConfigKey {
export type IWordMarkConfig = {
// 是否开启
enable = 'enable',
enable: boolean;

// 剪藏默认存储地址
defaultSavePosition = 'defaultSavePosition',
defaultSavePosition: ISavePosition;

// 划词置顶的操作
innerPinList = 'innerPinList',
innerPinList: Array<WordMarkOptionTypeEnum>;

// 禁用页面的 url
disableUrl = 'disableUrl',
disableUrl: Array<string>;

// 剪藏时唤起面板
evokePanelWhenClip = 'evokePanelWhenClip',
evokePanelWhenClip: boolean;

// 剪藏面板的排序规则
toolbars = 'toolbars',
toolbars: Array<WordMarkOptionTypeEnum>;

// 换次面板快捷键
evokeWordMarkShortKey = 'evokeWordMarkShortKey',
}
evokeWordMarkShortKey: string;

export interface IWordMarkConfig {
[WordMarkConfigKey.enable]: boolean;
[WordMarkConfigKey.defaultSavePosition]: ISavePosition;
[WordMarkConfigKey.innerPinList]: Array<WordMarkOptionTypeEnum>;
[WordMarkConfigKey.disableUrl]: Array<string>;
[WordMarkConfigKey.evokePanelWhenClip]: boolean;
[WordMarkConfigKey.toolbars]: Array<WordMarkOptionTypeEnum>;
[WordMarkConfigKey.evokeWordMarkShortKey]: string;
// 用户关闭的划词的某个功能
disableFunction: Array<WordMarkOptionTypeEnum>;
}

export type WordMarkConfigKey = keyof IWordMarkConfig;

export const defaultWordMarkConfig: IWordMarkConfig = {
enable: false,
defaultSavePosition: {
Expand All @@ -49,4 +44,5 @@ export const defaultWordMarkConfig: IWordMarkConfig = {
evokePanelWhenClip: false,
toolbars: [WordMarkOptionTypeEnum.clipping, WordMarkOptionTypeEnum.translate],
evokeWordMarkShortKey: '',
disableFunction: [],
};
6 changes: 3 additions & 3 deletions src/isomorphic/link-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ const LinkHelper = {
joinGroup:
'https://www.yuque.com/yuque/yuque-browser-extension/welcome#BQrrd',
settingPage: chrome.runtime.getURL('setting.html'),
wordMarkSettingPage: `${chrome.runtime.getURL('setting.html')}?page=wordMark`,
shortcutSettingPage: `${chrome.runtime.getURL('setting.html')}?page=shortcut`,
sidePanelSettingPage: `${chrome.runtime.getURL('setting.html')}?page=sidePanel`,
wordMarkSettingPage: `${chrome.runtime.getURL('setting.html')}#wordMark`,
shortcutSettingPage: `${chrome.runtime.getURL('setting.html')}#shortcut`,
sidePanelSettingPage: `${chrome.runtime.getURL('setting.html')}#sidePanel`,
};

export default LinkHelper;
10 changes: 7 additions & 3 deletions src/pages/inject/LevitateBall/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ function App() {

const onCloseLevitateBall = () => {
let disableType: DisableType = 'disableOnce';
Modal.confirm({
const modal = Modal.confirm({});
modal.update({
content: (
<AntdLayout>
<Radio.Group
Expand Down Expand Up @@ -108,13 +109,16 @@ function App() {
footer: (
<AntdLayout>
<div className={styles.disableModalFooter}>
<Button className={styles.button} onClick={Modal.destroyAll}>
<Button className={styles.button} onClick={modal.destroy}>
{__i18n('取消')}
</Button>
<Button
className={classnames(styles.button, styles.sure)}
type="primary"
onClick={() => disableLevitateBall(disableType)}
onClick={() => {
disableLevitateBall(disableType);
modal.destroy();
}}
>
{__i18n('确定')}
</Button>
Expand Down
14 changes: 4 additions & 10 deletions src/pages/inject/WordMark/Inner/DisableMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,26 +1,20 @@
import React from 'react';
import { __i18n } from '@/isomorphic/i18n';
import LinkHelper from '@/isomorphic/link-helper';
import { WordMarkConfigKey } from '@/isomorphic/constant/wordMark';
import { backgroundBridge } from '@/core/bridge/background';
import styles from './DisableMenu.module.less';

function DisableMenu() {
const disableForever = () => {
backgroundBridge.configManager.update(
'wordMark',
WordMarkConfigKey.enable,
false,
{
notice: true,
},
);
backgroundBridge.configManager.update('wordMark', 'enable', false, {
notice: true,
});
};

const disableForPage = () => {
backgroundBridge.configManager.update(
'wordMark',
WordMarkConfigKey.disableUrl,
'disableUrl',
`${window.location.origin}${window.location.pathname}`,
{
notice: true,
Expand Down
11 changes: 4 additions & 7 deletions src/pages/inject/WordMark/Inner/OperateMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { PushpinOutlined, PushpinFilled } from '@ant-design/icons';
import classnames from 'classnames';
import { backgroundBridge } from '@/core/bridge/background';
import { WordMarkOptionTypeEnum } from '@/isomorphic/constants';
import { WordMarkConfigKey } from '@/isomorphic/constant/wordMark';
import { useWordMarkContext } from '@/components/WordMarkLayout/useWordMarkContext';
import DragList from '@/components/DragList';
import { ToolbarItem, toolbars as defaultToolbars } from '../constants';
Expand All @@ -26,11 +25,7 @@ function OperateMenu(props: IOperateMenuProps) {
const updateToolbar = (list: ToolbarItem[]) => {
const result = list.map(item => item.id) as WordMarkOptionTypeEnum[];
setToolbarKeys(result);
backgroundBridge.configManager.update(
'wordMark',
WordMarkConfigKey.toolbars,
result,
);
backgroundBridge.configManager.update('wordMark', 'toolbars', result);
};

const toolbars = useMemo(() => {
Expand All @@ -47,7 +42,9 @@ function OperateMenu(props: IOperateMenuProps) {
return (
<div className={styles.menus}>
<DragList
dataSource={toolbars}
dataSource={toolbars.filter(
item => !wordMarkContext.disableFunction.includes(item.id as any),
)}
renderItem={item => {
const { type, name, icon } = item;
const pinned = pinList.includes(type);
Expand Down
15 changes: 7 additions & 8 deletions src/pages/inject/WordMark/Inner/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React, { useCallback, useState } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { Popover } from 'antd';
import Icon, { CloseOutlined } from '@ant-design/icons';
import { WordMarkOptionTypeEnum } from '@/isomorphic/constants';
import { WordMarkConfigKey } from '@/isomorphic/constant/wordMark';
import { backgroundBridge } from '@/core/bridge/background';
import { useWordMarkContext } from '@/components/WordMarkLayout/useWordMarkContext';
import YuqueLogo from '@/assets/svg/yuque-logo.svg';
Expand All @@ -20,23 +19,23 @@ function InnerWordMark(props: InnerWordMarkProps) {
const { executeCommand } = props;
const wordMarkContext = useWordMarkContext();
const [pinedTools, setPinedTools] = useState<WordMarkOptionTypeEnum[]>(
wordMarkContext.innerPinList,
wordMarkContext.filterInnerPinList,
);

const handlePin = useCallback((type: WordMarkOptionTypeEnum) => {
setPinedTools(tools => {
const result = tools.includes(type)
? tools.filter(t => t !== type)
: [type, ...tools];
backgroundBridge.configManager.update(
'wordMark',
WordMarkConfigKey.innerPinList,
result,
);
backgroundBridge.configManager.update('wordMark', 'innerPinList', result);
return result;
});
}, []);

useEffect(() => {
setPinedTools(wordMarkContext.filterInnerPinList);
}, [wordMarkContext]);

return (
<div
className={styles.innerWordMarkWrapper}
Expand Down
7 changes: 6 additions & 1 deletion src/pages/inject/WordMark/Panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { CloseOutlined } from '@ant-design/icons';
import NoteLogoSvg from '@/assets/svg/note-logo.svg';
import CopySvg from '@/assets/svg/copy.svg';
import { backgroundBridge } from '@/core/bridge/background';
import { useWordMarkContext } from '@/components/WordMarkLayout/useWordMarkContext';
import { toolbars } from '../constants';
import { IEditorRef } from '../Editor';
import styles from './index.module.less';
Expand All @@ -32,6 +33,7 @@ function WordMarkPanel(props: WordMarkPanelProps) {
save,
editorRef,
} = props;
const wordMarkContext = useWordMarkContext();
const [result, setResult] = useState<string>(StepMessage.onStart);
const [type, setType] = useState(defaultType);
const [loading, setLoading] = useState(true);
Expand Down Expand Up @@ -89,7 +91,10 @@ function WordMarkPanel(props: WordMarkPanelProps) {
<div className={styles.panelWrapper}>
<div className={styles.execCommandWrapper}>
{toolbars.map(item => {
if ([WordMarkOptionTypeEnum.clipping].includes(item.type)) {
if (
[WordMarkOptionTypeEnum.clipping].includes(item.type) ||
wordMarkContext.disableFunction.includes(item.id as any)
) {
return null;
}
return (
Expand Down
Loading
Loading