feat: 支持GitHub Actions和一堆其他更新

This commit is contained in:
qier222 2022-04-02 19:29:43 +08:00
parent f5ab5ea754
commit e748155032
No known key found for this signature in database
GPG key ID: 9C85007ED905F14D
28 changed files with 185 additions and 36 deletions

View file

@ -6,14 +6,23 @@ module.exports = {
appId: 'com.qier222.yesplaymusic', appId: 'com.qier222.yesplaymusic',
productName: 'YesPlayMusic', productName: 'YesPlayMusic',
copyright: 'Copyright © 2022 ${author}', copyright: 'Copyright © 2022 ${author}',
asar: false, asar: true,
directories: { directories: {
output: 'release/${version}', output: 'release',
buildResources: 'build', buildResources: 'build',
}, },
npmRebuild: false, npmRebuild: false,
buildDependenciesFromSource: true, buildDependenciesFromSource: true,
files: ['dist'], files: ['./dist'],
publish: [
{
provider: 'github',
owner: 'qier222',
repo: 'YesPlayMusic',
vPrefixedTagName: true,
releaseType: 'draft',
},
],
win: { win: {
target: [ target: [
{ {
@ -28,8 +37,14 @@ module.exports = {
target: 'nsis', target: 'nsis',
arch: ['ia32'], arch: ['ia32'],
}, },
{
target: 'portable',
arch: ['x64'],
},
], ],
artifactName: '${productName}-${version}-Setup.${ext}', artifactName: '${productName}-${os}-${version}-${arch}-Setup.${ext}',
publisherName: 'qier222',
icon: 'build/icons/icon.ico',
}, },
nsis: { nsis: {
oneClick: false, oneClick: false,
@ -38,12 +53,49 @@ module.exports = {
deleteAppDataOnUninstall: true, deleteAppDataOnUninstall: true,
}, },
mac: { mac: {
target: ['dmg'], target: [
artifactName: '${productName}-${version}-Installer.${ext}', {
target: 'dmg',
arch: ['x64', 'arm64', 'universal'],
},
],
artifactName: '${productName}-${os}-${version}-${arch}.${ext}',
darkModeSupport: true,
category: 'public.app-category.music',
},
dmg: {
icon: 'build/icons/icon.icns',
}, },
linux: { linux: {
target: ['AppImage'], target: [
artifactName: '${productName}-${version}-Installer.${ext}', {
target: 'deb',
arch: ['x64', 'arm64', 'armv7l'],
},
{
target: 'AppImage',
arch: ['x64'],
},
{
target: 'snap',
arch: ['x64'],
},
{
target: 'pacman',
arch: ['x64'],
},
{
target: 'rpm',
arch: ['x64'],
},
{
target: 'tar.gz',
arch: ['x64'],
},
],
artifactName: '${productName}-${os}-${version}.${ext}',
category: 'Music',
icon: './build/icon.icns',
}, },
files: [ files: [
'dist/main/**/*', 'dist/main/**/*',

90
.github/workflows/build.yaml vendored Normal file
View file

@ -0,0 +1,90 @@
name: Build/Release
on:
push:
branches:
- react
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, windows-latest, ubuntu-18.04]
steps:
- name: Check out Git repository
uses: actions/checkout@v3
with:
submodules: 'recursive'
- uses: pnpm/action-setup@v2.0.1
with:
version: 6.29.0
- name: Install Node.js 16
uses: actions/setup-node@v2
with:
node-version: 16
cache: 'pnpm'
- name: Install dependencies
run: pnpm install --frozen-lockfile false
- name: Electron rebuild
run: pnpm electron-rebuild
- name: Install RPM & Pacman (on Ubuntu)
if: runner.os == 'Linux'
run: |
sudo apt-get update &&
sudo apt-get install --no-install-recommends -y rpm &&
sudo apt-get install --no-install-recommends -y bsdtar &&
sudo apt-get install --no-install-recommends -y libopenjp2-tools
- 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 }}
- name: Build/Release Electron app
uses: njzydark/action-electron-builder-pnpm@v1.1.0-pnpm
env:
ELECTRON_WEB_SERVER_PORT: 42710
VITE_APP_NETEASE_API_URL: /netease
VITE_APP_LASTFM_API_KEY: 09c55292403d961aa517ff7f5e8a3d9c
VITE_APP_LASTFM_API_SHARED_SECRET: 307c9fda32b3904e53654baff215cb67
with:
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
github_token: ${{ secrets.github_token }}
# If the commit is tagged with a version (e.g. "v1.0.0"),
# release the app after building
release: ${{ startsWith(github.ref, 'refs/tags/v') }}
args: --config .electron-builder.config.js
skip_package_manager_install: true
package_manager: pnpm
- name: Upload Artifact (macOS)
uses: actions/upload-artifact@v3
with:
name: YesPlayMusic-mac
path: release/*-universal.dmg
if-no-files-found: ignore
- name: Upload Artifact (Windows)
uses: actions/upload-artifact@v3
with:
name: YesPlayMusic-win
path: release/*-Setup.exe
if-no-files-found: ignore
- name: Upload Artifact (Linux)
uses: actions/upload-artifact@v3
with:
name: YesPlayMusic-linux
path: release/*.AppImage
if-no-files-found: ignore

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

BIN
build/icons/1024x1024.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 523 KiB

BIN
build/icons/128x128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
build/icons/16x16.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 474 B

BIN
build/icons/24x24.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 750 B

BIN
build/icons/256x256.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

BIN
build/icons/32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 965 B

BIN
build/icons/48x48.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
build/icons/512x512.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 105 KiB

BIN
build/icons/64x64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
build/icons/icon.icns Normal file

Binary file not shown.

BIN
build/icons/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 KiB

BIN
build/icons/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

BIN
build/icons/menu@88.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View file

@ -14,13 +14,13 @@
"dev:renderer": "vite dev", "dev:renderer": "vite dev",
"build:main": "node scripts/build.main.mjs", "build:main": "node scripts/build.main.mjs",
"build:renderer": "vite build", "build:renderer": "vite build",
"build": "npm run typecheck && cross-env-shell IS_ELECTRON=true npm run build:renderer && npm run build:main && electron-builder --config .electron-builder.config.js", "build": "npm run typecheck && cross-env-shell IS_ELECTRON=true npm run build:renderer && npm run build:main",
"build-dir": "npm run typecheck && cross-env-shell IS_ELECTRON=true npm run build:renderer && npm run build:main && electron-builder --config .electron-builder.config.js --dir", "build:app": "npm run build && electron-builder --config .electron-builder.config.js",
"build:app-dir": "npm run build && electron-builder --config .electron-builder.config.js --dir",
"typecheck": "tsc --noEmit --project src/renderer/tsconfig.json", "typecheck": "tsc --noEmit --project src/renderer/tsconfig.json",
"debug": "cross-env-shell NODE_ENV=debug \"npm run typecheck && node scripts/build.mjs && vite ./src/renderer\"", "debug": "cross-env-shell NODE_ENV=debug \"npm run typecheck && node scripts/build.mjs && vite ./src/renderer\"",
"eslint": "eslint --ext .ts,.js ./", "eslint": "eslint --ext .ts,.js ./",
"prettier": "prettier --write './**/*.{ts,js,tsx,jsx}'", "prettier": "prettier --write './**/*.{ts,js,tsx,jsx}'"
"postinstall": "electron-rebuild"
}, },
"engines": { "engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0" "node": "^12.20.0 || ^14.13.1 || >=16.0.0"

View file

@ -92,6 +92,10 @@ if (argv.watch) {
spinner.start() spinner.start()
build({ build({
...options, ...options,
define: {
...options.define,
'process.env.NODE_ENV': '"production"',
},
minify: true, minify: true,
}) })
.then(() => { .then(() => {

View file

@ -14,6 +14,7 @@ import path from 'path'
logger.info('[server] starting http server') logger.info('[server] starting http server')
const isDev = process.env.NODE_ENV === 'development' const isDev = process.env.NODE_ENV === 'development'
const isProd = process.env.NODE_ENV === 'production'
// eslint-disable-next-line @typescript-eslint/no-var-requires // eslint-disable-next-line @typescript-eslint/no-var-requires
const neteaseApi = require('NeteaseCloudMusicApi') as (params: any) => any[] const neteaseApi = require('NeteaseCloudMusicApi') as (params: any) => any[]
@ -87,14 +88,14 @@ app.post('/yesplaymusic/audio/:id', async (req: Request, res: Response) => {
} }
}) })
if (!isDev) { if (isProd) {
app.use(express.static(path.join(__dirname, '../renderer'))) app.use('/', express.static(path.join(__dirname, '../renderer/')))
} }
const port = Number( const port = Number(
isDev isProd
? process.env.ELECTRON_DEV_NETEASE_API_PORT ?? 3000 ? process.env.ELECTRON_WEB_SERVER_PORT ?? 42710
: process.env.ELECTRON_WEB_SERVER_PORT ?? 42710 : process.env.ELECTRON_DEV_NETEASE_API_PORT ?? 3000
) )
app.listen(port, () => { app.listen(port, () => {
logger.info(`[server] API server listening on port ${port}`) logger.info(`[server] API server listening on port ${port}`)

View file

@ -69,8 +69,6 @@ const FMCard = () => {
if (coverUrl) { if (coverUrl) {
average(coverUrl, { amount: 1, format: 'hex', sample: 1 }).then(color => { average(coverUrl, { amount: 1, format: 'hex', sample: 1 }).then(color => {
let c = colord(color as string) let c = colord(color as string)
console.log({ dark: c.isDark(), light: c.isLight() })
if (c.isLight()) c = c.darken(0.15) if (c.isLight()) c = c.darken(0.15)
else if (c.isDark()) c = c.lighten(0.1) else if (c.isDark()) c = c.lighten(0.1)
const to = c.darken(0.15).rotate(-5).toHex() const to = c.darken(0.15).rotate(-5).toHex()

View file

@ -226,8 +226,7 @@ const TracksList = memo(
track={track} track={track}
isLiked={userLikedSongs?.ids?.includes(track.id) ?? false} isLiked={userLikedSongs?.ids?.includes(track.id) ?? false}
isSkeleton={false} isSkeleton={false}
isPlaying={track.id === playingTrack?.id} isHighlight={track.id === playingTrack?.id}
subtitle={track.tns?.at(0) ?? track.alia?.at(0)}
/> />
))} ))}
</div> </div>

View file

@ -1,5 +1,5 @@
import { StrictMode } from 'react' import { StrictMode } from 'react'
import { render } from 'react-dom' import * as ReactDOMClient from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom' import { BrowserRouter } from 'react-router-dom'
import * as Sentry from '@sentry/react' import * as Sentry from '@sentry/react'
import { BrowserTracing } from '@sentry/tracing' import { BrowserTracing } from '@sentry/tracing'
@ -20,11 +20,13 @@ Sentry.init({
tracesSampleRate: 1.0, tracesSampleRate: 1.0,
}) })
render( const container = document.getElementById('root') as HTMLElement
const root = ReactDOMClient.createRoot(container)
root.render(
<StrictMode> <StrictMode>
<BrowserRouter> <BrowserRouter>
<App /> <App />
</BrowserRouter> </BrowserRouter>
</StrictMode>, </StrictMode>
document.getElementById('root')
) )

View file

@ -1,4 +1,3 @@
import { RefObject } from 'react'
import { proxy, subscribe } from 'valtio' import { proxy, subscribe } from 'valtio'
import { devtools } from 'valtio/utils' import { devtools } from 'valtio/utils'
import { player as PlayerCore } from '@/utils/player' import { player as PlayerCore } from '@/utils/player'
@ -33,7 +32,7 @@ export const player = proxy(PlayerCore)
player.init() player.init()
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
window.player = player ;(window as any).player = player
} }
// Devtools // Devtools

View file

@ -154,7 +154,7 @@ export class Player {
*/ */
private async _fetchTrack(trackID: TrackID) { private async _fetchTrack(trackID: TrackID) {
const response = await fetchTracksWithReactQuery({ ids: [trackID] }) const response = await fetchTracksWithReactQuery({ ids: [trackID] })
return response?.songs?.length ? response.songs[0] : null return response?.songs.length ? response.songs[0] : null
} }
/** /**
@ -173,8 +173,10 @@ export class Player {
* Play a track based on this.trackID * Play a track based on this.trackID
*/ */
private async _playTrack() { private async _playTrack() {
const id = this.trackID
if (!id) return
this.state = State.LOADING this.state = State.LOADING
const track = await this._fetchTrack(this.trackID) const track = await this._fetchTrack(id)
if (!track) { if (!track) {
toast('加载歌曲信息失败') toast('加载歌曲信息失败')
return return
@ -208,7 +210,7 @@ export class Player {
this.play() this.play()
this.state = State.PLAYING this.state = State.PLAYING
_howler.once('load', () => { _howler.once('load', () => {
this._cacheAudio(_howler._src) this._cacheAudio((_howler as any)._src)
}) })
if (!this._progressInterval) { if (!this._progressInterval) {
@ -233,9 +235,6 @@ export class Player {
} }
private async _nextFMTrack() { private async _nextFMTrack() {
this.fmTrackList.shift()
this._playTrack()
const loadMoreTracks = async () => { const loadMoreTracks = async () => {
if (this.fmTrackList.length <= 5) { if (this.fmTrackList.length <= 5) {
const response = await fetchPersonalFMWithReactQuery() const response = await fetchPersonalFMWithReactQuery()
@ -248,7 +247,11 @@ export class Player {
if (track?.al.picUrl) axios.get(resizeImage(track.al.picUrl, 'md')) if (track?.al.picUrl) axios.get(resizeImage(track.al.picUrl, 'md'))
} }
loadMoreTracks() if (this.fmTrackList.length === 0) await loadMoreTracks()
this.fmTrackList.shift()
this._playTrack()
this.fmTrackList.length === 0 ? await loadMoreTracks() : loadMoreTracks()
prefetchNextTrack() prefetchNextTrack()
} }
@ -405,6 +408,7 @@ export class Player {
* Trash current PersonalFMTrack * Trash current PersonalFMTrack
*/ */
async fmTrash() { async fmTrash() {
this.mode = Mode.FM
const trashTrackID = this.fmTrackList[0] const trashTrackID = this.fmTrackList[0]
fmTrash(trashTrackID) fmTrash(trashTrackID)
this._nextFMTrack() this._nextFMTrack()
@ -424,5 +428,5 @@ export class Player {
export const player = new Player() export const player = new Player()
if (import.meta.env.DEV) { if (import.meta.env.DEV) {
window.howler = _howler ;(window as any).howler = _howler
} }

View file

@ -40,7 +40,7 @@ export default defineConfig({
], ],
}), }),
], ],
base: './', base: '/',
build: { build: {
target: process.env.IS_ELECTRON ? 'esnext' : 'modules', target: process.env.IS_ELECTRON ? 'esnext' : 'modules',
sourcemap: process.env.NODE_ENV === 'debug', sourcemap: process.env.NODE_ENV === 'debug',