replace_html & DPI Scaling support

This commit is contained in:
ItsSelis
2022-05-25 21:40:01 +02:00
parent f8baf84c02
commit e10212d4c8
8 changed files with 100 additions and 53 deletions
+11
View File
@@ -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
+7 -2
View File
@@ -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;
+1
View File
@@ -376,6 +376,7 @@ rules:
ignoreUrls: true,
ignoreRegExpLiterals: true,
ignoreStrings: true,
ignoreTemplateLiterals: true,
}]
## Enforce a maximum number of lines per file
# max-lines: error
+3 -6
View File
@@ -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;
+6 -5
View File
@@ -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
View File
@@ -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
+22
View File
@@ -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 -->