mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-07-16 17:44:25 +01:00
replace_html & DPI Scaling support
This commit is contained in:
@@ -298,6 +298,17 @@
|
||||
: "[id].browser:update")
|
||||
message_queue = null
|
||||
|
||||
/**
|
||||
* public
|
||||
*
|
||||
* Replaces the inline HTML content.
|
||||
*
|
||||
* required inline_html string HTML to inject
|
||||
*/
|
||||
/datum/tgui_window/proc/replace_html(inline_html = "")
|
||||
client << output(url_encode(inline_html), is_browser \
|
||||
? "[id]:replaceHtml" \
|
||||
: "[id].browser:replaceHtml")
|
||||
|
||||
/**
|
||||
* private
|
||||
|
||||
@@ -217,8 +217,13 @@
|
||||
|
||||
$wrap.width($wrap.width() + 2); //Dumb hack to fix a bizarre sizing bug
|
||||
|
||||
var docWidth = $wrap.outerWidth(),
|
||||
docHeight = $wrap.outerHeight();
|
||||
var pixelRatio = 1;
|
||||
if (window.devicePixelRatio) {
|
||||
pixelRatio = window.devicePixelRatio;
|
||||
}
|
||||
|
||||
var docWidth = Math.floor($wrap.outerWidth() * pixelRatio),
|
||||
docHeight = Math.floor($wrap.outerHeight() * pixelRatio);
|
||||
|
||||
if (posY + docHeight > map.size.y) { //Is the bottom edge below the window? Snap it up if so
|
||||
posY = (posY - docHeight) - realIconSize - tooltip.padding;
|
||||
|
||||
@@ -376,6 +376,7 @@ rules:
|
||||
ignoreUrls: true,
|
||||
ignoreRegExpLiterals: true,
|
||||
ignoreStrings: true,
|
||||
ignoreTemplateLiterals: true,
|
||||
}]
|
||||
## Enforce a maximum number of lines per file
|
||||
# max-lines: error
|
||||
|
||||
@@ -247,7 +247,7 @@ type BackendState<TData> = {
|
||||
shared: Record<string, any>,
|
||||
suspending: boolean,
|
||||
suspended: boolean,
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Selects a backend-related slice of Redux state
|
||||
@@ -257,12 +257,9 @@ export const selectBackend = <TData>(state: any): BackendState<TData> => (
|
||||
);
|
||||
|
||||
/**
|
||||
* A React hook (sort of) for getting tgui state and related functions.
|
||||
* Get data from tgui backend.
|
||||
*
|
||||
* This is supposed to be replaced with a real React Hook, which can only
|
||||
* be used in functional components.
|
||||
*
|
||||
* You can make
|
||||
* Includes the `act` function for performing DM actions.
|
||||
*/
|
||||
export const useBackend = <TData>(context: any) => {
|
||||
const { store } = context;
|
||||
|
||||
@@ -54,18 +54,19 @@ window.addEventListener('beforeunload', () => {
|
||||
});
|
||||
|
||||
/**
|
||||
* Get the bounding box of the DOM element.
|
||||
* Get the bounding box of the DOM element in display-pixels.
|
||||
*/
|
||||
const getBoundingBox = element => {
|
||||
const pixelRatio = window.devicePixelRatio ?? 1;
|
||||
const rect = element.getBoundingClientRect();
|
||||
return {
|
||||
pos: [
|
||||
rect.left,
|
||||
rect.top,
|
||||
rect.left * pixelRatio,
|
||||
rect.top * pixelRatio,
|
||||
],
|
||||
size: [
|
||||
rect.right - rect.left,
|
||||
rect.bottom - rect.top,
|
||||
(rect.right - rect.left) * pixelRatio,
|
||||
(rect.bottom - rect.top) * pixelRatio,
|
||||
],
|
||||
};
|
||||
};
|
||||
|
||||
+49
-39
@@ -5,10 +5,11 @@
|
||||
*/
|
||||
|
||||
import { storage } from 'common/storage';
|
||||
import { vecAdd, vecInverse, vecMultiply, vecScale } from 'common/vector';
|
||||
import { vecAdd, vecSubtract, vecMultiply, vecScale } from 'common/vector';
|
||||
import { createLogger } from './logging';
|
||||
|
||||
const logger = createLogger('drag');
|
||||
const pixelRatio = window.devicePixelRatio ?? 1;
|
||||
|
||||
let windowKey = Byond.windowId;
|
||||
let dragging = false;
|
||||
@@ -24,37 +25,37 @@ export const setWindowKey = key => {
|
||||
windowKey = key;
|
||||
};
|
||||
|
||||
export const getWindowPosition = () => [
|
||||
window.screenLeft,
|
||||
window.screenTop,
|
||||
const getWindowPosition = () => [
|
||||
window.screenLeft * pixelRatio,
|
||||
window.screenTop * pixelRatio,
|
||||
];
|
||||
|
||||
export const getWindowSize = () => [
|
||||
window.innerWidth,
|
||||
window.innerHeight,
|
||||
const getWindowSize = () => [
|
||||
window.innerWidth * pixelRatio,
|
||||
window.innerHeight * pixelRatio,
|
||||
];
|
||||
|
||||
export const setWindowPosition = vec => {
|
||||
const setWindowPosition = vec => {
|
||||
const byondPos = vecAdd(vec, screenOffset);
|
||||
return Byond.winset(Byond.windowId, {
|
||||
pos: byondPos[0] + ',' + byondPos[1],
|
||||
});
|
||||
};
|
||||
|
||||
export const setWindowSize = vec => {
|
||||
const setWindowSize = vec => {
|
||||
return Byond.winset(Byond.windowId, {
|
||||
size: vec[0] + 'x' + vec[1],
|
||||
});
|
||||
};
|
||||
|
||||
export const getScreenPosition = () => [
|
||||
const getScreenPosition = () => [
|
||||
0 - screenOffset[0],
|
||||
0 - screenOffset[1],
|
||||
];
|
||||
|
||||
export const getScreenSize = () => [
|
||||
window.screen.availWidth,
|
||||
window.screen.availHeight,
|
||||
const getScreenSize = () => [
|
||||
window.screen.availWidth * pixelRatio,
|
||||
window.screen.availHeight * pixelRatio,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -83,7 +84,7 @@ const touchRecents = (recents, touchedItem, limit = 50) => {
|
||||
return [nextRecents, trimmedItem];
|
||||
};
|
||||
|
||||
export const storeWindowGeometry = async () => {
|
||||
const storeWindowGeometry = async () => {
|
||||
logger.log('storing geometry');
|
||||
const geometry = {
|
||||
pos: getWindowPosition(),
|
||||
@@ -106,14 +107,19 @@ export const recallWindowGeometry = async (options = {}) => {
|
||||
if (geometry) {
|
||||
logger.log('recalled geometry:', geometry);
|
||||
}
|
||||
// options.pos is assumed to already be in display-pixels
|
||||
let pos = geometry?.pos || options.pos;
|
||||
let size = options.size;
|
||||
// Convert size from css-pixels to display-pixels
|
||||
if (size) {
|
||||
size = [
|
||||
size[0] * pixelRatio,
|
||||
size[1] * pixelRatio,
|
||||
];
|
||||
}
|
||||
// Wait until screen offset gets resolved
|
||||
await screenOffsetPromise;
|
||||
const areaAvailable = [
|
||||
window.screen.availWidth,
|
||||
window.screen.availHeight,
|
||||
];
|
||||
const areaAvailable = getScreenSize();
|
||||
// Set window size
|
||||
if (size) {
|
||||
// Constraint size to not exceed available screen area.
|
||||
@@ -143,10 +149,12 @@ export const recallWindowGeometry = async (options = {}) => {
|
||||
|
||||
export const setupDrag = async () => {
|
||||
// Calculate screen offset caused by the windows taskbar
|
||||
let windowPosition = getWindowPosition();
|
||||
|
||||
screenOffsetPromise = Byond.winget(Byond.windowId, 'pos')
|
||||
.then(pos => [
|
||||
pos.x - window.screenLeft,
|
||||
pos.y - window.screenTop,
|
||||
pos.x - windowPosition[0],
|
||||
pos.y - windowPosition[1],
|
||||
]);
|
||||
screenOffset = await screenOffsetPromise;
|
||||
logger.debug('screen offset', screenOffset);
|
||||
@@ -179,10 +187,10 @@ const constraintPosition = (pos, size) => {
|
||||
export const dragStartHandler = event => {
|
||||
logger.log('drag start');
|
||||
dragging = true;
|
||||
dragPointOffset = [
|
||||
window.screenLeft - event.screenX,
|
||||
window.screenTop - event.screenY,
|
||||
];
|
||||
let windowPosition = getWindowPosition();
|
||||
dragPointOffset = vecSubtract(
|
||||
[event.screenX, event.screenY],
|
||||
getWindowPosition());
|
||||
// Focus click target
|
||||
event.target?.focus();
|
||||
document.addEventListener('mousemove', dragMoveHandler);
|
||||
@@ -204,7 +212,7 @@ const dragMoveHandler = event => {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
setWindowPosition(vecAdd(
|
||||
setWindowPosition(vecSubtract(
|
||||
[event.screenX, event.screenY],
|
||||
dragPointOffset));
|
||||
};
|
||||
@@ -213,14 +221,10 @@ export const resizeStartHandler = (x, y) => event => {
|
||||
resizeMatrix = [x, y];
|
||||
logger.log('resize start', resizeMatrix);
|
||||
resizing = true;
|
||||
dragPointOffset = [
|
||||
window.screenLeft - event.screenX,
|
||||
window.screenTop - event.screenY,
|
||||
];
|
||||
initialSize = [
|
||||
window.innerWidth,
|
||||
window.innerHeight,
|
||||
];
|
||||
dragPointOffset = vecSubtract(
|
||||
[event.screenX, event.screenY],
|
||||
getWindowPosition());
|
||||
initialSize = getWindowSize();
|
||||
// Focus click target
|
||||
event.target?.focus();
|
||||
document.addEventListener('mousemove', resizeMoveHandler);
|
||||
@@ -242,13 +246,19 @@ const resizeMoveHandler = event => {
|
||||
return;
|
||||
}
|
||||
event.preventDefault();
|
||||
size = vecAdd(initialSize, vecMultiply(resizeMatrix, vecAdd(
|
||||
const currentOffset = vecSubtract(
|
||||
[event.screenX, event.screenY],
|
||||
vecInverse([window.screenLeft, window.screenTop]),
|
||||
dragPointOffset,
|
||||
[1, 1])));
|
||||
getWindowPosition());
|
||||
const delta = vecSubtract(
|
||||
currentOffset,
|
||||
dragPointOffset);
|
||||
// Extra 1x1 area is added to ensure the browser can see the cursor
|
||||
size = vecAdd(
|
||||
initialSize,
|
||||
vecMultiply(resizeMatrix, delta),
|
||||
[1, 1]);
|
||||
// Sane window size values
|
||||
size[0] = Math.max(size[0], 150);
|
||||
size[1] = Math.max(size[1], 50);
|
||||
size[0] = Math.max(size[0], 150 * pixelRatio);
|
||||
size[1] = Math.max(size[1], 50 * pixelRatio);
|
||||
setWindowSize(size);
|
||||
};
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -471,6 +471,26 @@ window.update.flushQueue = function (listener) {
|
||||
}
|
||||
};
|
||||
|
||||
window.replaceHtml = function (inline_html) {
|
||||
var children = document.body.childNodes;
|
||||
|
||||
for (var i = 0; i < children.length; i++) {
|
||||
if (children[i].nodeValue == " tgui:inline-html-start ") {
|
||||
while (children[i].nodeValue != " tgui:inline-html-end ") {
|
||||
children[i].remove();
|
||||
}
|
||||
children[i].remove();
|
||||
}
|
||||
}
|
||||
|
||||
document.body.insertAdjacentHTML(
|
||||
"afterbegin",
|
||||
"<!-- tgui:inline-html-start -->"
|
||||
+ inline_html
|
||||
+ "<!-- tgui:inline-html-end -->"
|
||||
);
|
||||
};
|
||||
|
||||
// Signal tgui that we're ready to receive updates
|
||||
Byond.sendMessage('ready');
|
||||
</script>
|
||||
@@ -567,7 +587,9 @@ Byond.sendMessage('ready');
|
||||
|
||||
<!-- tgui:inline-polyfill -->
|
||||
<!-- tgui:assets -->
|
||||
<!-- tgui:inline-html-start -->
|
||||
<!-- tgui:inline-html -->
|
||||
<!-- tgui:inline-html-end -->
|
||||
<!-- tgui:inline-js -->
|
||||
|
||||
<!-- Root element for tgui interfaces -->
|
||||
|
||||
Reference in New Issue
Block a user