mirror of
https://github.com/th-ch/youtube-music.git
synced 2026-01-10 18:21:47 +00:00
Merge branch 'local-upstream/master' into use-ToastXML
This commit is contained in:
20
.github/workflows/dependency-review.yml
vendored
Normal file
20
.github/workflows/dependency-review.yml
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
# Dependency Review Action
|
||||
#
|
||||
# This Action will scan dependency manifest files that change as part of a Pull Reqest, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
|
||||
#
|
||||
# Source repository: https://github.com/actions/dependency-review-action
|
||||
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
|
||||
name: "Dependency Review"
|
||||
on: [pull_request]
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
dependency-review:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: "Checkout Repository"
|
||||
uses: actions/checkout@v3
|
||||
- name: "Dependency Review"
|
||||
uses: actions/dependency-review-action@v3
|
||||
11
index.js
11
index.js
@ -311,17 +311,6 @@ app.once("browser-window-created", (event, win) => {
|
||||
win.webContents.on("will-prevent-unload", (event) => {
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
win.webContents.on(
|
||||
"new-window",
|
||||
(e, url, frameName, disposition, options) => {
|
||||
// hook on new opened window
|
||||
|
||||
// at now new window in mainWindow renderer process.
|
||||
// Also, this will automatically get an option `nodeIntegration=false`(not override to true, like in iframe's) - like in regular browsers
|
||||
options.webPreferences.affinity = "main-window";
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
app.on("window-all-closed", () => {
|
||||
|
||||
9
menu.js
9
menu.js
@ -1,7 +1,7 @@
|
||||
const { existsSync } = require("fs");
|
||||
const path = require("path");
|
||||
|
||||
const { app, Menu, dialog } = require("electron");
|
||||
const { app, clipboard, Menu, dialog } = require("electron");
|
||||
const is = require("electron-is");
|
||||
const { restart } = require("./providers/app-controls");
|
||||
|
||||
@ -327,6 +327,13 @@ const mainMenuTemplate = (win) => {
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Copy current URL",
|
||||
click: () => {
|
||||
const currentURL = win.webContents.getURL();
|
||||
clipboard.writeText(currentURL);
|
||||
},
|
||||
},
|
||||
{
|
||||
label: "Restart App",
|
||||
click: restart
|
||||
|
||||
24
package.json
24
package.json
@ -89,7 +89,7 @@
|
||||
"release:win": "yarn run clean && electron-builder --win -p always"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14.0.0",
|
||||
"node": ">=16.0.0",
|
||||
"npm": "Please use yarn and not npm"
|
||||
},
|
||||
"dependencies": {
|
||||
@ -103,7 +103,7 @@
|
||||
"butterchurn": "^2.6.7",
|
||||
"butterchurn-presets": "^2.4.7",
|
||||
"chokidar": "^3.5.3",
|
||||
"custom-electron-prompt": "^1.5.0",
|
||||
"custom-electron-prompt": "^1.5.1",
|
||||
"custom-electron-titlebar": "^4.1.5",
|
||||
"discord-rpc": "^4.0.1",
|
||||
"electron-better-web-request": "^1.0.1",
|
||||
@ -112,9 +112,9 @@
|
||||
"electron-localshortcut": "^3.2.1",
|
||||
"electron-store": "^8.1.0",
|
||||
"electron-unhandled": "^4.0.1",
|
||||
"electron-updater": "^4.6.3",
|
||||
"electron-updater": "^5.3.0",
|
||||
"filenamify": "^4.3.0",
|
||||
"html-to-text": "^8.2.1",
|
||||
"html-to-text": "^9.0.3",
|
||||
"md5": "^2.3.0",
|
||||
"mpris-service": "^2.1.2",
|
||||
"node-fetch": "^2.6.8",
|
||||
@ -123,20 +123,20 @@
|
||||
"ytpl": "^2.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@playwright/test": "^1.25.1",
|
||||
"@playwright/test": "^1.29.2",
|
||||
"auto-changelog": "^2.4.0",
|
||||
"del-cli": "^5.0.0",
|
||||
"electron": "^20.1.1",
|
||||
"electron-builder": "^23.0.3",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"electron": "^22.0.2",
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-devtools-installer": "^3.2.0",
|
||||
"electron-icon-maker": "0.0.5",
|
||||
"playwright": "^1.25.1",
|
||||
"xo": "^0.45.0"
|
||||
"playwright": "^1.29.2",
|
||||
"xo": "^0.53.1"
|
||||
},
|
||||
"resolutions": {
|
||||
"glob-parent": "5.1.2",
|
||||
"minimist": "1.2.6",
|
||||
"yargs-parser": "18.1.3"
|
||||
"minimist": "1.2.7",
|
||||
"yargs-parser": "21.1.1"
|
||||
},
|
||||
"auto-changelog": {
|
||||
"hideCredit": true,
|
||||
|
||||
@ -1,15 +1,21 @@
|
||||
const { ipcMain, dialog } = require("electron");
|
||||
const { ipcMain } = require("electron");
|
||||
|
||||
module.exports = () => {
|
||||
ipcMain.handle('captionsSelector', async (_, captionLabels, currentIndex) => {
|
||||
return await dialog.showMessageBox({
|
||||
type: "question",
|
||||
buttons: captionLabels,
|
||||
defaultId: currentIndex,
|
||||
title: "Choose Caption",
|
||||
message: "Choose Caption:",
|
||||
detail: `Current Caption: ${captionLabels[currentIndex]}`,
|
||||
cancelId: -1
|
||||
})
|
||||
})
|
||||
const prompt = require("custom-electron-prompt");
|
||||
const promptOptions = require("../../providers/prompt-options");
|
||||
|
||||
module.exports = (win) => {
|
||||
ipcMain.handle("captionsSelector", async (_, captionLabels, currentIndex) => {
|
||||
return await prompt(
|
||||
{
|
||||
title: "Choose Caption",
|
||||
label: `Current Caption: ${captionLabels[currentIndex] || "None"}`,
|
||||
type: "select",
|
||||
value: currentIndex,
|
||||
selectOptions: captionLabels,
|
||||
resizable: true,
|
||||
...promptOptions(),
|
||||
},
|
||||
win
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
@ -4,7 +4,7 @@ const { ipcRenderer } = require("electron");
|
||||
function $(selector) { return document.querySelector(selector); }
|
||||
|
||||
const captionsSettingsButton = ElementFromFile(
|
||||
templatePath(__dirname, "captionsSettingsTemplate.html")
|
||||
templatePath(__dirname, "captions-settings-template.html")
|
||||
);
|
||||
|
||||
module.exports = (options) => {
|
||||
@ -28,33 +28,33 @@ function setup(event, options) {
|
||||
|
||||
$(".right-controls-buttons").append(captionsSettingsButton);
|
||||
|
||||
captionsSettingsButton.onclick = function chooseQuality() {
|
||||
captionsSettingsButton.onclick = async () => {
|
||||
api.loadModule("captions");
|
||||
|
||||
const captionTrackList = api.getOption("captions", "tracklist");
|
||||
|
||||
if (captionTrackList?.length) {
|
||||
const currentCaptionTrack = api.getOption("captions", "track");
|
||||
const currentIndex = captionTrackList.indexOf(captionTrackList.find(track => track.languageCode === currentCaptionTrack.languageCode));
|
||||
let currentIndex = !currentCaptionTrack ?
|
||||
null :
|
||||
captionTrackList.indexOf(captionTrackList.find(track => track.languageCode === currentCaptionTrack.languageCode));
|
||||
|
||||
const captionLabels = [
|
||||
...captionTrackList.map(track => track.displayName),
|
||||
'None'
|
||||
];
|
||||
|
||||
ipcRenderer.invoke('captionsSelector', captionLabels, currentIndex).then(promise => {
|
||||
if (promise.response === -1) return;
|
||||
currentIndex = await ipcRenderer.invoke('captionsSelector', captionLabels, currentIndex)
|
||||
if (currentIndex === null) return;
|
||||
|
||||
const newCaptions = captionTrackList[promise.response];
|
||||
if (newCaptions) {
|
||||
api.loadModule("captions");
|
||||
api.setOption("captions", "track", { languageCode: newCaptions.languageCode });
|
||||
} else {
|
||||
api.unloadModule("captions");
|
||||
}
|
||||
const newCaptions = captionTrackList[currentIndex];
|
||||
if (newCaptions) {
|
||||
api.setOption("captions", "track", { languageCode: newCaptions.languageCode });
|
||||
} else {
|
||||
api.setOption("captions", "track", {});
|
||||
}
|
||||
|
||||
setTimeout(() => api.playVideo());
|
||||
});
|
||||
setTimeout(() => api.playVideo());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,7 @@ const registerCallback = require("../../providers/song-info");
|
||||
|
||||
const secToMilisec = t => Math.round(Number(t) * 1e3);
|
||||
const data = {
|
||||
cover: '',
|
||||
cover_url: '',
|
||||
title: '',
|
||||
artists: [],
|
||||
@ -43,6 +44,7 @@ module.exports = async (win) => {
|
||||
|
||||
data.duration = secToMilisec(songInfo.songDuration)
|
||||
data.progress = secToMilisec(songInfo.elapsedSeconds)
|
||||
data.cover = songInfo.imageSrc;
|
||||
data.cover_url = songInfo.imageSrc;
|
||||
data.album_url = songInfo.imageSrc;
|
||||
data.title = songInfo.title;
|
||||
|
||||
@ -64,6 +64,8 @@ winget install th-ch.YouTubeMusic
|
||||
|
||||
- **Bypass age restrictions**: bypass YouTube's age verification
|
||||
|
||||
- **Captions selector**: Enable captions
|
||||
|
||||
- **Disable Autoplay**: Makes every song start in "paused" mode
|
||||
|
||||
- [**Discord**](https://discord.com/): Show your friends what you listen to with [Rich Presence](https://user-images.githubusercontent.com/28219076/104362104-a7a0b980-5513-11eb-9744-bb89eabe0016.png)
|
||||
|
||||
@ -9,18 +9,27 @@ const appPath = path.resolve(__dirname, "..");
|
||||
|
||||
test("YouTube Music App - With default settings, app is launched and visible", async () => {
|
||||
const app = await electron.launch({
|
||||
cwd: appPath,
|
||||
args: [
|
||||
appPath,
|
||||
"--no-sandbox",
|
||||
"--disable-gpu",
|
||||
"--whitelisted-ips=",
|
||||
"--disable-dev-shm-usage",
|
||||
appPath,
|
||||
],
|
||||
});
|
||||
|
||||
const window = await app.firstWindow();
|
||||
|
||||
const consentForm = await window.$(
|
||||
"form[action='https://consent.youtube.com/save']"
|
||||
);
|
||||
if (consentForm) {
|
||||
await consentForm.click("button");
|
||||
}
|
||||
|
||||
const title = await window.title();
|
||||
expect(title).toEqual("YouTube Music");
|
||||
expect(title.replace(/\s/g, " ")).toEqual("YouTube Music");
|
||||
|
||||
const url = window.url();
|
||||
expect(url.startsWith("https://music.youtube.com")).toBe(true);
|
||||
|
||||
Reference in New Issue
Block a user