def show(self) -> None: self._show() self.init_aside(name="Home") self.set_aside() self.collapse_menu() self.alas_name = "" if hasattr(self, "alas"): del self.alas self.set_status(0) def set_language(l): lang.set_language(l) self.show() def set_theme(t): self.set_theme(t) run_js("location.reload()") with use_scope("content"): put_text("Select your language / 选择语言").style("text-align: center") put_buttons( [ {"label": "简体中文", "value": "zh-CN"}, {"label": "繁體中文", "value": "zh-TW"}, {"label": "English", "value": "en-US"}, {"label": "日本語", "value": "ja-JP"}, ], onclick=lambda l: set_language(l), ).style("text-align: center") put_text("Change theme / 更改主题").style("text-align: center") put_buttons( [ {"label": "Light", "value": "default", "color": "light"}, {"label": "Dark", "value": "dark", "color": "dark"}, ], onclick=lambda t: set_theme(t), ).style("text-align: center") # show something put_markdown( """ Alas is a free open source software, if you paid for Alas from any channel, please refund. Alas 是一款免费开源软件,如果你在任何渠道付费购买了Alas,请退款。 Project repository 项目地址:`https://github.com/LmeSzinc/AzurLaneAutoScript` """ ).style("text-align: center") if lang.TRANSLATE_MODE: lang.reload() def _disable(): lang.TRANSLATE_MODE = False self.show() toast( _t("Gui.Toast.DisableTranslateMode"), duration=0, position="right", onclick=_disable, )
def _force_restart(): if State.restart_event is not None: toast("Alas will restart in 3 seconds", duration=0, color="error") clearup() State.restart_event.set() else: toast("Reload not enabled", color="error")
async def main(): """PyWebIO聊天室 和当前所有在线的人聊天 """ global chat_msgs # run_js("alert('233')") put_markdown( "## PyWebIO聊天室\n欢迎来到聊天室,你可以和当前所有在线的人聊天。你可以在浏览器的多个标签页中打开本页面来测试聊天效果。" "本应用使用不到80行代码实现,源代码[链接](https://github.com/wang0618/PyWebIO/blob/dev/demos/chat_room.py)", lstrip=True) msg_box = output() put_scrollable(msg_box, height=300, keep_bottom=True) nickname = await input("请输入你的昵称", required=True, validate=lambda n: '昵称已被使用' if n in online_users or n == '📢' else None) online_users.add(nickname) chat_msgs.append( ('📢', '`%s`加入聊天室. 当前在线人数 %s' % (nickname, len(online_users)))) msg_box.append( put_markdown('`📢`: `%s`加入聊天室. 当前在线人数 %s' % (nickname, len(online_users)))) @defer_call def on_close(): online_users.remove(nickname) chat_msgs.append( ('📢', '`%s`退出聊天室. 当前在线人数 %s' % (nickname, len(online_users)))) refresh_task = run_async(refresh_msg(nickname, msg_box)) while True: data = await input_group( '发送消息', [ input(name='msg', help_text='消息内容支持行内Markdown语法'), actions( name='cmd', buttons=['发送', '多行输入', { 'label': '退出', 'type': 'cancel' }]) ], validate=lambda d: ('msg', '消息不为空') if d['cmd'] == '发送' and not d['msg'] else None) if data is None: break if data['cmd'] == '多行输入': data['msg'] = '\n' + await textarea( '消息内容', help_text='消息内容支持Markdown语法', required=True) msg_box.append( put_markdown('`%s`: %s' % (nickname, data['msg']), sanitize=True)) msg_box.append(put_markdown(str(chat_msgs), sanitize=True)) chat_msgs.append((nickname, data['msg'])) refresh_task.close() toast("你已经退出聊天室")
def login(password): if get_localstorage("password") == str(password): return True pwd = input(label="Please login below.", type=PASSWORD, placeholder="PASSWORD") if str(pwd) == str(password): set_localstorage("password", str(pwd)) return True else: toast("Wrong password!", color="error") return False
def login(password): if get_localstorage('password') == password: return True pwd = input(label='Please login below.', type=PASSWORD, placeholder='PASSWORD') if pwd == password: set_localstorage('password', pwd) return True else: toast('Wrong password!', color='error') return False
def _alas_thread_update_config(self) -> None: modified = {} valid = [] invalid = [] while self.alive: try: d = self.modified_config_queue.get(timeout=10) config_name = self.alas_name except queue.Empty: continue modified[self.idx_to_path[d["name"]]] = parse_pin_value(d["value"]) while True: try: d = self.modified_config_queue.get(timeout=1) modified[self.idx_to_path[d["name"]]] = parse_pin_value( d["value"]) except queue.Empty: config = read_file(filepath_config(config_name)) for k, v in modified.copy().items(): validate = deep_get(self.ALAS_ARGS, k + ".validate") if not len(str(v)): default = deep_get(self.ALAS_ARGS, k + ".value") deep_set(config, k, default) valid.append(self.path_to_idx[k]) modified[k] = default elif not validate or re_fullmatch(validate, v): deep_set(config, k, v) valid.append(self.path_to_idx[k]) else: modified.pop(k) invalid.append(self.path_to_idx[k]) logger.warning( f"Invalid value {v} for key {k}, skip saving.") # toast(t("Gui.Toast.InvalidConfigValue").format( # t('.'.join(k.split('.')[1:] + ['name']))), # duration=0, position='right', color='warn') self.pin_remove_invalid_mark(valid) self.pin_set_invalid_mark(invalid) if modified: toast( t("Gui.Toast.ConfigSaved"), duration=1, position="right", color="success", ) logger.info( f"Save config {filepath_config(config_name)}, {dict_to_kv(modified)}" ) write_file(filepath_config(config_name), config) modified.clear() valid.clear() invalid.clear() break
def _save_config(self, modified: Dict[str, str], config_name: str) -> None: try: valid = [] invalid = [] config = State.config_updater.read_file(config_name) for k, v in modified.copy().items(): valuetype = deep_get(self.ALAS_ARGS, k + ".valuetype") v = parse_pin_value(v, valuetype) validate = deep_get(self.ALAS_ARGS, k + ".validate") if not len(str(v)): default = deep_get(self.ALAS_ARGS, k + ".value") deep_set(config, k, default) valid.append(self.path_to_idx[k]) modified[k] = default elif not validate or re_fullmatch(validate, v): deep_set(config, k, v) valid.append(self.path_to_idx[k]) # update Emotion Record if Emotion Value is changed if "Emotion" in k and "Value" in k: k = k.split(".") k[-1] = k[-1].replace("Value", "Record") k = ".".join(k) v = datetime.now().strftime("%Y-%m-%d %H:%M:%S") modified[k] = v deep_set(config, k, v) valid.append(self.path_to_idx[k]) pin[self.path_to_idx[k]] = v else: modified.pop(k) invalid.append(self.path_to_idx[k]) logger.warning(f"Invalid value {v} for key {k}, skip saving.") self.pin_remove_invalid_mark(valid) self.pin_set_invalid_mark(invalid) if modified: toast( t("Gui.Toast.ConfigSaved"), duration=1, position="right", color="success", ) logger.info( f"Save config {filepath_config(config_name)}, {dict_to_kv(modified)}" ) State.config_updater.write_file(config_name, config) except Exception as e: logger.exception(e)
def run(self) -> None: # setup gui set_env(title="Alas", output_animation=False) add_css(filepath_css('alas')) if self.is_mobile: add_css(filepath_css('alas-mobile')) else: add_css(filepath_css('alas-pc')) if self.theme == 'dark': add_css(filepath_css('dark-alas')) else: add_css(filepath_css('light-alas')) # Auto refresh when lost connection # [For develop] Disable by run `reload=0` in console run_js(''' reload = 1; WebIO._state.CurrentSession.on_session_close( ()=>{ setTimeout( ()=>{ if (reload == 1){ location.reload(); } }, 4000 ) } ); ''') aside = get_localstorage('aside') self.show() # detect config change _thread_wait_config_change = Thread( target=self._alas_thread_wait_config_change) register_thread(_thread_wait_config_change) _thread_wait_config_change.start() # save config _thread_save_config = Thread(target=self._alas_thread_update_config) register_thread(_thread_save_config) _thread_save_config.start() visibility_state_switch = Switch(status={ True: [ lambda: self.__setattr__('visible', True), lambda: self.alas_update_overiew_task() if self.page == 'Overview' else 0, lambda: self.task_handler._task.__setattr__('delay', 15) ], False: [ lambda: self.__setattr__('visible', False), lambda: self.task_handler._task.__setattr__('delay', 1) ] }, get_state=get_window_visibility_state, name='visibility_state') self.state_switch = Switch( status=self.set_status, get_state=lambda: getattr(getattr(self, 'alas', -1), 'state', 0), name='state') def goto_update(): self.ui_develop() self.dev_update() update_switch = Switch(status={ 1: lambda: toast(t("Gui.Toast.ClickToUpdate"), duration=0, position='right', color='success', onclick=goto_update) }, get_state=lambda: updater.state, name='update_state') self.task_handler.add(self.state_switch.g(), 2) self.task_handler.add(visibility_state_switch.g(), 15) self.task_handler.add(update_switch.g(), 1) self.task_handler.start() # Return to previous page if aside not in ["Develop", "Home", None]: self.ui_alas(aside)
def show_text(): pout.toast("Button is clicked!", duration=10)
# # pout.put_code("""pin.select("Who's GOAT in NBA?", options=["Bryant", "Jordan", "James"])""") # pin.select("Who's GOAT in NBA?", options=["Bryant", "Jordan", "James"]) # # pout.put_code("""pin.radio("Are you ready to try pyWebIO?", options=["Yes", "No"])""") # pin.radio("Are you ready to try pyWebIO?", options=["Yes", "No"]) pout.put_text("This is an awesome library.") pout.put_table([("Col 1 Title", "Col 2 Title"), ("Row 1, Col 1", "Row 1, Col 2"), ("Row 2, Col 1", "Row 2, Col2")]) pout.put_markdown("# This is the Title") pout.put_markdown("## This is the Subtitle") pout.put_markdown("_Bold Text_") pout.put_markdown("__Italic Text__") pout.put_markdown("*__Bold & Italic__*") pout.put_markdown("[google.com](google.com)") pout.put_image(open("airplane.jpg", "rb").read()) pout.toast("Please Pay Attention!", duration=10) def show_text(): pout.toast("Button is clicked!", duration=10) pout.put_button("I'm Ready!", onclick=show_text) pout.toast("test")