nav.rs
1 use freya::icons::lucide; 2 use freya::prelude::{AccessibilityExt, Alignment, Border, BorderAlignment, 3 BorderWidth, Button, ButtonLayoutThemePartialExt, ChildrenExt, 4 CircularLoader, ContainerExt, ContainerSizeExt, ContainerWithContentExt, 5 Direction, Element, Gaps, IntoElement, Layer, LayerExt, Position, Size, 6 StyleExt, TextAlign, TextStyleExt, label, rect, svg, use_side_effect, 7 use_state}; 8 use freya::radio::use_radio; 9 use crate::components::profile::{ProfileElement, ProfileState}; 10 use crate::constants::{BorderColor, TextColor}; 11 use crate::data::radio::{AppDataChannel, DataChannel}; 12 use crate::data::{ActiveContent, AppData}; 13 use crate::net::limiter::request::RequestEvent; 14 15 pub fn NavBar() -> impl IntoElement 16 { 17 let mut profileState = use_radio::<ProfileState, DataChannel>(DataChannel::ProfileState); 18 let appData = use_radio::<AppData, AppDataChannel>(AppDataChannel::Settings); 19 let requestEvent = use_radio::<RequestEvent, DataChannel>(DataChannel::RateLimiter); 20 let mut activeContent = use_radio::<Option<ActiveContent>, DataChannel>(DataChannel::ActiveContent); 21 22 let mut selected = use_state(|| match activeContent.read().clone() 23 { 24 None => appData.read().app.settings.defaultActivePlatform, 25 Some(ac) => ac, 26 }); 27 28 let taskCounter: Option<Element> = match requestEvent.read().clone() 29 { 30 RequestEvent::Processing(count) => Some( 31 rect() 32 .cross_align(Alignment::Center) 33 .direction(Direction::Vertical) 34 .main_align(Alignment::End) 35 .height(Size::Fill) 36 .width(Size::percent(100.0)) 37 38 .child( 39 CircularLoader::new() 40 .size(32.0) 41 ) 42 43 .child( 44 label() 45 .font_size(12.0) 46 .text(format!("{} processing", count)) 47 .text_align(TextAlign::Center) 48 .width(Size::percent(100.0)) 49 ) 50 .into() 51 ), 52 53 _ => None, 54 }; 55 56 use_side_effect(move || **activeContent.write() = Some(selected())); 57 58 return rect() 59 .direction(Direction::Horizontal) 60 .height(Size::Fill) 61 .layer(Layer::Overlay) 62 .margin(Gaps::new(0.0, 0.0, 0.0, 7.5)) 63 .max_width(Size::px(100.0)) 64 .min_width(Size::px(50.0)) 65 .position(Position::new_absolute() 66 .left(0.0) 67 .top(0.0) 68 ) 69 .width(Size::FillMinimum) 70 71 .child( 72 rect() 73 .border(Some( 74 Border::new() 75 .alignment(BorderAlignment::Center) 76 .fill(BorderColor) 77 .width(BorderWidth 78 { 79 bottom: 0.0, 80 top: 0.0, 81 right: 1.0, 82 left: 0.0, 83 }) 84 )) 85 .direction(Direction::Vertical) 86 .height(Size::Fill) 87 .padding(Gaps::new(10.0, 10.0, 5.0, 0.0)) 88 .spacing(10.0) 89 .width(Size::FillMinimum) 90 91 // Open/close button 92 .child( 93 Button::new() 94 .width(Size::Fill) 95 .on_press(move |_| { 96 let mut profileState = profileState.write(); 97 match profileState.clone() 98 { 99 ProfileState::Hidden => **profileState = ProfileState::Shown, 100 ProfileState::Shown => **profileState = ProfileState::Hidden, 101 _ => {} 102 } 103 }) 104 105 .maybe_child(( 106 profileState.read().clone() == ProfileState::Hiding 107 || profileState.read().clone() == ProfileState::Shown 108 ) 109 .then(|| 110 svg(lucide::chevron_left()) 111 .color(TextColor) 112 .height(Size::px(32.0)) 113 .width(Size::px(32.0)) 114 )) 115 116 .maybe_child(( 117 profileState.read().clone() == ProfileState::Hidden 118 || profileState.read().clone() == ProfileState::Showing 119 ) 120 .then(|| 121 svg(lucide::chevron_right()) 122 .color(TextColor) 123 .height(Size::px(32.0)) 124 .width(Size::px(32.0)) 125 )) 126 ) 127 128 .child( 129 Button::new() 130 .width(Size::percent(100.0)) 131 .on_press(move |_| selected.set(ActiveContent::Settings)) 132 .child( 133 svg(lucide::settings()) 134 .color(TextColor) 135 .height(Size::px(32.0)) 136 .width(Size::px(32.0)) 137 .a11y_alt("Settings") 138 ) 139 ) 140 141 .child( 142 Button::new() 143 .width(Size::percent(100.0)) 144 .child("BNet") 145 .on_press(move |_| selected.set(ActiveContent::BattleNet)) 146 ) 147 148 /* 149 .child( 150 Button::new() 151 .width(Size::percent(100.0)) 152 .child("EGS") 153 .on_press(move |_| selected.set(ActiveContent::EpicGamesStore)) 154 ) 155 */ 156 157 .child( 158 Button::new() 159 .width(Size::percent(100.0)) 160 .child("GOG") 161 .on_press(move |_| selected.set(ActiveContent::Gog)) 162 ) 163 164 .child( 165 Button::new() 166 .width(Size::percent(100.0)) 167 .child("RA") 168 .on_press(move |_| selected.set(ActiveContent::RetroAchievements)) 169 ) 170 171 .child( 172 Button::new() 173 .width(Size::percent(100.0)) 174 .child("RPCS3") 175 .on_press(move |_| selected.set(ActiveContent::Rpcs3)) 176 ) 177 178 .child( 179 Button::new() 180 .width(Size::percent(100.0)) 181 .child("Steam") 182 .on_press(move |_| selected.set(ActiveContent::Steam)) 183 ) 184 185 .maybe_child(taskCounter) 186 ) 187 188 .child(ProfileElement::new()); 189 }