diff --git a/code/game/machinery/telecomms/computers/message.dm b/code/game/machinery/telecomms/computers/message.dm
index 80bbf7d9f85..0d0a6c9fb97 100644
--- a/code/game/machinery/telecomms/computers/message.dm
+++ b/code/game/machinery/telecomms/computers/message.dm
@@ -432,7 +432,6 @@
"message" = html_decode(custommessage),
"ref" = REF(src),
"targets" = list(customrecepient),
- "emojis" = FALSE,
"rigged" = FALSE,
"automated" = FALSE,
))
diff --git a/code/modules/asset_cache/assets/emojipedia.dm b/code/modules/asset_cache/assets/emojipedia.dm
new file mode 100644
index 00000000000..b2c8c779fba
--- /dev/null
+++ b/code/modules/asset_cache/assets/emojipedia.dm
@@ -0,0 +1,7 @@
+/datum/asset/spritesheet/emojipedia
+ name = "emojipedia"
+ cross_round_cachable = TRUE // The Emoji DMI is static and doesn't change without a commit mis-match.
+
+/datum/asset/spritesheet/create_spritesheets()
+ InsertAll("", EMOJI_SET)
+
diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
index 55fe1dc47d1..8c577e60f9d 100644
--- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm
+++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm
@@ -334,12 +334,14 @@
greyscale_config = /datum/greyscale_config/tablet/mime
greyscale_colors = "#FAFAFA#EA3232"
inserted_item = /obj/item/toy/crayon/mime
+ starting_programs = list(
+ /datum/computer_file/program/emojipedia,
+ )
/obj/item/modular_computer/tablet/pda/mime/Initialize(mapload)
. = ..()
for(var/datum/computer_file/program/messenger/msg in stored_files)
msg.mime_mode = TRUE
- msg.allow_emojis = TRUE
msg.ringer_status = FALSE
/obj/item/modular_computer/tablet/pda/curator
@@ -351,13 +353,13 @@
inserted_item = /obj/item/pen/fountain
long_ranged = TRUE
starting_programs = list(
+ /datum/computer_file/program/emojipedia,
/datum/computer_file/program/newscaster,
)
/obj/item/modular_computer/tablet/pda/curator/Initialize(mapload)
. = ..()
for(var/datum/computer_file/program/messenger/msg in stored_files)
- msg.allow_emojis = TRUE
msg.ringer_status = FALSE
/**
diff --git a/code/modules/modular_computers/file_system/programs/emojipedia.dm b/code/modules/modular_computers/file_system/programs/emojipedia.dm
new file mode 100644
index 00000000000..ad842d94dd1
--- /dev/null
+++ b/code/modules/modular_computers/file_system/programs/emojipedia.dm
@@ -0,0 +1,31 @@
+/// A tablet app that lets anyone see all the valid emoji they can send via a PDA message (and even OOC!)
+/datum/computer_file/program/emojipedia
+ filename = "emojipedia"
+ filedesc = "EmojiPedia"
+ category = PROGRAM_CATEGORY_CREW // we want everyone to be able to access this application, since everyone can send emoji via PDA messages
+ program_icon_state = "generic"
+ extended_desc = "This program allows you to view all the emojis you can send via PDA messages."
+ size = 3
+ tgui_id = "NtosEmojipedia"
+ program_icon = "icons"
+ /// Store the list of potential emojis here.
+ var/static/list/emoji_list = icon_states(icon(EMOJI_SET))
+
+/datum/computer_file/program/emojipedia/New()
+ . = ..()
+ // Sort the emoji list so it's easier to find things and we don't have to keep sorting on ui_data since the number of emojis can not change in-game.
+ emoji_list = sortTim(emoji_list, /proc/cmp_text_asc)
+
+/datum/computer_file/program/emojipedia/ui_static_data(mob_user)
+ var/list/data = get_header_data()
+ for(var/emoji in emoji_list)
+ data["emoji_list"] += list(list(
+ "name" = emoji,
+ ))
+
+ return data
+
+/datum/computer_file/program/emojipedia/ui_assets(mob/user)
+ return list(
+ get_asset_datum(/datum/asset/spritesheet/emojipedia),
+ )
diff --git a/code/modules/modular_computers/file_system/programs/ntmessenger.dm b/code/modules/modular_computers/file_system/programs/ntmessenger.dm
index 5a7996730d7..5480287c1bf 100644
--- a/code/modules/modular_computers/file_system/programs/ntmessenger.dm
+++ b/code/modules/modular_computers/file_system/programs/ntmessenger.dm
@@ -30,8 +30,6 @@
var/datum/picture/saved_image
/// Whether the user is invisible to the message list.
var/invisible = FALSE
- /// Whether or not we allow emojis to be sent by the user.
- var/allow_emojis = FALSE
/// Whether or not we're currently looking at the message list.
var/viewing_messages = FALSE
// Whether or not this device is currently hidden from the message monitor.
@@ -292,7 +290,6 @@
"message" = html_decode(message),
"ref" = REF(computer),
"targets" = targets,
- "emojis" = allow_emojis,
"rigged" = rigged,
"photo" = photo_path,
"automated" = FALSE,
@@ -311,9 +308,8 @@
playsound(src, 'sound/machines/terminal_error.ogg', 15, TRUE)
return FALSE
- if(allow_emojis)
- message = emoji_parse(message)//already sent- this just shows the sent emoji as one to the sender in the to_chat
- signal.data["message"] = emoji_parse(signal.data["message"])
+ message = emoji_parse(message)//already sent- this just shows the sent emoji as one to the sender in the to_chat
+ signal.data["message"] = emoji_parse(signal.data["message"])
// Log it in our logs
var/list/message_data = list()
@@ -382,8 +378,7 @@
reply = "\[Automated Message\]"
var/inbound_message = signal.format_message()
- if(signal.data["emojis"] == TRUE)//so will not parse emojis as such from pdas that don't send emojis
- inbound_message = emoji_parse(inbound_message)
+ inbound_message = emoji_parse(inbound_message)
if(ringer_status && L.is_literate())
to_chat(L, "[icon2html(src)] PDA message from [hrefstart][signal.data["name"]] ([signal.data["job"]])[hrefend], [inbound_message] [reply]")
diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm
index cf6ad9a8c5b..02e19c38c1e 100644
--- a/code/modules/unit_tests/_unit_tests.dm
+++ b/code/modules/unit_tests/_unit_tests.dm
@@ -195,6 +195,7 @@
#include "traitor.dm"
#include "unit_test.dm"
#include "verify_config_tags.dm"
+#include "verify_emoji_names.dm"
#include "wizard_loadout.dm"
#ifdef REFERENCE_TRACKING_DEBUG //Don't try and parse this file if ref tracking isn't turned on. IE: don't parse ref tracking please mr linter
#include "find_reference_sanity.dm"
diff --git a/code/modules/unit_tests/verify_emoji_names.dm b/code/modules/unit_tests/verify_emoji_names.dm
new file mode 100644
index 00000000000..d91a41f17ab
--- /dev/null
+++ b/code/modules/unit_tests/verify_emoji_names.dm
@@ -0,0 +1,10 @@
+/// Apparently, spritesheets (or maybe how the CSS backend works) do not respond well to icon_state names that are just pure numbers (which was a behavior in emoji.dmi).
+/// In case we add more emoji, let's just make sure that we don't have any pure numbers in the emoji.dmi file if we ever add more.
+/datum/unit_test/verify_emoji_names
+
+/datum/unit_test/verify_emoji_names/Run()
+ var/static/list/emoji_list = icon_states(icon(EMOJI_SET))
+ for(var/checkable in emoji_list)
+ if(isnum(text2num(checkable)))
+ TEST_FAIL("Emoji name [checkable] in [EMOJI_SET] is a pure number. This will cause issues with the CSS backend via Spritesheets. Please rename it to something else.")
+ continue
diff --git a/icons/ui_icons/emoji/emoji.dmi b/icons/ui_icons/emoji/emoji.dmi
index 7dd443b6f02..cf94375083c 100644
Binary files a/icons/ui_icons/emoji/emoji.dmi and b/icons/ui_icons/emoji/emoji.dmi differ
diff --git a/modular_skyrat/master_files/icons/emoji.dmi b/modular_skyrat/master_files/icons/emoji.dmi
index ff7cba47069..09af134cd70 100644
Binary files a/modular_skyrat/master_files/icons/emoji.dmi and b/modular_skyrat/master_files/icons/emoji.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 20cd79c6f6a..ee49ecbb3dc 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -2543,6 +2543,7 @@
#include "code\modules\asset_cache\assets\common.dm"
#include "code\modules\asset_cache\assets\condiments.dm"
#include "code\modules\asset_cache\assets\contracts.dm"
+#include "code\modules\asset_cache\assets\emojipedia.dm"
#include "code\modules\asset_cache\assets\fish.dm"
#include "code\modules\asset_cache\assets\fontawesome.dm"
#include "code\modules\asset_cache\assets\genetics.dm"
@@ -3973,6 +3974,7 @@
#include "code\modules\modular_computers\file_system\programs\cargoship.dm"
#include "code\modules\modular_computers\file_system\programs\configurator.dm"
#include "code\modules\modular_computers\file_system\programs\crewmanifest.dm"
+#include "code\modules\modular_computers\file_system\programs\emojipedia.dm"
#include "code\modules\modular_computers\file_system\programs\file_browser.dm"
#include "code\modules\modular_computers\file_system\programs\frontier.dm"
#include "code\modules\modular_computers\file_system\programs\jobmanagement.dm"
diff --git a/tgui/packages/tgui/interfaces/NtosEmojipedia.js b/tgui/packages/tgui/interfaces/NtosEmojipedia.js
new file mode 100644
index 00000000000..9f7c05b172c
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/NtosEmojipedia.js
@@ -0,0 +1,69 @@
+import { classes } from 'common/react';
+import { useBackend, useSharedState } from '../backend';
+import { Box, Button, Input, Section } from '../components';
+import { NtosWindow } from '../layouts';
+
+export const NtosEmojipedia = (props, context) => {
+ const { data } = useBackend(context);
+ const { emoji_list } = data;
+ const [filter, updatefilter] = useSharedState(context, 'filter', '');
+
+ let filtered_emoji_list = filter
+ ? emoji_list.filter((emoji) => {
+ return emoji.name.toLowerCase().includes(filter.toLowerCase());
+ })
+ : emoji_list;
+ if (filtered_emoji_list.length === 0) {
+ filtered_emoji_list = emoji_list;
+ }
+
+ return (
+
+
+
+
+
+ );
+};
diff --git a/tgui/packages/tgui/styles/interfaces/Emojipedia.scss b/tgui/packages/tgui/styles/interfaces/Emojipedia.scss
new file mode 100644
index 00000000000..5007851b1ac
--- /dev/null
+++ b/tgui/packages/tgui/styles/interfaces/Emojipedia.scss
@@ -0,0 +1,7 @@
+.emojipedia16x16 {
+ transform-origin: center;
+ margin: 0.5em;
+ &:hover {
+ transform: scale(1.5);
+ }
+}
diff --git a/tgui/packages/tgui/styles/main.scss b/tgui/packages/tgui/styles/main.scss
index 281cff4f6dd..69ffdad1c6d 100644
--- a/tgui/packages/tgui/styles/main.scss
+++ b/tgui/packages/tgui/styles/main.scss
@@ -70,6 +70,7 @@
@include meta.load-css('./interfaces/RequestManager.scss');
@include meta.load-css('./interfaces/UtilityModulesPane.scss');
@include meta.load-css('./interfaces/Fabricator.scss');
+@include meta.load-css('./interfaces/Emojipedia.scss');
// Layouts
@include meta.load-css('./layouts/Layout.scss');