use rust_on_rails::prelude::*;
use crate::events::{KeyboardActiveEvent, NavigateEvent, NavigatorSelect};
use crate::layout::{Column, Row, Padding, Offset, Size, Opt};
use crate::components::avatar::AvatarContent;
use crate::components::button::{IconButton, ButtonState};
use crate::Callback;
use crate::AppPage;
use crate::ElementID;
use std::fmt::Debug;
use super::{NavigationButton, MobileKeyboard};
#[derive(Debug, Component)]
pub struct MobileInterface (Column, Box<dyn AppPage>, Option<Opt<MobileNavigator>>, Option<MobileKeyboard>);
impl MobileInterface {
pub fn new(
ctx: &mut Context,
start_page: impl AppPage,
start_index: Option<usize>,
navigation: Option<Vec<(&'static str, &'static str, Box<Callback>)>>,
profile: Option<(&'static str, AvatarContent, Box<Callback>)>,
) -> Self {
let navigator = navigation.zip(profile).zip(start_index).map(|((nav, p), i)| Opt::new(MobileNavigator::new(ctx, i, nav, p), false));
#[cfg(target_os = "ios")] let insets = safe_area_insets();
#[cfg(not(target_os = "ios"))]
let insets = (0., 0., 0., 0.);
MobileInterface(
Column::new(0.0, Offset::Center, Size::Fit, Padding(0.0, insets.0, 0.0, insets.1)),
Box::new(start_page),
navigator,
None,
)
}
}
impl OnEvent for MobileInterface {
fn on_event(&mut self, ctx: &mut Context, event: &mut dyn Event) -> bool {
if let Some(_event) = event.downcast_ref::<TickEvent>() {
} else if let Some(KeyboardActiveEvent(enabled)) = event.downcast_ref::<KeyboardActiveEvent>() {
self.3 = match enabled {
true => Some(MobileKeyboard::new(ctx)),
false => None
};
} else if let Some(NavigateEvent(page)) = event.downcast_ref::<NavigateEvent>() {
self.1 = page.get_page(ctx);
}
true
}
}
#[derive(Debug, Component)]
pub struct MobileNavigator(Row, Vec<NavigationButton>);
impl MobileNavigator {
pub fn new(
ctx: &mut Context,
start_index: usize,
navigation: Vec<(&'static str, &'static str, Box<Callback>)>,
mut profile: (&'static str, AvatarContent, Box<Callback>)
) -> Self {
if navigation.is_empty() {
panic!("MobileNavigator: Parameter 1 was empty. Navigator has no data.");
}
let profile_id = ElementID::new();
let mut tabs: Vec<NavigationButton> = navigation.into_iter().enumerate().map(|(y, (i, _, mut c))| {
let id = ElementID::new();
let ib = IconButton::tab_nav(ctx, i, y == start_index, move |ctx: &mut Context| {
ctx.trigger_event(NavigatorSelect(id));
(c)(ctx);
});
NavigationButton::new(id, None, Some(ib))
}).collect();
let ib = IconButton::tab_nav(ctx, "profile", false, move |ctx: &mut Context| {
ctx.trigger_event(NavigatorSelect(profile_id));
(profile.2)(ctx);
});
tabs.push(NavigationButton::new(profile_id, None, Some(ib)));
MobileNavigator(
Row(48.0, Offset::Center, Size::Fit, Padding(0.0, 8.0, 0.0, 8.0)),
tabs
)
}
}
impl OnEvent for MobileNavigator {
fn on_event(&mut self, ctx: &mut Context, event: &mut dyn Event) -> bool {
if let Some(NavigatorSelect(id)) = event.downcast_ref::<NavigatorSelect>() {
self.1.iter_mut().for_each(|button| {
let status = if button.id() == *id {ButtonState::Selected} else {ButtonState::UnSelected};
*button.icon_button().as_mut().unwrap().status() = status;
button.icon_button().as_mut().unwrap().color(ctx, status);
});
}
true
}
}