StarRailCopilot/module/webui/base.py
2023-08-30 00:45:28 +08:00

170 lines
4.8 KiB
Python

from typing import Any, Dict
from pywebio.output import clear, put_html, put_scope, put_text, use_scope
from pywebio.session import defer_call, info, run_js
from module.webui.utils import Icon, WebIOTaskHandler, set_localstorage
class Base:
def __init__(self) -> None:
self.alive = True
# Whether window is visible
self.visible = True
# Device type
self.is_mobile = info.user_agent.is_mobile
# Task handler
self.task_handler = WebIOTaskHandler()
# Record scopes to reduce data transfer to frontend
# Key: scope name, value: last update time
self.scope: Dict[str, Any] = {}
defer_call(self.stop)
def stop(self) -> None:
self.alive = False
self.task_handler.stop()
def scope_clear(self):
self.scope = {}
def scope_add(self, key, value):
self.scope[key] = value
def scope_expired(self, key, value) -> bool:
try:
return self.scope[key] != value
except KeyError:
return True
def scope_expired_then_add(self, key, value) -> bool:
if self.scope_expired(key, value):
self.scope_add(key, value)
return True
else:
return False
class Frame(Base):
def __init__(self) -> None:
super().__init__()
self.page = "Home"
def init_aside(self, expand_menu: bool = True, name: str = None) -> None:
"""
Call this in aside button callback function.
Args:
expand_menu: expand menu
name: button name(label) to be highlight
"""
self.visible = True
self.scope_clear()
self.task_handler.remove_pending_task()
clear("menu")
if expand_menu:
self.expand_menu()
if name:
self.active_button("aside", name)
set_localstorage("aside", name)
def init_menu(self, collapse_menu: bool = True, name: str = None) -> None:
"""
Call this in menu button callback function.
Args:
collapse_menu: collapse menu
name: button name(label) to be highlight
"""
self.visible = True
self.page = name
self.scope_clear()
self.task_handler.remove_pending_task()
clear("content")
if collapse_menu:
self.collapse_menu()
if name:
self.active_button("menu", name)
@staticmethod
@use_scope("ROOT", clear=True)
def _show() -> None:
put_scope(
"header",
[
put_html(Icon.ALAS).style("--header-icon--"),
put_text("Alas").style("--header-text--"),
put_scope("header_status"),
put_scope("header_title"),
],
)
put_scope(
"contents",
[
put_scope("aside"),
put_scope("menu"),
put_scope("content"),
],
)
@staticmethod
@use_scope("header_title", clear=True)
def set_title(text=""):
put_text(text)
@staticmethod
def collapse_menu() -> None:
run_js(
f"""
$("#pywebio-scope-menu").addClass("container-menu-collapsed");
$(".container-content-collapsed").removeClass("container-content-collapsed");
"""
)
@staticmethod
def expand_menu() -> None:
run_js(
f"""
$(".container-menu-collapsed").removeClass("container-menu-collapsed");
$("#pywebio-scope-content").addClass("container-content-collapsed");
"""
)
@staticmethod
def active_button(position, value) -> None:
run_js(
f"""
$("button.btn-{position}").removeClass("btn-{position}-active");
$("div[style*='--{position}-{value}--']>button").addClass("btn-{position}-active");
"""
)
@staticmethod
def pin_set_invalid_mark(keys) -> None:
if isinstance(keys, str):
keys = [keys]
keys = ["_".join(key.split(".")) for key in keys]
js = "".join(
[
f"""$(".form-control[name='{key}']").addClass('is-invalid');"""
for key in keys
]
)
if js:
run_js(js)
# for key in keys:
# pin_update(key, valid_status=False)
@staticmethod
def pin_remove_invalid_mark(keys) -> None:
if isinstance(keys, str):
keys = [keys]
keys = ["_".join(key.split(".")) for key in keys]
js = "".join(
[
f"""$(".form-control[name='{key}']").removeClass('is-invalid');"""
for key in keys
]
)
if js:
run_js(js)
# for key in keys:
# pin_update(key, valid_status=0)