Merge branch 'main' into following-tests

This commit is contained in:
Conrad Irwin 2024-01-05 16:14:12 -07:00
commit 204ef451d0
224 changed files with 12664 additions and 23906 deletions

View file

@ -672,9 +672,13 @@ impl Render for PanelButtons {
&& panel.position_is_valid(position, cx)
{
let panel = panel.clone();
menu = menu.entry(position.to_label(), None, move |cx| {
panel.set_position(position, cx);
})
menu = menu.entry(
format!("Dock {}", position.to_label()),
None,
move |cx| {
panel.set_position(position, cx);
},
)
}
}
menu

View file

@ -246,7 +246,15 @@ impl Member {
.size_full()
.child(pane.clone())
.when_some(leader_border, |this, color| {
this.border_2().border_color(color)
this.child(
div()
.absolute()
.size_full()
.left_0()
.top_0()
.border_2()
.border_color(color),
)
})
.when_some(leader_status_box, |this, status_box| {
this.child(

View file

@ -6,7 +6,12 @@ use std::path::Path;
use anyhow::{anyhow, bail, Context, Result};
use db::{define_connection, query, sqlez::connection::Connection, sqlez_macros::sql};
use gpui::{Axis, WindowBounds};
use gpui::{point, size, Axis, Bounds, WindowBounds};
use sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use util::{unzip_option, ResultExt};
use uuid::Uuid;
@ -20,6 +25,121 @@ use model::{
use self::model::DockStructure;
#[derive(Copy, Clone, Debug, PartialEq)]
pub(crate) struct SerializedAxis(pub(crate) gpui::Axis);
impl sqlez::bindable::StaticColumnCount for SerializedAxis {}
impl sqlez::bindable::Bind for SerializedAxis {
fn bind(
&self,
statement: &sqlez::statement::Statement,
start_index: i32,
) -> anyhow::Result<i32> {
match self.0 {
gpui::Axis::Horizontal => "Horizontal",
gpui::Axis::Vertical => "Vertical",
}
.bind(statement, start_index)
}
}
impl sqlez::bindable::Column for SerializedAxis {
fn column(
statement: &mut sqlez::statement::Statement,
start_index: i32,
) -> anyhow::Result<(Self, i32)> {
String::column(statement, start_index).and_then(|(axis_text, next_index)| {
Ok((
match axis_text.as_str() {
"Horizontal" => Self(Axis::Horizontal),
"Vertical" => Self(Axis::Vertical),
_ => anyhow::bail!("Stored serialized item kind is incorrect"),
},
next_index,
))
})
}
}
#[derive(Clone, Debug, PartialEq)]
pub(crate) struct SerializedWindowsBounds(pub(crate) WindowBounds);
impl StaticColumnCount for SerializedWindowsBounds {
fn column_count() -> usize {
5
}
}
impl Bind for SerializedWindowsBounds {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let (region, next_index) = match self.0 {
WindowBounds::Fullscreen => {
let next_index = statement.bind(&"Fullscreen", start_index)?;
(None, next_index)
}
WindowBounds::Maximized => {
let next_index = statement.bind(&"Maximized", start_index)?;
(None, next_index)
}
WindowBounds::Fixed(region) => {
let next_index = statement.bind(&"Fixed", start_index)?;
(Some(region), next_index)
}
};
statement.bind(
&region.map(|region| {
(
SerializedGlobalPixels(region.origin.x),
SerializedGlobalPixels(region.origin.y),
SerializedGlobalPixels(region.size.width),
SerializedGlobalPixels(region.size.height),
)
}),
next_index,
)
}
}
impl Column for SerializedWindowsBounds {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (window_state, next_index) = String::column(statement, start_index)?;
let bounds = match window_state.as_str() {
"Fullscreen" => SerializedWindowsBounds(WindowBounds::Fullscreen),
"Maximized" => SerializedWindowsBounds(WindowBounds::Maximized),
"Fixed" => {
let ((x, y, width, height), _) = Column::column(statement, next_index)?;
let x: f64 = x;
let y: f64 = y;
let width: f64 = width;
let height: f64 = height;
SerializedWindowsBounds(WindowBounds::Fixed(Bounds {
origin: point(x.into(), y.into()),
size: size(width.into(), height.into()),
}))
}
_ => bail!("Window State did not have a valid string"),
};
Ok((bounds, next_index + 4))
}
}
#[derive(Clone, Debug, PartialEq)]
struct SerializedGlobalPixels(gpui::GlobalPixels);
impl sqlez::bindable::StaticColumnCount for SerializedGlobalPixels {}
impl sqlez::bindable::Bind for SerializedGlobalPixels {
fn bind(
&self,
statement: &sqlez::statement::Statement,
start_index: i32,
) -> anyhow::Result<i32> {
let this: f64 = self.0.into();
let this: f32 = this as _;
this.bind(statement, start_index)
}
}
define_connection! {
// Current schema shape using pseudo-rust syntax:
//
@ -181,7 +301,7 @@ impl WorkspaceDb {
/// Returns a serialized workspace for the given worktree_roots. If the passed array
/// is empty, the most recent workspace is returned instead. If no workspace for the
/// passed roots is stored, returns none.
pub fn workspace_for_roots<P: AsRef<Path>>(
pub(crate) fn workspace_for_roots<P: AsRef<Path>>(
&self,
worktree_roots: &[P],
) -> Option<SerializedWorkspace> {
@ -192,7 +312,7 @@ impl WorkspaceDb {
let (workspace_id, workspace_location, bounds, display, docks): (
WorkspaceId,
WorkspaceLocation,
Option<WindowBounds>,
Option<SerializedWindowsBounds>,
Option<Uuid>,
DockStructure,
) = self
@ -230,7 +350,7 @@ impl WorkspaceDb {
.get_center_pane_group(workspace_id)
.context("Getting center group")
.log_err()?,
bounds,
bounds: bounds.map(|bounds| bounds.0),
display,
docks,
})
@ -238,7 +358,7 @@ impl WorkspaceDb {
/// Saves a workspace using the worktree roots. Will garbage collect any workspaces
/// that used this workspace previously
pub async fn save_workspace(&self, workspace: SerializedWorkspace) {
pub(crate) async fn save_workspace(&self, workspace: SerializedWorkspace) {
self.write(move |conn| {
conn.with_savepoint("update_worktrees", || {
// Clear out panes and pane_groups
@ -367,7 +487,7 @@ impl WorkspaceDb {
type GroupKey = (Option<GroupId>, WorkspaceId);
type GroupOrPane = (
Option<GroupId>,
Option<Axis>,
Option<SerializedAxis>,
Option<PaneId>,
Option<bool>,
Option<String>,
@ -536,7 +656,7 @@ impl WorkspaceDb {
}
query! {
pub async fn set_window_bounds(workspace_id: WorkspaceId, bounds: WindowBounds, display: Uuid) -> Result<()> {
pub(crate) async fn set_window_bounds(workspace_id: WorkspaceId, bounds: SerializedWindowsBounds, display: Uuid) -> Result<()> {
UPDATE workspaces
SET window_state = ?2,
window_x = ?3,
@ -683,7 +803,7 @@ mod tests {
fn group(axis: Axis, children: Vec<SerializedPaneGroup>) -> SerializedPaneGroup {
SerializedPaneGroup::Group {
axis,
axis: SerializedAxis(axis),
flexes: None,
children,
}

View file

@ -1,3 +1,4 @@
use super::SerializedAxis;
use crate::{item::ItemHandle, ItemDeserializers, Member, Pane, PaneAxis, Workspace, WorkspaceId};
use anyhow::{Context, Result};
use async_recursion::async_recursion;
@ -5,7 +6,7 @@ use db::sqlez::{
bindable::{Bind, Column, StaticColumnCount},
statement::Statement,
};
use gpui::{AsyncWindowContext, Axis, Model, Task, View, WeakView, WindowBounds};
use gpui::{AsyncWindowContext, Model, Task, View, WeakView, WindowBounds};
use project::Project;
use std::{
path::{Path, PathBuf},
@ -54,13 +55,13 @@ impl Column for WorkspaceLocation {
}
#[derive(Debug, PartialEq, Clone)]
pub struct SerializedWorkspace {
pub id: WorkspaceId,
pub location: WorkspaceLocation,
pub center_group: SerializedPaneGroup,
pub bounds: Option<WindowBounds>,
pub display: Option<Uuid>,
pub docks: DockStructure,
pub(crate) struct SerializedWorkspace {
pub(crate) id: WorkspaceId,
pub(crate) location: WorkspaceLocation,
pub(crate) center_group: SerializedPaneGroup,
pub(crate) bounds: Option<WindowBounds>,
pub(crate) display: Option<Uuid>,
pub(crate) docks: DockStructure,
}
#[derive(Debug, PartialEq, Clone, Default)]
@ -126,9 +127,9 @@ impl Bind for DockData {
}
#[derive(Debug, PartialEq, Clone)]
pub enum SerializedPaneGroup {
pub(crate) enum SerializedPaneGroup {
Group {
axis: Axis,
axis: SerializedAxis,
flexes: Option<Vec<f32>>,
children: Vec<SerializedPaneGroup>,
},
@ -183,7 +184,7 @@ impl SerializedPaneGroup {
}
Some((
Member::Axis(PaneAxis::load(axis, members, flexes)),
Member::Axis(PaneAxis::load(axis.0, members, flexes)),
current_active_pane,
items,
))

View file

@ -42,9 +42,9 @@ use node_runtime::NodeRuntime;
use notifications::{simple_message_notification::MessageNotification, NotificationHandle};
pub use pane::*;
pub use pane_group::*;
use persistence::DB;
use persistence::{model::SerializedWorkspace, SerializedWindowsBounds, DB};
pub use persistence::{
model::{ItemId, SerializedWorkspace, WorkspaceLocation},
model::{ItemId, WorkspaceLocation},
WorkspaceDb, DB as WORKSPACE_DB,
};
use postage::stream::Stream;
@ -70,8 +70,9 @@ use util::ResultExt;
use uuid::Uuid;
pub use workspace_settings::{AutosaveSetting, WorkspaceSettings};
use crate::persistence::model::{
DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup,
use crate::persistence::{
model::{DockData, DockStructure, SerializedItem, SerializedPane, SerializedPaneGroup},
SerializedAxis,
};
lazy_static! {
@ -107,6 +108,7 @@ actions!(
NewCenterTerminal,
ToggleTerminalFocus,
NewSearch,
DeploySearch,
Feedback,
Restart,
Welcome,
@ -624,7 +626,11 @@ impl Workspace {
if let Some(display_uuid) = display.uuid().log_err() {
cx.background_executor()
.spawn(DB.set_window_bounds(workspace_id, bounds, display_uuid))
.spawn(DB.set_window_bounds(
workspace_id,
SerializedWindowsBounds(bounds),
display_uuid,
))
.detach_and_log_err(cx);
}
}
@ -1186,7 +1192,7 @@ impl Workspace {
mut save_intent: SaveIntent,
cx: &mut ViewContext<Self>,
) -> Task<Result<bool>> {
if self.project.read(cx).is_read_only() {
if self.project.read(cx).is_disconnected() {
return Task::ready(Ok(true));
}
let dirty_items = self
@ -2509,7 +2515,7 @@ impl Workspace {
}
fn update_window_edited(&mut self, cx: &mut ViewContext<Self>) {
let is_edited = !self.project.read(cx).is_read_only()
let is_edited = !self.project.read(cx).is_disconnected()
&& self
.items(cx)
.any(|item| item.has_conflict(cx) || item.is_dirty(cx));
@ -2988,7 +2994,7 @@ impl Workspace {
flexes,
bounding_boxes: _,
}) => SerializedPaneGroup::Group {
axis: *axis,
axis: SerializedAxis(*axis),
children: members
.iter()
.map(|member| build_serialized_pane_group(member, cx))
@ -3265,6 +3271,7 @@ impl Workspace {
let user_store = project.read(cx).user_store();
let workspace_store = cx.new_model(|cx| WorkspaceStore::new(client.clone(), cx));
cx.activate_window();
let app_state = Arc::new(AppState {
languages: project.read(cx).languages().clone(),
workspace_store,
@ -3633,7 +3640,7 @@ impl Render for Workspace {
})),
)
.child(self.status_bar.clone())
.children(if self.project.read(cx).is_read_only() {
.children(if self.project.read(cx).is_disconnected() {
Some(DisconnectedOverlay)
} else {
None
@ -4763,8 +4770,7 @@ mod tests {
});
// Deactivating the window saves the file.
cx.simulate_deactivation();
cx.executor().run_until_parked();
cx.deactivate_window();
item.update(cx, |item, _| assert_eq!(item.save_count, 1));
// Autosave on focus change.
@ -4784,14 +4790,13 @@ mod tests {
item.update(cx, |item, _| assert_eq!(item.save_count, 2));
// Deactivating the window still saves the file.
cx.simulate_activation();
cx.update(|cx| cx.activate_window());
item.update(cx, |item, cx| {
cx.focus_self();
item.is_dirty = true;
});
cx.simulate_deactivation();
cx.deactivate_window();
cx.executor().run_until_parked();
item.update(cx, |item, _| assert_eq!(item.save_count, 3));
// Autosave after delay.