[MIRROR] Converts some of tgui-panel to typescript [MDB IGNORE] (#25529)

Converts some of tgui-panel to typescript

Co-authored-by: Jeremiah <42397676+jlsnow301@users.noreply.github.com>
Co-authored-by: Giz <13398309+vinylspiders@users.noreply.github.com>
This commit is contained in:
SkyratBot
2023-12-10 05:49:30 +01:00
committed by GitHub
parent f8ea5afafd
commit 0f3ee0c7ce
26 changed files with 96 additions and 102 deletions

View File

@@ -29,7 +29,7 @@
"@babel/preset-typescript": "^7.23.3",
"@types/jest": "^29.5.10",
"@types/jsdom": "^21.1.6",
"@types/node": "14.x",
"@types/node": "^14.x",
"@types/webpack": "^5.28.5",
"@types/webpack-env": "^1.18.4",
"@typescript-eslint/parser": "^5.62.0",

View File

@@ -15,10 +15,6 @@ import { ReconnectButton } from './reconnect';
import { SettingsPanel, useSettings } from './settings';
export const Panel = (props) => {
// IE8-10: Needs special treatment due to missing Flex support
if (Byond.IS_LTE_IE10) {
return <HoboPanel />;
}
const audio = useAudio();
const settings = useSettings();
const game = useGame();
@@ -29,6 +25,7 @@ export const Panel = (props) => {
return <KitchenSink panel />;
}
}
return (
<Pane theme={settings.theme}>
<Stack fill vertical>
@@ -102,28 +99,3 @@ export const Panel = (props) => {
</Pane>
);
};
const HoboPanel = (props) => {
const settings = useSettings();
return (
<Pane theme={settings.theme}>
<Pane.Content scrollable>
<Button
style={{
position: 'fixed',
top: '1em',
right: '2em',
zIndex: 1000,
}}
selected={settings.visible}
onClick={() => settings.toggle()}
>
Settings
</Button>
{(settings.visible && <SettingsPanel />) || (
<ChatPanel lineHeight={settings.lineHeight} />
)}
</Pane.Content>
</Pane>
);
};

View File

@@ -10,10 +10,6 @@ const logger = createLogger('AudioPlayer');
export class AudioPlayer {
constructor() {
// Doesn't support HTMLAudioElement
if (Byond.IS_LTE_IE9) {
return;
}
// Set up the HTMLAudioElement node
this.node = document.createElement('audio');
this.node.style.setProperty('display', 'none');

View File

@@ -317,15 +317,14 @@ class ChatRenderer {
const to = Math.max(0, len - COMBINE_MAX_MESSAGES);
for (let i = from; i >= to; i--) {
const message = this.visibleMessages[i];
// prettier-ignore
const matches = (
const matches =
// Is not an internal message
!message.type.startsWith(MESSAGE_TYPE_INTERNAL)
!message.type.startsWith(MESSAGE_TYPE_INTERNAL) &&
// Text payload must fully match
&& isSameMessage(message, predicate)
isSameMessage(message, predicate) &&
// Must land within the specified time window
&& now < message.createdAt + COMBINE_MAX_TIME_WINDOW
);
now < message.createdAt + COMBINE_MAX_TIME_WINDOW;
if (matches) {
return message;
}
@@ -457,11 +456,13 @@ class ChatRenderer {
if (!message.type) {
// IE8: Does not support querySelector on elements that
// are not yet in the document.
// prettier-ignore
const typeDef = !Byond.IS_LTE_IE8 && MESSAGE_TYPES
.find(typeDef => (
typeDef.selector && node.querySelector(typeDef.selector)
));
const typeDef =
!Byond.IS_LTE_IE8 &&
MESSAGE_TYPES.find(
(typeDef) =>
typeDef.selector && node.querySelector(typeDef.selector),
);
message.type = typeDef?.type || MESSAGE_TYPE_UNKNOWN;
}
updateMessageBadge(message);
@@ -516,10 +517,10 @@ class ChatRenderer {
message.node = 'pruned';
}
// Remove pruned messages from the message array
// prettier-ignore
this.messages = this.messages.filter(message => (
message.node !== 'pruned'
));
this.messages = this.messages.filter(
(message) => message.node !== 'pruned',
);
logger.log(`pruned ${fromIndex} visible messages`);
}
}
@@ -586,19 +587,22 @@ class ChatRenderer {
}
}
// Create a page
// prettier-ignore
const pageHtml = '<!doctype html>\n'
+ '<html>\n'
+ '<head>\n'
+ '<title>SS13 Chat Log</title>\n'
+ '<style>\n' + cssText + '</style>\n'
+ '</head>\n'
+ '<body>\n'
+ '<div class="Chat">\n'
+ messagesHtml
+ '</div>\n'
+ '</body>\n'
+ '</html>\n';
const pageHtml =
'<!doctype html>\n' +
'<html>\n' +
'<head>\n' +
'<title>SS13 Chat Log</title>\n' +
'<style>\n' +
cssText +
'</style>\n' +
'</head>\n' +
'<body>\n' +
'<div class="Chat">\n' +
messagesHtml +
'</div>\n' +
'</body>\n' +
'</html>\n';
// Create and send a nice blob
const blob = new Blob([pageHtml]);
const timestamp = new Date()

View File

@@ -171,8 +171,8 @@ export const highlightNode = (
// Linkify
// --------------------------------------------------------
// prettier-ignore
const URL_REGEX = /(?:(?:https?:\/\/)|(?:www\.))(?:[^ ]*?\.[^ ]*?)+[-A-Za-z0-9+&@#/%?=~_|$!:,.;(){}]+/ig;
const URL_REGEX =
/(?:(?:https?:\/\/)|(?:www\.))(?:[^ ]*?\.[^ ]*?)+[-A-Za-z0-9+&@#/%?=~_|$!:,.;(){}]+/gi;
/**
* Highlights the text in the node based on the provided regular expression.

View File

@@ -9,7 +9,7 @@ import { map } from 'common/collections';
export const selectChat = (state) => state.chat;
export const selectChatPages = (state) =>
map((id) => state.chat.pageById[id])(state.chat.pages);
map((id: string) => state.chat.pageById[id])(state.chat.pages);
export const selectCurrentChatPage = (state) =>
state.chat.pageById[state.chat.currentPageId];

View File

@@ -16,7 +16,7 @@ const initialState = {
};
export const gameReducer = (state = initialState, action) => {
const { type, payload, meta } = action;
const { type, meta } = action;
if (type === 'roundrestart') {
return {
...state,

View File

@@ -85,7 +85,7 @@ const setupApp = () => {
});
// Resize the panel to match the non-browser output
Byond.winget('output').then((output) => {
Byond.winget('output').then((output: { size: string }) => {
Byond.winset('browseroutput', {
size: output.size,
});
@@ -94,19 +94,22 @@ const setupApp = () => {
// Enable hot module reloading
if (module.hot) {
setupHotReloading();
// prettier-ignore
module.hot.accept([
'./audio',
'./chat',
'./game',
'./Notifications',
'./Panel',
'./ping',
'./settings',
'./telemetry',
], () => {
renderApp();
});
module.hot.accept(
[
'./audio',
'./chat',
'./game',
'./Notifications',
'./Panel',
'./ping',
'./settings',
'./telemetry',
],
() => {
renderApp();
},
);
}
};

View File

@@ -1,9 +1,10 @@
{
"private": true,
"name": "tgui-panel",
"version": "4.3.2",
"version": "5.0.0",
"dependencies": {
"@types/react": "^18.2.39",
"@types/node": "^14.x",
"@types/react": "^18.2.42",
"common": "workspace:*",
"dompurify": "^2.4.4",
"react": "^18.2.0",

View File

@@ -12,7 +12,14 @@ import {
PING_ROUNDTRIP_WORST,
} from './constants';
export const pingReducer = (state = {}, action) => {
type PingState = {
roundtrip: number | undefined;
roundtripAvg: number | undefined;
failCount: number;
networkQuality: number;
};
export const pingReducer = (state = {} as PingState, action) => {
const { type, payload } = action;
if (type === pingSuccess.type) {
@@ -34,7 +41,7 @@ export const pingReducer = (state = {}, action) => {
const networkQuality = clamp01(
state.networkQuality - failCount / PING_MAX_FAILS,
);
const nextState = {
const nextState: PingState = {
...state,
failCount: failCount + 1,
networkQuality,

View File

@@ -3,7 +3,7 @@
*/
import { createUuid } from 'common/uuid';
export const createHighlightSetting = (obj) => ({
export const createHighlightSetting = (obj?: Record<string, any>) => ({
id: createUuid(),
highlightText: '',
highlightColor: '#ffdd44',
@@ -13,7 +13,7 @@ export const createHighlightSetting = (obj) => ({
...obj,
});
export const createDefaultHighlightSetting = (obj) =>
export const createDefaultHighlightSetting = (obj?: Record<string, any>) =>
createHighlightSetting({
id: 'default',
...obj,

View File

@@ -11,12 +11,10 @@ const logger = createLogger('telemetry');
const MAX_CONNECTIONS_STORED = 10;
// prettier-ignore
const connectionsMatch = (a, b) => (
a.ckey === b.ckey
&& a.address === b.address
&& a.computer_id === b.computer_id
);
const connectionsMatch = (a, b) =>
a.ckey === b.ckey &&
a.address === b.address &&
a.computer_id === b.computer_id;
export const telemetryMiddleware = (store) => {
let telemetry;
@@ -58,9 +56,10 @@ export const telemetryMiddleware = (store) => {
}
// Append a connection record
let telemetryMutated = false;
// prettier-ignore
const duplicateConnection = telemetry.connections
.find(conn => connectionsMatch(conn, client));
const duplicateConnection = telemetry.connections.find((conn) =>
connectionsMatch(conn, client),
);
if (!duplicateConnection) {
telemetryMutated = true;
telemetry.connections.unshift(client);

View File

@@ -10,7 +10,7 @@ const COLOR_DARK_BG = '#202020';
const COLOR_DARK_BG_DARKER = '#171717';
const COLOR_DARK_TEXT = '#a4bad6';
let setClientThemeTimer = null;
let setClientThemeTimer: NodeJS.Timeout;
/**
* Darkmode preference, originally by Kmc2000.

View File

@@ -2487,10 +2487,10 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:14.x":
version: 14.18.36
resolution: "@types/node@npm:14.18.36"
checksum: da7f479b3fc996d585e60b8329987c6e310ddbf051e14f2d900ce04f7768f42fa7b760f0eb376008d3eca130ce9431018fb5c9e44027dcb7bb139c547e44b9c5
"@types/node@npm:^14.x":
version: 14.18.63
resolution: "@types/node@npm:14.18.63"
checksum: be909061a54931778c71c49dc562586c32f909c4b6197e3d71e6dac726d8bd9fccb9f599c0df99f52742b68153712b5097c0f00cac4e279fa894b0ea6719a8fd
languageName: node
linkType: hard
@@ -2521,6 +2521,17 @@ __metadata:
languageName: node
linkType: hard
"@types/react@npm:^18.2.42":
version: 18.2.42
resolution: "@types/react@npm:18.2.42"
dependencies:
"@types/prop-types": "*"
"@types/scheduler": "*"
csstype: ^3.0.2
checksum: d2019afdf48303a3a598a97cc9dd2284e3c04b369e791f6ba3c33232b7f8645daff97b093a19f8b3ce75ac8a261b47552cb4513226ab16d843eb9443b0f91844
languageName: node
linkType: hard
"@types/scheduler@npm:*":
version: 0.16.8
resolution: "@types/scheduler@npm:0.16.8"
@@ -10131,7 +10142,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "tgui-panel@workspace:packages/tgui-panel"
dependencies:
"@types/react": ^18.2.39
"@types/node": ^14.x
"@types/react": ^18.2.42
common: "workspace:*"
dompurify: ^2.4.4
react: ^18.2.0
@@ -10178,7 +10190,7 @@ __metadata:
"@babel/preset-typescript": ^7.23.3
"@types/jest": ^29.5.10
"@types/jsdom": ^21.1.6
"@types/node": 14.x
"@types/node": ^14.x
"@types/webpack": ^5.28.5
"@types/webpack-env": ^1.18.4
"@typescript-eslint/parser": ^5.62.0