Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T02:59:08.373Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git
Browse files

history_manager.rs

145 lines · 4.5 KB · rust
1use std::{path::PathBuf, sync::Arc};
2
3use fs::Fs;
4use gpui::{AppContext, Entity, Global, MenuItem};
5use smallvec::SmallVec;
6use ui::{App, Context};
7use util::{ResultExt, paths::PathExt};
8
9use crate::{
10    NewWindow, SerializedWorkspaceLocation, WorkspaceId, path_list::PathList,
11    persistence::WorkspaceDb,
12};
13
14pub fn init(fs: Arc<dyn Fs>, cx: &mut App) {
15    let manager = cx.new(|_| HistoryManager::new());
16    HistoryManager::set_global(manager.clone(), cx);
17    HistoryManager::init(manager, fs, cx);
18}
19
20pub struct HistoryManager {
21    /// The history of workspaces that have been opened in the past, in reverse order.
22    /// The most recent workspace is at the end of the vector.
23    history: Vec<HistoryManagerEntry>,
24}
25
26#[derive(Debug)]
27pub struct HistoryManagerEntry {
28    pub id: WorkspaceId,
29    pub path: SmallVec<[PathBuf; 2]>,
30}
31
32struct GlobalHistoryManager(Entity<HistoryManager>);
33
34impl Global for GlobalHistoryManager {}
35
36impl HistoryManager {
37    fn new() -> Self {
38        Self {
39            history: Vec::new(),
40        }
41    }
42
43    fn init(this: Entity<HistoryManager>, fs: Arc<dyn Fs>, cx: &App) {
44        let db = WorkspaceDb::global(cx);
45        cx.spawn(async move |cx| {
46            let recent_folders = db
47                .recent_project_workspaces(fs.as_ref())
48                .await
49                .unwrap_or_default()
50                .into_iter()
51                .rev()
52                .filter_map(|workspace| {
53                    if matches!(workspace.location, SerializedWorkspaceLocation::Local) {
54                        Some(HistoryManagerEntry::new(
55                            workspace.workspace_id,
56                            &workspace.paths,
57                        ))
58                    } else {
59                        None
60                    }
61                })
62                .collect::<Vec<_>>();
63            this.update(cx, |this, cx| {
64                this.history = recent_folders;
65                this.update_jump_list(cx);
66            })
67        })
68        .detach();
69    }
70
71    pub fn global(cx: &App) -> Option<Entity<Self>> {
72        cx.try_global::<GlobalHistoryManager>()
73            .map(|model| model.0.clone())
74    }
75
76    fn set_global(history_manager: Entity<Self>, cx: &mut App) {
77        cx.set_global(GlobalHistoryManager(history_manager));
78    }
79
80    pub fn update_history(
81        &mut self,
82        id: WorkspaceId,
83        entry: HistoryManagerEntry,
84        cx: &mut Context<'_, HistoryManager>,
85    ) {
86        if let Some(pos) = self.history.iter().position(|e| e.id == id) {
87            self.history.remove(pos);
88        }
89        self.history.push(entry);
90        self.update_jump_list(cx);
91    }
92
93    pub fn delete_history(&mut self, id: WorkspaceId, cx: &mut Context<'_, HistoryManager>) {
94        let Some(pos) = self.history.iter().position(|e| e.id == id) else {
95            return;
96        };
97        self.history.remove(pos);
98        self.update_jump_list(cx);
99    }
100
101    fn update_jump_list(&mut self, cx: &mut Context<'_, HistoryManager>) {
102        let menus = vec![MenuItem::action("New Window", NewWindow)];
103        let entries = self
104            .history
105            .iter()
106            .rev()
107            .map(|entry| entry.path.clone())
108            .collect::<Vec<_>>();
109        let user_removed = cx.update_jump_list(menus, entries);
110        let db = WorkspaceDb::global(cx);
111        cx.spawn(async move |this, cx| {
112            let user_removed = user_removed.await;
113            if user_removed.is_empty() {
114                return;
115            }
116            let mut deleted_ids = Vec::new();
117            if let Ok(()) = this.update(cx, |this, _| {
118                for idx in (0..this.history.len()).rev() {
119                    if let Some(entry) = this.history.get(idx)
120                        && user_removed.contains(&entry.path)
121                    {
122                        deleted_ids.push(entry.id);
123                        this.history.remove(idx);
124                    }
125                }
126            }) {
127                for id in deleted_ids.iter() {
128                    db.delete_workspace_by_id(*id).await.log_err();
129                }
130            }
131        })
132        .detach();
133    }
134}
135
136impl HistoryManagerEntry {
137    pub fn new(id: WorkspaceId, paths: &PathList) -> Self {
138        let path = paths
139            .ordered_paths()
140            .map(|path| path.compact())
141            .collect::<SmallVec<[PathBuf; 2]>>();
142        Self { id, path }
143    }
144}
145
Served at tenant.openagents/omega Member data and write actions are omitted.