diff --git a/code/controllers/subsystems/media_tracks.dm b/code/controllers/subsystems/media_tracks.dm index aaa182a040..295f536e07 100644 --- a/code/controllers/subsystems/media_tracks.dm +++ b/code/controllers/subsystems/media_tracks.dm @@ -202,6 +202,28 @@ SUBSYSTEM_DEF(media_tracks) to_chat(C, "") +/datum/controller/subsystem/media_tracks/proc/add_track(var/mob/user, var/new_url, var/new_title, var/new_duration, var/new_artist, var/new_genre, var/new_secret, var/new_lobby) + if(!check_rights(R_DEBUG|R_FUN)) + return + var/datum/track/T = new(new_url, new_title, new_duration, new_artist, new_genre, new_secret, new_lobby) + all_tracks += T + report_progress("Media track added by [user]: [T.title]") + sort_tracks() + return + +/datum/controller/subsystem/media_tracks/proc/remove_track(var/mob/user, var/datum/track/T) + if(!check_rights(R_DEBUG|R_FUN)) + return + + if(!T) + return + + report_progress("Media track removed by [user]: [T.title]") + all_tracks -= T + qdel(T) + sort_tracks() + return + /datum/controller/subsystem/media_tracks/vv_get_dropdown() . = ..() VV_DROPDOWN_OPTION("", "---") diff --git a/code/game/machinery/jukebox.dm b/code/game/machinery/jukebox.dm index 9446102a49..f28b6334d3 100644 --- a/code/game/machinery/jukebox.dm +++ b/code/game/machinery/jukebox.dm @@ -196,6 +196,7 @@ for(var/datum/track/T in getTracksList()) tgui_tracks.Add(list(T.toTguiList())) data["tracks"] = tgui_tracks + data["admin"] = is_admin(user) return data @@ -245,6 +246,13 @@ else StartPlaying() return TRUE + if("add_new_track") + SSmedia_tracks.add_track(usr, params["url"], params["title"], text2num(params["duration"]) * 10, params["artist"], params["genre"], text2num(params["secret"]), text2num(params["lobby"])) + if("remove_new_track") + var/datum/track/track_to_remove = locate(params["ref"]) in getTracksList() + if(track_to_remove == current_track && playing) + StopPlaying() + SSmedia_tracks.remove_track(usr, track_to_remove) /obj/machinery/media/jukebox/attack_ai(mob/user as mob) return src.attack_hand(user) diff --git a/code/modules/vore/eating/vorepanel_vr.dm b/code/modules/vore/eating/vorepanel_vr.dm index f7d598515c..ee9242d3ba 100644 --- a/code/modules/vore/eating/vorepanel_vr.dm +++ b/code/modules/vore/eating/vorepanel_vr.dm @@ -2925,57 +2925,57 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono", host.weight_messages[index] = new_message if("im_digest") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Digest mode. Write them in 2nd person ('%pred's %belly squishes down on you.')."+help,"Idle Message (Digest)",host.vore_selected.get_messages("im_digest"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Digest mode. Write them in 2nd person ('%pred's %belly squishes down on you.')."+help,"Idle Message (Digest)",host.vore_selected.get_messages("im_digest"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_digest") if("im_hold") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Hold mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Hold)",host.vore_selected.get_messages("im_hold"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Hold mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Hold)",host.vore_selected.get_messages("im_hold"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_hold") if("im_holdabsorbed") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are absorbed. Write them in 2nd person ('%pred's %belly squishes down on you.') %count will not work for this type, and %countprey will only count absorbed victims."+help,"Idle Message (Hold Absorbed)",host.vore_selected.get_messages("im_holdabsorbed"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are absorbed. Write them in 2nd person ('%pred's %belly squishes down on you.') %count will not work for this type, and %countprey will only count absorbed victims."+help,"Idle Message (Hold Absorbed)",host.vore_selected.get_messages("im_holdabsorbed"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_holdabsorbed") if("im_absorb") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Absorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Absorb)",host.vore_selected.get_messages("im_absorb"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Absorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Absorb)",host.vore_selected.get_messages("im_absorb"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_absorb") if("im_heal") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Heal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Heal)",host.vore_selected.get_messages("im_heal"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Heal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Heal)",host.vore_selected.get_messages("im_heal"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_heal") if("im_drain") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Drain mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Drain)",host.vore_selected.get_messages("im_drain"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Drain mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Drain)",host.vore_selected.get_messages("im_drain"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_drain") if("im_steal") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Size Steal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Size Steal)",host.vore_selected.get_messages("im_steal"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Size Steal mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Size Steal)",host.vore_selected.get_messages("im_steal"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_steal") if("im_egg") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Encase In Egg mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Encase In Egg)",host.vore_selected.get_messages("im_egg"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Encase In Egg mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Encase In Egg)",host.vore_selected.get_messages("im_egg"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_egg") if("im_shrink") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Shrink mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Shrink)",host.vore_selected.get_messages("im_shrink"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Shrink mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Shrink)",host.vore_selected.get_messages("im_shrink"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_shrink") if("im_grow") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Grow mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Grow)",host.vore_selected.get_messages("im_grow"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Grow mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Grow)",host.vore_selected.get_messages("im_grow"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_grow") if("im_unabsorb") - var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every minute when you are on Unabsorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Unabsorb)",host.vore_selected.get_messages("im_unabsorb"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) + var/new_message = sanitize(tgui_input_text(user,"These are sent to prey every [host.vore_selected.emote_time] seconds when you are on Unabsorb mode. Write them in 2nd person ('%pred's %belly squishes down on you.')"+help,"Idle Message (Unabsorb)",host.vore_selected.get_messages("im_unabsorb"), multiline = TRUE, prevent_enter = TRUE),MAX_MESSAGE_LEN,0,0,0) if(new_message) host.vore_selected.set_messages(new_message,"im_unabsorb") diff --git a/tgui/packages/tgui/interfaces/Jukebox.jsx b/tgui/packages/tgui/interfaces/Jukebox.jsx index f0a4fb30cc..d265ad7c80 100644 --- a/tgui/packages/tgui/interfaces/Jukebox.jsx +++ b/tgui/packages/tgui/interfaces/Jukebox.jsx @@ -1,15 +1,22 @@ import { round } from 'common/math'; +import { capitalize } from 'common/string'; +import { useState } from 'react'; import { useBackend } from '../backend'; import { Box, Button, Collapsible, + Divider, + Flex, + Input, LabeledList, + NumberInput, ProgressBar, Section, Slider, } from '../components'; +import { formatTime } from '../format'; import { Window } from '../layouts'; export const Jukebox = (props) => { @@ -24,6 +31,7 @@ export const Jukebox = (props) => { current_genre, percent, tracks, + admin, } = data; let genre_songs = @@ -39,6 +47,22 @@ export const Jukebox = (props) => { let true_genre = playing && (current_genre || 'Uncategorized'); + const [newTitle, setNewTitle] = useState('Unknown'); + const [newUrl, setNewUrl] = useState(''); + const [newDuration, setNewDuration] = useState(0); + const [newArtist, setNewArtist] = useState('Unknown'); + const [newGenre, setNewGenre] = useState('Admin'); + const [newSecret, setNewSecret] = useState(false); + const [newLobby, setNewLobby] = useState(false); + const [unlockGenre, setUnlockGenre] = useState(false); + + function handleUnlockGenre() { + if (unlockGenre) { + setNewGenre('Admin'); + } + setUnlockGenre(!unlockGenre); + } + return ( @@ -123,31 +147,181 @@ export const Jukebox = (props) => { {(tracks.length && Object.keys(genre_songs) .sort() - .map((genre) => ( - -
- {genre_songs[genre].map((track) => ( - - ))} -
-
- ))) || Error: No songs loaded.} + .map( + (genre) => + capitalize(genre) !== 'Admin' && ( + +
+ {genre_songs[genre].map((track) => ( + + ))} +
+
+ ), + )) || Error: No songs loaded.} + {admin && ( + <> +
+ {(tracks.length && + Object.keys(genre_songs) + .sort() + .map( + (genre) => + capitalize(genre) === 'Admin' && ( + +
+ {genre_songs[genre].map((track) => ( + + + + + + + act('remove_new_track', { + ref: track.ref, + }) + } + /> + + + ))} +
+
+ ), + )) || Error: No songs added.} +
+
+ + + + setNewTitle(val)} + /> + + + setNewUrl(val)} + /> + + + setNewDuration(val)} + format={(val) => formatTime(round(val * 10))} + /> + + + setNewArtist(val)} + /> + + + + + {unlockGenre ? ( + setNewGenre(val)} + /> + ) : ( + {newGenre} + )} + + + handleUnlockGenre()} + /> + + + + + setNewSecret(!newSecret)} + /> + + + setNewLobby(!newLobby)} + /> + + + + + +
+ + )}
);