diff --git a/maplestation_modules/code/modules/client/preferences/languages.dm b/maplestation_modules/code/modules/client/preferences/languages.dm index 12697838d0e9..d9ad432b93f3 100644 --- a/maplestation_modules/code/modules/client/preferences/languages.dm +++ b/maplestation_modules/code/modules/client/preferences/languages.dm @@ -125,12 +125,6 @@ action_delegations = list( "set_language" = PROC_REF(set_language), ) - /// Static list of all "base" languages learnable via ui - /// (roundstart languages, languages readily available / common) - var/static/list/base_languages - /// Static list of all "bonus" languages learnable via ui - /// (rarer languages, not typically available roundstart, dictated by a required_species_id) - var/static/list/bonus_languages /datum/preference_middleware/language/proc/set_language(list/params, mob/user) var/datum/preference/additional_language/language_pref = GLOB.preference_entries[/datum/preference/additional_language] @@ -161,48 +155,42 @@ /datum/preference_middleware/language/get_ui_data(mob/user) var/list/data = list() - var/datum/species/species = preferences.read_preference(/datum/preference/choiced/species) data["selected_lang"] = preferences.read_preference(/datum/preference/additional_language) + data["selected_species"] = preferences.read_preference(/datum/preference/choiced/species) data["pref_name"] = preferences.read_preference(/datum/preference/name/real_name) data["trilingual"] = ("Trilingual" in preferences.all_quirks) data["bilingual"] = ("Bilingual" in preferences.all_quirks) - data["species"] = species - - // This should all be moved to constant data when I figure out how tee hee - if(!length(base_languages) && !length(bonus_languages) && length(GLOB.language_datum_instances)) - base_languages = list() - bonus_languages = list() - - for(var/found_language in GLOB.language_datum_instances) - var/datum/language/found_instance = GLOB.language_datum_instances[found_language] - if(!found_instance.available_as_pref) - continue - - var/list/lang_data = list() - lang_data["name"] = found_instance.name - lang_data["type"] = found_language - if(found_instance.banned_from_species) - lang_data["incompatible_with"] = initial(found_instance.banned_from_species.name) - if(found_instance.required_species) - lang_data["requires"] = initial(found_instance.required_species.name) - // Having a required species makes it a bonus language, otherwise it's a base language - if(found_instance.required_species) - UNTYPED_LIST_ADD(bonus_languages, lang_data) - else - UNTYPED_LIST_ADD(base_languages, lang_data) - - for(var/list/lang_type as anything in base_languages + bonus_languages) - var/datum/language/lang_instance = GLOB.language_datum_instances[lang_type["type"]] - lang_type["pickable"] = !((lang_instance.banned_from_species && ispath(species, lang_instance.banned_from_species)) \ - || (lang_instance.required_species && !ispath(species, lang_instance.required_species))) - data["base_languages"] = base_languages - data["bonus_languages"] = bonus_languages return data -/datum/preference_middleware/language/get_ui_static_data(mob/user) +/datum/preference_middleware/language/get_constant_data() var/list/data = list() - // Again constant data when I figure it out + var/list/base_languages = list() + var/list/bonus_languages = list() + for(var/found_language in GLOB.language_datum_instances) + var/datum/language/found_instance = GLOB.language_datum_instances[found_language] + if(!found_instance.available_as_pref) + continue + + var/list/lang_data = list() + lang_data["name"] = found_instance.name + lang_data["type"] = found_language + + var/datum/species/banned_species = found_instance.banned_from_species + if(banned_species) + lang_data["incompatible_with"] = list("name" = initial(banned_species.name), "type" = banned_species) + var/datum/species/required_species = found_instance.required_species + if(required_species) + lang_data["requires"] = list("name" = initial(required_species.name), "type" = required_species) + + // Having a required species makes it a bonus language, otherwise it's a base language + if(found_instance.required_species) + UNTYPED_LIST_ADD(bonus_languages, lang_data) + else + UNTYPED_LIST_ADD(base_languages, lang_data) + + data["base_languages"] = base_languages + data["bonus_languages"] = bonus_languages data["blacklisted_species"] = BLACKLISTED_SPECIES_FROM_LANGUAGES return data diff --git a/maplestation_modules/code/modules/client/preferences/multiline_preferences.dm b/maplestation_modules/code/modules/client/preferences/multiline_preferences.dm index 0a4f91a6c020..08f0aa4ad5df 100644 --- a/maplestation_modules/code/modules/client/preferences/multiline_preferences.dm +++ b/maplestation_modules/code/modules/client/preferences/multiline_preferences.dm @@ -17,6 +17,9 @@ /datum/preference/multiline_text/create_default_value() return null +/datum/preference/multiline_text/compile_constant_data() + return list("maximum_length" = max_length) + /// Preferences that add onto flavor text datum /datum/preference/multiline_text/flavor_datum abstract_type = /datum/preference/multiline_text/flavor_datum @@ -62,6 +65,7 @@ savefile_identifier = PREFERENCE_CHARACTER category = PREFERENCE_CATEGORY_NON_CONTEXTUAL priority = PREFERENCE_PRIORITY_NAMES + max_length = MAX_MESSAGE_LEN /datum/preference/multiline_text/record/New() . = ..() diff --git a/maplestation_modules/code/modules/loadouts/loadout_ui/limbs.dm b/maplestation_modules/code/modules/loadouts/loadout_ui/limbs.dm index 7d7d0f731285..6e9c6376934a 100644 --- a/maplestation_modules/code/modules/loadouts/loadout_ui/limbs.dm +++ b/maplestation_modules/code/modules/loadouts/loadout_ui/limbs.dm @@ -94,45 +94,39 @@ data["preview_flat_icon"] = cached_icon return data -/datum/preference_middleware/limbs/get_ui_static_data(mob/user) +/datum/preference_middleware/limbs/get_constant_data() var/list/data = list() + var/list/all_limb_data = list() + var/list/raw_limb_data = list( + BODY_ZONE_HEAD = list(), + BODY_ZONE_CHEST = list(), + BODY_ZONE_L_ARM = list(), + BODY_ZONE_R_ARM = list(), + BODY_ZONE_L_LEG = list(), + BODY_ZONE_R_LEG = list(), + ) - // This should all be moved to constant data when I figure out how tee hee - var/static/list/limbs_data - if(isnull(limbs_data)) - var/list/raw_data = list( - BODY_ZONE_HEAD = list(), - BODY_ZONE_CHEST = list(), - BODY_ZONE_L_ARM = list(), - BODY_ZONE_R_ARM = list(), - BODY_ZONE_L_LEG = list(), - BODY_ZONE_R_LEG = list(), + for(var/limb_type in GLOB.limb_loadout_options) + var/datum/limb_option_datum/limb_datum = GLOB.limb_loadout_options[limb_type] + var/limb_zone = limb_datum.ui_zone + if(isnull(limb_zone) || !islist(raw_limb_data[limb_zone])) + stack_trace("Invalid limb zone found in limb datums: [limb_zone || "null"]. (From: [limb_type])") + continue + + var/list/limb_data = list( + "name" = limb_datum.name, + "tooltip" = limb_datum.desc, + "path" = limb_type, ) - for(var/limb_type in GLOB.limb_loadout_options) - var/datum/limb_option_datum/limb_datum = GLOB.limb_loadout_options[limb_type] - var/limb_zone = limb_datum.ui_zone - - if(isnull(limb_zone) || !islist(raw_data[limb_zone])) - stack_trace("Invalid limb zone found in limb datums: [limb_zone || "null"]. (From: [limb_type])") - continue - - var/list/limb_data = list( - "name" = limb_datum.name, - "tooltip" = limb_datum.desc, - "path" = limb_type, - ) - - UNTYPED_LIST_ADD(raw_data[limb_zone], limb_data) - - limbs_data = list() - for(var/raw_list_key in raw_data) - var/list/ui_formatted_raw_list = list( - "category_name" = raw_list_key, - "category_data" = raw_data[raw_list_key], - ) - UNTYPED_LIST_ADD(limbs_data, ui_formatted_raw_list) + UNTYPED_LIST_ADD(raw_limb_data[limb_zone], limb_data) + for(var/raw_list_key in raw_limb_data) + var/list/ui_formatted_raw_list = list( + "category_name" = raw_list_key, + "category_data" = raw_limb_data[raw_list_key], + ) + UNTYPED_LIST_ADD(all_limb_data, ui_formatted_raw_list) - data["limbs"] = limbs_data + data["limbs"] = all_limb_data return data diff --git a/maplestation_modules/code/modules/loadouts/loadout_ui/loadout_manager.dm b/maplestation_modules/code/modules/loadouts/loadout_ui/loadout_manager.dm index d127a2a684b2..b516600e2052 100644 --- a/maplestation_modules/code/modules/loadouts/loadout_ui/loadout_manager.dm +++ b/maplestation_modules/code/modules/loadouts/loadout_ui/loadout_manager.dm @@ -96,7 +96,7 @@ GLOBAL_LIST_INIT(loadout_categories, init_loadout_categories()) return character_preview_view /datum/preference_middleware/loadout/on_new_character(mob/user) - character_preview_view.update_body() + character_preview_view?.update_body() /datum/preference_middleware/loadout/proc/action_select_item(list/params, mob/user) var/path_to_use = text2path(params["path"]) @@ -196,17 +196,17 @@ GLOBAL_LIST_INIT(loadout_categories, init_loadout_categories()) /datum/preference_middleware/loadout/get_ui_static_data(mob/user) var/list/data = list() data["loadout_preview_view"] = character_preview_view.assigned_map + return data - // This should all be moved to constant data when I figure out how tee hee - var/static/list/loadout_tabs - if(isnull(loadout_tabs)) - loadout_tabs = list() - for(var/datum/loadout_category/category as anything in GLOB.loadout_categories) - UNTYPED_LIST_ADD(loadout_tabs, list( - "name" = category.category_name, - "title" = category.ui_title, - "contents" = category.items_to_ui_data(), - )) +/datum/preference_middleware/loadout/get_constant_data() + var/list/data = list() + var/list/loadout_tabs = list() + for(var/datum/loadout_category/category as anything in GLOB.loadout_categories) + UNTYPED_LIST_ADD(loadout_tabs, list( + "name" = category.category_name, + "title" = category.ui_title, + "contents" = category.items_to_ui_data(), + )) data["loadout_tabs"] = loadout_tabs data["tutorial_text"] = get_tutorial_text() diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx index d80b91d545a6..d49d8734d34c 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferenceWindow.tsx @@ -4,9 +4,9 @@ import { useState } from 'react'; import { useBackend } from '../../backend'; import { Button, Stack } from '../../components'; import { Window } from '../../layouts'; -import { LanguagePage } from '../_LanguagePicker'; // NON-MODULE CHANGE -import { LimbManagerPage } from '../_LimbManager'; // NON-MODULE CHANGE -import { LoadoutPage } from '../_LoadoutManager'; // NON-MODULE CHANGE +import { LanguagePage } from './_LanguagePicker'; // NON-MODULE CHANGE +import { LimbManagerPage } from './_LimbManager'; // NON-MODULE CHANGE +import { LoadoutPage } from './_LoadoutManager'; // NON-MODULE CHANGE import { AntagsPage } from './AntagsPage'; import { PreferencesMenuData } from './data'; import { JobsPage } from './JobsPage'; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/_LanguagePicker.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/_LanguagePicker.tsx new file mode 100644 index 000000000000..bdfdca673d21 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/_LanguagePicker.tsx @@ -0,0 +1,184 @@ +import { BooleanLike } from 'common/react'; + +import { useBackend } from '../../backend'; +import { + Box, + Button, + Dimmer, + NoticeBox, + Section, + Stack, +} from '../../components'; +import { ServerPreferencesFetcher } from './ServerPreferencesFetcher'; + +type typePath = string; + +type Data = { + pref_name: string; + selected_species: typePath; + selected_lang: typePath | string; + trilingual: BooleanLike; + bilingual: BooleanLike; +}; + +type Species = { + name: string; + type: typePath; +}; + +export type Language = { + name: string; + type: typePath; + incompatible_with: Species | null; + requires: Species | null; +}; + +// Fake an ispath() check to determine if this species can learn this language +const isPickable = (lang: Language, species: typePath): boolean => { + if (lang.incompatible_with && species.includes(lang.incompatible_with.type)) { + return false; + } + if (lang.requires && !species.includes(lang.requires.type)) { + return false; + } + return true; +}; + +const getLanguageTooltip = (lang: Language): string => { + if (lang.incompatible_with && lang.requires) { + return `This language cannot be selected by + the "${lang.incompatible_with.name}" species and requires + the "${lang.requires.name}" species.`; + } + if (lang.incompatible_with) { + return `This language cannot be selected by + the "${lang.incompatible_with.name}" species.`; + } + if (lang.requires) { + return `This language requires + the "${lang.requires.name}" species.`; + } + return ''; +}; + +const LanguageStack = (props: { + language: Language; + selected_lang: typePath; + selected_species: typePath; +}) => { + const { act } = useBackend(); + const { language, selected_species } = props; + const { name, type } = language; + const pickable = isPickable(language, selected_species); + + return ( + + + {name} + + + + act('set_language', { + lang_type: type, + deselecting: type === props.selected_lang, + }) + } + /> + + + ); +}; + +const WarningDimmer = (props) => { + return ( + + {props.message} + + ); +}; + +const LanguagePageInner = (props: { + base_languages: Language[]; + bonus_languages: Language[]; + blacklisted_species: typePath[]; +}) => { + const { data } = useBackend(); + const { base_languages, bonus_languages, blacklisted_species } = props; + const { selected_species, selected_lang, trilingual, bilingual } = data; + + return ( +
+ {!!trilingual && ( + + )} + {!!bilingual && ( + + )} + {blacklisted_species.includes(selected_species) && ( + + )} +
+ + {base_languages.map((language) => ( + + + + ))} + +
+
+ + {bonus_languages.map((language) => ( + + + + ))} + +
+
+ ); +}; + +export const LanguagePage = () => { + return ( + { + return serverData ? ( + + ) : ( + Loading... + ); + }} + /> + ); +}; diff --git a/tgui/packages/tgui/interfaces/_LimbManager.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/_LimbManager.tsx similarity index 91% rename from tgui/packages/tgui/interfaces/_LimbManager.tsx rename to tgui/packages/tgui/interfaces/PreferencesMenu/_LimbManager.tsx index fde04f68d765..2c73e8d381c1 100644 --- a/tgui/packages/tgui/interfaces/_LimbManager.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/_LimbManager.tsx @@ -1,9 +1,17 @@ import { Component, createRef } from 'react'; -import { resolveAsset } from '../assets'; -import { useBackend } from '../backend'; -import { BlockQuote, Button, Image, Section, Stack } from '../components'; -import { Connections } from './common/Connections'; +import { resolveAsset } from '../../assets'; +import { useBackend } from '../../backend'; +import { + BlockQuote, + Button, + Image, + NoticeBox, + Section, + Stack, +} from '../../components'; +import { Connections } from '../common/Connections'; +import { ServerPreferencesFetcher } from './ServerPreferencesFetcher'; const makeCategoryReadable = (cat: string | null): string | null => { switch (cat) { @@ -82,12 +90,12 @@ const getActiveCategory = ( }; type Data = { - limbs: LimbCategory[]; + // limbs: LimbCategory[]; selected_limbs: string[] | null; preview_flat_icon: string; }; -type LimbCategory = { +export type LimbCategory = { category_name: string; category_data: Limb[]; }; @@ -348,14 +356,21 @@ class LimbManagerInner extends Component< } export const LimbManagerPage = () => { - const { act, data } = useBackend(); - const { limbs, selected_limbs, preview_flat_icon } = data; + const { data } = useBackend(); return ( - { + return serverData ? ( + + ) : ( + Loading... + ); + }} /> ); }; diff --git a/tgui/packages/tgui/interfaces/_LoadoutManager.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/_LoadoutManager.tsx similarity index 71% rename from tgui/packages/tgui/interfaces/_LoadoutManager.tsx rename to tgui/packages/tgui/interfaces/PreferencesMenu/_LoadoutManager.tsx index b77475bea4b1..5661fb3ce6c4 100644 --- a/tgui/packages/tgui/interfaces/_LoadoutManager.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/_LoadoutManager.tsx @@ -1,6 +1,7 @@ import { BooleanLike } from 'common/react'; +import { useState } from 'react'; -import { useBackend, useLocalState } from '../backend'; +import { useBackend } from '../../backend'; import { Box, Button, @@ -10,8 +11,9 @@ import { Section, Stack, Tabs, -} from '../components'; -import { CharacterPreview } from './common/CharacterPreview'; +} from '../../components'; +import { CharacterPreview } from '../common/CharacterPreview'; +import { ServerPreferencesFetcher } from './ServerPreferencesFetcher'; type typePath = string; @@ -27,7 +29,7 @@ type LoadoutItem = { buttons: LoadoutButton[]; }; -type LoadoutCategory = { +export type LoadoutCategory = { name: string; title: string; contents: LoadoutItem[]; @@ -38,29 +40,48 @@ type Data = { mob_name: string; job_clothes: BooleanLike; loadout_preview_view: string; - loadout_tabs: LoadoutCategory[]; - tutorial_text: string; current_slot: number; - max_loadout_slots: number; }; export const LoadoutPage = () => { - const { data } = useBackend(); - const { loadout_tabs } = data; - const [tutorialStatus, setTutorialStatus] = useLocalState( - 'tutorialStatus', - false, + return ( + { + return serverData ? ( + + ) : ( + Loading... + ); + }} + /> ); - const [searchLoadout, setSearchLoadout] = useLocalState('searchLoadout', ''); - const [selectedTabName, setSelectedTab] = useLocalState( - 'tabs', - loadout_tabs[0]?.name, +}; + +const LoadoutPageInner = (props: { + tutorial_text: string; + loadout_tabs: LoadoutCategory[]; + max_loadout_slots: number; +}) => { + const { tutorial_text, loadout_tabs, max_loadout_slots } = props; + const [tutorialStatus, setTutorialStatus] = useState(false); + const [searchLoadout, setSearchLoadout] = useState(''); + const [selectedTabName, setSelectedTab] = useState( + loadout_tabs[0].name, ); return ( - {!!tutorialStatus && } + {!!tutorialStatus && ( + + )}
{ setSearchLoadout(value)} + onInput={(_, value) => setSearchLoadout(value)} placeholder="Search for item" value={searchLoadout} /> @@ -100,30 +122,32 @@ export const LoadoutPage = () => {
- +
); }; - -const LoadoutTutorialDimmer = () => { - const { data } = useBackend(); - const { tutorial_text } = data; - const [tutorialStatus, setTutorialStatus] = useLocalState( - 'tutorialStatus', - false, - ); +const LoadoutTutorialDimmer = (props: { + text: string; + updateTutorialState: (newState: boolean) => void; +}) => { return ( - {tutorial_text} + {props.text} @@ -133,10 +157,7 @@ const LoadoutTutorialDimmer = () => { ); }; -const ItemDisplay = ( - props: { item: LoadoutItem; active: boolean }, - context, -) => { +const ItemDisplay = (props: { item: LoadoutItem; active: boolean }) => { const { act } = useBackend(); const { item, active } = props; return ( @@ -207,10 +228,13 @@ const LoadoutTabDisplay = (props: { ); }; -const SearchDisplay = () => { +const SearchDisplay = (props: { + loadout_tabs: LoadoutCategory[]; + currentSearch: string; +}) => { const { data } = useBackend(); - const { loadout_tabs, selected_loadout } = data; - const [searchLoadout] = useLocalState('searchLoadout', ''); + const { selected_loadout } = data; + const { loadout_tabs, currentSearch } = props; const allLoadoutItems = () => { const concatItems: LoadoutItem[] = []; @@ -222,7 +246,7 @@ const SearchDisplay = () => { return concatItems.sort((a, b) => a.name.localeCompare(b.name)); }; const validLoadoutItems = allLoadoutItems().filter((item) => - item.name.toLowerCase().includes(searchLoadout.toLowerCase()), + item.name.toLowerCase().includes(currentSearch.toLowerCase()), ); if (validLoadoutItems.length === 0) { @@ -247,16 +271,25 @@ const SearchDisplay = () => { ); }; -const LoadoutTabs = (props, context) => { +const LoadoutTabs = (props: { + slots: number; + loadout_tabs: LoadoutCategory[]; + currentTab: string; + currentSearch: string; + currentTutorialStatus: boolean; +}) => { const { act, data } = useBackend(); - const { loadout_tabs } = data; - const [selectedTabName] = useLocalState('tabs', loadout_tabs[0]?.name); - const [searchLoadout] = useLocalState('searchLoadout', ''); + const { + slots, + loadout_tabs, + currentTab, + currentSearch, + currentTutorialStatus, + } = props; const activeCategory = loadout_tabs.find((curTab) => { - return curTab.name === selectedTabName; + return curTab.name === currentTab; }); - - const searching = searchLoadout.length > 1; + const searching = currentSearch.length > 1; return ( @@ -282,7 +315,10 @@ const LoadoutTabs = (props, context) => { > {searching ? ( - + ) : ( )} @@ -295,23 +331,22 @@ const LoadoutTabs = (props, context) => { )} - + ); }; -const LoadoutPreviewSection = () => { +const LoadoutPreviewSection = (props: { + slots: number; + tutorialStatus: boolean; +}) => { const { act, data } = useBackend(); - const { - mob_name, - job_clothes, - loadout_preview_view, - current_slot, - max_loadout_slots, - } = data; - - const [tutorialStatus] = useLocalState('tutorialStatus', false); + const { mob_name, job_clothes, loadout_preview_view, current_slot } = data; + const { slots, tutorialStatus } = props; const loadoutSlots = (maxSlots: number) => { const slots: number[] = []; @@ -344,13 +379,14 @@ const LoadoutPreviewSection = () => { - {loadoutSlots(max_loadout_slots).map((slot) => ( + {loadoutSlots(slots).map((slot) => ( ))} diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts b/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts index 2ce4e171bd3e..eb13e7d5fddc 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/data.ts @@ -1,6 +1,9 @@ import { BooleanLike } from 'common/react'; import { sendAct } from '../../backend'; +import { Language } from './_LanguagePicker'; // NON-MODULE CHANGE +import { LimbCategory } from './_LimbManager'; // NON-MODULE CHANGE +import { LoadoutCategory } from './_LoadoutManager'; // NON-MODULE CHANGE import { Gender } from './preferences/gender'; export enum Food { @@ -191,5 +194,20 @@ export type ServerData = { randomizable: string[]; }; species: Record; + // NON-MODULE CHANGE + loadout: { + tutorial_text: string; + loadout_tabs: LoadoutCategory[]; + max_loadout_slots: number; + }; + limbs: { + limbs: LimbCategory[]; + }; + language: { + base_languages: Language[]; + bonus_languages: Language[]; + blacklisted_species: string[]; + }; + // NON-MODULE CHANGE END [otheyKey: string]: unknown; }; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx index bd7562ce570f..0a6ed46915ad 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx @@ -1,6 +1,12 @@ import { sortBy, sortStrings } from 'common/collections'; import { BooleanLike, classes } from 'common/react'; -import { ComponentType, createElement, ReactNode, useState } from 'react'; +import { + ComponentType, + createElement, + ReactNode, + useEffect, + useState, +} from 'react'; import { sendAct, useBackend } from '../../../../backend'; import { @@ -348,6 +354,10 @@ export const FeatureValueInput = (props: { createSetPreference(props.act, props.featureId)(newValue); }; + useEffect(() => { + setPredictedValue(props.value); + }, [data.active_slot, props.value]); + return ( { diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/_height.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/_height.tsx similarity index 100% rename from tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/_height.tsx rename to tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/_height.tsx diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/_multiline_text.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/_multiline_text.tsx similarity index 54% rename from tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/_multiline_text.tsx rename to tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/_multiline_text.tsx index 19361659b38b..fcb14f0f2ec3 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/game_preferences/_multiline_text.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/_multiline_text.tsx @@ -1,43 +1,51 @@ -import { Stack, TextArea } from '../../../../../components'; -import { Feature, FeatureValueProps } from '../base'; +import { Box, TextArea } from '../../../../../components'; +import { Feature, FeatureShortTextData, FeatureValueProps } from '../base'; + +export type FeatureMultiline = Feature; +export type FeatureMultilineProps = FeatureValueProps< + string, + string, + FeatureShortTextData +>; export const MultilineText = ( - props: FeatureValueProps & { box_height: string | null }, + props: FeatureMultilineProps & { + box_height: string | null; + }, ) => { - const { handleSetValue, value } = props; + if (!props.serverData) { + return Loading...; + } return ( - - -