Add the Re-Nav share page.
This commit is contained in:
parent
4d0fd3e60d
commit
7b11e66551
|
@ -0,0 +1,61 @@
|
|||
{% extends "source/includes/base.html" %}
|
||||
{% import "source/includes/macros.html" as macros %}
|
||||
|
||||
{% set title = "Re-Nav ↩ Share" %}
|
||||
|
||||
{% block head %}
|
||||
<link rel="stylesheet" href="/scss/re-nav/re-nav.scss">
|
||||
<link rel="stylesheet" href="/scss/re-nav/share.scss">
|
||||
{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<header class="page-header">
|
||||
<h1>
|
||||
<img src="../../assets/re-nav.png" alt="Re-Nav Logo">
|
||||
Re-Nav
|
||||
</h1>
|
||||
</header>
|
||||
|
||||
<main class="page-main">
|
||||
<p class="subtitle">
|
||||
Welcome to Re-Nav's share page!
|
||||
<br />
|
||||
Use the share button in Re-Nav's options page to create a link with your
|
||||
redirect.
|
||||
</p>
|
||||
|
||||
<div class="hidden-by-default redirect">
|
||||
<p class="matcher-data">
|
||||
<span class="matcher-type"></span>
|
||||
{{-":"-}}
|
||||
<span class="matcher-value"></span>
|
||||
</p>
|
||||
<p class="arrow">↓</p>
|
||||
<p class="redirect-data">
|
||||
<span class="redirect-type"></span>
|
||||
{{-":"-}}
|
||||
<span class="redirect-value"></span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{#
|
||||
This element will be shown by JS on page load, and if Re-Nav is installed,
|
||||
it will be used as the root container for the import button.
|
||||
#}
|
||||
<div class="hidden-by-default re-nav-import">
|
||||
<p>
|
||||
With <a href="..">Re-Nav</a> installed, you'll see a button here to import
|
||||
this redirect.
|
||||
</p>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="page-footer">
|
||||
©
|
||||
<a href="https://git.bauke.xyz/Holllo/re-nav">AGPL-3.0-or-later</a>
|
||||
💖
|
||||
<a href="mailto:helllo@holllo.org">helllo@holllo.org</a>
|
||||
</footer>
|
||||
|
||||
<script src="../../ts/re-nav/share.ts" type="module"></script>
|
||||
{% endblock %}
|
|
@ -0,0 +1,54 @@
|
|||
.page-main {
|
||||
display: grid;
|
||||
gap: var(--spacing-16);
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
}
|
||||
|
||||
.subtitle {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.redirect {
|
||||
border: 1px solid var(--foreground-1);
|
||||
display: grid;
|
||||
gap: var(--spacing-08);
|
||||
grid-template-columns: repeat(1, 1fr);
|
||||
padding: var(--spacing-16);
|
||||
|
||||
.matcher-data,
|
||||
.redirect-data {
|
||||
background-color: var(--background-color);
|
||||
color: var(--background-1);
|
||||
padding: var(--spacing-16);
|
||||
overflow: auto;
|
||||
text-align: center;
|
||||
|
||||
span {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
.matcher-data {
|
||||
--background-color: var(--da-3);
|
||||
}
|
||||
|
||||
.redirect-data {
|
||||
--background-color: var(--da-7);
|
||||
}
|
||||
|
||||
.arrow {
|
||||
font-weight: bold;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.re-nav-import {
|
||||
p {
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
.hidden-by-default {
|
||||
display: none;
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
import {Base64} from 'js-base64';
|
||||
|
||||
const fragmentPrefix = '#json=';
|
||||
|
||||
const exampleRedirect: Redirect = {
|
||||
matcherType: 'hostname',
|
||||
matcherValue: 'example.com',
|
||||
redirectType: 'hostname',
|
||||
redirectValue: 'example.org',
|
||||
};
|
||||
|
||||
function decodeBase64<T>(base64: string): T {
|
||||
return JSON.parse(Base64.decode(base64)) as T;
|
||||
}
|
||||
|
||||
function encodeBase64(source: any): string {
|
||||
return Base64.encode(JSON.stringify(source), true);
|
||||
}
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
window['Re-Nav'] = {
|
||||
decodeBase64,
|
||||
encodeBase64,
|
||||
share,
|
||||
};
|
||||
|
||||
console.log(
|
||||
"Want to manually create a share link? Use the window['Re-Nav'].share",
|
||||
'function, where redirect is an object with matcherType, matcherValue,',
|
||||
'redirectType and redirectValue properties. Like this:',
|
||||
);
|
||||
console.log(JSON.stringify(exampleRedirect, undefined, 2));
|
||||
console.log(window['Re-Nav'].share);
|
||||
|
||||
if (!location.hash.startsWith(fragmentPrefix)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const decoded = decodeBase64<Redirect>(
|
||||
location.hash.slice(fragmentPrefix.length),
|
||||
);
|
||||
for (const [key, value] of Object.entries(decoded)) {
|
||||
insertText(key as keyof Redirect, value);
|
||||
}
|
||||
|
||||
for (const element of document.querySelectorAll('.hidden-by-default')) {
|
||||
element.classList.remove('hidden-by-default');
|
||||
}
|
||||
|
||||
document.querySelector('.subtitle')!.textContent =
|
||||
'Someone shared a redirect with you!';
|
||||
});
|
||||
|
||||
function insertText(key: keyof Redirect, value: string): void {
|
||||
const insert = (selector: string, text: string) => {
|
||||
document.querySelector(selector)!.textContent = text;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line unicorn/prefer-switch
|
||||
if (key === 'matcherType') {
|
||||
insert('.matcher-type', value);
|
||||
} else if (key === 'matcherValue') {
|
||||
insert('.matcher-value', value);
|
||||
} else if (key === 'redirectType') {
|
||||
insert('.redirect-type', value);
|
||||
} else if (key === 'redirectValue') {
|
||||
insert('.redirect-value', value);
|
||||
} else {
|
||||
console.warn(`Unknown key: ${key as string}`);
|
||||
}
|
||||
}
|
||||
|
||||
function share(redirect: Redirect): string {
|
||||
const encoded = encodeBase64(redirect);
|
||||
const url = new URL(window.location.href);
|
||||
url.hash = `${fragmentPrefix}${encoded}`;
|
||||
return url.href;
|
||||
}
|
|
@ -13,6 +13,21 @@ declare global {
|
|||
readonly PROD: boolean;
|
||||
readonly VITE_BROWSER: 'chromium' | 'firefox';
|
||||
}
|
||||
|
||||
interface Window {
|
||||
'Re-Nav': {
|
||||
decodeBase64<T>(base64: string): T;
|
||||
encodeBase64(source: any): string;
|
||||
share(redirect: Redirect): string;
|
||||
};
|
||||
}
|
||||
|
||||
type Redirect = {
|
||||
matcherType: string;
|
||||
matcherValue: string;
|
||||
redirectType: string;
|
||||
redirectValue: string;
|
||||
};
|
||||
}
|
||||
|
||||
// Make TypeScript see this file as a module.
|
||||
|
|
|
@ -19,6 +19,7 @@ export default defineConfig({
|
|||
home: path.join(sourceDir, 'index.html'),
|
||||
queue: path.join(sourceDir, 'queue/index.html'),
|
||||
're-nav': path.join(sourceDir, 're-nav/index.html'),
|
||||
're-nav/share': path.join(sourceDir, 're-nav/share/index.html'),
|
||||
},
|
||||
},
|
||||
sourcemap: true,
|
||||
|
|
Loading…
Reference in New Issue