Skip to content

Commit

Permalink
Persist project settings (#302)
Browse files Browse the repository at this point in the history
  • Loading branch information
Kitenite authored Sep 6, 2024
1 parent 3a79064 commit 445db7e
Show file tree
Hide file tree
Showing 18 changed files with 261 additions and 93 deletions.
10 changes: 10 additions & 0 deletions app/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ export enum MainChannels {
SEND_ANALYTICS = 'send-analytics',
GET_USER_SETTINGS = 'get-user-settings',
UPDATE_USER_SETTINGS = 'update-user-settings',
GET_PROJECT_SETTINGS = 'get-project-settings',
UPDATE_PROJECT_SETTINGS = 'update-project-settings',

// Ast
GET_TEMPLATE_NODE_AST = 'get-template-node-ast',
Expand All @@ -70,6 +72,14 @@ export enum Links {

export const APP_NAME = 'Onlook';

export const DefaultSettings = {
SCALE: 0.6,
POSITION: { x: 300, y: 50 },
URL: 'http://localhost:3000/',
FRAME_POSITION: { x: 0, y: 0 },
FRAME_DIMENSION: { width: 1536, height: 960 },
};

export const INLINE_ONLY_CONTAINERS = new Set([
'a',
'abbr',
Expand Down
2 changes: 1 addition & 1 deletion app/common/models/element/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export interface WebViewElement extends DomElement {
webviewId: string;
}

export interface Position {
export interface ElementPosition {
x: number;
y: number;
}
23 changes: 23 additions & 0 deletions app/common/models/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,26 @@ export interface UserSettings {
enableAnalytics?: boolean;
ideType?: IdeType;
}

export interface RectPosition {
x: number;
y: number;
}

export interface RectDimension {
width: number;
height: number;
}

export interface FrameSettings {
id: string;
url: string;
position: RectPosition;
dimension: RectDimension;
}

export interface ProjectSettings {
scale?: number;
frames?: FrameSettings[];
position?: RectPosition;
}
10 changes: 5 additions & 5 deletions app/electron/main/analytics/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ipcMain } from 'electron';
import * as Mixpanel from 'mixpanel';
import { nanoid } from 'nanoid';
import { readUserSettings, writeUserSettings } from '../storage';
import { PersistenStorage } from '../storage';
import { MainChannels } from '/common/constants';

export function sendAnalytics(event: string, data?: Record<string, any>) {
Expand All @@ -17,12 +17,12 @@ class Analytics {
}

restoreSettings() {
const settings = readUserSettings();
const settings = PersistenStorage.USER_SETTINGS.read();
const enable = settings.enableAnalytics;
this.id = settings.id;
if (!this.id) {
this.id = nanoid();
writeUserSettings({ enableAnalytics: enable, id: this.id });
PersistenStorage.USER_SETTINGS.write({ enableAnalytics: enable, id: this.id });
}

if (enable) {
Expand All @@ -33,7 +33,7 @@ class Analytics {
}

toggleSetting(enable: boolean) {
const settings = readUserSettings();
const settings = PersistenStorage.USER_SETTINGS.read();
if (settings.enableAnalytics === enable) {
return;
}
Expand All @@ -45,7 +45,7 @@ class Analytics {
this.track('disable analytics');
this.disable();
}
writeUserSettings({ enableAnalytics: enable, id: this.id });
PersistenStorage.USER_SETTINGS.write({ enableAnalytics: enable, id: this.id });
}

enable() {
Expand Down
6 changes: 3 additions & 3 deletions app/electron/main/code/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { shell, dialog } from 'electron';
import { readUserSettings } from '../storage';
import { dialog, shell } from 'electron';
import { PersistenStorage } from '../storage';
import { formatContent, readFile, writeFile } from './files';
import { IDE, IdeType } from '/common/ide';
import { CodeDiff } from '/common/models/code';
Expand Down Expand Up @@ -69,7 +69,7 @@ export async function writeCode(codeDiffs: CodeDiff[]): Promise<boolean> {
}

function getIdeFromUserSettings(): IDE {
const userSettings = readUserSettings();
const userSettings = PersistenStorage.USER_SETTINGS.read();
return IDE.fromType(userSettings.ideType || IdeType.VS_CODE);
}

Expand Down
14 changes: 11 additions & 3 deletions app/electron/main/events/settings.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,21 @@
import { ipcMain } from 'electron';
import { readUserSettings, updateUserSettings } from '../storage';
import { PersistenStorage } from '../storage';
import { MainChannels } from '/common/constants';

export function listenForSettingMessages() {
ipcMain.handle(MainChannels.GET_USER_SETTINGS, (e: Electron.IpcMainInvokeEvent) => {
return readUserSettings();
return PersistenStorage.USER_SETTINGS.read();
});

ipcMain.handle(MainChannels.UPDATE_USER_SETTINGS, (e: Electron.IpcMainInvokeEvent, args) => {
updateUserSettings(args);
PersistenStorage.USER_SETTINGS.update(args);
});

ipcMain.handle(MainChannels.GET_PROJECT_SETTINGS, (e: Electron.IpcMainInvokeEvent) => {
return PersistenStorage.PROJECT_SETTINGS.read();
});

ipcMain.handle(MainChannels.UPDATE_PROJECT_SETTINGS, (e: Electron.IpcMainInvokeEvent, args) => {
PersistenStorage.PROJECT_SETTINGS.update(args);
});
}
40 changes: 24 additions & 16 deletions app/electron/main/storage/index.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,33 @@
import { app } from 'electron';
import { existsSync, readFileSync, writeFileSync } from 'fs';
import { UserSettings } from '/common/models/settings';
import { ProjectSettings, UserSettings } from '/common/models/settings';

const path = app.getPath('userData');
const settingsPath = `${path}/user-settings.json`;
export class PersistenStorage<T> {
public readonly FILE_PATH: string;
static readonly USER_SETTINGS = new PersistenStorage<UserSettings>('user-settings');
static readonly PROJECT_SETTINGS = new PersistenStorage<ProjectSettings>('project-settings');

export function updateUserSettings(settings: UserSettings) {
const userSettings = readUserSettings();
writeUserSettings({ ...userSettings, ...settings });
}
private constructor(public readonly fileName: string) {
const APP_PATH = app.getPath('userData');
this.FILE_PATH = `${APP_PATH}/${fileName}.json`;
}

export function writeUserSettings(settings: UserSettings) {
const userData = JSON.stringify(settings);
writeFileSync(settingsPath, userData);
}
read(): T {
if (!existsSync(this.FILE_PATH)) {
return {} as T;
}

export function readUserSettings(): UserSettings {
if (!existsSync(settingsPath)) {
return {};
const content = readFileSync(this.FILE_PATH, 'utf8');
return JSON.parse(content || '') as T;
}

const content = readFileSync(settingsPath, 'utf8');
return JSON.parse(content || '') as UserSettings;
write(value: T) {
const data = JSON.stringify(value);
writeFileSync(this.FILE_PATH, data);
}

update(value: T) {
const existingValue = this.read();
this.write({ ...existingValue, ...value });
}
}
113 changes: 113 additions & 0 deletions app/src/lib/editor/engine/canvas/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import { debounce } from 'lodash';
import { makeAutoObservable } from 'mobx';
import { nanoid } from 'nanoid';
import { DefaultSettings, MainChannels } from '/common/constants';
import {
FrameSettings,
ProjectSettings,
RectDimension,
RectPosition,
} from '/common/models/settings';

export class CanvasManager {
private zoomScale: number = DefaultSettings.SCALE;
private panPosition: RectPosition = DefaultSettings.POSITION;
private idToFrame: Map<string, FrameSettings> = new Map();

constructor() {
makeAutoObservable(this);
this.restoreSettings();
}

get scale() {
return this.zoomScale;
}

set scale(value: number) {
this.zoomScale = value;
this.saveSettings();
}

get position() {
return this.panPosition;
}

set position(value: RectPosition) {
this.panPosition = value;
this.saveSettings();
}

get frames() {
return Array.from(this.idToFrame.values());
}

saveFrame(
id: string,
newSettings: {
url?: string;
position?: RectPosition;
dimension?: RectDimension;
},
) {
let frame = this.idToFrame.get(id);
if (!frame) {
return;
}

frame = { ...frame, ...newSettings };
this.idToFrame.set(id, frame);
this.saveSettings();
}

restoreSettings() {
window.api.invoke(MainChannels.GET_PROJECT_SETTINGS).then((res) => {
const settings: ProjectSettings = res as ProjectSettings;
this.scale = settings.scale || DefaultSettings.SCALE;
this.position = settings.position || DefaultSettings.POSITION;
this.idToFrame = this.getFrameMap(
settings.frames && settings.frames.length
? settings.frames
: [this.getDefaultFrame()],
);
});
}

getFrameMap(frames: FrameSettings[]): Map<string, FrameSettings> {
const map = new Map<string, FrameSettings>();
frames.forEach((frame) => {
map.set(frame.id, frame);
});
return map;
}

getDefaultFrame(): FrameSettings {
return {
id: nanoid(),
url: DefaultSettings.URL,
position: DefaultSettings.FRAME_POSITION,
dimension: DefaultSettings.FRAME_DIMENSION,
};
}

saveSettings = debounce(this.undebouncedSaveSettings, 1000);

private undebouncedSaveSettings() {
const settings: ProjectSettings = {
scale: this.zoomScale,
position: this.panPosition,
frames: Array.from(this.frames.values()),
};
window.api.invoke(
MainChannels.UPDATE_PROJECT_SETTINGS,
JSON.parse(JSON.stringify(settings)),
);
}

private clearSettings() {
const settings: ProjectSettings = {};
window.api.invoke(
MainChannels.UPDATE_PROJECT_SETTINGS,
JSON.parse(JSON.stringify(settings)),
);
}
}
9 changes: 5 additions & 4 deletions app/src/lib/editor/engine/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { EditorMode } from '@/lib/models';
import { makeAutoObservable } from 'mobx';
import { ActionManager } from './action';
import { AstManager } from './ast';
import { CanvasManager } from './canvas';
import { CodeManager } from './code';
import { DomManager } from './dom';
import { ElementManager } from './element';
Expand All @@ -14,8 +15,6 @@ import { StyleManager } from './style';
import { WebviewManager } from './webview';

export class EditorEngine {
public scale: number = 0;

private editorMode: EditorMode = EditorMode.DESIGN;
private overlayManager: OverlayManager = new OverlayManager();
private webviewManager: WebviewManager = new WebviewManager();
Expand All @@ -38,6 +37,7 @@ export class EditorEngine {
private moveManager: MoveManager = new MoveManager(this.overlayManager, this.historyManager);
private styleManager: StyleManager = new StyleManager(this.actionManager, this.elementManager);
private projectInfoManager = new ProjectInfoManager();
private canvasManager = new CanvasManager();

constructor() {
makeAutoObservable(this);
Expand Down Expand Up @@ -75,14 +75,15 @@ export class EditorEngine {
get move() {
return this.moveManager;
}

get projectInfo() {
return this.projectInfoManager;
}

get style() {
return this.styleManager;
}
get canvas() {
return this.canvasManager;
}

set mode(mode: EditorMode) {
this.editorMode = mode;
Expand Down
Loading

0 comments on commit 445db7e

Please sign in to comment.