Track space sidebar width
This commit is contained in:
@@ -103,7 +103,8 @@ fn render_sidebar_tabs_header(snapshot: &BrowserSnapshot, active_space: &Space)
|
|||||||
.text_color(rgb(colors::MUTED))
|
.text_color(rgb(colors::MUTED))
|
||||||
.child(IconName::LayoutDashboard)
|
.child(IconName::LayoutDashboard)
|
||||||
.child(format!(
|
.child(format!(
|
||||||
"{} / {}",
|
"{} / {} / {}",
|
||||||
|
sidebar_width_label(active_space),
|
||||||
archive_policy_label(active_space.archive_policy()),
|
archive_policy_label(active_space.archive_policy()),
|
||||||
snapshot.favorite_limit.label()
|
snapshot.favorite_limit.label()
|
||||||
)),
|
)),
|
||||||
@@ -127,10 +128,54 @@ fn render_sidebar_tabs_settings(
|
|||||||
.flex_col()
|
.flex_col()
|
||||||
.gap_4()
|
.gap_4()
|
||||||
.child(render_archive_policy_section(active_space, cx))
|
.child(render_archive_policy_section(active_space, cx))
|
||||||
|
.child(render_sidebar_width_section(active_space))
|
||||||
.child(render_favorite_limit_section(snapshot.favorite_limit, cx))
|
.child(render_favorite_limit_section(snapshot.favorite_limit, cx))
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn render_sidebar_width_section(active_space: &Space) -> AnyElement {
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_3()
|
||||||
|
.pt_4()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.flex()
|
||||||
|
.items_center()
|
||||||
|
.justify_between()
|
||||||
|
.gap_4()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.min_w_0()
|
||||||
|
.flex()
|
||||||
|
.flex_col()
|
||||||
|
.gap_1()
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_sm()
|
||||||
|
.font_semibold()
|
||||||
|
.text_color(rgb(colors::INK))
|
||||||
|
.child("Sidebar Width"),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child("Current Space sidebar width."),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.child(
|
||||||
|
div()
|
||||||
|
.text_xs()
|
||||||
|
.font_semibold()
|
||||||
|
.text_color(rgb(colors::MUTED))
|
||||||
|
.child(sidebar_width_label(active_space)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.into_any_element()
|
||||||
|
}
|
||||||
|
|
||||||
fn render_archive_policy_section(active_space: &Space, cx: &mut Context<ElyShell>) -> AnyElement {
|
fn render_archive_policy_section(active_space: &Space, cx: &mut Context<ElyShell>) -> AnyElement {
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
@@ -233,6 +278,10 @@ fn render_favorite_limit_section(
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn sidebar_width_label(space: &Space) -> String {
|
||||||
|
format!("{} px", space.sidebar_width_px())
|
||||||
|
}
|
||||||
|
|
||||||
fn render_archive_policy_option(
|
fn render_archive_policy_option(
|
||||||
index: usize,
|
index: usize,
|
||||||
option: &'static ArchivePolicyOption,
|
option: &'static ArchivePolicyOption,
|
||||||
|
|||||||
@@ -32,6 +32,11 @@ impl ElyShell {
|
|||||||
active_tab: BrowserTab,
|
active_tab: BrowserTab,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> AnyElement {
|
) -> AnyElement {
|
||||||
|
let sidebar_width = match active_sidebar_width(&snapshot) {
|
||||||
|
Ok(sidebar_width) => sidebar_width,
|
||||||
|
Err(message) => return render_error(message),
|
||||||
|
};
|
||||||
|
|
||||||
div()
|
div()
|
||||||
.size_full()
|
.size_full()
|
||||||
.track_focus(&self.focus_handle)
|
.track_focus(&self.focus_handle)
|
||||||
@@ -53,13 +58,13 @@ impl ElyShell {
|
|||||||
.text_color(rgb(ELY_THEME.ink))
|
.text_color(rgb(ELY_THEME.ink))
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
.child(self.render_command_bar(&snapshot, &active_tab, cx))
|
.child(self.render_command_bar(&snapshot, &active_tab, sidebar_width, cx))
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
.overflow_hidden()
|
.overflow_hidden()
|
||||||
.child(self.render_sidebar(&snapshot, cx))
|
.child(self.render_sidebar(&snapshot, sidebar_width, cx))
|
||||||
.child(self.render_content_area(&snapshot, &active_tab, cx)),
|
.child(self.render_content_area(&snapshot, &active_tab, cx)),
|
||||||
)
|
)
|
||||||
.into_any_element()
|
.into_any_element()
|
||||||
@@ -69,6 +74,7 @@ impl ElyShell {
|
|||||||
&mut self,
|
&mut self,
|
||||||
snapshot: &BrowserSnapshot,
|
snapshot: &BrowserSnapshot,
|
||||||
active_tab: &BrowserTab,
|
active_tab: &BrowserTab,
|
||||||
|
sidebar_width: f32,
|
||||||
cx: &mut Context<Self>,
|
cx: &mut Context<Self>,
|
||||||
) -> AnyElement {
|
) -> AnyElement {
|
||||||
let favorite_icon =
|
let favorite_icon =
|
||||||
@@ -87,7 +93,7 @@ impl ElyShell {
|
|||||||
.border_color(rgb(colors::HAIRLINE))
|
.border_color(rgb(colors::HAIRLINE))
|
||||||
.child(
|
.child(
|
||||||
div()
|
div()
|
||||||
.w(px(spacing::SIDEBAR_WIDTH - spacing::XL))
|
.w(px(sidebar_width - spacing::XL))
|
||||||
.flex()
|
.flex()
|
||||||
.items_center()
|
.items_center()
|
||||||
.gap_2()
|
.gap_2()
|
||||||
@@ -139,9 +145,14 @@ impl ElyShell {
|
|||||||
.into_any_element()
|
.into_any_element()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_sidebar(&mut self, snapshot: &BrowserSnapshot, cx: &mut Context<Self>) -> AnyElement {
|
fn render_sidebar(
|
||||||
|
&mut self,
|
||||||
|
snapshot: &BrowserSnapshot,
|
||||||
|
sidebar_width: f32,
|
||||||
|
cx: &mut Context<Self>,
|
||||||
|
) -> AnyElement {
|
||||||
div()
|
div()
|
||||||
.w(px(spacing::SIDEBAR_WIDTH))
|
.w(px(sidebar_width))
|
||||||
.h_full()
|
.h_full()
|
||||||
.flex()
|
.flex()
|
||||||
.flex_col()
|
.flex_col()
|
||||||
@@ -420,6 +431,16 @@ fn section_label(label: &'static str) -> impl IntoElement {
|
|||||||
div().text_xs().font_semibold().text_color(rgb(colors::MUTED)).child(label)
|
div().text_xs().font_semibold().text_color(rgb(colors::MUTED)).child(label)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn active_sidebar_width(snapshot: &BrowserSnapshot) -> Result<f32, String> {
|
||||||
|
let Some(active_space) =
|
||||||
|
snapshot.spaces.iter().find(|space| space.id() == &snapshot.active_space_id)
|
||||||
|
else {
|
||||||
|
return Err("Active Space is unavailable.".to_string());
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(f32::from(active_space.sidebar_width_px()))
|
||||||
|
}
|
||||||
|
|
||||||
fn archive_source_label(source: &ArchiveSource) -> &'static str {
|
fn archive_source_label(source: &ArchiveSource) -> &'static str {
|
||||||
match source {
|
match source {
|
||||||
ArchiveSource::ManualClose => "Closed",
|
ArchiveSource::ManualClose => "Closed",
|
||||||
|
|||||||
@@ -252,6 +252,20 @@ impl BrowserCore {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_space_sidebar_width(
|
||||||
|
&mut self,
|
||||||
|
space_id: &SpaceId,
|
||||||
|
sidebar_width_px: u16,
|
||||||
|
) -> Result<(), CoreError> {
|
||||||
|
let space = self
|
||||||
|
.spaces
|
||||||
|
.iter_mut()
|
||||||
|
.find(|space| space.id() == space_id)
|
||||||
|
.ok_or_else(|| CoreError::SpaceNotFound { id: space_id.clone() })?;
|
||||||
|
space.set_sidebar_width_px(sidebar_width_px);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_search_engine(&mut self, search_engine: SearchEngine) {
|
pub fn set_search_engine(&mut self, search_engine: SearchEngine) {
|
||||||
self.search_engine = search_engine;
|
self.search_engine = search_engine;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use ely_browser_core::{BrowserCore, CoreError, InitialBrowserConfig};
|
use ely_browser_core::{BrowserCore, CoreError, InitialBrowserConfig};
|
||||||
use ely_domain::{ArchivePolicy, ProfileId, ProfileKind};
|
use ely_domain::{ArchivePolicy, DEFAULT_SIDEBAR_WIDTH_PX, ProfileId, ProfileKind};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn created_space_binds_current_profile_as_default() -> Result<(), Box<dyn Error>> {
|
fn created_space_binds_current_profile_as_default() -> Result<(), Box<dyn Error>> {
|
||||||
@@ -36,6 +36,21 @@ fn created_space_records_creation_timestamps() -> Result<(), Box<dyn Error>> {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn created_space_uses_default_sidebar_width() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
let research_space_id = core.create_space("Research", "R", 0x9fc9a2)?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
let Some(research_space) =
|
||||||
|
snapshot.spaces.iter().find(|space| space.id() == &research_space_id)
|
||||||
|
else {
|
||||||
|
return Err("missing research space".into());
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(research_space.sidebar_width_px(), DEFAULT_SIDEBAR_WIDTH_PX);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn space_default_profile_updates_with_profile_validation() -> Result<(), Box<dyn Error>> {
|
fn space_default_profile_updates_with_profile_validation() -> Result<(), Box<dyn Error>> {
|
||||||
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
@@ -73,8 +88,27 @@ fn space_settings_refresh_updated_at() -> Result<(), Box<dyn Error>> {
|
|||||||
core.set_space_default_profile(&work_space_id, &research_profile_id)?;
|
core.set_space_default_profile(&work_space_id, &research_profile_id)?;
|
||||||
let after_profile_update = active_space_updated_at(&core, &work_space_id)?;
|
let after_profile_update = active_space_updated_at(&core, &work_space_id)?;
|
||||||
|
|
||||||
|
core.set_space_sidebar_width(&work_space_id, 320)?;
|
||||||
|
let after_sidebar_update = active_space_updated_at(&core, &work_space_id)?;
|
||||||
|
|
||||||
assert!(after_archive_update > before_update);
|
assert!(after_archive_update > before_update);
|
||||||
assert!(after_profile_update > after_archive_update);
|
assert!(after_profile_update > after_archive_update);
|
||||||
|
assert!(after_sidebar_update > after_profile_update);
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn space_sidebar_width_updates_selected_space() -> Result<(), Box<dyn Error>> {
|
||||||
|
let mut core = BrowserCore::new(InitialBrowserConfig::ely_defaults()?)?;
|
||||||
|
let work_space_id = core.snapshot()?.active_space_id;
|
||||||
|
|
||||||
|
core.set_space_sidebar_width(&work_space_id, 320)?;
|
||||||
|
let snapshot = core.snapshot()?;
|
||||||
|
let Some(work_space) = snapshot.spaces.iter().find(|space| space.id() == &work_space_id) else {
|
||||||
|
return Err("missing work space".into());
|
||||||
|
};
|
||||||
|
|
||||||
|
assert_eq!(work_space.sidebar_width_px(), 320);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ pub use site_permission::{
|
|||||||
SiteOrigin, SitePermissionAuditAction, SitePermissionAuditEvent, SitePermissionDecision,
|
SiteOrigin, SitePermissionAuditAction, SitePermissionAuditEvent, SitePermissionDecision,
|
||||||
SitePermissionEntry, SitePermissionFeature,
|
SitePermissionEntry, SitePermissionFeature,
|
||||||
};
|
};
|
||||||
pub use space::{ArchivePolicy, Space};
|
pub use space::{ArchivePolicy, DEFAULT_SIDEBAR_WIDTH_PX, Space};
|
||||||
pub use split::{MAX_SPLIT_PANES, SplitAxis, SplitLayout, SplitPane};
|
pub use split::{MAX_SPLIT_PANES, SplitAxis, SplitLayout, SplitPane};
|
||||||
pub use sync::{
|
pub use sync::{
|
||||||
SyncConnectionState, SyncObjectKind, SyncObjectPolicy, SyncObjectState, SyncObjectStatus,
|
SyncConnectionState, SyncObjectKind, SyncObjectPolicy, SyncObjectState, SyncObjectStatus,
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ use std::time::{Duration, SystemTime};
|
|||||||
|
|
||||||
use crate::{ProfileId, SpaceId};
|
use crate::{ProfileId, SpaceId};
|
||||||
|
|
||||||
|
pub const DEFAULT_SIDEBAR_WIDTH_PX: u16 = 280;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum ArchivePolicy {
|
pub enum ArchivePolicy {
|
||||||
Manual,
|
Manual,
|
||||||
@@ -16,6 +18,7 @@ pub struct Space {
|
|||||||
accent_hex: u32,
|
accent_hex: u32,
|
||||||
default_profile_id: ProfileId,
|
default_profile_id: ProfileId,
|
||||||
archive_policy: ArchivePolicy,
|
archive_policy: ArchivePolicy,
|
||||||
|
sidebar_width_px: u16,
|
||||||
created_at: SystemTime,
|
created_at: SystemTime,
|
||||||
updated_at: SystemTime,
|
updated_at: SystemTime,
|
||||||
}
|
}
|
||||||
@@ -36,6 +39,7 @@ impl Space {
|
|||||||
accent_hex,
|
accent_hex,
|
||||||
default_profile_id,
|
default_profile_id,
|
||||||
archive_policy: ArchivePolicy::Manual,
|
archive_policy: ArchivePolicy::Manual,
|
||||||
|
sidebar_width_px: DEFAULT_SIDEBAR_WIDTH_PX,
|
||||||
created_at,
|
created_at,
|
||||||
updated_at: created_at,
|
updated_at: created_at,
|
||||||
}
|
}
|
||||||
@@ -81,6 +85,16 @@ impl Space {
|
|||||||
self.record_update();
|
self.record_update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
pub fn sidebar_width_px(&self) -> u16 {
|
||||||
|
self.sidebar_width_px
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_sidebar_width_px(&mut self, sidebar_width_px: u16) {
|
||||||
|
self.sidebar_width_px = sidebar_width_px;
|
||||||
|
self.record_update();
|
||||||
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn created_at(&self) -> SystemTime {
|
pub fn created_at(&self) -> SystemTime {
|
||||||
self.created_at
|
self.created_at
|
||||||
|
|||||||
Reference in New Issue
Block a user