Skip to content

Commit

Permalink
Merge branch 'qier222-master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Shi committed May 2, 2022
2 parents c91a7c5 + 080322c commit 10745db
Show file tree
Hide file tree
Showing 20 changed files with 1,398 additions and 975 deletions.
36 changes: 36 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
name: Release

env:
YARN_INSTALL_NOPT: yarn add --ignore-platform --ignore-optional

on:
push:
branches:
Expand Down Expand Up @@ -36,6 +39,39 @@ jobs:
sudo apt-get install --no-install-recommends -y libarchive-tools &&
sudo apt-get install --no-install-recommends -y libopenjp2-tools
- id: get_unm_version
name: Get the installed UNM version
run: |
yarn --ignore-optional
unm_version=$(node -e "console.log(require('./node_modules/@unblockneteasemusic/rust-napi/package.json').version)")
echo "::set-output name=unmver::${unm_version}"
shell: bash

- name: Install UNM dependencies for Windows
if: runner.os == 'Windows'
run: |
${{ env.YARN_INSTALL_NOPT }} \
@unblockneteasemusic/rust-napi-win32-x64-msvc@${{steps.get_unm_version.outputs.unmver}}
shell: bash

- name: Install UNM dependencies for macOS
if: runner.os == 'macOS'
run: |
${{ env.YARN_INSTALL_NOPT }} \
@unblockneteasemusic/rust-napi-darwin-x64@${{steps.get_unm_version.outputs.unmver}} \
@unblockneteasemusic/rust-napi-darwin-arm64@${{steps.get_unm_version.outputs.unmver}} \
dmg-license
shell: bash

- name: Install UNM dependencies for Linux
if: runner.os == 'Linux'
run: |
${{ env.YARN_INSTALL_NOPT }} \
@unblockneteasemusic/rust-napi-linux-x64-gnu@${{steps.get_unm_version.outputs.unmver}} \
@unblockneteasemusic/rust-napi-linux-arm64-gnu@${{steps.get_unm_version.outputs.unmver}} \
@unblockneteasemusic/rust-napi-linux-arm-gnueabihf@${{steps.get_unm_version.outputs.unmver}}
shell: bash

