Skip to content

Commit 4483916

Browse files
committed
ui(post-configuration-panel): synchronize the webview ui theme to vscode active color schema
1 parent d1510d8 commit 4483916

File tree

8 files changed

+213
-147
lines changed

8 files changed

+213
-147
lines changed

src/commands/posts-list/modify-post-settings.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -38,23 +38,21 @@ export const modifyPostSettings = async (input: Post | Uri) => {
3838
}
3939
const postEditDto = editDto.post;
4040
const localFilePath = PostFileMapManager.getFilePath(postId);
41-
await postConfigurationPanel.open(
42-
{
43-
panelTitle: '',
44-
breadcrumbs: ['更新博文设置', editDto.post.title],
45-
post: postEditDto,
46-
localFileUri: localFilePath ? Uri.file(localFilePath) : undefined,
47-
},
48-
() => {
41+
await postConfigurationPanel.open({
42+
panelTitle: '',
43+
breadcrumbs: ['更新博文设置', editDto.post.title],
44+
post: postEditDto,
45+
localFileUri: localFilePath ? Uri.file(localFilePath) : undefined,
46+
successCallback: () => {
4947
AlertService.info('博文已更新');
5048
},
51-
async post => {
49+
beforeUpdate: async post => {
5250
if (localFilePath && fs.existsSync(localFilePath)) {
5351
await saveFilePendingChanges(localFilePath);
5452
const content = await new LocalFileService(localFilePath).readAllText();
5553
post.postBody = content;
5654
}
5755
return true;
58-
}
59-
);
56+
},
57+
});
6058
};
Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import { commands, Uri } from 'vscode';
1+
import { commands, TextDocumentShowOptions, Uri } from 'vscode';
22
import { Post } from '../../models/post';
33
import { LocalFileService } from '../../services/local-draft.service';
44
import { PostFileMapManager } from '../../services/post-file-map';
55

