From 3001e9f3ccf1e62d94d5aae6351314218c5fa5de Mon Sep 17 00:00:00 2001 From: Elio Struyf Date: Thu, 7 Sep 2023 11:52:34 +0200 Subject: [PATCH] #651 - fix setting listeners --- CHANGELOG.md | 1 + src/commands/Dashboard.ts | 2 +- src/extension.ts | 11 +-- src/helpers/SettingsHelper.ts | 81 +++++++++++++++---- src/listeners/dashboard/BaseListener.ts | 2 +- src/panelWebView/PanelProvider.ts | 2 +- src/panelWebView/ViewPanel.tsx | 2 + src/panelWebView/components/BaseView.tsx | 16 +--- .../components/InitializeAction.tsx | 32 ++++++++ 9 files changed, 106 insertions(+), 43 deletions(-) create mode 100644 src/panelWebView/components/InitializeAction.tsx diff --git a/CHANGELOG.md b/CHANGELOG.md index 7be68d63..7ab5e9da 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ - [#646](https://github.com/estruyf/vscode-front-matter/issues/646): Update the Astro `3000` port to `4321` - [#647](https://github.com/estruyf/vscode-front-matter/issues/647): Fix the open in browser action on the preview - [#648](https://github.com/estruyf/vscode-front-matter/issues/648): Fix the global configuration reference to the URL of the schema file +- [#651](https://github.com/estruyf/vscode-front-matter/issues/651): Fix settings listeners which did not push updates to the webviews ## [9.1.0] - 2023-08-31 diff --git a/src/commands/Dashboard.ts b/src/commands/Dashboard.ts index 351960ac..03b7df40 100644 --- a/src/commands/Dashboard.ts +++ b/src/commands/Dashboard.ts @@ -160,7 +160,7 @@ export class Dashboard { await commands.executeCommand('setContext', CONTEXT.isDashboardOpen, false); }); - SettingsHelper.onConfigChange(() => { + SettingsHelper.attachListener('dashboard-listener', () => { SettingsListener.getSettings(true); }); diff --git a/src/extension.ts b/src/extension.ts index 00adb0af..b7966c93 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -13,7 +13,6 @@ import { } from './helpers'; import ContentProvider from './providers/ContentProvider'; import { PagesListener } from './listeners/dashboard'; -import { DataListener, SettingsListener } from './listeners/panel'; import { NavigationType } from './dashboardWebView/models'; import { ModeSwitch } from './services/ModeSwitch'; import { PagesParser } from './services/PagesParser'; @@ -275,15 +274,7 @@ export async function activate(context: vscode.ExtensionContext) { }); // Things to do when configuration changes - SettingsHelper.onConfigChange(() => { - Preview.init(); - GitListener.init(); - - SettingsListener.getSettings(); - DataListener.getFoldersAndFiles(); - MarkdownFoldingProvider.triggerHighlighting(true); - ModeSwitch.register(); - }); + SettingsHelper.startListening(); // Create the status bar frontMatterStatusBar = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Left, 100); diff --git a/src/helpers/SettingsHelper.ts b/src/helpers/SettingsHelper.ts index aad558ce..70f14833 100644 --- a/src/helpers/SettingsHelper.ts +++ b/src/helpers/SettingsHelper.ts @@ -1,10 +1,10 @@ -import { SETTING_EXTENSIBILITY_SCRIPTS, SETTING_PROJECTS } from './../constants/settings'; +import { SETTING_PROJECTS } from './../constants/settings'; import { parseWinPath } from './parseWinPath'; import { Telemetry } from './Telemetry'; import { Notifications } from './Notifications'; import { commands, Uri, workspace, window } from 'vscode'; import * as vscode from 'vscode'; -import { ContentType, CustomTaxonomy, Project, TaxonomyType } from '../models'; +import { ContentType, CustomTaxonomy, Project } from '../models'; import { SETTING_TAXONOMY_TAGS, SETTING_TAXONOMY_CATEGORIES, @@ -42,7 +42,11 @@ import { debounceCallback } from './DebounceCallback'; import { Logger } from './Logger'; import * as jsoncParser from 'jsonc-parser'; import { existsAsync, fetchWithTimeout, readFileAsync, writeFileAsync } from '../utils'; -import { Cache } from '../commands'; +import { Cache, Preview } from '../commands'; +import { GitListener } from '../listeners/general'; +import { DataListener } from '../listeners/panel'; +import { MarkdownFoldingProvider } from '../providers/MarkdownFoldingProvider'; +import { ModeSwitch } from '../services/ModeSwitch'; export class Settings { public static globalFile = 'frontmatter.json'; @@ -50,7 +54,7 @@ export class Settings { public static globalConfig: any; private static config: vscode.WorkspaceConfiguration; private static isInitialized: boolean = false; - private static listeners: any[] = []; + private static listeners: { id: string; callback: (global?: any) => void }[] = []; private static fileCreationWatcher: vscode.FileSystemWatcher | undefined; private static fileChangeWatcher: vscode.FileSystemWatcher | undefined; private static fileSaveListener: vscode.Disposable; @@ -92,9 +96,26 @@ export class Settings { Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY); - Settings.onConfigChange(async () => { + Settings.attachListener('settings-init', async () => { Settings.config = vscode.workspace.getConfiguration(CONFIG_KEY); }); + + Settings.onConfigChange(); + } + + /** + * Start listening to changes + */ + public static startListening() { + // Things to do when configuration changes + Settings.attachListener('settings-global', () => { + Preview.init(); + GitListener.init(); + + DataListener.getFoldersAndFiles(); + MarkdownFoldingProvider.triggerHighlighting(true); + ModeSwitch.register(); + }); } /** @@ -164,21 +185,47 @@ export class Settings { } } + /** + * Attach a new listener for the setting changes + * @param id + * @param callback + * @returns + */ + public static attachListener(id: string, callback: (global?: any) => void) { + const listener = Settings.listeners.find((l) => l.id === id); + if (listener) { + listener.callback = callback; + return; + } + + Settings.listeners.push({ + id, + callback + }); + } + + /** + * Trigger all the listeners + */ + public static triggerListeners() { + for (const listener of Settings.listeners) { + Logger.info(`Triggering listener: ${listener.id}`); + listener.callback(); + } + } + /** * Check for config changes on global and local settings * @param callback */ - public static onConfigChange(callback: (global?: any) => void) { + public static onConfigChange() { const projectConfig = Settings.projectConfigPath; const configDebouncer = debounceCallback(); workspace.onDidChangeConfiguration(() => { - callback(); + Settings.triggerListeners(); }); - // Keep track of the listeners - Settings.listeners.push(callback); - if (projectConfig && !existsSync(projectConfig)) { // No config file, no need to watch Settings.createFileCreationWatcher(); @@ -199,7 +246,7 @@ export class Settings { ); Settings.fileChangeWatcher.onDidChange(async () => { Logger.info(`Config change detected - ${projectConfig} changed`); - configDebouncer(() => callback(), 200); + configDebouncer(() => Settings.triggerListeners(), 200); }); } @@ -212,9 +259,9 @@ export class Settings { Logger.info(`Reloaded config...`); if (debounced) { - configDebouncer(() => callback(), 200); + configDebouncer(() => Settings.triggerListeners(), 200); } else { - callback(); + Settings.triggerListeners(); } }; @@ -909,6 +956,7 @@ export class Settings { Settings.fileCreationWatcher.onDidCreate( (uri) => { if (parseWinPath(uri.fsPath) === parseWinPath(Settings.projectConfigPath)) { + Settings.onConfigChange(); Settings.rebindWatchers(); // Stop listening to file creation events Settings.fileCreationWatcher?.dispose(); @@ -927,10 +975,11 @@ export class Settings { private static rebindWatchers() { Logger.info(`Rebinding ${this.listeners.length} listeners`); - this.listeners.forEach((l) => { - Settings.onConfigChange(l); - l(); + Settings.listeners.forEach((l) => { + Settings.attachListener(l.id, l.callback); }); + + Settings.triggerListeners(); } /** diff --git a/src/listeners/dashboard/BaseListener.ts b/src/listeners/dashboard/BaseListener.ts index b686ce87..11166dc1 100644 --- a/src/listeners/dashboard/BaseListener.ts +++ b/src/listeners/dashboard/BaseListener.ts @@ -13,7 +13,7 @@ export abstract class BaseListener { * @param data */ public static sendMsg(command: DashboardCommand, payload: any) { - Logger.info(`Sending message to webview: ${command}`); + Logger.info(`Sending message to dashboard: ${command}`); Dashboard.postWebviewMessage({ command, diff --git a/src/panelWebView/PanelProvider.ts b/src/panelWebView/PanelProvider.ts index 449fbdc1..98fb27d8 100644 --- a/src/panelWebView/PanelProvider.ts +++ b/src/panelWebView/PanelProvider.ts @@ -127,7 +127,7 @@ export class PanelProvider implements WebviewViewProvider, Disposable { } }, this); - Settings.onConfigChange(() => { + Settings.attachListener('panel-listener', () => { SettingsListener.getSettings(); }); } diff --git a/src/panelWebView/ViewPanel.tsx b/src/panelWebView/ViewPanel.tsx index 69e8bf12..edc9e3dc 100644 --- a/src/panelWebView/ViewPanel.tsx +++ b/src/panelWebView/ViewPanel.tsx @@ -17,6 +17,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react'; import { usePrevious } from './hooks/usePrevious'; import * as l10n from '@vscode/l10n'; import { LocalizationKey } from '../localization'; +import { InitializeAction } from './components/InitializeAction'; export interface IViewPanelProps { } @@ -92,6 +93,7 @@ export const ViewPanel: React.FunctionComponent = ( return (
+ { isDevMode && (
diff --git a/src/panelWebView/components/BaseView.tsx b/src/panelWebView/components/BaseView.tsx index 65a0f648..632a427e 100644 --- a/src/panelWebView/components/BaseView.tsx +++ b/src/panelWebView/components/BaseView.tsx @@ -14,6 +14,7 @@ import { GitAction } from './Git/GitAction'; import { useMemo } from 'react'; import * as l10n from "@vscode/l10n" import { LocalizationKey } from '../../localization'; +import { InitializeAction } from './InitializeAction'; export interface IBaseViewProps { settings: PanelSettings | undefined; @@ -30,10 +31,6 @@ const BaseView: React.FunctionComponent = ({ Messenger.send(CommandToCode.openDashboard); }; - const initProject = () => { - Messenger.send(CommandToCode.initProject); - }; - const createContent = () => { Messenger.send(CommandToCode.createContent); }; @@ -75,16 +72,7 @@ const BaseView: React.FunctionComponent = ({ return (
- {!settings?.isInitialized && ( -
- -
- )} + {settings?.isInitialized && ( <> diff --git a/src/panelWebView/components/InitializeAction.tsx b/src/panelWebView/components/InitializeAction.tsx new file mode 100644 index 00000000..1a0a5a80 --- /dev/null +++ b/src/panelWebView/components/InitializeAction.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; +import { PanelSettings } from '../../models'; +import * as l10n from "@vscode/l10n" +import { LocalizationKey } from '../../localization'; +import { Messenger } from '@estruyf/vscode/dist/client'; +import { CommandToCode } from '../CommandToCode'; + +export interface IInitializeActionProps { + settings: PanelSettings | undefined; +} + +export const InitializeAction: React.FunctionComponent = ({ settings }: React.PropsWithChildren) => { + + const initProject = () => { + Messenger.send(CommandToCode.initProject); + }; + + if (settings?.isInitialized) { + return null; + } + + return ( +
+ +
+ ); +}; \ No newline at end of file