diff --git a/code/game/machinery/status_display.dm b/code/game/machinery/status_display.dm
index 2ce0dc641a6..b925baf894f 100644
--- a/code/game/machinery/status_display.dm
+++ b/code/game/machinery/status_display.dm
@@ -592,7 +592,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32)
LAZYOR(active_displays, new_display)
set_display_with_priority(SD_GREENSCREEN, DISPLAY_PRIORITY_MESSAGE, force_override = TRUE)
if("friendcomputer")
- friendc = !friendc
+ // Friend Computer should only affect AI displays, not evac displays
+ return
update()
/obj/machinery/status_display/evac/vv_edit_var(vname, vval)
@@ -733,32 +734,67 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/evac, 32)
desc = "A small screen which the AI can use to present itself."
current_mode = SD_PICTURE
var/emotion = AI_DISPLAY_DONT_GLOW
+ var/frequency = FREQ_STATUS_DISPLAYS
+ var/friendc = FALSE // track if Friend Computer mode
+ var/last_picture // For when Friend Computer mode is undone
MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/status_display/ai, 32)
+/obj/machinery/status_display/ai/Initialize(mapload)
+ . = ..()
+ // register for radio system to receive AI emote signals
+ SSradio.add_object(src, frequency)
+ find_and_hang_on_wall()
+
+/obj/machinery/status_display/ai/Destroy()
+ SSradio.remove_object(src, frequency)
+ return ..()
+
/obj/machinery/status_display/ai/attack_ai(mob/living/silicon/ai/user)
if(!isAI(user))
return
- var/list/choices = list()
- for(var/emotion_const in GLOB.ai_status_display_emotes)
- var/icon_state = GLOB.ai_status_display_emotes[emotion_const]
- choices[emotion_const] = image(icon = 'icons/obj/machines/status_display.dmi', icon_state = icon_state)
- var/emotion_result = show_radial_menu(user, src, choices, tooltips = TRUE)
- for(var/_emote in typesof(/datum/emote/ai/emotion_display))
- var/datum/emote/ai/emotion_display/emote = _emote
- if(initial(emote.emotion) == emotion_result)
- user.emote(initial(emote.key))
- break
+ // Open the TGUI interface for selecting status display options
+ if(!user.status_display_picker)
+ user.status_display_picker = new(user, src)
+ user.status_display_picker.ui_interact(user)
/obj/machinery/status_display/ai/process()
if(machine_stat & NOPOWER)
update_appearance()
return PROCESS_KILL
- set_picture(GLOB.ai_status_display_emotes[emotion])
+ if(!length(GLOB.ai_status_display_all_options))
+ init_ai_status_display_options()
+
+ var/icon_state
+ // First try the combined list
+ if(emotion in GLOB.ai_status_display_all_options)
+ icon_state = GLOB.ai_status_display_all_options[emotion]
+ // Then try the original emotes list
+ else if(emotion in GLOB.ai_status_display_emotes)
+ icon_state = GLOB.ai_status_display_emotes[emotion]
+ // Default fallback
+ else
+ icon_state = "ai_neutral"
+
+ set_picture(icon_state)
return PROCESS_KILL
+/obj/machinery/status_display/ai/receive_signal(datum/signal/signal)
+ switch(signal.data["command"])
+ if("friendcomputer")
+ friendc = !friendc
+ if(friendc)
+ last_picture = emotion // Save current display
+ emotion = AI_EMOTION_FRIEND_COMPUTER
+ else
+ if(last_picture)
+ emotion = last_picture // Restore previous display
+ else
+ emotion = AI_DISPLAY_DONT_GLOW
+ update_appearance()
+
/obj/item/circuit_component/status_display
display_name = "Status Display"
desc = "Output text and pictures to a status display."
diff --git a/code/modules/client/preferences/ai_emote_display.dm b/code/modules/client/preferences/ai_emote_display.dm
index fc70e284583..685887e4e49 100644
--- a/code/modules/client/preferences/ai_emote_display.dm
+++ b/code/modules/client/preferences/ai_emote_display.dm
@@ -6,13 +6,17 @@
should_generate_icons = TRUE
/datum/preference/choiced/ai_emote_display/init_possible_values()
- return assoc_to_keys(GLOB.ai_status_display_emotes)
+ if(!length(GLOB.ai_status_display_all_options))
+ init_ai_status_display_options()
+ return assoc_to_keys(GLOB.ai_status_display_all_options)
/datum/preference/choiced/ai_emote_display/icon_for(value)
if (value == "Random")
return uni_icon('icons/mob/silicon/ai.dmi', "questionmark")
else
- return uni_icon('icons/obj/machines/status_display.dmi', GLOB.ai_status_display_emotes[value])
+ if(!length(GLOB.ai_status_display_all_options))
+ init_ai_status_display_options()
+ return uni_icon('icons/obj/machines/status_display.dmi', GLOB.ai_status_display_all_options[value])
/datum/preference/choiced/ai_emote_display/is_accessible(datum/preferences/preferences)
if (!..(preferences))
diff --git a/code/modules/mob/living/silicon/ai/_preferences.dm b/code/modules/mob/living/silicon/ai/_preferences.dm
index 34125aa7cc5..d790c7d6511 100644
--- a/code/modules/mob/living/silicon/ai/_preferences.dm
+++ b/code/modules/mob/living/silicon/ai/_preferences.dm
@@ -1,5 +1,6 @@
// A mapping between AI_EMOTION_* string constants, which also double as user readable descriptions, and the name of the iconfile. (used for /obj/machinery/status_display/ai )
GLOBAL_LIST_INIT(ai_status_display_emotes, list(
+ // Original AI emotion states
AI_EMOTION_AWESOME = "ai_awesome",
AI_EMOTION_BLANK = AI_DISPLAY_DONT_GLOW,
AI_EMOTION_BLUE_GLOW = "ai_sal",
@@ -18,6 +19,60 @@ GLOBAL_LIST_INIT(ai_status_display_emotes, list(
AI_EMOTION_VERY_HAPPY = "ai_veryhappy",
))
+// Mapping from AI core display options to new status display icon states
+// This allows AI status displays to show the same choice as AI core displays
+GLOBAL_LIST_INIT(ai_core_to_status_display_mapping, list(
+ "Alien" = "ai_status_alien",
+ "Angel" = "ai_status_angel",
+ "Banned" = "ai_status_banned",
+ "Bliss" = "ai_status_bliss",
+ "Blue" = "ai_status_blue",
+ "Clown" = "ai_status_clown",
+ "Database" = "ai_status_database",
+ "Dorf" = "ai_status_dorf",
+ "Firewall" = "ai_status_firewall",
+ "Fuzzy" = "ai_status_fuzzy",
+ "Gentoo" = "ai_status_gentoo",
+ "Glitchman" = "ai_status_glitchman",
+ "Gondola" = "ai_status_gondola",
+ "Goon" = "ai_status_goon",
+ "Hades" = "ai_status_hades",
+ "HAL 9000" = "ai_status_hal9000",
+ "Heartline" = "ai_status_heartline",
+ "Helios" = "ai_status_helios",
+ "House" = "ai_status_house",
+ "Matrix" = "ai_status_matrix",
+ "Monochrome" = "ai_status_monochrome",
+ "Murica" = "ai_status_murica",
+ "Nanotrasen" = "ai_status_nanotrasen",
+ "Not Malf" = "ai_status_not_malf",
+ "President" = "ai_status_president",
+ "Rainbow" = "ai_status_rainbow",
+ "Red October" = "ai_status_red_october",
+ "Red" = "ai_status_red",
+ "Static" = "ai_status_static",
+ "Syndicat Meow" = "ai_status_syndicat_meow",
+ "Text" = "ai_status_text",
+ "Too Deep" = "ai_status_too_deep",
+ "Triumvirate" = "ai_status_triumvirate",
+ "Weird" = "ai_status_weird",
+))
+
+// Combined list for AI status display preferences, including both emotion states and AI core display options
+GLOBAL_LIST_INIT(ai_status_display_all_options, list())
+
+// Initialize the combined list at runtime
+/proc/init_ai_status_display_options()
+ if(length(GLOB.ai_status_display_all_options)) // Already initialized
+ return
+
+ // Start with original emotes
+ GLOB.ai_status_display_all_options = GLOB.ai_status_display_emotes.Copy()
+
+ // Add AI core display mappings
+ for(var/core_option in GLOB.ai_core_to_status_display_mapping)
+ GLOB.ai_status_display_all_options[core_option] = GLOB.ai_core_to_status_display_mapping[core_option]
+
GLOBAL_LIST_INIT(ai_hologram_category_options, list(
AI_HOLOGRAM_CATEGORY_ANIMAL = list(
AI_HOLOGRAM_BEAR,
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index d2ac0acd742..9ad600b0f88 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -144,6 +144,7 @@
QDEL_NULL(malf_picker)
QDEL_NULL(doomsday_device)
QDEL_NULL(robot_control)
+ QDEL_NULL(status_display_picker)
QDEL_NULL(aiMulti)
QDEL_NULL(alert_control)
QDEL_NULL(ai_tracking_tool)
@@ -195,7 +196,9 @@
var/emote_choice = player_client.prefs.read_preference(/datum/preference/choiced/ai_emote_display)
if(emote_choice == "Random")
- emote_choice = pick(GLOB.ai_status_display_emotes)
+ if(!length(GLOB.ai_status_display_all_options))
+ init_ai_status_display_options()
+ emote_choice = pick(GLOB.ai_status_display_all_options)
apply_emote_display(emote_choice)
@@ -208,29 +211,28 @@
/mob/living/silicon/ai/verb/pick_icon()
set category = "AI Commands"
set name = "Set AI Core Display"
+ set desc = "Choose what appears on your AI core display"
+
if(incapacitated)
- return
- icon = initial(icon)
- icon_state = "ai"
- cut_overlays()
- var/list/iconstates = GLOB.ai_core_display_screens
- for(var/option in iconstates)
- if(option == "Random")
- iconstates[option] = image(icon = src.icon, icon_state = "ai-random")
- continue
- if(option == "Portrait")
- iconstates[option] = image(icon = src.icon, icon_state = "ai-portrait")
- continue
- iconstates[option] = image(icon = src.icon, icon_state = resolve_ai_icon(option))
-
- view_core()
- var/ai_core_icon = show_radial_menu(src, src , iconstates, radius = 42)
-
- if(!ai_core_icon || incapacitated)
+ to_chat(src, span_warning("You cannot access the core display controls in your current state."))
return
- display_icon_override = ai_core_icon
- set_core_display_icon(ai_core_icon)
+ if(!core_display_picker)
+ core_display_picker = new(src)
+ core_display_picker.ui_interact(src)
+
+/mob/living/silicon/ai/verb/pick_status_display()
+ set category = "AI Commands"
+ set name = "Set AI Status Display"
+ set desc = "Choose what appears on status displays around the station"
+
+ if(incapacitated)
+ to_chat(src, span_warning("You cannot access the status display controls in your current state."))
+ return
+
+ if(!status_display_picker)
+ status_display_picker = new(src)
+ status_display_picker.ui_interact(src)
/mob/living/silicon/ai/get_status_tab_items()
. = ..()
diff --git a/code/modules/mob/living/silicon/ai/ai_core_display_picker.dm b/code/modules/mob/living/silicon/ai/ai_core_display_picker.dm
new file mode 100644
index 00000000000..311f0d064ab
--- /dev/null
+++ b/code/modules/mob/living/silicon/ai/ai_core_display_picker.dm
@@ -0,0 +1,79 @@
+/**
+ * AI Core Display Picker TGUI
+ * Allows AIs to select core display options with search functionality
+ */
+/datum/ai_core_display_picker
+ var/mob/living/silicon/ai/ai_user
+
+/datum/ai_core_display_picker/New(mob/living/silicon/ai/user)
+ ai_user = user
+
+/datum/ai_core_display_picker/ui_status(mob/user, datum/ui_state/state)
+ if(!ai_user || user != ai_user || ai_user.incapacitated)
+ return UI_CLOSE
+ return ..()
+
+/datum/ai_core_display_picker/ui_state(mob/user)
+ return GLOB.always_state
+
+/datum/ai_core_display_picker/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "AiCoreDisplayPicker")
+ ui.open()
+
+/datum/ai_core_display_picker/ui_close(mob/user)
+ if(ai_user)
+ ai_user.core_display_picker = null
+
+/datum/ai_core_display_picker/ui_data(mob/user)
+ var/list/data = list()
+
+ // If no override is set, find the actual current display from the AI's icon state
+ var/current_display = ai_user.display_icon_override
+ if(!current_display)
+ // Default to "Blue" if no override
+ current_display = "Blue"
+ // Try to identify current display
+ if(ai_user.icon_state)
+ for(var/display_name in GLOB.ai_core_display_screens)
+ if("ai-[LOWER_TEXT(display_name)]" == ai_user.icon_state)
+ current_display = display_name
+ break
+
+ data["current_display"] = current_display
+
+ // Get icon for current display
+ var/current_icon_state = resolve_ai_icon_sync(current_display)
+ data["current_icon"] = list(
+ "icon" = 'icons/mob/silicon/ai.dmi',
+ "icon_state" = current_icon_state
+ )
+
+ var/list/options = list()
+
+ for(var/option_name in GLOB.ai_core_display_screens)
+ var/icon_state = resolve_ai_icon_sync(option_name)
+ var/list/option_data = list(
+ "name" = option_name,
+ "icon_state" = icon_state,
+ "icon" = 'icons/mob/silicon/ai.dmi'
+ )
+ options += list(option_data)
+
+ data["options"] = options
+
+ return data
+
+/datum/ai_core_display_picker/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+
+ switch(action)
+ if("select_option")
+ var/chosen_option = params["option"]
+ if(chosen_option in GLOB.ai_core_display_screens)
+ ai_user.display_icon_override = chosen_option
+ ai_user.set_core_display_icon(chosen_option)
+ return TRUE
diff --git a/code/modules/mob/living/silicon/ai/ai_defines.dm b/code/modules/mob/living/silicon/ai/ai_defines.dm
index e1399a1ddb1..de631e7b867 100644
--- a/code/modules/mob/living/silicon/ai/ai_defines.dm
+++ b/code/modules/mob/living/silicon/ai/ai_defines.dm
@@ -163,6 +163,10 @@
/* UI */
/// UI for station alerts
VAR_FINAL/datum/station_alert/alert_control
+ /// UI for AI status display picker
+ VAR_FINAL/datum/ai_status_display_picker/status_display_picker
+ /// UI for AI core display picker
+ VAR_FINAL/datum/ai_core_display_picker/core_display_picker
/* I'M DUMB AND CAN'T SORT */
/// Used as a fake multitool in tcomms machinery
diff --git a/code/modules/mob/living/silicon/ai/ai_status_display_picker.dm b/code/modules/mob/living/silicon/ai/ai_status_display_picker.dm
new file mode 100644
index 00000000000..e88fc60c92a
--- /dev/null
+++ b/code/modules/mob/living/silicon/ai/ai_status_display_picker.dm
@@ -0,0 +1,123 @@
+/**
+ * AI Status Display Picker TGUI
+ * Allows AIs to select status display options with search functionality
+ */
+
+/datum/ai_status_display_picker
+ /// The AI user who opened this interface
+ var/mob/living/silicon/ai/ai_user
+ /// The status display that was clicked
+ var/obj/machinery/status_display/ai/target_display
+
+/datum/ai_status_display_picker/New(mob/living/silicon/ai/user)
+ ai_user = user
+
+/datum/ai_status_display_picker/ui_status(mob/user, datum/ui_state/state)
+ if(!ai_user || user != ai_user || ai_user.incapacitated)
+ return UI_CLOSE
+ return ..()
+
+/datum/ai_status_display_picker/ui_state(mob/user)
+ return GLOB.always_state
+
+/datum/ai_status_display_picker/ui_interact(mob/user, datum/tgui/ui)
+ ui = SStgui.try_update_ui(user, src, ui)
+ if(!ui)
+ ui = new(user, src, "AiStatusDisplayPicker")
+ ui.open()
+
+/datum/ai_status_display_picker/ui_close(mob/user)
+ if(ai_user)
+ ai_user.status_display_picker = null
+
+// No assets needed for DMIcon system
+
+/datum/ai_status_display_picker/ui_static_data(mob/user)
+ // Always ensure initialization
+ init_ai_status_display_options()
+
+ var/list/data = list()
+ var/list/options = list()
+
+ for(var/option_name in GLOB.ai_status_display_emotes)
+ var/icon_state = GLOB.ai_status_display_emotes[option_name]
+ var/list/option_data = list(
+ "name" = option_name,
+ "icon_state" = icon_state,
+ "is_original" = TRUE,
+ "icon" = 'icons/obj/machines/status_display.dmi'
+ )
+ options += list(option_data)
+
+ for(var/option_name in GLOB.ai_core_to_status_display_mapping)
+ var/icon_state = GLOB.ai_core_to_status_display_mapping[option_name]
+ var/list/option_data = list(
+ "name" = option_name,
+ "icon_state" = icon_state,
+ "is_original" = FALSE,
+ "icon" = 'icons/obj/machines/status_display.dmi'
+ )
+ options += list(option_data)
+
+ data["options"] = options
+
+ return data
+
+/datum/ai_status_display_picker/ui_data(mob/user)
+ var/list/data = list()
+
+ // Find current display emotion from first available AI status display
+ var/current_emotion = "None"
+ var/current_icon_state
+ var/obj/machinery/status_display/ai/first_display = locate() in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/status_display/ai)
+ if(first_display?.emotion)
+ current_emotion = first_display.emotion
+ if(current_emotion in GLOB.ai_status_display_emotes)
+ current_icon_state = GLOB.ai_status_display_emotes[current_emotion]
+ else if(current_emotion in GLOB.ai_core_to_status_display_mapping)
+ current_icon_state = GLOB.ai_core_to_status_display_mapping[current_emotion]
+ else
+ current_icon_state = "ai_neutral"
+ else
+ current_icon_state = "ai_neutral"
+
+ data["current_emotion"] = current_emotion
+ data["current_icon"] = list(
+ "icon" = 'icons/obj/machines/status_display.dmi',
+ "icon_state" = current_icon_state
+ )
+
+ return data
+
+/datum/ai_status_display_picker/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state)
+ . = ..()
+ if(.)
+ return
+
+ if(!ai_user)
+ return FALSE
+
+ switch(action)
+ if("select_option")
+ var/selected_option = params["option"]
+ if(!selected_option || !(selected_option in GLOB.ai_status_display_all_options))
+ return FALSE
+
+ // Check if this is an original AI emotion (has a corresponding emote)
+ var/found_emote = FALSE
+ for(var/_emote in typesof(/datum/emote/ai/emotion_display))
+ var/datum/emote/ai/emotion_display/emote = _emote
+ if(initial(emote.emotion) == selected_option)
+ ai_user.emote(initial(emote.key))
+ found_emote = TRUE
+ break
+
+ // If no emote found (i.e., it's a new AI core display option), directly apply it
+ if(!found_emote)
+ ai_user.apply_emote_display(selected_option)
+
+ return TRUE
+
+ return FALSE
+
+
diff --git a/icons/obj/machines/status_display.dmi b/icons/obj/machines/status_display.dmi
index 98f78627823..2fa55c8436b 100644
Binary files a/icons/obj/machines/status_display.dmi and b/icons/obj/machines/status_display.dmi differ
diff --git a/tgstation.dme b/tgstation.dme
index 864f10efcb0..5e7b7ef98dc 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -5497,10 +5497,12 @@
#include "code\modules\mob\living\silicon\silicon_say.dm"
#include "code\modules\mob\living\silicon\ai\_preferences.dm"
#include "code\modules\mob\living\silicon\ai\ai.dm"
+#include "code\modules\mob\living\silicon\ai\ai_core_display_picker.dm"
#include "code\modules\mob\living\silicon\ai\ai_defense.dm"
#include "code\modules\mob\living\silicon\ai\ai_defines.dm"
#include "code\modules\mob\living\silicon\ai\ai_portrait_picker.dm"
#include "code\modules\mob\living\silicon\ai\ai_say.dm"
+#include "code\modules\mob\living\silicon\ai\ai_status_display_picker.dm"
#include "code\modules\mob\living\silicon\ai\death.dm"
#include "code\modules\mob\living\silicon\ai\emote.dm"
#include "code\modules\mob\living\silicon\ai\examine.dm"
diff --git a/tgui/packages/tgui/interfaces/AiCoreDisplayPicker.tsx b/tgui/packages/tgui/interfaces/AiCoreDisplayPicker.tsx
new file mode 100644
index 00000000000..a248373d490
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/AiCoreDisplayPicker.tsx
@@ -0,0 +1,146 @@
+import { useState } from 'react';
+import {
+ Box,
+ Button,
+ Flex,
+ ImageButton,
+ Input,
+ Section,
+ Stack,
+ Table,
+ DmIcon,
+} from 'tgui-core/components';
+import { classes } from 'tgui-core/react';
+import { useBackend } from '../backend';
+import { Window } from '../layouts';
+
+type CoreDisplayOption = {
+ name: string;
+ icon_state: string;
+ icon: string;
+};
+
+type CurrentIcon = {
+ icon: string;
+ icon_state: string;
+};
+
+type Data = {
+ current_display: string;
+ current_icon: CurrentIcon | null;
+ options: CoreDisplayOption[];
+};
+
+export const AiCoreDisplayPicker = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+const AiCoreDisplayPickerContent = () => {
+ const { act, data } = useBackend();
+ const { current_display, current_icon, options = [] } = data;
+
+ const [searchTerm, setSearchTerm] = useState('');
+ const [tiledView, setTiledView] = useState(false);
+
+ // Filter options based on search term
+ const filteredOptions = options.filter((option) =>
+ option.name.toLowerCase().includes(searchTerm.toLowerCase())
+ );
+
+ return (
+
+
+
+
+ {current_icon && (
+
+
+
+
+
+ )}
+
+
+ {current_display}
+
+
+
+
+
+
+
+ setSearchTerm(value)}
+ fluid
+ />
+
+
+
+
+
+
+
+
+ {filteredOptions.length === 0 && (
+
+
+ No options found matching "{searchTerm}"
+
+
+ )}
+
+
+
+
+
+ );
+};
+
+const OptionsList = ({
+ options,
+}: {
+ options: CoreDisplayOption[];
+}) => {
+ const { act } = useBackend();
+
+ return (
+ <>
+ {options.map((option) => (
+ act('select_option', { option: option.name })}
+ imageSize={64}
+ tooltip={option.name}
+ >
+ {option.name}
+
+ ))}
+ >
+ );
+};
diff --git a/tgui/packages/tgui/interfaces/AiStatusDisplayPicker.tsx b/tgui/packages/tgui/interfaces/AiStatusDisplayPicker.tsx
new file mode 100644
index 00000000000..1adc55bb4be
--- /dev/null
+++ b/tgui/packages/tgui/interfaces/AiStatusDisplayPicker.tsx
@@ -0,0 +1,164 @@
+import { useState } from 'react';
+import type { BooleanLike } from 'tgui-core/react';
+import {
+ Box,
+ Button,
+ Flex,
+ ImageButton,
+ Input,
+ Section,
+ Stack,
+ DmIcon,
+} from 'tgui-core/components';
+import { useBackend } from '../backend';
+import { Window } from '../layouts';
+
+type StatusDisplayOption = {
+ name: string;
+ icon_state: string;
+ is_original: BooleanLike;
+ dmi: string;
+ icon: string;
+};
+
+type CurrentIcon = {
+ icon: string;
+ icon_state: string;
+};
+
+type Data = {
+ current_emotion: string;
+ current_icon: CurrentIcon | null;
+ options: StatusDisplayOption[];
+};
+
+export const AiStatusDisplayPicker = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+const AiStatusDisplayPickerContent = () => {
+ const { act, data } = useBackend();
+ const { current_emotion, current_icon, options = [] } = data;
+
+ const [searchTerm, setSearchTerm] = useState('');
+
+ // Filter options based on search term
+ const filteredOptions = options.filter((option) =>
+ option.name.toLowerCase().includes(searchTerm.toLowerCase())
+ );
+
+ // Separate original emotions and new AI core options
+ const originalOptions = filteredOptions.filter((option) => option.is_original);
+ const newOptions = filteredOptions.filter((option) => !option.is_original);
+
+ return (
+
+
+
+
+ {current_icon && (
+
+
+
+
+
+ )}
+
+
+ {current_emotion || 'No Selection'}
+
+
+
+
+
+
+
+
+
+
+
+
+ {originalOptions.length > 0 && (
+
+
+
+ )}
+
+ {newOptions.length > 0 && (
+
+
+
+ )}
+
+ {filteredOptions.length === 0 && (
+
+
+ No options found matching "{searchTerm}"
+
+
+ )}
+
+
+
+
+
+ );
+};
+
+const OptionsList = ({
+ options
+}: {
+ options: StatusDisplayOption[];
+}) => {
+ const { act } = useBackend();
+
+ return (
+ <>
+ {options.map((option) => (
+ act('select_option', { option: option.name })}
+ imageSize={64}
+ tooltip={option.name}
+ >
+ {option.name}
+
+ ))}
+ >
+ );
+};