From a02538999ad8ba7f1c5588415bb2000ef698fc92 Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 27 Oct 2021 11:25:21 +0300 Subject: [PATCH] responding to comments / clean up Signed-off-by: Roman --- .../components/dock/create-resource.store.ts | 26 ++++++++-------- .../components/dock/create-resource.tsx | 8 ++--- src/renderer/components/dock/dock.store.ts | 8 ++--- .../monaco-editor/monaco-editor.tsx | 17 ++++++----- .../components/monaco-editor/monaco-themes.ts | 2 +- src/renderer/theme.store.ts | 30 ++++++------------- 6 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/renderer/components/dock/create-resource.store.ts b/src/renderer/components/dock/create-resource.store.ts index 62124d823b..c279d2c51d 100644 --- a/src/renderer/components/dock/create-resource.store.ts +++ b/src/renderer/components/dock/create-resource.store.ts @@ -24,16 +24,14 @@ import glob from "glob"; import path from "path"; import os from "os"; import { promisify } from "util"; -import { action, makeObservable, observable } from "mobx"; +import { action, makeObservable, observable, ObservableMap } from "mobx"; import logger from "../../../common/logger"; import { DockTabStore } from "./dock-tab.store"; import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store"; export interface TemplatesGroup { label: string; - templates: { - [filepath: string]: string; // filepath is relative to templates folder - }; + templates: ObservableMap; } export class CreateResourceStore extends DockTabStore { @@ -42,16 +40,16 @@ export class CreateResourceStore extends DockTabStore { makeObservable(this); } - readonly templateGroups: Record = observable({ + readonly templateGroups: Record = { [this.appTemplatesFolder]: { label: "Lens Templates", - templates: {}, + templates: observable.map(), }, [this.userTemplatesFolder]: { label: "Custom templates", - templates: {}, + templates: observable.map(), }, - }); + }; get appTemplatesFolder(): string { // production: declare files to copy in "package.json" -> "build.extraResources" @@ -80,9 +78,7 @@ export class CreateResourceStore extends DockTabStore { await fs.ensureDir(sourceFolder); const files = await promisify(glob)("**/*.@(yaml|yml|json)", { cwd: sourceFolder }); - templatesGroup.templates = Object.fromEntries( - files.map(filePath => [filePath, "" /* empty: content not loaded yet */]) - ); + templatesGroup.templates.replace(files.map(filePath => [filePath, "" /*content*/])); } catch (error) { logger.error(`[CREATE-RESOURCE]: scanning template folders error: ${error}`); } @@ -98,9 +94,11 @@ export class CreateResourceStore extends DockTabStore { return ""; // unknown group, exit } - const template = templatesGroup.templates[filePath]; + const template = templatesGroup.templates.get(filePath); - if (template) return template; // return cache, preloaded already + if (template) { + return template; // return cache, preloaded already + } try { const templatePath = path.resolve(sourceFolder, filePath); @@ -110,7 +108,7 @@ export class CreateResourceStore extends DockTabStore { const textContent = await fs.readFile(templatePath, { encoding: "utf-8" }); - templatesGroup.templates[filePath] = textContent; // save cache + templatesGroup.templates.set(filePath, textContent); // save cache return textContent; } catch (error) { diff --git a/src/renderer/components/dock/create-resource.tsx b/src/renderer/components/dock/create-resource.tsx index ca6aaa1675..631b8b6828 100644 --- a/src/renderer/components/dock/create-resource.tsx +++ b/src/renderer/components/dock/create-resource.tsx @@ -41,7 +41,6 @@ type SelectOptionTemplate = SelectOption; interface SelectOptionTemplateValue { sourceFolder: string; filePath: string; // relative to `sourceFolder` - content?: string; // available after loading (template selection) } @observer @@ -115,11 +114,10 @@ export class CreateResource extends React.Component { return Object.entries(createResourceStore.templateGroups).map(([sourceFolder, group]) => { return { label: group.label, - options: Object.entries(group.templates).map(([filePath, content]) => { + options: Array.from(group.templates.keys()).map(filePath => { return { label: filePath, value: { filePath, sourceFolder }, - content, }; }), }; @@ -127,8 +125,8 @@ export class CreateResource extends React.Component { } onSelectTemplate = async ({ value }: SelectOptionTemplate) => { - const { filePath, sourceFolder, content } = value; - const templateContent = content ?? await createResourceStore.loadTemplate({ filePath, sourceFolder }); + const { filePath, sourceFolder } = value; + const templateContent = await createResourceStore.loadTemplate({ filePath, sourceFolder }); createResourceStore.setData(this.tabId, templateContent); // update draft }; diff --git a/src/renderer/components/dock/dock.store.ts b/src/renderer/components/dock/dock.store.ts index 35c2bd74db..6cfb9c4883 100644 --- a/src/renderer/components/dock/dock.store.ts +++ b/src/renderer/components/dock/dock.store.ts @@ -89,8 +89,8 @@ export interface DockStorageState { } export interface DockTabChangeEvent { - tabId?: TabId; - tab?: DockTab; + tab: DockTab; + tabId: TabId; prevTab?: DockTab; } @@ -212,11 +212,11 @@ export class DockStore implements DockStorageState { }); } - onTabChange(callback?: (evt: DockTabChangeEvent) => void, options: DockTabChangeEventOptions = {}) { + onTabChange(callback: (evt: DockTabChangeEvent) => void, options: DockTabChangeEventOptions = {}) { const { tabKind, dockIsVisible = true, ...reactionOpts } = options; return reaction(() => this.selectedTab, ((tab, prevTab) => { - if (!tab) return; // skip + if (!tab) return; // skip when dock is empty if (tabKind && tabKind !== tab.kind) return; // handle specific tab.kind only if (dockIsVisible && !this.isOpen) return; diff --git a/src/renderer/components/monaco-editor/monaco-editor.tsx b/src/renderer/components/monaco-editor/monaco-editor.tsx index 8cf34c7395..20faf75aa0 100644 --- a/src/renderer/components/monaco-editor/monaco-editor.tsx +++ b/src/renderer/components/monaco-editor/monaco-editor.tsx @@ -26,7 +26,7 @@ import { observer } from "mobx-react"; import { editor, Uri } from "monaco-editor"; import { MonacoTheme, registerCustomThemes } from "./monaco-themes"; import { MonacoValidator, monacoValidators } from "./monaco-validators"; -import { cssNames, disposer, toJS } from "../../utils"; +import { cssNames, disposer, noop, toJS } from "../../utils"; import { UserStore } from "../../../common/user-store"; import { ThemeStore } from "../../theme.store"; import debounce from "lodash/debounce"; @@ -71,6 +71,10 @@ export class MonacoEditor extends React.Component { public staticId = `editor-id#${Math.round(1e7 * Math.random())}`; public dispose = disposer(); + // TODO: investigate why replacing console.* to common/logger.* calls leads for stucking UI / infinite loop.. + // e.g. happens on tab change/create, maybe some other cases too. + logger = { info: noop, error: noop } as Console; + @observable.ref containerElem: HTMLElement; @observable.ref editor: editor.IStandaloneCodeEditor; @observable dimensions: { width?: number, height?: number } = {}; @@ -121,10 +125,8 @@ export class MonacoEditor extends React.Component { return () => resizeObserver.unobserve(containerElem); } - // TODO: investigate why replacing console.* to common logger.* calls in a file leads for stucking UI / infinite loop. - // e.g. happens on tab change/create, maybe some other cases onModelChange = (model: editor.ITextModel, oldModel?: editor.ITextModel) => { - console.info("[MONACO]: model change", { model, oldModel }); + this.logger.info("[MONACO]: model change", { model, oldModel }); this.saveViewState(oldModel); this.editor.setModel(model); @@ -157,9 +159,9 @@ export class MonacoEditor extends React.Component { componentDidMount() { try { this.createEditor(); - console.info(`[MONACO]: editor did mount`); + this.logger.info(`[MONACO]: editor did mount`); } catch (error) { - console.error(`[MONACO]: mounting failed: ${error}`, this); + this.logger.error(`[MONACO]: mounting failed: ${error}`, this); } } @@ -185,7 +187,7 @@ export class MonacoEditor extends React.Component { ...this.options, }); - console.info(`[MONACO]: editor created for language=${language}, theme=${theme}`); + this.logger.info(`[MONACO]: editor created for language=${language}, theme=${theme}`); this.validateLazy(); // validate initial value this.restoreViewState(); // restore previous state if any @@ -231,7 +233,6 @@ export class MonacoEditor extends React.Component { @action setDimensions(width: number, height: number) { - console.info(`[MONACO]: refreshing dimensions to width=${width} and height=${height}`); this.dimensions.width = width; this.dimensions.height = height; this.editor?.layout({ width, height }); diff --git a/src/renderer/components/monaco-editor/monaco-themes.ts b/src/renderer/components/monaco-editor/monaco-themes.ts index 75cabb734f..73da1e8ca6 100644 --- a/src/renderer/components/monaco-editor/monaco-themes.ts +++ b/src/renderer/components/monaco-editor/monaco-themes.ts @@ -31,7 +31,7 @@ export interface MonacoThemeData extends editor.IStandaloneThemeData { } // Registered names could be then used in "themes/*.json" in "{monacoTheme: [name]}" -export const customThemes: Partial> = { +export const customThemes: Partial> = { "clouds-midnight": cloudsMidnight as MonacoThemeData, }; diff --git a/src/renderer/theme.store.ts b/src/renderer/theme.store.ts index 4df0a76809..faef28a1c2 100644 --- a/src/renderer/theme.store.ts +++ b/src/renderer/theme.store.ts @@ -23,15 +23,14 @@ import { computed, makeObservable, observable, reaction } from "mobx"; import { autoBind, Singleton } from "./utils"; import { UserStore } from "../common/user-store"; import logger from "../main/logger"; -import lensDarkTheme from "./themes/lens-dark.json"; -import lensLightTheme from "./themes/lens-light.json"; +import lensDarkThemeJson from "./themes/lens-dark.json"; +import lensLightThemeJson from "./themes/lens-light.json"; import type { SelectOption } from "./components/select"; import type { MonacoEditorProps } from "./components/monaco-editor"; export type ThemeId = string; export interface Theme { - id?: ThemeId; name: string; type: "dark" | "light"; colors: Record; @@ -45,34 +44,23 @@ export class ThemeStore extends Singleton { protected styles: HTMLStyleElement; // bundled themes from `themes/${themeId}.json` - private allThemes = observable.map({ - "lens-dark": lensDarkTheme as Theme, - "lens-light": lensLightTheme as Theme, + private themes = observable.map({ + "lens-dark": lensDarkThemeJson as Theme, + "lens-light": lensLightThemeJson as Theme, }); - @computed get themes() { - return Array.from(this.allThemes.entries()).map(([themeId, themeOriginal]) => { - const theme: Required = { - id: themeId, // take id from map's key - ...themeOriginal, - }; - - return theme; - }); - } - @computed get activeThemeId(): string { return UserStore.getInstance().colorTheme; } @computed get activeTheme(): Theme { - return this.allThemes.get(this.activeThemeId) ?? this.allThemes.get(ThemeStore.defaultTheme); + return this.themes.get(this.activeThemeId) ?? this.themes.get(ThemeStore.defaultTheme); } @computed get themeOptions(): SelectOption[] { - return this.themes.map(theme => ({ + return Array.from(this.themes).map(([themeId, theme]) => ({ label: theme.name, - value: theme.id, + value: themeId, })); } @@ -96,7 +84,7 @@ export class ThemeStore extends Singleton { } getThemeById(themeId: ThemeId): Theme { - return this.allThemes.get(themeId); + return this.themes.get(themeId); } protected applyTheme(theme: Theme) {