Implement autoredirect
This commit is contained in:
parent
6861a549ac
commit
e66b399961
4 changed files with 88 additions and 13 deletions
|
@ -61,6 +61,14 @@ abbr[title] {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-hcenter {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.flex-row {
|
.flex-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -76,6 +84,13 @@ abbr[title] {
|
||||||
flex-direction: column-reverse;
|
flex-direction: column-reverse;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.flex-vevenly {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.half-width {
|
.half-width {
|
||||||
min-width: 50%;
|
min-width: 50%;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,12 @@
|
||||||
<button onclick="showAddInstanceDialog()">Add an instance</button>
|
<button onclick="showAddInstanceDialog()">Add an instance</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="half-width">
|
<div class="half-width">
|
||||||
|
<div class="flex-hcenter">
|
||||||
|
<div class="flex-vevenly">
|
||||||
<button id="redirect">Redirect</button>
|
<button id="redirect">Redirect</button>
|
||||||
|
<button id="redirectAlways">Redirect always</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dialog>
|
</dialog>
|
||||||
|
|
|
@ -13,6 +13,7 @@ const detailsDialog = findDialogOrFail(document.body, "#instanceDetails");
|
||||||
const addDialog = findDialogOrFail(document.body, "#addInstance");
|
const addDialog = findDialogOrFail(document.body, "#addInstance");
|
||||||
const instanceSelectForm = findFormOrFail(document.body, "#instanceSelectForm");
|
const instanceSelectForm = findFormOrFail(document.body, "#instanceSelectForm");
|
||||||
const redirectButton = findButtonOrFail(document.body, "#redirect");
|
const redirectButton = findButtonOrFail(document.body, "#redirect");
|
||||||
|
const redirectAlwaysButton = findButtonOrFail(document.body, "#redirectAlways");
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
showAddInstanceDialog,
|
showAddInstanceDialog,
|
||||||
|
@ -48,24 +49,73 @@ function createInstanceSelectOptions() {
|
||||||
instanceSelectForm.appendChild(div);
|
instanceSelectForm.appendChild(div);
|
||||||
}
|
}
|
||||||
const firstInput = instanceSelectForm.querySelector("input");
|
const firstInput = instanceSelectForm.querySelector("input");
|
||||||
if (firstInput) {
|
if (firstInput) firstInput.checked = true;
|
||||||
firstInput.checked = true;
|
setRedirectButtonState(firstInput !== null);
|
||||||
redirectButton.disabled = false;
|
|
||||||
} else {
|
|
||||||
redirectButton.disabled = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
createInstanceSelectOptions();
|
createInstanceSelectOptions();
|
||||||
storageManager.addSaveCallback(createInstanceSelectOptions);
|
storageManager.addSaveCallback(createInstanceSelectOptions);
|
||||||
|
|
||||||
function redirect() {
|
function setRedirectButtonState(enabled: boolean) {
|
||||||
// Can be assumed to not fail because the button is disabled if there are no options and the first one is selected by default
|
redirectButton.disabled = !enabled;
|
||||||
const option = findInputOrFail(instanceSelectForm, `input[name="${radioButtonName}"]:checked`).value;
|
redirectAlwaysButton.disabled = !enabled;
|
||||||
const url = URL.parse(option)!;
|
}
|
||||||
|
|
||||||
|
export function getTargetSoftwareOrGroup(): string {
|
||||||
const currentURL = URL.parse(location.href)!;
|
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();
|
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()!);
|
||||||
|
});
|
||||||
|
|
|
@ -25,6 +25,11 @@ export type Instance = {
|
||||||
* Make sure to sanitize this! Could lead to XSS
|
* Make sure to sanitize this! Could lead to XSS
|
||||||
*/
|
*/
|
||||||
iconURL?: string,
|
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 = {
|
type LocalStorage = {
|
||||||
|
|
Loading…
Add table
Reference in a new issue