Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wip: manifest v3 #24

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
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
147 changes: 43 additions & 104 deletions add-on/background.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
'use strict'
/* eslint-env browser, webextensions */
/* eslint-env chrome. webextensions */

const googleMusicPlayerUrl = 'https://play.google.com/music/listen*'
const youtubeMusicPlayerUrl = 'https://music.youtube.com/*'
Expand All @@ -10,7 +10,7 @@ const nextSongCommand = 'next-song'
const backupSuffix = '-backup'

async function openPlayer () {
await browser.tabs.create({
await chrome.tabs.create({
pinned: true,
url: youtubeMusicPlayerUrl.replace('*', '')
})
Expand All @@ -30,68 +30,9 @@ function scriptFor (command, scriptThatClicksOn) {
}
}

function googleMusicScriptThatClicksOn (actionName) { // TODO: remove them GM is dead
const script = function () {
// Google Music (to be removed)
// ============================
const buttons = document.getElementsByTagName('paper-icon-button')
let disabledMainPlayButton = false
for (let i = 0; i < buttons.length; i++) {
if (buttons[i].getAttribute('data-id') === 'kitty') {
if (buttons[i].style['pointer-events'] === 'none') {
disabledMainPlayButton = true
} else {
buttons[i].click()
}
break
}
}
const tryFallbackButtons = function () {
// try I'm Feeling Lucky button (main page)
let buttons = document.getElementsByTagName('gpm-ifl-button')
if (buttons.length > 0) {
console.log('[Google Music Hotkeys] Playing Feeling Lucky Radio')
buttons[0].click()
return
}
// try first 'play' button (eg. on album listing page)
buttons = document.getElementsByTagName('button')
for (let i = 0; i < buttons.length; i++) {
if (buttons[i].getAttribute('data-id') === 'play') {
console.log('[Google Music Hotkeys] Playing first playable item')
buttons[i].click()
return
}
}
// TODO: try 'play all' button (eg. on album listing page)
// try standalone play button (eg. on a radio page)
const playButton = document.getElementById('playButton')
if (playButton) {
console.log('[Google Music Hotkeys] Playing current context')
playButton.click()
return
}
// try context's shuffle button (eg. on the main library page)
buttons = document.getElementsByTagName('paper-button')
for (let i = 0; i < buttons.length; i++) {
if (buttons[i].getAttribute('data-id') === 'shuffle-my-library') {
console.log('[Google Music Hotkeys] Playing shuffled library')
buttons[i].click()
return
}
}
}
if (disabledMainPlayButton) {
// https://github.com/lidel/google-music-hotkeys/issues/2
console.log('[Google Music Hotkeys] trying to load a new playlist..')
tryFallbackButtons()
}
}
return '(' + script.toString().replace('kitty', actionName) + ')()'
}

function youTubeMusicScriptThatClicksOn (actionName) {
const script = function () {
return () => {
// TODO: revisit when YouTube Music adds 'feeling lucky' on page without player
const findButton = (actionName) => {
const qs = (q) => document.querySelector(q)
Expand All @@ -104,18 +45,17 @@ function youTubeMusicScriptThatClicksOn (actionName) {
return qs('.ytmusic-player-bar.play-pause-button') || qs('.play-pause-button') || document.getElementById('play-button')
}
}
const button = findButton('kitty')
const button = findButton(actionName)
if (button) {
button.click()
} else {
console.log('[YouTube Music Hotkeys] unable to find the play button, please report a bug at https://github.com/lidel/google-music-hotkeys/issues/new')
}
}
return '(' + script.toString().replace('kitty', actionName) + ')()'
}

function podcastsScriptThatClicksOn (actionName) {
const script = function (actionName) {
return () => {
const getElementFromAria = function (...strings) {
const selector = strings.map(str => `div[aria-label="${str}"]`).join(', ')
return document.querySelector(selector)
Expand Down Expand Up @@ -151,89 +91,88 @@ function podcastsScriptThatClicksOn (actionName) {
}
}
}
return '(' + script.toString() + ')("' + actionName + '")'
}

async function executeGoogleMusicCommand (command) {
console.log('[Google Music Hotkeys] executing command: ', command)
const gmTabs = await browser.tabs.query({ url: googleMusicPlayerUrl })
const ymTabs = await browser.tabs.query({ url: youtubeMusicPlayerUrl })
const gpTabs = await browser.tabs.query({ url: gpodcastMusicPlayerUrl })
const gmTabs = await chrome.tabs.query({ url: googleMusicPlayerUrl })
const ymTabs = await chrome.tabs.query({ url: youtubeMusicPlayerUrl })
const gpTabs = await chrome.tabs.query({ url: gpodcastMusicPlayerUrl })

if (gmTabs.length === 0 && ymTabs.length === 0 && gpTabs.length === 0) {
openPlayer()
return
}
for (const tab of gmTabs) { // TODO: remove them GM is dead
browser.tabs.executeScript(tab.id, {
runAt: 'document_start',
code: scriptFor(command, googleMusicScriptThatClicksOn)
})
}
for (const tab of ymTabs) {
browser.tabs.executeScript(tab.id, {
runAt: 'document_start',
code: scriptFor(command, youTubeMusicScriptThatClicksOn)
// TODO: wait until chrome.scripting.executeScript is present in Brave
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: scriptFor(command, youTubeMusicScriptThatClicksOn)
})
}
for (const tab of gpTabs) {
browser.tabs.executeScript(tab.id, {
runAt: 'document_start',
code: scriptFor(command, podcastsScriptThatClicksOn)
chrome.scripting.executeScript({
target: { tabId: tab.id },
func: scriptFor(command, podcastsScriptThatClicksOn)
})
}
}

async function onRuntimeMessage (request, sender) {
console.log('[Google Music Hotkeys] onRuntimeMessage', request)
await browser.tabs.executeScript(sender.tab.id, {
runAt: 'document_start',
code: scriptFor(request.command)
await chrome.scripting.executeScript({
target: { tabId: sender.tab.id },
func: scriptFor(request.command)
})
}

// listen for keyboard hotkeys
browser.commands.onCommand.addListener(executeGoogleMusicCommand)
chrome.commands.onCommand.addListener(executeGoogleMusicCommand)

// listen for messages from content script
setTimeout(() => {
// this needs to be run bit later due to a bug in Chrome with current browser polyfill:
// Uncaught Error: runtime namespace is null or undefined
browser.runtime.onMessage.addListener(onRuntimeMessage)
}, 250)
chrome.runtime.onMessage.addListener(onRuntimeMessage)

// regular click on browser action toggles playback
browser.browserAction.onClicked.addListener(() => executeGoogleMusicCommand('toggle-playback'))
// regular click on chrome.action toggles playback
chrome.action.onClicked.addListener(() => executeGoogleMusicCommand('toggle-playback'))

// context-click on browser action displays more options
browser.contextMenus.create({
// context-click on chrome.action displays more options

/* TODO
chrome.contextMenus.removeAll()

chrome.contextMenus.create({
id: 'toggle-playback-menu-item',
title: 'Toggle Playback',
contexts: ['browser_action'],
onclick: () => executeGoogleMusicCommand(togglePlaybackCommand)
// TODO: onclick: () => executeGoogleMusicCommand(togglePlaybackCommand)
// TODO Extensions using event pages or Service Workers cannot pass an onclick parameter to chrome.contextMenus.create.
// TODO Instead, use the chrome.contextMenus.onClicked event.
})
browser.contextMenus.create({

chrome.contextMenus.create({
id: 'previous-song-menu-item',
title: 'Previous Song',
contexts: ['browser_action'],
onclick: () => executeGoogleMusicCommand(previousSongCommand)
// TODO: onclick: () => executeGoogleMusicCommand(previousSongCommand)
})
browser.contextMenus.create({
chrome.contextMenus.create({
id: 'next-song-menu-item',
title: 'Next Song',
contexts: ['browser_action'],
onclick: () => executeGoogleMusicCommand(nextSongCommand)
// TODO: onclick: () => executeGoogleMusicCommand(nextSongCommand)
})
browser.contextMenus.create({
chrome.contextMenus.create({
id: 'open-preferences-menu-item',
title: 'Customize Shortcuts',
contexts: ['browser_action'],
onclick: () => {
browser.runtime.openOptionsPage()
TODO onclick: () => {
chrome.runtime.openOptionsPage()
.catch((err) => {
console.error('runtime.openOptionsPage() failed, opening options page in tab instead.', err)
// fallback for weird browsers ;-)
browser.tabs.create({ url: browser.extension.getURL('options.html') })
// fallback for weird chrome. ;-)
chrome.tabs.create({ url: chrome.extension.getURL('options.html') })
})
}
})

*/
21 changes: 12 additions & 9 deletions add-on/manifest.json
Original file line number Diff line number Diff line change
@@ -1,32 +1,35 @@
{
"manifest_version": 2,
"manifest_version": 3,
"name": "YouTube Music Hotkeys",
"version" : "1.9.0",
"version" : "2.0.0",
"description": "Use keyboard shortcuts to control YouTube Music",
"homepage_url": "https://github.com/lidel/google-music-hotkeys",
"author": "Marcin Rataj",
"author": "lidel",
"icons": {
"128": "Play_music_triangle.png"
},

"permissions": [
"https://play.google.com/music/listen*",
"https://podcasts.google.com/*",
"https://music.youtube.com/*",
"contextMenus",
"tabs"
],

"host_permissions": [
"https://play.google.com/music/listen*",
"https://podcasts.google.com/*",
"https://music.youtube.com/*"
],

"background": {
"scripts": ["browser-polyfill.min.js", "background.js"]
"service_worker": "background.js"
},

"options_ui": {
"page": "options.html",
"browser_style": true
},

"browser_action": {
"action": {
"browser_style": true,
"default_icon": {
"128": "Play_music_triangle.png"
Expand Down Expand Up @@ -64,7 +67,7 @@
"https://podcasts.google.com/*",
"https://music.youtube.com/*"
],
"js": ["browser-polyfill.min.js", "autoplay.js"],
"js": ["autoplay.js"],
"all_frames" : false,
"run_at": "document_idle"
}
Expand Down
3 changes: 1 addition & 2 deletions add-on/options.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!DOCTYPE html>

<html>
<html lang=en>
<head>
<meta charset="utf-8">
<style>
Expand Down Expand Up @@ -60,7 +60,6 @@ <h2>How To Customize Shortcuts in Chrome</h2>
</li>
</ol>
</div>
<script src="browser-polyfill.min.js"></script>
<script src="webextensions-lib-shortcut-customize-ui/ShortcutCustomizeUI.js"></script>
<script src="options.js"></script>
</body>
Expand Down
Loading