Fixed CharacterDirectory (#15757)

This commit is contained in:
Selis
2024-02-12 14:17:31 +01:00
committed by GitHub
parent cc7bf56ae5
commit 66d4b40e9d
8 changed files with 250 additions and 222 deletions
+13 -3
View File
@@ -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.
+21 -12
View File
@@ -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
+17 -12
View File
@@ -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
@@ -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 (
<Window width={640} height={480} resizeable>
<Window.Content scrollable>
{(overlay && <ViewCharacter />) || (
{(overlay && (
<ViewCharacter overlay={overlay} onOverlay={handleOverlay} />
)) || (
<>
<Section
title="Controls"
@@ -92,7 +96,7 @@ export const CharacterDirectory = (props) => {
</LabeledList.Item>
</LabeledList>
</Section>
<CharacterDirectoryList />
<CharacterDirectoryList onOverlay={handleOverlay} />
</>
)}
</Window.Content>
@@ -101,43 +105,41 @@ export const CharacterDirectory = (props) => {
};
const ViewCharacter = (props) => {
const [overlay, setOverlay] = useState(null);
return (
<Section
title={overlay.name}
title={props.overlay.name}
buttons={
<Button
icon="arrow-left"
content="Back"
onClick={() => setOverlay(null)}
onClick={() => props.onOverlay(null)}
/>
}
>
<Section level={2} title="Species">
<Box>{overlay.species}</Box>
<Box>{props.overlay.species}</Box>
</Section>
<Section level={2} title="Vore Tag">
<Box p={1} backgroundColor={getTagColor(overlay.tag)}>
{overlay.tag}
<Box p={1} backgroundColor={getTagColor(props.overlay.tag)}>
{props.overlay.tag}
</Box>
</Section>
<Section level={2} title="ERP Tag">
<Box>{overlay.erptag}</Box>
<Box>{props.overlay.erptag}</Box>
</Section>
<Section level={2} title="Character Ad">
<Box style={{ 'word-break': 'break-all' }} preserveWhitespace>
{overlay.character_ad || 'Unset.'}
{props.overlay.character_ad || 'Unset.'}
</Box>
</Section>
<Section level={2} title="OOC Notes">
<Box style={{ 'word-break': 'break-all' }} preserveWhitespace>
{overlay.ooc_notes || 'Unset.'}
{props.overlay.ooc_notes || 'Unset.'}
</Box>
</Section>
<Section level={2} title="Flavor Text">
<Box style={{ 'word-break': 'break-all' }} preserveWhitespace>
{overlay.flavor_text || 'Unset.'}
{props.overlay.flavor_text || 'Unset.'}
</Box>
</Section>
</Section>
@@ -151,7 +153,6 @@ const CharacterDirectoryList = (props) => {
const [sortId, _setSortId] = useState('name');
const [sortOrder, _setSortOrder] = useState('name');
const [overlay, setOverlay] = useState(null);
return (
<Section
@@ -183,7 +184,7 @@ const CharacterDirectoryList = (props) => {
<Table.Cell>{character.erptag}</Table.Cell>
<Table.Cell collapsing textAlign="right">
<Button
onClick={() => setOverlay(character)}
onClick={() => props.onOverlay(character)}
color="transparent"
icon="sticky-note"
mr={1}
+2 -1
View File
@@ -48,7 +48,8 @@ const defTag = [
// Advanced HTML tags that we can trust admins (but not players) with
const advTag = ['img'];
const defAttr = ['class', 'style'];
// Background is here because it accepts image urls
const defAttr = ['class', 'style', 'background'];
/**
* Feed it a string and it should spit out a sanitized version.
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5 -3
View File
@@ -516,9 +516,6 @@ window.replaceHtml = function (inline_html) {
+ "<!-- tgui:inline-html-end -->"
);
};
// Signal tgui that we're ready to receive updates
Byond.sendMessage('ready');
</script>
<style>
@@ -662,5 +659,10 @@ Thank you for your cooperation.
<div>Please enable Javascript and restart the game.</div>
</div>
</noscript>
<script>
// Signal tgui that we're ready to receive updates
Byond.sendMessage('ready');
</script>
</body>
</html>