add shortcuts

This commit is contained in:
Mathium05
2026-07-28 18:22:56 -05:00
parent bb87342b7e
commit 888b8439aa
5 changed files with 184 additions and 0 deletions
+33
View File
@@ -51,6 +51,8 @@ import {CDNParams} from "./utils/cdnParams.js";
import {SnowFlake} from "./snowflake.js";
import {trimTrailingSlashes} from "./utils/netUtils.js";
import {Versions} from "./versions.js";
import {Shortcut} from "./shortcuts/shortcut.js";
import {getShortcuts, setShortcuts} from "./utils/storage/shortcuts.js";
type traceObj = {
micros: number;
calls?: (string | traceObj)[];
@@ -93,6 +95,7 @@ class Localuser {
readonly messages = new Map<string, Message>();
readonly idToPrev = new Map<string, string | undefined>();
readonly idToNext = new Map<string, string | undefined>();
static readonly globalShortcuts = new Shortcut();
get status() {
return this.user.status;
}
@@ -2570,6 +2573,15 @@ class Localuser {
});
d.show();
}
static initShortcuts() {
const cur = getShortcuts();
for (const [name, combo] of cur) {
this.globalShortcuts.registerKeycombo(combo, name);
}
this.globalShortcuts.registerShortcut("gifSearch", () => {
document.getElementById("gifTB")?.click();
});
}
async showusersettings() {
const prefs = await getPreferences();
const localSettings = getLocalSettings();
@@ -3167,6 +3179,25 @@ class Localuser {
}
})();
}
{
const shortcuts = settings.addButton(I18n.keyboard.shortcuts(), {contained: true});
const cur = getShortcuts();
console.log(Localuser.globalShortcuts);
for (const [name] of cur) {
shortcuts.addText(I18n.keyboard.descs[name]());
shortcuts.addHTMLArea(
Localuser.globalShortcuts.shortCutbutton(
name,
(short) => {
cur[name] = short;
setShortcuts(cur);
console.log(cur);
},
true,
),
);
}
}
const installP = installPGet();
if (installP) {
@@ -5528,4 +5559,6 @@ class Localuser {
return userinfos.preferences.notisound;
}
}
Localuser.globalShortcuts.listen(document.body);
Localuser.initShortcuts();
export {Localuser};
+117
View File
@@ -0,0 +1,117 @@
import {I18n} from "../i18n";
export class Shortcut {
private shortcuts = new Map<string, () => void>();
private keycombos = new Map<string, string>();
private nameToCombo = new Map<string, Set<string>>();
registerShortcut(name: string, callback: () => void) {
this.shortcuts.set(name, callback);
}
unregisterKeycombo(combo: string) {
const name = this.keycombos.get(combo);
this.keycombos.delete(Shortcut.normalize(combo));
if (!name) return;
let nset = this.nameToCombo.get(name);
if (nset) nset.delete(combo);
}
registerKeycombo(combo: string, name: string) {
combo = Shortcut.normalize(combo);
this.keycombos.set(combo, name);
let nset = this.nameToCombo.get(name);
if (!nset) {
nset = new Set();
this.nameToCombo.set(name, nset);
}
nset.add(combo);
}
clear() {
this.keycombos.clear();
this.shortcuts.clear();
this.nameToCombo.clear();
}
private static normalize(e: string): string {
const code = new Set(e.toLowerCase().split("-"));
const build = [] as string[];
if (code.has("meta")) build.push("meta");
if (code.has("ctrl")) build.push("ctrl");
if (code.has("alt")) build.push("alt");
if (code.has("shift")) build.push("shift");
build.push(...[...code].filter((_) => _.length === 1).map((_) => _.toLowerCase()));
return build.join("-");
}
private static eventToCombo(e: KeyboardEvent, down = true): string {
const build = [] as string[];
if (e.metaKey || (e.key === "Meta" && down)) {
if (e.key !== "Meta" || down) build.push("meta");
}
if (e.ctrlKey) build.push("ctrl");
if (e.altKey) build.push("alt");
if (e.shiftKey) build.push("shift");
if (e.key.length === 1) build.push(e.key.toLowerCase());
return build.join("-");
}
shortCutbutton(name: string | null, callback: (combo: string) => void, updateCombo: boolean) {
let cur = (name && [...(this.nameToCombo.get(name) ?? [])].at(0)) ?? "";
const button = document.createElement("button");
function updateButton(combo?: string) {
button.textContent = combo || cur || I18n.keyboard.empty();
}
const register = () => {
button.onkeyup = (event) => {
const combo = Shortcut.eventToCombo(event, false);
updateButton(combo);
};
button.onkeydown = (event) => {
const combo = Shortcut.eventToCombo(event);
updateButton(combo);
if (event.key.length === 1) {
callback(combo);
button.onkeyup = () => {};
button.onkeydown = () => {};
if (updateCombo && name) {
this.unregisterKeycombo(cur);
this.registerKeycombo(combo, name);
}
cur = combo;
updateButton();
}
event.preventDefault();
};
button.onblur = () => {
button.onkeyup = () => {};
button.onkeydown = () => {};
updateButton();
};
};
button.onclick = register;
updateButton();
const div = document.createElement("div");
div.classList.add("flexltr", "shortCutSetting");
const clear = document.createElement("button");
clear.textContent = I18n.settings.clear();
div.append(button, clear);
clear.onclick = () => {
callback("");
if (updateCombo && name) {
this.unregisterKeycombo(cur);
}
cur = "";
updateButton();
};
return div;
}
listen(elm: HTMLElement) {
elm.addEventListener("keydown", (event) => {
if (event.key.length !== 1) return;
const combo = Shortcut.eventToCombo(event);
const name = this.keycombos.get(combo);
if (!name) return;
const func = this.shortcuts.get(name);
if (!func) return;
event.stopImmediatePropagation();
event.preventDefault();
func();
});
}
}
+5
View File
@@ -187,6 +187,11 @@ body {
min-height: 0;
display: flex;
}
.shortCutSetting {
:last-child {
margin-left: 10px;
}
}
.pollRes {
padding-left: 50px;
}
+22
View File
@@ -0,0 +1,22 @@
const props = ["gifSearch"] as const;
export class Shortcuts {
gifSearch = "ctrl+g";
constructor(data: Partial<Shortcuts> = {}) {
Object.assign(this, data);
}
*[Symbol.iterator]() {
for (const thing of props) {
yield [thing, this[thing]] as const;
}
return;
}
}
export function getShortcuts(): Shortcuts {
return new Shortcuts(JSON.parse(localStorage.getItem("shortCuts") ?? "{}"));
}
export function setShortcuts(settings: Shortcuts): void {
localStorage.setItem("shortCuts", JSON.stringify(settings));
}
+7
View File
@@ -991,6 +991,13 @@
"editMode":{
"editMsg":"Escape to $1cancel$1"
},
"keyboard":{
"shortcuts":"Shortcuts",
"empty":"<No keybind set>",
"descs":{
"gifSearch":"Search GIFs:"
}
},
"domain":{
"title":"Verify domain",
"domain":"Domain:",