Skip to content

Commit 2a47537

Browse files
authored
feat: allow customize page size of posts list (#77)
1 parent 0f47920 commit 2a47537

File tree

6 files changed

+97
-40
lines changed

6 files changed

+97
-40
lines changed

.vscode/settings.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
// Turn off tsc task auto detection since we have the necessary tasks as npm scripts
1212
"typescript.tsc.autoDetect": "off",
1313
"editor.formatOnSave": true,
14-
"cSpell.words": ["ASPNETCORE", "fluentui", "randomstring", "tailwindcss"],
14+
"cSpell.words": ["ASPNETCORE", "fluentui", "randomstring", "singleline", "tailwindcss"],
1515
"json.format.enable": false,
1616
"eslint.alwaysShowStatus": true,
1717
"eslint.lintTask.enable": true,

package.json

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@
231231
"scope": "application",
232232
"type": "string",
233233
"editPresentation": "singlelineText",
234-
"markdownDescription": "存放markdown博文的文件夹, 默认为`~/Documents/Cnblogs`, 当检测到vscode处于此工作空间时, 可以vscode-cnb插件编辑已有博文, 也可以将本地markdown文件保存到博客园"
234+
"markdownDescription": "存放博文的文件夹, 默认为`~/Documents/Cnblogs`, 当检测到vscode处于此工作空间时, 可以vscode-cnb插件编辑已有博文, 也可以将本地markdown文件保存到博客园"
235235
},
236236
"cnblogsClientForVSCode.windows.chromiumPath": {
237237
"order": 1,
@@ -254,7 +254,7 @@
254254
"default": true,
255255
"scope": "application",
256256
"type": "boolean",
257-
"markdownDescription": "设置是否根据博文分类保存到不同的文件夹中"
257+
"markdownDescription": "创建本地博文时, 是否根据博文分类保存到对应的文件夹中"
258258
},
259259
"cnblogsClientForVSCode.automaticallyExtractImages": {
260260
"order": 4,
@@ -273,7 +273,27 @@
273273
"自动提取全部图片"
274274
],
275275
"editPresentation": "singlelineText",
276-
"description": "配置保存到博客园时要自动进行提取上传到博客园的图片"
276+
"markdownDescription": "提取图片, 配置保存到博客园时要自动提取上传到博客园的图片"
277+
},
278+
"cnblogsClientForVSCode.pageSize.postsList": {
279+
"order": 5,
280+
"default": 30,
281+
"scope": "application",
282+
"editPresentation": "singlelineText",
283+
"markdownDescription": "随笔列表分页大小, 自定义随笔列表每页展示数量",
284+
"type": "integer",
285+
"maximum": 100,
286+
"enum": [
287+
20,
288+
30,
289+
40,
290+
50,
291+
60,
292+
70,
293+
80,
294+
90,
295+
100
296+
]
277297
}
278298
}
279299
}

src/commands/posts-list/refresh-posts-list.ts

Lines changed: 55 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -4,35 +4,55 @@ import vscode from 'vscode';
44
import { postsDataProvider } from '../../tree-view-providers/posts-data-provider';
55
import { AlertService } from '../../services/alert.service';
66
import { PostsListState } from '../../models/posts-list-state';
7-
import { PageModel } from '../../models/page-model';
8-
import { Post } from '../../models/post';
97
import { window } from 'vscode';
108
import { extensionViews } from '../../tree-view-providers/tree-view-registration';
119

