fix: update @unraid/shared-callbacks to version 3.0.0 (#1831)

…on and pnpm-lock.yaml

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added a standalone redirect page that shows "Redirecting..." and
navigates automatically.

* **Improvements**
* Redirect preserves hash callback data, validates targets, and logs the
computed redirect.
  * Purchase callback origin changed to a different account host.
* Date/time formatting now tolerates missing or empty server formats
with safe fallbacks.
  * Redirect page included in backup/restore.

* **Tests**
  * Added tests covering date/time formatting fallbacks.

* **Chores**
  * Dependency @unraid/shared-callbacks upgraded.
  * Removed multiple demo/debug pages and related test UIs.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
Eli Bosley
2025-12-15 16:20:18 -05:00
committed by GitHub
parent d6e29395c8
commit 73b2ce360c
22 changed files with 276 additions and 1439 deletions

View File

@@ -0,0 +1,91 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Redirect Page</title>
</head>
<body>
<div id="text" style="text-align: center; margin-top: calc(100vh - 75%); display: none; font-family: sans-serif;">
<h1>Redirecting...</h1>
<h2><a id="redirectButton" href="/Main">Click here if you are not redirected automatically</a></h2>
</div>
<script>
(function () {
function parseRedirectTarget(target) {
if (target && target !== '/') {
// Parse target and ensure it is a bare path with no query parameters.
// This keeps us on the same origin and avoids arbitrary redirects.
try {
const url = new URL(target, window.location.origin);
return url.pathname || '/Main';
} catch (_e) {
// If the target is malformed, fall back safely.
return '/Main';
}
}
return '/Main';
}
function getRedirectUrl() {
const search = new URLSearchParams(window.location.search);
const rawHash = window.location.hash || '';
const hashString = rawHash.charAt(0) === '#' ? rawHash.substring(1) : rawHash;
let hashData = '';
if (hashString.startsWith('data=')) {
hashData = hashString.slice('data='.length);
}
const targetRoute = parseRedirectTarget(search.get('target'));
const baseUrl = `${window.location.origin}${targetRoute}`;
// If the incoming URL already has a hash-based data payload, preserve it exactly.
if (hashData) {
return `${baseUrl}#data=${hashData}`;
}
// Fallback: accept legacy ?data= input and convert it to hash-based data.
const queryData = search.get('data');
if (queryData) {
const encoded = encodeURIComponent(queryData);
return `${baseUrl}#data=${encoded}`;
}
return baseUrl;
}
function showText() {
const textEl = document.getElementById('text');
if (textEl) {
textEl.style.display = 'block';
}
}
function startRedirect() {
setTimeout(showText, 750);
const redirectUrl = getRedirectUrl();
console.log('[redirect.htm] redirecting to:', redirectUrl);
const link = document.getElementById('redirectButton');
if (link) {
link.setAttribute('href', redirectUrl);
}
window.location.href = redirectUrl;
}
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', startRedirect);
} else {
startRedirect();
}
})();
</script>
</body>
</html>