6-
export const openPostFile = async (post: LocalFileService | Post | string) => {
6+
export const openPostFile = async (post: LocalFileService | Post | string, options?: TextDocumentShowOptions) => {
77
let filePath = '';
88
if (post instanceof LocalFileService) {
99
filePath = post.filePath;
@@ -15,7 +15,9 @@ export const openPostFile = async (post: LocalFileService | Post | string) => {
1515
if (!filePath) {
1616
return;
1717
}
18-
await commands.executeCommand('vscode.open', Uri.file(filePath), {
19-
preview: false,
20-
});
18+
await commands.executeCommand(
19+
'vscode.open',
20+
Uri.file(filePath),
21+
Object.assign({ preview: false } as TextDocumentShowOptions, options ?? {})
22+
);
2123
};

src/commands/posts-list/save-post.ts

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -98,20 +98,18 @@ export const saveLocalDraftToCnblogs = async (localDraft: LocalFileService) => {
9898
post.title = localDraft.fileNameWithoutExt;
9999
post.isMarkdown = true;
100100
post.categoryIds ??= [];
101-
void postConfigurationPanel.open(
102-
{
103-
panelTitle: '',
104-
breadcrumbs: ['新建博文', '博文设置', post.title],
105-
post,
106-
},
107-
async savedPost => {
101+
void postConfigurationPanel.open({
102+
panelTitle: '',
103+
breadcrumbs: ['新建博文', '博文设置', post.title],
104+
post,
105+
successCallback: async savedPost => {
108106
await refreshPostsList();
109107
await PostFileMapManager.updateOrCreate(savedPost.id, localDraft.filePath);
110108
postsDataProvider.fireTreeDataChangedEvent(undefined);
111109
await openPostFile(localDraft);
112110
AlertService.info('博文已创建');
113111
},
114-
async (postToSave, panel) => {
112+
beforeUpdate: async (postToSave, panel) => {
115113
await saveFilePendingChanges(localDraft.filePath);
116114
// 本地文件已经被删除了
117115
if (!localDraft.exist && panel) {
@@ -121,8 +119,8 @@ export const saveLocalDraftToCnblogs = async (localDraft: LocalFileService) => {
121119
const content = await localDraft.readAllText();
122120
postToSave.postBody = content;
123121
return true;
124-
}
125-
);
122+
},
123+
});
126124
};
127125

128126
export const savePostToCnblogs = async (input: Post | PostEditDto | undefined, isNewPost = false) => {

src/models/webview-command.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export namespace webviewCommand {
55
updateBreadcrumbs = 'updateBreadcrumbs',
66
updateImageUploadStatus = 'updateImageUploadStatus',
77
setFluentIconBaseUrl = 'setFluentIconBaseUrl',
8+
changeTheme = 'changeTheme',
89
}
910

1011
export enum ExtensionCommands {

src/models/webview-message.ts

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ export namespace webviewMessage {
1212
command: webviewCommand.UiCommands | webviewCommand.ExtensionCommands;
1313
}
1414

15+
/**
16+
* messages which post from the extension to the webview
17+
*
18+
* @export
19+
* @interface IUiMessage
20+
*/
21+
export interface IUiMessage {}
22+
1523
export interface EditPostConfigurationMessage extends Message {
1624
post: Post;
1725
activeTheme: ColorThemeKind;
@@ -25,24 +33,28 @@ export namespace webviewMessage {
2533
post: Post;
2634
}
2735

28-
export interface ShowErrorResponseMessage extends Message {
36+
export interface ShowErrorResponseMessage extends Message, IUiMessage {
2937
errorResponse: ErrorResponse;
3038
}
3139

32-
export interface UpdateBreadcrumbsMessage extends Message {
40+
export interface UpdateBreadcrumbsMessage extends Message, IUiMessage {
3341
breadcrumbs?: string[];
3442
}
3543

3644
export interface UploadImageMessage extends Message {
3745
imageId: string;
3846
}
3947

40-
export interface UpdateImageUpdateStatusMessage extends Message {
48+
export interface UpdateImageUpdateStatusMessage extends Message, IUiMessage {
4149
imageId: string;
4250
status: ImageUploadStatus;
4351
}
4452

45-
export interface SetFluentIconBaseUrlMessage extends Message {
53+
export interface SetFluentIconBaseUrlMessage extends Message, IUiMessage {
4654
baseUrl: string;
4755
}
56+
57+
export interface ChangeThemeMessage extends Message, IUiMessage {
58+
colorThemeKind: ColorThemeKind;
59+
}
4860
}
Lines changed: 108 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { cloneDeep } from 'lodash';
22
import vscode, { Uri } from 'vscode';
33
import path from 'path';
4-
import fs from 'fs';
54
import { Post } from '../models/post';
65
import { globalState } from './global-state';
76
import { postCategoryService } from './post-category.service';
@@ -13,6 +12,7 @@ import { webviewMessage } from '../models/webview-message';
1312
import { webviewCommand } from '../models/webview-command';
1413
import { uploadImage } from '../commands/upload-image/upload-image';
1514
import { ImageUploadStatusId } from '../models/image-upload-status';
15+
import { openPostFile } from '../commands/posts-list/open-post-file';
1616

1717
const panels: Map<string, vscode.WebviewPanel> = new Map();
1818

@@ -23,6 +23,8 @@ export namespace postConfigurationPanel {
2323
panelTitle?: string;
2424
localFileUri?: Uri;
2525
breadcrumbs?: string[];
26+
successCallback: (post: Post) => any;
27+
beforeUpdate?: (postToUpdate: Post, panel: vscode.WebviewPanel) => Promise<boolean>;
2628
}
2729
const resourceRootUri = () =>
2830
vscode.Uri.file(path.join(globalState.extensionContext!.extensionPath, 'dist', 'assets'));
@@ -37,29 +39,19 @@ export namespace postConfigurationPanel {
3739
};
3840

3941
export const buildPanelId = (postId: number, postTitle: string): string => `${postId}-${postTitle}`;
40-
export const findPanel = (panelId: string) => panels.get(panelId);
41-
42-
export const open = async (
43-
option: PostConfigurationPanelOpenOption,
44-
successCallback: (post: Post) => any,
45-
beforeUpdate?: (postToUpdate: Post, panel: vscode.WebviewPanel) => Promise<boolean>
46-
) => {
47-
let { post, panelTitle, localFileUri, breadcrumbs } = option;
48-
const { extensionContext } = globalState;
49-
if (!panelTitle) {
50-
panelTitle = `博文设置 - ${post.title}`;
51-
}
52-
if (localFileUri && fs.existsSync(localFileUri.fsPath)) {
53-
await vscode.commands.executeCommand('vscode.open', localFileUri, {
54-
preview: false,
55-
viewColumn: vscode.ViewColumn.One,
56-
} as vscode.TextDocumentShowOptions);
57-
}
42+
export const findPanelById = (panelId: string) => panels.get(panelId);
43+
export const open = async (option: PostConfigurationPanelOpenOption) => {
44+
let { post, panelTitle, breadcrumbs } = option;
45+
panelTitle = panelTitle ? panelTitle : `博文设置 - ${post.title}`;
46+
await openPostFile(post, {
47+
viewColumn: vscode.ViewColumn.One,
48+
});
5849
const panelId = buildPanelId(post.id, post.title);
59-
let panel = findPanel(panelId);
60-
if (revealPanel(panel, option)) {
50+
let panel = tryRevealPanel(panelId, option);
51+
if (panel) {
6152
return;
6253
}
54+
let disposables: (vscode.Disposable | undefined)[] = [];
6355
panel = await createPanel(panelTitle, post);
6456
const { webview } = panel;
6557
await webview.postMessage({
@@ -75,63 +67,23 @@ export namespace postConfigurationPanel {
7567
tags: cloneDeep(await postTagService.fetchTags()),
7668
breadcrumbs,
7769
} as webviewMessage.EditPostConfigurationMessage);
78-
webview.onDidReceiveMessage(
79-
async message => {
80-
const { command } = (message ?? {}) as webviewMessage.Message;
81-
switch (command) {
82-
case webviewCommand.ExtensionCommands.savePost:
83-
try {
84-
if (!panel) {
85-
return;
86-
}
87-
const { post: postToUpdate } = message as webviewMessage.SavePostMessage;
88-
if (beforeUpdate) {
89-
if (!(await beforeUpdate(postToUpdate, panel))) {
90-
panel.dispose();
91-
return;
92-
}
93-
}
94-
const postSavedModel = await postService.updatePost(postToUpdate);
95-
panel.dispose();
96-
successCallback(Object.assign({}, postToUpdate, postSavedModel));
97-
} catch (err) {
98-
if (isErrorResponse(err)) {
99-
await webview.postMessage({
100-
command: webviewCommand.UiCommands.showErrorResponse,
101-
errorResponse: err,
102-
} as webviewMessage.ShowErrorResponseMessage);
103-
} else {
104-
throw err;
105-
}
106-
}
107-
break;
108-
case webviewCommand.ExtensionCommands.disposePanel:
109-
panel?.dispose();
110-
break;
111-
case webviewCommand.ExtensionCommands.uploadImage:
112-
await handleUploadImageCommand(panel, message as any);
113-
break;
114-
}
115-
},
116-
undefined,
117-
globalState.extensionContext?.subscriptions
118-
);
119-
panel.onDidDispose(
120-
() => {
121-
panels.delete(panelId);
122-
panel = undefined;
123-
},
124-
undefined,
125-
extensionContext!.subscriptions
70+
disposables.push(
71+
observeWebviewMessages(panel, option),
72+
observeActiveColorSchemaChange(panel),
73+
observerPanelDisposeEvent(panel, disposables)
12674
);
12775
};
12876

129-
const revealPanel = (
130-
panel: vscode.WebviewPanel | null | undefined,
77+
const tryRevealPanel = (
78+
panelId: string | undefined,
13179
options: PostConfigurationPanelOpenOption
132-
): panel is vscode.WebviewPanel => {
80+
): vscode.WebviewPanel | undefined => {
81+
if (!panelId) {
82+
return;
83+
}
84+
const panel = findPanelById(panelId);
13385
if (!panel) {
134-
return false;
86+
return;
13587
}
13688
try {
13789
const { breadcrumbs } = options;
@@ -141,10 +93,11 @@ export namespace postConfigurationPanel {
14193
breadcrumbs,
14294
} as webviewMessage.UpdateBreadcrumbsMessage);
14395
panel.reveal();
144-
return true;
14596
} catch {
146-
return false;
97+
return undefined;
14798
}
99+
100+
return panel;
148101
};
149102

150103
const createPanel = async (panelTitle: string, post: Post): Promise<vscode.WebviewPanel> => {
@@ -160,7 +113,7 @@ export namespace postConfigurationPanel {
160113
return panel;
161114
};
162115

163-
const handleUploadImageCommand = async (
116+
const onUploadImageCommand = async (
164117
panel: vscode.WebviewPanel | undefined,
165118
message: webviewMessage.UploadImageMessage
166119
) => {
@@ -197,4 +150,83 @@ export namespace postConfigurationPanel {
197150
}
198151
}
199152
};
153+
154+
const observeActiveColorSchemaChange = (panel: vscode.WebviewPanel | undefined): vscode.Disposable | undefined => {
155+
if (!panel) {
156+
return;
157+
}
158+
const { webview } = panel;
159+
return vscode.window.onDidChangeActiveColorTheme(async theme => {
160+
await webview.postMessage({
161+
command: webviewCommand.UiCommands.changeTheme,
162+
colorThemeKind: theme.kind,
163+
} as webviewMessage.ChangeThemeMessage);
164+
});
165+
};
166+
167+
const observeWebviewMessages = (
168+
panel: vscode.WebviewPanel | undefined,
169+
options: PostConfigurationPanelOpenOption
170+
): vscode.Disposable | undefined => {
171+
if (!panel) {
172+
return;
173+
}
174+
const { webview } = panel;
175+
const { beforeUpdate, successCallback } = options;
176+
return webview.onDidReceiveMessage(async message => {
177+
const { command } = (message ?? {}) as webviewMessage.Message;
178+
switch (command) {
179+
case webviewCommand.ExtensionCommands.savePost:
180+
try {
181+
if (!panel) {
182+
return;
183+
}
184+
const { post: postToUpdate } = message as webviewMessage.SavePostMessage;
185+
if (beforeUpdate) {
186+
if (!(await beforeUpdate(postToUpdate, panel))) {
187+
panel.dispose();
188+
return;
189+
}
190+
}
191+
const postSavedModel = await postService.updatePost(postToUpdate);
192+
panel.dispose();
193+
successCallback(Object.assign({}, postToUpdate, postSavedModel));
194+
} catch (err) {
195+
if (isErrorResponse(err)) {
196+
await webview.postMessage({
197+
command: webviewCommand.UiCommands.showErrorResponse,
198+
errorResponse: err,
199+
} as webviewMessage.ShowErrorResponseMessage);
200+
} else {
201+
throw err;
202+
}
203+
}
204+
break;
205+
case webviewCommand.ExtensionCommands.disposePanel:
206+
panel?.dispose();
207+
break;
208+
case webviewCommand.ExtensionCommands.uploadImage:
209+
await onUploadImageCommand(panel, message as any);
210+
break;
211+
}
212+
});
213+
};
214+
215+
const observerPanelDisposeEvent = (
216+
panel: vscode.WebviewPanel | undefined,
217+
disposables: (vscode.Disposable | undefined)[]
218+
): vscode.Disposable | undefined => {
219+
if (!panel) {
220+
return;
221+
}
222+
223+
return panel.onDidDispose(() => {
224+
if (panel) {
225+
const panelId = panel.viewType;
226+
panels.delete(panelId);
227+
panel = undefined;
228+
disposables.forEach(disposable => disposable?.dispose());
229+
}
230+
});
231+
};
200232
}

0 commit comments

Comments
 (0)