feat: simple extension setup

This commit is contained in:
2026-05-31 21:37:04 +02:00
parent d6f170ac2f
commit 98f0fd10b0
12 changed files with 522 additions and 0 deletions

46
src/content.ts Normal file
View File

@@ -0,0 +1,46 @@
import { State, STORAGE_KEY } from "./types";
const KEY_BINDINGS: Record<string, string> = {
// TODO
};
let enabled = false;
const clickButton = (selector: string): void => {
const el = document.querySelector<HTMLElement>(selector);
el?.click();
};
const onKeyDown = (event: KeyboardEvent): void => {
if (!enabled) return;
const target = event.target as HTMLElement;
if (
target.tagName === "INPUT" ||
target.tagName === "TEXTAREA" ||
target.isContentEditable
) return;
const selector = KEY_BINDINGS[event.code];
if (selector) {
event.preventDefault();
clickButton(selector);
}
};
const init = async (): Promise<void> => {
const result = await chrome.storage.local.get(STORAGE_KEY);
const state = result[STORAGE_KEY] as State | undefined;
enabled = state?.enabled ?? true;
document.addEventListener("keydown", onKeyDown);
chrome.storage.onChanged.addListener((changes) => {
if (STORAGE_KEY in changes) {
const next = changes[STORAGE_KEY].newValue as State;
enabled = next.enabled;
}
});
};
init();

49
src/popup.css Normal file
View File

@@ -0,0 +1,49 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
width: 320px;
padding: 16px;
font-family: system-ui, -apple-system, sans-serif;
background: #0f1117;
color: #e2e8f0;
}
h1 {
font-size: 0.95rem;
font-weight: 700;
letter-spacing: 0.02em;
margin-bottom: 6px;
}
p {
font-size: 0.75rem;
color: #94a3b8;
line-height: 1.4;
margin-bottom: 16px;
}
#toggle {
width: 100%;
padding: 9px;
border: none;
border-radius: 6px;
font-size: 0.85rem;
font-weight: 700;
cursor: pointer;
letter-spacing: 0.05em;
transition: background 0.15s;
}
#toggle.on {
background: #22c55e;
color: #fff;
}
#toggle.off {
background: #3f3f46;
color: #94a3b8;
}

13
src/popup.html Normal file
View File

@@ -0,0 +1,13 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>WoV Tweaks</title>
<link rel="stylesheet" href="popup.css">
</head>
<body>
<h1>Assassins Convention Tweaks</h1>
<button id="toggle"></button>
<script src="../dist/popup.js"></script>
</body>
</html>

34
src/popup.ts Normal file
View File

@@ -0,0 +1,34 @@
import { State, STORAGE_KEY } from "./types";
const DEFAULT_STATE: State = {
enabled: true,
};
const getState = async (): Promise<State> => {
const result = await chrome.storage.local.get(STORAGE_KEY);
return (result[STORAGE_KEY] as State | undefined) ?? DEFAULT_STATE;
};
const setState = async (state: State): Promise<void> => {
await chrome.storage.local.set({ [STORAGE_KEY]: state });
};
const render = (btn: HTMLButtonElement, enabled: boolean): void => {
btn.textContent = enabled ? "ON" : "OFF";
btn.className = enabled ? "on" : "off";
};
const init = async (): Promise<void> => {
const btn = document.getElementById("toggle") as HTMLButtonElement;
const state = await getState();
render(btn, state.enabled);
btn.addEventListener("click", async () => {
const current = await getState();
const next = { enabled: !current.enabled };
await setState(next);
render(btn, next.enabled);
});
};
document.addEventListener("DOMContentLoaded", init);

5
src/types.ts Normal file
View File

@@ -0,0 +1,5 @@
export type State = {
enabled: boolean;
};
export const STORAGE_KEY = "wov_assassins_convention_tweaks_state";