Implement autoredirect

This commit is contained in:
CenTdemeern1 2025-01-15 06:44:47 +01:00 committed by git.gay
parent 6861a549ac
commit e66b399961
4 changed files with 88 additions and 13 deletions

View file

@ -61,6 +61,14 @@ abbr[title] {
height: 100%;
}
.flex-hcenter {
display: flex;
flex-direction: row;
justify-content: center;
width: 100%;
height: 100%;
}
.flex-row {
display: flex;
flex-direction: row;
@ -76,6 +84,13 @@ abbr[title] {
flex-direction: column-reverse;
}
.flex-vevenly {
display: flex;
flex-direction: column;
justify-content: space-evenly;
height: 100%;
}
.half-width {
min-width: 50%;
}

View file

@ -29,7 +29,12 @@
<button onclick="showAddInstanceDialog()">Add an instance</button>
</div>
<div class="half-width">
<button id="redirect">Redirect</button>
<div class="flex-hcenter">
<div class="flex-vevenly">
<button id="redirect">Redirect</button>
<button id="redirectAlways">Redirect always</button>
</div>
</div>
</div>
</div>
</dialog>

View file

@ -13,6 +13,7 @@ const detailsDialog = findDialogOrFail(document.body, "#instanceDetails");
const addDialog = findDialogOrFail(document.body, "#addInstance");
const instanceSelectForm = findFormOrFail(document.body, "#instanceSelectForm");
const redirectButton = findButtonOrFail(document.body, "#redirect");
const redirectAlwaysButton = findButtonOrFail(document.body, "#redirectAlways");
export const {
showAddInstanceDialog,
@ -48,24 +49,73 @@ function createInstanceSelectOptions() {
instanceSelectForm.appendChild(div);
}
const firstInput = instanceSelectForm.querySelector("input");
if (firstInput) {
firstInput.checked = true;
redirectButton.disabled = false;
} else {
redirectButton.disabled = true;
}
if (firstInput) firstInput.checked = true;
setRedirectButtonState(firstInput !== null);
}
createInstanceSelectOptions();
storageManager.addSaveCallback(createInstanceSelectOptions);
function redirect() {
// Can be assumed to not fail because the button is disabled if there are no options and the first one is selected by default
const option = findInputOrFail(instanceSelectForm, `input[name="${radioButtonName}"]:checked`).value;
const url = URL.parse(option)!;
function setRedirectButtonState(enabled: boolean) {
redirectButton.disabled = !enabled;
redirectAlwaysButton.disabled = !enabled;
}
export function getTargetSoftwareOrGroup(): string {
const currentURL = URL.parse(location.href)!;
url.pathname = currentURL.pathname.replace(/\/.*?\//, "/");
const target = currentURL.pathname.match(/\/+([^\/]*)\/?/)?.[1];
if (target == null) throw new Error("Crossroad was served on an invalid path (likely a backend routing mistake)");
const softwareName = Object.entries(knownSoftware.software).find(([name, software]) => software.aliases.includes(target))?.[0];
if (softwareName) return softwareName;
const groupName = Object.entries(knownSoftware.groups).find(([name, group]) => group.aliases.includes(target))?.[0];
if (groupName) return groupName;
throw new Error("Could not identify target software or group");
}
function getTargetPath(): string {
const currentURL = URL.parse(location.href)!;
return currentURL.pathname.replace(/\/+[^\/]*\/?/, "/");
}
function getSelectedOption(): string | null {
try {
return findInputOrFail(instanceSelectForm, `input[name="${radioButtonName}"]:checked`).value;
} catch {
return null;
}
}
function autoRedirect() {
const targetSoftware = getTargetSoftwareOrGroup();
const preferredFor = storageManager.storage.instances.find(instance => instance.preferredFor?.includes(targetSoftware));
if (preferredFor) redirect(preferredFor.origin);
}
autoRedirect();
function setAutoRedirect(option: string) {
const instance = storageManager.storage.instances.find(e => e.origin === option);
if (!instance) throw new Error("Invalid argument");
instance.preferredFor ??= [];
instance.preferredFor.push(getTargetSoftwareOrGroup());
storageManager.save();
}
redirectAlwaysButton.addEventListener("click", e => {
// Can be assumed to not fail because the button is disabled if there are no options and the first one is selected by default
const option = getSelectedOption()!;
setAutoRedirect(option);
redirect(option);
});
function redirect(to: string) {
const url = URL.parse(to);
if (url === null) throw new Error("Couldn't parse destination");
url.pathname = getTargetPath();
location.href = url.toString();
}
redirectButton.addEventListener("click", e => redirect());
redirectButton.addEventListener("click", e => {
// Can be assumed to not fail because the button is disabled if there are no options and the first one is selected by default
redirect(getSelectedOption()!);
});

View file

@ -25,6 +25,11 @@ export type Instance = {
* Make sure to sanitize this! Could lead to XSS
*/
iconURL?: string,
/**
* The list of software names and groups the user prefers to autoredirect to this instance
* @example ["sharkey", "misskey-compliant"]
*/
preferredFor?: string[],
}
type LocalStorage = {