From c2f7d9196e274022a0d87ef152a3e1bd9f915256 Mon Sep 17 00:00:00 2001 From: "lianjie.lj" Date: Tue, 19 Oct 2021 11:30:28 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E5=AF=B9=E9=92=89=E4=BD=8F?= =?UTF-8?q?=E7=8A=B6=E6=80=81=E7=9A=84=E6=9C=AC=E5=9C=B0=E5=AD=98=E5=82=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Link: https://code.aone.alibaba-inc.com/ali-lowcode/ali-lowcode-engine/codereview/6694701 * feat: 大纲树面板提供钉住状态记忆 --- packages/editor-core/package.json | 3 +- packages/editor-core/src/editor.ts | 12 ++++ packages/editor-core/src/utils/index.ts | 1 + packages/editor-core/src/utils/logger.ts | 7 +++ packages/editor-core/src/utils/preference.ts | 58 +++++++++++++++++++ .../widget-views/panel-operation-row.tsx | 11 +--- packages/editor-skeleton/src/skeleton.ts | 44 +++++++++++++- packages/editor-skeleton/src/widget/panel.ts | 13 ++++- packages/engine/src/engine-core.ts | 10 +++- 9 files changed, 145 insertions(+), 14 deletions(-) create mode 100644 packages/editor-core/src/utils/logger.ts create mode 100644 packages/editor-core/src/utils/preference.ts diff --git a/packages/editor-core/package.json b/packages/editor-core/package.json index ace087271..b66387805 100644 --- a/packages/editor-core/package.json +++ b/packages/editor-core/package.json @@ -25,7 +25,8 @@ "power-di": "^2.2.4", "react": "^16", "react-dom": "^16.7.0", - "store": "^2.0.12" + "store": "^2.0.12", + "zen-logger": "^1.1.0" }, "devDependencies": { "@alib/build-scripts": "^0.1.18", diff --git a/packages/editor-core/src/editor.ts b/packages/editor-core/src/editor.ts index 79f717fae..944c47402 100644 --- a/packages/editor-core/src/editor.ts +++ b/packages/editor-core/src/editor.ts @@ -13,6 +13,7 @@ import { } from '@ali/lowcode-types'; import { globalLocale } from './intl'; import * as utils from './utils'; +import Preference from './utils/preference'; import { obx } from './utils'; import { AssetsJson, AssetLoader } from '@ali/lowcode-utils'; @@ -33,6 +34,7 @@ export declare interface Editor extends StrictEventEmitter void): this; prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this; eventNames(): Array; + getPreference(): Preference; } export class Editor extends (EventEmitter as any) implements IEditor { @@ -46,6 +48,12 @@ export class Editor extends (EventEmitter as any) implements IEditor { } readonly utils = utils; + /** + * used to store preferences + * + * @memberof Editor + */ + readonly preference = new Preference(); private hooks: HookConfig[] = []; @@ -176,6 +184,10 @@ export class Editor extends (EventEmitter as any) implements IEditor { } } + getPreference() { + return this.preference; + } + initHooks = (hooks: HookConfig[]) => { this.hooks = hooks.map((hook) => ({ ...hook, diff --git a/packages/editor-core/src/utils/index.ts b/packages/editor-core/src/utils/index.ts index add9b05f6..0e269ef3b 100644 --- a/packages/editor-core/src/utils/index.ts +++ b/packages/editor-core/src/utils/index.ts @@ -4,3 +4,4 @@ export * from './obx'; export * from './request'; export * from './focus-tracker'; export * from './control'; +export * from './preference'; diff --git a/packages/editor-core/src/utils/logger.ts b/packages/editor-core/src/utils/logger.ts new file mode 100644 index 000000000..21ff230a6 --- /dev/null +++ b/packages/editor-core/src/utils/logger.ts @@ -0,0 +1,7 @@ +import Logger, { Level } from 'zen-logger'; + +export { Logger }; + +export function getLogger(config: { level: Level, bizName: string }): Logger { + return new Logger(config); +} diff --git a/packages/editor-core/src/utils/preference.ts b/packages/editor-core/src/utils/preference.ts new file mode 100644 index 000000000..e26f92e80 --- /dev/null +++ b/packages/editor-core/src/utils/preference.ts @@ -0,0 +1,58 @@ +import store from 'store'; +import { getLogger } from './logger'; + +const logger = getLogger({ level: 'log', bizName: 'Preference' }); +const STORAGE_KEY_PREFIX = 'ale'; + +/** + * used to store user preferences, such as pinned status of a pannel. + * save to local storage. + * + * @class PreferenceStore + */ +export default class Preference { + getStorageKey(key: string, module?: string): string { + const moduleKey = module || '__inner__'; + return `${STORAGE_KEY_PREFIX}_${moduleKey}.${key}`; + } + + set(key: string, value:any, module?: string) { + if (!key || typeof key !== 'string' || key.length === 0) { + logger.error('Invalid key when setting preference', key); + return; + } + const storageKey = this.getStorageKey(key, module); + logger.log('storageKey:', storageKey, 'set with value:', value); + store.set(storageKey, value); + } + + get(key: string, module: string) : any { + if (!key || typeof key !== 'string' || key.length === 0) { + logger.error('Invalid key when getting from preference', key); + return; + } + const storageKey = this.getStorageKey(key, module); + const result = store.get(storageKey); + logger.log('storageKey:', storageKey, 'get with result:', result); + return result; + } + /** + * check if local storage contain certain key + * + * @param {string} key + * @param {string} module + * @returns {boolean} + * @memberof Preference + */ + contains(key: string, module: string) : boolean { + if (!key || typeof key !== 'string' || key.length === 0) { + logger.error('Invalid key when getting from preference', key); + return false; + } + const storageKey = this.getStorageKey(key, module); + const result = store.get(storageKey); + + return !(result === undefined || result === null); + } + +} \ No newline at end of file diff --git a/packages/editor-skeleton/src/components/widget-views/panel-operation-row.tsx b/packages/editor-skeleton/src/components/widget-views/panel-operation-row.tsx index 91728efde..f5b9d3d93 100644 --- a/packages/editor-skeleton/src/components/widget-views/panel-operation-row.tsx +++ b/packages/editor-skeleton/src/components/widget-views/panel-operation-row.tsx @@ -18,15 +18,8 @@ export default class PanelOperationRow extends Component<{ panel: Panel }> { if (!current) { return; } - if (panel?.parent?.name === 'leftFloatArea') { - panel.skeleton.leftFloatArea.remove(current); - panel.skeleton.leftFixedArea.add(current); - panel.skeleton.leftFixedArea.container.active(current); - } else { - panel.skeleton.leftFixedArea.remove(current); - panel.skeleton.leftFloatArea.add(current); - panel.skeleton.leftFloatArea.container.active(current); - } + + panel.skeleton.toggleFloatStatus(panel); } render() { diff --git a/packages/editor-skeleton/src/skeleton.ts b/packages/editor-skeleton/src/skeleton.ts index 26804294b..9c32b9e1b 100644 --- a/packages/editor-skeleton/src/skeleton.ts +++ b/packages/editor-skeleton/src/skeleton.ts @@ -1,4 +1,4 @@ -import { Editor } from '@ali/lowcode-editor-core'; +import { Editor, action, makeObservable } from '@ali/lowcode-editor-core'; import { DockConfig, PanelConfig, @@ -59,6 +59,7 @@ export class Skeleton { readonly stages: Area; constructor(readonly editor: Editor) { + makeObservable(this); this.leftArea = new Area( this, 'leftArea', @@ -157,6 +158,47 @@ export class Skeleton { }); this.setupPlugins(); + this.setupEvents(); + } + /** + * setup events + * + * @memberof Skeleton + */ + setupEvents() { + // adjust pinned status when panel shown + this.editor.on('skeleton.panel.show', (panelName, panel) => { + const panelNameKey = `${panelName}-pinned-status-isFloat`; + const isInFloatAreaPreferenceExists = this.editor?.getPreference()?.contains(panelNameKey, 'skeleton'); + if (isInFloatAreaPreferenceExists) { + const isInFloatAreaFromPreference = this.editor?.getPreference()?.get(panelNameKey, 'skeleton'); + const currentIsInFloatArea = panel?.isInFloatArea(); + if (isInFloatAreaFromPreference !== currentIsInFloatArea) { + this.toggleFloatStatus(panel); + } + } + }); + } + + /** + * set isFloat status for panel + * + * @param {*} panel + * @memberof Skeleton + */ + @action + toggleFloatStatus(panel: Panel) { + const isFloat = panel?.parent?.name === 'leftFloatArea'; + if (isFloat) { + this.leftFloatArea.remove(panel); + this.leftFixedArea.add(panel); + this.leftFixedArea.container.active(panel); + } else { + this.leftFixedArea.remove(panel); + this.leftFloatArea.add(panel); + this.leftFloatArea.container.active(panel); + } + this.editor?.getPreference()?.set(`${panel.name}-pinned-status-isFloat`, !isFloat, 'skeleton'); } buildFromConfig(config?: EditorConfig, components: PluginClassSet = {}) { diff --git a/packages/editor-skeleton/src/widget/panel.ts b/packages/editor-skeleton/src/widget/panel.ts index b9a4273c6..dfbe6af7c 100644 --- a/packages/editor-skeleton/src/widget/panel.ts +++ b/packages/editor-skeleton/src/widget/panel.ts @@ -154,6 +154,15 @@ export default class Panel implements IWidget { getContent() { return this.content; } + /** + * check is current panel is in float area or not + * + * @returns {boolean} + * @memberof Panel + */ + isInFloatArea(): boolean { + return this.parent?.name === 'leftFloatArea'; + } setActive(flag: boolean) { if (flag === this._actived) { @@ -161,9 +170,9 @@ export default class Panel implements IWidget { return; } if (flag) { - if (this.parent.name === 'leftFloatArea') { + if (this.isInFloatArea()) { this.skeleton.leftFixedArea.container.unactiveAll(); - } else if (this.parent.name === 'leftFixedArea') { + } else { this.skeleton.leftFloatArea.container.unactiveAll(); } this._actived = true; diff --git a/packages/engine/src/engine-core.ts b/packages/engine/src/engine-core.ts index 65849dcfe..a5f071e34 100644 --- a/packages/engine/src/engine-core.ts +++ b/packages/engine/src/engine-core.ts @@ -152,13 +152,21 @@ plugins.register((ctx: ILowCodePluginContext) => { }, }); } + + // by default in float area; + let isInFloatArea = true; + const hasPreferenceForOutline = editor?.getPreference()?.contains('outline-pane-pinned-status-isFloat', 'skeleton'); + if (hasPreferenceForOutline) { + isInFloatArea = editor?.getPreference()?.get('outline-pane-pinned-status-isFloat', 'skeleton'); + } + skeleton.add({ area: 'leftArea', name: 'outlinePane', type: 'PanelDock', content: Outline, panelProps: { - area: 'leftFloatArea', + area: isInFloatArea ? 'leftFloatArea' : 'leftFixedArea', keepVisibleWhileDragging: true, }, });