12-
export const refreshPostsList = async () => {
13-
if (refreshing) {
10+
let refreshTask: Promise<any> | null = null;
11+
12+
export const refreshPostsList = ({ queue = false } = {}): Promise<boolean> => {
13+
if (refreshing && !queue) {
1414
alertRefreshing();
15-
return;
16-
}
17-
await setRefreshing(true);
18-
let pagedPosts: PageModel<Post> | undefined;
19-
try {
20-
await postsDataProvider.loadPosts();
21-
pagedPosts = postsDataProvider.pagedPosts;
22-
if (pagedPosts) {
23-
await postService.updatePostsListState(pagedPosts);
24-
updatePostsListViewTitle();
25-
}
26-
} catch (e) {
27-
console.error('refresh posts list failed', e);
28-
AlertService.error('刷新博文列表失败');
15+
return refreshTask || Promise.resolve(false);
16+
} else if (refreshing && refreshTask != null) {
17+
return refreshTask.then(() => refreshPostsList());
2918
}
30-
await setPostListContext(
31-
pagedPosts?.pageCount ?? 0,
32-
pagedPosts?.hasPrevious ?? false,
33-
pagedPosts?.hasNext ?? false
19+
20+
refreshTask = new Promise<boolean>(resolve =>
21+
setRefreshing(true).finally(() =>
22+
postsDataProvider
23+
.loadPosts()
24+
.then(pagedPosts =>
25+
setPostListContext(
26+
pagedPosts?.pageCount ?? 0,
27+
pagedPosts?.hasPrevious ?? false,
28+
pagedPosts?.hasNext ?? false
29+
).then(() => pagedPosts)
30+
)
31+
.then(pagedPosts =>
32+
pagedPosts == null
33+
? Promise.resolve(false).finally(() => AlertService.error('刷新博文列表失败'))
34+
: postService
35+
.updatePostsListState(pagedPosts)
36+
.then(() => updatePostsListViewTitle())
37+
.then(
38+
() => true,
39+
() => true
40+
)
41+
)
42+
.catch(() => false)
43+
.then(x =>
44+
setRefreshing(false).then(
45+
() => x,
46+
() => x
47+
)
48+
)
49+
.then(undefined, () => false)
50+
.then(x => resolve(x))
51+
.finally(() => (refreshTask = null))
52+
)
3453
);
35-
await setRefreshing(false);
54+
55+
return refreshTask;
3656
};
3757

3858
export const gotoNextPostsList = async () => {
@@ -71,7 +91,9 @@ export const seekPostsList = async () => {
7191
let refreshing = false;
7292
const setRefreshing = async (value = false) => {
7393
const extName = globalState.extensionName;
74-
await vscode.commands.executeCommand('setContext', `${extName}.posts-list.refreshing`, value);
94+
await vscode.commands
95+
.executeCommand('setContext', `${extName}.posts-list.refreshing`, value)
96+
.then(undefined, () => false);
7597
refreshing = value;
7698
};
7799

@@ -116,12 +138,14 @@ const updatePostsListViewTitle = () => {
116138
return;
117139
}
118140
const { pageIndex, pageCount } = state;
119-
const view = extensionViews.postsList;
120-
if (view) {
121-
let title = view.title!;
122-
const idx = title.indexOf('(');
123-
const pager = `第${pageIndex}页,共${pageCount}页`;
124-
title = idx >= 0 ? title.substring(0, idx) : title;
125-
view.title = `${title}(${pager})`;
141+
const views = [extensionViews.postsList, extensionViews.anotherPostsList];
142+
for (const view of views) {
143+
if (view) {
144+
let title = view.title!;
145+
const idx = title.indexOf('(');
146+
const pager = `第${pageIndex}页,共${pageCount}页`;
147+
title = idx >= 0 ? title.substring(0, idx) : title;
148+
view.title = `${title}(${pager})`;
149+
}
126150
}
127151
};

src/services/check-workspace.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { commands, workspace } from 'vscode';
22
import { refreshPostCategoriesList } from '../commands/post-category/refresh-post-categories-list';
3+
import { refreshPostsList } from '../commands/posts-list/refresh-posts-list';
34
import { globalState } from './global-state';
45
import { PostFileMapManager } from './post-file-map';
56
import { Settings } from './settings.service';
@@ -20,6 +21,9 @@ export const observeConfigurationChange = () => {
2021
if (ev.affectsConfiguration(`${Settings.iconThemePrefix}.${Settings.iconThemeKey}`)) {
2122
refreshPostCategoriesList();
2223
}
24+
if (ev.affectsConfiguration(`${Settings.prefix}.${Settings.postsListPageSizeKey}`)) {
25+
void refreshPostsList({ queue: true });
26+
}
2327
})
2428
);
2529
isTargetWorkspace();

src/services/settings.service.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,11 @@ import { homedir, platform } from 'os';
22
import fs from 'fs';
33
import { ConfigurationTarget, Uri, workspace } from 'vscode';
44
import { MarkdownImagesExtractor } from './images-extractor.service';
5+
import { isNumber } from 'lodash';
56

67
export class Settings {
8+
static readonly postsListPageSizeKey = 'pageSize.postsList';
9+
710
static get prefix() {
811
return `cnblogsClientForVSCode`;
912
}
@@ -81,4 +84,9 @@ export class Settings {
8184
this.configuration.get<MarkdownImagesExtractor['imageType']>('automaticallyExtractImages') ?? null;
8285
return value?.startsWith('---') ? null : value;
8386
}
87+
88+
static get postsListPageSize() {
89+
let size = this.configuration.get<number>(this.postsListPageSizeKey);
90+
return isNumber(size) ? size : 30;
91+
}
8492
}

src/tree-view-providers/posts-data-provider.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,21 @@ export class PostsDataProvider implements TreeDataProvider<PostDataProviderItem>
8080
} as TreeItem);
8181
}
8282

83-
async loadPosts(): Promise<void> {
83+
async loadPosts(): Promise<PageModel<Post> | null> {
8484
try {
85-
const { pageIndex, pageSize } = postService.postsListState ?? {
86-
pageIndex: undefined,
87-
pageSize: undefined,
88-
};
85+
const { pageIndex } = postService.postsListState ?? {};
86+
const pageSize = Settings.postsListPageSize;
8987
this._pagedPosts = await postService.fetchPostsList({ pageIndex, pageSize });
9088
this.fireTreeDataChangedEvent(undefined);
89+
return this._pagedPosts;
9190
} catch (ex) {
9291
if (ex instanceof Error) {
9392
AlertService.error(ex.message);
9493
} else {
9594
AlertService.error(`Failed to fetch posts list\n${JSON.stringify(ex)}`);
9695
}
96+
97+
return null;
9798
}
9899
}
99100

0 commit comments

Comments
 (0)