146 lines
6.6 KiB
Python
146 lines
6.6 KiB
Python
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
|
|
)
|