/ src / components / nav.rs
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  }