commit 0d1366aa576f843fe84c8bd316387f5922fd00da Author: Choi lab Date: Tue May 12 11:10:14 2026 +0900 first commit diff --git a/content.js b/content.js new file mode 100644 index 0000000..c2171ae --- /dev/null +++ b/content.js @@ -0,0 +1,80 @@ +(function() { + // ボタン群を包むコンテナのID + const CONTAINER_ID = 'yt-swift-control-container'; + + function updateSpeedButtonStyle(btn, rate) { + if (rate === 2) { + btn.style.backgroundColor = "#ff0000"; + btn.style.color = "#ffffff"; + btn.style.fontWeight = "bold"; + btn.innerHTML = '2.0x'; + } else { + btn.style.backgroundColor = "rgba(255, 255, 255, 0.1)"; + btn.style.color = "#ffffff"; + btn.style.fontWeight = "normal"; + btn.innerHTML = '1.0x'; + } + } + + function createControlBtn(text, title, onClick) { + const btn = document.createElement('button'); + btn.className = 'ytp-button'; + btn.innerHTML = text; + btn.title = title; + btn.style.width = 'auto'; + btn.style.minWidth = '45px'; + btn.style.height = '30px'; + btn.style.marginTop = '8px'; + btn.style.marginRight = '5px'; + btn.style.borderRadius = '4px'; + btn.style.fontSize = '12px'; + btn.style.display = 'inline-flex'; + btn.style.alignItems = 'center'; + btn.style.justifyContent = 'center'; + btn.style.transition = 'background-color 0.2s'; + btn.style.verticalAlign = 'top'; + btn.onclick = onClick; + return btn; + } + + function injectControls() { + const controls = document.querySelector('.ytp-right-controls'); + if (!controls || document.getElementById(CONTAINER_ID)) return; + + const container = document.createElement('div'); + container.id = CONTAINER_ID; + container.style.display = 'inline-flex'; + container.style.marginRight = '10px'; + container.style.verticalAlign = 'top'; + + const video = document.querySelector('video'); + + // 1. 10秒巻き戻しボタン + const prevBtn = createControlBtn('←10', '10秒巻き戻す', () => { + if (video) video.currentTime -= 10; + }); + + // 2. 速度切り替えボタン + const speedBtn = createControlBtn('1.0x', '再生速度を1x/2xで切り替え', () => { + if (video) { + const newRate = video.playbackRate === 1 ? 2 : 1; + video.playbackRate = newRate; + updateSpeedButtonStyle(speedBtn, newRate); + } + }); + updateSpeedButtonStyle(speedBtn, video ? video.playbackRate : 1); + + // 3. 10秒スキップボタン + const nextBtn = createControlBtn('10→', '10秒スキップ', () => { + if (video) video.currentTime += 10; + }); + + container.appendChild(prevBtn); + container.appendChild(speedBtn); + container.appendChild(nextBtn); + controls.prepend(container); + } + + const observer = new MutationObserver(injectControls); + observer.observe(document.body, { childList: true, subtree: true }); +})(); \ No newline at end of file diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..e3d66cd Binary files /dev/null and b/icon.png differ diff --git a/manifest.json b/manifest.json new file mode 100644 index 0000000..bae3f8a --- /dev/null +++ b/manifest.json @@ -0,0 +1,20 @@ +{ + "manifest_version": 3, + "name": "YT Swift Control", + "version": "1.1", + "description": "10秒スキップ、巻き戻し、再生速度の瞬時切り替えボタンを追加します", + "permissions": ["activeTab"], + "icons": { + "128": "icon.png" + }, + "action": { + "default_icon": "icon.png" + }, + "content_scripts": [ + { + "matches": ["https://www.youtube.com/*"], + "js": ["content.js"], + "run_at": "document_idle" + } + ] +} \ No newline at end of file