diff --git a/code/modules/tgui/external.dm b/code/modules/tgui/external.dm index 88e7c90a0f..85b48569ba 100644 --- a/code/modules/tgui/external.dm +++ b/code/modules/tgui/external.dm @@ -36,6 +36,7 @@ * public * * Static Data to be sent to the UI. + * * Static data differs from normal data in that it's large data that should be * sent infrequently. This is implemented optionally for heavy uis that would * be sending a lot of redundant data frequently. Gets squished into one @@ -65,6 +66,17 @@ if(ui) ui.send_full_update() +/** + * public + * + * Will force an update on static data for all viewers. + * Should be done manually whenever something happens to + * change static data. + */ +/datum/proc/update_static_data_for_all_viewers() + for (var/datum/tgui/window as anything in open_uis) + window.send_full_update() + /** * public * @@ -130,7 +142,6 @@ * Associative list of JSON-encoded shared states that were set by * tgui clients. */ - /datum/var/list/tgui_shared_states /** @@ -194,8 +205,7 @@ // Name the verb, and hide it from the user panel. set name = "uiclose" set hidden = TRUE - - var/mob/user = src && src.mob + var/mob/user = src?.mob if(!user) return // Close all tgui datums based on window_id. diff --git a/code/modules/tgui/tgui.dm b/code/modules/tgui/tgui.dm index cf75db176c..fd45f9723d 100644 --- a/code/modules/tgui/tgui.dm +++ b/code/modules/tgui/tgui.dm @@ -11,7 +11,7 @@ var/mob/user /// The object which owns the UI. var/datum/src_object - /// The title of te UI. + /// The title of the UI. var/title /// The window_id for browse() and onclose(). var/datum/tgui_window/window @@ -76,22 +76,29 @@ if(ui_x && ui_y) src.window_size = list(ui_x, ui_y) +/datum/tgui/Destroy() + user = null + src_object = null + return ..() + /** * public * * Open this UI (and initialize it with data). + * + * return bool - TRUE if a new pooled window is opened, FALSE in all other situations including if a new pooled window didn't open because one already exists. */ /datum/tgui/proc/open() if(!user.client) - return null + return FALSE if(window) - return null + return FALSE process_status() if(status < STATUS_UPDATE) - return null + return FALSE window = SStgui.request_pooled_window(user) if(!window) - return null + return FALSE opened_at = world.time window.acquire_lock(src) if(!window.is_ready()) @@ -114,10 +121,14 @@ window.set_mouse_macro() SStgui.on_open(src) + return TRUE + /** * public * - * Close the UI, and all its children. + * Close the UI. + * + * optional can_be_suspended bool */ /datum/tgui/proc/close(can_be_suspended = TRUE, logout = FALSE) if(closing) @@ -146,7 +157,7 @@ * * Enable/disable auto-updating of the UI. * - * required autoupdate bool Enable/disable auto-updating. + * required value bool Enable/disable auto-updating. */ /datum/tgui/proc/set_autoupdate(autoupdate) src.autoupdate = autoupdate @@ -178,6 +189,8 @@ * Makes an asset available to use in tgui. * * required asset datum/asset + * + * return bool - true if an asset was actually sent */ /datum/tgui/proc/send_asset(datum/asset/asset) if(!window) @@ -282,14 +295,12 @@ return // Validate ping if(!initialized && world.time - opened_at > TGUI_PING_TIMEOUT) - // #ifdef TGUI_DEBUGGING // Always log zombie windows log_tgui(user, \ "Error: Zombie window detected, killing it with fire.\n" \ + "window_id: [window.id]\n" \ + "opened_at: [opened_at]\n" \ + "world.time: [world.time]") close(can_be_suspended = FALSE) - // #endif return // Update through a normal call to ui_interact if(status != STATUS_DISABLED && (autoupdate || force)) @@ -321,9 +332,7 @@ /** * private * - * Handle clicks from the UI. - * Call the src_object's ui_act() if status is UI_INTERACTIVE. - * If the src_object's ui_act() returns 1, update all UIs attacked to it. + * Callback for handling incoming tgui messages. */ /datum/tgui/proc/on_message(type, list/payload, list/href_list) // Pass act type messages to tgui_act diff --git a/code/modules/tgui/tgui_window.dm b/code/modules/tgui/tgui_window.dm index 73dfdf2803..62435ac30a 100644 --- a/code/modules/tgui/tgui_window.dm +++ b/code/modules/tgui/tgui_window.dm @@ -1,4 +1,4 @@ -/** +/*! * Copyright (c) 2020 Aleksej Komarov * SPDX-License-Identifier: MIT */ @@ -26,6 +26,18 @@ var/initial_inline_css var/mouse_event_macro_set = FALSE + /** + * Static list used to map in macros that will then emit execute events to the tgui window + * A small disclaimer though I'm no tech wiz: I don't think it's possible to map in right or middle + * clicks in the current state, as they're keywords rather than modifiers. + */ + var/static/list/byondToTguiEventMap = list( + "MouseDown" = "byond/mousedown", + "MouseUp" = "byond/mouseup", + "Ctrl" = "byond/ctrldown", + "Ctrl+UP" = "byond/ctrlup", + ) + /** * public * @@ -165,8 +177,8 @@ * Acquire the window lock. Pool will not be able to provide this window * to other UIs for the duration of the lock. * - * Can be given an optional tgui datum, which will hook its on_message - * callback into the message stream. + * Can be given an optional tgui datum, which will be automatically + * subscribed to incoming messages via the on_message proc. * * optional ui /datum/tgui */ @@ -175,6 +187,8 @@ locked_by = ui /** + * public + * * Release the window lock. */ /datum/tgui_window/proc/release_lock() @@ -391,11 +405,6 @@ if(mouse_event_macro_set) return - var/list/byondToTguiEventMap = list( - "MouseDown" = "byond/mousedown", - "MouseUp" = "byond/mouseup" - ) - for(var/mouseMacro in byondToTguiEventMap) var/command_template = ".output CONTROL PAYLOAD" var/event_message = TGUI_CREATE_MESSAGE(byondToTguiEventMap[mouseMacro], null) @@ -416,10 +425,6 @@ /datum/tgui_window/proc/remove_mouse_macro() if(!mouse_event_macro_set) stack_trace("Unsetting mouse macro on tgui window that has none") - var/list/byondToTguiEventMap = list( - "MouseDown" = "byond/mousedown", - "MouseUp" = "byond/mouseup" - ) for(var/mouseMacro in byondToTguiEventMap) winset(client, null, "[mouseMacro]Window[id]Macro.parent=null") mouse_event_macro_set = FALSE diff --git a/tgui/packages/tgui/interfaces/CharacterDirectory.jsx b/tgui/packages/tgui/interfaces/CharacterDirectory.jsx index 0f25f56bdf..18ffcba9d5 100644 --- a/tgui/packages/tgui/interfaces/CharacterDirectory.jsx +++ b/tgui/packages/tgui/interfaces/CharacterDirectory.jsx @@ -25,17 +25,21 @@ const getTagColor = (tag) => { export const CharacterDirectory = (props) => { const { act, data } = useBackend(); - const { personalVisibility, personalTag, personalErpTag } = data; const [overlay, setOverlay] = useState(null); - const [overwritePrefs, setOverwritePrefs] = useState(false); + function handleOverlay(value) { + setOverlay(value); + } + return ( - {(overlay && ) || ( + {(overlay && ( + + )) || ( <>
{
- + )}
@@ -101,43 +105,41 @@ export const CharacterDirectory = (props) => { }; const ViewCharacter = (props) => { - const [overlay, setOverlay] = useState(null); - return (
setOverlay(null)} + onClick={() => props.onOverlay(null)} /> } >
- {overlay.species} + {props.overlay.species}
- - {overlay.tag} + + {props.overlay.tag}
- {overlay.erptag} + {props.overlay.erptag}
- {overlay.character_ad || 'Unset.'} + {props.overlay.character_ad || 'Unset.'}
- {overlay.ooc_notes || 'Unset.'} + {props.overlay.ooc_notes || 'Unset.'}
- {overlay.flavor_text || 'Unset.'} + {props.overlay.flavor_text || 'Unset.'}
@@ -151,7 +153,6 @@ const CharacterDirectoryList = (props) => { const [sortId, _setSortId] = useState('name'); const [sortOrder, _setSortOrder] = useState('name'); - const [overlay, setOverlay] = useState(null); return (
{ {character.erptag}