from functools import partial from typing import Optional, Callable import rio from from_root import from_root from rio import Component, Row, Rectangle, Text, Color, Spacer, PointerEventListener, Column, Image, TextStyle, Icon, PointerEvent, EventHandler from elm.services import ConfigurationService class NavigationButton(Component): icon: str text: str target_url: str extension_state_changed: Optional[Callable] new_tab: bool = False current_rectangle_fill_color = Color.TRANSPARENT current_text_fill_color = Color.from_hex("b9ccb2") COLOR_ACTIVE_RECTANGLE = Color.from_hex("4EFBE5") COLOR_ACTIVE_TEXT = Color.from_hex("4EFBE5") COLOR_INACTIVE_RECTANGLE = Color.TRANSPARENT COLOR_INACTIVE_TEXT = Color.from_hex("b9ccb2") async def on_pointer_enter(self, _: PointerEvent) -> None: self.current_rectangle_fill_color = self.COLOR_ACTIVE_RECTANGLE self.current_text_fill_color = self.COLOR_ACTIVE_TEXT self.force_refresh() async def on_pointer_leave(self, _: PointerEvent) -> None: self.current_rectangle_fill_color = self.COLOR_INACTIVE_RECTANGLE self.current_text_fill_color = self.COLOR_INACTIVE_TEXT self.force_refresh() async def on_press(self, _: PointerEvent) -> None: if self.new_tab: self.session.open_url_in_browser(self.target_url) else: self.session.navigate_to(self.target_url) if self.extension_state_changed is not None: await self.extension_state_changed(None) def is_active(self) -> bool: return self.session.active_page_url.path == self.target_url def build(self) -> Component: return PointerEventListener( Rectangle( content=Row( Rectangle(fill=self.COLOR_ACTIVE_RECTANGLE if self.is_active() else self.current_rectangle_fill_color, min_width=0.3, margin_right=1.7, transition_time=0.2), Icon( self.icon, min_width=1.9, min_height=1.9, fill=self.COLOR_ACTIVE_TEXT if self.is_active() else self.current_text_fill_color ), Text( self.text, style=TextStyle(fill=self.COLOR_ACTIVE_TEXT if self.is_active() else self.current_text_fill_color, font_weight="normal", font_size=1.1), margin_left=1, margin_top=1.3, margin_bottom=1.3, grow_x=True, selectable=False ), ), hover_shadow_radius=1, hover_shadow_color=self.session.theme.primary_color_darker , hover_fill=self.session.theme.primary_color_darker , corner_radius=0.1, cursor="pointer", transition_time=0.2 ), on_pointer_enter=self.on_pointer_enter, on_pointer_leave=self.on_pointer_leave, on_press=self.on_press ) class NavigationBar(Component): extension_state_changed: EventHandler[bool] is_extended: bool = False async def on_extension_pressed(self, _: PointerEvent) -> None: if self.session.is_mobile(): self.is_extended = not self.is_extended await self.call_event_handler(partial(self.extension_state_changed, self.is_extended)) self.force_refresh() def build(self) -> Component: navigation = Column( Column( NavigationButton("material/house", "Startseite", "/", extension_state_changed=self.on_extension_pressed), NavigationButton("material/local_activity", "Tickets", "/tickets", extension_state_changed=self.on_extension_pressed), NavigationButton("material/chair_alt", "Sitzplan", "/seating", extension_state_changed=self.on_extension_pressed), NavigationButton("material/group", "Teilnehmer", "/participants", extension_state_changed=self.on_extension_pressed), NavigationButton("material/local_dining", "Catering", "/catering", extension_state_changed=self.on_extension_pressed), NavigationButton("material/trophy", "Turniere", "/tournaments", extension_state_changed=self.on_extension_pressed), margin_bottom=6 ), Column( NavigationButton("material/help", "FAQ", "/faq", extension_state_changed=self.on_extension_pressed), NavigationButton("material/contact_page", "Kontakt", "mailto:tech@ezgg-ev.de?subject=Kontaktanfrage", new_tab=True, extension_state_changed=self.on_extension_pressed), NavigationButton("material/sports_bar", "EZ GG e.V.", "https://ezgg-ev.de", new_tab=True, extension_state_changed=None), NavigationButton("material/article", "Impressum", "/imprint", extension_state_changed=self.on_extension_pressed), NavigationButton("material/balance", "Regeln & AGB", "/rules", extension_state_changed=self.on_extension_pressed), ), Spacer(), Text(f"ELM v{self.session[ConfigurationService].APP_VERSION}", font_size=0.5, fill=self.session.theme.primary_color_darker), margin=1 ) if self.session.is_mobile(): return Rectangle( content=Column( Row( PointerEventListener( Rectangle( content=Icon("material/keyboard_double_arrow_left" if self.is_extended else "material/view_headline"), cursor="pointer", margin=0.5, min_height=1.5, min_width=1.5 ), on_press=self.on_extension_pressed ), Spacer() ), Spacer() if not self.is_extended else navigation, Spacer() ), fill=self.session.theme.box_color, stroke_width=0.1, stroke_color=self.session.theme.box_border_color, min_width=self.session.screen_width if self.is_extended else 2 ) else: # Tablet % Desktop return Rectangle( content=navigation, fill=self.session.theme.box_color, stroke_width=0.1, stroke_color=self.session.theme.box_border_color, min_width=20 )