APIキーを入力するオプションの実装

This commit is contained in:
Keisuke Hirata 2026-04-09 04:20:56 +09:00
parent 177a98d312
commit b38b39dab3
5 changed files with 141 additions and 2 deletions

View File

@ -30,8 +30,16 @@ async function build(browser) {
outfile: `${outdir}/injected/page-script.js`,
format: "iife",
}),
esbuild.build({
...common,
entryPoints: ["src/options/options.ts"],
outfile: `${outdir}/options/options.js`,
format: "iife",
}),
]);
cpSync("src/options/options.html", `${outdir}/options/options.html`);
cpSync(`manifest.${browser}.json`, `${outdir}/manifest.json`);
}

View File

@ -4,7 +4,6 @@
"version": "0.1.1",
"description": "Extract and work with YouTube playlist data",
"permissions": ["storage"],
"host_permissions": ["https://www.googleapis.com/*"],
"background": {
"service_worker": "background/service-worker.js"
},
@ -15,6 +14,13 @@
"run_at": "document_idle"
}
],
"action": {
"default_popup": "options/options.html"
},
"options_ui": {
"page": "options/options.html",
"open_in_tab": false
},
"web_accessible_resources": [
{
"resources": ["injected/page-script.js"],

View File

@ -4,7 +4,6 @@
"version": "0.1.1",
"description": "Extract and work with YouTube playlist data",
"permissions": ["storage"],
"host_permissions": ["https://www.googleapis.com/*"],
"background": {
"scripts": ["background/service-worker.js"]
},
@ -15,6 +14,13 @@
"run_at": "document_idle"
}
],
"action": {
"default_popup": "options/options.html"
},
"options_ui": {
"page": "options/options.html",
"open_in_tab": false
},
"web_accessible_resources": [
{
"resources": ["injected/page-script.js"],

87
src/options/options.html Normal file
View File

@ -0,0 +1,87 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<style>
body {
font-family: "Roboto", "Arial", sans-serif;
font-size: 14px;
padding: 16px;
min-width: 360px;
color: #333;
}
h2 {
font-size: 16px;
margin: 0 0 12px;
}
label {
display: block;
font-size: 12px;
color: #606060;
margin-bottom: 4px;
}
input[type="text"] {
width: 100%;
box-sizing: border-box;
padding: 8px 10px;
border: 1px solid #ccc;
border-radius: 6px;
font-size: 13px;
font-family: "Roboto Mono", monospace;
}
.hint {
font-size: 11px;
color: #999;
margin-top: 4px;
}
.actions {
margin-top: 12px;
display: flex;
gap: 8px;
}
button {
padding: 6px 16px;
border: 1px solid #ccc;
border-radius: 16px;
background: #fff;
font-size: 13px;
cursor: pointer;
}
button:hover {
background: #f2f2f2;
}
button.primary {
background: #065fd4;
color: #fff;
border-color: #065fd4;
}
button.primary:hover {
background: #0554b8;
}
.status {
font-size: 12px;
margin-top: 8px;
color: #1a8a1a;
}
</style>
</head>
<body>
<h2>YT Playlist Features</h2>
<label for="apiKey">YouTube Data API Key</label>
<input type="text" id="apiKey" placeholder="..." />
<div class="hint">
Leave blank to use the default key.
<a
href="https://console.cloud.google.com/apis/credentials"
target="_blank"
>Get your own key</a
>
</div>
<div class="actions">
<button class="primary" id="save">Save</button>
<button id="clear">Clear</button>
</div>
<div class="status" id="status"></div>
<script src="options.js"></script>
</body>
</html>

32
src/options/options.ts Normal file
View File

@ -0,0 +1,32 @@
import browser from "webextension-polyfill";
const input = document.getElementById("apiKey") as HTMLInputElement;
const saveBtn = document.getElementById("save") as HTMLButtonElement;
const clearBtn = document.getElementById("clear") as HTMLButtonElement;
const status = document.getElementById("status") as HTMLDivElement;
function flash(text: string) {
status.textContent = text;
setTimeout(() => { status.textContent = ""; }, 2000);
}
// Load
browser.storage.sync.get("apiKey").then((result) => {
input.value = (result.apiKey as string) || "";
});
// Save
saveBtn.addEventListener("click", () => {
const key = input.value.trim();
if (key) {
browser.storage.sync.set({ apiKey: key }).then(() => flash("Saved"));
} else {
browser.storage.sync.remove("apiKey").then(() => flash("Using default key"));
}
});
// Clear
clearBtn.addEventListener("click", () => {
input.value = "";
browser.storage.sync.remove("apiKey").then(() => flash("Cleared"));
});