From c285ba20cc107af6c5ecda2715949bdb20e3123b Mon Sep 17 00:00:00 2001 From: John Smith Date: Sat, 16 Mar 2024 22:58:06 +0800 Subject: [PATCH] =?UTF-8?q?GUI=E6=8F=92=E4=BB=B6=E5=AE=8C=E6=88=90?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E7=AA=97=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- plugins/native-ui/config.py | 132 ++++++++++++++++++ plugins/native-ui/data/config.example.ini | 47 +++++++ plugins/native-ui/designer/native-ui.fbp | 155 ++------------------- plugins/native-ui/designer/ui_base.py | 47 ++++--- plugins/native-ui/main.pyw | 1 + plugins/native-ui/ui/app.py | 8 ++ plugins/native-ui/ui/room_config_dialog.py | 96 +++++++++++++ plugins/native-ui/ui/room_frame.py | 74 +++++++--- 8 files changed, 379 insertions(+), 181 deletions(-) create mode 100644 plugins/native-ui/data/config.example.ini create mode 100644 plugins/native-ui/ui/room_config_dialog.py diff --git a/plugins/native-ui/config.py b/plugins/native-ui/config.py index b0273fa..04e992a 100644 --- a/plugins/native-ui/config.py +++ b/plugins/native-ui/config.py @@ -1,5 +1,137 @@ # -*- coding: utf-8 -*- +import configparser +import logging import os +from typing import * + +import pubsub.pub as pub + +logger = logging.getLogger('native-ui.' + __name__) BASE_PATH = os.path.realpath(os.getcwd()) LOG_PATH = os.path.join(BASE_PATH, 'log') +DATA_PATH = os.path.join(BASE_PATH, 'data') + +SAVE_CONFIG_PATH = os.path.join(DATA_PATH, 'config.ini') +CONFIG_PATH_LIST = [ + SAVE_CONFIG_PATH, + os.path.join(DATA_PATH, 'config.example.ini') +] + +_config: Optional['AppConfig'] = None + + +def init(): + if reload(): + return + logger.warning('Using default config') + set_config(AppConfig()) + + +def reload(): + config_path = '' + for path in CONFIG_PATH_LIST: + if os.path.exists(path): + config_path = path + break + if config_path == '': + return False + + config = AppConfig() + if not config.load(config_path): + return False + + set_config(config) + return True + + +def get_config(): + return _config + + +def set_config(new_config: 'AppConfig'): + global _config + old_config = _config + _config = new_config + + if old_config is not None and new_config is not old_config: + pub.sendMessage('config_change', new_config=new_config, old_config=old_config) + + +class AppConfig: + def __init__(self): + self.room_opacity = 100 + + self.chat_url_params = self._get_default_url_params() + self.paid_url_params = self._get_default_url_params() + + @staticmethod + def _get_default_url_params(): + return { + 'minGiftPrice': '0', + 'showGiftName': 'true', + 'maxNumber': '200', + } + + def is_url_params_changed(self, other: 'AppConfig'): + return self.chat_url_params != other.chat_url_params or self.paid_url_params != other.paid_url_params + + def load(self, path): + try: + config = configparser.ConfigParser() + config.read(path, 'utf-8-sig') + + self._load_ui_config(config) + self._load_url_params(config) + except Exception: # noqa + logger.exception('Failed to load config:') + return False + return True + + def save(self, path): + try: + config = configparser.ConfigParser() + + self._save_ui_config(config) + self._save_url_params(config) + + tmp_path = path + '.tmp' + with open(tmp_path, 'w', encoding='utf-8-sig') as f: + config.write(f) + os.replace(tmp_path, path) + except Exception: # noqa + logger.exception('Failed to save config:') + return False + return True + + def _load_ui_config(self, config: configparser.ConfigParser): + ui_section = config['ui'] + self.room_opacity = ui_section.getint('room_opacity', self.room_opacity) + + def _save_ui_config(self, config: configparser.ConfigParser): + config['ui'] = { + 'room_opacity': str(self.room_opacity), + } + + def _load_url_params(self, config: configparser.ConfigParser): + self.chat_url_params = self._section_to_url_params(config['chat_url_params']) + self.paid_url_params = self._section_to_url_params(config['paid_url_params']) + + @staticmethod + def _section_to_url_params(section: configparser.SectionProxy): + params = {} + for line in section.values(): + key, _, value = line.partition('=') + params[key.strip()] = value.strip() + return params + + def _save_url_params(self, config: configparser.ConfigParser): + config['chat_url_params'] = self._url_params_to_section(self.chat_url_params) + config['paid_url_params'] = self._url_params_to_section(self.paid_url_params) + + @staticmethod + def _url_params_to_section(url_params: dict): + return { + str(index): f'{key} = {value}' + for index, (key, value) in enumerate(url_params.items(), 1) + } diff --git a/plugins/native-ui/data/config.example.ini b/plugins/native-ui/data/config.example.ini new file mode 100644 index 0000000..1af6b4f --- /dev/null +++ b/plugins/native-ui/data/config.example.ini @@ -0,0 +1,47 @@ +# 如果要修改配置,可以复制此文件并重命名为“config.ini”再修改 + +[ui] +# 房间窗口不透明度 +room_opacity = 100 + + +# 评论栏浏览器URL中的参数 +[chat_url_params] +# --- 这些参数不可改变 --- +# 通过服务器转发消息 +# 1 = relayMessagesByServer = true + +# --- 这些参数可以在UI中设置 --- +# 自动翻译弹幕到日语 +1 = autoTranslate = false +# 标注打赏用户名读音 +2 = giftUsernamePronunciation = +# 最低显示打赏价格(元) +3 = minGiftPrice = 0 +# 屏蔽礼物弹幕 +4 = blockGiftDanmaku = true + +# --- 其他的参数自己发挥 --- +# 显示礼物名 +5 = showGiftName = true +# 最大弹幕数 +6 = maxNumber = 200 + + +# 付费消息浏览器URL中的参数 +[paid_url_params] +# --- 这些参数不可改变 --- +# 通过服务器转发消息 +# 1 = relayMessagesByServer = true +# 显示弹幕 +# 2 = showDanmaku = false + +# --- 这些参数可以在UI中设置 --- +1 = autoTranslate = false +2 = giftUsernamePronunciation = +3 = minGiftPrice = 0 +4 = blockGiftDanmaku = true + +# --- 其他的参数自己发挥 --- +5 = showGiftName = true +6 = maxNumber = 200 diff --git a/plugins/native-ui/designer/native-ui.fbp b/plugins/native-ui/designer/native-ui.fbp index 29f7f77..556e39c 100644 --- a/plugins/native-ui/designer/native-ui.fbp +++ b/plugins/native-ui/designer/native-ui.fbp @@ -443,7 +443,7 @@ 付费消息 - 0 + 1 1 1 @@ -824,7 +824,7 @@ 统计 - 1 + 0 1 1 @@ -1134,7 +1134,7 @@ RoomConfigDialogBase -1,-1 - wxDEFAULT_DIALOG_STYLE + wxDEFAULT_DIALOG_STYLE|wxDIALOG_NO_PARENT ; ; forward_declare 房间设置 @@ -1288,7 +1288,7 @@ Resizable 1 - -1,-1 + 200,-1 wxSL_HORIZONTAL ; ; forward_declare 0 @@ -1301,6 +1301,7 @@ + _on_opacity_slider_change @@ -1472,7 +1473,7 @@ 0 1 - auto_translate_label1 + gift_pron_label 1 @@ -1503,9 +1504,9 @@ none 5 - wxALL - 0 - + wxALL|wxEXPAND + 1 + 1 1 1 @@ -1519,6 +1520,7 @@ 1 0 + "不显示" "拼音" "日文假名" 1 1 @@ -1534,7 +1536,6 @@ 0 0 wxID_ANY - 不显示 0 @@ -1542,72 +1543,7 @@ 0 1 - gift_pron_none_radio - 1 - - - protected - 1 - - Resizable - 1 - - wxRB_GROUP - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - 1 - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - 拼音 - - 0 - - - 0 - - 1 - gift_pron_pinyin_radio + gift_pron_choice 1 @@ -1615,6 +1551,7 @@ 1 Resizable + 0 1 @@ -1625,72 +1562,6 @@ wxFILTER_NONE wxDefaultValidator - 0 - - - - - - - 5 - wxALL - 0 - - 1 - 1 - 1 - 1 - - - - - - - - 1 - 0 - 1 - - 1 - 0 - Dock - 0 - Left - 0 - 1 - - 1 - - 0 - 0 - wxID_ANY - 日文假名 - - 0 - - - 0 - - 1 - gift_pron_kana_radio - 1 - - - protected - 1 - - Resizable - 1 - - - ; ; forward_declare - 0 - - - wxFILTER_NONE - wxDefaultValidator - - 0 @@ -2079,6 +1950,7 @@ + _on_ok @@ -2153,6 +2025,7 @@ + _on_cancel diff --git a/plugins/native-ui/designer/ui_base.py b/plugins/native-ui/designer/ui_base.py index 60d6929..c2fb0d9 100644 --- a/plugins/native-ui/designer/ui_base.py +++ b/plugins/native-ui/designer/ui_base.py @@ -64,7 +64,7 @@ class RoomFrameBase ( wx.Frame ): self.paid_panel.SetSizer( bSizer4 ) self.paid_panel.Layout() bSizer4.Fit( self.paid_panel ) - self.console_notebook.AddPage( self.paid_panel, u"付费消息", False ) + self.console_notebook.AddPage( self.paid_panel, u"付费消息", True ) self.super_chat_panel = wx.Panel( self.console_notebook, wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, wx.TAB_TRAVERSAL ) bSizer5 = wx.BoxSizer( wx.VERTICAL ) @@ -115,7 +115,7 @@ class RoomFrameBase ( wx.Frame ): self.statistics_panel.SetSizer( bSizer7 ) self.statistics_panel.Layout() bSizer7.Fit( self.statistics_panel ) - self.console_notebook.AddPage( self.statistics_panel, u"统计", True ) + self.console_notebook.AddPage( self.statistics_panel, u"统计", False ) bSizer1.Add( self.console_notebook, 1, wx.EXPAND, 5 ) @@ -160,7 +160,7 @@ class RoomFrameBase ( wx.Frame ): class RoomConfigDialogBase ( wx.Dialog ): def __init__( self, parent ): - wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"房间设置", pos = wx.DefaultPosition, size = wx.Size( -1,-1 ), style = wx.DEFAULT_DIALOG_STYLE ) + wx.Dialog.__init__ ( self, parent, id = wx.ID_ANY, title = u"房间设置", pos = wx.DefaultPosition, size = wx.Size( -1,-1 ), style = wx.DEFAULT_DIALOG_STYLE|wx.DIALOG_NO_PARENT ) self.SetSizeHints( wx.DefaultSize, wx.DefaultSize ) @@ -177,7 +177,7 @@ class RoomConfigDialogBase ( wx.Dialog ): fgSizer1.Add( self.opacity_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5 ) - self.opacity_slider = wx.Slider( sbSizer1.GetStaticBox(), wx.ID_ANY, 100, 10, 100, wx.DefaultPosition, wx.Size( -1,-1 ), wx.SL_HORIZONTAL ) + self.opacity_slider = wx.Slider( sbSizer1.GetStaticBox(), wx.ID_ANY, 100, 10, 100, wx.DefaultPosition, wx.Size( 200,-1 ), wx.SL_HORIZONTAL ) fgSizer1.Add( self.opacity_slider, 1, wx.ALL|wx.EXPAND, 5 ) self.auto_translate_label = wx.StaticText( sbSizer1.GetStaticBox(), wx.ID_ANY, u"自动翻译弹幕到日语", wx.DefaultPosition, wx.DefaultSize, 0 ) @@ -188,22 +188,17 @@ class RoomConfigDialogBase ( wx.Dialog ): self.auto_translate_check = wx.CheckBox( sbSizer1.GetStaticBox(), wx.ID_ANY, wx.EmptyString, wx.DefaultPosition, wx.DefaultSize, 0 ) fgSizer1.Add( self.auto_translate_check, 1, wx.ALL|wx.EXPAND, 5 ) - self.auto_translate_label1 = wx.StaticText( sbSizer1.GetStaticBox(), wx.ID_ANY, u"标注打赏用户名读音", wx.DefaultPosition, wx.DefaultSize, 0 ) - self.auto_translate_label1.Wrap( -1 ) + self.gift_pron_label = wx.StaticText( sbSizer1.GetStaticBox(), wx.ID_ANY, u"标注打赏用户名读音", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.gift_pron_label.Wrap( -1 ) - fgSizer1.Add( self.auto_translate_label1, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5 ) + fgSizer1.Add( self.gift_pron_label, 0, wx.ALIGN_CENTER_VERTICAL|wx.ALIGN_RIGHT|wx.ALL, 5 ) bSizer2 = wx.BoxSizer( wx.HORIZONTAL ) - self.gift_pron_none_radio = wx.RadioButton( sbSizer1.GetStaticBox(), wx.ID_ANY, u"不显示", wx.DefaultPosition, wx.DefaultSize, wx.RB_GROUP ) - self.gift_pron_none_radio.SetValue( True ) - bSizer2.Add( self.gift_pron_none_radio, 0, wx.ALL, 5 ) - - self.gift_pron_pinyin_radio = wx.RadioButton( sbSizer1.GetStaticBox(), wx.ID_ANY, u"拼音", wx.DefaultPosition, wx.DefaultSize, 0 ) - bSizer2.Add( self.gift_pron_pinyin_radio, 0, wx.ALL, 5 ) - - self.gift_pron_kana_radio = wx.RadioButton( sbSizer1.GetStaticBox(), wx.ID_ANY, u"日文假名", wx.DefaultPosition, wx.DefaultSize, 0 ) - bSizer2.Add( self.gift_pron_kana_radio, 0, wx.ALL, 5 ) + gift_pron_choiceChoices = [ u"不显示", u"拼音", u"日文假名" ] + self.gift_pron_choice = wx.Choice( sbSizer1.GetStaticBox(), wx.ID_ANY, wx.DefaultPosition, wx.DefaultSize, gift_pron_choiceChoices, 0 ) + self.gift_pron_choice.SetSelection( 0 ) + bSizer2.Add( self.gift_pron_choice, 1, wx.ALL|wx.EXPAND, 5 ) fgSizer1.Add( bSizer2, 1, wx.ALL|wx.EXPAND, 5 ) @@ -250,12 +245,12 @@ class RoomConfigDialogBase ( wx.Dialog ): bSizer3.Add( ( 0, 0), 1, wx.EXPAND, 5 ) - self.ok_button = wx.Button( self, wx.ID_ANY, u"确定", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.ok_button = wx.Button( self, wx.ID_OK, u"确定", wx.DefaultPosition, wx.DefaultSize, 0 ) self.ok_button.SetDefault() bSizer3.Add( self.ok_button, 0, wx.ALL, 5 ) - self.cancel_button = wx.Button( self, wx.ID_ANY, u"取消", wx.DefaultPosition, wx.DefaultSize, 0 ) + self.cancel_button = wx.Button( self, wx.ID_CANCEL, u"取消", wx.DefaultPosition, wx.DefaultSize, 0 ) bSizer3.Add( self.cancel_button, 0, wx.ALL, 5 ) @@ -268,7 +263,23 @@ class RoomConfigDialogBase ( wx.Dialog ): self.Centre( wx.BOTH ) + # Connect Events + self.opacity_slider.Bind( wx.EVT_SLIDER, self._on_opacity_slider_change ) + self.ok_button.Bind( wx.EVT_BUTTON, self._on_ok ) + self.cancel_button.Bind( wx.EVT_BUTTON, self._on_cancel ) + def __del__( self ): pass + # Virtual event handlers, override them in your derived class + def _on_opacity_slider_change( self, event ): + event.Skip() + + def _on_ok( self, event ): + event.Skip() + + def _on_cancel( self, event ): + event.Skip() + + diff --git a/plugins/native-ui/main.pyw b/plugins/native-ui/main.pyw index c4a29be..0b23921 100755 --- a/plugins/native-ui/main.pyw +++ b/plugins/native-ui/main.pyw @@ -29,6 +29,7 @@ async def init(): init_signal_handlers() init_logging() + config.init() await blcsdk.init() if not blcsdk.is_sdk_version_compatible(): diff --git a/plugins/native-ui/ui/app.py b/plugins/native-ui/ui/app.py index 2b4e096..b9c701f 100644 --- a/plugins/native-ui/ui/app.py +++ b/plugins/native-ui/ui/app.py @@ -7,6 +7,7 @@ import wxasync import blcsdk.models as sdk_models import listener +import ui.room_config_dialog import ui.room_frame logger = logging.getLogger('native-ui.' + __name__) @@ -25,12 +26,14 @@ class App(wxasync.WxAsyncApp): self.SetExitOnFrameDelete(False) self._key_room_frame_dict: Dict[sdk_models.RoomKey, ui.room_frame.RoomFrame] = {} + self._room_config_dialog: Optional[ui.room_config_dialog.RoomConfigDialog] = None def OnInit(self): pub.subscribe(self._on_add_room, 'add_room') pub.subscribe(self._on_del_room, 'del_room') pub.subscribe(self._on_room_frame_close, 'room_frame_close') pub.subscribe(self._on_open_admin_ui, 'open_admin_ui') + pub.subscribe(self._on_open_room_config_dialog, 'open_room_config_dialog') return True def _on_add_room(self, room_key: sdk_models.RoomKey): @@ -51,3 +54,8 @@ class App(wxasync.WxAsyncApp): def _on_open_admin_ui(self): for room in listener.iter_rooms(): self._on_add_room(room.room_key) + + def _on_open_room_config_dialog(self): + if self._room_config_dialog is None or self._room_config_dialog.IsBeingDeleted(): + self._room_config_dialog = ui.room_config_dialog.RoomConfigDialog(None) + self._room_config_dialog.Show() diff --git a/plugins/native-ui/ui/room_config_dialog.py b/plugins/native-ui/ui/room_config_dialog.py new file mode 100644 index 0000000..4e7605b --- /dev/null +++ b/plugins/native-ui/ui/room_config_dialog.py @@ -0,0 +1,96 @@ +# -*- coding: utf-8 -*- +import copy +import logging +from typing import * + +import pubsub.pub as pub +import wx + +import config +import designer.ui_base + +logger = logging.getLogger('native-ui.' + __name__) + + +class RoomConfigDialog(designer.ui_base.RoomConfigDialogBase): + _GIFT_PRON_CHOICES = ('', 'pinyin', 'kana') + + def __init__(self, parent): + super().__init__(parent) + + self._new_cfg_cache: Optional[config.AppConfig] = None + + def TransferDataToWindow(self): + cfg = config.get_config() + url_params: dict = cfg.chat_url_params + + self.opacity_slider.SetValue(cfg.room_opacity) + self.auto_translate_check.SetValue(self._to_bool(url_params.get('autoTranslate', 'false'))) + try: + gift_pron_index = self._GIFT_PRON_CHOICES.index(url_params.get('giftUsernamePronunciation', '')) + except ValueError: + gift_pron_index = 0 + self.gift_pron_choice.SetSelection(gift_pron_index) + self.min_gift_price_edit.SetValue(url_params.get('minGiftPrice', '0')) + self.block_gift_danmaku_check.SetValue(self._to_bool(url_params.get('blockGiftDanmaku', 'true'))) + + return super().TransferDataToWindow() + + def _on_ok(self, event): + try: + self._new_cfg_cache = self._create_config_from_window() + except Exception as e: + logger.exception('_create_config_from_window failed:') + wx.MessageBox(str(e), '应用设置失败', wx.OK | wx.ICON_ERROR | wx.CENTRE, self) + return + + if ( + self._new_cfg_cache.is_url_params_changed(config.get_config()) + and wx.MessageBox( + '修改部分设置需要刷新浏览器,是否继续?', '提示', wx.YES_NO | wx.CENTRE, self + ) != wx.YES + ): + return + super()._on_ok(event) + + def _create_config_from_window(self): + cfg = copy.deepcopy(config.get_config()) + + cfg.room_opacity = self.opacity_slider.GetValue() + url_params = { + 'autoTranslate': self._bool_to_str(self.auto_translate_check.GetValue()), + 'giftUsernamePronunciation': self._GIFT_PRON_CHOICES[self.gift_pron_choice.GetSelection()], + 'minGiftPrice': self.min_gift_price_edit.GetValue(), + 'blockGiftDanmaku': self._bool_to_str(self.block_gift_danmaku_check.GetValue()), + } + cfg.chat_url_params.update(url_params) + cfg.paid_url_params.update(url_params) + + return cfg + + def TransferDataFromWindow(self): + if self._new_cfg_cache is None: + logger.warning('_new_cfg_cache is None') + return False + + config.set_config(self._new_cfg_cache) + wx.CallAfter(self._new_cfg_cache.save, config.SAVE_CONFIG_PATH) + + return super().TransferDataFromWindow() + + def _on_cancel(self, event): + pub.sendMessage('room_config_dialog_cancel') + super()._on_cancel(event) + + @staticmethod + def _to_bool(value): + if isinstance(value, str): + return value.lower() not in ('false', 'no', 'off', '0', '') + return bool(value) + + @staticmethod + def _bool_to_str(value): + return 'true' if value else 'false' + + def _on_opacity_slider_change(self, event): + pub.sendMessage('preview_room_opacity', room_opacity=self.opacity_slider.GetValue()) diff --git a/plugins/native-ui/ui/room_frame.py b/plugins/native-ui/ui/room_frame.py index 985dde4..b18fbc3 100644 --- a/plugins/native-ui/ui/room_frame.py +++ b/plugins/native-ui/ui/room_frame.py @@ -10,6 +10,7 @@ import xlsxwriter.exceptions import blcsdk import blcsdk.models as sdk_models +import config import designer.ui_base import listener @@ -25,10 +26,7 @@ class RoomFrame(designer.ui_base.RoomFrameBase): room_str = str(room.room_id) if room is not None else str(self._room_key) self.SetTitle(f'blivechat - 房间 {room_str}') - room_params = {'minGiftPrice': 0, 'showGiftName': 'true'} - self.chat_web_view.LoadURL(self._get_room_url(room_params)) - room_params['showDanmaku'] = 'false' - self.paid_web_view.LoadURL(self._get_room_url(room_params)) + self._apply_config(True) self.super_chat_list.AppendColumn('时间', width=50) self.super_chat_list.AppendColumn('用户名', width=120) @@ -53,6 +51,9 @@ class RoomFrame(designer.ui_base.RoomFrameBase): for index in room.uid_paid_user_dict: self._on_uid_paid_user_dict_change(room, room.uid_paid_user_dict, index, True) + pub.subscribe(self._on_preview_room_opacity, 'preview_room_opacity') + pub.subscribe(self._on_room_config_dialog_cancel, 'room_config_dialog_cancel') + pub.subscribe(self._on_config_change, 'config_change') pub.subscribe(self._on_super_chats_change, 'room_data_change.super_chats') pub.subscribe(self._on_gifts_change, 'room_data_change.gifts') pub.subscribe(self._on_uid_paid_user_dict_change, 'room_data_change.uid_paid_user_dict') @@ -60,22 +61,8 @@ class RoomFrame(designer.ui_base.RoomFrameBase): pub.subscribe(self._on_simple_statistics_change, 'room_data_change.interact_uids') pub.subscribe(self._on_simple_statistics_change, 'room_data_change.total_paid_price') - def _get_room_url(self, params: dict): - params = params.copy() - params['roomKeyType'] = self._room_key.type.value - params['relayMessagesByServer'] = 'true' - - query = '&'.join( - f'{urllib.parse.quote_plus(key)}={urllib.parse.quote_plus(str(value))}' - for key, value in params.items() - ) - blc_port = blcsdk.get_blc_port() - encoded_room_key_value = urllib.parse.quote_plus(str(self._room_key.value)) - url = f'http://localhost:{blc_port}/room/{encoded_room_key_value}?{query}' - return url - # - # UI事件 + # 本窗口UI事件 # def _on_close(self, event): @@ -83,9 +70,7 @@ class RoomFrame(designer.ui_base.RoomFrameBase): super()._on_close(event) def _on_config_button_click(self, event): - # TODO WIP - dialog = designer.ui_base.RoomConfigDialogBase(self) - dialog.Show() + pub.sendMessage('open_room_config_dialog') def _on_stay_on_top_button_toggle(self, event: wx.CommandEvent): style = self.GetWindowStyle() @@ -161,6 +146,51 @@ class RoomFrame(designer.ui_base.RoomFrameBase): for row in range(row_num): yield [list_ctrl.GetItemText(row, col) for col in range(col_num)] + # + # 配置事件 + # + + def _on_preview_room_opacity(self, room_opacity): + self._set_opacity(room_opacity) + + def _set_opacity(self, opacity): + opacity = min(max(opacity, 10), 100) + alpha = round(opacity * wx.IMAGE_ALPHA_OPAQUE / 100) + return self.SetTransparent(alpha) + + def _on_room_config_dialog_cancel(self): + cfg = config.get_config() + self._set_opacity(cfg.room_opacity) + + def _on_config_change(self, new_config: config.AppConfig, old_config: config.AppConfig): + self._apply_config(new_config.is_url_params_changed(old_config)) + + def _apply_config(self, reload_web_views): + cfg = config.get_config() + self._set_opacity(cfg.room_opacity) + if reload_web_views: + self.chat_web_view.LoadURL(self._get_room_url(cfg.chat_url_params)) + self.paid_web_view.LoadURL(self._get_room_url(cfg.paid_url_params, {'showDanmaku': 'false'})) + + def _get_room_url(self, params: dict, override_params: Optional[dict] = None): + if override_params is None: + override_params = {} + params = { + **params, + 'roomKeyType': self._room_key.type.value, + 'relayMessagesByServer': 'true', + **override_params, + } + + query = '&'.join( + f'{urllib.parse.quote_plus(key)}={urllib.parse.quote_plus(str(value))}' + for key, value in params.items() + ) + blc_port = blcsdk.get_blc_port() + encoded_room_key_value = urllib.parse.quote_plus(str(self._room_key.value)) + url = f'http://localhost:{blc_port}/room/{encoded_room_key_value}?{query}' + return url + # # 模型事件 #