Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions js&css/extension/www.youtube.com/player/media-keys-content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Media key handler for YouTube player (content script)

class YouTubeMediaKeyController {
constructor() {
this.video = null;
this.initialize();
}

initialize() {
// Wait for the video element to be available
this.waitForVideoElement().then(() => {
this.setupEventListeners();
});

// Listen for messages from background script
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
if (request.type === 'MEDIA_KEY_ACTION') {
this.handleMediaKeyAction(request.action, request.value);
}
});
}

waitForVideoElement() {
return new Promise((resolve) => {
const checkVideo = () => {
this.video = document.querySelector('video');
if (this.video) {
resolve();
} else {
setTimeout(checkVideo, 500);
}
};
checkVideo();
});
}

setupEventListeners() {
// Re-initialize if video element changes (e.g., when navigating between videos)
const observer = new MutationObserver((mutations) => {
if (!document.body.contains(this.video)) {
this.video = document.querySelector('video');
}
});

observer.observe(document.body, { childList: true, subtree: true });
}

handleMediaKeyAction(action, value) {
if (!this.video) {
this.video = document.querySelector('video');
if (!this.video) return;
}

try {
switch (action) {
case 'skip':
this.video.currentTime += value;
this.showSkipFeedback(value > 0 ? 'forward' : 'backward', Math.abs(value));
break;
case 'playPause':
if (this.video.paused) {
this.video.play();
} else {
this.video.pause();
}
break;
}
} catch (error) {
console.error('Error handling media key action:', error);
}
}

showSkipFeedback(direction, seconds) {
// Create or update feedback element
let feedback = document.getElementById('improvedtube-skip-feedback');
if (!feedback) {
feedback = document.createElement('div');
feedback.id = 'improvedtube-skip-feedback';
feedback.style.position = 'fixed';
feedback.style.top = '50%';
feedback.style.left = '50%';
feedback.style.transform = 'translate(-50%, -50%)';
feedback.style.backgroundColor = 'rgba(0, 0, 0, 0.7)';
feedback.style.color = 'white';
feedback.style.padding = '10px 20px';
feedback.style.borderRadius = '20px';
feedback.style.fontSize = '24px';
feedback.style.zIndex = '9999';
feedback.style.display = 'flex';
feedback.style.alignItems = 'center';
feedback.style.justifyContent = 'center';
document.body.appendChild(feedback);

// Auto-remove after animation
setTimeout(() => {
if (feedback) {
feedback.style.opacity = '0';
feedback.style.transition = 'opacity 0.5s';
setTimeout(() => {
if (feedback && feedback.parentNode) {
feedback.parentNode.removeChild(feedback);
}
}, 500);
}
}, 1000);
}

// Update feedback content
const icon = direction === 'forward' ? '⏩' : '⏪';
feedback.textContent = `${icon} ${seconds}s`;
feedback.style.opacity = '1';
feedback.style.transition = 'none';
}
}

// Initialize when page is loaded
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', () => {
new YouTubeMediaKeyController();
});
} else {
new YouTubeMediaKeyController();
}
50 changes: 50 additions & 0 deletions js&css/extension/www.youtube.com/player/media-keys.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// Media key handler for YouTube player

class MediaKeyHandler {
constructor() {
this.skipSeconds = 10; // Default skip duration in seconds
this.initialize();
}

initialize() {
// Load saved skip duration from storage
chrome.storage.local.get(['mediaKeySkipSeconds'], (result) => {
if (result.mediaKeySkipSeconds) {
this.skipSeconds = parseInt(result.mediaKeySkipSeconds, 10);
}
});

// Listen for media key commands
chrome.commands.onCommand.addListener((command) => {
if (command === 'mediaNextTrack') {
this.forward();
} else if (command === 'mediaPrevTrack') {
this.rewind();
}
});
}

// Send message to content script to control video
sendMessage(action, value) {
chrome.tabs.query({url: '*://*.youtube.com/*'}, (tabs) => {
if (tabs && tabs.length > 0) {
chrome.tabs.sendMessage(tabs[0].id, {
type: 'MEDIA_KEY_ACTION',
action: action,
value: value
});
}
});
}

forward() {
this.sendMessage('skip', this.skipSeconds);
}

rewind() {
this.sendMessage('skip', -this.skipSeconds);
}
}

// Initialize media key handler when the script loads
const mediaKeyHandler = new MediaKeyHandler();
31 changes: 29 additions & 2 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,15 +51,40 @@
"js&css/extension/www.youtube.com/general/general.js",
"js&css/extension/www.youtube.com/appearance/sidebar/sidebar.js",
"js&css/extension/www.youtube.com/appearance/comments/comments.js",
"js&css/extension/www.youtube.com/player/media-keys.js",
"js&css/extension/www.youtube.com/player/media-keys-content.js",
"js&css/extension/init.js"
],
"matches": ["https://www.youtube.com/*"],
"run_at": "document_start"
}
],
"host_permissions": ["https://www.youtube.com/*"],
"optional_permissions": ["downloads"],
"permissions": ["contextMenus", "storage"],
"optional_permissions": [
"downloads"
],
"permissions": [
"contextMenus",
"storage",
"tabs",
"scripting",
"webNavigation",
"commands"
],
"commands": {
"mediaPrevTrack": {
"suggested_key": {
"default": "MediaPrevTrack"
},
"description": "Rewind video by 10 seconds"
},
"mediaNextTrack": {
"suggested_key": {
"default": "MediaNextTrack"
},
"description": "Fast forward video by 10 seconds"
}
},
"web_accessible_resources": [
{
"resources": [
Expand All @@ -68,6 +93,8 @@
"js&css/web-accessible/functions.js",
"js&css/web-accessible/www.youtube.com/appearance.js",
"js&css/web-accessible/www.youtube.com/player.js",
"js&css/web-accessible/www.youtube.com/player/media-keys.js",
"js&css/web-accessible/www.youtube.com/player/media-keys-content.js",
"js&css/web-accessible/www.youtube.com/themes.js",
"js&css/web-accessible/www.youtube.com/playlist.js",
"js&css/web-accessible/www.youtube.com/playlist-complete-playlist.js",
Expand Down