some cute emotes
This commit is contained in:
141
src/IRCPanel.py
141
src/IRCPanel.py
@@ -38,12 +38,19 @@ class IRCPanel(wx.Panel):
|
||||
self.input_ctrl.SetHint("Type message here …")
|
||||
self.input_ctrl.Bind(wx.EVT_TEXT_ENTER, self.on_send)
|
||||
self.input_ctrl.Bind(wx.EVT_KEY_DOWN, self.on_key_down)
|
||||
|
||||
# Kaomoji picker button - inserts plain ASCII kaomojis into the input box
|
||||
self.kaomoji_btn = wx.Button(self, label="Emotes")
|
||||
self.kaomoji_btn.SetToolTip("Emotes :3")
|
||||
self.kaomoji_btn.Bind(wx.EVT_BUTTON, self.on_pick_kaomoji)
|
||||
|
||||
send_btn = wx.Button(self, label="Send")
|
||||
send_btn.SetToolTip("Send message (Enter)")
|
||||
send_btn.Bind(wx.EVT_BUTTON, self.on_send)
|
||||
|
||||
|
||||
# Order: input field, kaomoji, send
|
||||
input_sizer.Add(self.input_ctrl, 1, wx.EXPAND | wx.ALL, 2)
|
||||
input_sizer.Add(self.kaomoji_btn, 0, wx.ALL, 2)
|
||||
input_sizer.Add(send_btn, 0, wx.ALL, 2)
|
||||
|
||||
sizer.Add(input_sizer, 0, wx.EXPAND | wx.ALL, 0)
|
||||
@@ -365,6 +372,7 @@ class IRCPanel(wx.Panel):
|
||||
logger.error(f"Error in tab completion: {e}")
|
||||
|
||||
def on_send(self, event):
|
||||
"""Send the current input to the active IRC target."""
|
||||
try:
|
||||
message = self.input_ctrl.GetValue().strip()
|
||||
if message and self.target:
|
||||
@@ -374,3 +382,134 @@ class IRCPanel(wx.Panel):
|
||||
self.input_ctrl.Clear()
|
||||
except Exception as e:
|
||||
logger.error(f"Error sending message: {e}")
|
||||
|
||||
|
||||
def insert_text_at_caret(self, text):
|
||||
"""Insert given text at the current caret position in the input box."""
|
||||
try:
|
||||
current = self.input_ctrl.GetValue()
|
||||
pos = self.input_ctrl.GetInsertionPoint()
|
||||
new_value = current[:pos] + text + current[pos:]
|
||||
self.input_ctrl.SetValue(new_value)
|
||||
self.input_ctrl.SetInsertionPoint(pos + len(text))
|
||||
except Exception as e:
|
||||
logger.error(f"Error inserting text at caret: {e}")
|
||||
|
||||
def on_pick_kaomoji(self, event):
|
||||
"""Show a kaomoji popup next to the button and insert the chosen one.
|
||||
|
||||
All entries are ASCII-only so they are safe for any IRC server.
|
||||
"""
|
||||
try:
|
||||
choices = [
|
||||
":-)", ":)", ":-D", ":D", "^_^", "^o^", "(*^_^*)", "( ^_^)/", "(:3)", "=)", "=]", "^.^",
|
||||
":-(", ":'(", "T_T", ";_;", ">_<", "(-_-)", "(_ _)",
|
||||
">:(", ">:-(", ">:-O", ">.<", "(-_-)#",
|
||||
"<3", "(*^3^)", "(^^)v", "(X_X)", "(^_^)", "*^_^*",
|
||||
":-O", ":O", ":-0", "O_O", "o_O", "O_o",
|
||||
"-_-", "(-.-) zzz", "(~_~)", "zzz",
|
||||
r"¯\_(._.)_/¯", "(¬_¬)", "(*_*)", "(>_>)", "(<_<)",
|
||||
"OwO", "UwU", ">w<", "^w^", "^u^", "rawr x3", ":3", ":3c", "x3", "nya~", "n_n", "(>ω<)", ":33", "^3^",
|
||||
"^///^", "(//▽//)", "(*^///^*)", ">///<", "^_^;", "^///^;",
|
||||
"(*^▽^*)", "(*´▽`*)", "UwU~", "OwO~",
|
||||
":33", "x3", ":3~", ":3c", "owo", "uwu", "rawr", ":33p",
|
||||
"xD", ";-)", ";)", ":-P", ":P", ":-|", ":|", "(o_O)", "(O_o)", "('_')",
|
||||
]
|
||||
|
||||
ascii_choices = [c for c in choices if all(ord(ch) < 128 for ch in c)]
|
||||
if not ascii_choices:
|
||||
ascii_choices = [":)", ":D", ";)", ":P"]
|
||||
|
||||
popup = wx.PopupTransientWindow(self, wx.BORDER_SIMPLE)
|
||||
panel = wx.Panel(popup)
|
||||
sizer = wx.BoxSizer(wx.VERTICAL)
|
||||
listbox = wx.ListBox(panel, choices=ascii_choices, style=wx.LB_SINGLE)
|
||||
sizer.Add(listbox, 1, wx.EXPAND | wx.ALL, 4)
|
||||
panel.SetSizerAndFit(sizer)
|
||||
popup.SetClientSize(panel.GetBestSize())
|
||||
|
||||
# Keep a reference so the popup isn't GC'd
|
||||
self._kaomoji_popup = popup
|
||||
|
||||
def on_select(evt):
|
||||
"""Handle selection from the kaomoji list (keyboard or programmatic)."""
|
||||
# Ignore synthetic selection changes triggered only for hover visualization
|
||||
if getattr(self, "_suppress_kaomoji_select", False):
|
||||
return
|
||||
|
||||
try:
|
||||
idx = evt.GetSelection()
|
||||
except AttributeError:
|
||||
# Fallback for synthetic events where we used SetInt()
|
||||
idx = evt.GetInt() if hasattr(evt, "GetInt") else -1
|
||||
|
||||
try:
|
||||
if 0 <= idx < len(ascii_choices):
|
||||
choice = ascii_choices[idx]
|
||||
if choice:
|
||||
# Insert at current caret position, but DO NOT auto-send.
|
||||
current = self.input_ctrl.GetValue()
|
||||
pos = self.input_ctrl.GetInsertionPoint()
|
||||
needs_space = pos > 0 and not current[pos - 1].isspace()
|
||||
insert_text = (" " + choice) if needs_space else choice
|
||||
new_value = current[:pos] + insert_text + current[pos:]
|
||||
self.input_ctrl.SetValue(new_value)
|
||||
self.input_ctrl.SetInsertionPoint(pos + len(insert_text))
|
||||
finally:
|
||||
popup.Dismiss()
|
||||
|
||||
def on_left_click(evt):
|
||||
"""Single left-click handler for the kaomoji menu."""
|
||||
try:
|
||||
pos = evt.GetPosition()
|
||||
idx = listbox.HitTest(pos)
|
||||
if idx != wx.NOT_FOUND:
|
||||
# Ensure the item is selected, then reuse on_select logic
|
||||
listbox.SetSelection(idx)
|
||||
cmd_evt = wx.CommandEvent(wx.wxEVT_LISTBOX, listbox.GetId())
|
||||
cmd_evt.SetEventObject(listbox)
|
||||
cmd_evt.SetInt(idx)
|
||||
on_select(cmd_evt)
|
||||
else:
|
||||
evt.Skip()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in kaomoji left-click handler: {e}")
|
||||
|
||||
def on_motion(evt):
|
||||
"""Visual hover selector so the current row is highlighted."""
|
||||
try:
|
||||
pos = evt.GetPosition()
|
||||
idx = listbox.HitTest(pos)
|
||||
current_sel = listbox.GetSelection()
|
||||
|
||||
if idx != wx.NOT_FOUND and idx != current_sel:
|
||||
# Temporarily suppress on_select so hover highlight doesn't send
|
||||
self._suppress_kaomoji_select = True
|
||||
try:
|
||||
listbox.SetSelection(idx)
|
||||
finally:
|
||||
self._suppress_kaomoji_select = False
|
||||
elif idx == wx.NOT_FOUND:
|
||||
# Optionally clear selection when hovering outside items
|
||||
self._suppress_kaomoji_select = True
|
||||
try:
|
||||
listbox.DeselectAll()
|
||||
finally:
|
||||
self._suppress_kaomoji_select = False
|
||||
except Exception as e:
|
||||
logger.error(f"Error in kaomoji hover handler: {e}")
|
||||
finally:
|
||||
evt.Skip()
|
||||
|
||||
# Single left-click selects and sends; keyboard selection still works
|
||||
listbox.Bind(wx.EVT_LISTBOX, on_select)
|
||||
listbox.Bind(wx.EVT_LEFT_DOWN, on_left_click)
|
||||
listbox.Bind(wx.EVT_MOTION, on_motion)
|
||||
|
||||
# Position popup under the kaomoji button
|
||||
btn = self.kaomoji_btn
|
||||
btn_pos = btn.ClientToScreen((0, btn.GetSize().height))
|
||||
popup.Position(btn_pos, (0, 0))
|
||||
popup.Popup()
|
||||
except Exception as e:
|
||||
logger.error(f"Error in kaomoji picker: {e}")
|
||||
@@ -229,24 +229,41 @@ class ScanWizardResultsPage(adv.WizardPageSimple):
|
||||
start_callback(params)
|
||||
|
||||
def on_scan_progress(self, scanned, total):
|
||||
total = max(total, 1)
|
||||
self.gauge.SetRange(total)
|
||||
self.gauge.SetValue(min(scanned, total))
|
||||
self.summary.SetLabel(f"Scanning… {scanned}/{total} hosts checked")
|
||||
try:
|
||||
total = max(total, 1)
|
||||
self.gauge.SetRange(total)
|
||||
self.gauge.SetValue(min(scanned, total))
|
||||
self.summary.SetLabel(f"Scanning… {scanned}/{total} hosts checked")
|
||||
except RuntimeError:
|
||||
# C++ SHIT
|
||||
logger.debug("Scan progress update after controls destroyed; ignoring")
|
||||
|
||||
def on_scan_result(self, server_info):
|
||||
idx = self.results_list.InsertItem(self.results_list.GetItemCount(), server_info["address"])
|
||||
self.results_list.SetItem(idx, 1, str(server_info["port"]))
|
||||
self.results_list.SetItem(idx, 2, server_info.get("banner", "IRC server detected"))
|
||||
self.discovered.append(server_info)
|
||||
self.summary.SetLabel(f"Found {len(self.discovered)} {"server" if self.discovered == 1 else "servers"}")
|
||||
"""Handle a single discovered server row."""
|
||||
try:
|
||||
idx = self.results_list.InsertItem(self.results_list.GetItemCount(), server_info["address"])
|
||||
self.results_list.SetItem(idx, 1, str(server_info["port"]))
|
||||
self.results_list.SetItem(idx, 2, server_info.get("banner", "IRC server detected"))
|
||||
self.discovered.append(server_info)
|
||||
self.summary.SetLabel(
|
||||
f"Found {len(self.discovered)} {'server' if len(self.discovered) == 1 else 'servers'}"
|
||||
)
|
||||
except RuntimeError:
|
||||
logger.debug("Scan result update after controls destroyed; ignoring")
|
||||
|
||||
def on_scan_complete(self, results):
|
||||
if results:
|
||||
self.summary.SetLabel(f"Scan complete : {len(results)} {"server" if len(results) == 1 else "servers"} ready.")
|
||||
else:
|
||||
self.summary.SetLabel("Scan complete : no IRC servers discovered.")
|
||||
self._toggle_buttons()
|
||||
"""Final scan completion callback."""
|
||||
try:
|
||||
if results:
|
||||
self.summary.SetLabel(
|
||||
f"Scan complete : {len(results)} "
|
||||
f"{'server' if len(results) == 1 else 'servers'} ready."
|
||||
)
|
||||
else:
|
||||
self.summary.SetLabel("Scan complete : no IRC servers discovered.")
|
||||
self._toggle_buttons()
|
||||
except RuntimeError:
|
||||
logger.debug("Scan completion update after controls destroyed; ignoring")
|
||||
|
||||
def on_quick_connect(self, event):
|
||||
row = self.results_list.GetFirstSelected()
|
||||
|
||||
Reference in New Issue
Block a user