Skip to content

Commit

Permalink
fix: projects should be updated when settings changed
Browse files Browse the repository at this point in the history
  • Loading branch information
kyswtn committed Sep 22, 2024
1 parent 6f2072d commit 0e03eac
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 15 deletions.
5 changes: 5 additions & 0 deletions .changeset/tame-pets-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vscode-vercel": patch
---

Fix projects not being updated when settings changed
2 changes: 1 addition & 1 deletion extension/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ export const enum CommandId {
}

export const enum ConfigId {
FilesExclude = 'vercel.files.exclude',
FilesExclude = 'files.exclude',
}

export const enum TreeId {
Expand Down
53 changes: 41 additions & 12 deletions extension/src/extension-configuration.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,40 @@
import * as vscode from 'vscode'
import {ConfigId, extensionPrefix} from './constants'
import {Injectable} from './lib'
import {diffArrays} from './utils'

export type OnDidChangeFilesExcludeEvent = {
added: string[]
removed: string[]
}

@Injectable()
export class ExtensionConfiguration implements vscode.Disposable {
private readonly config = vscode.workspace.getConfiguration()
private readonly disposable: vscode.Disposable
private _filesExclude: string[] = []
private filesConfig = vscode.workspace.getConfiguration('files')
private vercelConfig = vscode.workspace.getConfiguration(extensionPrefix)

private allFilesExclude = this.getAllFilesExclude()
private readonly onDidChangeFilesExcludeEventEmitter = new vscode.EventEmitter<OnDidChangeFilesExcludeEvent>()

constructor() {
this.updateCache()
this.disposable = vscode.workspace.onDidChangeConfiguration((event) => {
if (event.affectsConfiguration(extensionPrefix)) {
this.updateCache()
this.vercelConfig = vscode.workspace.getConfiguration(extensionPrefix)
}

if (event.affectsConfiguration('files')) {
this.filesConfig = vscode.workspace.getConfiguration('files')
}

if (this.affectsSomeConfigurations(event, [`${extensionPrefix}.${ConfigId.FilesExclude}`, 'files.exclude'])) {
const newFileExcludes = this.getAllFilesExclude()
const diff = diffArrays(this.allFilesExclude, newFileExcludes)

if (diff) {
this.allFilesExclude = newFileExcludes
this.onDidChangeFilesExcludeEventEmitter.fire(diff)
}
}
})
}
Expand All @@ -21,17 +43,24 @@ export class ExtensionConfiguration implements vscode.Disposable {
this.disposable.dispose()
}

private updateCache() {
get filesExclude() {
return this.allFilesExclude
}

get onDidChangeFilesExclude() {
return this.onDidChangeFilesExcludeEventEmitter.event
}

private affectsSomeConfigurations(event: vscode.ConfigurationChangeEvent, sections: string[]) {
return sections.some((section) => event.affectsConfiguration(section))
}

private getAllFilesExclude() {
// `files.exclude` is not a string array. It's an object of patterns with boolean values.
const vscodeFilesExclude = this.config.get<Record<string, boolean>>('files.exclude', {})
const vscodeFilesExclude = this.filesConfig.get<Record<string, boolean>>('exclude', {})
const vscodeFilesExcludeGlobs = Object.entries(vscodeFilesExclude)
.filter(([, enabled]) => enabled)
.map(([globPattern]) => globPattern)

this._filesExclude = [...vscodeFilesExcludeGlobs, ...this.config.get<string[]>(ConfigId.FilesExclude, [])]
}

get filesExclude() {
return this._filesExclude
return [...vscodeFilesExcludeGlobs, ...this.vercelConfig.get<string[]>(ConfigId.FilesExclude, [])]
}
}
18 changes: 16 additions & 2 deletions extension/src/local-projects-state-provider.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import path from 'pathe'
import * as vscode from 'vscode'
import {FilePattern, projectJsonPath} from './constants'
import {ExtensionConfiguration} from './extension-configuration'
import {ExtensionConfiguration, OnDidChangeFilesExcludeEvent} from './extension-configuration'
import {FileWatchersStateProvider} from './file-watchers-state-provider'
import {FoldersStateProvider} from './folders-state-provider'
import {Injectable, Logger, type WatchedFileChangeEvent} from './lib'
import type {ProjectJson} from './types'
import {naiveGlobMatch, naiveHash, normalizePath, settleAllPromises} from './utils'
import {diffArrays, naiveGlobMatch, naiveHash, normalizePath, settleAllPromises} from './utils'
import {PromiseQueue} from './utils/promise-queue'
import {isValidProjectJson} from './utils/validation'
import {readJsonFile} from './utils/vscode'
Expand Down Expand Up @@ -55,6 +55,9 @@ export class LocalProjectsStateProvider implements vscode.Disposable {
this.fileWatchersState.onDidChangeWatchedFiles((event) => {
void updateLocalProjectsQueue.enqueue(() => this.updateLocalProjectsWhenWatchedFilesChanged(event))
}),
this.extensionConfig.onDidChangeFilesExclude((event) => {
void updateLocalProjectsQueue.enqueue(() => this.updateLocalProjectsWhenConfigChanged(event))
}),
)
}

Expand All @@ -75,6 +78,17 @@ export class LocalProjectsStateProvider implements vscode.Disposable {
this._localProjects = await this.getProjectsFromMultipleWorkspaceFolders(this.foldersState.folders)
}

private async updateLocalProjectsWhenConfigChanged(_event: OnDidChangeFilesExcludeEvent) {
// It's not worth it to read event and filter out projects, so just reload & emit an event.
const oldLocalProjects = this._localProjects
await this.loadLocalProjects()

const newEvent = diffArrays(oldLocalProjects, this._localProjects, (a, b) => a.id === b.id)
const hasChanged = newEvent && newEvent.added.length + newEvent.removed.length > 0

if (hasChanged) this.onDidChangeLocalProjectsEventEmitter.fire({...newEvent, changed: []})
}

private async updateLocalProjectsWhenFoldersChanged(event: vscode.WorkspaceFoldersChangeEvent) {
const newEvent: OnDidChangeLocalProjectEvent = {
added: [],
Expand Down

0 comments on commit 0e03eac

Please sign in to comment.