diff --git a/package.json b/package.json index 6ecf5c0..4f6cc49 100644 --- a/package.json +++ b/package.json @@ -84,8 +84,8 @@ "prettier": "2.5.1", "prettier-plugin-tailwindcss": "^0.1.8", "qrcode": "^1.5.0", - "react": "^17.0.2", - "react-dom": "^17.0.2", + "react": "^18.0.0", + "react-dom": "^18.0.0", "react-hot-toast": "^2.2.0", "react-query": "^3.34.19", "react-router-dom": "^6.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index bc19942..fb405b2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -57,8 +57,8 @@ specifiers: prettier: 2.5.1 prettier-plugin-tailwindcss: ^0.1.8 qrcode: ^1.5.0 - react: ^17.0.2 - react-dom: ^17.0.2 + react: ^18.0.0 + react-dom: ^18.0.0 react-hot-toast: ^2.2.0 react-query: ^3.34.19 react-router-dom: ^6.3.0 @@ -89,7 +89,7 @@ dependencies: fast-folder-size: 1.6.1 devDependencies: - '@sentry/react': 6.19.3_react@17.0.2 + '@sentry/react': 6.19.3_react@18.0.0 '@types/better-sqlite3': 7.5.0 '@types/cookie-parser': 1.4.2 '@types/express': 4.17.13 @@ -135,19 +135,19 @@ devDependencies: prettier: 2.5.1 prettier-plugin-tailwindcss: 0.1.8_prettier@2.5.1 qrcode: 1.5.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-hot-toast: 2.2.0_383bc679f6b8b3c30a924b2c4a84e8d7 - react-query: 3.34.19_react-dom@17.0.2+react@17.0.2 - react-router-dom: 6.3.0_react-dom@17.0.2+react@17.0.2 - react-use: 17.3.2_react-dom@17.0.2+react@17.0.2 + react: 18.0.0 + react-dom: 18.0.0_react@18.0.0 + react-hot-toast: 2.2.0_aee3b59847029cfc9aee5217330a3daf + react-query: 3.34.19_react-dom@18.0.0+react@18.0.0 + react-router-dom: 6.3.0_react-dom@18.0.0+react@18.0.0 + react-use: 17.3.2_react-dom@18.0.0+react@18.0.0 rollup: 2.70.1 rollup-plugin-visualizer: 5.6.0_rollup@2.70.1 sass: 1.49.10 tailwindcss: 3.0.23_autoprefixer@10.4.4 typescript: 4.6.3 unplugin-auto-import: 0.6.9_e121d8abdbc15677ab11cd9085287858 - valtio: 1.5.0_react@17.0.2+vite@2.9.1 + valtio: 1.5.0_react@18.0.0+vite@2.9.1 valtio-persist: 1.0.2_valtio@1.5.0 vite: 2.9.1_sass@1.49.10 vite-plugin-resolve: 1.8.0 @@ -662,7 +662,7 @@ packages: - supports-color dev: false - /@sentry/react/6.19.3_react@17.0.2: + /@sentry/react/6.19.3_react@18.0.0: resolution: {integrity: sha512-Zza1RX0+1tFCM1Hfq3Yl50cbc/ml0V/katw4aVZIU6+vEgvk5EuSFKU2LtblmJkpID7x6UwWz+1qgXumZPze6Q==} engines: {node: '>=6'} peerDependencies: @@ -673,7 +673,7 @@ packages: '@sentry/types': 6.19.3 '@sentry/utils': 6.19.3 hoist-non-react-statics: 3.3.2 - react: 17.0.2 + react: 18.0.0 tslib: 1.14.1 dev: true @@ -5194,7 +5194,7 @@ packages: transitivePeerDependencies: - supports-color - /nano-css/5.3.4_react-dom@17.0.2+react@17.0.2: + /nano-css/5.3.4_react-dom@18.0.0+react@18.0.0: resolution: {integrity: sha512-wfcviJB6NOxDIDfr7RFn/GlaN7I/Bhe4d39ZRCJ3xvZX60LVe2qZ+rDqM49nm4YT81gAjzS+ZklhKP/Gnfnubg==} peerDependencies: react: '*' @@ -5204,8 +5204,8 @@ packages: csstype: 3.0.11 fastest-stable-stringify: 2.0.2 inline-style-prefixer: 6.0.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 + react: 18.0.0 + react-dom: 18.0.0_react@18.0.0 rtl-css-js: 1.15.0 sourcemap-codec: 1.4.8 stacktrace-js: 2.0.2 @@ -6050,18 +6050,17 @@ packages: minimist: 1.2.6 strip-json-comments: 2.0.1 - /react-dom/17.0.2_react@17.0.2: - resolution: {integrity: sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==} + /react-dom/18.0.0_react@18.0.0: + resolution: {integrity: sha512-XqX7uzmFo0pUceWFCt7Gff6IyIMzFUn7QMZrbrQfGxtaxXZIcGQzoNpRLE3fQLnS4XzLLPMZX2T9TRcSrasicw==} peerDependencies: - react: 17.0.2 + react: ^18.0.0 dependencies: loose-envify: 1.4.0 - object-assign: 4.1.1 - react: 17.0.2 - scheduler: 0.20.2 + react: 18.0.0 + scheduler: 0.21.0 dev: true - /react-hot-toast/2.2.0_383bc679f6b8b3c30a924b2c4a84e8d7: + /react-hot-toast/2.2.0_aee3b59847029cfc9aee5217330a3daf: resolution: {integrity: sha512-248rXw13uhf/6TNDVzagX+y7R8J183rp7MwUMNkcrBRyHj/jWOggfXTGlM8zAOuh701WyVW+eUaWG2LeSufX9g==} engines: {node: '>=10'} peerDependencies: @@ -6069,8 +6068,8 @@ packages: react-dom: '>=16' dependencies: goober: 2.1.8_csstype@3.0.11 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 + react: 18.0.0 + react-dom: 18.0.0_react@18.0.0 transitivePeerDependencies: - csstype dev: true @@ -6079,7 +6078,7 @@ packages: resolution: {integrity: sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==} dev: true - /react-query/3.34.19_react-dom@17.0.2+react@17.0.2: + /react-query/3.34.19_react-dom@18.0.0+react@18.0.0: resolution: {integrity: sha512-JO0Ymi58WKmvnhgg6bGIrYIeKb64KsKaPWo8JcGnmK2jJxAs2XmMBzlP75ZepSU7CHzcsWtIIyhMrLbX3pb/3w==} peerDependencies: react: ^16.8.0 || ^17.0.0 @@ -6094,8 +6093,8 @@ packages: '@babel/runtime': 7.17.8 broadcast-channel: 3.7.0 match-sorter: 6.3.1 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 + react: 18.0.0 + react-dom: 18.0.0_react@18.0.0 dev: true /react-refresh/0.11.0: @@ -6103,38 +6102,38 @@ packages: engines: {node: '>=0.10.0'} dev: true - /react-router-dom/6.3.0_react-dom@17.0.2+react@17.0.2: + /react-router-dom/6.3.0_react-dom@18.0.0+react@18.0.0: resolution: {integrity: sha512-uaJj7LKytRxZNQV8+RbzJWnJ8K2nPsOOEuX7aQstlMZKQT0164C+X2w6bnkqU3sjtLvpd5ojrezAyfZ1+0sStw==} peerDependencies: react: '>=16.8' react-dom: '>=16.8' dependencies: history: 5.3.0 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-router: 6.3.0_react@17.0.2 + react: 18.0.0 + react-dom: 18.0.0_react@18.0.0 + react-router: 6.3.0_react@18.0.0 dev: true - /react-router/6.3.0_react@17.0.2: + /react-router/6.3.0_react@18.0.0: resolution: {integrity: sha512-7Wh1DzVQ+tlFjkeo+ujvjSqSJmkt1+8JO+T5xklPlgrh70y7ogx75ODRW0ThWhY7S+6yEDks8TYrtQe/aoboBQ==} peerDependencies: react: '>=16.8' dependencies: history: 5.3.0 - react: 17.0.2 + react: 18.0.0 dev: true - /react-universal-interface/0.6.2_react@17.0.2+tslib@2.3.1: + /react-universal-interface/0.6.2_react@18.0.0+tslib@2.3.1: resolution: {integrity: sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==} peerDependencies: react: '*' tslib: '*' dependencies: - react: 17.0.2 + react: 18.0.0 tslib: 2.3.1 dev: true - /react-use/17.3.2_react-dom@17.0.2+react@17.0.2: + /react-use/17.3.2_react-dom@18.0.0+react@18.0.0: resolution: {integrity: sha512-bj7OD0/1wL03KyWmzFXAFe425zziuTf7q8olwCYBfOeFHY1qfO1FAMjROQLsLZYwG4Rx63xAfb7XAbBrJsZmEw==} peerDependencies: react: ^16.8.0 || ^17.0.0 @@ -6146,10 +6145,10 @@ packages: fast-deep-equal: 3.1.3 fast-shallow-equal: 1.0.0 js-cookie: 2.2.1 - nano-css: 5.3.4_react-dom@17.0.2+react@17.0.2 - react: 17.0.2 - react-dom: 17.0.2_react@17.0.2 - react-universal-interface: 0.6.2_react@17.0.2+tslib@2.3.1 + nano-css: 5.3.4_react-dom@18.0.0+react@18.0.0 + react: 18.0.0 + react-dom: 18.0.0_react@18.0.0 + react-universal-interface: 0.6.2_react@18.0.0+tslib@2.3.1 resize-observer-polyfill: 1.5.1 screenfull: 5.2.0 set-harmonic-interval: 1.0.1 @@ -6158,12 +6157,11 @@ packages: tslib: 2.3.1 dev: true - /react/17.0.2: - resolution: {integrity: sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==} + /react/18.0.0: + resolution: {integrity: sha512-x+VL6wbT4JRVPm7EGxXhZ8w8LTROaxPXOqhlGyVSrv0sB1jkyFGgXxJ8LVoPRLvPR6/CIZGFmfzqUa2NYeMr2A==} engines: {node: '>=0.10.0'} dependencies: loose-envify: 1.4.0 - object-assign: 4.1.1 dev: true /read-config-file/6.2.0: @@ -6473,11 +6471,10 @@ packages: resolution: {integrity: sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==} dev: true - /scheduler/0.20.2: - resolution: {integrity: sha512-2eWfGgAqqWFGqtdMmcL5zCMK1U8KlXv8SQFGglL3CEtd0aDVDWgeF/YoCmvln55m5zSk3J/20hTaSBeSObsQDQ==} + /scheduler/0.21.0: + resolution: {integrity: sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==} dependencies: loose-envify: 1.4.0 - object-assign: 4.1.1 dev: true /screenfull/5.2.0: @@ -7455,12 +7452,12 @@ packages: prepend-http: 2.0.0 dev: true - /use-sync-external-store/1.0.0_react@17.0.2: + /use-sync-external-store/1.0.0_react@18.0.0: resolution: {integrity: sha512-AFVsxg5GkFg8GDcxnl+Z0lMAz9rE8DGJCc28qnBuQF7lac57B5smLcT37aXpXIIPz75rW4g3eXHPjhHwdGskOw==} peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0-rc dependencies: - react: 17.0.2 + react: 18.0.0 dev: true /use/3.1.1: @@ -7490,10 +7487,10 @@ packages: valtio: ^1.2.5 dependencies: lodash: 4.17.21 - valtio: 1.5.0_react@17.0.2+vite@2.9.1 + valtio: 1.5.0_react@18.0.0+vite@2.9.1 dev: true - /valtio/1.5.0_react@17.0.2+vite@2.9.1: + /valtio/1.5.0_react@18.0.0+vite@2.9.1: resolution: {integrity: sha512-HfhX/BmRlIlV3AyBKv0nQ5I3SRKOB0giqhF8Gayb8Pnru0HvZQlzRstuXBppHtTBGmuJJOtCGv5jpdUfWEgeqA==} engines: {node: '>=12.7.0'} peerDependencies: @@ -7518,8 +7515,8 @@ packages: optional: true dependencies: proxy-compare: 2.1.0 - react: 17.0.2 - use-sync-external-store: 1.0.0_react@17.0.2 + react: 18.0.0 + use-sync-external-store: 1.0.0_react@18.0.0 vite: 2.9.1_sass@1.49.10 dev: true diff --git a/src/renderer/api/personalFM.ts b/src/renderer/api/personalFM.ts index 8cf4445..b9d5119 100644 --- a/src/renderer/api/personalFM.ts +++ b/src/renderer/api/personalFM.ts @@ -91,7 +91,6 @@ export interface FetchPersonalFMResponse { s_ctrp: string }[] } - export function fetchPersonalFM(): Promise { return request({ url: '/personal/fm', diff --git a/src/renderer/assets/icons/dislike.svg b/src/renderer/assets/icons/dislike.svg index 967008d..394de56 100644 --- a/src/renderer/assets/icons/dislike.svg +++ b/src/renderer/assets/icons/dislike.svg @@ -1,3 +1,3 @@ - + diff --git a/src/renderer/components/FMCard.tsx b/src/renderer/components/FMCard.tsx index fa028eb..a453c3e 100644 --- a/src/renderer/components/FMCard.tsx +++ b/src/renderer/components/FMCard.tsx @@ -5,6 +5,7 @@ import { resizeImage } from '@/utils/common' import SvgIcon from '@/components/SvgIcon' import ArtistInline from '@/components/ArtistsInline' import { State as PlayerState, Mode as PlayerMode } from '@/utils/player' +import Skeleton from './Skeleton' const MediaControls = () => { const classes = @@ -67,39 +68,64 @@ const FMCard = () => { useEffect(() => { if (coverUrl) { average(coverUrl, { amount: 1, format: 'hex', sample: 1 }).then(color => { - const to = colord(color as string) - .darken(0.15) - .rotate(-5) - .toHex() - setBackground(`linear-gradient(to bottom right, ${color}, ${to})`) + let c = colord(color as string) + console.log({ dark: c.isDark(), light: c.isLight() }) + + if (c.isLight()) c = c.darken(0.15) + else if (c.isDark()) c = c.lighten(0.1) + const to = c.darken(0.15).rotate(-5).toHex() + setBackground(`linear-gradient(to bottom right, ${c.toHex()}, ${to})`) }) - } else { - setBackground(`linear-gradient(to bottom right, #66ccff, #ee0000)`) } }, [coverUrl]) return (
- {coverUrl && } + {coverUrl ? ( + + ) : ( +
+ )}
{/* Track info */}
-
{track?.name}
- + {track ? ( +
{track?.name}
+ ) : ( +
+
+ PLACEHOLDER12345 +
+
+ )} + {track ? ( + + ) : ( +
+
+ PLACEHOLDER +
+
+ )}
- + {track ? :
} {/* FM logo */} -
+
私人FM
@@ -109,11 +135,4 @@ const FMCard = () => { ) } -/** - * 不能在player的构造函数中调用initFM - * 那样在APP启动时不会加载私人FM的数据 - * 只能在这里进行数据的初始化 - */ -player.initFM() - export default FMCard diff --git a/src/renderer/components/Player.tsx b/src/renderer/components/Player.tsx index 1d2b76c..e3f4bfb 100644 --- a/src/renderer/components/Player.tsx +++ b/src/renderer/components/Player.tsx @@ -75,6 +75,7 @@ const MediaControls = () => { const state = useMemo(() => playerSnapshot.state, [playerSnapshot.state]) const track = useMemo(() => playerSnapshot.track, [playerSnapshot.track]) const mode = useMemo(() => playerSnapshot.mode, [playerSnapshot.mode]) + return (
{mode === PlayerMode.PLAYLIST && ( diff --git a/src/renderer/hooks/usePersonalFM.ts b/src/renderer/hooks/usePersonalFM.ts index 2f81493..b6ae34f 100644 --- a/src/renderer/hooks/usePersonalFM.ts +++ b/src/renderer/hooks/usePersonalFM.ts @@ -4,8 +4,12 @@ import reactQueryClient from '@/utils/reactQueryClient' export function fetchPersonalFMWithReactQuery() { return reactQueryClient.fetchQuery( PersonalFMApiNames.FETCH_PERSONAL_FM, - () => { - return fetchPersonalFM() + async () => { + const data = await fetchPersonalFM() + if (!data.data?.length) { + throw new Error('No data') + } + return data }, { retry: 3, diff --git a/src/renderer/hooks/useTracks.ts b/src/renderer/hooks/useTracks.ts index 1528341..d4f3860 100644 --- a/src/renderer/hooks/useTracks.ts +++ b/src/renderer/hooks/useTracks.ts @@ -34,7 +34,10 @@ export function fetchTracksWithReactQuery(params: FetchTracksParams) { return fetchTracks(params) }, { - retry: 3, + retry: 4, + retryDelay: (retryCount: number) => { + return retryCount * 500 + }, staleTime: 86400000, } ) diff --git a/src/renderer/pages/Artist.tsx b/src/renderer/pages/Artist.tsx index 563aafc..39338b1 100644 --- a/src/renderer/pages/Artist.tsx +++ b/src/renderer/pages/Artist.tsx @@ -18,7 +18,7 @@ const Header = ({ artist }: { artist: Artist | undefined }) => {
{coverImage && ( <> - + )} diff --git a/src/renderer/store.ts b/src/renderer/store.ts index c05ec6e..bcc1f6b 100644 --- a/src/renderer/store.ts +++ b/src/renderer/store.ts @@ -30,6 +30,11 @@ subscribe(state, () => { }) export const player = proxy(PlayerCore) +player.init() + +if (import.meta.env.DEV) { + window.player = player +} // Devtools devtools(state, 'state') diff --git a/src/renderer/styles/global.scss b/src/renderer/styles/global.scss index 8956fbc..6af159c 100644 --- a/src/renderer/styles/global.scss +++ b/src/renderer/styles/global.scss @@ -111,3 +111,7 @@ a, button { cursor: default; } + +img { + -webkit-user-drag: none; +} diff --git a/src/renderer/utils/player.ts b/src/renderer/utils/player.ts index 27128a4..7119dc4 100644 --- a/src/renderer/utils/player.ts +++ b/src/renderer/utils/player.ts @@ -7,6 +7,8 @@ import { fetchPersonalFMWithReactQuery } from '@/hooks/usePersonalFM' import { fmTrash } from '@/api/personalFM' import { cacheAudio } from '@/api/yesplaymusic' import { clamp } from 'lodash-es' +import axios from 'axios' +import { resizeImage } from './common' type TrackID = number enum TrackListSourceType { @@ -43,8 +45,6 @@ export class Player { private _progress: number = 0 private _progressInterval: ReturnType | undefined private _volume: number = 1 // 0 to 1 - private _fmTrack: Track | null = null - private _fmInited = false state: State = State.INITIALIZING mode: Mode = Mode.PLAYLIST @@ -53,9 +53,11 @@ export class Player { fmTrackList: TrackID[] = [] shuffle: boolean = false repeatMode: RepeatMode = RepeatMode.OFF + fmTrack: Track | null = null - constructor() { - // + init() { + this.state = State.READY + this.initFM() } /** @@ -105,11 +107,7 @@ export class Player { * Get current playing track */ get track(): Track | null { - return this._track ?? null - } - - get fmTrack(): Track | null { - return this._fmTrack ?? null + return this.mode === Mode.FM ? this.fmTrack : this._track } /** @@ -144,7 +142,6 @@ export class Player { * Fetch track details from Netease based on this.trackID */ private async _fetchTrack(trackID: TrackID) { - this.state = State.LOADING const response = await fetchTracksWithReactQuery({ ids: [trackID] }) if (response.songs.length) { return response.songs[0] @@ -167,9 +164,14 @@ export class Player { * Play a track based on this.trackID */ private async _playTrack() { + this.state = State.LOADING const track = await this._fetchTrack(this.trackID) - if (track) this._track = track - if (track && this.mode === Mode.FM) this._fmTrack = track + if (!track) { + toast('加载歌曲信息失败') + return + } + if (this.mode === Mode.PLAYLIST) this._track = track + if (this.mode === Mode.FM) this.fmTrack = track this._playAudio() } @@ -204,7 +206,6 @@ export class Player { } private _howlerOnEndCallback() { - console.log('_howlerOnEndCallback') if (this.mode !== Mode.FM && this.repeatMode === RepeatMode.ONE) { _howler.seek(0) _howler.play() @@ -221,24 +222,23 @@ export class Player { } private async _nextFMTrack() { - if (this.fmTrackList.length <= 1) { - for (let i = 0; i < 5; i++) { - const response = await fetchPersonalFMWithReactQuery() - if (!response?.data?.length) continue - this.fmTrackList.shift() - this.fmTrackList.push(...response?.data?.map(r => r.id)) + this.fmTrackList.shift() + this._playTrack() - this._playTrack() - break - } - } else { - this.fmTrackList.shift() - this._playTrack() - if (this.fmTrackList.length <= 1) { + const loadMoreTracks = async () => { + if (this.fmTrackList.length <= 5) { const response = await fetchPersonalFMWithReactQuery() - this.fmTrackList.push(...response?.data?.map(r => r.id)) + this.fmTrackList.push(...(response?.data?.map(r => r.id) ?? {})) } } + const prefetchNextTrack = async () => { + const prefetchTrackID = this.fmTrackList[1] + const track = await this._fetchTrack(prefetchTrackID) + if (track?.al.picUrl) axios.get(resizeImage(track.al.picUrl, 'md')) + } + + loadMoreTracks() + prefetchNextTrack() } /** @@ -246,10 +246,14 @@ export class Player { * @param {boolean} fade fade in */ play(fade: boolean = false) { - if (_howler.playing()) return + if (_howler.playing()) { + this.state = State.PLAYING + return + } _howler.play() if (fade) { + this.state = State.PLAYING _howler.once('play', () => { _howler.fade(0, this._volume, PLAY_PAUSE_FADE_DURATION) }) @@ -303,7 +307,6 @@ export class Player { * Play next track */ nextTrack(forceFM: boolean = false) { - console.log(this) if (forceFM || this.mode === Mode.FM) { this.mode = Mode.FM this._nextFMTrack() @@ -343,7 +346,6 @@ export class Player { * @param {null|number=} autoPlayTrackID */ async playAlbum(album: Album, autoPlayTrackID?: null | number) { - console.log(album) if (!album?.songs?.length) return this.trackListSource = { type: TrackListSourceType.ALBUM, @@ -364,9 +366,9 @@ export class Player { this.mode = Mode.FM if ( this.fmTrackList.length > 0 && - this._fmTrack?.id === this.fmTrackList[0] + this.fmTrack?.id === this.fmTrackList[0] ) { - this._track = this._fmTrack + this._track = this.fmTrack this._playAudio() } else { this._playTrack() @@ -375,49 +377,23 @@ export class Player { /** * Init personal fm - * should only be called in components/FMCard */ async initFM() { - if (this._fmInited) return const response = await fetchPersonalFMWithReactQuery() - this.fmTrackList.push(...response?.data?.map(r => r.id)) + this.fmTrackList.push(...(response?.data?.map(r => r.id) ?? {})) const trackId = this.fmTrackList[0] const track = await this._fetchTrack(trackId) - if (track) this._fmTrack = track - this._fmInited = true + if (track) this.fmTrack = track } /** * Trash current PersonalFMTrack */ async fmTrash() { - let trashId = this.fmTrackList.shift() ?? 0 - if (trashId === 0) return - - if (this.mode === Mode.FM) { - await this._nextFMTrack() - } else { - for (let i = 0; i < 5 && this.fmTrackList.length <= 1; i++) { - const response = await fetchPersonalFMWithReactQuery() - this.fmTrackList.push(...response?.data?.map(r => r.id)) - } - - for (let i = 0; i < 5; i++) { - let track = await this._fetchTrack(this.fmTrackList.at(0) ?? 0) - if (track) { - this._fmTrack = track - break - } else { - this.fmTrackList.shift() - if (this.fmTrackList.length <= 1) { - const response = await fetchPersonalFMWithReactQuery() - this.fmTrackList.push(...response?.data?.map(r => r.id)) - } - } - } - } - fmTrash(trashId) + const trashTrackID = this.fmTrackList[0] + fmTrash(trashTrackID) + this._nextFMTrack() } /** @@ -432,3 +408,7 @@ export class Player { } export const player = new Player() + +if (import.meta.env.DEV) { + window.howler = _howler +}