認識vscode(三)

上一篇文章我介紹了vscode從入口文件開始一直到渲染進程的運行流程。今天我們通過實現 dark mode 來了解一下workbench.

先看一下效果圖鎮場子, 本篇文章只介紹邏輯實現. 具體UI不探討.

2c238907-0410-44f5-a6d2-ac0bc99194c7.gif

我個人的話實現dark mode其實是使用了兩套主題. 其實vscode有提供dark mode api. 不過比較麻煩。 因爲我個人遇到的實際場景是不需要讓用戶切換主題的。所以我就選了兩套主題做切換來實現 僞dark mode

我們從workbench.ts裏的startup開始。這裏開始vscode會渲染我們看到的UI. 所以我們可以給 workbench.ts 加倆函數分別是 startupDarkModeButtonchangeThemeHandle 分別負責button的渲染和切換主題邏輯

private startupDarkModeButton(instantiationService: IInstantiationService) {
        const node = document.createElement("input");
        node.id = "dark-mode-button";
        node.style.backgroundColor = "blue";
        node.value = "dark mode";
        node.type = "checkbox";
        node.style.height = "26px";
        node.style.width = "100px";
        node.style.color = "#ffffff";
        // 這裏我就隨便加入到body裏面了...本文章只討論實現方式
        document.body.insertBefore(node, document.getElementById('monaco-parts-splash'))
        
        node.onchange = async () => {
            this.changeThemeHandle(instantiationService, node);
        }
}
private changeThemeHandle(instantiationService: IInstantiationService, checkbox: HTMLInputElement) {
    const themeIDs: string[] = [
        // 正常主題
        "vs thenikso-github-plus-theme-themes-github-plus-theme-json",
        // dark mode 主題
        "vs-dark vscode-theme-defaults-themes-dark_vs-json"
    ];
   
    // invokeFunction 主要是獲取ServicesAccessor
    instantiationService.invokeFunction((accessor: ServicesAccessor) => {
        const workbenchThemeService: IWorkbenchThemeService = accessor.get(IWorkbenchThemeService);
        
        // 切換主題       
        workbenchThemeService.setColorTheme(BELLCODE_THEMES[Number(el.checked)], undefined)
    })
}

然後在 startup 函數內調用我們的startupDarkModeButton函數來掛載我們的小按鈕

startup(): IInstantiationService {
        try {

            // Configure emitter leak warning threshold
            setGlobalLeakWarningThreshold(175);

            // ARIA
            setARIAContainer(document.body);

            // Services
            const instantiationService = this.initServices(this.serviceCollection);

            instantiationService.invokeFunction(async accessor => {
                const lifecycleService = accessor.get(ILifecycleService);
                const storageService = accessor.get(IStorageService);
                const configurationService = accessor.get(IConfigurationService);

                // Layout
                this.initLayout(accessor);

                // Registries
                this.startRegistries(accessor);

                // Context Keys
                this._register(instantiationService.createInstance(WorkbenchContextKeysHandler));

                // Register Listeners
                this.registerListeners(lifecycleService, storageService, configurationService);

                // Render Workbench
                this.renderWorkbench(instantiationService, accessor.get(INotificationService) as NotificationService, storageService, configurationService);

                // Workbench Layout
                this.createWorkbenchLayout();

                // Layout
                this.layout();
                
                // mount dark mode button
                this.startupDarkModeButton();
                
                // Restore
                try {
                    await this.restoreWorkbench(accessor.get(IEditorService), accessor.get(IEditorGroupsService), accessor.get(IViewletService), accessor.get(IPanelService), accessor.get(ILogService), lifecycleService);
                } catch (error) {
                    onUnexpectedError(error);
                }
            });

            return instantiationService;
        } catch (error) {
            onUnexpectedError(error);

            throw error; // rethrow because this is a critical issue we cannot handle properly here
        }
    }

簡單的兩個函數我們就基本實現了主題切換。如果像我的效果圖一樣自己寫了一些組件怎麼辦呢? 明天我們就講講如何擴展vscode UI。如果你覺得每天的文章內容過於簡單有問題可以私信我。 每天進步一點點.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章