Skip to content

Commit c31243d

Browse files
authored
Merge pull request #168 from CodinGame/improve-view-management
Improve view management
2 parents f330549 + 21d6445 commit c31243d

File tree

12 files changed

+332
-136
lines changed

12 files changed

+332
-136
lines changed

demo/index.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,11 @@ <h1>Editor</h1>
2121
<button id="filesystem">Attach filesystem</button>
2222
<button id="customEditorPanel">Open custom editor panel</button>
2323
<button id="clearStorage">Clear storage</button>
24+
<br />
25+
<button id="togglePanel">Toggle Panel</button>
26+
<button id="toggleAuxiliary">Toggle Secondary Panel</button>
2427
</div>
28+
<div style="border: 1px solid var(--vscode-editorWidget-border); width: 300px; height: 800px" id="auxiliaryBar"></div>
2529
</div>
2630

2731
<div id="panel"></div>

demo/src/main.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { createConfiguredEditor, createModelReference } from 'vscode/monaco'
44
import { registerFileSystemOverlay, HTMLFileSystemProvider } from 'vscode/service-override/files'
55
import * as vscode from 'vscode'
66
import { ILogService, StandaloneServices, IPreferencesService, IEditorService, IDialogService } from 'vscode/services'
7-
import { ConfirmResult } from 'vscode/service-override/views'
7+
import { ConfirmResult, Parts, isPartVisibile, setPartVisibility } from 'vscode/service-override/views'
88
import { clearStorage } from './setup'
99
import { CustomEditorInput } from './features/customView'
1010
import './features/debugger'
@@ -191,5 +191,13 @@ document.querySelector('#customEditorPanel')!.addEventListener('click', async ()
191191
})
192192

193193
document.querySelector('#clearStorage')!.addEventListener('click', async () => {
194-
clearStorage()
194+
await clearStorage()
195+
})
196+
197+
document.querySelector('#togglePanel')!.addEventListener('click', async () => {
198+
setPartVisibility(Parts.PANEL_PART, !isPartVisibile(Parts.PANEL_PART))
199+
})
200+
201+
document.querySelector('#toggleAuxiliary')!.addEventListener('click', async () => {
202+
setPartVisibility(Parts.AUXILIARYBAR_PART, !isPartVisibile(Parts.AUXILIARYBAR_PART))
195203
})

demo/src/setup.ts

Lines changed: 31 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ILogService, LogLevel, StandaloneServices, initialize as initializeMonacoService } from 'vscode/services'
1+
import { ILogService, IStorageService, LogLevel, StandaloneServices, getService, initialize as initializeMonacoService } from 'vscode/services'
22
import { initialize as initializeVscodeExtensions } from 'vscode/extensions'
33
import getModelServiceOverride from 'vscode/service-override/model'
44
import getNotificationServiceOverride from 'vscode/service-override/notifications'
@@ -9,7 +9,13 @@ import getTextmateServiceOverride from 'vscode/service-override/textmate'
99
import getThemeServiceOverride from 'vscode/service-override/theme'
1010
import getLanguagesServiceOverride from 'vscode/service-override/languages'
1111
import getAudioCueServiceOverride from 'vscode/service-override/audioCue'
12-
import getViewsServiceOverride, { isEditorPartVisible, renderSidebarPart, renderActivitybarPar, renderEditorPart, renderPanelPart, renderStatusBarPart } from 'vscode/service-override/views'
12+
import getViewsServiceOverride, {
13+
isEditorPartVisible,
14+
Parts,
15+
onPartVisibilityChange,
16+
isPartVisibile,
17+
attachPart
18+
} from 'vscode/service-override/views'
1319
import getDebugServiceOverride from 'vscode/service-override/debug'
1420
import getPreferencesServiceOverride from 'vscode/service-override/preferences'
1521
import getSnippetServiceOverride from 'vscode/service-override/snippets'
@@ -20,7 +26,7 @@ import getSearchServiceOverride from 'vscode/service-override/search'
2026
import getMarkersServiceOverride from 'vscode/service-override/markers'
2127
import getAccessibilityServiceOverride from 'vscode/service-override/accessibility'
2228
import getLanguageDetectionWorkerServiceOverride from 'vscode/service-override/languageDetectionWorker'
23-
import getStorageServiceOverride, { IStorageItemsChangeEvent, StorageScope } from 'vscode/service-override/storage'
29+
import getStorageServiceOverride, { BrowserStorageService } from 'vscode/service-override/storage'
2430
import getExtensionServiceOverride from 'vscode/service-override/extensions'
2531
import EditorWorker from 'monaco-editor/esm/vs/editor/editor.worker.js?worker'
2632
import TextMateWorker from 'vscode/workers/textMate.worker?worker'
@@ -50,8 +56,6 @@ window.MonacoEnvironment = {
5056
}
5157
}
5258

