Skip to content

Commit 16cc188

Browse files
committed
Ensure the API correctly returns an empty array, add deduplication logic, and remove redundant sorting steps when updating fields
1 parent 1c240e0 commit 16cc188

File tree

1 file changed

+65
-30
lines changed

1 file changed

+65
-30
lines changed

kernel/model/storage.go

Lines changed: 65 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -51,23 +51,33 @@ type OutlineDoc struct {
5151

5252
var recentDocLock = sync.Mutex{}
5353

54-
// 三种类型各保留 32 条记录,并清空 Title 和 Icon
55-
func trimRecentDocs(recentDocs []*RecentDoc) []*RecentDoc {
56-
if len(recentDocs) <= 32 {
54+
// normalizeRecentDocs 规范化最近文档列表:去重、清空 Title/Icon、按类型截取 32 条记录
55+
func normalizeRecentDocs(recentDocs []*RecentDoc) []*RecentDoc {
56+
// 去重
57+
seen := make(map[string]struct{}, len(recentDocs))
58+
deduplicated := make([]*RecentDoc, 0, len(recentDocs))
59+
for _, doc := range recentDocs {
60+
if _, ok := seen[doc.RootID]; !ok {
61+
seen[doc.RootID] = struct{}{}
62+
deduplicated = append(deduplicated, doc)
63+
}
64+
}
65+
66+
if len(deduplicated) <= 32 {
5767
// 清空 Title 和 Icon
58-
for _, doc := range recentDocs {
68+
for _, doc := range deduplicated {
5969
doc.Title = ""
6070
doc.Icon = ""
6171
}
62-
return recentDocs
72+
return deduplicated
6373
}
6474

6575
// 分别统计三种类型的记录
6676
var viewedDocs []*RecentDoc
6777
var openedDocs []*RecentDoc
6878
var closedDocs []*RecentDoc
6979

70-
for _, doc := range recentDocs {
80+
for _, doc := range deduplicated {
7181
if doc.ViewedAt > 0 {
7282
viewedDocs = append(viewedDocs, doc)
7383
}
@@ -131,7 +141,7 @@ func UpdateRecentDocOpenTime(rootID string) (err error) {
131141
recentDocLock.Lock()
132142
defer recentDocLock.Unlock()
133143

134-
recentDocs, err := getRecentDocs("")
144+
recentDocs, err := loadRecentDocsRaw()
135145
if err != nil {
136146
return
137147
}
@@ -168,7 +178,7 @@ func UpdateRecentDocViewTime(rootID string) (err error) {
168178
recentDocLock.Lock()
169179
defer recentDocLock.Unlock()
170180

171-
recentDocs, err := getRecentDocs("")
181+
recentDocs, err := loadRecentDocsRaw()
172182
if err != nil {
173183
return
174184
}
@@ -214,7 +224,7 @@ func BatchUpdateRecentDocCloseTime(rootIDs []string) (err error) {
214224
recentDocLock.Lock()
215225
defer recentDocLock.Unlock()
216226

217-
recentDocs, err := getRecentDocs("")
227+
recentDocs, err := loadRecentDocsRaw()
218228
if err != nil {
219229
return
220230
}
@@ -266,7 +276,7 @@ func GetRecentDocs(sortBy string) (ret []*RecentDoc, err error) {
266276
}
267277

268278
func setRecentDocs(recentDocs []*RecentDoc) (err error) {
269-
recentDocs = trimRecentDocs(recentDocs)
279+
recentDocs = normalizeRecentDocs(recentDocs)
270280

271281
dirPath := filepath.Join(util.DataDir, "storage")
272282
if err = os.MkdirAll(dirPath, 0755); err != nil {
@@ -289,8 +299,7 @@ func setRecentDocs(recentDocs []*RecentDoc) (err error) {
289299
return
290300
}
291301

292-
func getRecentDocs(sortBy string) (ret []*RecentDoc, err error) {
293-
var tmp []*RecentDoc
302+
func loadRecentDocsRaw() (ret []*RecentDoc, err error) {
294303
dataPath := filepath.Join(util.DataDir, "storage/recent-doc.json")
295304
if !filelock.IsExist(dataPath) {
296305
return
@@ -302,22 +311,41 @@ func getRecentDocs(sortBy string) (ret []*RecentDoc, err error) {
302311
return
303312
}
304313

305-
if err = gulu.JSON.UnmarshalJSON(data, &tmp); err != nil {
314+
if err = gulu.JSON.UnmarshalJSON(data, &ret); err != nil {
306315
logging.LogErrorf("unmarshal storage [recent-doc] failed: %s", err)
307316
if err = setRecentDocs([]*RecentDoc{}); err != nil {
308317
logging.LogErrorf("reset storage [recent-doc] failed: %s", err)
309318
}
310319
ret = []*RecentDoc{}
311320
return
312321
}
322+
return
323+
}
324+
325+
func getRecentDocs(sortBy string) (ret []*RecentDoc, err error) {
326+
ret = []*RecentDoc{} // 初始化为空切片,确保 API 始终返回非 nil
327+
recentDocs, err := loadRecentDocsRaw()
328+
if err != nil {
329+
return
330+
}
331+
332+
// 去重
333+
seen := make(map[string]struct{}, len(recentDocs))
334+
var deduplicated []*RecentDoc
335+
for _, doc := range recentDocs {
336+
if _, ok := seen[doc.RootID]; !ok {
337+
seen[doc.RootID] = struct{}{}
338+
deduplicated = append(deduplicated, doc)
339+
}
340+
}
313341

314342
var rootIDs []string
315-
for _, doc := range tmp {
343+
for _, doc := range deduplicated {
316344
rootIDs = append(rootIDs, doc.RootID)
317345
}
318346
bts := treenode.GetBlockTrees(rootIDs)
319347
var notExists []string
320-
for _, doc := range tmp {
348+
for _, doc := range deduplicated {
321349
if bt := bts[doc.RootID]; nil != bt {
322350
// 获取最新的文档标题和图标
323351
doc.Title = path.Base(bt.HPath) // Recent docs not updated after renaming https://github.com/siyuan-note/siyuan/issues/7827
@@ -332,9 +360,9 @@ func getRecentDocs(sortBy string) (ret []*RecentDoc, err error) {
332360
}
333361

334362
if 0 < len(notExists) {
335-
err := setRecentDocs(ret)
363+
err = setRecentDocs(ret)
336364
if err != nil {
337-
return nil, err
365+
return
338366
}
339367
}
340368

@@ -391,38 +419,45 @@ func getRecentDocs(sortBy string) (ret []*RecentDoc, err error) {
391419
ret = append(ret, doc)
392420
}
393421
case "closedAt": // 按关闭时间排序
394-
var filtered []*RecentDoc
422+
filtered := []*RecentDoc{} // 初始化为空切片,确保 API 始终返回非 nil
395423
for _, doc := range ret {
396424
if doc.ClosedAt > 0 {
397425
filtered = append(filtered, doc)
398426
}
399427
}
400428
ret = filtered
401-
sort.Slice(ret, func(i, j int) bool {
402-
return ret[i].ClosedAt > ret[j].ClosedAt
403-
})
429+
if 0 < len(ret) {
430+
sort.Slice(ret, func(i, j int) bool {
431+
return ret[i].ClosedAt > ret[j].ClosedAt
432+
})
433+
}
404434
case "openAt": // 按打开时间排序
405-
var filtered []*RecentDoc
435+
filtered := []*RecentDoc{} // 初始化为空切片,确保 API 始终返回非 nil
406436
for _, doc := range ret {
407437
if doc.OpenAt > 0 {
408438
filtered = append(filtered, doc)
409439
}
410440
}
411441
ret = filtered
412-
sort.Slice(ret, func(i, j int) bool {
413-
return ret[i].OpenAt > ret[j].OpenAt
414-
})
415-
default: // 默认按浏览时间排序
416-
var filtered []*RecentDoc
442+
if 0 < len(ret) {
443+
sort.Slice(ret, func(i, j int) bool {
444+
return ret[i].OpenAt > ret[j].OpenAt
445+
})
446+
}
447+
case "viewedAt": // 按浏览时间排序
448+
default:
449+
filtered := []*RecentDoc{} // 初始化为空切片,确保 API 始终返回非 nil
417450
for _, doc := range ret {
418451
if doc.ViewedAt > 0 {
419452
filtered = append(filtered, doc)
420453
}
421454
}
422455
ret = filtered
423-
sort.Slice(ret, func(i, j int) bool {
424-
return ret[i].ViewedAt > ret[j].ViewedAt
425-
})
456+
if 0 < len(ret) {
457+
sort.Slice(ret, func(i, j int) bool {
458+
return ret[i].ViewedAt > ret[j].ViewedAt
459+
})
460+
}
426461
}
427462
return
428463
}

0 commit comments

Comments
 (0)