From 2e7bc89dbc7a89a63ac3fd721c891bd1e4e0359e Mon Sep 17 00:00:00 2001 From: LynithDev <61880709+LynithDev@users.noreply.github.com> Date: Sat, 1 Aug 2026 11:46:15 +0200 Subject: [PATCH] feat(ui): rename External tab to Browser and add toolbar browse action --- .../view/app/cluster/package_manager/mod.rs | 16 +++---- .../view/app/cluster/package_manager/views.rs | 42 ++++++++++++------- 2 files changed, 37 insertions(+), 21 deletions(-) diff --git a/packages/oneclient_app/src/view/app/cluster/package_manager/mod.rs b/packages/oneclient_app/src/view/app/cluster/package_manager/mod.rs index 9f582915..019bdf08 100644 --- a/packages/oneclient_app/src/view/app/cluster/package_manager/mod.rs +++ b/packages/oneclient_app/src/view/app/cluster/package_manager/mod.rs @@ -222,7 +222,7 @@ fn make_row( pub(super) enum Tab { All, Category(String), - External, + Browser, Local, } @@ -231,7 +231,7 @@ impl Tab { match self { Tab::All => "All".to_string(), Tab::Category(c) => c.clone(), - Tab::External => "External".to_string(), + Tab::Browser => "Browser".to_string(), Tab::Local => "Local".to_string(), } } @@ -241,8 +241,8 @@ impl Tab { // Every package assigned to the cluster, regardless of origin. Tab::All => true, Tab::Category(c) => p.categories.iter().any(|pc| pc == c), - // External = remote provider content that is NOT provided by a bundle. - Tab::External => p.is_remote() && !p.in_bundle(), + // Browser = remote provider content that is NOT provided by a bundle. + Tab::Browser => p.is_remote() && !p.in_bundle(), Tab::Local => !p.is_remote(), } } @@ -269,7 +269,7 @@ fn build_tabs(categories: &[String], items: &[PackageEntry]) -> Vec { } } - // Category tabs are hidden when empty; All + External + Local are always shown. + // Category tabs are hidden when empty; All + Browser + Local are always shown. let mut tabs: Vec = vec![Tab::All]; tabs.extend( cats.into_iter() @@ -277,7 +277,7 @@ fn build_tabs(categories: &[String], items: &[PackageEntry]) -> Vec { .filter(|t| items.iter().any(|p| t.matches(p))), ); - tabs.push(Tab::External); + tabs.push(Tab::Browser); tabs.push(Tab::Local); tabs } @@ -348,7 +348,7 @@ impl Component for PackageManager { let tab_filter = tabs.get(active_idx); let content_kind = match tab_filter { - Some(Tab::External) => ContentKind::External, + Some(Tab::Browser) => ContentKind::Browser, Some(Tab::Local) => ContentKind::Local, _ => ContentKind::Other, }; @@ -380,6 +380,8 @@ impl Component for PackageManager { sort_mode, enabled_filter, layout, + cluster_id, + package_type, )) .maybe_child(session_live.then(|| views::running_notice(noun_plural))) .child(ContentBox::new( diff --git a/packages/oneclient_app/src/view/app/cluster/package_manager/views.rs b/packages/oneclient_app/src/view/app/cluster/package_manager/views.rs index 96810b93..e16bd69d 100644 --- a/packages/oneclient_app/src/view/app/cluster/package_manager/views.rs +++ b/packages/oneclient_app/src/view/app/cluster/package_manager/views.rs @@ -114,6 +114,8 @@ pub(super) fn toolbar_bar( current_sort: SortMode, enabled_filter: State, layout: State, + cluster_id: i64, + package_type: &'static str, ) -> impl IntoElement { let tab_items = tabs.iter().enumerate().map(|(i, tab)| { let mut active = active; @@ -172,6 +174,15 @@ pub(super) fn toolbar_bar( .segment(Segment::new(ViewLayout::List).icon(IconType::ParagraphWrap)) .segment(Segment::new(ViewLayout::Grid).icon(IconType::DotsGrid)), ) + .child( + Button::new() + .primary() + .height(Size::px(34.)) + .font_size(12.) + .on_press(move |_| open_browser(cluster_id, package_type)) + .child(Icon::new(IconType::Plus).size(15.)) + .text("Add Content"), + ) .into_element() } @@ -462,23 +473,26 @@ fn add_from_file_button( .text("Add from file") } +/// Opens the content browser scoped to this cluster and package type. +fn open_browser(cluster_id: i64, package_type: &'static str) { + let _ = RouterContext::get().push(Route::Browser { + cluster_id, + package_type: package_type.to_string(), + pick_cluster: false, + }); +} + fn browse_button(cluster_id: i64, package_type: &'static str) -> impl IntoElement { Button::new() .primary() - .on_press(move |_| { - let _ = RouterContext::get().push(Route::Browser { - cluster_id, - package_type: package_type.to_string(), - pick_cluster: false, - }); - }) + .on_press(move |_| open_browser(cluster_id, package_type)) .child(Icon::new(IconType::SearchMd).size(14.)) .text("Browse Content") } #[derive(Clone, Copy, PartialEq)] pub(super) enum ContentKind { - External, + Browser, Local, Other, } @@ -556,7 +570,7 @@ impl Component for ContentBox { }); let empty = (count == 0).then(|| match kind { - ContentKind::External => external_empty(cluster_id, package_type).into_element(), + ContentKind::Browser => browser_empty(cluster_id, package_type).into_element(), ContentKind::Local => { local_empty(cluster_id, content_type, dispatch.clone(), noun_plural).into_element() } @@ -565,9 +579,9 @@ impl Component for ContentBox { let header = (count > 0) .then(|| match kind { - ContentKind::External => { - Some(action_header(browse_button(cluster_id, package_type)).into_element()) - } + // The toolbar above already carries a permanent "Add Content" + // button, so this list needs no browse action of its own. + ContentKind::Browser => None, ContentKind::Local => Some( action_header(add_from_file_button( cluster_id, @@ -699,9 +713,9 @@ fn empty_state(noun_plural: &'static str) -> impl IntoElement { .into_element() } -fn external_empty(cluster_id: i64, package_type: &'static str) -> impl IntoElement { +fn browser_empty(cluster_id: i64, package_type: &'static str) -> impl IntoElement { empty_shell(IconType::SearchMd) - .child(empty_title("No external content installed.")) + .child(empty_title("No content installed from the browser.")) .child(empty_hint( "Browse providers to add mods, resource packs and more.", ))