import Emitter from "./emitter"; import { load, store } from "./storage"; const SETTINGS_KEY = "settings"; export const EDITOR_FONT_SIZE = { normal: 14, large: 16, }; export const EDITOR_MODE = { default: "default", emacs: "emacs", vim: "vim", }; export const EDITOR_THEME = { default: "default", light: "light", }; const DEFAULTSETTINGS = { editor_auto_completion: true, editor_auto_signature: true, editor_font_size: EDITOR_FONT_SIZE.normal, editor_theme: EDITOR_THEME.default, editor_ligatures: false, editor_markdown_word_wrap: true, editor_mode: EDITOR_MODE.default, custom_view_show_section: true, custom_view_show_markdown: true, custom_view_show_output: true, custom_view_spotlight: false, }; /** * Stores local configuration and persists it across browser sessions. */ class SettingsStore { /** @private */ _onChange = new Emitter(); constructor() { this.settings = DEFAULTSETTINGS; this.loadSettings(); } /** * Returns the current settings. */ get() { return this.settings; } /** * Stores new settings. * * The given attributes are merged into the current settings. */ update(newSettings) { const prevSettings = this.settings; this.settings = { ...this.settings, ...newSettings }; this._onChange.dispatch(this.settings, prevSettings); this.storeSettings(); } /** * Registers to settings changes. * * The given function is called immediately with the current * settings and then on every change. * * Returns a subscription object with `destroy` method that * unsubscribes from changes. */ getAndSubscribe(callback) { callback(this.settings); return this._onChange.addListener(callback); } /** @private */ loadSettings() { const settings = load(SETTINGS_KEY); if (settings) { // Rewrite settings for backward compatibility if (!Object.values(EDITOR_THEME).includes(settings.editor_theme)) { delete settings.editor_theme; } this.settings = { ...this.settings, ...settings }; } } /** @private */ storeSettings() { store(SETTINGS_KEY, this.settings); } } export const settingsStore = new SettingsStore();