53-
const onStorageChange = new monaco.Emitter<IStorageItemsChangeEvent>()
54-
5559
// Override services
5660
await initializeMonacoService({
5761
...getExtensionServiceOverride(toWorkerConfig(ExtensionHostWorker)),
@@ -78,33 +82,32 @@ await initializeMonacoService({
7882
...getMarkersServiceOverride(),
7983
...getAccessibilityServiceOverride(),
8084
...getLanguageDetectionWorkerServiceOverride(),
81-
...getStorageServiceOverride({
82-
read (scope) {
83-
return new Map(Object.entries(JSON.parse(localStorage.getItem(`storage-${scope}`) ?? '{}')))
84-
},
85-
async write (scope, data) {
86-
localStorage.setItem(`storage-${scope}`, JSON.stringify(Object.fromEntries(data.entries())))
87-
},
88-
onDidChange: onStorageChange.event
89-
})
85+
...getStorageServiceOverride()
9086
})
9187
StandaloneServices.get(ILogService).setLevel(LogLevel.Off)
9288

93-
export function clearStorage (): void {
94-
const allKeys = new Set([StorageScope.APPLICATION, StorageScope.PROFILE, StorageScope.WORKSPACE].flatMap(scope => Object.keys(JSON.parse(localStorage.getItem(`storage-${scope}`) ?? '{}'))))
95-
localStorage.removeItem(`storage-${StorageScope.APPLICATION}`)
96-
localStorage.removeItem(`storage-${StorageScope.PROFILE}`)
97-
localStorage.removeItem(`storage-${StorageScope.WORKSPACE}`)
98-
onStorageChange.fire({
99-
deleted: allKeys,
100-
changed: new Map()
101-
})
89+
export async function clearStorage (): Promise<void> {
90+
await (await getService(IStorageService) as BrowserStorageService).clear()
10291
}
10392

10493
await initializeVscodeExtensions()
10594

106-
renderSidebarPart(document.querySelector<HTMLDivElement>('#sidebar')!)
107-
renderActivitybarPar(document.querySelector<HTMLDivElement>('#activityBar')!)
108-
renderPanelPart(document.querySelector<HTMLDivElement>('#panel')!)
109-
renderEditorPart(document.querySelector<HTMLDivElement>('#editors')!)
110-
renderStatusBarPart(document.querySelector<HTMLDivElement>('#statusBar')!)
95+
for (const { part, element } of [
96+
{ part: Parts.SIDEBAR_PART, element: '#sidebar' },
97+
{ part: Parts.ACTIVITYBAR_PART, element: '#activityBar' },
98+
{ part: Parts.PANEL_PART, element: '#panel' },
99+
{ part: Parts.EDITOR_PART, element: '#editors' },
100+
{ part: Parts.STATUSBAR_PART, element: '#statusBar' },
101+
{ part: Parts.AUXILIARYBAR_PART, element: '#auxiliaryBar' }
102+
]) {
103+
const el = document.querySelector<HTMLDivElement>(element)!
104+
attachPart(part, el)
105+
106+
if (!isPartVisibile(part)) {
107+
el.style.display = 'none'
108+
}
109+
110+
onPartVisibilityChange(part, visible => {
111+
el.style.display = visible ? 'block' : 'none'
112+
})
113+
}

src/lifecycle.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { Registry } from 'vs/platform/registry/common/platform'
2+
import { IWorkbenchContributionsRegistry, Extensions as WorkbenchExtensions } from 'vs/workbench/common/contributions'
3+
import { ILifecycleService, LifecyclePhase } from 'vs/workbench/services/lifecycle/common/lifecycle'
4+
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation'
5+
import { Barrier, RunOnceScheduler, runWhenIdle } from 'vs/base/common/async'
6+
import { Emitter } from 'vs/base/common/event'
7+
8+
const renderWorkbenchEmitter = new Emitter<ServicesAccessor>()
9+
export const onRenderWorkbench = renderWorkbenchEmitter.event
10+
11+
export const serviceInitializedBarrier = new Barrier()
12+
13+
interface ServiceInitializeParticipant {
14+
(accessor: ServicesAccessor): Promise<void>
15+
}
16+
const serviceInitializePreParticipants: ServiceInitializeParticipant[] = []
17+
const serviceInitializeParticipants: ServiceInitializeParticipant[] = []
18+
const serviceInitializePostParticipants: ServiceInitializeParticipant[] = []
19+
export function registerServiceInitializePreParticipant (participant: ServiceInitializeParticipant): void {
20+
serviceInitializePreParticipants.push(participant)
21+
}
22+
export function registerServiceInitializeParticipant (participant: ServiceInitializeParticipant): void {
23+
serviceInitializeParticipants.push(participant)
24+
}
25+
export function registerServiceInitializePostParticipant (participant: ServiceInitializeParticipant): void {
26+
serviceInitializePostParticipants.push(participant)
27+
}
28+
29+
export async function startup (instantiationService: IInstantiationService): Promise<void> {
30+
await instantiationService.invokeFunction(async accessor => {
31+
await Promise.all(serviceInitializePreParticipants.map(participant => participant(accessor)))
32+
})
33+
34+
await instantiationService.invokeFunction(async accessor => {
35+
const lifecycleService = accessor.get(ILifecycleService)
36+
37+
await Promise.all(serviceInitializeParticipants.map(participant => participant(accessor)))
38+
39+
// Signal to lifecycle that services are set
40+
lifecycleService.phase = LifecyclePhase.Ready
41+
})
42+
43+
await instantiationService.invokeFunction(async accessor => {
44+
await Promise.all(serviceInitializePostParticipants.map(participant => participant(accessor)))
45+
})
46+
47+
serviceInitializedBarrier.open()
48+
49+
instantiationService.invokeFunction(accessor => {
50+
const lifecycleService = accessor.get(ILifecycleService)
51+
52+
Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench).start(accessor)
53+
54+
renderWorkbenchEmitter.fire(accessor)
55+
56+
lifecycleService.phase = LifecyclePhase.Restored
57+
58+
// Set lifecycle phase to `Eventually` after a short delay and when idle (min 2.5sec, max 5sec)
59+
const eventuallyPhaseScheduler = new RunOnceScheduler(() => {
60+
runWhenIdle(() => {
61+
lifecycleService.phase = LifecyclePhase.Eventually
62+
}, 2500)
63+
}, 2500)
64+
eventuallyPhaseScheduler.schedule()
65+
})
66+
}

src/service-override/configuration.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import 'vs/workbench/api/common/configurationExtensionPoint'
3535
import { IBrowserWorkbenchEnvironmentService } from 'vs/workbench/services/environment/browser/environmentService'
3636
import getFileServiceOverride from './files'
3737
import { memoizedConstructor, unsupported } from '../tools'
38-
import { registerServiceInitializePreParticipant } from '../services'
38+
import { registerServiceInitializePreParticipant } from '../lifecycle'
3939

4040
async function updateUserConfiguration (configurationJson: string): Promise<void> {
4141
const userDataProfilesService = StandaloneServices.get(IUserDataProfilesService)

0 commit comments

Comments
 (0)