diff --git a/.vscodeignore b/.vscodeignore
index 8a67662..0408f9e 100644
--- a/.vscodeignore
+++ b/.vscodeignore
@@ -5,6 +5,7 @@
**/*.map
**/*.ts
**/tsconfig.json
+lab
media/res
media/vscodeignore
node_modules
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1022b6e..17b5488 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -17,35 +17,45 @@ Check [Keep a Changelog](http://keepachangelog.com) for recommendations on how t
- Shelljs vs Execa
- Support for other sites
+## [2.1.0] - July 2024
+- Fix Spotify and YouTube Music due to its UI change
+- webpack 5.92.1 compiled successfully in 10241 ms
+- 20 files, 1.4MB, 1.91.0
+
+### Note
+- Updating this project to 3.0 was rough, so here is the minor release
+- The Puppeteer@22 was having undesired bugs and behaviors
+- Adding puppeteer-extra on top of it = more strange behaviors
+- Why does Webpack's behavior change? - it doesn't combine files anymore
+
## [2.0.0] - December 2021
- Add new feature - treeview
- Rewrite/refactor most of the code - 30+ commits
- New float button style - old vs new in Windows
-- Fix Spotify bug due to it's style class's changes
+- Fix Spotify bug due to its style class's changes
- Fix site English version issue - observes another DOM element to update playback status
- Merge play and pause commands into one toggle function
- Move most of the minor inject action to inject script instead
- Re-config project's configs like eslint, tsconfig, vscode setting, and webpack (.js -> .ts)
- Rename directories: icon -> media, scripts -> inject
-- Playback icons is sync with the site's playback icons which was behaved contrarily before
+- Playback icons are synced with the site's playback icons, which behaved contrarily before
- Webpack 5.65.0 compiled successfully in 9980 ms
- 15 files, 1.39MB, 1.63.0
### Note
-#### This release mostly has more significant impact on the dev side rather than like a product update.
-
-#### One funny thing is that the picture in README.md accounts for a large part of this extension's size.
+- This release mostly has a more significant impact on the dev side rather than a product update.
+- One funny thing is that the picture in README.md accounts for a large part of this extension's size.
#### [MediaSession](https://developer.mozilla.org/en-US/docs/Web/API/MediaSession)
-- Soundcloud does update `playbackState` but only call `set` for from press play
-- Spotify does call `set` to update metadata but playbackState always *none*
+- Soundcloud does update `playbackState` but only calls `set` from pressing play
+- Spotify does call `set` to update metadata, but playbackState always *none*
- Youtube and YTmusic update `playbackState` consistent with proxy `set` event
#### Puppeteer
-- Seem Puppeteer doesn't keep track pages/tabs' order
-- If click too quick, this shows up: `Error: Execution context is not available in detached frame "about:blank" (are you trying to evaluate?)`
+- It seems like Puppeteer doesn't keep track of pages/tabs' order
+- If clicking too quickly, this shows up: `Error: Execution context is not available in detached frame "about:blank" (are you trying to evaluate?)`
Waiting and try/catch was fruitless
## [1.4.0] - October 2020
@@ -58,7 +68,7 @@ Check [Keep a Changelog](http://keepachangelog.com) for recommendations on how t
## [1.3.0] - February 2020
- Add [ignoreDisableSync](https://github.com/puppeteer/puppeteer/blob/0b1777e73cb1e83ece9e09b7b51d11b798def06f/lib/Launcher.js#L277) setting [#3](https://github.com/lanly-dev/VSCode-LMPTM/issues/3#issuecomment-572180371), [#5](https://github.com/lanly-dev/VSCode-LMPTM/issues/5)
- Remove [Adblocker](https://github.com/cliqz-oss/adblocker/tree/master/packages/adblocker-puppeteer) - New version breaks webpack build
-- Ignore [disable extension flag from puppeteer](https://github.com/puppeteer/puppeteer/blob/0b1777e73cb1e83ece9e09b7b51d11b798def06f/lib/Launcher.js#L270)
+- Ignore [disable extension flag from Puppeteer](https://github.com/puppeteer/puppeteer/blob/0b1777e73cb1e83ece9e09b7b51d11b798def06f/lib/Launcher.js#L270)
- Switch tslint to eslint in development
- 11 files, 141.77KB, 1.42.0
diff --git a/README.md b/README.md
index 2f3d961..200b0c9 100644
--- a/README.md
+++ b/README.md
@@ -1,14 +1,12 @@
-# LetMePlayTheMusic README
+# [LetMePlayTheMusic](https://marketplace.visualstudio.com/items?itemName=lanly-dev.letmeplaythemusic)
-[![Version](https://vsmarketplacebadge.apphb.com/version-short/lanly-dev.letmeplaythemusic.svg)](https://marketplace.visualstudio.com/items?itemName=lanly-dev.letmeplaythemusic)
-
-Tired or get annoyed from switching windows in order to pause or skip a song?\
+Are you tired or annoyed from switching windows in order to pause or skip a song?\
Doesn't want to or lazy to install the extra official players to the system?\
Or perhaps your keyboard doesn't have the handy media hotkeys?\
-Wanted to stay focus on your programing instead of those shortcomings above?
+Do you want to stay focused on your programming instead of those shortcomings above?
If yes, you are in luck!\
-This extension launches a Chrome/Chromium browser to the 4 popular music sites and you can control the playback from within your favorite Visual Studio Code editor.
+This extension launches a Chrome/Chromium browser to the 4 popular music sites, and you can control the playback from within your favorite Visual Studio Code editor.
>Extra [use case](https://github.com/lanly-dev/VSCode-LMPTM/issues/8#issuecomment-661796089) - you could use this extension to follow programming tutorials on Youtube with the handy seek forward/backward key shortcuts.
@@ -17,7 +15,7 @@ This extension launches a Chrome/Chromium browser to the 4 popular music sites a
## Features
-Supports SoundCloud, Spotify, Youtube and Youtube Music
+Supports SoundCloud, Spotify, YouTube, and YouTube Music
## Requirements
Required Chromium-based browser
@@ -25,24 +23,26 @@ Required Chromium-based browser
## Extension Settings
* `lmptm.browserPath`: Specify custom browser executable file path.
* `lmptm.ignoreDisableSync`: Ignore --disable-sync, this option is specifically for [Brave](https://brave.com) browser.
-* `lmptm.incognitoMode`: Specify whether to launch browser in incognito/private mode.
+* `lmptm.incognitoMode`: Specify whether to launch the browser in incognito/private mode.
* `lmptm.startPages`: Starting tabs.
-* `lmptm.userData`: Specify if the extension could store browser's user data, if enabled, user data directory setting is required.
-* `lmptm.userDataDirectory`: Specify [user data directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md), this will be ignored if **User Data** setting is unchecked.
+* `lmptm.userData`: Specify if the extension could store the browser's user data; if enabled, a user-data directory setting is required.
+* `lmptm.userDataDirectory`: Specify [user data directory](https://chromium.googlesource.com/chromium/src/+/master/docs/user_data_dir.md). This setting will be ignored if **User Data** setting is unchecked.
## Known Issues
- Does not work with Opera browser
-- Won't be able to login Youtube and SoundCloud(email method)
+- Won't be able to log into YouTube and SoundCloud(email method)
## Release Notes
+### 2.1.0
+- Fix Spotify and YouTube Music for its UI changes
+
### 2.0.0
-- Add treeview - so now the the app can switch between tabs
- 1. The page has to be picked before being able to use in the treeview
+- Fix Spotify bugs for its UI changes
+- Add treeview - so now the app can switch between tabs
+ 1. The page has to be picked before being able to be used in the treeview
2. You can select the treeview items that have the play/pause icon
3. The emoji ⛏️ means the tab is currently picked
- 4. First click switches the picked icon to target tab, later clicks toggles playing/paused status of the target tab media's playback
-
-- Fix spotify bugs due to it's new UI changes
+ 4. The first click switches the picked icon to the target tab, and the clicks that come after toggle the playing/paused status of the target tab media's playback
### 1.4.0
- Add key shortcuts
@@ -52,7 +52,7 @@ Required Chromium-based browser
### 1.3.0
- Remove adblocker
-- Enable adding extensions for browser
+- Enable adding extensions for the browser
- Add ignoreDisableSync setting option in order to able to launch [Brave](https://brave.com) browser
### 1.2.0
diff --git a/package.json b/package.json
index 896664c..1e73882 100644
--- a/package.json
+++ b/package.json
@@ -3,10 +3,10 @@
"displayName": "Let Me Play The Music",
"description": "Playback control buttons for the popular music sites",
"homepage": "https://github.com/lanly-dev/VSCode-LMPTM",
- "version": "2.0.0",
+ "version": "2.1.0",
"publisher": "lanly-dev",
"engines": {
- "vscode": "^1.63.0"
+ "vscode": "^1.91.0"
},
"extensionKind": [
"ui"
@@ -129,26 +129,26 @@
},
"devDependencies": {
"@types/copy-webpack-plugin": "^8.0.1",
- "@types/karma-chrome-launcher": "^3.1.1",
- "@types/node": "^16.11.13",
+ "@types/karma-chrome-launcher": "^3.1.4",
+ "@types/node": "^20.14.10",
"@types/puppeteer-core": "^5.4.0",
- "@types/shelljs": "^0.8.9",
- "@types/vscode": "^1.63.0",
- "@typescript-eslint/eslint-plugin": "^5.7.0",
- "@typescript-eslint/parser": "^5.7.0",
- "copy-webpack-plugin": "^10.1.0",
- "css-minimizer-webpack-plugin": "^3.2.0",
+ "@types/shelljs": "^0.8.15",
+ "@types/vscode": "^1.91.0",
+ "@typescript-eslint/eslint-plugin": "^7.15.0",
+ "@typescript-eslint/parser": "^7.15.0",
+ "copy-webpack-plugin": "^12.0.2",
+ "css-minimizer-webpack-plugin": "^7.0.0",
"eslint": "^8.4.1",
- "shelljs": "^0.8.4",
- "ts-loader": "^9.2.6",
- "ts-node": "^10.4.0",
- "typescript": "^4.5.4",
+ "shelljs": "^0.8.5",
+ "ts-loader": "^9.5.1",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.5.3",
"vsce": "^2.5.1",
- "webpack": "^5.65.0",
- "webpack-cli": "^4.9.1"
+ "webpack": "^5.92.1",
+ "webpack-cli": "^5.1.4"
},
"dependencies": {
- "karma-chrome-launcher": "^3.1.0",
+ "karma-chrome-launcher": "^3.2.0",
"puppeteer-core": "^13.0.0"
},
"repository": {
diff --git a/src/browser.ts b/src/browser.ts
index 57d79e6..717b48e 100644
--- a/src/browser.ts
+++ b/src/browser.ts
@@ -2,15 +2,15 @@ import * as path from 'path'
import * as puppeteer from 'puppeteer-core'
import * as vscode from 'vscode'
-import { Buttons } from './buttons'
-import { TreeviewProvider } from './treeview'
-import { WhichChrome } from './whichChrome'
import { Entry } from './interfaces'
-import { HTTPResponse } from 'puppeteer-core'
+
+import Buttons from './buttons'
+import TreeviewProvider from './treeview'
+import WhichChrome from './whichChrome'
const SEEK_MSG = 'Seeking backward/forward function is only work for Youtube videos. 💡'
const STATE_MSG = 'Please select the tab/page that either in playing or paused. 💡'
-export class Browser {
+export default class Browser {
public static activeBrowser: Browser | undefined
public static cssPath: string
public static jsPath: string
@@ -127,8 +127,9 @@ export class Browser {
await this.selectedPage.keyboard.up('ShiftLeft')
break
case 'spotify':
- // @ts-ignore
- this.selectedPage.evaluate(() => spotifyAction('skip'))
+ await this.selectedPage.keyboard.down('ControlLeft')
+ await this.selectedPage.keyboard.press('ArrowRight')
+ await this.selectedPage.keyboard.up('ControlLeft')
break
case 'youtube':
await this.selectedPage.keyboard.down('ShiftLeft')
@@ -149,8 +150,9 @@ export class Browser {
await this.selectedPage.keyboard.up('ShiftLeft')
break
case 'spotify':
- // @ts-ignore
- this.selectedPage.evaluate(() => spotifyAction('back'))
+ await this.selectedPage.keyboard.down('ControlLeft')
+ await this.selectedPage.keyboard.press('ArrowLeft')
+ await this.selectedPage.keyboard.up('ControlLeft')
break
case 'youtube':
this.selectedPage.goBack()
@@ -204,7 +206,7 @@ export class Browser {
private async launchPages() {
const links: string[] | undefined = vscode.workspace.getConfiguration().get('lmptm.startPages')
if (links && links.length) {
- const p: Promise[] = []
+ const p: Promise[] = []
links.forEach(async (e: string) => {
const pg = await this.newPage()
await pg.setDefaultNavigationTimeout(0)
@@ -295,6 +297,7 @@ export class Browser {
}
private async pageChanged(page: puppeteer.Page) {
+ // @ts-ignore
await page.waitForNetworkIdle() // this somehow prevents navigation error
const pageURL = page.url()
const brand = this.musicBrandCheck(pageURL)
diff --git a/src/buttons.ts b/src/buttons.ts
index 6ea6ab9..9a4862f 100644
--- a/src/buttons.ts
+++ b/src/buttons.ts
@@ -1,6 +1,6 @@
import { window, StatusBarItem, StatusBarAlignment } from 'vscode'
-export class Buttons {
+export default class Buttons {
private playButton: StatusBarItem
private skipButton: StatusBarItem
private backButton: StatusBarItem
diff --git a/src/extension.ts b/src/extension.ts
index 6521bbd..45903f0 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -1,8 +1,9 @@
import { commands, window, ExtensionContext } from 'vscode'
-import { Browser } from './browser'
-import { Buttons } from './buttons'
import { Entry } from './interfaces'
-import { TreeviewProvider } from './treeview'
+
+import Browser from './browser'
+import Buttons from './buttons'
+import TreeviewProvider from './treeview'
export function activate(context: ExtensionContext) {
const buttons = new Buttons()
diff --git a/src/inject/script.js b/src/inject/script.js
index 0948fad..3540060 100644
--- a/src/inject/script.js
+++ b/src/inject/script.js
@@ -11,9 +11,8 @@ const playButtonAttrs = {
},
spotify: {
css: 'button[data-testid="control-button-playpause"]',
- cssAll5Btns: '.player-controls button',
cssTitle: 'div[data-testid="now-playing-widget"]',
- play: 'M4.018 14L14.41 8 4.018 2z'
+ play: 'M3 1.713a.7.7 0 0 1 1.05-.607l10.89 6.288a.7.7 0 0 1 0 1.212L4.05 14.894A.7.7 0 0 1 3 14.288V1.713z'
},
youtube: { css: '.ytp-play-button' },
ytmusic: { css: '#play-pause-button' }
@@ -69,8 +68,7 @@ function click() {
}
brand = 'youtube'
} else if (href.includes('music.youtube.com')) {
- const e = 'ytmusic-app-layout[player-visible_] > [slot=player-bar]'
- if (!document.querySelectorAll(e)[0]) {
+ if (!href.includes('/watch')) {
btnPick.disabled = true
return void showInfo(btnPick, 'ytmusic')
}
@@ -187,23 +185,9 @@ function showInfo(btnPick, brand) {
btnTimeoutReset(btnPick)
}
-// eslint-disable-next-line @typescript-eslint/no-unused-vars
-function spotifyAction(action) {
- const { cssAll5Btns } = playButtonAttrs.spotify
- const actionBtn = document.querySelectorAll(cssAll5Btns)
- switch (action) {
- case 'skip':
- actionBtn[3].click()
- break
- case 'back':
- actionBtn[1].click()
- break
- }
-}
-
function btnTimeoutReset(btnPick) {
setTimeout(() => {
- btnPick.innerHTML = '⛏️ Pick?'
+ btnPick.innerHTML = PICK_MSG
btnPick.className = 'btn-pick-float'
btnPick.disabled = false
}, 3000)
@@ -211,7 +195,7 @@ function btnTimeoutReset(btnPick) {
function reset() {
const btnPick = document.querySelector('.btn-pick-float')
- btnPick.innerHTML = '⛏️ Pick?'
+ btnPick.innerHTML = PICK_MSG
btnPick.className = 'btn-pick-float'
sessionStorage.removeItem('lmptm')
}
diff --git a/src/treeview.ts b/src/treeview.ts
index 0f9e259..3056af9 100644
--- a/src/treeview.ts
+++ b/src/treeview.ts
@@ -1,8 +1,8 @@
-import { Browser } from './browser'
-import { Event, EventEmitter, ThemeIcon, TreeDataProvider, TreeItem, window } from 'vscode'
import { Entry } from './interfaces'
+import { Event, EventEmitter, ThemeIcon, TreeDataProvider, TreeItem, window } from 'vscode'
+import Browser from './browser'
-export class TreeviewProvider implements TreeDataProvider {
+export default class TreeviewProvider implements TreeDataProvider {
public static tvProvider: TreeviewProvider
private _onDidChangeTreeData: EventEmitter = new EventEmitter()
diff --git a/src/whichChrome.ts b/src/whichChrome.ts
index 1ec37e9..5f00cfa 100644
--- a/src/whichChrome.ts
+++ b/src/whichChrome.ts
@@ -1,14 +1,9 @@
'use strict'
-
-interface Paths {
- [key: string]: string
-}
-
import * as karmaChromeLauncher from 'karma-chrome-launcher'
-export class WhichChrome {
+export default class WhichChrome {
public static getPaths() {
- const chromePaths: Paths = {}
+ const chromePaths: { [key: string]: string } = {}
Object.keys(karmaChromeLauncher).forEach(key => {
if (key.indexOf('launcher:') !== 0) return
// @ts-ignore
diff --git a/webpack.config.ts b/webpack.config.ts
index dfe72ce..7c558aa 100644
--- a/webpack.config.ts
+++ b/webpack.config.ts
@@ -20,6 +20,7 @@ export default {
externals: {
vscode: 'commonjs vscode', // the vscode-module is created on-the-fly and must be excluded. Add other modules that cannot be webpack'ed, 📖 -> https://webpack.js.org/configuration/externals/
bufferutil: 'commonjs bufferutil', // https://github.com/websockets/ws/issues/1220#issuecomment-433066790
+ // eslint-disable-next-line @typescript-eslint/naming-convention
'utf-8-validate': 'commonjs utf-8-validate'
},
resolve: {