Domain ships HIDDEN_SIDEBAR_WIDTH_PX = 8 alongside the existing collapsed/default tiers. ElyShell tracks sidebar_hover_expanded with expand_hidden_sidebar / collapse_hidden_sidebar helpers; switching back to a non-hidden width via the layout cards or core API resets the flag automatically so the sidebar can never be both hidden and expanded after a mode change. Renderer: - render_sidebar takes a sidebar_hidden flag and routes to a thin 8 px clickable rail (hover bg + click expands) when the active space's width is at HIDDEN. - While the rail is expanded, render_browser overlays a transparent backdrop + the full default-width sidebar absolutely positioned in the shell inset, so the main pane content never reflows. - collapsed_sidebar_active still drives the COLLAPSED-tier compact sidebar; the hidden tier is opted out of that path. Appearance form: - Layout cards section gains the design's third "Hidden on hover" card with a 6 px sliver preview that mutates the active space to HIDDEN_SIDEBAR_WIDTH_PX. LayoutMode now derives id/width/preview from a small enum so adding a fourth mode would be one match arm. The hover-expanded state never persists into the domain; once the user switches modes or clicks the backdrop, it collapses cleanly.
129 lines
2.9 KiB
Rust
129 lines
2.9 KiB
Rust
use std::time::{Duration, SystemTime};
|
|
|
|
use crate::{ProfileId, SpaceId};
|
|
|
|
pub const DEFAULT_SIDEBAR_WIDTH_PX: u16 = 280;
|
|
pub const COLLAPSED_SIDEBAR_WIDTH_PX: u16 = 56;
|
|
pub const HIDDEN_SIDEBAR_WIDTH_PX: u16 = 8;
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub enum ArchivePolicy {
|
|
Manual,
|
|
IdleDays(u16),
|
|
}
|
|
|
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
pub struct Space {
|
|
id: SpaceId,
|
|
name: String,
|
|
icon: String,
|
|
accent_hex: u32,
|
|
default_profile_id: ProfileId,
|
|
archive_policy: ArchivePolicy,
|
|
sidebar_width_px: u16,
|
|
sort_key: u64,
|
|
created_at: SystemTime,
|
|
updated_at: SystemTime,
|
|
}
|
|
|
|
impl Space {
|
|
#[must_use]
|
|
pub fn new(
|
|
name: impl Into<String>,
|
|
icon: impl Into<String>,
|
|
accent_hex: u32,
|
|
default_profile_id: ProfileId,
|
|
sort_key: u64,
|
|
) -> Self {
|
|
let created_at = SystemTime::now();
|
|
Self {
|
|
id: SpaceId::new(),
|
|
name: name.into(),
|
|
icon: icon.into(),
|
|
accent_hex,
|
|
default_profile_id,
|
|
archive_policy: ArchivePolicy::Manual,
|
|
sidebar_width_px: DEFAULT_SIDEBAR_WIDTH_PX,
|
|
sort_key,
|
|
created_at,
|
|
updated_at: created_at,
|
|
}
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn id(&self) -> &SpaceId {
|
|
&self.id
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn name(&self) -> &str {
|
|
&self.name
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn icon(&self) -> &str {
|
|
&self.icon
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn accent_hex(&self) -> u32 {
|
|
self.accent_hex
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn default_profile_id(&self) -> &ProfileId {
|
|
&self.default_profile_id
|
|
}
|
|
|
|
pub fn set_default_profile_id(&mut self, profile_id: ProfileId) {
|
|
self.default_profile_id = profile_id;
|
|
self.record_update();
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn archive_policy(&self) -> &ArchivePolicy {
|
|
&self.archive_policy
|
|
}
|
|
|
|
pub fn set_archive_policy(&mut self, archive_policy: ArchivePolicy) {
|
|
self.archive_policy = archive_policy;
|
|
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]
|
|
pub fn sort_key(&self) -> u64 {
|
|
self.sort_key
|
|
}
|
|
|
|
pub fn set_sort_key(&mut self, sort_key: u64) {
|
|
self.sort_key = sort_key;
|
|
self.record_update();
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn created_at(&self) -> SystemTime {
|
|
self.created_at
|
|
}
|
|
|
|
#[must_use]
|
|
pub fn updated_at(&self) -> SystemTime {
|
|
self.updated_at
|
|
}
|
|
|
|
fn record_update(&mut self) {
|
|
let now = SystemTime::now();
|
|
self.updated_at =
|
|
if now > self.updated_at { now } else { self.updated_at + Duration::from_nanos(1) };
|
|
}
|
|
}
|