mirror of
https://github.com/MathMan05/Fermi.git
synced 2026-07-18 07:26:13 +00:00
made sub menu buttons more obvious
This commit is contained in:
+126
-124
@@ -2731,9 +2731,9 @@ class Localuser {
|
||||
const genSecurity = () => {
|
||||
security.removeAll();
|
||||
if (this.mfa_enabled) {
|
||||
security.addButtonInput("", I18n.localuser["2faDisable"](), () => {
|
||||
const form = security.addSubForm(
|
||||
I18n.localuser["2faDisable"](),
|
||||
security.addSubButtonInput(I18n.localuser["2faDisable"](), (sub) => {
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(_: any) => {
|
||||
if (_.message) {
|
||||
switch (_.code) {
|
||||
@@ -2755,13 +2755,13 @@ class Localuser {
|
||||
form.addTextInput(I18n.localuser["2faCode:"](), "code", {required: true});
|
||||
});
|
||||
} else {
|
||||
security.addButtonInput("", I18n.localuser["2faEnable"](), async () => {
|
||||
security.addSubButtonInput(I18n.localuser["2faEnable"](), async (sub) => {
|
||||
let secret = "";
|
||||
for (let i = 0; i < 18; i++) {
|
||||
secret += "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"[Math.floor(Math.random() * 32)];
|
||||
}
|
||||
const form = security.addSubForm(
|
||||
I18n.localuser.setUp2fa(),
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(_: any) => {
|
||||
if (_.message) {
|
||||
switch (_.code) {
|
||||
@@ -2794,8 +2794,7 @@ class Localuser {
|
||||
});
|
||||
}
|
||||
{
|
||||
security.addButtonInput("", I18n.webauth.manage(), () => {
|
||||
const keyMenu = security.addSubOptions("Manage Keys");
|
||||
security.addSubButtonInput(I18n.webauth.manage(), (keyMenu) => {
|
||||
const addKey = (key: {name: string; id: string}) => {
|
||||
keyMenu.addButtonInput("", key.name, () => {
|
||||
const opt = keyMenu.addSubOptions(key.name);
|
||||
@@ -2882,9 +2881,9 @@ class Localuser {
|
||||
});
|
||||
});
|
||||
}
|
||||
security.addButtonInput("", I18n.localuser.changeDiscriminator(), () => {
|
||||
const form = security.addSubForm(
|
||||
I18n.localuser.changeDiscriminator(),
|
||||
security.addSubButtonInput(I18n.localuser.changeDiscriminator(), (sub) => {
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(_) => {
|
||||
security.returnFromSub();
|
||||
},
|
||||
@@ -2896,9 +2895,9 @@ class Localuser {
|
||||
);
|
||||
form.addTextInput(I18n.localuser.newDiscriminator(), "discriminator");
|
||||
});
|
||||
security.addButtonInput("", I18n.localuser.changeEmail(), () => {
|
||||
const form = security.addSubForm(
|
||||
I18n.localuser.changeEmail(),
|
||||
security.addSubButtonInput(I18n.localuser.changeEmail(), (sub) => {
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(_) => {
|
||||
security.returnFromSub();
|
||||
},
|
||||
@@ -2916,9 +2915,9 @@ class Localuser {
|
||||
}
|
||||
form.addTextInput(I18n.localuser["newEmail:"](), "email");
|
||||
});
|
||||
security.addButtonInput("", I18n.localuser.changeUsername(), () => {
|
||||
const form = security.addSubForm(
|
||||
I18n.localuser.changeUsername(),
|
||||
security.addSubButtonInput(I18n.localuser.changeUsername(), (sub) => {
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(_) => {
|
||||
security.returnFromSub();
|
||||
},
|
||||
@@ -2936,9 +2935,9 @@ class Localuser {
|
||||
}
|
||||
form.addTextInput(I18n.localuser.newUsername(), "username");
|
||||
});
|
||||
security.addButtonInput("", I18n.localuser.changePassword(), () => {
|
||||
const form = security.addSubForm(
|
||||
I18n.localuser.changePassword(),
|
||||
security.addSubButtonInput(I18n.localuser.changePassword(), (sub) => {
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(_) => {
|
||||
security.returnFromSub();
|
||||
},
|
||||
@@ -3196,9 +3195,9 @@ class Localuser {
|
||||
}).then(async (teamsRes) => {
|
||||
const teams = await teamsRes.json();
|
||||
|
||||
const button = devPortal.addButtonInput("", I18n.localuser.createApp(), () => {
|
||||
const form = devPortal.addSubForm(
|
||||
I18n.localuser.createApp(),
|
||||
const button = devPortal.addSubButtonInput(I18n.localuser.createApp(), (sub) => {
|
||||
const form = sub.addForm(
|
||||
"",
|
||||
(json: any) => {
|
||||
if (json.message) form.error("name", json.message);
|
||||
else {
|
||||
@@ -3412,111 +3411,114 @@ class Localuser {
|
||||
});
|
||||
}
|
||||
if (this.rights.hasPermission("CREATE_REGISTRATION_TOKENS")) {
|
||||
manageInstance.addButtonInput("", I18n.manageInstance.createTokens(), () => {
|
||||
const tokens = manageInstance.addSubOptions(I18n.manageInstance.createTokens(), {
|
||||
noSubmit: true,
|
||||
});
|
||||
const count = tokens.addTextInput(I18n.manageInstance.count(), () => {}, {
|
||||
initText: "1",
|
||||
});
|
||||
const length = tokens.addTextInput(I18n.manageInstance.length(), () => {}, {
|
||||
initText: "32",
|
||||
});
|
||||
const format = tokens.addSelect(
|
||||
I18n.manageInstance.format(),
|
||||
() => {},
|
||||
[
|
||||
I18n.manageInstance.TokenFormats.JSON(),
|
||||
I18n.manageInstance.TokenFormats.plain(),
|
||||
I18n.manageInstance.TokenFormats.URLs(),
|
||||
],
|
||||
{
|
||||
defaultIndex: 2,
|
||||
},
|
||||
);
|
||||
format.watchForChange((e) => {
|
||||
if (e !== 2) {
|
||||
urlOption.removeAll();
|
||||
} else {
|
||||
makeURLMenu();
|
||||
}
|
||||
});
|
||||
const urlOption = tokens.addOptions("");
|
||||
const urlOptionsJSON = {
|
||||
url: window.location.origin,
|
||||
type: "Jank",
|
||||
};
|
||||
function makeURLMenu() {
|
||||
urlOption
|
||||
.addTextInput(I18n.manageInstance.clientURL(), () => {}, {
|
||||
initText: urlOptionsJSON.url,
|
||||
})
|
||||
.watchForChange((str) => {
|
||||
urlOptionsJSON.url = str;
|
||||
});
|
||||
urlOption
|
||||
.addSelect(
|
||||
I18n.manageInstance.regType(),
|
||||
() => {},
|
||||
["Jank", I18n.manageInstance.genericType()],
|
||||
{
|
||||
defaultIndex: ["Jank", "generic"].indexOf(urlOptionsJSON.type),
|
||||
},
|
||||
)
|
||||
.watchForChange((i) => {
|
||||
urlOptionsJSON.type = ["Jank", "generic"][i];
|
||||
});
|
||||
}
|
||||
makeURLMenu();
|
||||
tokens.addButtonInput("", I18n.manageInstance.create(), async () => {
|
||||
const params = new URLSearchParams();
|
||||
params.set("count", count.value);
|
||||
params.set("length", length.value);
|
||||
const json = (await (
|
||||
await fetch(
|
||||
this.info.api + "/auth/generate-registration-tokens?" + params.toString(),
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
)
|
||||
).json()) as {tokens: string[]};
|
||||
if (format.index === 0) {
|
||||
pre.textContent = JSON.stringify(json.tokens);
|
||||
} else if (format.index === 1) {
|
||||
pre.textContent = json.tokens.join("\n");
|
||||
} else if (format.index === 2) {
|
||||
if (urlOptionsJSON.type === "Jank") {
|
||||
const options = new URLSearchParams();
|
||||
options.set("instance", this.info.wellknown);
|
||||
pre.textContent = json.tokens
|
||||
.map((token) => {
|
||||
options.set("token", token);
|
||||
return `${urlOptionsJSON.url}/register?` + options.toString();
|
||||
})
|
||||
.join("\n");
|
||||
manageInstance.addSubButtonInput(
|
||||
I18n.manageInstance.createTokens(),
|
||||
(tokens) => {
|
||||
const count = tokens.addTextInput(I18n.manageInstance.count(), () => {}, {
|
||||
initText: "1",
|
||||
});
|
||||
const length = tokens.addTextInput(I18n.manageInstance.length(), () => {}, {
|
||||
initText: "32",
|
||||
});
|
||||
const format = tokens.addSelect(
|
||||
I18n.manageInstance.format(),
|
||||
() => {},
|
||||
[
|
||||
I18n.manageInstance.TokenFormats.JSON(),
|
||||
I18n.manageInstance.TokenFormats.plain(),
|
||||
I18n.manageInstance.TokenFormats.URLs(),
|
||||
],
|
||||
{
|
||||
defaultIndex: 2,
|
||||
},
|
||||
);
|
||||
format.watchForChange((e) => {
|
||||
if (e !== 2) {
|
||||
urlOption.removeAll();
|
||||
} else {
|
||||
const options = new URLSearchParams();
|
||||
pre.textContent = json.tokens
|
||||
.map((token) => {
|
||||
options.set("token", token);
|
||||
return `${urlOptionsJSON.url}/register?` + options.toString();
|
||||
})
|
||||
.join("\n");
|
||||
makeURLMenu();
|
||||
}
|
||||
});
|
||||
const urlOption = tokens.addOptions("");
|
||||
const urlOptionsJSON = {
|
||||
url: window.location.origin,
|
||||
type: "Jank",
|
||||
};
|
||||
function makeURLMenu() {
|
||||
urlOption
|
||||
.addTextInput(I18n.manageInstance.clientURL(), () => {}, {
|
||||
initText: urlOptionsJSON.url,
|
||||
})
|
||||
.watchForChange((str) => {
|
||||
urlOptionsJSON.url = str;
|
||||
});
|
||||
urlOption
|
||||
.addSelect(
|
||||
I18n.manageInstance.regType(),
|
||||
() => {},
|
||||
["Jank", I18n.manageInstance.genericType()],
|
||||
{
|
||||
defaultIndex: ["Jank", "generic"].indexOf(urlOptionsJSON.type),
|
||||
},
|
||||
)
|
||||
.watchForChange((i) => {
|
||||
urlOptionsJSON.type = ["Jank", "generic"][i];
|
||||
});
|
||||
}
|
||||
});
|
||||
tokens.addButtonInput("", I18n.manageInstance.copy(), async () => {
|
||||
try {
|
||||
if (pre.textContent) {
|
||||
await navigator.clipboard.writeText(pre.textContent);
|
||||
makeURLMenu();
|
||||
tokens.addButtonInput("", I18n.manageInstance.create(), async () => {
|
||||
const params = new URLSearchParams();
|
||||
params.set("count", count.value);
|
||||
params.set("length", length.value);
|
||||
const json = (await (
|
||||
await fetch(
|
||||
this.info.api + "/auth/generate-registration-tokens?" + params.toString(),
|
||||
{
|
||||
headers: this.headers,
|
||||
},
|
||||
)
|
||||
).json()) as {tokens: string[]};
|
||||
if (format.index === 0) {
|
||||
pre.textContent = JSON.stringify(json.tokens);
|
||||
} else if (format.index === 1) {
|
||||
pre.textContent = json.tokens.join("\n");
|
||||
} else if (format.index === 2) {
|
||||
if (urlOptionsJSON.type === "Jank") {
|
||||
const options = new URLSearchParams();
|
||||
options.set("instance", this.info.wellknown);
|
||||
pre.textContent = json.tokens
|
||||
.map((token) => {
|
||||
options.set("token", token);
|
||||
return `${urlOptionsJSON.url}/register?` + options.toString();
|
||||
})
|
||||
.join("\n");
|
||||
} else {
|
||||
const options = new URLSearchParams();
|
||||
pre.textContent = json.tokens
|
||||
.map((token) => {
|
||||
options.set("token", token);
|
||||
return `${urlOptionsJSON.url}/register?` + options.toString();
|
||||
})
|
||||
.join("\n");
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
const pre = document.createElement("pre");
|
||||
tokens.addHTMLArea(pre);
|
||||
});
|
||||
});
|
||||
tokens.addButtonInput("", I18n.manageInstance.copy(), async () => {
|
||||
try {
|
||||
if (pre.textContent) {
|
||||
await navigator.clipboard.writeText(pre.textContent);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
});
|
||||
const pre = document.createElement("pre");
|
||||
tokens.addHTMLArea(pre);
|
||||
},
|
||||
{
|
||||
noSubmit: true,
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
(async () => {
|
||||
|
||||
@@ -354,6 +354,42 @@ class CheckboxInput implements OptionsElement<boolean> {
|
||||
}
|
||||
}
|
||||
|
||||
class SubButtonInput implements OptionsElement<void> {
|
||||
readonly owner: Options;
|
||||
readonly onClick: (opt: Options) => void;
|
||||
textContent: string;
|
||||
value!: void;
|
||||
opts?: {noSubmit?: boolean; ltr?: boolean};
|
||||
|
||||
constructor(
|
||||
textContent: string,
|
||||
onClick: (opt: Options) => void,
|
||||
owner: Options,
|
||||
{} = {},
|
||||
opts?: SubButtonInput["opts"],
|
||||
) {
|
||||
this.owner = owner;
|
||||
this.onClick = onClick;
|
||||
this.textContent = textContent;
|
||||
this.opts = opts;
|
||||
}
|
||||
buttonHtml?: HTMLButtonElement;
|
||||
generateHTML(): HTMLDivElement {
|
||||
const div = document.createElement("div");
|
||||
const button = document.createElement("button");
|
||||
button.classList.add("subButton");
|
||||
button.textContent = this.textContent;
|
||||
button.onclick = () => {
|
||||
this.onClick(this.owner.addSubOptions(this.textContent, this.opts));
|
||||
};
|
||||
this.buttonHtml = button;
|
||||
div.append(button);
|
||||
return div;
|
||||
}
|
||||
watchForChange() {}
|
||||
submit() {}
|
||||
}
|
||||
|
||||
class ButtonInput implements OptionsElement<void> {
|
||||
readonly label: string;
|
||||
readonly owner: Options;
|
||||
@@ -1516,6 +1552,16 @@ class Options implements OptionsElement<void> {
|
||||
this.generate(button);
|
||||
return button;
|
||||
}
|
||||
addSubButtonInput(
|
||||
textContent: string,
|
||||
onSubmit: (opt: Options) => void,
|
||||
{ltr = false, noSubmit = false} = {},
|
||||
) {
|
||||
const button = new SubButtonInput(textContent, onSubmit, this, {ltr, noSubmit});
|
||||
this.options.push(button);
|
||||
this.generate(button);
|
||||
return button;
|
||||
}
|
||||
addCheckboxInput(label: string, onSubmit: (str: boolean) => void, {initState = false} = {}) {
|
||||
const box = new CheckboxInput(label, onSubmit, this, {initState});
|
||||
this.options.push(box);
|
||||
|
||||
+23
-3
@@ -755,6 +755,23 @@ select {
|
||||
cursor: pointer;
|
||||
transition: background 0.1s ease-in-out;
|
||||
}
|
||||
.subButton {
|
||||
min-width: 350px;
|
||||
padding: 10px;
|
||||
position: relative;
|
||||
&::after {
|
||||
content: "";
|
||||
mask: url(./icons/intoMenu.svg);
|
||||
mask-size: contain !important;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
background: var(--primary-text-soft);
|
||||
display: block;
|
||||
position: absolute;
|
||||
right: 4px;
|
||||
top: 8px;
|
||||
}
|
||||
}
|
||||
input::file-selector-button {
|
||||
margin-right: 6px;
|
||||
}
|
||||
@@ -2896,11 +2913,13 @@ input[type="search"]:read-only {
|
||||
background: var(--spoiler-bg);
|
||||
color: var(--spoiler-bg);
|
||||
cursor: pointer;
|
||||
samp, a {
|
||||
samp,
|
||||
a {
|
||||
background: transparent;
|
||||
color: inherit;
|
||||
}
|
||||
pre, .quote {
|
||||
pre,
|
||||
.quote {
|
||||
background: var(--spoiler-bg);
|
||||
color: var(--spoiler-bg);
|
||||
}
|
||||
@@ -2908,7 +2927,8 @@ input[type="search"]:read-only {
|
||||
.spoiler:hover {
|
||||
background: var(--spoiler-hover);
|
||||
color: var(--spoiler-hover);
|
||||
pre, .quote {
|
||||
pre,
|
||||
.quote {
|
||||
background: var(--spoiler-hover);
|
||||
color: var(--spoiler-hover);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user