返回 DeepSeek-Reasonix
session_topic_index.go
根目录 / desktop / session_topic_index.go
1 package main
2
3 import (
4 "sort"
5 "strings"
6
7 "reasonix/desktop/internal/workspacestate"
8 "reasonix/internal/session"
9 )
10
11 // Group and pin membership need no session header. Apply them before Stat so
12 // opening a small group cannot load every unrelated current-format manifest.
13 // The ordinary unfiltered view retains the existing header path.
14 func admittedWorkspaceTopicMembers(req ProjectTopicPageRequest, state workspacestate.State, workspace workspacestate.Workspace) []string {
15 grouped := req.GroupFilter == "group" || req.GroupFilter == "ungrouped"
16 if !grouped && !req.pinnedOnly && !req.ExcludePinned {
17 return workspace.SessionIDs
18 }
19 members := map[string]bool{}
20 groups := req.groupAll
21 if req.GroupFilter == "group" {
22 groups = nil
23 if req.groupSelected != nil {
24 groups = []desktopGroup{*req.groupSelected}
25 }
26 }
27 for _, group := range groups {
28 for _, key := range group.SessionKeys {
29 members[strings.TrimSpace(key)] = true
30 }
31 }
32 ids := make([]string, 0)
33 for _, id := range workspace.SessionIDs {
34 pin := state.Presentation[id].Pinned
35 if req.pinnedOnly && !pin || req.ExcludePinned && pin {
36 continue
37 }
38 member := members[workspacestate.SessionKey(id)]
39 if req.GroupFilter == "group" && !member || req.GroupFilter == "ungrouped" && member {
40 continue
41 }
42 ids = append(ids, id)
43 }
44 return ids
45 }
46
47 // Sorting is owned by the immutable read snapshot. Do not retain a second
48 // cache of mutable materialized rows with an independent eviction policy.
49 func (a *App) indexedWorkspaceTopics(req ProjectTopicPageRequest, state workspacestate.State, workspace workspacestate.Workspace, org workspacestate.Organization, infos map[string]session.SessionInfo, sources []ProjectNode) []ProjectNode {
50 created := loadTopicCreatedAts(topicTitleRoot(req.Scope, req.WorkspaceRoot))
51 all := req
52 all.Query, all.TimeFilter, all.GroupFilter = "", "", "all"
53 all.ExcludePinned, all.groupSelected, all.groupAll = false, nil, nil
54 nodes := a.canonicalTopicNodes(all, state, workspace, infos, sources, created)
55 nodes = filterWorkspaceSessionNodes(req, org, state, workspace.ID, nodes)
56 sort.SliceStable(nodes, func(i, j int) bool { return projectTopicLess(nodes[i], nodes[j], req.SortMode, org.ManualOrderEnabled) })
57 return nodes
58 }
59
60 func cloneTopicPage(nodes []ProjectNode) []ProjectNode {
61 result := make([]ProjectNode, len(nodes))
62 for i, node := range nodes {
63 node.Children = cloneTopicPage(node.Children)
64 node.IdentityAliases = append([]string(nil), node.IdentityAliases...)
65 if node.Session != nil {
66 ref := *node.Session
67 node.Session = &ref
68 }
69 if node.ParentSession != nil {
70 ref := *node.ParentSession
71 node.ParentSession = &ref
72 }
73 if node.Source != nil {
74 ref := *node.Source
75 node.Source = &ref
76 }
77 if node.Remote != nil {
78 ref := *node.Remote
79 node.Remote = &ref
80 }
81 result[i] = node
82 }
83 return result
84 }
85
85 lines GO