mirror of
https://github.com/coder/code-server.git
synced 2026-05-08 21:37:27 +02:00
Merge commit 'be3e8236086165e5e45a5a10783823874b3f3ebd' as 'lib/vscode'
This commit is contained in:
@@ -0,0 +1,211 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Event, Emitter } from 'vs/base/common/event';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { RawContextKey, IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IFilesConfiguration, AutoSaveConfiguration, HotExitConfiguration } from 'vs/platform/files/common/files';
|
||||
import { equals } from 'vs/base/common/objects';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { isWeb } from 'vs/base/common/platform';
|
||||
|
||||
export const AutoSaveAfterShortDelayContext = new RawContextKey<boolean>('autoSaveAfterShortDelayContext', false);
|
||||
|
||||
export interface IAutoSaveConfiguration {
|
||||
autoSaveDelay?: number;
|
||||
autoSaveFocusChange: boolean;
|
||||
autoSaveApplicationChange: boolean;
|
||||
}
|
||||
|
||||
export const enum AutoSaveMode {
|
||||
OFF,
|
||||
AFTER_SHORT_DELAY,
|
||||
AFTER_LONG_DELAY,
|
||||
ON_FOCUS_CHANGE,
|
||||
ON_WINDOW_CHANGE
|
||||
}
|
||||
|
||||
export const IFilesConfigurationService = createDecorator<IFilesConfigurationService>('filesConfigurationService');
|
||||
|
||||
export interface IFilesConfigurationService {
|
||||
|
||||
readonly _serviceBrand: undefined;
|
||||
|
||||
//#region Auto Save
|
||||
|
||||
readonly onAutoSaveConfigurationChange: Event<IAutoSaveConfiguration>;
|
||||
|
||||
getAutoSaveConfiguration(): IAutoSaveConfiguration;
|
||||
|
||||
getAutoSaveMode(): AutoSaveMode;
|
||||
|
||||
toggleAutoSave(): Promise<void>;
|
||||
|
||||
//#endregion
|
||||
|
||||
readonly onFilesAssociationChange: Event<void>;
|
||||
|
||||
readonly isHotExitEnabled: boolean;
|
||||
|
||||
readonly hotExitConfiguration: string | undefined;
|
||||
|
||||
preventSaveConflicts(resource: URI, language: string): boolean;
|
||||
}
|
||||
|
||||
export class FilesConfigurationService extends Disposable implements IFilesConfigurationService {
|
||||
|
||||
declare readonly _serviceBrand: undefined;
|
||||
|
||||
private static DEFAULT_AUTO_SAVE_MODE = isWeb ? AutoSaveConfiguration.AFTER_DELAY : AutoSaveConfiguration.OFF;
|
||||
|
||||
private readonly _onAutoSaveConfigurationChange = this._register(new Emitter<IAutoSaveConfiguration>());
|
||||
readonly onAutoSaveConfigurationChange = this._onAutoSaveConfigurationChange.event;
|
||||
|
||||
private readonly _onFilesAssociationChange = this._register(new Emitter<void>());
|
||||
readonly onFilesAssociationChange = this._onFilesAssociationChange.event;
|
||||
|
||||
private configuredAutoSaveDelay?: number;
|
||||
private configuredAutoSaveOnFocusChange: boolean | undefined;
|
||||
private configuredAutoSaveOnWindowChange: boolean | undefined;
|
||||
|
||||
private autoSaveAfterShortDelayContext: IContextKey<boolean>;
|
||||
|
||||
private currentFilesAssociationConfig: { [key: string]: string; };
|
||||
|
||||
private currentHotExitConfig: string;
|
||||
|
||||
constructor(
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
super();
|
||||
|
||||
this.autoSaveAfterShortDelayContext = AutoSaveAfterShortDelayContext.bindTo(contextKeyService);
|
||||
|
||||
const configuration = configurationService.getValue<IFilesConfiguration>();
|
||||
|
||||
this.currentFilesAssociationConfig = configuration?.files?.associations;
|
||||
this.currentHotExitConfig = configuration?.files?.hotExit || HotExitConfiguration.ON_EXIT;
|
||||
|
||||
this.onFilesConfigurationChange(configuration);
|
||||
|
||||
this.registerListeners();
|
||||
}
|
||||
|
||||
private registerListeners(): void {
|
||||
|
||||
// Files configuration changes
|
||||
this._register(this.configurationService.onDidChangeConfiguration(e => {
|
||||
if (e.affectsConfiguration('files')) {
|
||||
this.onFilesConfigurationChange(this.configurationService.getValue<IFilesConfiguration>());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
protected onFilesConfigurationChange(configuration: IFilesConfiguration): void {
|
||||
|
||||
// Auto Save
|
||||
const autoSaveMode = configuration?.files?.autoSave || FilesConfigurationService.DEFAULT_AUTO_SAVE_MODE;
|
||||
switch (autoSaveMode) {
|
||||
case AutoSaveConfiguration.AFTER_DELAY:
|
||||
this.configuredAutoSaveDelay = configuration?.files?.autoSaveDelay;
|
||||
this.configuredAutoSaveOnFocusChange = false;
|
||||
this.configuredAutoSaveOnWindowChange = false;
|
||||
break;
|
||||
|
||||
case AutoSaveConfiguration.ON_FOCUS_CHANGE:
|
||||
this.configuredAutoSaveDelay = undefined;
|
||||
this.configuredAutoSaveOnFocusChange = true;
|
||||
this.configuredAutoSaveOnWindowChange = false;
|
||||
break;
|
||||
|
||||
case AutoSaveConfiguration.ON_WINDOW_CHANGE:
|
||||
this.configuredAutoSaveDelay = undefined;
|
||||
this.configuredAutoSaveOnFocusChange = false;
|
||||
this.configuredAutoSaveOnWindowChange = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
this.configuredAutoSaveDelay = undefined;
|
||||
this.configuredAutoSaveOnFocusChange = false;
|
||||
this.configuredAutoSaveOnWindowChange = false;
|
||||
break;
|
||||
}
|
||||
|
||||
this.autoSaveAfterShortDelayContext.set(this.getAutoSaveMode() === AutoSaveMode.AFTER_SHORT_DELAY);
|
||||
|
||||
// Emit as event
|
||||
this._onAutoSaveConfigurationChange.fire(this.getAutoSaveConfiguration());
|
||||
|
||||
// Check for change in files associations
|
||||
const filesAssociation = configuration?.files?.associations;
|
||||
if (!equals(this.currentFilesAssociationConfig, filesAssociation)) {
|
||||
this.currentFilesAssociationConfig = filesAssociation;
|
||||
this._onFilesAssociationChange.fire();
|
||||
}
|
||||
|
||||
// Hot exit
|
||||
const hotExitMode = configuration?.files?.hotExit;
|
||||
if (hotExitMode === HotExitConfiguration.OFF || hotExitMode === HotExitConfiguration.ON_EXIT_AND_WINDOW_CLOSE) {
|
||||
this.currentHotExitConfig = hotExitMode;
|
||||
} else {
|
||||
this.currentHotExitConfig = HotExitConfiguration.ON_EXIT;
|
||||
}
|
||||
}
|
||||
|
||||
getAutoSaveMode(): AutoSaveMode {
|
||||
if (this.configuredAutoSaveOnFocusChange) {
|
||||
return AutoSaveMode.ON_FOCUS_CHANGE;
|
||||
}
|
||||
|
||||
if (this.configuredAutoSaveOnWindowChange) {
|
||||
return AutoSaveMode.ON_WINDOW_CHANGE;
|
||||
}
|
||||
|
||||
if (this.configuredAutoSaveDelay && this.configuredAutoSaveDelay > 0) {
|
||||
return this.configuredAutoSaveDelay <= 1000 ? AutoSaveMode.AFTER_SHORT_DELAY : AutoSaveMode.AFTER_LONG_DELAY;
|
||||
}
|
||||
|
||||
return AutoSaveMode.OFF;
|
||||
}
|
||||
|
||||
getAutoSaveConfiguration(): IAutoSaveConfiguration {
|
||||
return {
|
||||
autoSaveDelay: this.configuredAutoSaveDelay && this.configuredAutoSaveDelay > 0 ? this.configuredAutoSaveDelay : undefined,
|
||||
autoSaveFocusChange: !!this.configuredAutoSaveOnFocusChange,
|
||||
autoSaveApplicationChange: !!this.configuredAutoSaveOnWindowChange
|
||||
};
|
||||
}
|
||||
|
||||
async toggleAutoSave(): Promise<void> {
|
||||
const currentSetting = this.configurationService.getValue('files.autoSave');
|
||||
|
||||
let newAutoSaveValue: string;
|
||||
if ([AutoSaveConfiguration.AFTER_DELAY, AutoSaveConfiguration.ON_FOCUS_CHANGE, AutoSaveConfiguration.ON_WINDOW_CHANGE].some(setting => setting === currentSetting)) {
|
||||
newAutoSaveValue = AutoSaveConfiguration.OFF;
|
||||
} else {
|
||||
newAutoSaveValue = AutoSaveConfiguration.AFTER_DELAY;
|
||||
}
|
||||
|
||||
return this.configurationService.updateValue('files.autoSave', newAutoSaveValue);
|
||||
}
|
||||
|
||||
get isHotExitEnabled(): boolean {
|
||||
return this.currentHotExitConfig !== HotExitConfiguration.OFF;
|
||||
}
|
||||
|
||||
get hotExitConfiguration(): string {
|
||||
return this.currentHotExitConfig;
|
||||
}
|
||||
|
||||
preventSaveConflicts(resource: URI, language: string): boolean {
|
||||
return this.configurationService.getValue('files.saveConflictResolution', { resource, overrideIdentifier: language }) !== 'overwriteFileOnDisk';
|
||||
}
|
||||
}
|
||||
|
||||
registerSingleton(IFilesConfigurationService, FilesConfigurationService);
|
||||
Reference in New Issue
Block a user