mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
responding to comments / clean up
Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
parent
a33165044e
commit
a02538999a
@ -24,16 +24,14 @@ import glob from "glob";
|
|||||||
import path from "path";
|
import path from "path";
|
||||||
import os from "os";
|
import os from "os";
|
||||||
import { promisify } from "util";
|
import { promisify } from "util";
|
||||||
import { action, makeObservable, observable } from "mobx";
|
import { action, makeObservable, observable, ObservableMap } from "mobx";
|
||||||
import logger from "../../../common/logger";
|
import logger from "../../../common/logger";
|
||||||
import { DockTabStore } from "./dock-tab.store";
|
import { DockTabStore } from "./dock-tab.store";
|
||||||
import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store";
|
import { dockStore, DockTabCreateSpecific, TabKind } from "./dock.store";
|
||||||
|
|
||||||
export interface TemplatesGroup {
|
export interface TemplatesGroup {
|
||||||
label: string;
|
label: string;
|
||||||
templates: {
|
templates: ObservableMap<string/*filepath*/, string>;
|
||||||
[filepath: string]: string; // filepath is relative to templates folder
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class CreateResourceStore extends DockTabStore<string> {
|
export class CreateResourceStore extends DockTabStore<string> {
|
||||||
@ -42,16 +40,16 @@ export class CreateResourceStore extends DockTabStore<string> {
|
|||||||
makeObservable(this);
|
makeObservable(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
readonly templateGroups: Record<string, TemplatesGroup> = observable({
|
readonly templateGroups: Record<string, TemplatesGroup> = {
|
||||||
[this.appTemplatesFolder]: {
|
[this.appTemplatesFolder]: {
|
||||||
label: "Lens Templates",
|
label: "Lens Templates",
|
||||||
templates: {},
|
templates: observable.map(),
|
||||||
},
|
},
|
||||||
[this.userTemplatesFolder]: {
|
[this.userTemplatesFolder]: {
|
||||||
label: "Custom templates",
|
label: "Custom templates",
|
||||||
templates: {},
|
templates: observable.map(),
|
||||||
},
|
},
|
||||||
});
|
};
|
||||||
|
|
||||||
get appTemplatesFolder(): string {
|
get appTemplatesFolder(): string {
|
||||||
// production: declare files to copy in "package.json" -> "build.extraResources"
|
// production: declare files to copy in "package.json" -> "build.extraResources"
|
||||||
@ -80,9 +78,7 @@ export class CreateResourceStore extends DockTabStore<string> {
|
|||||||
await fs.ensureDir(sourceFolder);
|
await fs.ensureDir(sourceFolder);
|
||||||
const files = await promisify(glob)("**/*.@(yaml|yml|json)", { cwd: sourceFolder });
|
const files = await promisify(glob)("**/*.@(yaml|yml|json)", { cwd: sourceFolder });
|
||||||
|
|
||||||
templatesGroup.templates = Object.fromEntries(
|
templatesGroup.templates.replace(files.map(filePath => [filePath, "" /*content*/]));
|
||||||
files.map(filePath => [filePath, "" /* empty: content not loaded yet */])
|
|
||||||
);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(`[CREATE-RESOURCE]: scanning template folders error: ${error}`);
|
logger.error(`[CREATE-RESOURCE]: scanning template folders error: ${error}`);
|
||||||
}
|
}
|
||||||
@ -98,9 +94,11 @@ export class CreateResourceStore extends DockTabStore<string> {
|
|||||||
return ""; // unknown group, exit
|
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 {
|
try {
|
||||||
const templatePath = path.resolve(sourceFolder, filePath);
|
const templatePath = path.resolve(sourceFolder, filePath);
|
||||||
@ -110,7 +108,7 @@ export class CreateResourceStore extends DockTabStore<string> {
|
|||||||
|
|
||||||
const textContent = await fs.readFile(templatePath, { encoding: "utf-8" });
|
const textContent = await fs.readFile(templatePath, { encoding: "utf-8" });
|
||||||
|
|
||||||
templatesGroup.templates[filePath] = textContent; // save cache
|
templatesGroup.templates.set(filePath, textContent); // save cache
|
||||||
|
|
||||||
return textContent;
|
return textContent;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|||||||
@ -41,7 +41,6 @@ type SelectOptionTemplate = SelectOption<SelectOptionTemplateValue>;
|
|||||||
interface SelectOptionTemplateValue {
|
interface SelectOptionTemplateValue {
|
||||||
sourceFolder: string;
|
sourceFolder: string;
|
||||||
filePath: string; // relative to `sourceFolder`
|
filePath: string; // relative to `sourceFolder`
|
||||||
content?: string; // available after loading (template selection)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
@ -115,11 +114,10 @@ export class CreateResource extends React.Component<Props> {
|
|||||||
return Object.entries(createResourceStore.templateGroups).map(([sourceFolder, group]) => {
|
return Object.entries(createResourceStore.templateGroups).map(([sourceFolder, group]) => {
|
||||||
return {
|
return {
|
||||||
label: group.label,
|
label: group.label,
|
||||||
options: Object.entries(group.templates).map(([filePath, content]) => {
|
options: Array.from(group.templates.keys()).map(filePath => {
|
||||||
return {
|
return {
|
||||||
label: filePath,
|
label: filePath,
|
||||||
value: { filePath, sourceFolder },
|
value: { filePath, sourceFolder },
|
||||||
content,
|
|
||||||
};
|
};
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
@ -127,8 +125,8 @@ export class CreateResource extends React.Component<Props> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onSelectTemplate = async ({ value }: SelectOptionTemplate) => {
|
onSelectTemplate = async ({ value }: SelectOptionTemplate) => {
|
||||||
const { filePath, sourceFolder, content } = value;
|
const { filePath, sourceFolder } = value;
|
||||||
const templateContent = content ?? await createResourceStore.loadTemplate({ filePath, sourceFolder });
|
const templateContent = await createResourceStore.loadTemplate({ filePath, sourceFolder });
|
||||||
|
|
||||||
createResourceStore.setData(this.tabId, templateContent); // update draft
|
createResourceStore.setData(this.tabId, templateContent); // update draft
|
||||||
};
|
};
|
||||||
|
|||||||
@ -89,8 +89,8 @@ export interface DockStorageState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DockTabChangeEvent {
|
export interface DockTabChangeEvent {
|
||||||
tabId?: TabId;
|
tab: DockTab;
|
||||||
tab?: DockTab;
|
tabId: TabId;
|
||||||
prevTab?: DockTab;
|
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;
|
const { tabKind, dockIsVisible = true, ...reactionOpts } = options;
|
||||||
|
|
||||||
return reaction(() => this.selectedTab, ((tab, prevTab) => {
|
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 (tabKind && tabKind !== tab.kind) return; // handle specific tab.kind only
|
||||||
if (dockIsVisible && !this.isOpen) return;
|
if (dockIsVisible && !this.isOpen) return;
|
||||||
|
|
||||||
|
|||||||
@ -26,7 +26,7 @@ import { observer } from "mobx-react";
|
|||||||
import { editor, Uri } from "monaco-editor";
|
import { editor, Uri } from "monaco-editor";
|
||||||
import { MonacoTheme, registerCustomThemes } from "./monaco-themes";
|
import { MonacoTheme, registerCustomThemes } from "./monaco-themes";
|
||||||
import { MonacoValidator, monacoValidators } from "./monaco-validators";
|
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 { UserStore } from "../../../common/user-store";
|
||||||
import { ThemeStore } from "../../theme.store";
|
import { ThemeStore } from "../../theme.store";
|
||||||
import debounce from "lodash/debounce";
|
import debounce from "lodash/debounce";
|
||||||
@ -71,6 +71,10 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
|
|||||||
public staticId = `editor-id#${Math.round(1e7 * Math.random())}`;
|
public staticId = `editor-id#${Math.round(1e7 * Math.random())}`;
|
||||||
public dispose = disposer();
|
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 containerElem: HTMLElement;
|
||||||
@observable.ref editor: editor.IStandaloneCodeEditor;
|
@observable.ref editor: editor.IStandaloneCodeEditor;
|
||||||
@observable dimensions: { width?: number, height?: number } = {};
|
@observable dimensions: { width?: number, height?: number } = {};
|
||||||
@ -121,10 +125,8 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
|
|||||||
return () => resizeObserver.unobserve(containerElem);
|
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) => {
|
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.saveViewState(oldModel);
|
||||||
this.editor.setModel(model);
|
this.editor.setModel(model);
|
||||||
@ -157,9 +159,9 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
|
|||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
try {
|
try {
|
||||||
this.createEditor();
|
this.createEditor();
|
||||||
console.info(`[MONACO]: editor did mount`);
|
this.logger.info(`[MONACO]: editor did mount`);
|
||||||
} catch (error) {
|
} 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<MonacoEditorProps> {
|
|||||||
...this.options,
|
...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.validateLazy(); // validate initial value
|
||||||
this.restoreViewState(); // restore previous state if any
|
this.restoreViewState(); // restore previous state if any
|
||||||
|
|
||||||
@ -231,7 +233,6 @@ export class MonacoEditor extends React.Component<MonacoEditorProps> {
|
|||||||
|
|
||||||
@action
|
@action
|
||||||
setDimensions(width: number, height: number) {
|
setDimensions(width: number, height: number) {
|
||||||
console.info(`[MONACO]: refreshing dimensions to width=${width} and height=${height}`);
|
|
||||||
this.dimensions.width = width;
|
this.dimensions.width = width;
|
||||||
this.dimensions.height = height;
|
this.dimensions.height = height;
|
||||||
this.editor?.layout({ width, height });
|
this.editor?.layout({ width, height });
|
||||||
|
|||||||
@ -31,7 +31,7 @@ export interface MonacoThemeData extends editor.IStandaloneThemeData {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Registered names could be then used in "themes/*.json" in "{monacoTheme: [name]}"
|
// Registered names could be then used in "themes/*.json" in "{monacoTheme: [name]}"
|
||||||
export const customThemes: Partial<Record<MonacoTheme, MonacoThemeData>> = {
|
export const customThemes: Partial<Record<MonacoCustomTheme, MonacoThemeData>> = {
|
||||||
"clouds-midnight": cloudsMidnight as MonacoThemeData,
|
"clouds-midnight": cloudsMidnight as MonacoThemeData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -23,15 +23,14 @@ import { computed, makeObservable, observable, reaction } from "mobx";
|
|||||||
import { autoBind, Singleton } from "./utils";
|
import { autoBind, Singleton } from "./utils";
|
||||||
import { UserStore } from "../common/user-store";
|
import { UserStore } from "../common/user-store";
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import lensDarkTheme from "./themes/lens-dark.json";
|
import lensDarkThemeJson from "./themes/lens-dark.json";
|
||||||
import lensLightTheme from "./themes/lens-light.json";
|
import lensLightThemeJson from "./themes/lens-light.json";
|
||||||
import type { SelectOption } from "./components/select";
|
import type { SelectOption } from "./components/select";
|
||||||
import type { MonacoEditorProps } from "./components/monaco-editor";
|
import type { MonacoEditorProps } from "./components/monaco-editor";
|
||||||
|
|
||||||
export type ThemeId = string;
|
export type ThemeId = string;
|
||||||
|
|
||||||
export interface Theme {
|
export interface Theme {
|
||||||
id?: ThemeId;
|
|
||||||
name: string;
|
name: string;
|
||||||
type: "dark" | "light";
|
type: "dark" | "light";
|
||||||
colors: Record<string, string>;
|
colors: Record<string, string>;
|
||||||
@ -45,34 +44,23 @@ export class ThemeStore extends Singleton {
|
|||||||
protected styles: HTMLStyleElement;
|
protected styles: HTMLStyleElement;
|
||||||
|
|
||||||
// bundled themes from `themes/${themeId}.json`
|
// bundled themes from `themes/${themeId}.json`
|
||||||
private allThemes = observable.map<string, Theme>({
|
private themes = observable.map<ThemeId, Theme>({
|
||||||
"lens-dark": lensDarkTheme as Theme,
|
"lens-dark": lensDarkThemeJson as Theme,
|
||||||
"lens-light": lensLightTheme as Theme,
|
"lens-light": lensLightThemeJson as Theme,
|
||||||
});
|
});
|
||||||
|
|
||||||
@computed get themes() {
|
|
||||||
return Array.from(this.allThemes.entries()).map(([themeId, themeOriginal]) => {
|
|
||||||
const theme: Required<Theme> = {
|
|
||||||
id: themeId, // take id from map's key
|
|
||||||
...themeOriginal,
|
|
||||||
};
|
|
||||||
|
|
||||||
return theme;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@computed get activeThemeId(): string {
|
@computed get activeThemeId(): string {
|
||||||
return UserStore.getInstance().colorTheme;
|
return UserStore.getInstance().colorTheme;
|
||||||
}
|
}
|
||||||
|
|
||||||
@computed get activeTheme(): Theme {
|
@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<string>[] {
|
@computed get themeOptions(): SelectOption<string>[] {
|
||||||
return this.themes.map(theme => ({
|
return Array.from(this.themes).map(([themeId, theme]) => ({
|
||||||
label: theme.name,
|
label: theme.name,
|
||||||
value: theme.id,
|
value: themeId,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,7 +84,7 @@ export class ThemeStore extends Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getThemeById(themeId: ThemeId): Theme {
|
getThemeById(themeId: ThemeId): Theme {
|
||||||
return this.allThemes.get(themeId);
|
return this.themes.get(themeId);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected applyTheme(theme: Theme) {
|
protected applyTheme(theme: Theme) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user