feat: add options page for API key and thresholds
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 5.5
parent
3a28991522
commit
513a64f84a
+2
-1
@@ -6,5 +6,6 @@
|
|||||||
"permissions": ["storage"],
|
"permissions": ["storage"],
|
||||||
"host_permissions": ["https://www.googleapis.com/youtube/v3/*"],
|
"host_permissions": ["https://www.googleapis.com/youtube/v3/*"],
|
||||||
"background": { "service_worker": "src/background.js", "type": "module" },
|
"background": { "service_worker": "src/background.js", "type": "module" },
|
||||||
"action": { "default_title": "Outlier Saver" }
|
"action": { "default_title": "Outlier Saver" },
|
||||||
|
"options_ui": { "page": "src/options/options.html", "open_in_tab": true }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
:root {
|
||||||
|
color-scheme: light dark;
|
||||||
|
--line: color-mix(in srgb, currentColor 20%, transparent);
|
||||||
|
--muted: color-mix(in srgb, currentColor 60%, transparent);
|
||||||
|
}
|
||||||
|
body { margin: 0; font: 15px/1.5 system-ui, sans-serif; }
|
||||||
|
main { max-width: 520px; margin: 0 auto; padding: 24px 16px; }
|
||||||
|
h1 { font-size: 20px; margin: 0 0 16px; }
|
||||||
|
form { display: grid; gap: 16px; }
|
||||||
|
label { display: grid; gap: 4px; font-weight: 600; }
|
||||||
|
input { padding: 8px 10px; font: inherit; border: 1px solid var(--line); border-radius: 6px; background: transparent; color: inherit; }
|
||||||
|
.actions { display: flex; align-items: center; gap: 12px; }
|
||||||
|
button { padding: 8px 16px; font: inherit; border: 0; border-radius: 6px; background: #1a73e8; color: #fff; cursor: pointer; }
|
||||||
|
#saved { color: var(--muted); }
|
||||||
|
details { margin-top: 24px; color: var(--muted); }
|
||||||
|
summary { cursor: pointer; }
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html lang="ru">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
|
<title>Outlier Saver — настройки</title>
|
||||||
|
<link rel="stylesheet" href="options.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<main>
|
||||||
|
<h1>Outlier Saver</h1>
|
||||||
|
<form id="form">
|
||||||
|
<label>
|
||||||
|
API-ключ YouTube Data API v3
|
||||||
|
<input id="apiKey" type="password" autocomplete="off" spellcheck="false">
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Порог score (просмотры ÷ подписчики)
|
||||||
|
<input id="threshold" type="number" min="0.1" step="0.1" required>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
Минимум просмотров
|
||||||
|
<input id="minViews" type="number" min="0" step="1000" required>
|
||||||
|
</label>
|
||||||
|
<div class="actions">
|
||||||
|
<button type="submit">Сохранить</button>
|
||||||
|
<span id="saved" role="status"></span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<details>
|
||||||
|
<summary>Как получить API-ключ</summary>
|
||||||
|
<ol>
|
||||||
|
<li>Откройте <a href="https://console.cloud.google.com/" target="_blank" rel="noreferrer">Google Cloud Console</a> и создайте проект.</li>
|
||||||
|
<li>В разделе «API и сервисы → Библиотека» включите <b>YouTube Data API v3</b>.</li>
|
||||||
|
<li>В «Учётные данные» создайте <b>API-ключ</b>.</li>
|
||||||
|
<li>В ограничениях ключа выберите «Ограничить API → YouTube Data API v3». Ограничение по HTTP-источникам (referrer) <b>не включайте</b>: запросы идут из расширения.</li>
|
||||||
|
<li>Вставьте ключ в поле выше и нажмите «Сохранить».</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
||||||
|
</main>
|
||||||
|
<script type="module" src="options.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
import { getSettings, saveSettings } from '../lib/storage.js';
|
||||||
|
|
||||||
|
const form = document.getElementById('form');
|
||||||
|
const apiKey = document.getElementById('apiKey');
|
||||||
|
const threshold = document.getElementById('threshold');
|
||||||
|
const minViews = document.getElementById('minViews');
|
||||||
|
const savedLabel = document.getElementById('saved');
|
||||||
|
|
||||||
|
function fill(settings) {
|
||||||
|
apiKey.value = settings.apiKey;
|
||||||
|
threshold.value = settings.threshold;
|
||||||
|
minViews.value = settings.minViews;
|
||||||
|
}
|
||||||
|
|
||||||
|
fill(await getSettings());
|
||||||
|
|
||||||
|
form.addEventListener('submit', async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
fill(await saveSettings({ apiKey: apiKey.value, threshold: threshold.value, minViews: minViews.value }));
|
||||||
|
savedLabel.textContent = 'Сохранено';
|
||||||
|
setTimeout(() => {
|
||||||
|
savedLabel.textContent = '';
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user