TGUI News & Random PDA fixes

This commit is contained in:
ShadowLarkens
2020-09-16 21:31:50 -07:00
parent 637576848e
commit 12f92da168
5 changed files with 290 additions and 37 deletions
+80 -1
View File
@@ -124,4 +124,83 @@
if(isnull(results))
results = list(list("entry" = "pressure", "units" = "kPa", "val" = "0", "bad_high" = 120, "poor_high" = 110, "poor_low" = 95, "bad_low" = 80))
data["aircontents"] = results
data["aircontents"] = results
/datum/data/pda/app/news
name = "News"
icon = "newspaper"
template = "pda_news"
var/newsfeed_channel
/datum/data/pda/app/news/update_ui(mob/user as mob, list/data)
data["feeds"] = compile_news()
data["latest_news"] = get_recent_news()
if(newsfeed_channel)
data["target_feed"] = data["feeds"][newsfeed_channel]
else
data["target_feed"] = null
/datum/data/pda/app/news/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state)
if(..())
return TRUE
switch(action)
if("newsfeed")
newsfeed_channel = text2num(params["newsfeed"])
/datum/data/pda/app/news/proc/compile_news()
var/list/feeds = list()
for(var/datum/feed_channel/channel in news_network.network_channels)
var/list/messages = list()
if(!channel.censored)
var/index = 0
for(var/datum/feed_message/FM in channel.messages)
index++
var/list/msgdata = list(
"author" = FM.author,
"body" = FM.body,
"img" = null,
"message_type" = FM.message_type,
"time_stamp" = FM.time_stamp,
"caption" = FM.caption,
"index" = index
)
if(FM.img)
msgdata["img"] = icon2base64(FM.img)
messages[++messages.len] = msgdata
feeds[++feeds.len] = list(
"name" = channel.channel_name,
"censored" = channel.censored,
"author" = channel.author,
"messages" = messages,
"index" = feeds.len + 1
)
return feeds
/datum/data/pda/app/news/proc/get_recent_news()
var/list/news = list()
// Compile all the newscasts
for(var/datum/feed_channel/channel in news_network.network_channels)
if(!channel.censored)
for(var/datum/feed_message/FM in channel.messages)
var/body = replacetext(FM.body, "\n", "<br>")
news[++news.len] = list(
"channel" = channel.channel_name,
"author" = FM.author,
"body" = body,
"message_type" = FM.message_type,
"time_stamp" = FM.time_stamp,
"has_image" = (FM.img != null),
"caption" = FM.caption,
"time" = FM.post_time
)
// Cut out all but the youngest three
if(news.len > 3)
sortByKey(news, "time")
news.Cut(1, news.len - 2) // Last three have largest timestamps, youngest posts
news.Swap(1, 3) // List is sorted in ascending order of timestamp, we want descending
return news
+1
View File
@@ -51,6 +51,7 @@ var/global/list/obj/item/device/pda/PDAs = list()
var/list/programs = list(
new/datum/data/pda/app/main_menu,
new/datum/data/pda/app/notekeeper,
new/datum/data/pda/app/news,
new/datum/data/pda/app/messenger,
new/datum/data/pda/app/manifest,
new/datum/data/pda/app/atmos_scanner,
+83 -35
View File
@@ -1,7 +1,7 @@
import { round } from 'common/math';
import { Fragment } from 'inferno';
import { useBackend } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../components";
import { useBackend, useLocalState } from "../backend";
import { Box, Button, Flex, Icon, LabeledList, Modal, ProgressBar, Section } from "../components";
import { Window } from "../layouts";
/* This is all basically stolen from routes.js. */
@@ -49,22 +49,28 @@ export const Pda = (props, context) => {
let App = getPdaApp(app.template);
const [settingsMode, setSettingsMode] = useLocalState(context, 'settingsMode', false);
return (
<Window width={580} height={670} theme={useRetro ? "pda-retro" : null} resizable>
<Window.Content scrollable>
<PDAHeader />
<Section
title={
<Box>
<Icon name={app.icon} mr={1} />
{app.name}
</Box>
}
p={1}>
<App />
</Section>
<PDAHeader settingsMode={settingsMode} setSettingsMode={setSettingsMode} />
{settingsMode && (
<PDASettings />
) || (
<Section
title={
<Box>
<Icon name={app.icon} mr={1} />
{app.name}
</Box>
}
p={1}>
<App />
</Section>
)}
<Box mb={8} />
<PDAFooter />
<PDAFooter setSettingsMode={setSettingsMode} />
</Window.Content>
</Window>
);
@@ -73,6 +79,11 @@ export const Pda = (props, context) => {
const PDAHeader = (props, context) => {
const { act, data } = useBackend(context);
const {
settingsMode,
setSettingsMode,
} = props;
const {
idInserted,
idLink,
@@ -82,45 +93,79 @@ const PDAHeader = (props, context) => {
return (
<Box mb={1}>
<Flex align="center" justify="space-between" pl={1} pr={1}>
<Flex align="center" justify="space-between">
{!!idInserted && (
<Flex.Item>
<Button
color="transparent"
icon="eject"
color="transparent"
onClick={() => act("Authenticate")}
content={idLink} />
</Flex.Item>
)}
{!!cartridge_name && (
<Flex.Item>
<Button
color="transparent"
icon="eject"
onClick={() => act("Eject")}
content={cartridge_name} />
</Flex.Item>
)}
<Flex.Item>
<Button
icon="cog"
color="transparent"
content={"Retro Theme"}
onClick={() => act("Retro")} />
<Flex.Item grow={1} textAlign="center" bold>
{stationTime}
</Flex.Item>
<Flex.Item>
<Box bold>
{stationTime}
</Box>
<Button
selected={settingsMode}
onClick={() => setSettingsMode(!settingsMode)}
icon="cog" />
<Button
onClick={() => act("Retro")}
icon="adjust" />
</Flex.Item>
</Flex>
</Box>
);
};
const PDASettings = (props, context) => {
const { act, data } = useBackend(context);
const {
idInserted,
idLink,
cartridge_name,
} = data;
return (
<Section title="Settings">
<LabeledList>
<LabeledList.Item label="R.E.T.R.O Mode">
<Button
icon="cog"
content={"Retro Theme"}
onClick={() => act("Retro")} />
</LabeledList.Item>
{!!cartridge_name && (
<LabeledList.Item label="Cartridge">
<Button
icon="eject"
onClick={() => act("Eject")}
content={cartridge_name} />
</LabeledList.Item>
)}
{!!idInserted && (
<LabeledList.Item label="ID Card">
<Button
icon="eject"
onClick={() => act("Authenticate")}
content={idLink} />
</LabeledList.Item>
)}
</LabeledList>
</Section>
);
};
const PDAFooter = (props, context) => {
const { act, data } = useBackend(context);
const {
setSettingsMode,
} = props;
const {
app,
useRetro,
@@ -149,7 +194,10 @@ const PDAFooter = (props, context) => {
icon="home"
mb={0}
fontSize={1.7}
onClick={() => act("Home")} />
onClick={() => {
setSettingsMode(false);
act("Home");
}} />
</Flex.Item>
</Flex>
</Box>
@@ -8,7 +8,7 @@ export const pda_manifest = (props, context) => {
const { act, data } = useBackend(context);
return (
<Box>
<Box color="white">
<IdentificationComputerCrewManifest />
</Box>
);
@@ -0,0 +1,125 @@
import { filter } from 'common/collections';
import { decodeHtmlEntities, toTitleCase } from 'common/string';
import { Fragment } from 'inferno';
import { useBackend, useLocalState } from "../../backend";
import { Box, Button, Flex, Icon, LabeledList, ProgressBar, Section } from "../../components";
// Stolen wholesale from communicators. TGUITODO: Merge PDA & Communicator shared code once both are in
/* News */
export const pda_news = (props, context) => {
const { act, data } = useBackend(context);
const {
feeds,
target_feed,
} = data;
return (
<Box>
{!feeds.length && (
<Box color="bad">
Error: No newsfeeds available. Please try again later.
</Box>
) || target_feed && (
<NewsTargetFeed />
) || (
<NewsFeed />
)}
</Box>
);
};
const NewsTargetFeed = (props, context) => {
const { act, data } = useBackend(context);
const {
target_feed,
} = data;
return (
<Section
title={decodeHtmlEntities(target_feed.name) + " by " + decodeHtmlEntities(target_feed.author)}
level={2}
buttons={
<Button
content="Back"
icon="chevron-up"
onClick={() => act("newsfeed", { newsfeed: null })} />
}>
{target_feed.messages.length && target_feed.messages.map(message => (
<Section key={message.ref}>
- {decodeHtmlEntities(message.body)}
{!!message.img && (
<Box>
<img src={"data:image/png;base64," + message.img} />
{decodeHtmlEntities(message.caption) || null}
</Box>
)}
<Box color="grey">
[{message.message_type} by {decodeHtmlEntities(message.author)} - {message.time_stamp}]
</Box>
</Section>
)) || (
<Box>
No stories found in {target_feed.name}.
</Box>
)}
</Section>
);
};
const NewsFeed = (props, context) => {
const { act, data } = useBackend(context);
const {
feeds,
latest_news,
} = data;
return (
<Fragment>
<Section title="Recent News" level={2}>
{latest_news.length && (
<Section>
{latest_news.map(news => (
<Box mb={2} key={news.index}>
<h5>
{decodeHtmlEntities(news.channel)}
<Button
ml={1}
icon="chevron-up"
onClick={() => act("newsfeed", { newsfeed: news.index })}
content="Go to" />
</h5>
- {decodeHtmlEntities(news.body)}
{!!news.img && (
<Box>
[image omitted, view story for more details]
{news.caption || null}
</Box>
)}
<Box fontSize={0.9}>
[{news.message_type} by <Box inline color="average">{news.author}</Box> - {news.time_stamp}]
</Box>
</Box>
))}
</Section>
) || (
<Box>
No recent stories found.
</Box>
)}
</Section>
<Section title="News Feeds" level={2}>
{feeds.map(feed => (
<Button
key={feed.index}
fluid
icon="chevron-up"
onClick={() => act("newsfeed", { newsfeed: feed.index })}
content={feed.name} />
))}
</Section>
</Fragment>
);
};