mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-28 06:28:01 +01:00
TGUI News & Random PDA fixes
This commit is contained in:
@@ -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
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
};
|
||||
Reference in New Issue
Block a user