fix: menues now working, also project selector
This commit is contained in:
3
crates/bds-ui/assets/icons/folder.svg
Normal file
3
crates/bds-ui/assets/icons/folder.svg
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="#ffffff">
|
||||||
|
<path d="M10 4H4a2 2 0 0 0-2 2v12a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-8l-2-2z"/>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 201 B |
@@ -65,6 +65,7 @@ pub enum Message {
|
|||||||
SetOfflineMode(bool),
|
SetOfflineMode(bool),
|
||||||
SetUiLocale(UiLocale),
|
SetUiLocale(UiLocale),
|
||||||
ToggleLocaleDropdown,
|
ToggleLocaleDropdown,
|
||||||
|
ToggleProjectDropdown,
|
||||||
|
|
||||||
// Blog actions (dispatched to engine)
|
// Blog actions (dispatched to engine)
|
||||||
RebuildDatabase,
|
RebuildDatabase,
|
||||||
@@ -73,6 +74,7 @@ pub enum Message {
|
|||||||
BlogTaskFinished { label: String, result: Result<(), String> },
|
BlogTaskFinished { label: String, result: Result<(), String> },
|
||||||
|
|
||||||
Noop,
|
Noop,
|
||||||
|
InitMenuBar,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ───────────────────────────────────────────────────────────
|
// ───────────────────────────────────────────────────────────
|
||||||
@@ -115,6 +117,7 @@ pub struct BdsApp {
|
|||||||
// Flags
|
// Flags
|
||||||
offline_mode: bool,
|
offline_mode: bool,
|
||||||
locale_dropdown_open: bool,
|
locale_dropdown_open: bool,
|
||||||
|
project_dropdown_open: bool,
|
||||||
|
|
||||||
// macOS lifecycle receiver
|
// macOS lifecycle receiver
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
@@ -188,7 +191,9 @@ impl BdsApp {
|
|||||||
Task::done(Message::ProjectsLoaded(projects.clone()))
|
Task::done(Message::ProjectsLoaded(projects.clone()))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Disable items that need selection
|
// Chain menu initialization after project loading
|
||||||
|
// (must happen after the event loop has started for macOS)
|
||||||
|
let init_task = Task::batch([init_task, Task::done(Message::InitMenuBar)]);
|
||||||
registry.set_enabled(MenuAction::Save, false);
|
registry.set_enabled(MenuAction::Save, false);
|
||||||
registry.set_enabled(MenuAction::PublishSelected, false);
|
registry.set_enabled(MenuAction::PublishSelected, false);
|
||||||
registry.set_enabled(MenuAction::PreviewPost, false);
|
registry.set_enabled(MenuAction::PreviewPost, false);
|
||||||
@@ -216,6 +221,7 @@ impl BdsApp {
|
|||||||
ui_locale: locale,
|
ui_locale: locale,
|
||||||
offline_mode: false,
|
offline_mode: false,
|
||||||
locale_dropdown_open: false,
|
locale_dropdown_open: false,
|
||||||
|
project_dropdown_open: false,
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
_lifecycle_rx,
|
_lifecycle_rx,
|
||||||
},
|
},
|
||||||
@@ -294,6 +300,7 @@ impl BdsApp {
|
|||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
Message::SwitchProject(project_id) => {
|
Message::SwitchProject(project_id) => {
|
||||||
|
self.project_dropdown_open = false;
|
||||||
if let Some(ref db) = self.db {
|
if let Some(ref db) = self.db {
|
||||||
match engine::project::set_active_project(db.conn(), &project_id) {
|
match engine::project::set_active_project(db.conn(), &project_id) {
|
||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
@@ -431,6 +438,12 @@ impl BdsApp {
|
|||||||
}
|
}
|
||||||
Message::ToggleLocaleDropdown => {
|
Message::ToggleLocaleDropdown => {
|
||||||
self.locale_dropdown_open = !self.locale_dropdown_open;
|
self.locale_dropdown_open = !self.locale_dropdown_open;
|
||||||
|
self.project_dropdown_open = false;
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
|
Message::ToggleProjectDropdown => {
|
||||||
|
self.project_dropdown_open = !self.project_dropdown_open;
|
||||||
|
self.locale_dropdown_open = false;
|
||||||
Task::none()
|
Task::none()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -463,6 +476,11 @@ impl BdsApp {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Message::Noop => Task::none(),
|
Message::Noop => Task::none(),
|
||||||
|
Message::InitMenuBar => {
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
menu::init_menu_for_nsapp(&self._menu_bar);
|
||||||
|
Task::none()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -479,10 +497,13 @@ impl BdsApp {
|
|||||||
&self.task_snapshots,
|
&self.task_snapshots,
|
||||||
&self.output_entries,
|
&self.output_entries,
|
||||||
active_name,
|
active_name,
|
||||||
|
&self.projects,
|
||||||
|
self.active_project.as_ref().map(|p| p.id.as_str()),
|
||||||
0, // post_count — populated in later milestones
|
0, // post_count — populated in later milestones
|
||||||
0, // media_count — populated in later milestones
|
0, // media_count — populated in later milestones
|
||||||
self.offline_mode,
|
self.offline_mode,
|
||||||
self.locale_dropdown_open,
|
self.locale_dropdown_open,
|
||||||
|
self.project_dropdown_open,
|
||||||
self.ui_locale,
|
self.ui_locale,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,13 +289,16 @@ pub fn build_menu_bar(locale: UiLocale) -> (Menu, MenuRegistry) {
|
|||||||
let _ = menu.append(&blog_menu);
|
let _ = menu.append(&blog_menu);
|
||||||
let _ = menu.append(&help_menu);
|
let _ = menu.append(&help_menu);
|
||||||
|
|
||||||
// Attach on macOS
|
(menu, reg)
|
||||||
#[cfg(target_os = "macos")]
|
|
||||||
{
|
|
||||||
let _ = menu.init_for_nsapp();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
(menu, reg)
|
/// Attach the built menu to the macOS NSApp.
|
||||||
|
///
|
||||||
|
/// Must be called **after** the event loop has started (e.g. from the
|
||||||
|
/// init task or first update), not during `build_menu_bar`.
|
||||||
|
#[cfg(target_os = "macos")]
|
||||||
|
pub fn init_menu_for_nsapp(menu: &Menu) {
|
||||||
|
let _ = menu.init_for_nsapp();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Re-translate every registered menu item for a new locale.
|
/// Re-translate every registered menu item for a new locale.
|
||||||
|
|||||||
@@ -4,4 +4,5 @@ pub mod sidebar;
|
|||||||
pub mod tab_bar;
|
pub mod tab_bar;
|
||||||
pub mod status_bar;
|
pub mod status_bar;
|
||||||
pub mod panel;
|
pub mod panel;
|
||||||
|
pub mod project_selector;
|
||||||
pub mod welcome;
|
pub mod welcome;
|
||||||
|
|||||||
226
crates/bds-ui/src/views/project_selector.rs
Normal file
226
crates/bds-ui/src/views/project_selector.rs
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
use iced::widget::{button, container, row, svg, text, Column, Space};
|
||||||
|
use iced::{Background, Border, Color, Element, Length, Theme};
|
||||||
|
|
||||||
|
use bds_core::i18n::UiLocale;
|
||||||
|
use bds_core::model::Project;
|
||||||
|
|
||||||
|
use crate::app::Message;
|
||||||
|
use crate::i18n::t;
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Styles
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
fn dropdown_bg(_theme: &Theme) -> container::Style {
|
||||||
|
container::Style {
|
||||||
|
background: Some(Background::Color(Color::from_rgb(0.18, 0.18, 0.22))),
|
||||||
|
border: Border {
|
||||||
|
color: Color::from_rgb(0.30, 0.30, 0.35),
|
||||||
|
width: 1.0,
|
||||||
|
radius: 4.0.into(),
|
||||||
|
},
|
||||||
|
..container::Style::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn project_item(_theme: &Theme, status: button::Status) -> button::Style {
|
||||||
|
let bg = match status {
|
||||||
|
button::Status::Hovered => Color::from_rgb(0.25, 0.25, 0.30),
|
||||||
|
_ => Color::from_rgb(0.18, 0.18, 0.22),
|
||||||
|
};
|
||||||
|
button::Style {
|
||||||
|
background: Some(Background::Color(bg)),
|
||||||
|
text_color: Color::WHITE,
|
||||||
|
border: Border {
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
width: 0.0,
|
||||||
|
radius: 2.0.into(),
|
||||||
|
},
|
||||||
|
..button::Style::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn project_item_active(_theme: &Theme, status: button::Status) -> button::Style {
|
||||||
|
let bg = match status {
|
||||||
|
button::Status::Hovered => Color::from_rgb(0.25, 0.32, 0.45),
|
||||||
|
_ => Color::from_rgb(0.20, 0.28, 0.40),
|
||||||
|
};
|
||||||
|
button::Style {
|
||||||
|
background: Some(Background::Color(bg)),
|
||||||
|
text_color: Color::WHITE,
|
||||||
|
border: Border {
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
width: 0.0,
|
||||||
|
radius: 2.0.into(),
|
||||||
|
},
|
||||||
|
..button::Style::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new_project_btn(_theme: &Theme, status: button::Status) -> button::Style {
|
||||||
|
let bg = match status {
|
||||||
|
button::Status::Hovered => Color::from_rgb(0.25, 0.25, 0.30),
|
||||||
|
_ => Color::TRANSPARENT,
|
||||||
|
};
|
||||||
|
button::Style {
|
||||||
|
background: Some(Background::Color(bg)),
|
||||||
|
text_color: Color::from_rgb(0.55, 0.75, 0.95),
|
||||||
|
border: Border {
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
width: 0.0,
|
||||||
|
radius: 2.0.into(),
|
||||||
|
},
|
||||||
|
..button::Style::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn header_style(_theme: &Theme) -> container::Style {
|
||||||
|
container::Style {
|
||||||
|
border: Border {
|
||||||
|
color: Color::from_rgb(0.30, 0.30, 0.35),
|
||||||
|
width: 0.0,
|
||||||
|
radius: 0.0.into(),
|
||||||
|
},
|
||||||
|
..container::Style::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Folder icon SVG (16x16)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const FOLDER_ICON: &[u8] = include_bytes!("../../assets/icons/folder.svg");
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// View: renders the dropdown content (project list + new project)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub fn view(
|
||||||
|
projects: &[Project],
|
||||||
|
active_project_id: Option<&str>,
|
||||||
|
locale: UiLocale,
|
||||||
|
) -> Element<'static, Message> {
|
||||||
|
let header = container(
|
||||||
|
text(t(locale, "projectSelector.projectsHeader"))
|
||||||
|
.size(11)
|
||||||
|
.color(Color::from_rgb(0.55, 0.55, 0.60)),
|
||||||
|
)
|
||||||
|
.padding([4, 8])
|
||||||
|
.style(header_style);
|
||||||
|
|
||||||
|
let mut items: Vec<Element<'static, Message>> = Vec::new();
|
||||||
|
items.push(header.into());
|
||||||
|
|
||||||
|
for project in projects {
|
||||||
|
let is_active = active_project_id == Some(project.id.as_str());
|
||||||
|
let name = project.name.clone();
|
||||||
|
let id = project.id.clone();
|
||||||
|
|
||||||
|
let label = if is_active {
|
||||||
|
row![
|
||||||
|
text("\u{2713}").size(12).color(Color::from_rgb(0.40, 0.80, 0.40)),
|
||||||
|
text(name).size(12).color(Color::WHITE),
|
||||||
|
]
|
||||||
|
.spacing(6)
|
||||||
|
} else {
|
||||||
|
row![
|
||||||
|
Space::with_width(Length::Fixed(14.0)),
|
||||||
|
text(name).size(12).color(Color::from_rgb(0.80, 0.80, 0.85)),
|
||||||
|
]
|
||||||
|
.spacing(6)
|
||||||
|
};
|
||||||
|
|
||||||
|
let style_fn = if is_active { project_item_active } else { project_item };
|
||||||
|
|
||||||
|
items.push(
|
||||||
|
button(label)
|
||||||
|
.on_press(Message::SwitchProject(id))
|
||||||
|
.padding([4, 8])
|
||||||
|
.width(Length::Fill)
|
||||||
|
.style(style_fn)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Separator
|
||||||
|
items.push(
|
||||||
|
container(Space::new(Length::Fill, Length::Fixed(1.0)))
|
||||||
|
.style(|_theme: &Theme| container::Style {
|
||||||
|
background: Some(Background::Color(Color::from_rgb(0.30, 0.30, 0.35))),
|
||||||
|
..container::Style::default()
|
||||||
|
})
|
||||||
|
.width(Length::Fill)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// New project button
|
||||||
|
items.push(
|
||||||
|
button(
|
||||||
|
row![
|
||||||
|
text("+").size(14).color(Color::from_rgb(0.55, 0.75, 0.95)),
|
||||||
|
text(t(locale, "projectSelector.newProject")).size(12),
|
||||||
|
]
|
||||||
|
.spacing(6),
|
||||||
|
)
|
||||||
|
.on_press(Message::RequestCreateProject)
|
||||||
|
.padding([4, 8])
|
||||||
|
.width(Length::Fill)
|
||||||
|
.style(new_project_btn)
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
|
|
||||||
|
container(
|
||||||
|
Column::with_children(items)
|
||||||
|
.spacing(2)
|
||||||
|
.padding(4)
|
||||||
|
.width(Length::Fixed(200.0)),
|
||||||
|
)
|
||||||
|
.style(dropdown_bg)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
// Trigger button for status bar (folder icon + project name + chevron)
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
pub fn trigger_style(_theme: &Theme, status: button::Status) -> button::Style {
|
||||||
|
let bg = match status {
|
||||||
|
button::Status::Hovered => Color::from_rgb(0.22, 0.22, 0.27),
|
||||||
|
_ => Color::TRANSPARENT,
|
||||||
|
};
|
||||||
|
button::Style {
|
||||||
|
background: Some(Background::Color(bg)),
|
||||||
|
text_color: Color::WHITE,
|
||||||
|
border: Border {
|
||||||
|
color: Color::TRANSPARENT,
|
||||||
|
width: 0.0,
|
||||||
|
radius: 3.0.into(),
|
||||||
|
},
|
||||||
|
..button::Style::default()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trigger_button(project_name: &str) -> Element<'static, Message> {
|
||||||
|
let folder = svg::Handle::from_memory(FOLDER_ICON);
|
||||||
|
let folder_icon = svg(folder)
|
||||||
|
.width(Length::Fixed(14.0))
|
||||||
|
.height(Length::Fixed(14.0));
|
||||||
|
|
||||||
|
let name = text(project_name.to_string())
|
||||||
|
.size(12)
|
||||||
|
.color(Color::from_rgb(0.80, 0.80, 0.85));
|
||||||
|
|
||||||
|
let chevron = text("\u{25BE}")
|
||||||
|
.size(10)
|
||||||
|
.color(Color::from_rgb(0.55, 0.55, 0.60));
|
||||||
|
|
||||||
|
button(
|
||||||
|
row![folder_icon, name, chevron]
|
||||||
|
.spacing(4)
|
||||||
|
.align_y(iced::Alignment::Center),
|
||||||
|
)
|
||||||
|
.on_press(Message::ToggleProjectDropdown)
|
||||||
|
.padding([2, 6])
|
||||||
|
.style(trigger_style)
|
||||||
|
.into()
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ use bds_core::i18n::UiLocale;
|
|||||||
use crate::app::Message;
|
use crate::app::Message;
|
||||||
use crate::i18n::tw;
|
use crate::i18n::tw;
|
||||||
use crate::state::navigation::TaskSnapshot;
|
use crate::state::navigation::TaskSnapshot;
|
||||||
|
use crate::views::project_selector;
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
// Styles
|
// Styles
|
||||||
@@ -119,9 +120,9 @@ pub fn view(
|
|||||||
) -> Element<'static, Message> {
|
) -> Element<'static, Message> {
|
||||||
let label_color = Color::from_rgb(0.60, 0.60, 0.65);
|
let label_color = Color::from_rgb(0.60, 0.60, 0.65);
|
||||||
|
|
||||||
// ── Left: project name + task indicator ──
|
// ── Left: project selector trigger + task indicator ──
|
||||||
let project_label = active_project_name.unwrap_or("\u{2014}").to_string();
|
let project_name = active_project_name.unwrap_or("\u{2014}");
|
||||||
let project_text = text(project_label).size(12).color(Color::from_rgb(0.80, 0.80, 0.85));
|
let project_trigger = project_selector::trigger_button(project_name);
|
||||||
|
|
||||||
let running: Vec<&TaskSnapshot> = task_snapshots
|
let running: Vec<&TaskSnapshot> = task_snapshots
|
||||||
.iter()
|
.iter()
|
||||||
@@ -138,7 +139,9 @@ pub fn view(
|
|||||||
Space::with_width(0).into()
|
Space::with_width(0).into()
|
||||||
};
|
};
|
||||||
|
|
||||||
let left = row![project_text, task_indicator].spacing(12);
|
let left = row![project_trigger, task_indicator]
|
||||||
|
.spacing(12)
|
||||||
|
.align_y(Alignment::Center);
|
||||||
|
|
||||||
// ── Right side ──
|
// ── Right side ──
|
||||||
|
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ use iced::widget::text::Shaping;
|
|||||||
use iced::{Alignment, Background, Color, Element, Length, Padding, Theme};
|
use iced::{Alignment, Background, Color, Element, Length, Padding, Theme};
|
||||||
|
|
||||||
use bds_core::i18n::UiLocale;
|
use bds_core::i18n::UiLocale;
|
||||||
|
use bds_core::model::Project;
|
||||||
|
|
||||||
use crate::app::Message;
|
use crate::app::Message;
|
||||||
use crate::state::navigation::{OutputEntry, PanelTab, SidebarView, TaskSnapshot};
|
use crate::state::navigation::{OutputEntry, PanelTab, SidebarView, TaskSnapshot};
|
||||||
use crate::state::tabs::Tab;
|
use crate::state::tabs::Tab;
|
||||||
use crate::views::{activity_bar, panel, sidebar, status_bar, tab_bar, welcome};
|
use crate::views::{activity_bar, panel, project_selector, sidebar, status_bar, tab_bar, welcome};
|
||||||
|
|
||||||
/// Main content area background.
|
/// Main content area background.
|
||||||
fn content_bg(_theme: &Theme) -> container::Style {
|
fn content_bg(_theme: &Theme) -> container::Style {
|
||||||
@@ -54,10 +55,13 @@ pub fn view(
|
|||||||
output_entries: &[OutputEntry],
|
output_entries: &[OutputEntry],
|
||||||
// Status bar
|
// Status bar
|
||||||
active_project_name: Option<&str>,
|
active_project_name: Option<&str>,
|
||||||
|
projects: &[Project],
|
||||||
|
active_project_id: Option<&str>,
|
||||||
post_count: usize,
|
post_count: usize,
|
||||||
media_count: usize,
|
media_count: usize,
|
||||||
offline_mode: bool,
|
offline_mode: bool,
|
||||||
locale_dropdown_open: bool,
|
locale_dropdown_open: bool,
|
||||||
|
project_dropdown_open: bool,
|
||||||
// i18n
|
// i18n
|
||||||
locale: UiLocale,
|
locale: UiLocale,
|
||||||
) -> Element<'static, Message> {
|
) -> Element<'static, Message> {
|
||||||
@@ -107,8 +111,8 @@ pub fn view(
|
|||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
if locale_dropdown_open {
|
// Overlay: either locale dropdown or project dropdown (mutually exclusive)
|
||||||
// Build the dropdown menu overlay
|
let overlay: Option<Element<'static, Message>> = if locale_dropdown_open {
|
||||||
let items: Vec<Element<'static, Message>> = UiLocale::all()
|
let items: Vec<Element<'static, Message>> = UiLocale::all()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&l| {
|
.map(|&l| {
|
||||||
@@ -129,25 +133,52 @@ pub fn view(
|
|||||||
)
|
)
|
||||||
.style(status_bar::dropdown_bg);
|
.style(status_bar::dropdown_bg);
|
||||||
|
|
||||||
// Position the dropdown at bottom-right, above the status bar (24px)
|
// Position at bottom-right, above status bar
|
||||||
let overlay: Element<'static, Message> = container(
|
Some(
|
||||||
|
container(
|
||||||
container(
|
container(
|
||||||
row![
|
row![
|
||||||
Space::with_width(Length::Fill),
|
Space::with_width(Length::Fill),
|
||||||
dropdown_menu,
|
dropdown_menu,
|
||||||
// Offset from right edge to align near the flag trigger
|
|
||||||
Space::with_width(Length::Fixed(40.0)),
|
Space::with_width(Length::Fixed(40.0)),
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.align_y(Alignment::End)
|
.align_y(Alignment::End)
|
||||||
.padding(Padding { top: 0.0, right: 0.0, bottom: 25.0, left: 0.0 }) // above status bar
|
.padding(Padding { top: 0.0, right: 0.0, bottom: 25.0, left: 0.0 })
|
||||||
)
|
)
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
.align_y(Alignment::End)
|
.align_y(Alignment::End)
|
||||||
.into();
|
.into()
|
||||||
|
)
|
||||||
|
} else if project_dropdown_open {
|
||||||
|
let dropdown = project_selector::view(projects, active_project_id, locale);
|
||||||
|
|
||||||
|
// Position at bottom-left, above status bar
|
||||||
|
Some(
|
||||||
|
container(
|
||||||
|
container(
|
||||||
|
row![
|
||||||
|
Space::with_width(Length::Fixed(8.0)),
|
||||||
|
dropdown,
|
||||||
|
Space::with_width(Length::Fill),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.align_y(Alignment::End)
|
||||||
|
.padding(Padding { top: 0.0, right: 0.0, bottom: 25.0, left: 0.0 })
|
||||||
|
)
|
||||||
|
.width(Length::Fill)
|
||||||
|
.height(Length::Fill)
|
||||||
|
.align_y(Alignment::End)
|
||||||
|
.into()
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(overlay) = overlay {
|
||||||
stack![base_layout, overlay]
|
stack![base_layout, overlay]
|
||||||
.width(Length::Fill)
|
.width(Length::Fill)
|
||||||
.height(Length::Fill)
|
.height(Length::Fill)
|
||||||
|
|||||||
@@ -71,6 +71,9 @@ fn new_message_variants_constructable() {
|
|||||||
// Settings
|
// Settings
|
||||||
let _offline = Message::SetOfflineMode(true);
|
let _offline = Message::SetOfflineMode(true);
|
||||||
let _locale = Message::SetUiLocale(UiLocale::De);
|
let _locale = Message::SetUiLocale(UiLocale::De);
|
||||||
|
let _toggle_locale = Message::ToggleLocaleDropdown;
|
||||||
|
let _toggle_project = Message::ToggleProjectDropdown;
|
||||||
|
let _init_menu = Message::InitMenuBar;
|
||||||
|
|
||||||
// Blog actions
|
// Blog actions
|
||||||
let _rebuild = Message::RebuildDatabase;
|
let _rebuild = Message::RebuildDatabase;
|
||||||
|
|||||||
Reference in New Issue
Block a user