返回 DeepSeek-Reasonix
topic_delete.go
根目录 / desktop / topic_delete.go
1 package main
2
3 // DeleteTopic removes a topic and its title metadata.
4 func (a *App) DeleteTopic(topicID string) error {
5 return friendlySessionFileError(a.deleteTopic(topicID))
6 }
7
8 func (a *App) deleteTopic(topicID string) error {
9 a.topicTitleMutationMu.Lock()
10 defer a.topicTitleMutationMu.Unlock()
11 topicIndexMu.Lock()
12 defer topicIndexMu.Unlock()
13 return a.deleteTopicMutationLocked(topicID)
14 }
15
16 func (a *App) deleteTopicMutationLocked(topicID string) error {
17 desktopProjectsFileMu.Lock()
18 defer desktopProjectsFileMu.Unlock()
19 return a.deleteTopicMutationProjectsLocked(topicID)
20 }
21
22 func (a *App) deleteTopicMutationProjectsLocked(topicID string) error {
23 release, err := acquireDesktopProjectsFileLock()
24 if err != nil {
25 return err
26 }
27 defer release()
28 return a.deleteTopicMutationProjectsCrossProcessLocked(topicID)
29 }
30
31 // deleteTopicMutationProjectsCrossProcessLocked requires the process and file
32 // locks for desktop-projects.json.
33 func (a *App) deleteTopicMutationProjectsCrossProcessLocked(topicID string) error {
34 f := loadProjectsFile()
35 indexed := map[string]bool{
36 "": containsDesktopString(f.GlobalTopics, topicID) || containsDesktopString(f.GlobalPinnedTopics, topicID),
37 }
38 roots := make([]string, 0, len(f.Projects)+1)
39 for _, project := range f.Projects {
40 roots = append(roots, project.Root)
41 indexed[project.Root] = containsDesktopString(project.Topics, topicID) || containsDesktopString(project.PinnedTopics, topicID)
42 }
43 // The tombstone prevents stale migration and repair snapshots from
44 // resurrecting the topic while its per-scope metadata is removed.
45 if err := removeTopicFromProjectsFileCrossProcessLocked(topicID); err != nil {
46 return err
47 }
48 roots = append(roots, "")
49 for _, root := range roots {
50 titles, err := loadTopicTitlesForUpdate(root)
51 if err != nil {
52 if indexed[root] {
53 return err
54 }
55 continue
56 }
57 if _, hasTitle := titles[topicID]; !hasTitle && !indexed[root] {
58 continue
59 }
60 if err := deleteTopicState(root, topicID); err != nil {
61 return err
62 }
63 }
64 a.emitProjectTreeMetadataChanged()
65 return nil
66 }
67
67 lines GO