Detailed changes
@@ -565,15 +565,17 @@ fn collect_importable_threads(
let Some(folder_paths) = session.work_dirs else {
continue;
};
+ let updated_at = session.updated_at.unwrap_or_else(|| Utc::now());
to_insert.push(ThreadMetadata {
thread_id: ThreadId::new(),
session_id: Some(session.session_id),
agent_id: agent_id.clone(),
title: session.title,
- updated_at: session.updated_at.unwrap_or_else(|| Utc::now()),
+ updated_at,
created_at: session.created_at,
worktree_paths: WorktreePaths::from_folder_paths(&folder_paths),
remote_connection: remote_connection.clone(),
+ last_user_interaction: updated_at,
archived: true,
});
}
@@ -908,12 +910,19 @@ mod tests {
let thread_id = uuid::Uuid::new_v4();
let session_id = uuid::Uuid::new_v4().to_string();
connection
- .exec_bound::<(uuid::Uuid, &str, &str, &str, bool)>(
+ .exec_bound::<(uuid::Uuid, &str, &str, &str, bool, &str)>(
"INSERT INTO sidebar_threads \
- (thread_id, session_id, title, updated_at, archived) \
- VALUES (?1, ?2, ?3, ?4, ?5)",
+ (thread_id, session_id, title, updated_at, archived, last_user_interaction) \
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6)",
)
- .unwrap()((thread_id, session_id.as_str(), title, updated_at, archived))
+ .unwrap()((
+ thread_id,
+ session_id.as_str(),
+ title,
+ updated_at,
+ archived,
+ updated_at,
+ ))
.unwrap();
}
@@ -127,6 +127,7 @@ fn migrate_thread_metadata(cx: &mut App) -> Task<anyhow::Result<()>> {
created_at: entry.created_at,
worktree_paths: WorktreePaths::from_folder_paths(&entry.folder_paths),
remote_connection: None,
+ last_user_interaction: entry.updated_at,
archived: true,
})
})
@@ -296,6 +297,7 @@ pub struct ThreadMetadata {
pub created_at: Option<DateTime<Utc>>,
pub worktree_paths: WorktreePaths,
pub remote_connection: Option<RemoteConnectionOptions>,
+ pub last_user_interaction: DateTime<Utc>,
pub archived: bool,
}
@@ -672,6 +674,20 @@ impl ThreadMetadataStore {
.log_err();
}
+ pub fn update_last_user_interaction(
+ &mut self,
+ thread_id: ThreadId,
+ time: DateTime<Utc>,
+ cx: &mut Context<Self>,
+ ) {
+ if let Some(thread) = self.threads.get(&thread_id).cloned() {
+ self.save_internal(ThreadMetadata {
+ last_user_interaction: time,
+ ..thread
+ });
+ cx.notify();
+ }
+ }
fn cache_thread_metadata(&mut self, metadata: ThreadMetadata) {
let Some(session_id) = metadata.session_id.as_ref() else {
debug_panic!("cannot store thread metadata without a session_id");
@@ -1190,6 +1206,7 @@ impl ThreadMetadataStore {
updated_at,
worktree_paths,
remote_connection,
+ last_user_interaction: updated_at,
archived,
};
@@ -1277,6 +1294,35 @@ impl Domain for ThreadMetadataDb {
DROP TABLE sidebar_threads;
ALTER TABLE sidebar_threads_v2 RENAME TO sidebar_threads;
),
+ sql!(
+ ALTER TABLE sidebar_threads ADD COLUMN last_user_interaction TEXT;
+
+ UPDATE sidebar_threads SET last_user_interaction = updated_at
+ WHERE last_user_interaction IS NULL;
+
+ CREATE TABLE sidebar_threads_v3(
+ thread_id BLOB PRIMARY KEY,
+ session_id TEXT,
+ agent_id TEXT,
+ title TEXT NOT NULL,
+ updated_at TEXT NOT NULL,
+ created_at TEXT,
+ folder_paths TEXT,
+ folder_paths_order TEXT,
+ archived INTEGER DEFAULT 0,
+ main_worktree_paths TEXT,
+ main_worktree_paths_order TEXT,
+ remote_connection TEXT,
+ last_user_interaction TEXT NOT NULL
+ ) STRICT;
+
+ INSERT INTO sidebar_threads_v3(thread_id, session_id, agent_id, title, updated_at, created_at, folder_paths, folder_paths_order, archived, main_worktree_paths, main_worktree_paths_order, remote_connection, last_user_interaction)
+ SELECT thread_id, session_id, agent_id, title, updated_at, created_at, folder_paths, folder_paths_order, archived, main_worktree_paths, main_worktree_paths_order, remote_connection, last_user_interaction
+ FROM sidebar_threads;
+
+ DROP TABLE sidebar_threads;
+ ALTER TABLE sidebar_threads_v3 RENAME TO sidebar_threads;
+ ),
sql!(
DELETE FROM thread_archived_worktrees
WHERE thread_id IN (
@@ -1307,7 +1353,7 @@ impl ThreadMetadataDb {
const LIST_QUERY: &str = "SELECT thread_id, session_id, agent_id, title, updated_at, \
created_at, folder_paths, folder_paths_order, archived, main_worktree_paths, \
- main_worktree_paths_order, remote_connection \
+ main_worktree_paths_order, remote_connection, last_user_interaction \
FROM sidebar_threads \
WHERE session_id IS NOT NULL \
ORDER BY updated_at DESC";
@@ -1360,10 +1406,11 @@ impl ThreadMetadataDb {
.context("serialize thread metadata remote connection")?;
let thread_id = row.thread_id;
let archived = row.archived;
+ let last_user_interaction = row.last_user_interaction.to_rfc3339();
self.write(move |conn| {
- let sql = "INSERT INTO sidebar_threads(thread_id, session_id, agent_id, title, updated_at, created_at, folder_paths, folder_paths_order, archived, main_worktree_paths, main_worktree_paths_order, remote_connection) \
- VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12) \
+ let sql = "INSERT INTO sidebar_threads(thread_id, session_id, agent_id, title, updated_at, created_at, folder_paths, folder_paths_order, archived, main_worktree_paths, main_worktree_paths_order, remote_connection, last_user_interaction) \
+ VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13) \
ON CONFLICT(thread_id) DO UPDATE SET \
session_id = excluded.session_id, \
agent_id = excluded.agent_id, \
@@ -1375,7 +1422,8 @@ impl ThreadMetadataDb {
archived = excluded.archived, \
main_worktree_paths = excluded.main_worktree_paths, \
main_worktree_paths_order = excluded.main_worktree_paths_order, \
- remote_connection = excluded.remote_connection";
+ remote_connection = excluded.remote_connection, \
+ last_user_interaction = excluded.last_user_interaction";
let mut stmt = Statement::prepare(conn, sql)?;
let mut i = stmt.bind(&thread_id, 1)?;
i = stmt.bind(&session_id, i)?;
@@ -1388,7 +1436,8 @@ impl ThreadMetadataDb {
i = stmt.bind(&archived, i)?;
i = stmt.bind(&main_worktree_paths, i)?;
i = stmt.bind(&main_worktree_paths_order, i)?;
- stmt.bind(&remote_connection, i)?;
+ i = stmt.bind(&remote_connection, i)?;
+ stmt.bind(&last_user_interaction, i)?;
stmt.exec()
})
.await
@@ -1544,6 +1593,7 @@ impl Column for ThreadMetadata {
Column::column(statement, next)?;
let (remote_connection_json, next): (Option<String>, i32) =
Column::column(statement, next)?;
+ let (last_user_interaction_str, next): (String, i32) = Column::column(statement, next)?;
let agent_id = agent_id
.map(|id| AgentId::new(id))
@@ -1580,6 +1630,9 @@ impl Column for ThreadMetadata {
.transpose()
.context("deserialize thread metadata remote connection")?;
+ let last_user_interaction =
+ DateTime::parse_from_rfc3339(&last_user_interaction_str)?.with_timezone(&Utc);
+
let worktree_paths = WorktreePaths::from_path_lists(main_worktree_paths, folder_paths)
.unwrap_or_else(|_| WorktreePaths::default());
@@ -1599,6 +1652,7 @@ impl Column for ThreadMetadata {
created_at,
worktree_paths,
remote_connection,
+ last_user_interaction,
archived,
},
next,
@@ -1688,6 +1742,7 @@ mod tests {
created_at: Some(updated_at),
worktree_paths: WorktreePaths::from_folder_paths(&folder_paths),
remote_connection: None,
+ last_user_interaction: updated_at,
}
}
@@ -1869,6 +1924,7 @@ mod tests {
created_at: Some(updated_time),
worktree_paths: WorktreePaths::from_folder_paths(&second_paths),
remote_connection: None,
+ last_user_interaction: updated_time,
archived: false,
};
@@ -1952,6 +2008,7 @@ mod tests {
created_at: Some(now - chrono::Duration::seconds(10)),
worktree_paths: WorktreePaths::from_folder_paths(&project_a_paths),
remote_connection: None,
+ last_user_interaction: now - chrono::Duration::seconds(10),
archived: false,
};
@@ -2072,6 +2129,7 @@ mod tests {
created_at: Some(existing_updated_at),
worktree_paths: WorktreePaths::from_folder_paths(&project_paths),
remote_connection: None,
+ last_user_interaction: existing_updated_at,
archived: false,
};
@@ -2745,6 +2803,7 @@ mod tests {
created_at: Some(now),
worktree_paths: linked_worktree_paths.clone(),
remote_connection: None,
+ last_user_interaction: now,
};
let remote_linked_thread = ThreadMetadata {
@@ -2757,6 +2816,7 @@ mod tests {
created_at: Some(now - chrono::Duration::seconds(1)),
worktree_paths: linked_worktree_paths,
remote_connection: Some(remote_a.clone()),
+ last_user_interaction: now - chrono::Duration::seconds(1),
};
cx.update(|cx| {
@@ -354,15 +354,9 @@ pub struct Sidebar {
/// Tracks which sidebar entry is currently active (highlighted).
active_entry: Option<ActiveEntry>,
hovered_thread_index: Option<usize>,
-
- /// Updated only in response to explicit user actions (clicking a
- /// thread, confirming in the thread switcher, etc.) — never from
- /// background data changes. Used to sort the thread switcher popup.
- thread_last_accessed: HashMap<acp::SessionId, DateTime<Utc>>,
- /// Updated when the user presses a key to send or queue a message.
- /// Used for sorting threads in the sidebar and as a secondary sort
- /// key in the thread switcher.
- thread_last_message_sent_or_queued: HashMap<agent_ui::ThreadId, DateTime<Utc>>,
+ /// The last time the user opened/focused each thread in the agent panel.
+ /// Used for ordering the ctrl-tab switcher.
+ last_accessed: HashMap<ThreadId, DateTime<Utc>>,
thread_switcher: Option<Entity<ThreadSwitcher>>,
_thread_switcher_subscriptions: Vec<gpui::Subscription>,
pending_thread_activation: Option<agent_ui::ThreadId>,
@@ -456,8 +450,7 @@ impl Sidebar {
active_entry: None,
hovered_thread_index: None,
- thread_last_accessed: HashMap::new(),
- thread_last_message_sent_or_queued: HashMap::new(),
+ last_accessed: HashMap::default(),
thread_switcher: None,
_thread_switcher_subscriptions: Vec::new(),
pending_thread_activation: None,
@@ -638,7 +631,10 @@ impl Sidebar {
this.update_entries(cx);
}
AgentPanelEvent::MessageSentOrQueued { thread_id } => {
- this.record_thread_message_sent(thread_id);
+ let now = Utc::now();
+ ThreadMetadataStore::global(cx).update(cx, |store, cx| {
+ store.update_last_user_interaction(*thread_id, now, cx);
+ });
this.update_entries(cx);
}
},
@@ -888,7 +884,6 @@ impl Sidebar {
let mut entries = Vec::new();
let mut notified_threads = previous.notified_threads;
- let mut current_session_ids: HashSet<acp::SessionId> = HashSet::new();
let mut current_thread_ids: HashSet<agent_ui::ThreadId> = HashSet::new();
let mut project_header_indices: Vec<usize> = Vec::new();
let mut seen_thread_ids: HashSet<agent_ui::ThreadId> = HashSet::new();
@@ -1130,9 +1125,9 @@ impl Sidebar {
}
threads.sort_by(|a, b| {
- let a_time = self.display_time(&a.metadata);
- let b_time = self.display_time(&b.metadata);
- b_time.cmp(&a_time)
+ b.metadata
+ .last_user_interaction
+ .cmp(&a.metadata.last_user_interaction)
});
} else {
for info in live_infos {
@@ -1205,9 +1200,6 @@ impl Sidebar {
});
for thread in matched_threads {
- if let Some(sid) = thread.metadata.session_id.clone() {
- current_session_ids.insert(sid);
- }
current_thread_ids.insert(thread.metadata.thread_id);
entries.push(thread.into());
}
@@ -1228,9 +1220,6 @@ impl Sidebar {
}
for thread in threads {
- if let Some(sid) = &thread.metadata.session_id {
- current_session_ids.insert(sid.clone());
- }
current_thread_ids.insert(thread.metadata.thread_id);
entries.push(thread.into());
}
@@ -1239,9 +1228,7 @@ impl Sidebar {
notified_threads.retain(|id| current_thread_ids.contains(id));
- self.thread_last_accessed
- .retain(|id, _| current_session_ids.contains(id));
- self.thread_last_message_sent_or_queued
+ self.last_accessed
.retain(|id, _| current_thread_ids.contains(id));
self.contents = SidebarContents {
@@ -2217,7 +2204,7 @@ impl Sidebar {
session_id: metadata.session_id.clone(),
workspace: workspace.clone(),
});
- self.record_thread_access(&metadata.session_id);
+ self.record_thread_accessed(metadata.thread_id);
if metadata.session_id.is_some() {
self.pending_thread_activation = Some(metadata.thread_id);
@@ -2286,7 +2273,7 @@ impl Sidebar {
session_id: target_session_id.clone(),
workspace: workspace_for_entry.clone(),
});
- sidebar.record_thread_access(&target_session_id);
+ sidebar.record_thread_accessed(metadata_thread_id);
sidebar.update_entries(cx);
});
}
@@ -3303,22 +3290,12 @@ impl Sidebar {
}
}
- fn record_thread_access(&mut self, session_id: &Option<acp::SessionId>) {
- if let Some(sid) = session_id {
- self.thread_last_accessed.insert(sid.clone(), Utc::now());
- }
- }
-
- fn record_thread_message_sent(&mut self, thread_id: &agent_ui::ThreadId) {
- self.thread_last_message_sent_or_queued
- .insert(*thread_id, Utc::now());
+ fn record_thread_accessed(&mut self, thread_id: ThreadId) {
+ self.last_accessed.insert(thread_id, Utc::now());
}
fn display_time(&self, metadata: &ThreadMetadata) -> DateTime<Utc> {
- self.thread_last_message_sent_or_queued
- .get(&metadata.thread_id)
- .copied()
- .unwrap_or(metadata.updated_at)
+ metadata.last_user_interaction
}
fn mru_threads_for_switcher(&self, cx: &App) -> Vec<ThreadSwitcherEntry> {
@@ -3381,28 +3358,16 @@ impl Sidebar {
.collect();
entries.sort_by(|a, b| {
- let a_accessed = self.thread_last_accessed.get(&a.session_id);
- let b_accessed = self.thread_last_accessed.get(&b.session_id);
-
+ let a_accessed = self.last_accessed.get(&a.metadata.thread_id);
+ let b_accessed = self.last_accessed.get(&b.metadata.thread_id);
match (a_accessed, b_accessed) {
(Some(a_time), Some(b_time)) => b_time.cmp(a_time),
(Some(_), None) => std::cmp::Ordering::Less,
(None, Some(_)) => std::cmp::Ordering::Greater,
- (None, None) => {
- let a_sent = self
- .thread_last_message_sent_or_queued
- .get(&a.metadata.thread_id);
- let b_sent = self
- .thread_last_message_sent_or_queued
- .get(&b.metadata.thread_id);
-
- match (a_sent, b_sent) {
- (Some(a_time), Some(b_time)) => b_time.cmp(a_time),
- (Some(_), None) => std::cmp::Ordering::Less,
- (None, Some(_)) => std::cmp::Ordering::Greater,
- (None, None) => b.metadata.updated_at.cmp(&a.metadata.updated_at),
- }
- }
+ (None, None) => b
+ .metadata
+ .last_user_interaction
+ .cmp(&a.metadata.last_user_interaction),
}
});
@@ -3500,7 +3465,7 @@ impl Sidebar {
mw.retain_active_workspace(cx);
});
}
- this.record_thread_access(&metadata.session_id);
+ this.record_thread_accessed(metadata.thread_id);
this.active_entry = Some(ActiveEntry {
thread_id: metadata.thread_id,
session_id: metadata.session_id.clone(),
@@ -271,6 +271,7 @@ fn save_thread_metadata(
updated_at,
created_at,
worktree_paths,
+ last_user_interaction: updated_at,
archived: false,
remote_connection,
};
@@ -305,6 +306,7 @@ fn save_thread_metadata_with_main_paths(
updated_at,
created_at: None,
worktree_paths: WorktreePaths::from_path_lists(main_worktree_paths, folder_paths).unwrap(),
+ last_user_interaction: updated_at,
archived: false,
remote_connection: None,
};
@@ -770,6 +772,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
title: Some("Completed thread".into()),
updated_at: Utc::now(),
created_at: Some(Utc::now()),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -794,6 +797,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
title: Some("Running thread".into()),
updated_at: Utc::now(),
created_at: Some(Utc::now()),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -818,6 +822,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
title: Some("Error thread".into()),
updated_at: Utc::now(),
created_at: Some(Utc::now()),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -843,6 +848,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
title: Some("Waiting thread".into()),
updated_at: Utc::now(),
created_at: Some(Utc::now()),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -868,6 +874,7 @@ async fn test_visible_entries_as_strings(cx: &mut TestAppContext) {
title: Some("Notified thread".into()),
updated_at: Utc::now(),
created_at: Some(Utc::now()),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -3917,6 +3924,7 @@ async fn test_activate_archived_thread_with_saved_paths_activates_matching_works
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[PathBuf::from(
"/project-b",
)])),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -3985,6 +3993,7 @@ async fn test_activate_archived_thread_cwd_fallback_with_matching_workspace(
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[
std::path::PathBuf::from("/project-b"),
])),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -4049,6 +4058,7 @@ async fn test_activate_archived_thread_no_paths_no_cwd_uses_active_workspace(
updated_at: Utc::now(),
created_at: None,
worktree_paths: WorktreePaths::default(),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -4105,6 +4115,7 @@ async fn test_activate_archived_thread_saved_paths_opens_new_workspace(cx: &mut
updated_at: Utc::now(),
created_at: None,
worktree_paths: WorktreePaths::from_folder_paths(&path_list_b),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -4162,6 +4173,7 @@ async fn test_activate_archived_thread_reuses_workspace_in_another_window(cx: &m
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[PathBuf::from(
"/project-b",
)])),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -4242,6 +4254,7 @@ async fn test_activate_archived_thread_reuses_workspace_in_another_window_with_t
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[PathBuf::from(
"/project-b",
)])),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -4325,6 +4338,7 @@ async fn test_activate_archived_thread_prefers_current_window_for_matching_paths
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[PathBuf::from(
"/project-a",
)])),
+ last_user_interaction: Utc::now(),
archived: false,
remote_connection: None,
},
@@ -5250,6 +5264,8 @@ async fn test_archive_last_worktree_thread_not_blocked_by_remote_thread_at_same_
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[PathBuf::from(
"/wt-feature-a",
)])),
+ last_user_interaction: chrono::TimeZone::with_ymd_and_hms(&Utc, 2024, 1, 1, 0, 0, 0)
+ .unwrap(),
archived: false,
remote_connection: Some(remote_host),
};
@@ -5554,8 +5570,6 @@ async fn test_thread_switcher_ordering(cx: &mut TestAppContext) {
cx.run_until_parked();
assert_eq!(switcher_selected_id(&sidebar, cx), session_id_c);
- assert!(sidebar.update(cx, |sidebar, _cx| sidebar.thread_last_accessed.is_empty()));
-
// Confirm on Thread C.
sidebar.update_in(cx, |sidebar, window, cx| {
let switcher = sidebar.thread_switcher.as_ref().unwrap();
@@ -5572,14 +5586,7 @@ async fn test_thread_switcher_ordering(cx: &mut TestAppContext) {
);
});
- sidebar.update(cx, |sidebar, _cx| {
- let last_accessed = sidebar
- .thread_last_accessed
- .keys()
- .cloned()
- .collect::<Vec<_>>();
- assert_eq!(last_accessed.len(), 1);
- assert!(last_accessed.contains(&session_id_c));
+ sidebar.read_with(cx, |sidebar, _cx| {
assert!(
is_active_session(&sidebar, &session_id_c),
"active_entry should be Thread({session_id_c:?})"
@@ -5608,15 +5615,7 @@ async fn test_thread_switcher_ordering(cx: &mut TestAppContext) {
});
cx.run_until_parked();
- sidebar.update(cx, |sidebar, _cx| {
- let last_accessed = sidebar
- .thread_last_accessed
- .keys()
- .cloned()
- .collect::<Vec<_>>();
- assert_eq!(last_accessed.len(), 2);
- assert!(last_accessed.contains(&session_id_c));
- assert!(last_accessed.contains(&session_id_a));
+ sidebar.read_with(cx, |sidebar, _cx| {
assert!(
is_active_session(&sidebar, &session_id_a),
"active_entry should be Thread({session_id_a:?})"
@@ -5651,16 +5650,7 @@ async fn test_thread_switcher_ordering(cx: &mut TestAppContext) {
});
cx.run_until_parked();
- sidebar.update(cx, |sidebar, _cx| {
- let last_accessed = sidebar
- .thread_last_accessed
- .keys()
- .cloned()
- .collect::<Vec<_>>();
- assert_eq!(last_accessed.len(), 3);
- assert!(last_accessed.contains(&session_id_c));
- assert!(last_accessed.contains(&session_id_a));
- assert!(last_accessed.contains(&session_id_b));
+ sidebar.read_with(cx, |sidebar, _cx| {
assert!(
is_active_session(&sidebar, &session_id_b),
"active_entry should be Thread({session_id_b:?})"
@@ -6013,6 +6003,7 @@ async fn test_unarchive_first_thread_in_group_does_not_create_spurious_draft(
updated_at: Utc::now(),
created_at: None,
worktree_paths: WorktreePaths::from_folder_paths(&path_list_b),
+ last_user_interaction: Utc::now(),
archived: true,
remote_connection: None,
},
@@ -6105,6 +6096,7 @@ async fn test_unarchive_into_new_workspace_does_not_create_duplicate_real_thread
updated_at: Utc::now(),
created_at: None,
worktree_paths: WorktreePaths::from_folder_paths(&path_list_b),
+ last_user_interaction: Utc::now(),
archived: true,
remote_connection: None,
},
@@ -6332,6 +6324,7 @@ async fn test_unarchive_into_inactive_existing_workspace_does_not_leave_active_d
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[
PathBuf::from("/project-b"),
])),
+ last_user_interaction: Utc::now(),
archived: true,
remote_connection: None,
},
@@ -7176,6 +7169,7 @@ async fn test_unarchive_linked_worktree_thread_into_project_group_shows_only_res
folder_paths.clone(),
)
.expect("main and folder paths should be well-formed"),
+ last_user_interaction: Utc::now(),
archived: true,
remote_connection: None,
},
@@ -7835,6 +7829,8 @@ async fn test_legacy_thread_with_canonical_path_opens_main_repo_workspace(cx: &m
worktree_paths: WorktreePaths::from_folder_paths(&PathList::new(&[PathBuf::from(
"/project",
)])),
+ last_user_interaction: chrono::TimeZone::with_ymd_and_hms(&Utc, 2024, 1, 1, 0, 0, 0)
+ .unwrap(),
archived: false,
remote_connection: None,
};
@@ -8817,6 +8813,7 @@ mod property_test {
updated_at,
created_at: None,
worktree_paths: WorktreePaths::from_path_lists(main_worktree_paths, path_list).unwrap(),
+ last_user_interaction: updated_at,
archived: false,
remote_connection: None,
};
@@ -9719,6 +9716,8 @@ async fn test_remote_project_integration_does_not_briefly_render_as_separate_pro
PathList::new(&[PathBuf::from("/project-wt-1")]),
)
.unwrap(),
+ last_user_interaction: chrono::TimeZone::with_ymd_and_hms(&Utc, 2024, 1, 1, 0, 0, 1)
+ .unwrap(),
archived: false,
remote_connection,
};