Skip to content

Commit

Permalink
feat: support save user preference
Browse files Browse the repository at this point in the history
  • Loading branch information
F-star committed Dec 17, 2024
1 parent 4f732d2 commit eca05df
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 21 deletions.
5 changes: 3 additions & 2 deletions packages/core/src/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import Ruler from './ruler';
import { SceneGraph } from './scene/scene_graph';
import { SelectedBox } from './selected_box';
import { SelectedElements } from './selected_elements';
import { Setting } from './setting';
import { Setting, type SettingValue } from './setting';
import { TextEditor } from './text/text_editor';
import { ToolManager } from './tools';
import { type IChanges, type IEditorPaperData } from './type';
Expand All @@ -38,6 +38,7 @@ interface IEditorOptions {
offsetX?: number;
offsetY?: number;
showPerfMonitor?: boolean;
userPreference?: Partial<SettingValue>;
}

interface Events {
Expand Down Expand Up @@ -89,7 +90,7 @@ export class SuikaEditor {
this.containerElement.appendChild(this.canvasElement);
this.ctx = this.canvasElement.getContext('2d')!;

this.setting = new Setting();
this.setting = new Setting(options.userPreference);
if (options.offsetX) {
this.setting.set('offsetX', options.offsetX);
}
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/scene/scene_graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -297,10 +297,11 @@ export class SceneGraph {
this.initGraphicsTree(graphicsArr);
}

on(eventName: 'render', handler: () => void) {
on<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.on(eventName, handler);
}
off(eventName: 'render', handler: () => void) {

off<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.off(eventName, handler);
}
}
19 changes: 14 additions & 5 deletions packages/core/src/setting.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { EventEmitter } from '@suika/common';
import { EventEmitter, pick } from '@suika/common';

import { type IPaint, PaintType } from './paint';
import { type BooleanKeys } from './type';

interface Events {
update(attrs: SettingValue): void;
update(attrs: SettingValue, changedKey: keyof SettingValue): void;
}

export class Setting {
Expand Down Expand Up @@ -149,6 +149,15 @@ export class Setting {
textEditorCursorLineStroke: '#000',
textEditorSelectionFill: '#0069c433',
};

constructor(partialVal?: Partial<SettingValue>) {
partialVal = pick(partialVal, Object.keys(this.value));
this.value = {
...this.value,
...partialVal,
};
}

toggle<K extends BooleanKeys<SettingValue>>(key: K) {
const value = this.value[key];
if (typeof value === 'boolean') {
Expand All @@ -159,7 +168,7 @@ export class Setting {
}
set<K extends keyof SettingValue>(key: K, value: SettingValue[K]) {
this.value[key] = value;
this.eventEmitter.emit('update', this.getAttrs());
this.eventEmitter.emit('update', this.getAttrs(), key);
}
get<K extends keyof SettingValue>(key: K) {
return this.value[key];
Expand All @@ -168,10 +177,10 @@ export class Setting {
return { ...this.value };
}

on(eventName: 'update', handler: (value: SettingValue) => void) {
on<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.on(eventName, handler);
}
off(eventName: 'update', handler: (value: SettingValue) => void) {
off<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.off(eventName, handler);
}
}
Expand Down
5 changes: 3 additions & 2 deletions packages/core/src/viewport_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,10 +68,11 @@ export class ViewportManager {
maxY: y + height / zoom,
};
}
on(eventName: 'xOrYChange', handler: (x: number, y: number) => void) {

on<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.on(eventName, handler);
}
off(eventName: 'xOrYChange', handler: (x: number, y: number) => void) {
off<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.off(eventName, handler);
}
}
12 changes: 4 additions & 8 deletions packages/core/src/zoom_manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,16 +216,12 @@ export class ZoomManager {
y: newScrollY,
});
}
on(
eventName: 'zoomChange',
handler: (zoom: number, prevZoom: number) => void,
) {

on<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.on(eventName, handler);
}
off(
eventName: 'zoomChange',
handler: (zoom: number, prevZoom: number) => void,
) {

off<K extends keyof Events>(eventName: K, handler: Events[K]) {
this.eventEmitter.off(eventName, handler);
}
}
Expand Down
35 changes: 33 additions & 2 deletions packages/suika/src/components/Editor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import './Editor.scss';

import { throttle } from '@suika/common';
import { SuikaEditor } from '@suika/core';
import { pick, throttle } from '@suika/common';
import { type SettingValue, SuikaEditor } from '@suika/core';
import { type FC, useEffect, useRef, useState } from 'react';

import { EditorContext } from '../context';
Expand All @@ -14,21 +14,52 @@ import { LayerPanel } from './LayerPanel';
const topMargin = 48;
const leftRightMargin = 240 * 2;

const USER_PREFERENCE_KEY = 'suika-user-preference';
const storeKeys: Partial<keyof SettingValue>[] = [
'enablePixelGrid',
'snapToGrid',
'enableRuler',

'keepToolSelectedAfterUse',
'invertZoomDirection',
'highlightLayersOnHover',
'flipObjectsWhileResizing',
];

const Editor: FC = () => {
const containerRef = useRef<HTMLDivElement>(null);

const [editor, setEditor] = useState<SuikaEditor | null>(null);

useEffect(() => {
if (containerRef.current) {
const userPreferenceEncoded = localStorage.getItem(USER_PREFERENCE_KEY);
const userPreference = userPreferenceEncoded
? (JSON.parse(userPreferenceEncoded) as Partial<SettingValue>)
: undefined;

const editor = new SuikaEditor({
containerElement: containerRef.current,
width: document.body.clientWidth - leftRightMargin,
height: document.body.clientHeight - topMargin,
offsetY: 48,
offsetX: 240,
showPerfMonitor: false,
userPreference: userPreference,
});

editor.setting.on(
'update',
(value: SettingValue, changedKey: keyof SettingValue) => {
if (!storeKeys.includes(changedKey)) return;

localStorage.setItem(
USER_PREFERENCE_KEY,
JSON.stringify(pick(value, storeKeys)),
);
},
);

(window as any).editor = editor;

new AutoSaveGraphics(editor);
Expand Down

0 comments on commit eca05df

Please sign in to comment.