mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-29 15:08:02 +01:00
TGUI say: Upgrades chat input with modern features (#23907)
* initial stuff (broken) * initial stuff (works) * fix most other things * fix thinking indicator * file name moment * contra review * better logs * snowball feedback * expanded drag handles * Update code/modules/tgui_input/say_modal/tgui_say_modal.dm Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com> * Update code/modules/tgui_input/say_modal/tgui_say_modal.dm Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com> * Drag handle * fix missing colours * TGUI rebuild (im clever) * Make msay useable by admins again (i hope) * fixed blacklist channel leaks due to lack of user eyes * clear old TGUIsay macros on keybind update * TGUI say tweaks * Update code/modules/tgui_input/say_modal/tgui_say_modal.dm * whisper is now a channel * remove placeholder, shorten width * tidies prefs, fix lightmode, refactor typing/thinking indicators * clarify more prefs * TG Typing Indicators and increace layer * modifiers? * makes the TGUI say macros serverside * add checks for muted stuff * dgamer review * fix talk and type issue * Update code/datums/keybindings/communication_keybinds.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> * review and binary stuff * Removes force say from TGUI say * updated * Apply suggestions from code review Co-authored-by: Aylong <69762909+AyIong@users.noreply.github.com> * remove verb * le rebuild * better behaviour on illegal entries --------- Co-authored-by: Aylong <alexanderkitsa@gmail.com> Co-authored-by: Contrabang <91113370+Contrabang@users.noreply.github.com> Co-authored-by: GDN <Roanrichards1@Gmail.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: Aylong <69762909+AyIong@users.noreply.github.com>
This commit is contained in:
co-authored by
Contrabang
Luc
Aylong
Aylong
GDN
parent
c120721cde
commit
3be2d5f8b6
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* Creates a JSON encoded message to open TGUI say modals properly.
|
||||
*
|
||||
* Arguments:
|
||||
* channel - The channel to open the modal in.
|
||||
* Returns:
|
||||
* string - A JSON encoded message to open the modal.
|
||||
*/
|
||||
/client/proc/tgui_say_create_open_command(channel)
|
||||
var/message = TGUI_CREATE_MESSAGE("open", list(
|
||||
channel = channel,
|
||||
))
|
||||
return "\".output tgui_say.browser:update [message]\""
|
||||
|
||||
/**
|
||||
* The tgui say modal. This initializes an input window which hides until
|
||||
* the user presses one of the speech hotkeys. Once something is entered, it will
|
||||
* delegate the speech to the proper channel.
|
||||
*/
|
||||
/datum/tgui_say
|
||||
/// The user who opened the window
|
||||
var/client/client
|
||||
/// The modal window
|
||||
var/datum/tgui_window/window
|
||||
/// Boolean for whether the tgui_say was opened by the user.
|
||||
var/window_open
|
||||
|
||||
/** Creates the new input window to exist in the background. */
|
||||
/datum/tgui_say/New(client/client, id)
|
||||
src.client = client
|
||||
window = new(client, id)
|
||||
winset(client, "tgui_say", "size=1,1;is-visible=0;")
|
||||
window.subscribe(src, PROC_REF(on_message))
|
||||
window.is_browser = TRUE
|
||||
|
||||
/**
|
||||
* After a brief period, injects the scripts into
|
||||
* the window to listen for open commands.
|
||||
*/
|
||||
/datum/tgui_say/proc/initialize()
|
||||
set waitfor = FALSE
|
||||
// Sleep to defer initialization to after client constructor
|
||||
sleep(3)
|
||||
window.initialize(
|
||||
strict_mode = TRUE,
|
||||
fancy = TRUE,
|
||||
inline_css = file("tgui/public/tgui-say.bundle.css"),
|
||||
inline_js = file("tgui/public/tgui-say.bundle.js"),
|
||||
);
|
||||
|
||||
/**
|
||||
* Ensures nothing funny is going on window load.
|
||||
* Minimizes the window, sets max length, closes all
|
||||
* typing and thinking indicators. This is triggered
|
||||
* as soon as the window sends the "ready" message.
|
||||
*/
|
||||
/datum/tgui_say/proc/load()
|
||||
window_open = FALSE
|
||||
winset(client, "tgui_say", "pos=848,500;size=275,30;is-visible=0;")
|
||||
window.send_message("props", list(
|
||||
"lightMode" = (client.prefs.toggles2 & PREFTOGGLE_2_ENABLE_TGUI_SAY_LIGHT_MODE),
|
||||
"maxLength" = MAX_MESSAGE_LEN,
|
||||
))
|
||||
stop_thinking()
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Sets the window as "opened" server side, though it is already
|
||||
* visible to the user. We do this to set local vars &
|
||||
* start typing (if enabled and in an IC channel).
|
||||
*
|
||||
* Arguments:
|
||||
* payload - A list containing the channel the window was opened in.
|
||||
*/
|
||||
/datum/tgui_say/proc/open(payload)
|
||||
if(!payload?["channel"])
|
||||
CRASH("No channel provided to an open TGUI-Say")
|
||||
window_open = TRUE
|
||||
switch(payload["channel"])
|
||||
if(ME_CHANNEL, RADIO_CHANNEL, SAY_CHANNEL, WHISPER_CHANNEL)
|
||||
start_thinking()
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Closes the window serverside. Closes any open chat bubbles
|
||||
* regardless of preference.
|
||||
*/
|
||||
/datum/tgui_say/proc/close()
|
||||
window_open = FALSE
|
||||
stop_thinking()
|
||||
stop_typing()
|
||||
|
||||
/**
|
||||
* The equivalent of ui_act, this waits on messages from the window
|
||||
* and delegates actions.
|
||||
*/
|
||||
/datum/tgui_say/proc/on_message(type, payload)
|
||||
switch(type)
|
||||
if("ready")
|
||||
load()
|
||||
return TRUE
|
||||
if("open")
|
||||
open(payload)
|
||||
return TRUE
|
||||
if("close")
|
||||
close()
|
||||
return TRUE
|
||||
if("thinking")
|
||||
if(payload["visible"] == TRUE)
|
||||
start_thinking()
|
||||
return TRUE
|
||||
if(payload["visible"] == FALSE)
|
||||
stop_thinking()
|
||||
return TRUE
|
||||
return FALSE
|
||||
if("typing")
|
||||
start_typing(payload["isMeChannel"])
|
||||
return TRUE
|
||||
if("entry")
|
||||
handle_entry(payload)
|
||||
return TRUE
|
||||
|
||||
return FALSE
|
||||
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Delegates the speech to the proper channel.
|
||||
*
|
||||
* Arguments:
|
||||
* entry - the text to broadcast
|
||||
* channel - the channel to broadcast in
|
||||
* Returns:
|
||||
* boolean - on success or failure
|
||||
*/
|
||||
/datum/tgui_say/proc/delegate_speech(entry, channel)
|
||||
switch(channel)
|
||||
if(SAY_CHANNEL)
|
||||
client.mob.say_verb(entry)
|
||||
return TRUE
|
||||
if(RADIO_CHANNEL)
|
||||
client.mob.say_verb((isliving(client.mob) ? ";" : "") + entry)
|
||||
return TRUE
|
||||
if(WHISPER_CHANNEL)
|
||||
client.mob.whisper(entry)
|
||||
return TRUE
|
||||
if(ME_CHANNEL)
|
||||
client.mob.me_verb(entry)
|
||||
return TRUE
|
||||
if(OOC_CHANNEL)
|
||||
client.ooc(entry)
|
||||
return TRUE
|
||||
if(LOOC_CHANNEL)
|
||||
client.looc(entry)
|
||||
return TRUE
|
||||
if(ADMIN_CHANNEL)
|
||||
client.cmd_admin_say(entry)
|
||||
return TRUE
|
||||
if(MENTOR_CHANNEL)
|
||||
client.cmd_mentor_say(entry)
|
||||
return TRUE
|
||||
if(DSAY_CHANNEL)
|
||||
client.dsay(entry)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/**
|
||||
* Handles text entry and forced speech.
|
||||
*
|
||||
* Arguments:
|
||||
* payload - a string list containing entry & channel
|
||||
* Returns:
|
||||
* boolean - success or failure
|
||||
*/
|
||||
/datum/tgui_say/proc/handle_entry(payload)
|
||||
if(!payload?["channel"] || !payload["entry"])
|
||||
var/hacker_man_ckey = usr.client.ckey
|
||||
qdel(usr.client)
|
||||
message_admins("[hacker_man_ckey] was kicked for attemping to send a null message to TGUI-say.")
|
||||
CRASH("[hacker_man_ckey] entered in a null payload to the chat window.")
|
||||
if(length(payload["entry"]) > MAX_MESSAGE_LEN)
|
||||
var/hacker_man_ckey = usr.client.ckey
|
||||
qdel(usr.client)
|
||||
message_admins("[hacker_man_ckey] was kicked for attemping to bypass TGUI-say character limits.")
|
||||
CRASH("[hacker_man_ckey] has entered more characters than allowed into a TGUI-Say.")
|
||||
delegate_speech(payload["entry"], payload["channel"])
|
||||
return TRUE
|
||||
@@ -0,0 +1,41 @@
|
||||
/** Sets the mob as "thinking" - with indicator */
|
||||
/datum/tgui_say/proc/start_thinking()
|
||||
if(!client?.mob || !window_open)
|
||||
return FALSE
|
||||
/// Special exemptions
|
||||
if(isabductor(client.mob))
|
||||
return FALSE
|
||||
client.mob.set_thinking_indicator(TRUE)
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_thinking)), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_STOPPABLE)
|
||||
|
||||
/** Removes typing/thinking indicators and flags the mob as not thinking */
|
||||
/datum/tgui_say/proc/stop_thinking()
|
||||
if(!client?.mob)
|
||||
return FALSE
|
||||
client.mob.set_thinking_indicator(FALSE)
|
||||
|
||||
/**
|
||||
* Handles the user typing. After a brief period of inactivity,
|
||||
* signals the client mob to revert to the "thinking" icon.
|
||||
*/
|
||||
/datum/tgui_say/proc/start_typing(me = FALSE)
|
||||
if(!client?.mob)
|
||||
return FALSE
|
||||
client.mob.set_typing_indicator(FALSE)
|
||||
client.mob.set_thinking_indicator(FALSE)
|
||||
if(!window_open)
|
||||
return FALSE
|
||||
client.mob.set_typing_indicator(TRUE, me)
|
||||
addtimer(CALLBACK(src, PROC_REF(stop_typing)), 5 SECONDS, TIMER_UNIQUE | TIMER_OVERRIDE | TIMER_STOPPABLE)
|
||||
|
||||
/**
|
||||
* Callback to remove the typing indicator after a brief period of inactivity.
|
||||
* If the user was typing IC, the thinking indicator is shown.
|
||||
*/
|
||||
/datum/tgui_say/proc/stop_typing()
|
||||
if(!client?.mob)
|
||||
return FALSE
|
||||
client.mob.set_typing_indicator(FALSE)
|
||||
if(!window_open)
|
||||
return FALSE
|
||||
client.mob.set_thinking_indicator(TRUE)
|
||||
Reference in New Issue
Block a user