- name: Build/release Electron app
uses: samuelmeuli/[email protected]
env:
Expand Down
3 changes: 2 additions & 1 deletion jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
},
"target": "ES6",
"module": "commonjs",
"allowSyntheticDefaultImports": true
"allowSyntheticDefaultImports": true,
"jsx": "preserve"
},
"include": ["src/**/*"],
"exclude": ["node_modules"]
Expand Down
20 changes: 10 additions & 10 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "yesplaymusic",
"version": "0.4.4-1",
"version": "0.4.5",
"private": true,
"description": "A third party music player for Netease Music",
"author": "qier222<[email protected]>",
Expand All @@ -23,27 +23,27 @@
},
"main": "background.js",
"dependencies": {
"@unblockneteasemusic/server": "v0.27.0-rc.6",
"@unblockneteasemusic/rust-napi": "^0.3.0-pre.1",
"NeteaseCloudMusicApi": "^4.5.2",
"axios": "^0.21.0",
"axios": "^0.26.1",
"change-case": "^4.1.2",
"cli-color": "^2.0.0",
"color": "^3.1.3",
"color": "^4.2.3",
"core-js": "^3.6.5",
"crypto-js": "^4.0.0",
"dayjs": "^1.8.36",
"dexie": "^3.0.3",
"discord-rich-presence": "^0.0.8",
"electron": "^13.6.7",
"electron-builder": "^23.0.0",
"electron-context-menu": "^2.3.0",
"electron-context-menu": "^3.1.2",
"electron-debug": "^3.1.0",
"electron-devtools-installer": "^3.2",
"electron-icon-builder": "^1.0.2",
"electron-is-dev": "^1.2.0",
"electron-icon-builder": "^2.0.1",
"electron-is-dev": "^2.0.0",
"electron-log": "^4.3.0",
"electron-store": "^6.0.1",
"electron-updater": "^4.3.5",
"electron-store": "^8.0.1",
"electron-updater": "^5.0.1",
"express": "^4.17.1",
"express-fileupload": "^1.2.0",
"express-http-proxy": "^1.6.2",
Expand All @@ -62,7 +62,7 @@
"prettier": "2.5.1",
"qrcode": "^1.4.4",
"register-service-worker": "^1.7.1",
"svg-sprite-loader": "^5.0.0",
"svg-sprite-loader": "^6.0.11",
"tunnel": "^0.0.6",
"vscode-codicons": "^0.0.17",
"vue": "^2.6.11",
Expand Down
12 changes: 7 additions & 5 deletions src/api/track.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,18 @@ import {
* @param {string} id - 音乐的 id,例如 id=405998841,33894312
*/
export function getMP3(id) {
let br =
store.state.settings?.musicQuality !== undefined
? store.state.settings.musicQuality
: 320000;
const getBr = () => {
// 当返回的 quality >= 400000时,就会优先返回 hi-res
const quality = store.state.settings?.musicQuality ?? '320000';
return quality === 'flac' ? '350000' : quality;
};

return request({
url: '/song/url',
method: 'get',
params: {
id,
br,
br: getBr(),
},
});
}
Expand Down
8 changes: 8 additions & 0 deletions src/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,14 @@ class Background {
this.store.set('window', this.window.getBounds());
});

this.window.on('maximize', () => {
this.window.webContents.send('isMaximized', true);
});

this.window.on('unmaximize', () => {
this.window.webContents.send('isMaximized', false);
});

this.window.webContents.on('new-window', function (e, url) {
e.preventDefault();
log('open url');
Expand Down
10 changes: 4 additions & 6 deletions src/components/LinuxTitlebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
<div
class="button max-restore codicon"
:class="{
'codicon-chrome-restore': !isShowMaximized,
'codicon-chrome-maximize': isShowMaximized,
'codicon-chrome-restore': isMaximized,
'codicon-chrome-maximize': !isMaximized,
}"
@click="windowMaxRestore"
></div>
Expand All @@ -40,7 +40,7 @@ export default {
name: 'LinuxTitlebar',
data() {
return {
isShowMaximized: true,
isMaximized: false,
};
},
computed: {
Expand All @@ -49,9 +49,7 @@ export default {
created() {
if (process.env.IS_ELECTRON === true) {
ipcRenderer.on('isMaximized', (_, value) => {
// 当窗口最大化时,value为false
// 当窗口还原时,value为true
this.isShowMaximized = value;
this.isMaximized = value;
});
}
},
Expand Down
3 changes: 1 addition & 2 deletions src/components/TrackList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ import { mapActions, mapMutations, mapState } from 'vuex';
import { addOrRemoveTrackFromPlaylist } from '@/api/playlist';
import { cloudDiskTrackDelete } from '@/api/user';
import { isAccountLoggedIn } from '@/utils/auth';
const { clipboard } = require('electron');
import TrackListItem from '@/components/TrackListItem.vue';
import ContextMenu from '@/components/ContextMenu.vue';
Expand Down Expand Up @@ -270,7 +269,7 @@ export default {
}
},
copyLink() {
clipboard.writeText(
navigator.clipboard.writeText(
`https://music.163.com/song?id=${this.rightClickedTrack.id}`
);
this.showToast(locale.t('toast.copied'));
Expand Down
10 changes: 4 additions & 6 deletions src/components/Win32Titlebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
<div
class="button max-restore codicon"
:class="{
'codicon-chrome-restore': !isShowMaximized,
'codicon-chrome-maximize': isShowMaximized,
'codicon-chrome-restore': isMaximized,
'codicon-chrome-maximize': !isMaximized,
}"
@click="windowMaxRestore"
></div>
Expand All @@ -37,7 +37,7 @@ export default {
name: 'Win32Titlebar',
data() {
return {
isShowMaximized: true,
isMaximized: false,
};
},
computed: {
Expand All @@ -46,9 +46,7 @@ export default {
created() {
if (process.env.IS_ELECTRON === true) {
ipcRenderer.on('isMaximized', (_, value) => {
// 当窗口最大化时,value为false
// 当窗口还原时,value为true
this.isShowMaximized = value;
this.isMaximized = value;
});
}
},
Expand Down
128 changes: 81 additions & 47 deletions src/electron/ipcMain.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { app, dialog, globalShortcut, ipcMain } from 'electron';
import match from '@unblockneteasemusic/server';
import UNM from '@unblockneteasemusic/rust-napi';
import { registerGlobalShortcut } from '@/electron/globalShortcut';
import cloneDeep from 'lodash/cloneDeep';
import shortcuts from '@/utils/shortcuts';
Expand Down Expand Up @@ -88,10 +88,10 @@ function toBuffer(data) {
}

/**
* Get the file URI from bilivideo.
* Get the file base64 data from bilivideo.
*
* @param {string} url The URL to fetch.
* @returns {Promise<string>} The file URI.
* @returns {Promise<string>} The file base64 data.
*/
async function getBiliVideoFile(url) {
const axios = await import('axios').then(m => m.default);
Expand All @@ -106,61 +106,97 @@ async function getBiliVideoFile(url) {
const buffer = toBuffer(response.data);
const encodedData = buffer.toString('base64');

return `data:application/octet-stream;base64,${encodedData}`;
return encodedData;
}

/**
* Parse the source string (`a, b`) to source list `['a', 'b']`.
*
* @param {import("@unblockneteasemusic/rust-napi").Executor} executor
* @param {string} sourceString The source string.
* @returns {string[]} The source list.
*/
function parseSourceStringToList(sourceString) {
return sourceString.split(',').map(s => s.trim());
}

export function initIpcMain(win, store, trayEventEmitter, lrc) {
ipcMain.handle('unblock-music', async (_, track, source) => {
// 兼容 unblockneteasemusic 所使用的 api 字段
track.alias = track.alia || [];
track.duration = track.dt || 0;
track.album = track.al || [];
track.artists = track.ar || [];

const timeoutPromise = new Promise((_, reject) => {
setTimeout(() => {
reject('timeout');
}, 5000);
});
function parseSourceStringToList(executor, sourceString) {
const availableSource = executor.list();

const sourceList =
typeof source === 'string' ? parseSourceStringToList(source) : null;
log(`[UNM] using source: ${sourceList || '<default>'}`);
return sourceString
.split(',')
.map(s => s.trim().toLowerCase())
.filter(s => {
const isAvailable = availableSource.includes(s);

try {
const matchedAudio = await Promise.race([
// TODO: tell users to install yt-dlp.
// we passed "null" to source, to let UNM choose the default source.
match(track.id, sourceList, track),
timeoutPromise,
]);

if (!matchedAudio || !matchedAudio.url) {
throw new Error('no such a song found');
if (!isAvailable) {
log(`This source is not one of the supported source: ${s}`);
}

// bilibili's audio file needs some special treatment
if (matchedAudio.url.includes('bilivideo.com')) {
matchedAudio.url = await getBiliVideoFile(matchedAudio.url);
}
return isAvailable;
});
}

return matchedAudio;
} catch (err) {
const errorMessage = err instanceof Error ? `${err.message}` : `${err}`;
log(`UnblockNeteaseMusic failed: ${errorMessage}`);
return null;
export function initIpcMain(win, store, trayEventEmitter, lrc) {
// WIP: Do not enable logging as it has some issues in non-blocking I/O environment.
// UNM.enableLogging(UNM.LoggingType.ConsoleEnv);
const unmExecutor = new UNM.Executor();

ipcMain.handle(
'unblock-music',
/**
*
* @param {*} _
* @param {string | null} sourceListString
* @param {Record<string, any>} ncmTrack
* @param {UNM.Context} context
*/
async (_, sourceListString, ncmTrack, context) => {
// Formt the track input
// FIXME: Figure out the structure of Track
const song = {
id: ncmTrack.id && ncmTrack.id.toString(),
name: ncmTrack.name,
duration: ncmTrack.dt,
album: ncmTrack.al && {
id: ncmTrack.al.id && ncmTrack.al.id.toString(),
name: ncmTrack.al.name,
},
artists: ncmTrack.ar
? ncmTrack.ar.map(({ id, name }) => ({
id: id && id.toString(),
name,
}))
: [],
};

const sourceList =
typeof sourceListString === 'string'
? parseSourceStringToList(unmExecutor, sourceListString)
: ['migu', 'ytdl', 'bilibili', 'pyncm', 'kugou'];
log(`[UNM] using source: ${sourceList.join(', ')}`);
log(`[UNM] using configuration: ${JSON.stringify(context)}`);

try {
// TODO: tell users to install yt-dlp.
const matchedAudio = await unmExecutor.search(
sourceList,
song,
context
);
const retrievedSong = await unmExecutor.retrieve(matchedAudio, context);

// bilibili's audio file needs some special treatment
if (retrievedSong.url.includes('bilivideo.com')) {
retrievedSong.url = await getBiliVideoFile(retrievedSong.url);
}

log(`respond with retrieve song…`);
log(JSON.stringify(matchedAudio));
return retrievedSong;
} catch (err) {
const errorMessage = err instanceof Error ? `${err.message}` : `${err}`;
log(`UnblockNeteaseMusic failed: ${errorMessage}`);
return null;
}
}
});
);

ipcMain.on('close', e => {
if (isMac) {
Expand All @@ -186,9 +222,7 @@ export function initIpcMain(win, store, trayEventEmitter, lrc) {
});

ipcMain.on('maximizeOrUnmaximize', () => {
const isMaximized = win.isMaximized();
isMaximized ? win.unmaximize() : win.maximize();
win.webContents.send('isMaximized', isMaximized);
win.isMaximized() ? win.unmaximize() : win.maximize();
});

ipcMain.on('settings', (event, options) => {
Expand Down
Loading

0 comments on commit 10745db

Please sign in to comment.