diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index e28aa0d..342b02b 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -1,5 +1,8 @@ name: Release +env: + YARN_INSTALL_NOPT: yarn add --ignore-platform --ignore-optional + on: push: branches: @@ -39,9 +42,41 @@ jobs: - name: Install Snapcraft (on Ubuntu) uses: samuelmeuli/action-snapcraft@v1 if: startsWith(matrix.os, 'ubuntu') - # with: - # Disable since the Snapcraft token is currently not working - # snapcraft_token: ${{ secrets.snapcraft_token }} + with: + snapcraft_token: ${{ secrets.snapcraft_token }} + + - 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/action-electron-builder@v1.6.0 diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..da2d398 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +14 \ No newline at end of file diff --git a/jsconfig.json b/jsconfig.json index 0d612a8..7787662 100644 --- a/jsconfig.json +++ b/jsconfig.json @@ -7,7 +7,8 @@ }, "target": "ES6", "module": "commonjs", - "allowSyntheticDefaultImports": true + "allowSyntheticDefaultImports": true, + "jsx": "preserve" }, "include": ["src/**/*"], "exclude": ["node_modules"] diff --git a/package.json b/package.json index 224010f..37ce354 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yesplaymusic", - "version": "0.4.4", + "version": "0.4.5", "private": true, "description": "A third party music player for Netease Music", "author": "qier222", @@ -23,12 +23,12 @@ }, "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", @@ -36,14 +36,14 @@ "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", @@ -62,12 +62,12 @@ "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", - "vue-analytics": "^5.22.1", "vue-clipboard2": "^0.3.1", + "vue-gtag": "1", "vue-i18n": "^8.22.0", "vue-router": "^3.4.3", "vue-slider-component": "^3.2.5", diff --git a/restyled.yml b/restyled.yml new file mode 100644 index 0000000..c31d3e8 --- /dev/null +++ b/restyled.yml @@ -0,0 +1,7 @@ +commit_template: 'style: with ${restyler.name}' +restylers: + - prettier + - prettier-json + - prettier-markdown + - prettier-yaml + - whitespace diff --git a/src/api/track.js b/src/api/track.js index 472dc6a..490c91c 100644 --- a/src/api/track.js +++ b/src/api/track.js @@ -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(), }, }); } diff --git a/src/background.js b/src/background.js index 276d790..1d4fdba 100644 --- a/src/background.js +++ b/src/background.js @@ -7,6 +7,7 @@ import { dialog, globalShortcut, nativeTheme, + screen, } from 'electron'; import { isWindows, @@ -201,8 +202,42 @@ class Background { }; if (this.store.get('window.x') && this.store.get('window.y')) { - options.x = this.store.get('window.x'); - options.y = this.store.get('window.y'); + let x = this.store.get('window.x'); + let y = this.store.get('window.y'); + + let displays = screen.getAllDisplays(); + let isResetWindiw = false; + if (displays.length === 1) { + let { bounds } = displays[0]; + if ( + x < bounds.x || + x > bounds.x + bounds.width - 50 || + y < bounds.y || + y > bounds.y + bounds.height - 50 + ) { + isResetWindiw = true; + } + } else { + isResetWindiw = true; + for (let i = 0; i < displays.length; i++) { + let { bounds } = displays[i]; + if ( + x > bounds.x && + x < bounds.x + bounds.width && + y > bounds.y && + y < bounds.y - bounds.height + ) { + // 检测到APP窗口当前处于一个可用的屏幕里,break + isResetWindiw = false; + break; + } + } + } + + if (!isResetWindiw) { + options.x = x; + options.y = y; + } } this.window = new BrowserWindow(options); @@ -261,6 +296,7 @@ class Background { this.window.once('ready-to-show', () => { log('window ready-to-show event'); this.window.show(); + this.store.set('window', this.window.getBounds()); }); this.window.on('close', e => { @@ -296,6 +332,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'); diff --git a/src/components/ArtistsInLine.vue b/src/components/ArtistsInLine.vue index cc13384..e2c619d 100644 --- a/src/components/ArtistsInLine.vue +++ b/src/components/ArtistsInLine.vue @@ -2,11 +2,13 @@ {{ computedPrefix }} - - {{ ar.name }} - + {{ + ar.name + }} {{ ar.name }} - , + , @@ -40,4 +42,12 @@ export default { }; - + diff --git a/src/components/ContextMenu.vue b/src/components/ContextMenu.vue index a290a47..186448f 100644 --- a/src/components/ContextMenu.vue +++ b/src/components/ContextMenu.vue @@ -80,11 +80,13 @@ export default { box-shadow: 0 6px 12px -4px rgba(0, 0, 0, 0.08); border: 1px solid rgba(0, 0, 0, 0.06); backdrop-filter: blur(12px); - border-radius: 8px; + border-radius: 12px; box-sizing: border-box; padding: 6px; z-index: 1000; -webkit-app-region: no-drag; + transition: background 125ms ease-out, opacity 125ms ease-out, + transform 125ms ease-out; &:focus { outline: none; @@ -94,8 +96,9 @@ export default { [data-theme='dark'] { .menu { background: rgba(36, 36, 36, 0.78); - backdrop-filter: blur(16px) contrast(120%); + backdrop-filter: blur(16px) contrast(120%) brightness(60%); border: 1px solid rgba(255, 255, 255, 0.08); + box-shadow: 0 0 6px rgba(255, 255, 255, 0.08); } .menu .item:hover { color: var(--color-text); @@ -112,7 +115,7 @@ export default { font-weight: 600; font-size: 14px; padding: 10px 14px; - border-radius: 7px; + border-radius: 8px; cursor: default; color: var(--color-text); display: flex; @@ -120,6 +123,11 @@ export default { &:hover { color: var(--color-primary); background: var(--color-primary-bg-for-transparent); + transition: opacity 125ms ease-out, transform 125ms ease-out; + } + &:active { + opacity: 0.75; + transform: scale(0.95); } .svg-icon { @@ -149,7 +157,7 @@ hr { border-radius: 4px; } .info { - margin-left: 8px; + margin-left: 10px; } .title { font-size: 16px; diff --git a/src/components/Cover.vue b/src/components/Cover.vue index 654d217..163022a 100644 --- a/src/components/Cover.vue +++ b/src/components/Cover.vue @@ -16,7 +16,7 @@ > - +
- +
diff --git a/src/components/ExplicitSymbol.vue b/src/components/ExplicitSymbol.vue index 99b2cd4..f8ed871 100644 --- a/src/components/ExplicitSymbol.vue +++ b/src/components/ExplicitSymbol.vue @@ -25,6 +25,8 @@ export default { this.svgStyle = { height: this.size + 'px', width: this.size + 'px', + position: 'relative', + left: '-1px', }; }, }; diff --git a/src/components/FMCard.vue b/src/components/FMCard.vue index a485002..c78b597 100644 --- a/src/components/FMCard.vue +++ b/src/components/FMCard.vue @@ -1,9 +1,10 @@