提交 4e68c8f6 编写于 作者: B Benjamin Pasero

state - towards storing state when it changes or specifically only on shutdown

上级 0fa33a2c
......@@ -9,9 +9,10 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
import { CodeLensModel } from 'vs/editor/contrib/codelens/codelens';
import { LRUCache, values } from 'vs/base/common/map';
import { CodeLensProvider, CodeLensList, CodeLens } from 'vs/editor/common/modes';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { Range } from 'vs/editor/common/core/range';
import { runWhenIdle } from 'vs/base/common/async';
import { once } from 'vs/base/common/functional';
export const ICodeLensCache = createDecorator<ICodeLensCache>('ICodeLensCache');
......@@ -59,9 +60,10 @@ export class CodeLensCache implements ICodeLensCache {
this._deserialize(raw);
// store lens data on shutdown
const listener = storageService.onWillSaveState(() => {
storageService.store(key, this._serialize(), StorageScope.WORKSPACE);
listener.dispose();
once(storageService.onWillSaveState)(e => {
if (e.reason === WillSaveStateReason.SHUTDOWN) {
storageService.store(key, this._serialize(), StorageScope.WORKSPACE);
}
});
}
......
......@@ -60,7 +60,7 @@ suite('Multicursor selection', () => {
let queryState: { [key: string]: any; } = {};
let serviceCollection = new ServiceCollection();
serviceCollection.set(IStorageService, {
_serviceBrand: undefined,
_serviceBrand: undefined as any,
onDidChangeStorage: Event.None,
onWillSaveState: Event.None,
get: (key: string) => queryState[key],
......
......@@ -5,7 +5,7 @@
import { LRUCache, TernarySearchTree } from 'vs/base/common/map';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { ITextModel } from 'vs/editor/common/model';
import { IPosition } from 'vs/editor/common/core/position';
import { CompletionItemKind, completionKindFromString } from 'vs/editor/common/modes';
......@@ -221,7 +221,11 @@ export class SuggestMemoryService extends Disposable implements ISuggestMemorySe
};
this._persistSoon = this._register(new RunOnceScheduler(() => this._saveState(), 500));
this._register(_storageService.onWillSaveState(() => this._saveState()));
this._register(_storageService.onWillSaveState(e => {
if (e.reason === WillSaveStateReason.SHUTDOWN) {
this._saveState();
}
}));
this._register(this._configService.onDidChangeConfiguration(e => {
if (e.affectsConfiguration('editor.suggestSelection') || e.affectsConfiguration('editor.suggest.shareSuggestSelections')) {
......
......@@ -5,7 +5,7 @@
import { toErrorMessage } from 'vs/base/common/errorMessage';
import { ShutdownReason, StartupKind, handleVetos, ILifecycleService } from 'vs/platform/lifecycle/common/lifecycle';
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { ipcRenderer as ipc } from 'electron';
import { IWindowService } from 'vs/platform/windows/common/windows';
import { ILogService } from 'vs/platform/log/common/log';
......@@ -90,8 +90,10 @@ export class LifecycleService extends AbstractLifecycleService {
});
// Save shutdown reason to retrieve on next startup
this.storageService.onWillSaveState(() => {
this.storageService.store(LifecycleService.LAST_SHUTDOWN_REASON_KEY, this.shutdownReason, StorageScope.WORKSPACE);
this.storageService.onWillSaveState(e => {
if (e.reason === WillSaveStateReason.SHUTDOWN) {
this.storageService.store(LifecycleService.LAST_SHUTDOWN_REASON_KEY, this.shutdownReason, StorageScope.WORKSPACE);
}
});
}
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { isUndefinedOrNull } from 'vs/base/common/types';
......@@ -26,7 +26,7 @@ export interface IWillSaveStateEvent {
export interface IStorageService {
_serviceBrand: any;
_serviceBrand: ServiceIdentifier<any>;
/**
* Emitted whenever data is updated or deleted.
......@@ -41,6 +41,10 @@ export interface IStorageService {
* The will save state event allows to optionally ask for the reason of
* saving the state, e.g. to find out if the state is saved due to a
* shutdown.
*
* Note: this event may be fired many times, not only on shutdown to prevent
* loss of state in situations where the shutdown is not sufficient to
* persist the data properly.
*/
readonly onWillSaveState: Event<IWillSaveStateEvent>;
......@@ -119,7 +123,7 @@ export interface IWorkspaceStorageChangeEvent {
export class InMemoryStorageService extends Disposable implements IStorageService {
_serviceBrand = undefined;
_serviceBrand = null as any;
private readonly _onDidChangeStorage: Emitter<IWorkspaceStorageChangeEvent> = this._register(new Emitter<IWorkspaceStorageChangeEvent>());
get onDidChangeStorage(): Event<IWorkspaceStorageChangeEvent> { return this._onDidChangeStorage.event; }
......
......@@ -3,7 +3,7 @@
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { Event, Emitter } from 'vs/base/common/event';
import { Disposable } from 'vs/base/common/lifecycle';
import { ILogService, LogLevel } from 'vs/platform/log/common/log';
......@@ -16,7 +16,7 @@ export const IStorageMainService = createDecorator<IStorageMainService>('storage
export interface IStorageMainService {
_serviceBrand: any;
_serviceBrand: ServiceIdentifier<any>;
/**
* Emitted whenever data is updated or deleted.
......@@ -27,6 +27,10 @@ export interface IStorageMainService {
* Emitted when the storage is about to persist. This is the right time
* to persist data to ensure it is stored before the application shuts
* down.
*
* Note: this event may be fired many times, not only on shutdown to prevent
* loss of state in situations where the shutdown is not sufficient to
* persist the data properly.
*/
readonly onWillSaveState: Event<void>;
......@@ -71,7 +75,7 @@ export interface IStorageChangeEvent {
export class StorageMainService extends Disposable implements IStorageMainService {
_serviceBrand: any;
_serviceBrand: ServiceIdentifier<any>;
private static STORAGE_NAME = 'state.vscdb';
......
......@@ -16,7 +16,7 @@ import { PanelPart } from 'vs/workbench/browser/parts/panel/panelPart';
import { PanelRegistry, Extensions as PanelExtensions } from 'vs/workbench/browser/panel';
import { Position, Parts, IWorkbenchLayoutService, ILayoutOptions } from 'vs/workbench/services/layout/browser/layoutService';
import { IWorkspaceContextService, WorkbenchState } from 'vs/platform/workspace/common/workspace';
import { IStorageService, StorageScope, IWillSaveStateEvent, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { IStorageService, StorageScope, WillSaveStateReason } from 'vs/platform/storage/common/storage';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IPanelService } from 'vs/workbench/services/panel/common/panelService';
......@@ -159,7 +159,6 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
wasPanelVisible: false,
transitionDisposables: new DisposableStore()
}
};
constructor(
......@@ -197,9 +196,6 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
private registerLayoutListeners(): void {
// Storage
this._register(this.storageService.onWillSaveState(e => this.saveLayoutState(e)));
// Restore editor if hidden and it changes
this._register(this.editorService.onDidVisibleEditorsChange(() => this.setEditorHidden(false)));
this._register(this.editorGroupService.onDidActivateGroup(() => this.setEditorHidden(false)));
......@@ -652,6 +648,22 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
// Event
this._onZenModeChange.fire(this.state.zenMode.active);
// State
if (this.state.zenMode.active) {
this.storageService.store(Storage.ZEN_MODE_ENABLED, true, StorageScope.WORKSPACE);
// Exit zen mode on shutdown unless configured to keep
this.state.zenMode.transitionDisposables.add(this.storageService.onWillSaveState(e => {
if (e.reason === WillSaveStateReason.SHUTDOWN && this.state.zenMode.active) {
if (!this.configurationService.getValue(Settings.ZEN_MODE_RESTORE)) {
this.toggleZenMode(true); // We will not restore zen mode, need to clear all zen mode state changes
}
}
}));
} else {
this.storageService.remove(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE);
}
}
private setStatusBarHidden(hidden: boolean, skipLayout?: boolean): void {
......@@ -1107,22 +1119,6 @@ export abstract class Layout extends Disposable implements IWorkbenchLayoutServi
}
}
private saveLayoutState(e: IWillSaveStateEvent): void {
// Zen Mode
if (this.state.zenMode.active) {
this.storageService.store(Storage.ZEN_MODE_ENABLED, true, StorageScope.WORKSPACE);
} else {
this.storageService.remove(Storage.ZEN_MODE_ENABLED, StorageScope.WORKSPACE);
}
if (e.reason === WillSaveStateReason.SHUTDOWN && this.state.zenMode.active) {
if (!this.configurationService.getValue(Settings.ZEN_MODE_RESTORE)) {
this.toggleZenMode(true); // We will not restore zen mode, need to clear all zen mode state changes
}
}
}
dispose(): void {
super.dispose();
......
......@@ -284,8 +284,6 @@ export class ConfigurationManager implements IConfigurationManager {
this.setCompoundSchemaValues();
}
}));
this.toDispose.push(this.storageService.onWillSaveState(this.saveState, this));
}
private initLaunches(): void {
......@@ -296,7 +294,7 @@ export class ConfigurationManager implements IConfigurationManager {
this.launches.push(this.instantiationService.createInstance(UserLaunch));
if (this.selectedLaunch && this.launches.indexOf(this.selectedLaunch) === -1) {
this.selectedLaunch = undefined;
this.setSelectedLaunch(undefined);
}
}
......@@ -348,13 +346,13 @@ export class ConfigurationManager implements IConfigurationManager {
const previousLaunch = this.selectedLaunch;
const previousName = this.selectedName;
this.selectedLaunch = launch;
this.setSelectedLaunch(launch);
const names = launch ? launch.getConfigurationNames() : [];
if (name && names.indexOf(name) >= 0) {
this.selectedName = name;
this.setSelectedLaunchName(name);
}
if (!this.selectedName || names.indexOf(this.selectedName) === -1) {
this.selectedName = names.length ? names[0] : undefined;
this.setSelectedLaunchName(names.length ? names[0] : undefined);
}
const configuration = this.selectedLaunch && this.selectedName ? this.selectedLaunch.getConfiguration(this.selectedName) : undefined;
......@@ -439,12 +437,23 @@ export class ConfigurationManager implements IConfigurationManager {
});
}
private saveState(): void {
private setSelectedLaunchName(selectedName: string | undefined): void {
this.selectedName = selectedName;
if (this.selectedName) {
this.storageService.store(DEBUG_SELECTED_CONFIG_NAME_KEY, this.selectedName, StorageScope.WORKSPACE);
} else {
this.storageService.remove(DEBUG_SELECTED_CONFIG_NAME_KEY, StorageScope.WORKSPACE);
}
}
private setSelectedLaunch(selectedLaunch: ILaunch | undefined): void {
this.selectedLaunch = selectedLaunch;
if (this.selectedLaunch) {
this.storageService.store(DEBUG_SELECTED_ROOT, this.selectedLaunch.uri.toString(), StorageScope.WORKSPACE);
} else {
this.storageService.remove(DEBUG_SELECTED_ROOT, StorageScope.WORKSPACE);
}
}
......
......@@ -337,7 +337,7 @@ export class ExplorerView extends ViewletPanel {
// save view state on shutdown
this._register(this.storageService.onWillSaveState(() => {
this.storageService.store(ExplorerView.TREE_VIEW_STATE_STORAGE_KEY, JSON.stringify(this.tree.getViewState()), StorageScope.WORKSPACE);
}, null));
}));
}
// React on events
......
......@@ -105,11 +105,10 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
// Set active channel to first channel if not set
if (!this.activeChannel) {
const channels = this.getChannelDescriptors();
this.activeChannel = channels && channels.length > 0 ? this.getChannel(channels[0].id) : undefined;
this.setActiveChannel(channels && channels.length > 0 ? this.getChannel(channels[0].id) : undefined);
}
this._register(this.lifecycleService.onShutdown(() => this.dispose()));
this._register(this.storageService.onWillSaveState(() => this.saveState()));
}
provideTextContent(resource: URI): Promise<ITextModel> | null {
......@@ -129,13 +128,13 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
return Promise.resolve(undefined);
}
this.activeChannel = channel;
this.setActiveChannel(channel);
let promise: Promise<void>;
if (this.isPanelShown()) {
promise = this.doShowChannel(channel, !!preserveFocus);
} else {
this.panelService.openPanel(OUTPUT_PANEL_ID);
promise = this.doShowChannel(this.activeChannel, !!preserveFocus);
promise = this.doShowChannel(channel, !!preserveFocus);
}
return promise.then(() => this._onActiveOutputChannel.fire(id));
}
......@@ -156,7 +155,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
const channel = this.createChannel(channelId);
this.channels.set(channelId, channel);
if (!this.activeChannel || this.activeChannelIdInStorage === channelId) {
this.activeChannel = channel;
this.setActiveChannel(channel);
this.onDidPanelOpen(this.panelService.getActivePanel(), true)
.then(() => this._onActiveOutputChannel.fire(channelId));
}
......@@ -198,7 +197,7 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
if (channel && this.isPanelShown()) {
this.showChannel(channel.id, true);
} else {
this.activeChannel = channel;
this.setActiveChannel(channel);
if (this.activeChannel) {
this._onActiveOutputChannel.fire(this.activeChannel.id);
}
......@@ -247,9 +246,13 @@ export class OutputService extends Disposable implements IOutputService, ITextMo
return this.instantiationService.createInstance(ResourceEditorInput, nls.localize('output', "{0} - Output", channel.label), nls.localize('channel', "Output channel for '{0}'", channel.label), resource, undefined);
}
private saveState(): void {
private setActiveChannel(channel: OutputChannel | undefined): void {
this.activeChannel = channel;
if (this.activeChannel) {
this.storageService.store(OUTPUT_ACTIVE_CHANNEL_KEY, this.activeChannel.id, StorageScope.WORKSPACE);
} else {
this.storageService.remove(OUTPUT_ACTIVE_CHANNEL_KEY, StorageScope.WORKSPACE);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册