Replace single NavigationView with ViewSwitcher (Installed, Catalog, Updates)
Restructure the app from a single NavigationView into an AdwViewStack with 3 top-level pages: Installed, Catalog, and Updates. Each page keeps its own header bar while an AdwViewSwitcherBar at the bottom provides tab-style navigation between them. The Installed page retains its own NavigationView for detail drill-down. The catalog action now switches the ViewStack tab instead of pushing a page.
This commit is contained in:
@@ -27,6 +27,7 @@ use crate::ui::library_view::{LibraryState, LibraryView};
|
||||
use crate::ui::preferences;
|
||||
use crate::ui::security_report;
|
||||
use crate::ui::update_dialog;
|
||||
use crate::ui::updates_view;
|
||||
use crate::ui::widgets;
|
||||
|
||||
mod imp {
|
||||
@@ -35,7 +36,8 @@ mod imp {
|
||||
pub struct DriftwoodWindow {
|
||||
pub settings: OnceCell<gio::Settings>,
|
||||
pub toast_overlay: OnceCell<adw::ToastOverlay>,
|
||||
pub navigation_view: OnceCell<adw::NavigationView>,
|
||||
pub view_stack: OnceCell<adw::ViewStack>,
|
||||
pub installed_nav: OnceCell<adw::NavigationView>,
|
||||
pub library_view: OnceCell<LibraryView>,
|
||||
pub database: OnceCell<Rc<Database>>,
|
||||
pub drop_overlay: OnceCell<gtk::Box>,
|
||||
@@ -48,7 +50,8 @@ mod imp {
|
||||
Self {
|
||||
settings: OnceCell::new(),
|
||||
toast_overlay: OnceCell::new(),
|
||||
navigation_view: OnceCell::new(),
|
||||
view_stack: OnceCell::new(),
|
||||
installed_nav: OnceCell::new(),
|
||||
library_view: OnceCell::new(),
|
||||
database: OnceCell::new(),
|
||||
drop_overlay: OnceCell::new(),
|
||||
@@ -162,9 +165,41 @@ impl DriftwoodWindow {
|
||||
// Library view (contains header bar, search, grid/list, empty state)
|
||||
let library_view = LibraryView::new(&menu);
|
||||
|
||||
// Navigation view
|
||||
let navigation_view = adw::NavigationView::new();
|
||||
navigation_view.push(&library_view.page);
|
||||
// Installed view: NavigationView for drill-down (detail, dashboard, etc.)
|
||||
let installed_nav = adw::NavigationView::new();
|
||||
installed_nav.push(&library_view.page);
|
||||
|
||||
// Catalog view
|
||||
let catalog_page = catalog_view::build_catalog_page(self.database());
|
||||
|
||||
// Updates view
|
||||
let updates_toolbar = updates_view::build_updates_view(self.database());
|
||||
|
||||
// ViewStack with 3 top-level pages
|
||||
let view_stack = adw::ViewStack::new();
|
||||
view_stack.set_vexpand(true);
|
||||
|
||||
let installed_vs_page = view_stack.add_titled(&installed_nav, Some("installed"), &i18n("Installed"));
|
||||
installed_vs_page.set_icon_name(Some("view-grid-symbolic"));
|
||||
|
||||
let catalog_vs_page = view_stack.add_titled(&catalog_page, Some("catalog"), &i18n("Catalog"));
|
||||
catalog_vs_page.set_icon_name(Some("system-software-install-symbolic"));
|
||||
|
||||
let updates_vs_page = view_stack.add_titled(&updates_toolbar, Some("updates"), &i18n("Updates"));
|
||||
updates_vs_page.set_icon_name(Some("software-update-available-symbolic"));
|
||||
|
||||
// ViewSwitcherBar at the bottom for tab navigation
|
||||
let view_switcher_bar = adw::ViewSwitcherBar::builder()
|
||||
.stack(&view_stack)
|
||||
.reveal(true)
|
||||
.build();
|
||||
|
||||
// Main content box: ViewStack + bottom switcher bar
|
||||
let main_box = gtk::Box::builder()
|
||||
.orientation(gtk::Orientation::Vertical)
|
||||
.build();
|
||||
main_box.append(&view_stack);
|
||||
main_box.append(&view_switcher_bar);
|
||||
|
||||
// Drop overlay - centered opaque card over a dimmed scrim
|
||||
let drop_overlay_icon = gtk::Image::builder()
|
||||
@@ -253,9 +288,9 @@ impl DriftwoodWindow {
|
||||
drop_overlay_content.add_controller(click);
|
||||
}
|
||||
|
||||
// Overlay wraps navigation view so the drop indicator sits on top
|
||||
// Overlay wraps main content so the drop indicator sits on top
|
||||
let overlay = gtk::Overlay::new();
|
||||
overlay.set_child(Some(&navigation_view));
|
||||
overlay.set_child(Some(&main_box));
|
||||
overlay.add_overlay(&drop_overlay_content);
|
||||
|
||||
// Toast overlay wraps the overlay
|
||||
@@ -353,7 +388,7 @@ impl DriftwoodWindow {
|
||||
|
||||
// Wire up card/row activation to push detail view (or toggle selection)
|
||||
{
|
||||
let nav = navigation_view.clone();
|
||||
let nav = installed_nav.clone();
|
||||
let db = self.database().clone();
|
||||
let window_weak = self.downgrade();
|
||||
library_view.connect_grid_activated(move |record_id| {
|
||||
@@ -371,7 +406,7 @@ impl DriftwoodWindow {
|
||||
});
|
||||
}
|
||||
{
|
||||
let nav = navigation_view.clone();
|
||||
let nav = installed_nav.clone();
|
||||
let db = self.database().clone();
|
||||
let window_weak = self.downgrade();
|
||||
library_view.connect_list_activated(move |record_id| {
|
||||
@@ -394,7 +429,7 @@ impl DriftwoodWindow {
|
||||
{
|
||||
let db = self.database().clone();
|
||||
let window_weak = self.downgrade();
|
||||
navigation_view.connect_popped(move |_nav, page| {
|
||||
installed_nav.connect_popped(move |_nav, page| {
|
||||
if page.tag().as_deref() == Some("detail") {
|
||||
if let Some(window) = window_weak.upgrade() {
|
||||
// Update window title for accessibility (WCAG 2.4.8)
|
||||
@@ -413,7 +448,7 @@ impl DriftwoodWindow {
|
||||
// Update window title when navigating to sub-pages (WCAG 2.4.8 Location)
|
||||
{
|
||||
let window_weak = self.downgrade();
|
||||
navigation_view.connect_pushed(move |nav| {
|
||||
installed_nav.connect_pushed(move |nav| {
|
||||
if let Some(window) = window_weak.upgrade() {
|
||||
if let Some(page) = nav.visible_page() {
|
||||
let page_title = page.title();
|
||||
@@ -439,9 +474,13 @@ impl DriftwoodWindow {
|
||||
.set(toast_overlay)
|
||||
.expect("ToastOverlay already set");
|
||||
self.imp()
|
||||
.navigation_view
|
||||
.set(navigation_view)
|
||||
.expect("NavigationView already set");
|
||||
.view_stack
|
||||
.set(view_stack)
|
||||
.expect("ViewStack already set");
|
||||
self.imp()
|
||||
.installed_nav
|
||||
.set(installed_nav)
|
||||
.expect("InstalledNav already set");
|
||||
if self.imp().library_view.set(library_view).is_err() {
|
||||
panic!("LibraryView already set");
|
||||
}
|
||||
@@ -454,7 +493,7 @@ impl DriftwoodWindow {
|
||||
let dashboard_action = gio::ActionEntry::builder("dashboard")
|
||||
.activate(|window: &Self, _, _| {
|
||||
let db = window.database().clone();
|
||||
let nav = window.imp().navigation_view.get().unwrap();
|
||||
let nav = window.imp().installed_nav.get().unwrap();
|
||||
let page = dashboard::build_dashboard_page(&db);
|
||||
nav.push(&page);
|
||||
})
|
||||
@@ -554,7 +593,7 @@ impl DriftwoodWindow {
|
||||
let security_report_action = gio::ActionEntry::builder("security-report")
|
||||
.activate(|window: &Self, _, _| {
|
||||
let db = window.database().clone();
|
||||
let nav = window.imp().navigation_view.get().unwrap();
|
||||
let nav = window.imp().installed_nav.get().unwrap();
|
||||
let page = security_report::build_security_report_page(&db);
|
||||
nav.push(&page);
|
||||
})
|
||||
@@ -568,13 +607,11 @@ impl DriftwoodWindow {
|
||||
})
|
||||
.build();
|
||||
|
||||
// Catalog browser action
|
||||
// Catalog browser action - switches to catalog tab
|
||||
let catalog_action = gio::ActionEntry::builder("catalog")
|
||||
.activate(|window: &Self, _, _| {
|
||||
let db = window.database().clone();
|
||||
let catalog_page = catalog_view::build_catalog_page(&db);
|
||||
let nav = window.imp().navigation_view.get().unwrap();
|
||||
nav.push(&catalog_page);
|
||||
let view_stack = window.imp().view_stack.get().unwrap();
|
||||
view_stack.set_visible_child_name("catalog");
|
||||
})
|
||||
.build();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user