[MIRROR] tgui say update (#10323)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-03-06 18:06:09 -07:00
committed by GitHub
parent a4493ca5ff
commit ab171de574
11 changed files with 118 additions and 33 deletions

View File

@@ -11,3 +11,5 @@
/// Simply removes the < and > characters, and limits the length of the message.
#define STRIP_HTML_SIMPLE(text, limit) (GLOB.angular_brackets.Replace(copytext(text, 1, limit), ""))
#define MAX_MESSAGE_CHUNKS 130

View File

@@ -45,6 +45,8 @@
var/datum/tgui/parent_ui
/// Children of this UI
var/list/children = list()
/// Any partial packets that we have received from TGUI, waiting to be sent
var/partial_packets
/**
* public
@@ -349,6 +351,28 @@
// Pass act type messages to tgui_act
if(type && copytext(type, 1, 5) == "act/")
var/act_type = copytext(type, 5)
var/id = href_list["packetId"]
if(!isnull(id))
id = text2num(id)
var/total = text2num(href_list["totalPackets"])
if(id == 1)
if(total > MAX_MESSAGE_CHUNKS)
return
partial_packets = new /list(total)
partial_packets[id] = href_list["packet"]
if(id != total)
return
var/assembled_payload = ""
for(var/packet in partial_packets)
assembled_payload += packet
payload = json_decode(assembled_payload)
partial_packets = null
#ifdef TGUI_DEBUGGING
log_tgui(user, "Action: [act_type] [href_list["payload"]], Window: [window.id], Source: [src_object]")
#endif

View File

@@ -31,6 +31,8 @@
var/datum/tgui_window/window
/// Boolean for whether the tgui_say was opened by the user.
var/window_open
/// Any partial packets that we have received from TGUI, waiting to be sent
var/partial_packets
/** Creates the new input window to exist in the background. */
/datum/tgui_say/New(client/client, id)
@@ -64,14 +66,14 @@
/datum/tgui_say/proc/load()
window_open = FALSE
var/minimum_height = client?.prefs?.read_preference(/datum/preference/numeric/tgui_say_height) || 1
var/minimu_width = client?.prefs?.read_preference(/datum/preference/numeric/tgui_say_width) || 1
var/minimum_width = client?.prefs?.read_preference(/datum/preference/numeric/tgui_say_width) || 1
var/minimum_height = (client?.prefs?.read_preference(/datum/preference/numeric/tgui_say_height) || 1) * 20 + 10
winset(client, "tgui_say", "pos=410,400;size=360,30;is-visible=0;")
window.send_message("props", list(
lightMode = client?.prefs?.read_preference(/datum/preference/toggle/tgui_say_light),
minimumWidth = minimum_width,
minimumHeight = minimum_height,
minimumWidth = minimu_width,
maxLength = max_length,
))
@@ -106,7 +108,7 @@
* The equivalent of ui_act, this waits on messages from the window
* and delegates actions.
*/
/datum/tgui_say/proc/on_message(type, payload)
/datum/tgui_say/proc/on_message(type, payload, href_list)
if(type == "ready")
load()
return TRUE
@@ -128,6 +130,28 @@
start_typing(payload["channel"])
return TRUE
if(type == "entry" || type == "force")
var/id = href_list["packetId"]
if(!isnull(id))
id = text2num(id)
var/total = text2num(href_list["totalPackets"])
if(id == 1)
if(total > MAX_MESSAGE_CHUNKS)
return
partial_packets = new /list(total)
partial_packets[id] = href_list["packet"]
if(id != total)
return
var/assembled_payload = ""
for(var/packet in partial_packets)
assembled_payload += packet
payload = json_decode(assembled_payload)
partial_packets = null
handle_entry(type, payload)
return TRUE
if(type == "lenwarn")

View File

@@ -15,7 +15,7 @@
* * encode - Toggling this determines if input is filtered via html_encode. Setting this to FALSE gives raw input.
* * timeout - The timeout of the textbox, after which the modal will close and qdel itself. Set to zero for no timeout.
*/
/proc/tgui_input_text(mob/user, message = "", title = "Text Input", default, max_length = INFINITY, multiline = FALSE, encode = FALSE, timeout = 0, prevent_enter = FALSE)
/proc/tgui_input_text(mob/user, message = "", title = "Text Input", default, max_length = 130000, multiline = FALSE, encode = FALSE, timeout = 0, prevent_enter = FALSE) // 130k limit due to chunking limit... if we need longer that needs fixing
if (!user)
user = usr
if (!istype(user))

View File

@@ -14,6 +14,7 @@ $border-color: rgba(140, 140, 140, 0.5) !default;
border-radius: 0.25em;
width: 3.75em;
text-align: right;
user-select: 'none';
}
.Ping__indicator {

View File

@@ -20,6 +20,8 @@ import { byondMessages } from './timers';
type ByondOpen = {
channel: Channel;
minimumWidth: number;
minimumHeight: number;
};
type ByondProps = {
@@ -287,8 +289,8 @@ export function TguiSay() {
function handleOpen(data: ByondOpen): void {
setTimeout(() => {
innerRef.current?.focus();
windowSet(WindowSize.Width, WindowSize.Small);
setSize(WindowSize.Width);
setSize(minimumHeight);
windowSet(minimumWidth, minimumHeight);
}, 1);
const { channel } = data;
@@ -339,7 +341,7 @@ export function TguiSay() {
} else {
newSize = WindowSize.Small;
}
newSize = clamp(newSize, minimumHeight * 20 + 10, WindowSize.Max);
newSize = clamp(newSize, minimumHeight, WindowSize.Max);
if (size !== newSize) {
setSize(newSize);
@@ -370,16 +372,24 @@ export function TguiSay() {
{buttonContent}
</button>
<textarea
spellCheck
autoCorrect="off"
className={`textarea textarea-${theme}`}
maxLength={maxLength}
onInput={handleInput}
onKeyDown={handleKeyDown}
ref={innerRef}
spellCheck={false}
rows={ROWS[size] || 1}
value={value}
/>
<button
key="escape"
className={`button button-${theme}`}
onClick={handleClose}
type="submit"
>
X
</button>
</div>
</>
);

View File

@@ -118,7 +118,7 @@
background-color: black;
display: grid;
font: 'tgfont';
grid-template-columns: 3.5rem 1fr;
grid-template-columns: 7rem 1fr 2rem;
inset: 2px;
overflow: hidden;
padding: 2px;

View File

@@ -33,6 +33,7 @@ export const COLORS = {
science: '#9b59b6',
engineering: '#f1c40f',
cargo: '#f39c12',
service: '#7cc46a',
centcom: '#00c100',
other: '#c38312',
},
@@ -66,24 +67,28 @@ export const COLORS = {
// Colors defined in CSS
export const CSS_COLORS = [
'black',
'white',
'red',
'orange',
'yellow',
'olive',
'green',
'teal',
'blue',
'violet',
'purple',
'pink',
'brown',
'grey',
'good',
'average',
'bad',
'black',
'blue',
'brown',
'darkgray',
'darkgreen',
'maroon',
'good',
'green',
'grey',
'label',
'olive',
'orange',
'pink',
'purple',
'red',
'teal',
'transparent',
'violet',
'white',
'yellow',
];
// VOREStation Edit Start

View File

@@ -591,10 +591,10 @@ const rank2color = {
'Off-duty Explorer': 'white',
'Off-duty Worker': 'white',
// AI / Robot
AI: 'darkgrey',
Cyborg: 'darkgrey',
Robot: 'darkgrey',
Drone: 'darkgrey',
AI: 'maroon',
Cyborg: 'maroon',
Robot: 'maroon',
Drone: 'maroon',
// Clown / Mime
Clown: 'green',
Jester: 'green',
@@ -627,11 +627,11 @@ const rank2color = {
Security: 'red',
Combat: 'yellow',
Engineering: 'orange',
Gravekeeper: 'dark-grey',
Gravekeeper: 'maroon',
Lost: 'grey',
Protector: 'darkred',
Mechanist: 'darkred',
'Combat Medic': 'darkred',
Protector: 'maroon',
Mechanist: 'maroon',
'Combat Medic': 'maroon',
};
type rank_icon = { rank: string; color: string };

View File

@@ -204,7 +204,25 @@
// JSON-encode the payload
if (message.payload !== null && message.payload !== undefined) {
message.payload = JSON.stringify(message.payload);
if(!Byond.TRIDENT && message.payload.length > 1024) {
var chunks = [];
for(var i = 0, charsLength = message.payload.length; i < charsLength; i += 1024) {
chunks.push(message.payload.substring(i, i + 1024))
}
for(var i = 0; i < chunks.length; i++) {
var to_send = chunks[i]
message = { type: type, packet: to_send, packetId: i + 1, totalPackets: chunks.length, tgui: 1, window_id: Byond.windowId };
Byond.topic(message);
}
return;
}
}
// Append an identifying header
assign(message, {
tgui: 1,

View File

@@ -152,6 +152,7 @@ export const IconCutterTarget = new Juke.Target({
'icons/**/*.png',
`icons/**/*${CUTTER_SUFFIX}`,
`cutter_templates/**/*${CUTTER_SUFFIX}`,
`tgui/public/tgui.html`,
cutter_path,
],
outputs: ({ get }) => {